| Previous | 199869 Revisions | Next |
| r34319 Saturday 10th January, 2015 at 12:53:11 UTC by Miodrag Milanović |
|---|
| Added integral version of jsoncpp source (nw) |
| [3rdparty/jsoncpp] | .clang-format* .gitignore* .travis.yml* AUTHORS* CMakeLists.txt* LICENSE* NEWS.txt* README.md* SConstruct* amalgamate.py* dev.makefile* doxybuild.py* makerelease.py* version* |
| [3rdparty/jsoncpp/devtools] | __init__.py* agent_vmw7.json* agent_vmxp.json* antglob.py* batchbuild.py* fixeol.py* licenseupdater.py* tarball.py* |
| [3rdparty/jsoncpp/doc] | doxyfile.in* footer.html* header.html* jsoncpp.dox* readme.txt* roadmap.dox* |
| [3rdparty/jsoncpp/include] | CMakeLists.txt* |
| [3rdparty/jsoncpp/include/json] | assertions.h* autolink.h* config.h* features.h* forwards.h* json.h* reader.h* value.h* version.h* writer.h* |
| [3rdparty/jsoncpp/makefiles/msvc2010] | jsoncpp.sln* jsontest.vcxproj* jsontest.vcxproj.filters* lib_json.vcxproj* lib_json.vcxproj.filters* test_lib_json.vcxproj* test_lib_json.vcxproj.filters* |
| [3rdparty/jsoncpp/makefiles/vs71] | jsoncpp.sln* jsontest.vcproj* lib_json.vcproj* test_lib_json.vcproj* |
| [3rdparty/jsoncpp/pkg-config] | jsoncpp.pc.in* |
| [3rdparty/jsoncpp/scons-tools] | globtool.py* srcdist.py* substinfile.py* targz.py* |
| [3rdparty/jsoncpp/src] | CMakeLists.txt* |
| [3rdparty/jsoncpp/src/jsontestrunner] | CMakeLists.txt* main.cpp* sconscript* |
| [3rdparty/jsoncpp/src/lib_json] | CMakeLists.txt* json_batchallocator.h* json_internalarray.inl* json_internalmap.inl* json_reader.cpp* json_tool.h* json_value.cpp* json_valueiterator.inl* json_writer.cpp* sconscript* version.h.in* |
| [3rdparty/jsoncpp/src/test_lib_json] | CMakeLists.txt* jsontest.cpp* jsontest.h* main.cpp* sconscript* |
| [3rdparty/jsoncpp/test] | cleantests.py* generate_expected.py* pyjsontestrunner.py* runjsontests.py* rununittests.py* |
| [3rdparty/jsoncpp/test/data] | fail_test_array_01.json* test_array_01.expected* test_array_01.json* test_array_02.expected* test_array_02.json* test_array_03.expected* test_array_03.json* test_array_04.expected* test_array_04.json* test_array_05.expected* test_array_05.json* test_array_06.expected* test_array_06.json* test_array_07.expected* test_array_07.json* test_basic_01.expected* test_basic_01.json* test_basic_02.expected* test_basic_02.json* test_basic_03.expected* test_basic_03.json* test_basic_04.expected* test_basic_04.json* test_basic_05.expected* test_basic_05.json* test_basic_06.expected* test_basic_06.json* test_basic_07.expected* test_basic_07.json* test_basic_08.expected* test_basic_08.json* test_basic_09.expected* test_basic_09.json* test_comment_01.expected* test_comment_01.json* test_comment_02.expected* test_comment_02.json* test_complex_01.expected* test_complex_01.json* test_integer_01.expected* test_integer_01.json* test_integer_02.expected* test_integer_02.json* test_integer_03.expected* test_integer_03.json* test_integer_04.expected* test_integer_04.json* test_integer_05.expected* test_integer_05.json* test_integer_06_64bits.expected* test_integer_06_64bits.json* test_integer_07_64bits.expected* test_integer_07_64bits.json* test_integer_08_64bits.expected* test_integer_08_64bits.json* test_large_01.expected* test_large_01.json* test_object_01.expected* test_object_01.json* test_object_02.expected* test_object_02.json* test_object_03.expected* test_object_03.json* test_object_04.expected* test_object_04.json* test_preserve_comment_01.expected* test_preserve_comment_01.json* test_real_01.expected* test_real_01.json* test_real_02.expected* test_real_02.json* test_real_03.expected* test_real_03.json* test_real_04.expected* test_real_04.json* test_real_05.expected* test_real_05.json* test_real_06.expected* test_real_06.json* test_real_07.expected* test_real_07.json* test_real_08.expected* test_real_08.json* test_real_09.expected* test_real_09.json* test_real_10.expected* test_real_10.json* test_real_11.expected* test_real_11.json* test_real_12.expected* test_real_12.json* test_string_01.expected* test_string_01.json* test_string_02.expected* test_string_02.json* test_string_03.expected* test_string_03.json* test_string_04.expected* test_string_04.json* test_string_05.expected* test_string_05.json* test_string_unicode_01.expected* test_string_unicode_01.json* test_string_unicode_02.expected* test_string_unicode_02.json* test_string_unicode_03.expected* test_string_unicode_03.json* test_string_unicode_04.expected* test_string_unicode_04.json* test_string_unicode_05.expected* test_string_unicode_05.json* |
| [3rdparty/jsoncpp/test/jsonchecker] | fail1.json* fail10.json* fail11.json* fail12.json* fail13.json* fail14.json* fail15.json* fail16.json* fail17.json* fail18.json* fail19.json* fail2.json* fail20.json* fail21.json* fail22.json* fail23.json* fail24.json* fail25.json* fail26.json* fail27.json* fail28.json* fail29.json* fail3.json* fail30.json* fail31.json* fail32.json* fail33.json* fail4.json* fail5.json* fail6.json* fail7.json* fail8.json* fail9.json* pass1.json* pass2.json* pass3.json* readme.txt* |
| [src/emu] | webengine.c |
| [src/lib] | lib.mak |
| [src/lib/web/json] |
| r0 | r242831 | |
|---|---|---|
| 1 | --- | |
| 2 | # BasedOnStyle: LLVM | |
| 3 | AccessModifierOffset: -2 | |
| 4 | ConstructorInitializerIndentWidth: 4 | |
| 5 | AlignEscapedNewlinesLeft: false | |
| 6 | AlignTrailingComments: true | |
| 7 | AllowAllParametersOfDeclarationOnNextLine: true | |
| 8 | AllowShortIfStatementsOnASingleLine: false | |
| 9 | AllowShortLoopsOnASingleLine: false | |
| 10 | AlwaysBreakTemplateDeclarations: false | |
| 11 | AlwaysBreakBeforeMultilineStrings: false | |
| 12 | BreakBeforeBinaryOperators: false | |
| 13 | BreakBeforeTernaryOperators: true | |
| 14 | BreakConstructorInitializersBeforeComma: false | |
| 15 | BinPackParameters: false | |
| 16 | ColumnLimit: 80 | |
| 17 | ConstructorInitializerAllOnOneLineOrOnePerLine: false | |
| 18 | DerivePointerBinding: false | |
| 19 | ExperimentalAutoDetectBinPacking: false | |
| 20 | IndentCaseLabels: false | |
| 21 | MaxEmptyLinesToKeep: 1 | |
| 22 | NamespaceIndentation: None | |
| 23 | ObjCSpaceBeforeProtocolList: true | |
| 24 | PenaltyBreakBeforeFirstCallParameter: 19 | |
| 25 | PenaltyBreakComment: 60 | |
| 26 | PenaltyBreakString: 1000 | |
| 27 | PenaltyBreakFirstLessLess: 120 | |
| 28 | PenaltyExcessCharacter: 1000000 | |
| 29 | PenaltyReturnTypeOnItsOwnLine: 60 | |
| 30 | PointerBindsToType: true | |
| 31 | SpacesBeforeTrailingComments: 1 | |
| 32 | Cpp11BracedListStyle: false | |
| 33 | Standard: Cpp03 | |
| 34 | IndentWidth: 2 | |
| 35 | TabWidth: 8 | |
| 36 | UseTab: Never | |
| 37 | BreakBeforeBraces: Attach | |
| 38 | IndentFunctionDeclarationAfterType: false | |
| 39 | SpacesInParentheses: false | |
| 40 | SpacesInAngles: false | |
| 41 | SpaceInEmptyParentheses: false | |
| 42 | SpacesInCStyleCastParentheses: false | |
| 43 | SpaceAfterControlStatementKeyword: true | |
| 44 | SpaceBeforeAssignmentOperators: true | |
| 45 | ContinuationIndentWidth: 4 | |
| 46 | ... | |
| 47 |
| r0 | r242831 | |
|---|---|---|
| 1 | /build/ | |
| 2 | *.pyc | |
| 3 | *.swp | |
| 4 | *.actual | |
| 5 | *.actual-rewrite | |
| 6 | *.process-output | |
| 7 | *.rewrite | |
| 8 | /bin/ | |
| 9 | /buildscons/ | |
| 10 | /libs/ | |
| 11 | /doc/doxyfile | |
| 12 | /dist/ | |
| 13 | /include/json/version.h |
| r0 | r242831 | |
|---|---|---|
| 1 | # Build matrix / environment variable are explained on: | |
| 2 | # http://about.travis-ci.org/docs/user/build-configuration/ | |
| 3 | # This file can be validated on: | |
| 4 | # http://lint.travis-ci.org/ | |
| 5 | before_install: sudo apt-get install cmake | |
| 6 | language: cpp | |
| 7 | compiler: | |
| 8 | - gcc | |
| 9 | - clang | |
| 10 | script: cmake -DJSONCPP_LIB_BUILD_SHARED=$SHARED_LIBRARY -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_VERBOSE_MAKEFILE=$VERBOSE_MAKE . && make | |
| 11 | env: | |
| 12 | matrix: | |
| 13 | - SHARED_LIBRARY=ON BUILD_TYPE=release VERBOSE_MAKE=false | |
| 14 | - SHARED_LIBRARY=OFF BUILD_TYPE=release VERBOSE_MAKE=false | |
| 15 | - SHARED_LIBRARY=OFF BUILD_TYPE=debug VERBOSE VERBOSE_MAKE=true | |
| 16 | notifications: | |
| 17 | email: | |
| 18 | - aaronjjacobs@gmail.com |
| r0 | r242831 | |
|---|---|---|
| 1 | Baptiste Lepilleur <blep@users.sourceforge.net> |
| r0 | r242831 | |
|---|---|---|
| 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8.5) | |
| 2 | PROJECT(jsoncpp) | |
| 3 | ENABLE_TESTING() | |
| 4 | ||
| 5 | OPTION(JSONCPP_WITH_TESTS "Compile and run JsonCpp test executables" ON) | |
| 6 | OPTION(JSONCPP_WITH_POST_BUILD_UNITTEST "Automatically run unit-tests as a post build step" ON) | |
| 7 | OPTION(JSONCPP_WITH_WARNING_AS_ERROR "Force compilation to fail if a warning occurs" OFF) | |
| 8 | OPTION(JSONCPP_WITH_PKGCONFIG_SUPPORT "Generate and install .pc files" ON) | |
| 9 | OPTION(JSONCPP_WITH_CMAKE_PACKAGE "Generate and install cmake package files" OFF) | |
| 10 | ||
| 11 | # Ensures that CMAKE_BUILD_TYPE is visible in cmake-gui on Unix | |
| 12 | IF(NOT WIN32) | |
| 13 | IF(NOT CMAKE_BUILD_TYPE) | |
| 14 | SET(CMAKE_BUILD_TYPE Release CACHE STRING | |
| 15 | "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Coverage." | |
| 16 | FORCE) | |
| 17 | ENDIF(NOT CMAKE_BUILD_TYPE) | |
| 18 | ENDIF(NOT WIN32) | |
| 19 | ||
| 20 | SET(LIB_SUFFIX "" CACHE STRING "Optional arch-dependent suffix for the library installation directory") | |
| 21 | ||
| 22 | SET(RUNTIME_INSTALL_DIR bin | |
| 23 | CACHE PATH "Install dir for executables and dlls") | |
| 24 | SET(ARCHIVE_INSTALL_DIR lib${LIB_SUFFIX} | |
| 25 | CACHE PATH "Install dir for static libraries") | |
| 26 | SET(LIBRARY_INSTALL_DIR lib${LIB_SUFFIX} | |
| 27 | CACHE PATH "Install dir for shared libraries") | |
| 28 | SET(INCLUDE_INSTALL_DIR include | |
| 29 | CACHE PATH "Install dir for headers") | |
| 30 | SET(PACKAGE_INSTALL_DIR lib${LIB_SUFFIX}/cmake | |
| 31 | CACHE PATH "Install dir for cmake package config files") | |
| 32 | MARK_AS_ADVANCED( RUNTIME_INSTALL_DIR ARCHIVE_INSTALL_DIR INCLUDE_INSTALL_DIR PACKAGE_INSTALL_DIR ) | |
| 33 | ||
| 34 | # This ensures shared DLL are in the same dir as executable on Windows. | |
| 35 | # Put all executables / libraries are in a project global directory. | |
| 36 | SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib | |
| 37 | CACHE PATH "Single directory for all static libraries.") | |
| 38 | SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib | |
| 39 | CACHE PATH "Single directory for all dynamic libraries on Unix.") | |
| 40 | SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin | |
| 41 | CACHE PATH "Single directory for all executable and dynamic libraries on Windows.") | |
| 42 | MARK_AS_ADVANCED( CMAKE_RUNTIME_OUTPUT_DIRECTORY CMAKE_LIBRARY_OUTPUT_DIRECTORY CMAKE_ARCHIVE_OUTPUT_DIRECTORY ) | |
| 43 | ||
| 44 | # Set variable named ${VAR_NAME} to value ${VALUE} | |
| 45 | FUNCTION(set_using_dynamic_name VAR_NAME VALUE) | |
| 46 | SET( "${VAR_NAME}" "${VALUE}" PARENT_SCOPE) | |
| 47 | ENDFUNCTION(set_using_dynamic_name) | |
| 48 | ||
| 49 | # Extract major, minor, patch from version text | |
| 50 | # Parse a version string "X.Y.Z" and outputs | |
| 51 | # version parts in ${OUPUT_PREFIX}_MAJOR, _MINOR, _PATCH. | |
| 52 | # If parse succeeds then ${OUPUT_PREFIX}_FOUND is TRUE. | |
| 53 | MACRO(jsoncpp_parse_version VERSION_TEXT OUPUT_PREFIX) | |
| 54 | SET(VERSION_REGEX "[0-9]+\\.[0-9]+\\.[0-9]+(-[a-zA-Z0-9_]+)?") | |
| 55 | IF( ${VERSION_TEXT} MATCHES ${VERSION_REGEX} ) | |
| 56 | STRING(REGEX MATCHALL "[0-9]+|-([A-Za-z0-9_]+)" VERSION_PARTS ${VERSION_TEXT}) | |
| 57 | LIST(GET VERSION_PARTS 0 ${OUPUT_PREFIX}_MAJOR) | |
| 58 | LIST(GET VERSION_PARTS 1 ${OUPUT_PREFIX}_MINOR) | |
| 59 | LIST(GET VERSION_PARTS 2 ${OUPUT_PREFIX}_PATCH) | |
| 60 | set_using_dynamic_name( "${OUPUT_PREFIX}_FOUND" TRUE ) | |
| 61 | ELSE( ${VERSION_TEXT} MATCHES ${VERSION_REGEX} ) | |
| 62 | set_using_dynamic_name( "${OUPUT_PREFIX}_FOUND" FALSE ) | |
| 63 | ENDIF( ${VERSION_TEXT} MATCHES ${VERSION_REGEX} ) | |
| 64 | ENDMACRO(jsoncpp_parse_version) | |
| 65 | ||
| 66 | # Read out version from "version" file | |
| 67 | FILE(STRINGS "version" JSONCPP_VERSION) | |
| 68 | ||
| 69 | jsoncpp_parse_version( ${JSONCPP_VERSION} JSONCPP_VERSION ) | |
| 70 | IF(NOT JSONCPP_VERSION_FOUND) | |
| 71 | MESSAGE(FATAL_ERROR "Failed to parse version string properly. Expect X.Y.Z") | |
| 72 | ENDIF(NOT JSONCPP_VERSION_FOUND) | |
| 73 | ||
| 74 | MESSAGE(STATUS "JsonCpp Version: ${JSONCPP_VERSION_MAJOR}.${JSONCPP_VERSION_MINOR}.${JSONCPP_VERSION_PATCH}") | |
| 75 | # File version.h is only regenerated on CMake configure step | |
| 76 | CONFIGURE_FILE( "${PROJECT_SOURCE_DIR}/src/lib_json/version.h.in" | |
| 77 | "${PROJECT_SOURCE_DIR}/include/json/version.h" ) | |
| 78 | ||
| 79 | macro(UseCompilationWarningAsError) | |
| 80 | if ( MSVC ) | |
| 81 | # Only enabled in debug because some old versions of VS STL generate | |
| 82 | # warnings when compiled in release configuration. | |
| 83 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /WX ") | |
| 84 | endif( MSVC ) | |
| 85 | endmacro() | |
| 86 | ||
| 87 | # Include our configuration header | |
| 88 | INCLUDE_DIRECTORIES( ${jsoncpp_SOURCE_DIR}/include ) | |
| 89 | ||
| 90 | if ( MSVC ) | |
| 91 | # Only enabled in debug because some old versions of VS STL generate | |
| 92 | # unreachable code warning when compiled in release configuration. | |
| 93 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /W4 ") | |
| 94 | endif( MSVC ) | |
| 95 | ||
| 96 | IF(JSONCPP_WITH_WARNING_AS_ERROR) | |
| 97 | UseCompilationWarningAsError() | |
| 98 | ENDIF(JSONCPP_WITH_WARNING_AS_ERROR) | |
| 99 | ||
| 100 | IF(JSONCPP_WITH_PKGCONFIG_SUPPORT) | |
| 101 | CONFIGURE_FILE( | |
| 102 | "pkg-config/jsoncpp.pc.in" | |
| 103 | "pkg-config/jsoncpp.pc" | |
| 104 | @ONLY) | |
| 105 | INSTALL(FILES "${CMAKE_BINARY_DIR}/pkg-config/jsoncpp.pc" | |
| 106 | DESTINATION "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}/pkgconfig") | |
| 107 | ENDIF(JSONCPP_WITH_PKGCONFIG_SUPPORT) | |
| 108 | ||
| 109 | IF(JSONCPP_WITH_CMAKE_PACKAGE) | |
| 110 | INSTALL(EXPORT jsoncpp | |
| 111 | DESTINATION ${PACKAGE_INSTALL_DIR}/jsoncpp | |
| 112 | FILE jsoncppConfig.cmake) | |
| 113 | ENDIF(JSONCPP_WITH_CMAKE_PACKAGE) | |
| 114 | ||
| 115 | # Build the different applications | |
| 116 | ADD_SUBDIRECTORY( src ) | |
| 117 | ||
| 118 | #install the includes | |
| 119 | ADD_SUBDIRECTORY( include ) |
| r0 | r242831 | |
|---|---|---|
| 1 | The JsonCpp library's source code, including accompanying documentation, | |
| 2 | tests and demonstration applications, are licensed under the following | |
| 3 | conditions... | |
| 4 | ||
| 5 | The author (Baptiste Lepilleur) explicitly disclaims copyright in all | |
| 6 | jurisdictions which recognize such a disclaimer. In such jurisdictions, | |
| 7 | this software is released into the Public Domain. | |
| 8 | ||
| 9 | In jurisdictions which do not recognize Public Domain property (e.g. Germany as of | |
| 10 | 2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is | |
| 11 | released under the terms of the MIT License (see below). | |
| 12 | ||
| 13 | In jurisdictions which recognize Public Domain property, the user of this | |
| 14 | software may choose to accept it either as 1) Public Domain, 2) under the | |
| 15 | conditions of the MIT License (see below), or 3) under the terms of dual | |
| 16 | Public Domain/MIT License conditions described here, as they choose. | |
| 17 | ||
| 18 | The MIT License is about as close to Public Domain as a license can get, and is | |
| 19 | described in clear, concise terms at: | |
| 20 | ||
| 21 | http://en.wikipedia.org/wiki/MIT_License | |
| 22 | ||
| 23 | The full text of the MIT License follows: | |
| 24 | ||
| 25 | ======================================================================== | |
| 26 | Copyright (c) 2007-2010 Baptiste Lepilleur | |
| 27 | ||
| 28 | Permission is hereby granted, free of charge, to any person | |
| 29 | obtaining a copy of this software and associated documentation | |
| 30 | files (the "Software"), to deal in the Software without | |
| 31 | restriction, including without limitation the rights to use, copy, | |
| 32 | modify, merge, publish, distribute, sublicense, and/or sell copies | |
| 33 | of the Software, and to permit persons to whom the Software is | |
| 34 | furnished to do so, subject to the following conditions: | |
| 35 | ||
| 36 | The above copyright notice and this permission notice shall be | |
| 37 | included in all copies or substantial portions of the Software. | |
| 38 | ||
| 39 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
| 40 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
| 41 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
| 42 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |
| 43 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |
| 44 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
| 45 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| 46 | SOFTWARE. | |
| 47 | ======================================================================== | |
| 48 | (END LICENSE TEXT) | |
| 49 | ||
| 50 | The MIT license is compatible with both the GPL and commercial | |
| 51 | software, affording one all of the rights of Public Domain with the | |
| 52 | minor nuisance of being required to keep the above copyright notice | |
| 53 | and license text in the source code. Note also that by accepting the | |
| 54 | Public Domain "license" you can re-license your copy using whatever | |
| 55 | license you like. |
| r0 | r242831 | |
|---|---|---|
| 1 | New in SVN | |
| 2 | ---------- | |
| 3 | ||
| 4 | * Updated the type system's behavior, in order to better support backwards | |
| 5 | compatibility with code that was written before 64-bit integer support was | |
| 6 | introduced. Here's how it works now: | |
| 7 | ||
| 8 | * isInt, isInt64, isUInt, and isUInt64 return true if and only if the | |
| 9 | value can be exactly represented as that type. In particular, a value | |
| 10 | constructed with a double like 17.0 will now return true for all of | |
| 11 | these methods. | |
| 12 | ||
| 13 | * isDouble and isFloat now return true for all numeric values, since all | |
| 14 | numeric values can be converted to a double or float without | |
| 15 | truncation. Note however that the conversion may not be exact -- for | |
| 16 | example, doubles cannot exactly represent all integers above 2^53 + 1. | |
| 17 | ||
| 18 | * isBool, isNull, isString, isArray, and isObject now return true if and | |
| 19 | only if the value is of that type. | |
| 20 | ||
| 21 | * isConvertibleTo(fooValue) indicates that it is safe to call asFoo. | |
| 22 | (For each type foo, isFoo always implies isConvertibleTo(fooValue).) | |
| 23 | asFoo returns an approximate or exact representation as appropriate. | |
| 24 | For example, a double value may be truncated when asInt is called. | |
| 25 | ||
| 26 | * For backwards compatibility with old code, isConvertibleTo(intValue) | |
| 27 | may return false even if type() == intValue. This is because the value | |
| 28 | may have been constructed with a 64-bit integer larger than maxInt, | |
| 29 | and calling asInt() would cause an exception. If you're writing new | |
| 30 | code, use isInt64 to find out whether the value is exactly | |
| 31 | representable using an Int64, or asDouble() combined with minInt64 and | |
| 32 | maxInt64 to figure out whether it is approximately representable. | |
| 33 | ||
| 34 | * Value | |
| 35 | - Patch #10: BOOST_FOREACH compatibility. Made Json::iterator more | |
| 36 | standard compliant, added missing iterator_category and value_type | |
| 37 | typedefs (contribued by Robert A. Iannucci). | |
| 38 | ||
| 39 | * Compilation | |
| 40 | ||
| 41 | - New CMake based build system. Based in part on contribution from | |
| 42 | Igor Okulist and Damien Buhl (Patch #14). | |
| 43 | ||
| 44 | - New header json/version.h now contains version number macros | |
| 45 | (JSONCPP_VERSION_MAJOR, JSONCPP_VERSION_MINOR, JSONCPP_VERSION_PATCH | |
| 46 | and JSONCPP_VERSION_HEXA). | |
| 47 | ||
| 48 | - Patch #11: added missing JSON_API on some classes causing link issues | |
| 49 | when building as a dynamic library on Windows | |
| 50 | (contributed by Francis Bolduc). | |
| 51 | ||
| 52 | - Visual Studio DLL: suppressed warning "C4251: <data member>: <type> | |
| 53 | needs to have dll-interface to be used by..." via pragma push/pop | |
| 54 | in json-cpp headers. | |
| 55 | ||
| 56 | - Added Travis CI intregration: https://travis-ci.org/blep/jsoncpp-mirror | |
| 57 | ||
| 58 | * Bug fixes | |
| 59 | - Patch #15: Copy constructor does not initialize allocated_ for stringValue | |
| 60 | (contributed by rmongia). | |
| 61 | ||
| 62 | - Patch #16: Missing field copy in Json::Value::iterator causing infinite | |
| 63 | loop when using experimental internal map (#define JSON_VALUE_USE_INTERNAL_MAP) | |
| 64 | (contributed by Ming-Lin Kao). | |
| 65 | ||
| 66 | ||
| 67 | New in JsonCpp 0.6.0: | |
| 68 | --------------------- | |
| 69 | ||
| 70 | * Compilation | |
| 71 | ||
| 72 | - LD_LIBRARY_PATH and LIBRARY_PATH environment variables are now | |
| 73 | propagated to the build environment as this is required for some | |
| 74 | compiler installation. | |
| 75 | ||
| 76 | - Added support for Microsoft Visual Studio 2008 (bug #2930462): | |
| 77 | The platform "msvc90" has been added. | |
| 78 | ||
| 79 | Notes: you need to setup the environment by running vcvars32.bat | |
| 80 | (e.g. MSVC 2008 command prompt in start menu) before running scons. | |
| 81 | ||
| 82 | - Added support for amalgamated source and header generation (a la sqlite). | |
| 83 | Refer to README.txt section "Generating amalgamated source and header" | |
| 84 | for detail. | |
| 85 | ||
| 86 | * Value | |
| 87 | ||
| 88 | - Removed experimental ValueAllocator, it caused static | |
| 89 | initialization/destruction order issues (bug #2934500). | |
| 90 | The DefaultValueAllocator has been inlined in code. | |
| 91 | ||
| 92 | - Added support for 64 bits integer: | |
| 93 | ||
| 94 | Types Json::Int64 and Json::UInt64 have been added. They are aliased | |
| 95 | to 64 bits integers on system that support them (based on __int64 on | |
| 96 | Microsoft Visual Studio platform, and long long on other platforms). | |
| 97 | ||
| 98 | Types Json::LargestInt and Json::LargestUInt have been added. They are | |
| 99 | aliased to the largest integer type supported: | |
| 100 | either Json::Int/Json::UInt or Json::Int64/Json::UInt64 respectively. | |
| 101 | ||
| 102 | Json::Value::asInt() and Json::Value::asUInt() still returns plain | |
| 103 | "int" based types, but asserts if an attempt is made to retrieve | |
| 104 | a 64 bits value that can not represented as the return type. | |
| 105 | ||
| 106 | Json::Value::asInt64() and Json::Value::asUInt64() have been added | |
| 107 | to obtain the 64 bits integer value. | |
| 108 | ||
| 109 | Json::Value::asLargestInt() and Json::Value::asLargestUInt() returns | |
| 110 | the integer as a LargestInt/LargestUInt respectively. Those functions | |
| 111 | functions are typically used when implementing writer. | |
| 112 | ||
| 113 | The reader attempts to read number as 64 bits integer, and fall back | |
| 114 | to reading a double if the number is not in the range of 64 bits | |
| 115 | integer. | |
| 116 | ||
| 117 | Warning: Json::Value::asInt() and Json::Value::asUInt() now returns | |
| 118 | long long. This changes break code that was passing the return value | |
| 119 | to *printf() function. | |
| 120 | ||
| 121 | Support for 64 bits integer can be disabled by defining the macro | |
| 122 | JSON_NO_INT64 (uncomment it in json/config.h for example), though | |
| 123 | it should have no impact on existing usage. | |
| 124 | ||
| 125 | - The type Json::ArrayIndex is used for indexes of a JSON value array. It | |
| 126 | is an unsigned int (typically 32 bits). | |
| 127 | ||
| 128 | - Array index can be passed as int to operator[], allowing use of literal: | |
| 129 | Json::Value array; | |
| 130 | array.append( 1234 ); | |
| 131 | int value = array[0].asInt(); // did not compile previously | |
| 132 | ||
| 133 | - Added float Json::Value::asFloat() to obtain a floating point value as a | |
| 134 | float (avoid lost of precision warning caused by used of asDouble() | |
| 135 | to initialize a float). | |
| 136 | ||
| 137 | * Reader | |
| 138 | ||
| 139 | - Renamed Reader::getFormatedErrorMessages() to getFormattedErrorMessages. | |
| 140 | Bug #3023708 (Formatted has 2 't'). The old member function is deprecated | |
| 141 | but still present for backward compatibility. | |
| 142 | ||
| 143 | * Tests | |
| 144 | ||
| 145 | - Added test to ensure that the escape sequence "\/" is corrected handled | |
| 146 | by the parser. | |
| 147 | ||
| 148 | * Bug fixes | |
| 149 | ||
| 150 | - Bug #3139677: JSON [1 2 3] was incorrectly parsed as [1, 3]. Error is now | |
| 151 | correctly detected. | |
| 152 | ||
| 153 | - Bug #3139678: stack buffer overflow when parsing a double with a | |
| 154 | length of 32 characters. | |
| 155 | ||
| 156 | - Fixed Value::operator <= implementation (had the semantic of operator >=). | |
| 157 | Found when adding unit tests for comparison operators. | |
| 158 | ||
| 159 | - Value::compare() is now const and has an actual implementation with | |
| 160 | unit tests. | |
| 161 | ||
| 162 | - Bug #2407932: strpbrk() can fail for NULL pointer. | |
| 163 | ||
| 164 | - Bug #3306345: Fixed minor typo in Path::resolve(). | |
| 165 | ||
| 166 | - Bug #3314841/#3306896: errors in amalgamate.py | |
| 167 | ||
| 168 | - Fixed some Coverity warnings and line-endings. | |
| 169 | ||
| 170 | * License | |
| 171 | ||
| 172 | - See file LICENSE for details. Basically JsonCpp is now licensed under | |
| 173 | MIT license, or public domain if desired and recognized in your jurisdiction. | |
| 174 | Thanks to Stephan G. Beal [http://wanderinghorse.net/home/stephan/]) who | |
| 175 | helped figuring out the solution to the public domain issue. |
| r0 | r242831 | |
|---|---|---|
| 1 | Introduction | |
| 2 | ------------ | |
| 3 | ||
| 4 | [JSON][json-org] is a lightweight data-interchange format. It can represent | |
| 5 | numbers, strings, ordered sequences of values, and collections of name/value | |
| 6 | pairs. | |
| 7 | ||
| 8 | [json-org]: http://json.org/ | |
| 9 | ||
| 10 | JsonCpp is a C++ library that allows manipulating JSON values, including | |
| 11 | serialization and deserialization to and from strings. It can also preserve | |
| 12 | existing comment in unserialization/serialization steps, making it a convenient | |
| 13 | format to store user input files. | |
| 14 | ||
| 15 | ## A note on backward-compatibility | |
| 16 | Very soon, we are switching to C++11 only. For older compilers, try the `pre-C++11` branch. | |
| 17 | ||
| 18 | Using JsonCpp in your project | |
| 19 | ----------------------------- | |
| 20 | ||
| 21 | The recommended approach to integrating JsonCpp in your project is to build | |
| 22 | the amalgamated source (a single `.cpp` file) with your own build system. This | |
| 23 | ensures consistency of compilation flags and ABI compatibility. See the section | |
| 24 | "Generating amalgamated source and header" for instructions. | |
| 25 | ||
| 26 | The `include/` should be added to your compiler include path. Jsoncpp headers | |
| 27 | should be included as follow: | |
| 28 | ||
| 29 | #include <json/json.h> | |
| 30 | ||
| 31 | If JsonCpp was build as a dynamic library on Windows, then your project needs to | |
| 32 | define the macro `JSON_DLL`. | |
| 33 | ||
| 34 | ||
| 35 | Building and testing with new CMake | |
| 36 | ----------------------------------- | |
| 37 | ||
| 38 | [CMake][] is a C++ Makefiles/Solution generator. It is usually available on most | |
| 39 | Linux system as package. On Ubuntu: | |
| 40 | ||
| 41 | sudo apt-get install cmake | |
| 42 | ||
| 43 | [CMake]: http://www.cmake.org | |
| 44 | ||
| 45 | Note that Python is also required to run the JSON reader/writer tests. If | |
| 46 | missing, the build will skip running those tests. | |
| 47 | ||
| 48 | When running CMake, a few parameters are required: | |
| 49 | ||
| 50 | * a build directory where the makefiles/solution are generated. It is also used | |
| 51 | to store objects, libraries and executables files. | |
| 52 | * the generator to use: makefiles or Visual Studio solution? What version or | |
| 53 | Visual Studio, 32 or 64 bits solution? | |
| 54 | ||
| 55 | Steps for generating solution/makefiles using `cmake-gui`: | |
| 56 | ||
| 57 | * Make "source code" point to the source directory. | |
| 58 | * Make "where to build the binary" point to the directory to use for the build. | |
| 59 | * Click on the "Grouped" check box. | |
| 60 | * Review JsonCpp build options (tick `JSONCPP_LIB_BUILD_SHARED` to build as a | |
| 61 | dynamic library). | |
| 62 | * Click the configure button at the bottom, then the generate button. | |
| 63 | * The generated solution/makefiles can be found in the binary directory. | |
| 64 | ||
| 65 | Alternatively, from the command-line on Unix in the source directory: | |
| 66 | ||
| 67 | mkdir -p build/debug | |
| 68 | cd build/debug | |
| 69 | cmake -DCMAKE_BUILD_TYPE=debug -DJSONCPP_LIB_BUILD_SHARED=OFF -G "Unix Makefiles" ../.. | |
| 70 | make | |
| 71 | ||
| 72 | Running `cmake -`" will display the list of available generators (passed using | |
| 73 | the `-G` option). | |
| 74 | ||
| 75 | By default CMake hides compilation commands. This can be modified by specifying | |
| 76 | `-DCMAKE_VERBOSE_MAKEFILE=true` when generating makefiles. | |
| 77 | ||
| 78 | ||
| 79 | Building and testing with SCons | |
| 80 | ------------------------------- | |
| 81 | ||
| 82 | **Note:** The SCons-based build system is deprecated. Please use CMake; see the | |
| 83 | section above. | |
| 84 | ||
| 85 | JsonCpp can use [Scons][] as a build system. Note that SCons requires Python to | |
| 86 | be installed. | |
| 87 | ||
| 88 | [SCons]: http://www.scons.org/ | |
| 89 | ||
| 90 | Invoke SCons as follows: | |
| 91 | ||
| 92 | scons platform=$PLATFORM [TARGET] | |
| 93 | ||
| 94 | where `$PLATFORM` may be one of: | |
| 95 | ||
| 96 | * `suncc`: Sun C++ (Solaris) | |
| 97 | * `vacpp`: Visual Age C++ (AIX) | |
| 98 | * `mingw` | |
| 99 | * `msvc6`: Microsoft Visual Studio 6 service pack 5-6 | |
| 100 | * `msvc70`: Microsoft Visual Studio 2002 | |
| 101 | * `msvc71`: Microsoft Visual Studio 2003 | |
| 102 | * `msvc80`: Microsoft Visual Studio 2005 | |
| 103 | * `msvc90`: Microsoft Visual Studio 2008 | |
| 104 | * `linux-gcc`: Gnu C++ (linux, also reported to work for Mac OS X) | |
| 105 | ||
| 106 | If you are building with Microsoft Visual Studio 2008, you need to set up the | |
| 107 | environment by running `vcvars32.bat` (e.g. MSVC 2008 command prompt) before | |
| 108 | running SCons. | |
| 109 | ||
| 110 | ||
| 111 | Running the tests manually | |
| 112 | -------------------------- | |
| 113 | ||
| 114 | Note that test can be run using SCons using the `check` target: | |
| 115 | ||
| 116 | scons platform=$PLATFORM check | |
| 117 | ||
| 118 | You need to run tests manually only if you are troubleshooting an issue. | |
| 119 | ||
| 120 | In the instructions below, replace `path/to/jsontest` with the path of the | |
| 121 | `jsontest` executable that was compiled on your platform. | |
| 122 | ||
| 123 | cd test | |
| 124 | # This will run the Reader/Writer tests | |
| 125 | python runjsontests.py path/to/jsontest | |
| 126 | ||
| 127 | # This will run the Reader/Writer tests, using JSONChecker test suite | |
| 128 | # (http://www.json.org/JSON_checker/). | |
| 129 | # Notes: not all tests pass: JsonCpp is too lenient (for example, | |
| 130 | # it allows an integer to start with '0'). The goal is to improve | |
| 131 | # strict mode parsing to get all tests to pass. | |
| 132 | python runjsontests.py --with-json-checker path/to/jsontest | |
| 133 | ||
| 134 | # This will run the unit tests (mostly Value) | |
| 135 | python rununittests.py path/to/test_lib_json | |
| 136 | ||
| 137 | # You can run the tests using valgrind: | |
| 138 | python rununittests.py --valgrind path/to/test_lib_json | |
| 139 | ||
| 140 | ||
| 141 | Building the documentation | |
| 142 | -------------------------- | |
| 143 | ||
| 144 | Run the Python script `doxybuild.py` from the top directory: | |
| 145 | ||
| 146 | python doxybuild.py --doxygen=$(which doxygen) --open --with-dot | |
| 147 | ||
| 148 | See `doxybuild.py --help` for options. | |
| 149 | ||
| 150 | ||
| 151 | Generating amalgamated source and header | |
| 152 | ---------------------------------------- | |
| 153 | ||
| 154 | JsonCpp is provided with a script to generate a single header and a single | |
| 155 | source file to ease inclusion into an existing project. The amalgamated source | |
| 156 | can be generated at any time by running the following command from the | |
| 157 | top-directory (this requires Python 2.6): | |
| 158 | ||
| 159 | python amalgamate.py | |
| 160 | ||
| 161 | It is possible to specify header name. See the `-h` option for detail. | |
| 162 | ||
| 163 | By default, the following files are generated: | |
| 164 | * `dist/jsoncpp.cpp`: source file that needs to be added to your project. | |
| 165 | * `dist/json/json.h`: corresponding header file for use in your project. It is | |
| 166 | equivalent to including `json/json.h` in non-amalgamated source. This header | |
| 167 | only depends on standard headers. | |
| 168 | * `dist/json/json-forwards.h`: header that provides forward declaration of all | |
| 169 | JsonCpp types. | |
| 170 | ||
| 171 | The amalgamated sources are generated by concatenating JsonCpp source in the | |
| 172 | correct order and defining the macro `JSON_IS_AMALGAMATION` to prevent inclusion | |
| 173 | of other headers. | |
| 174 | ||
| 175 | ||
| 176 | Adding a reader/writer test | |
| 177 | --------------------------- | |
| 178 | ||
| 179 | To add a test, you need to create two files in test/data: | |
| 180 | ||
| 181 | * a `TESTNAME.json` file, that contains the input document in JSON format. | |
| 182 | * a `TESTNAME.expected` file, that contains a flatened representation of the | |
| 183 | input document. | |
| 184 | ||
| 185 | The `TESTNAME.expected` file format is as follows: | |
| 186 | ||
| 187 | * each line represents a JSON element of the element tree represented by the | |
| 188 | input document. | |
| 189 | * each line has two parts: the path to access the element separated from the | |
| 190 | element value by `=`. Array and object values are always empty (i.e. | |
| 191 | represented by either `[]` or `{}`). | |
| 192 | * element path: `.` represents the root element, and is used to separate object | |
| 193 | members. `[N]` is used to specify the value of an array element at index `N`. | |
| 194 | ||
| 195 | See the examples `test_complex_01.json` and `test_complex_01.expected` to better | |
| 196 | understand element paths. | |
| 197 | ||
| 198 | ||
| 199 | Understanding reader/writer test output | |
| 200 | --------------------------------------- | |
| 201 | ||
| 202 | When a test is run, output files are generated beside the input test files. | |
| 203 | Below is a short description of the content of each file: | |
| 204 | ||
| 205 | * `test_complex_01.json`: input JSON document. | |
| 206 | * `test_complex_01.expected`: flattened JSON element tree used to check if | |
| 207 | parsing was corrected. | |
| 208 | * `test_complex_01.actual`: flattened JSON element tree produced by `jsontest` | |
| 209 | from reading `test_complex_01.json`. | |
| 210 | * `test_complex_01.rewrite`: JSON document written by `jsontest` using the | |
| 211 | `Json::Value` parsed from `test_complex_01.json` and serialized using | |
| 212 | `Json::StyledWritter`. | |
| 213 | * `test_complex_01.actual-rewrite`: flattened JSON element tree produced by | |
| 214 | `jsontest` from reading `test_complex_01.rewrite`. | |
| 215 | * `test_complex_01.process-output`: `jsontest` output, typically useful for | |
| 216 | understanding parsing errors. | |
| 217 | ||
| 218 | ||
| 219 | License | |
| 220 | ------- | |
| 221 | ||
| 222 | See the `LICENSE` file for details. In summary, JsonCpp is licensed under the | |
| 223 | MIT license, or public domain if desired and recognized in your jurisdiction. | |
| 224 |
| r0 | r242831 | |
|---|---|---|
| 1 | """ | |
| 2 | Notes: | |
| 3 | - shared library support is buggy: it assumes that a static and dynamic library can be build from the same object files. This is not true on many platforms. For this reason it is only enabled on linux-gcc at the current time. | |
| 4 | ||
| 5 | To add a platform: | |
| 6 | - add its name in options allowed_values below | |
| 7 | - add tool initialization for this platform. Search for "if platform == 'suncc'" as an example. | |
| 8 | """ | |
| 9 | ||
| 10 | import os | |
| 11 | import os.path | |
| 12 | import sys | |
| 13 | ||
| 14 | JSONCPP_VERSION = open(File('#version').abspath,'rt').read().strip() | |
| 15 | DIST_DIR = '#dist' | |
| 16 | ||
| 17 | options = Variables() | |
| 18 | options.Add( EnumVariable('platform', | |
| 19 | 'Platform (compiler/stl) used to build the project', | |
| 20 | 'msvc71', | |
| 21 | allowed_values='suncc vacpp mingw msvc6 msvc7 msvc71 msvc80 msvc90 linux-gcc'.split(), | |
| 22 | ignorecase=2) ) | |
| 23 | ||
| 24 | try: | |
| 25 | platform = ARGUMENTS['platform'] | |
| 26 | if platform == 'linux-gcc': | |
| 27 | CXX = 'g++' # not quite right, but env is not yet available. | |
| 28 | import commands | |
| 29 | version = commands.getoutput('%s -dumpversion' %CXX) | |
| 30 | platform = 'linux-gcc-%s' %version | |
| 31 | print "Using platform '%s'" %platform | |
| 32 | LD_LIBRARY_PATH = os.environ.get('LD_LIBRARY_PATH', '') | |
| 33 | LD_LIBRARY_PATH = "%s:libs/%s" %(LD_LIBRARY_PATH, platform) | |
| 34 | os.environ['LD_LIBRARY_PATH'] = LD_LIBRARY_PATH | |
| 35 | print "LD_LIBRARY_PATH =", LD_LIBRARY_PATH | |
| 36 | except KeyError: | |
| 37 | print 'You must specify a "platform"' | |
| 38 | sys.exit(2) | |
| 39 | ||
| 40 | print "Building using PLATFORM =", platform | |
| 41 | ||
| 42 | rootbuild_dir = Dir('#buildscons') | |
| 43 | build_dir = os.path.join( '#buildscons', platform ) | |
| 44 | bin_dir = os.path.join( '#bin', platform ) | |
| 45 | lib_dir = os.path.join( '#libs', platform ) | |
| 46 | sconsign_dir_path = Dir(build_dir).abspath | |
| 47 | sconsign_path = os.path.join( sconsign_dir_path, '.sconsign.dbm' ) | |
| 48 | ||
| 49 | # Ensure build directory exist (SConsignFile fail otherwise!) | |
| 50 | if not os.path.exists( sconsign_dir_path ): | |
| 51 | os.makedirs( sconsign_dir_path ) | |
| 52 | ||
| 53 | # Store all dependencies signature in a database | |
| 54 | SConsignFile( sconsign_path ) | |
| 55 | ||
| 56 | def make_environ_vars(): | |
| 57 | """Returns a dictionnary with environment variable to use when compiling.""" | |
| 58 | # PATH is required to find the compiler | |
| 59 | # TEMP is required for at least mingw | |
| 60 | # LD_LIBRARY_PATH & co is required on some system for the compiler | |
| 61 | vars = {} | |
| 62 | for name in ('PATH', 'TEMP', 'TMP', 'LD_LIBRARY_PATH', 'LIBRARY_PATH'): | |
| 63 | if name in os.environ: | |
| 64 | vars[name] = os.environ[name] | |
| 65 | return vars | |
| 66 | ||
| 67 | ||
| 68 | env = Environment( ENV = make_environ_vars(), | |
| 69 | toolpath = ['scons-tools'], | |
| 70 | tools=[] ) #, tools=['default'] ) | |
| 71 | ||
| 72 | if platform == 'suncc': | |
| 73 | env.Tool( 'sunc++' ) | |
| 74 | env.Tool( 'sunlink' ) | |
| 75 | env.Tool( 'sunar' ) | |
| 76 | env.Append( CCFLAGS = ['-mt'] ) | |
| 77 | elif platform == 'vacpp': | |
| 78 | env.Tool( 'default' ) | |
| 79 | env.Tool( 'aixcc' ) | |
| 80 | env['CXX'] = 'xlC_r' #scons does not pick-up the correct one ! | |
| 81 | # using xlC_r ensure multi-threading is enabled: | |
| 82 | # http://publib.boulder.ibm.com/infocenter/pseries/index.jsp?topic=/com.ibm.vacpp7a.doc/compiler/ref/cuselect.htm | |
| 83 | env.Append( CCFLAGS = '-qrtti=all', | |
| 84 | LINKFLAGS='-bh:5' ) # -bh:5 remove duplicate symbol warning | |
| 85 | elif platform == 'msvc6': | |
| 86 | env['MSVS_VERSION']='6.0' | |
| 87 | for tool in ['msvc', 'msvs', 'mslink', 'masm', 'mslib']: | |
| 88 | env.Tool( tool ) | |
| 89 | env['CXXFLAGS']='-GR -GX /nologo /MT' | |
| 90 | elif platform == 'msvc70': | |
| 91 | env['MSVS_VERSION']='7.0' | |
| 92 | for tool in ['msvc', 'msvs', 'mslink', 'masm', 'mslib']: | |
| 93 | env.Tool( tool ) | |
| 94 | env['CXXFLAGS']='-GR -GX /nologo /MT' | |
| 95 | elif platform == 'msvc71': | |
| 96 | env['MSVS_VERSION']='7.1' | |
| 97 | for tool in ['msvc', 'msvs', 'mslink', 'masm', 'mslib']: | |
| 98 | env.Tool( tool ) | |
| 99 | env['CXXFLAGS']='-GR -GX /nologo /MT' | |
| 100 | elif platform == 'msvc80': | |
| 101 | env['MSVS_VERSION']='8.0' | |
| 102 | for tool in ['msvc', 'msvs', 'mslink', 'masm', 'mslib']: | |
| 103 | env.Tool( tool ) | |
| 104 | env['CXXFLAGS']='-GR -EHsc /nologo /MT' | |
| 105 | elif platform == 'msvc90': | |
| 106 | env['MSVS_VERSION']='9.0' | |
| 107 | # Scons 1.2 fails to detect the correct location of the platform SDK. | |
| 108 | # So we propagate those from the environment. This requires that the | |
| 109 | # user run vcvars32.bat before compiling. | |
| 110 | if 'INCLUDE' in os.environ: | |
| 111 | env['ENV']['INCLUDE'] = os.environ['INCLUDE'] | |
| 112 | if 'LIB' in os.environ: | |
| 113 | env['ENV']['LIB'] = os.environ['LIB'] | |
| 114 | for tool in ['msvc', 'msvs', 'mslink', 'masm', 'mslib']: | |
| 115 | env.Tool( tool ) | |
| 116 | env['CXXFLAGS']='-GR -EHsc /nologo /MT' | |
| 117 | elif platform == 'mingw': | |
| 118 | env.Tool( 'mingw' ) | |
| 119 | env.Append( CPPDEFINES=[ "WIN32", "NDEBUG", "_MT" ] ) | |
| 120 | elif platform.startswith('linux-gcc'): | |
| 121 | env.Tool( 'default' ) | |
| 122 | env.Append( LIBS = ['pthread'], CCFLAGS = os.environ.get("CXXFLAGS", "-Wall"), LINKFLAGS=os.environ.get("LDFLAGS", "") ) | |
| 123 | env['SHARED_LIB_ENABLED'] = True | |
| 124 | else: | |
| 125 | print "UNSUPPORTED PLATFORM." | |
| 126 | env.Exit(1) | |
| 127 | ||
| 128 | env.Tool('targz') | |
| 129 | env.Tool('srcdist') | |
| 130 | env.Tool('globtool') | |
| 131 | ||
| 132 | env.Append( CPPPATH = ['#include'], | |
| 133 | LIBPATH = lib_dir ) | |
| 134 | short_platform = platform | |
| 135 | if short_platform.startswith('msvc'): | |
| 136 | short_platform = short_platform[2:] | |
| 137 | # Notes: on Windows you need to rebuild the source for each variant | |
| 138 | # Build script does not support that yet so we only build static libraries. | |
| 139 | # This also fails on AIX because both dynamic and static library ends with | |
| 140 | # extension .a. | |
| 141 | env['SHARED_LIB_ENABLED'] = env.get('SHARED_LIB_ENABLED', False) | |
| 142 | env['LIB_PLATFORM'] = short_platform | |
| 143 | env['LIB_LINK_TYPE'] = 'lib' # static | |
| 144 | env['LIB_CRUNTIME'] = 'mt' | |
| 145 | env['LIB_NAME_SUFFIX'] = '${LIB_PLATFORM}_${LIB_LINK_TYPE}${LIB_CRUNTIME}' # must match autolink naming convention | |
| 146 | env['JSONCPP_VERSION'] = JSONCPP_VERSION | |
| 147 | env['BUILD_DIR'] = env.Dir(build_dir) | |
| 148 | env['ROOTBUILD_DIR'] = env.Dir(rootbuild_dir) | |
| 149 | env['DIST_DIR'] = DIST_DIR | |
| 150 | if 'TarGz' in env['BUILDERS']: | |
| 151 | class SrcDistAdder: | |
| 152 | def __init__( self, env ): | |
| 153 | self.env = env | |
| 154 | def __call__( self, *args, **kw ): | |
| 155 | apply( self.env.SrcDist, (self.env['SRCDIST_TARGET'],) + args, kw ) | |
| 156 | env['SRCDIST_BUILDER'] = env.TarGz | |
| 157 | else: # If tarfile module is missing | |
| 158 | class SrcDistAdder: | |
| 159 | def __init__( self, env ): | |
| 160 | pass | |
| 161 | def __call__( self, *args, **kw ): | |
| 162 | pass | |
| 163 | env['SRCDIST_ADD'] = SrcDistAdder( env ) | |
| 164 | env['SRCDIST_TARGET'] = os.path.join( DIST_DIR, 'jsoncpp-src-%s.tar.gz' % env['JSONCPP_VERSION'] ) | |
| 165 | ||
| 166 | env_testing = env.Clone( ) | |
| 167 | env_testing.Append( LIBS = ['json_${LIB_NAME_SUFFIX}'] ) | |
| 168 | ||
| 169 | def buildJSONExample( env, target_sources, target_name ): | |
| 170 | env = env.Clone() | |
| 171 | env.Append( CPPPATH = ['#'] ) | |
| 172 | exe = env.Program( target=target_name, | |
| 173 | source=target_sources ) | |
| 174 | env['SRCDIST_ADD']( source=[target_sources] ) | |
| 175 | global bin_dir | |
| 176 | return env.Install( bin_dir, exe ) | |
| 177 | ||
| 178 | def buildJSONTests( env, target_sources, target_name ): | |
| 179 | jsontests_node = buildJSONExample( env, target_sources, target_name ) | |
| 180 | check_alias_target = env.Alias( 'check', jsontests_node, RunJSONTests( jsontests_node, jsontests_node ) ) | |
| 181 | env.AlwaysBuild( check_alias_target ) | |
| 182 | ||
| 183 | def buildUnitTests( env, target_sources, target_name ): | |
| 184 | jsontests_node = buildJSONExample( env, target_sources, target_name ) | |
| 185 | check_alias_target = env.Alias( 'check', jsontests_node, | |
| 186 | RunUnitTests( jsontests_node, jsontests_node ) ) | |
| 187 | env.AlwaysBuild( check_alias_target ) | |
| 188 | ||
| 189 | def buildLibrary( env, target_sources, target_name ): | |
| 190 | static_lib = env.StaticLibrary( target=target_name + '_${LIB_NAME_SUFFIX}', | |
| 191 | source=target_sources ) | |
| 192 | global lib_dir | |
| 193 | env.Install( lib_dir, static_lib ) | |
| 194 | if env['SHARED_LIB_ENABLED']: | |
| 195 | shared_lib = env.SharedLibrary( target=target_name + '_${LIB_NAME_SUFFIX}', | |
| 196 | source=target_sources ) | |
| 197 | env.Install( lib_dir, shared_lib ) | |
| 198 | env['SRCDIST_ADD']( source=[target_sources] ) | |
| 199 | ||
| 200 | Export( 'env env_testing buildJSONExample buildLibrary buildJSONTests buildUnitTests' ) | |
| 201 | ||
| 202 | def buildProjectInDirectory( target_directory ): | |
| 203 | global build_dir | |
| 204 | target_build_dir = os.path.join( build_dir, target_directory ) | |
| 205 | target = os.path.join( target_directory, 'sconscript' ) | |
| 206 | SConscript( target, build_dir=target_build_dir, duplicate=0 ) | |
| 207 | env['SRCDIST_ADD']( source=[target] ) | |
| 208 | ||
| 209 | ||
| 210 | def runJSONTests_action( target, source = None, env = None ): | |
| 211 | # Add test scripts to python path | |
| 212 | jsontest_path = Dir( '#test' ).abspath | |
| 213 | sys.path.insert( 0, jsontest_path ) | |
| 214 | data_path = os.path.join( jsontest_path, 'data' ) | |
| 215 | import runjsontests | |
| 216 | return runjsontests.runAllTests( os.path.abspath(source[0].path), data_path ) | |
| 217 | ||
| 218 | def runJSONTests_string( target, source = None, env = None ): | |
| 219 | return 'RunJSONTests("%s")' % source[0] | |
| 220 | ||
| 221 | import SCons.Action | |
| 222 | ActionFactory = SCons.Action.ActionFactory | |
| 223 | RunJSONTests = ActionFactory(runJSONTests_action, runJSONTests_string ) | |
| 224 | ||
| 225 | def runUnitTests_action( target, source = None, env = None ): | |
| 226 | # Add test scripts to python path | |
| 227 | jsontest_path = Dir( '#test' ).abspath | |
| 228 | sys.path.insert( 0, jsontest_path ) | |
| 229 | import rununittests | |
| 230 | return rununittests.runAllTests( os.path.abspath(source[0].path) ) | |
| 231 | ||
| 232 | def runUnitTests_string( target, source = None, env = None ): | |
| 233 | return 'RunUnitTests("%s")' % source[0] | |
| 234 | ||
| 235 | RunUnitTests = ActionFactory(runUnitTests_action, runUnitTests_string ) | |
| 236 | ||
| 237 | env.Alias( 'check' ) | |
| 238 | ||
| 239 | srcdist_cmd = env['SRCDIST_ADD']( source = """ | |
| 240 | AUTHORS README.txt SConstruct | |
| 241 | """.split() ) | |
| 242 | env.Alias( 'src-dist', srcdist_cmd ) | |
| 243 | ||
| 244 | buildProjectInDirectory( 'src/jsontestrunner' ) | |
| 245 | buildProjectInDirectory( 'src/lib_json' ) | |
| 246 | buildProjectInDirectory( 'src/test_lib_json' ) | |
| 247 | #print env.Dump() | |
| 248 |
| r0 | r242831 | |
|---|---|---|
| 1 | """Amalgate json-cpp library sources into a single source and header file. | |
| 2 | ||
| 3 | Requires Python 2.6 | |
| 4 | ||
| 5 | Example of invocation (must be invoked from json-cpp top directory): | |
| 6 | python amalgate.py | |
| 7 | """ | |
| 8 | import os | |
| 9 | import os.path | |
| 10 | import sys | |
| 11 | ||
| 12 | class AmalgamationFile: | |
| 13 | def __init__( self, top_dir ): | |
| 14 | self.top_dir = top_dir | |
| 15 | self.blocks = [] | |
| 16 | ||
| 17 | def add_text( self, text ): | |
| 18 | if not text.endswith( "\n" ): | |
| 19 | text += "\n" | |
| 20 | self.blocks.append( text ) | |
| 21 | ||
| 22 | def add_file( self, relative_input_path, wrap_in_comment=False ): | |
| 23 | def add_marker( prefix ): | |
| 24 | self.add_text( "" ) | |
| 25 | self.add_text( "// " + "/"*70 ) | |
| 26 | self.add_text( "// %s of content of file: %s" % (prefix, relative_input_path.replace("\\","/")) ) | |
| 27 | self.add_text( "// " + "/"*70 ) | |
| 28 | self.add_text( "" ) | |
| 29 | add_marker( "Beginning" ) | |
| 30 | f = open( os.path.join( self.top_dir, relative_input_path ), "rt" ) | |
| 31 | content = f.read() | |
| 32 | if wrap_in_comment: | |
| 33 | content = "/*\n" + content + "\n*/" | |
| 34 | self.add_text( content ) | |
| 35 | f.close() | |
| 36 | add_marker( "End" ) | |
| 37 | self.add_text( "\n\n\n\n" ) | |
| 38 | ||
| 39 | def get_value( self ): | |
| 40 | return "".join( self.blocks ).replace("\r\n","\n") | |
| 41 | ||
| 42 | def write_to( self, output_path ): | |
| 43 | output_dir = os.path.dirname( output_path ) | |
| 44 | if output_dir and not os.path.isdir( output_dir ): | |
| 45 | os.makedirs( output_dir ) | |
| 46 | f = open( output_path, "wb" ) | |
| 47 | f.write( str.encode(self.get_value(), 'UTF-8') ) | |
| 48 | f.close() | |
| 49 | ||
| 50 | def amalgamate_source( source_top_dir=None, | |
| 51 | target_source_path=None, | |
| 52 | header_include_path=None ): | |
| 53 | """Produces amalgated source. | |
| 54 | Parameters: | |
| 55 | source_top_dir: top-directory | |
| 56 | target_source_path: output .cpp path | |
| 57 | header_include_path: generated header path relative to target_source_path. | |
| 58 | """ | |
| 59 | print("Amalgating header...") | |
| 60 | header = AmalgamationFile( source_top_dir ) | |
| 61 | header.add_text( "/// Json-cpp amalgated header (http://jsoncpp.sourceforge.net/)." ) | |
| 62 | header.add_text( "/// It is intented to be used with #include <%s>" % header_include_path ) | |
| 63 | header.add_file( "LICENSE", wrap_in_comment=True ) | |
| 64 | header.add_text( "#ifndef JSON_AMALGATED_H_INCLUDED" ) | |
| 65 | header.add_text( "# define JSON_AMALGATED_H_INCLUDED" ) | |
| 66 | header.add_text( "/// If defined, indicates that the source file is amalgated" ) | |
| 67 | header.add_text( "/// to prevent private header inclusion." ) | |
| 68 | header.add_text( "#define JSON_IS_AMALGAMATION" ) | |
| 69 | header.add_file( "include/json/version.h" ) | |
| 70 | header.add_file( "include/json/config.h" ) | |
| 71 | header.add_file( "include/json/forwards.h" ) | |
| 72 | header.add_file( "include/json/features.h" ) | |
| 73 | header.add_file( "include/json/value.h" ) | |
| 74 | header.add_file( "include/json/reader.h" ) | |
| 75 | header.add_file( "include/json/writer.h" ) | |
| 76 | header.add_file( "include/json/assertions.h" ) | |
| 77 | header.add_text( "#endif //ifndef JSON_AMALGATED_H_INCLUDED" ) | |
| 78 | ||
| 79 | target_header_path = os.path.join( os.path.dirname(target_source_path), header_include_path ) | |
| 80 | print("Writing amalgated header to %r" % target_header_path) | |
| 81 | header.write_to( target_header_path ) | |
| 82 | ||
| 83 | base, ext = os.path.splitext( header_include_path ) | |
| 84 | forward_header_include_path = base + "-forwards" + ext | |
| 85 | print("Amalgating forward header...") | |
| 86 | header = AmalgamationFile( source_top_dir ) | |
| 87 | header.add_text( "/// Json-cpp amalgated forward header (http://jsoncpp.sourceforge.net/)." ) | |
| 88 | header.add_text( "/// It is intented to be used with #include <%s>" % forward_header_include_path ) | |
| 89 | header.add_text( "/// This header provides forward declaration for all JsonCpp types." ) | |
| 90 | header.add_file( "LICENSE", wrap_in_comment=True ) | |
| 91 | header.add_text( "#ifndef JSON_FORWARD_AMALGATED_H_INCLUDED" ) | |
| 92 | header.add_text( "# define JSON_FORWARD_AMALGATED_H_INCLUDED" ) | |
| 93 | header.add_text( "/// If defined, indicates that the source file is amalgated" ) | |
| 94 | header.add_text( "/// to prevent private header inclusion." ) | |
| 95 | header.add_text( "#define JSON_IS_AMALGAMATION" ) | |
| 96 | header.add_file( "include/json/config.h" ) | |
| 97 | header.add_file( "include/json/forwards.h" ) | |
| 98 | header.add_text( "#endif //ifndef JSON_FORWARD_AMALGATED_H_INCLUDED" ) | |
| 99 | ||
| 100 | target_forward_header_path = os.path.join( os.path.dirname(target_source_path), | |
| 101 | forward_header_include_path ) | |
| 102 | print("Writing amalgated forward header to %r" % target_forward_header_path) | |
| 103 | header.write_to( target_forward_header_path ) | |
| 104 | ||
| 105 | print("Amalgating source...") | |
| 106 | source = AmalgamationFile( source_top_dir ) | |
| 107 | source.add_text( "/// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/)." ) | |
| 108 | source.add_text( "/// It is intented to be used with #include <%s>" % header_include_path ) | |
| 109 | source.add_file( "LICENSE", wrap_in_comment=True ) | |
| 110 | source.add_text( "" ) | |
| 111 | source.add_text( "#include <%s>" % header_include_path ) | |
| 112 | source.add_text( "" ) | |
| 113 | lib_json = "src/lib_json" | |
| 114 | source.add_file( os.path.join(lib_json, "json_tool.h") ) | |
| 115 | source.add_file( os.path.join(lib_json, "json_reader.cpp") ) | |
| 116 | source.add_file( os.path.join(lib_json, "json_batchallocator.h") ) | |
| 117 | source.add_file( os.path.join(lib_json, "json_valueiterator.inl") ) | |
| 118 | source.add_file( os.path.join(lib_json, "json_value.cpp") ) | |
| 119 | source.add_file( os.path.join(lib_json, "json_writer.cpp") ) | |
| 120 | ||
| 121 | print("Writing amalgated source to %r" % target_source_path) | |
| 122 | source.write_to( target_source_path ) | |
| 123 | ||
| 124 | def main(): | |
| 125 | usage = """%prog [options] | |
| 126 | Generate a single amalgated source and header file from the sources. | |
| 127 | """ | |
| 128 | from optparse import OptionParser | |
| 129 | parser = OptionParser(usage=usage) | |
| 130 | parser.allow_interspersed_args = False | |
| 131 | parser.add_option("-s", "--source", dest="target_source_path", action="store", default="dist/jsoncpp.cpp", | |
| 132 | help="""Output .cpp source path. [Default: %default]""") | |
| 133 | parser.add_option("-i", "--include", dest="header_include_path", action="store", default="json/json.h", | |
| 134 | help="""Header include path. Used to include the header from the amalgated source file. [Default: %default]""") | |
| 135 | parser.add_option("-t", "--top-dir", dest="top_dir", action="store", default=os.getcwd(), | |
| 136 | help="""Source top-directory. [Default: %default]""") | |
| 137 | parser.enable_interspersed_args() | |
| 138 | options, args = parser.parse_args() | |
| 139 | ||
| 140 | msg = amalgamate_source( source_top_dir=options.top_dir, | |
| 141 | target_source_path=options.target_source_path, | |
| 142 | header_include_path=options.header_include_path ) | |
| 143 | if msg: | |
| 144 | sys.stderr.write( msg + "\n" ) | |
| 145 | sys.exit( 1 ) | |
| 146 | else: | |
| 147 | print("Source succesfully amalagated") | |
| 148 | ||
| 149 | if __name__ == "__main__": | |
| 150 | main() |
| r0 | r242831 | |
|---|---|---|
| 1 | all: build test-amalgamate | |
| 2 | ||
| 3 | build: | |
| 4 | mkdir -p build/debug | |
| 5 | cd build/debug; cmake -DCMAKE_BUILD_TYPE=debug -DJSONCPP_LIB_BUILD_SHARED=ON -G "Unix Makefiles" ../.. | |
| 6 | make -C build/debug | |
| 7 | ||
| 8 | # Currently, this depends on include/json/version.h generated | |
| 9 | # by cmake. | |
| 10 | test-amalgamate: build | |
| 11 | python2.7 amalgamate.py | |
| 12 | python3.4 amalgamate.py | |
| 13 | ||
| 14 | .PHONY: build |
| r0 | r242831 | |
|---|---|---|
| 1 | # module | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | { | |
| 2 | "cmake_variants" : [ | |
| 3 | {"name": "generator", | |
| 4 | "generators": [ | |
| 5 | {"generator": [ | |
| 6 | "Visual Studio 7 .NET 2003", | |
| 7 | "Visual Studio 9 2008", | |
| 8 | "Visual Studio 9 2008 Win64", | |
| 9 | "Visual Studio 10", | |
| 10 | "Visual Studio 10 Win64", | |
| 11 | "Visual Studio 11", | |
| 12 | "Visual Studio 11 Win64" | |
| 13 | ] | |
| 14 | }, | |
| 15 | {"generator": ["MinGW Makefiles"], | |
| 16 | "env_prepend": [{"path": "c:/wut/prg/MinGW/bin"}] | |
| 17 | } | |
| 18 | ] | |
| 19 | }, | |
| 20 | {"name": "shared_dll", | |
| 21 | "variables": [ | |
| 22 | ["JSONCPP_LIB_BUILD_SHARED=true"], | |
| 23 | ["JSONCPP_LIB_BUILD_SHARED=false"] | |
| 24 | ] | |
| 25 | }, | |
| 26 | {"name": "build_type", | |
| 27 | "build_types": [ | |
| 28 | "debug", | |
| 29 | "release" | |
| 30 | ] | |
| 31 | } | |
| 32 | ] | |
| 33 | } |
| r0 | r242831 | |
|---|---|---|
| 1 | { | |
| 2 | "cmake_variants" : [ | |
| 3 | {"name": "generator", | |
| 4 | "generators": [ | |
| 5 | {"generator": [ | |
| 6 | "Visual Studio 6", | |
| 7 | "Visual Studio 7", | |
| 8 | "Visual Studio 8 2005" | |
| 9 | ] | |
| 10 | } | |
| 11 | ] | |
| 12 | }, | |
| 13 | {"name": "shared_dll", | |
| 14 | "variables": [ | |
| 15 | ["JSONCPP_LIB_BUILD_SHARED=true"], | |
| 16 | ["JSONCPP_LIB_BUILD_SHARED=false"] | |
| 17 | ] | |
| 18 | }, | |
| 19 | {"name": "build_type", | |
| 20 | "build_types": [ | |
| 21 | "debug", | |
| 22 | "release" | |
| 23 | ] | |
| 24 | } | |
| 25 | ] | |
| 26 | } |
| r0 | r242831 | |
|---|---|---|
| 1 | #!/usr/bin/env python | |
| 2 | # encoding: utf-8 | |
| 3 | # Baptiste Lepilleur, 2009 | |
| 4 | ||
| 5 | from __future__ import print_function | |
| 6 | from dircache import listdir | |
| 7 | import re | |
| 8 | import fnmatch | |
| 9 | import os.path | |
| 10 | ||
| 11 | ||
| 12 | # These fnmatch expressions are used by default to prune the directory tree | |
| 13 | # while doing the recursive traversal in the glob_impl method of glob function. | |
| 14 | prune_dirs = '.git .bzr .hg .svn _MTN _darcs CVS SCCS ' | |
| 15 | ||
| 16 | # These fnmatch expressions are used by default to exclude files and dirs | |
| 17 | # while doing the recursive traversal in the glob_impl method of glob function. | |
| 18 | ##exclude_pats = prune_pats + '*~ #*# .#* %*% ._* .gitignore .cvsignore vssver.scc .DS_Store'.split() | |
| 19 | ||
| 20 | # These ant_glob expressions are used by default to exclude files and dirs and also prune the directory tree | |
| 21 | # while doing the recursive traversal in the glob_impl method of glob function. | |
| 22 | default_excludes = ''' | |
| 23 | **/*~ | |
| 24 | **/#*# | |
| 25 | **/.#* | |
| 26 | **/%*% | |
| 27 | **/._* | |
| 28 | **/CVS | |
| 29 | **/CVS/** | |
| 30 | **/.cvsignore | |
| 31 | **/SCCS | |
| 32 | **/SCCS/** | |
| 33 | **/vssver.scc | |
| 34 | **/.svn | |
| 35 | **/.svn/** | |
| 36 | **/.git | |
| 37 | **/.git/** | |
| 38 | **/.gitignore | |
| 39 | **/.bzr | |
| 40 | **/.bzr/** | |
| 41 | **/.hg | |
| 42 | **/.hg/** | |
| 43 | **/_MTN | |
| 44 | **/_MTN/** | |
| 45 | **/_darcs | |
| 46 | **/_darcs/** | |
| 47 | **/.DS_Store ''' | |
| 48 | ||
| 49 | DIR = 1 | |
| 50 | FILE = 2 | |
| 51 | DIR_LINK = 4 | |
| 52 | FILE_LINK = 8 | |
| 53 | LINKS = DIR_LINK | FILE_LINK | |
| 54 | ALL_NO_LINK = DIR | FILE | |
| 55 | ALL = DIR | FILE | LINKS | |
| 56 | ||
| 57 | _ANT_RE = re.compile( r'(/\*\*/)|(\*\*/)|(/\*\*)|(\*)|(/)|([^\*/]*)' ) | |
| 58 | ||
| 59 | def ant_pattern_to_re( ant_pattern ): | |
| 60 | """Generates a regular expression from the ant pattern. | |
| 61 | Matching convention: | |
| 62 | **/a: match 'a', 'dir/a', 'dir1/dir2/a' | |
| 63 | a/**/b: match 'a/b', 'a/c/b', 'a/d/c/b' | |
| 64 | *.py: match 'script.py' but not 'a/script.py' | |
| 65 | """ | |
| 66 | rex = ['^'] | |
| 67 | next_pos = 0 | |
| 68 | sep_rex = r'(?:/|%s)' % re.escape( os.path.sep ) | |
| 69 | ## print 'Converting', ant_pattern | |
| 70 | for match in _ANT_RE.finditer( ant_pattern ): | |
| 71 | ## print 'Matched', match.group() | |
| 72 | ## print match.start(0), next_pos | |
| 73 | if match.start(0) != next_pos: | |
| 74 | raise ValueError( "Invalid ant pattern" ) | |
| 75 | if match.group(1): # /**/ | |
| 76 | rex.append( sep_rex + '(?:.*%s)?' % sep_rex ) | |
| 77 | elif match.group(2): # **/ | |
| 78 | rex.append( '(?:.*%s)?' % sep_rex ) | |
| 79 | elif match.group(3): # /** | |
| 80 | rex.append( sep_rex + '.*' ) | |
| 81 | elif match.group(4): # * | |
| 82 | rex.append( '[^/%s]*' % re.escape(os.path.sep) ) | |
| 83 | elif match.group(5): # / | |
| 84 | rex.append( sep_rex ) | |
| 85 | else: # somepath | |
| 86 | rex.append( re.escape(match.group(6)) ) | |
| 87 | next_pos = match.end() | |
| 88 | rex.append('$') | |
| 89 | return re.compile( ''.join( rex ) ) | |
| 90 | ||
| 91 | def _as_list( l ): | |
| 92 | if isinstance(l, basestring): | |
| 93 | return l.split() | |
| 94 | return l | |
| 95 | ||
| 96 | def glob(dir_path, | |
| 97 | includes = '**/*', | |
| 98 | excludes = default_excludes, | |
| 99 | entry_type = FILE, | |
| 100 | prune_dirs = prune_dirs, | |
| 101 | max_depth = 25): | |
| 102 | include_filter = [ant_pattern_to_re(p) for p in _as_list(includes)] | |
| 103 | exclude_filter = [ant_pattern_to_re(p) for p in _as_list(excludes)] | |
| 104 | prune_dirs = [p.replace('/',os.path.sep) for p in _as_list(prune_dirs)] | |
| 105 | dir_path = dir_path.replace('/',os.path.sep) | |
| 106 | entry_type_filter = entry_type | |
| 107 | ||
| 108 | def is_pruned_dir( dir_name ): | |
| 109 | for pattern in prune_dirs: | |
| 110 | if fnmatch.fnmatch( dir_name, pattern ): | |
| 111 | return True | |
| 112 | return False | |
| 113 | ||
| 114 | def apply_filter( full_path, filter_rexs ): | |
| 115 | """Return True if at least one of the filter regular expression match full_path.""" | |
| 116 | for rex in filter_rexs: | |
| 117 | if rex.match( full_path ): | |
| 118 | return True | |
| 119 | return False | |
| 120 | ||
| 121 | def glob_impl( root_dir_path ): | |
| 122 | child_dirs = [root_dir_path] | |
| 123 | while child_dirs: | |
| 124 | dir_path = child_dirs.pop() | |
| 125 | for entry in listdir( dir_path ): | |
| 126 | full_path = os.path.join( dir_path, entry ) | |
| 127 | ## print 'Testing:', full_path, | |
| 128 | is_dir = os.path.isdir( full_path ) | |
| 129 | if is_dir and not is_pruned_dir( entry ): # explore child directory ? | |
| 130 | ## print '===> marked for recursion', | |
| 131 | child_dirs.append( full_path ) | |
| 132 | included = apply_filter( full_path, include_filter ) | |
| 133 | rejected = apply_filter( full_path, exclude_filter ) | |
| 134 | if not included or rejected: # do not include entry ? | |
| 135 | ## print '=> not included or rejected' | |
| 136 | continue | |
| 137 | link = os.path.islink( full_path ) | |
| 138 | is_file = os.path.isfile( full_path ) | |
| 139 | if not is_file and not is_dir: | |
| 140 | ## print '=> unknown entry type' | |
| 141 | continue | |
| 142 | if link: | |
| 143 | entry_type = is_file and FILE_LINK or DIR_LINK | |
| 144 | else: | |
| 145 | entry_type = is_file and FILE or DIR | |
| 146 | ## print '=> type: %d' % entry_type, | |
| 147 | if (entry_type & entry_type_filter) != 0: | |
| 148 | ## print ' => KEEP' | |
| 149 | yield os.path.join( dir_path, entry ) | |
| 150 | ## else: | |
| 151 | ## print ' => TYPE REJECTED' | |
| 152 | return list( glob_impl( dir_path ) ) | |
| 153 | ||
| 154 | ||
| 155 | if __name__ == "__main__": | |
| 156 | import unittest | |
| 157 | ||
| 158 | class AntPatternToRETest(unittest.TestCase): | |
| 159 | ## def test_conversion( self ): | |
| 160 | ## self.assertEqual( '^somepath$', ant_pattern_to_re( 'somepath' ).pattern ) | |
| 161 | ||
| 162 | def test_matching( self ): | |
| 163 | test_cases = [ ( 'path', | |
| 164 | ['path'], | |
| 165 | ['somepath', 'pathsuffix', '/path', '/path'] ), | |
| 166 | ( '*.py', | |
| 167 | ['source.py', 'source.ext.py', '.py'], | |
| 168 | ['path/source.py', '/.py', 'dir.py/z', 'z.pyc', 'z.c'] ), | |
| 169 | ( '**/path', | |
| 170 | ['path', '/path', '/a/path', 'c:/a/path', '/a/b/path', '//a/path', '/a/path/b/path'], | |
| 171 | ['path/', 'a/path/b', 'dir.py/z', 'somepath', 'pathsuffix', 'a/somepath'] ), | |
| 172 | ( 'path/**', | |
| 173 | ['path/a', 'path/path/a', 'path//'], | |
| 174 | ['path', 'somepath/a', 'a/path', 'a/path/a', 'pathsuffix/a'] ), | |
| 175 | ( '/**/path', | |
| 176 | ['/path', '/a/path', '/a/b/path/path', '/path/path'], | |
| 177 | ['path', 'path/', 'a/path', '/pathsuffix', '/somepath'] ), | |
| 178 | ( 'a/b', | |
| 179 | ['a/b'], | |
| 180 | ['somea/b', 'a/bsuffix', 'a/b/c'] ), | |
| 181 | ( '**/*.py', | |
| 182 | ['script.py', 'src/script.py', 'a/b/script.py', '/a/b/script.py'], | |
| 183 | ['script.pyc', 'script.pyo', 'a.py/b'] ), | |
| 184 | ( 'src/**/*.py', | |
| 185 | ['src/a.py', 'src/dir/a.py'], | |
| 186 | ['a/src/a.py', '/src/a.py'] ), | |
| 187 | ] | |
| 188 | for ant_pattern, accepted_matches, rejected_matches in list(test_cases): | |
| 189 | def local_path( paths ): | |
| 190 | return [ p.replace('/',os.path.sep) for p in paths ] | |
| 191 | test_cases.append( (ant_pattern, local_path(accepted_matches), local_path( rejected_matches )) ) | |
| 192 | for ant_pattern, accepted_matches, rejected_matches in test_cases: | |
| 193 | rex = ant_pattern_to_re( ant_pattern ) | |
| 194 | print('ant_pattern:', ant_pattern, ' => ', rex.pattern) | |
| 195 | for accepted_match in accepted_matches: | |
| 196 | print('Accepted?:', accepted_match) | |
| 197 | self.assertTrue( rex.match( accepted_match ) is not None ) | |
| 198 | for rejected_match in rejected_matches: | |
| 199 | print('Rejected?:', rejected_match) | |
| 200 | self.assertTrue( rex.match( rejected_match ) is None ) | |
| 201 | ||
| 202 | unittest.main() |
| r0 | r242831 | |
|---|---|---|
| 1 | from __future__ import print_function | |
| 2 | import collections | |
| 3 | import itertools | |
| 4 | import json | |
| 5 | import os | |
| 6 | import os.path | |
| 7 | import re | |
| 8 | import shutil | |
| 9 | import string | |
| 10 | import subprocess | |
| 11 | import sys | |
| 12 | import cgi | |
| 13 | ||
| 14 | class BuildDesc: | |
| 15 | def __init__(self, prepend_envs=None, variables=None, build_type=None, generator=None): | |
| 16 | self.prepend_envs = prepend_envs or [] # [ { "var": "value" } ] | |
| 17 | self.variables = variables or [] | |
| 18 | self.build_type = build_type | |
| 19 | self.generator = generator | |
| 20 | ||
| 21 | def merged_with( self, build_desc ): | |
| 22 | """Returns a new BuildDesc by merging field content. | |
| 23 | Prefer build_desc fields to self fields for single valued field. | |
| 24 | """ | |
| 25 | return BuildDesc( self.prepend_envs + build_desc.prepend_envs, | |
| 26 | self.variables + build_desc.variables, | |
| 27 | build_desc.build_type or self.build_type, | |
| 28 | build_desc.generator or self.generator ) | |
| 29 | ||
| 30 | def env( self ): | |
| 31 | environ = os.environ.copy() | |
| 32 | for values_by_name in self.prepend_envs: | |
| 33 | for var, value in list(values_by_name.items()): | |
| 34 | var = var.upper() | |
| 35 | if type(value) is unicode: | |
| 36 | value = value.encode( sys.getdefaultencoding() ) | |
| 37 | if var in environ: | |
| 38 | environ[var] = value + os.pathsep + environ[var] | |
| 39 | else: | |
| 40 | environ[var] = value | |
| 41 | return environ | |
| 42 | ||
| 43 | def cmake_args( self ): | |
| 44 | args = ["-D%s" % var for var in self.variables] | |
| 45 | # skip build type for Visual Studio solution as it cause warning | |
| 46 | if self.build_type and 'Visual' not in self.generator: | |
| 47 | args.append( "-DCMAKE_BUILD_TYPE=%s" % self.build_type ) | |
| 48 | if self.generator: | |
| 49 | args.extend( ['-G', self.generator] ) | |
| 50 | return args | |
| 51 | ||
| 52 | def __repr__( self ): | |
| 53 | return "BuildDesc( %s, build_type=%s )" % (" ".join( self.cmake_args()), self.build_type) | |
| 54 | ||
| 55 | class BuildData: | |
| 56 | def __init__( self, desc, work_dir, source_dir ): | |
| 57 | self.desc = desc | |
| 58 | self.work_dir = work_dir | |
| 59 | self.source_dir = source_dir | |
| 60 | self.cmake_log_path = os.path.join( work_dir, 'batchbuild_cmake.log' ) | |
| 61 | self.build_log_path = os.path.join( work_dir, 'batchbuild_build.log' ) | |
| 62 | self.cmake_succeeded = False | |
| 63 | self.build_succeeded = False | |
| 64 | ||
| 65 | def execute_build(self): | |
| 66 | print('Build %s' % self.desc) | |
| 67 | self._make_new_work_dir( ) | |
| 68 | self.cmake_succeeded = self._generate_makefiles( ) | |
| 69 | if self.cmake_succeeded: | |
| 70 | self.build_succeeded = self._build_using_makefiles( ) | |
| 71 | return self.build_succeeded | |
| 72 | ||
| 73 | def _generate_makefiles(self): | |
| 74 | print(' Generating makefiles: ', end=' ') | |
| 75 | cmd = ['cmake'] + self.desc.cmake_args( ) + [os.path.abspath( self.source_dir )] | |
| 76 | succeeded = self._execute_build_subprocess( cmd, self.desc.env(), self.cmake_log_path ) | |
| 77 | print('done' if succeeded else 'FAILED') | |
| 78 | return succeeded | |
| 79 | ||
| 80 | def _build_using_makefiles(self): | |
| 81 | print(' Building:', end=' ') | |
| 82 | cmd = ['cmake', '--build', self.work_dir] | |
| 83 | if self.desc.build_type: | |
| 84 | cmd += ['--config', self.desc.build_type] | |
| 85 | succeeded = self._execute_build_subprocess( cmd, self.desc.env(), self.build_log_path ) | |
| 86 | print('done' if succeeded else 'FAILED') | |
| 87 | return succeeded | |
| 88 | ||
| 89 | def _execute_build_subprocess(self, cmd, env, log_path): | |
| 90 | process = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=self.work_dir, | |
| 91 | env=env ) | |
| 92 | stdout, _ = process.communicate( ) | |
| 93 | succeeded = (process.returncode == 0) | |
| 94 | with open( log_path, 'wb' ) as flog: | |
| 95 | log = ' '.join( cmd ) + '\n' + stdout + '\nExit code: %r\n' % process.returncode | |
| 96 | flog.write( fix_eol( log ) ) | |
| 97 | return succeeded | |
| 98 | ||
| 99 | def _make_new_work_dir(self): | |
| 100 | if os.path.isdir( self.work_dir ): | |
| 101 | print(' Removing work directory', self.work_dir) | |
| 102 | shutil.rmtree( self.work_dir, ignore_errors=True ) | |
| 103 | if not os.path.isdir( self.work_dir ): | |
| 104 | os.makedirs( self.work_dir ) | |
| 105 | ||
| 106 | def fix_eol( stdout ): | |
| 107 | """Fixes wrong EOL produced by cmake --build on Windows (\r\r\n instead of \r\n). | |
| 108 | """ | |
| 109 | return re.sub( '\r*\n', os.linesep, stdout ) | |
| 110 | ||
| 111 | def load_build_variants_from_config( config_path ): | |
| 112 | with open( config_path, 'rb' ) as fconfig: | |
| 113 | data = json.load( fconfig ) | |
| 114 | variants = data[ 'cmake_variants' ] | |
| 115 | build_descs_by_axis = collections.defaultdict( list ) | |
| 116 | for axis in variants: | |
| 117 | axis_name = axis["name"] | |
| 118 | build_descs = [] | |
| 119 | if "generators" in axis: | |
| 120 | for generator_data in axis["generators"]: | |
| 121 | for generator in generator_data["generator"]: | |
| 122 | build_desc = BuildDesc( generator=generator, | |
| 123 | prepend_envs=generator_data.get("env_prepend") ) | |
| 124 | build_descs.append( build_desc ) | |
| 125 | elif "variables" in axis: | |
| 126 | for variables in axis["variables"]: | |
| 127 | build_desc = BuildDesc( variables=variables ) | |
| 128 | build_descs.append( build_desc ) | |
| 129 | elif "build_types" in axis: | |
| 130 | for build_type in axis["build_types"]: | |
| 131 | build_desc = BuildDesc( build_type=build_type ) | |
| 132 | build_descs.append( build_desc ) | |
| 133 | build_descs_by_axis[axis_name].extend( build_descs ) | |
| 134 | return build_descs_by_axis | |
| 135 | ||
| 136 | def generate_build_variants( build_descs_by_axis ): | |
| 137 | """Returns a list of BuildDesc generated for the partial BuildDesc for each axis.""" | |
| 138 | axis_names = list(build_descs_by_axis.keys()) | |
| 139 | build_descs = [] | |
| 140 | for axis_name, axis_build_descs in list(build_descs_by_axis.items()): | |
| 141 | if len(build_descs): | |
| 142 | # for each existing build_desc and each axis build desc, create a new build_desc | |
| 143 | new_build_descs = [] | |
| 144 | for prototype_build_desc, axis_build_desc in itertools.product( build_descs, axis_build_descs): | |
| 145 | new_build_descs.append( prototype_build_desc.merged_with( axis_build_desc ) ) | |
| 146 | build_descs = new_build_descs | |
| 147 | else: | |
| 148 | build_descs = axis_build_descs | |
| 149 | return build_descs | |
| 150 | ||
| 151 | HTML_TEMPLATE = string.Template('''<html> | |
| 152 | <head> | |
| 153 | <title>$title</title> | |
| 154 | <style type="text/css"> | |
| 155 | td.failed {background-color:#f08080;} | |
| 156 | td.ok {background-color:#c0eec0;} | |
| 157 | </style> | |
| 158 | </head> | |
| 159 | <body> | |
| 160 | <table border="1"> | |
| 161 | <thead> | |
| 162 | <tr> | |
| 163 | <th>Variables</th> | |
| 164 | $th_vars | |
| 165 | </tr> | |
| 166 | <tr> | |
| 167 | <th>Build type</th> | |
| 168 | $th_build_types | |
| 169 | </tr> | |
| 170 | </thead> | |
| 171 | <tbody> | |
| 172 | $tr_builds | |
| 173 | </tbody> | |
| 174 | </table> | |
| 175 | </body></html>''') | |
| 176 | ||
| 177 | def generate_html_report( html_report_path, builds ): | |
| 178 | report_dir = os.path.dirname( html_report_path ) | |
| 179 | # Vertical axis: generator | |
| 180 | # Horizontal: variables, then build_type | |
| 181 | builds_by_generator = collections.defaultdict( list ) | |
| 182 | variables = set() | |
| 183 | build_types_by_variable = collections.defaultdict( set ) | |
| 184 | build_by_pos_key = {} # { (generator, var_key, build_type): build } | |
| 185 | for build in builds: | |
| 186 | builds_by_generator[build.desc.generator].append( build ) | |
| 187 | var_key = tuple(sorted(build.desc.variables)) | |
| 188 | variables.add( var_key ) | |
| 189 | build_types_by_variable[var_key].add( build.desc.build_type ) | |
| 190 | pos_key = (build.desc.generator, var_key, build.desc.build_type) | |
| 191 | build_by_pos_key[pos_key] = build | |
| 192 | variables = sorted( variables ) | |
| 193 | th_vars = [] | |
| 194 | th_build_types = [] | |
| 195 | for variable in variables: | |
| 196 | build_types = sorted( build_types_by_variable[variable] ) | |
| 197 | nb_build_type = len(build_types_by_variable[variable]) | |
| 198 | th_vars.append( '<th colspan="%d">%s</th>' % (nb_build_type, cgi.escape( ' '.join( variable ) ) ) ) | |
| 199 | for build_type in build_types: | |
| 200 | th_build_types.append( '<th>%s</th>' % cgi.escape(build_type) ) | |
| 201 | tr_builds = [] | |
| 202 | for generator in sorted( builds_by_generator ): | |
| 203 | tds = [ '<td>%s</td>\n' % cgi.escape( generator ) ] | |
| 204 | for variable in variables: | |
| 205 | build_types = sorted( build_types_by_variable[variable] ) | |
| 206 | for build_type in build_types: | |
| 207 | pos_key = (generator, variable, build_type) | |
| 208 | build = build_by_pos_key.get(pos_key) | |
| 209 | if build: | |
| 210 | cmake_status = 'ok' if build.cmake_succeeded else 'FAILED' | |
| 211 | build_status = 'ok' if build.build_succeeded else 'FAILED' | |
| 212 | cmake_log_url = os.path.relpath( build.cmake_log_path, report_dir ) | |
| 213 | build_log_url = os.path.relpath( build.build_log_path, report_dir ) | |
| 214 | td = '<td class="%s"><a href="%s" class="%s">CMake: %s</a>' % ( | |
| 215 | build_status.lower(), cmake_log_url, cmake_status.lower(), cmake_status) | |
| 216 | if build.cmake_succeeded: | |
| 217 | td += '<br><a href="%s" class="%s">Build: %s</a>' % ( | |
| 218 | build_log_url, build_status.lower(), build_status) | |
| 219 | td += '</td>' | |
| 220 | else: | |
| 221 | td = '<td></td>' | |
| 222 | tds.append( td ) | |
| 223 | tr_builds.append( '<tr>%s</tr>' % '\n'.join( tds ) ) | |
| 224 | html = HTML_TEMPLATE.substitute( | |
| 225 | title='Batch build report', | |
| 226 | th_vars=' '.join(th_vars), | |
| 227 | th_build_types=' '.join( th_build_types), | |
| 228 | tr_builds='\n'.join( tr_builds ) ) | |
| 229 | with open( html_report_path, 'wt' ) as fhtml: | |
| 230 | fhtml.write( html ) | |
| 231 | print('HTML report generated in:', html_report_path) | |
| 232 | ||
| 233 | def main(): | |
| 234 | usage = r"""%prog WORK_DIR SOURCE_DIR CONFIG_JSON_PATH [CONFIG2_JSON_PATH...] | |
| 235 | Build a given CMake based project located in SOURCE_DIR with multiple generators/options.dry_run | |
| 236 | as described in CONFIG_JSON_PATH building in WORK_DIR. | |
| 237 | ||
| 238 | Example of call: | |
| 239 | python devtools\batchbuild.py e:\buildbots\jsoncpp\build . devtools\agent_vmw7.json | |
| 240 | """ | |
| 241 | from optparse import OptionParser | |
| 242 | parser = OptionParser(usage=usage) | |
| 243 | parser.allow_interspersed_args = True | |
| 244 | # parser.add_option('-v', '--verbose', dest="verbose", action='store_true', | |
| 245 | # help="""Be verbose.""") | |
| 246 | parser.enable_interspersed_args() | |
| 247 | options, args = parser.parse_args() | |
| 248 | if len(args) < 3: | |
| 249 | parser.error( "Missing one of WORK_DIR SOURCE_DIR CONFIG_JSON_PATH." ) | |
| 250 | work_dir = args[0] | |
| 251 | source_dir = args[1].rstrip('/\\') | |
| 252 | config_paths = args[2:] | |
| 253 | for config_path in config_paths: | |
| 254 | if not os.path.isfile( config_path ): | |
| 255 | parser.error( "Can not read: %r" % config_path ) | |
| 256 | ||
| 257 | # generate build variants | |
| 258 | build_descs = [] | |
| 259 | for config_path in config_paths: | |
| 260 | build_descs_by_axis = load_build_variants_from_config( config_path ) | |
| 261 | build_descs.extend( generate_build_variants( build_descs_by_axis ) ) | |
| 262 | print('Build variants (%d):' % len(build_descs)) | |
| 263 | # assign build directory for each variant | |
| 264 | if not os.path.isdir( work_dir ): | |
| 265 | os.makedirs( work_dir ) | |
| 266 | builds = [] | |
| 267 | with open( os.path.join( work_dir, 'matrix-dir-map.txt' ), 'wt' ) as fmatrixmap: | |
| 268 | for index, build_desc in enumerate( build_descs ): | |
| 269 | build_desc_work_dir = os.path.join( work_dir, '%03d' % (index+1) ) | |
| 270 | builds.append( BuildData( build_desc, build_desc_work_dir, source_dir ) ) | |
| 271 | fmatrixmap.write( '%s: %s\n' % (build_desc_work_dir, build_desc) ) | |
| 272 | for build in builds: | |
| 273 | build.execute_build() | |
| 274 | html_report_path = os.path.join( work_dir, 'batchbuild-report.html' ) | |
| 275 | generate_html_report( html_report_path, builds ) | |
| 276 | print('Done') | |
| 277 | ||
| 278 | ||
| 279 | if __name__ == '__main__': | |
| 280 | main() | |
| 281 |
| r0 | r242831 | |
|---|---|---|
| 1 | from __future__ import print_function | |
| 2 | import os.path | |
| 3 | ||
| 4 | def fix_source_eol( path, is_dry_run = True, verbose = True, eol = '\n' ): | |
| 5 | """Makes sure that all sources have the specified eol sequence (default: unix).""" | |
| 6 | if not os.path.isfile( path ): | |
| 7 | raise ValueError( 'Path "%s" is not a file' % path ) | |
| 8 | try: | |
| 9 | f = open(path, 'rb') | |
| 10 | except IOError as msg: | |
| 11 | print("%s: I/O Error: %s" % (file, str(msg)), file=sys.stderr) | |
| 12 | return False | |
| 13 | try: | |
| 14 | raw_lines = f.readlines() | |
| 15 | finally: | |
| 16 | f.close() | |
| 17 | fixed_lines = [line.rstrip('\r\n') + eol for line in raw_lines] | |
| 18 | if raw_lines != fixed_lines: | |
| 19 | print('%s =>' % path, end=' ') | |
| 20 | if not is_dry_run: | |
| 21 | f = open(path, "wb") | |
| 22 | try: | |
| 23 | f.writelines(fixed_lines) | |
| 24 | finally: | |
| 25 | f.close() | |
| 26 | if verbose: | |
| 27 | print(is_dry_run and ' NEED FIX' or ' FIXED') | |
| 28 | return True | |
| 29 | ## | |
| 30 | ## | |
| 31 | ## | |
| 32 | ##def _do_fix( is_dry_run = True ): | |
| 33 | ## from waftools import antglob | |
| 34 | ## python_sources = antglob.glob( '.', | |
| 35 | ## includes = '**/*.py **/wscript **/wscript_build', | |
| 36 | ## excludes = antglob.default_excludes + './waf.py', | |
| 37 | ## prune_dirs = antglob.prune_dirs + 'waf-* ./build' ) | |
| 38 | ## for path in python_sources: | |
| 39 | ## _fix_python_source( path, is_dry_run ) | |
| 40 | ## | |
| 41 | ## cpp_sources = antglob.glob( '.', | |
| 42 | ## includes = '**/*.cpp **/*.h **/*.inl', | |
| 43 | ## prune_dirs = antglob.prune_dirs + 'waf-* ./build' ) | |
| 44 | ## for path in cpp_sources: | |
| 45 | ## _fix_source_eol( path, is_dry_run ) | |
| 46 | ## | |
| 47 | ## | |
| 48 | ##def dry_fix(context): | |
| 49 | ## _do_fix( is_dry_run = True ) | |
| 50 | ## | |
| 51 | ##def fix(context): | |
| 52 | ## _do_fix( is_dry_run = False ) | |
| 53 | ## | |
| 54 | ##def shutdown(): | |
| 55 | ## pass | |
| 56 | ## | |
| 57 | ##def check(context): | |
| 58 | ## # Unit tests are run when "check" target is used | |
| 59 | ## ut = UnitTest.unit_test() | |
| 60 | ## ut.change_to_testfile_dir = True | |
| 61 | ## ut.want_to_see_test_output = True | |
| 62 | ## ut.want_to_see_test_error = True | |
| 63 | ## ut.run() | |
| 64 | ## ut.print_results() |
| r0 | r242831 | |
|---|---|---|
| 1 | """Updates the license text in source file. | |
| 2 | """ | |
| 3 | from __future__ import print_function | |
| 4 | ||
| 5 | # An existing license is found if the file starts with the string below, | |
| 6 | # and ends with the first blank line. | |
| 7 | LICENSE_BEGIN = "// Copyright " | |
| 8 | ||
| 9 | BRIEF_LICENSE = LICENSE_BEGIN + """2007-2010 Baptiste Lepilleur | |
| 10 | // Distributed under MIT license, or public domain if desired and | |
| 11 | // recognized in your jurisdiction. | |
| 12 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE | |
| 13 | ||
| 14 | """.replace('\r\n','\n') | |
| 15 | ||
| 16 | def update_license( path, dry_run, show_diff ): | |
| 17 | """Update the license statement in the specified file. | |
| 18 | Parameters: | |
| 19 | path: path of the C++ source file to update. | |
| 20 | dry_run: if True, just print the path of the file that would be updated, | |
| 21 | but don't change it. | |
| 22 | show_diff: if True, print the path of the file that would be modified, | |
| 23 | as well as the change made to the file. | |
| 24 | """ | |
| 25 | with open( path, 'rt' ) as fin: | |
| 26 | original_text = fin.read().replace('\r\n','\n') | |
| 27 | newline = fin.newlines and fin.newlines[0] or '\n' | |
| 28 | if not original_text.startswith( LICENSE_BEGIN ): | |
| 29 | # No existing license found => prepend it | |
| 30 | new_text = BRIEF_LICENSE + original_text | |
| 31 | else: | |
| 32 | license_end_index = original_text.index( '\n\n' ) # search first blank line | |
| 33 | new_text = BRIEF_LICENSE + original_text[license_end_index+2:] | |
| 34 | if original_text != new_text: | |
| 35 | if not dry_run: | |
| 36 | with open( path, 'wb' ) as fout: | |
| 37 | fout.write( new_text.replace('\n', newline ) ) | |
| 38 | print('Updated', path) | |
| 39 | if show_diff: | |
| 40 | import difflib | |
| 41 | print('\n'.join( difflib.unified_diff( original_text.split('\n'), | |
| 42 | new_text.split('\n') ) )) | |
| 43 | return True | |
| 44 | return False | |
| 45 | ||
| 46 | def update_license_in_source_directories( source_dirs, dry_run, show_diff ): | |
| 47 | """Updates license text in C++ source files found in directory source_dirs. | |
| 48 | Parameters: | |
| 49 | source_dirs: list of directory to scan for C++ sources. Directories are | |
| 50 | scanned recursively. | |
| 51 | dry_run: if True, just print the path of the file that would be updated, | |
| 52 | but don't change it. | |
| 53 | show_diff: if True, print the path of the file that would be modified, | |
| 54 | as well as the change made to the file. | |
| 55 | """ | |
| 56 | from devtools import antglob | |
| 57 | prune_dirs = antglob.prune_dirs + 'scons-local* ./build* ./libs ./dist' | |
| 58 | for source_dir in source_dirs: | |
| 59 | cpp_sources = antglob.glob( source_dir, | |
| 60 | includes = '''**/*.h **/*.cpp **/*.inl''', | |
| 61 | prune_dirs = prune_dirs ) | |
| 62 | for source in cpp_sources: | |
| 63 | update_license( source, dry_run, show_diff ) | |
| 64 | ||
| 65 | def main(): | |
| 66 | usage = """%prog DIR [DIR2...] | |
| 67 | Updates license text in sources of the project in source files found | |
| 68 | in the directory specified on the command-line. | |
| 69 | ||
| 70 | Example of call: | |
| 71 | python devtools\licenseupdater.py include src -n --diff | |
| 72 | => Show change that would be made to the sources. | |
| 73 | ||
| 74 | python devtools\licenseupdater.py include src | |
| 75 | => Update license statement on all sources in directories include/ and src/. | |
| 76 | """ | |
| 77 | from optparse import OptionParser | |
| 78 | parser = OptionParser(usage=usage) | |
| 79 | parser.allow_interspersed_args = False | |
| 80 | parser.add_option('-n', '--dry-run', dest="dry_run", action='store_true', default=False, | |
| 81 | help="""Only show what files are updated, do not update the files""") | |
| 82 | parser.add_option('--diff', dest="show_diff", action='store_true', default=False, | |
| 83 | help="""On update, show change made to the file.""") | |
| 84 | parser.enable_interspersed_args() | |
| 85 | options, args = parser.parse_args() | |
| 86 | update_license_in_source_directories( args, options.dry_run, options.show_diff ) | |
| 87 | print('Done') | |
| 88 | ||
| 89 | if __name__ == '__main__': | |
| 90 | import sys | |
| 91 | import os.path | |
| 92 | sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | |
| 93 | main() | |
| 94 |
| r0 | r242831 | |
|---|---|---|
| 1 | import os.path | |
| 2 | import gzip | |
| 3 | import tarfile | |
| 4 | ||
| 5 | TARGZ_DEFAULT_COMPRESSION_LEVEL = 9 | |
| 6 | ||
| 7 | def make_tarball(tarball_path, sources, base_dir, prefix_dir=''): | |
| 8 | """Parameters: | |
| 9 | tarball_path: output path of the .tar.gz file | |
| 10 | sources: list of sources to include in the tarball, relative to the current directory | |
| 11 | base_dir: if a source file is in a sub-directory of base_dir, then base_dir is stripped | |
| 12 | from path in the tarball. | |
| 13 | prefix_dir: all files stored in the tarball be sub-directory of prefix_dir. Set to '' | |
| 14 | to make them child of root. | |
| 15 | """ | |
| 16 | base_dir = os.path.normpath( os.path.abspath( base_dir ) ) | |
| 17 | def archive_name( path ): | |
| 18 | """Makes path relative to base_dir.""" | |
| 19 | path = os.path.normpath( os.path.abspath( path ) ) | |
| 20 | common_path = os.path.commonprefix( (base_dir, path) ) | |
| 21 | archive_name = path[len(common_path):] | |
| 22 | if os.path.isabs( archive_name ): | |
| 23 | archive_name = archive_name[1:] | |
| 24 | return os.path.join( prefix_dir, archive_name ) | |
| 25 | def visit(tar, dirname, names): | |
| 26 | for name in names: | |
| 27 | path = os.path.join(dirname, name) | |
| 28 | if os.path.isfile(path): | |
| 29 | path_in_tar = archive_name(path) | |
| 30 | tar.add(path, path_in_tar ) | |
| 31 | compression = TARGZ_DEFAULT_COMPRESSION_LEVEL | |
| 32 | tar = tarfile.TarFile.gzopen( tarball_path, 'w', compresslevel=compression ) | |
| 33 | try: | |
| 34 | for source in sources: | |
| 35 | source_path = source | |
| 36 | if os.path.isdir( source ): | |
| 37 | os.path.walk(source_path, visit, tar) | |
| 38 | else: | |
| 39 | path_in_tar = archive_name(source_path) | |
| 40 | tar.add(source_path, path_in_tar ) # filename, arcname | |
| 41 | finally: | |
| 42 | tar.close() | |
| 43 | ||
| 44 | def decompress( tarball_path, base_dir ): | |
| 45 | """Decompress the gzipped tarball into directory base_dir. | |
| 46 | """ | |
| 47 | # !!! This class method is not documented in the online doc | |
| 48 | # nor is bz2open! | |
| 49 | tar = tarfile.TarFile.gzopen(tarball_path, mode='r') | |
| 50 | try: | |
| 51 | tar.extractall( base_dir ) | |
| 52 | finally: | |
| 53 | tar.close() |
| r0 | r242831 | |
|---|---|---|
| 1 | # Doxyfile 1.8.5 | |
| 2 | ||
| 3 | # This file describes the settings to be used by the documentation system | |
| 4 | # doxygen (www.doxygen.org) for a project. | |
| 5 | # | |
| 6 | # All text after a double hash (##) is considered a comment and is placed in | |
| 7 | # front of the TAG it is preceding. | |
| 8 | # | |
| 9 | # All text after a single hash (#) is considered a comment and will be ignored. | |
| 10 | # The format is: | |
| 11 | # TAG = value [value, ...] | |
| 12 | # For lists, items can also be appended using: | |
| 13 | # TAG += value [value, ...] | |
| 14 | # Values that contain spaces should be placed between quotes (\" \"). | |
| 15 | ||
| 16 | #--------------------------------------------------------------------------- | |
| 17 | # Project related configuration options | |
| 18 | #--------------------------------------------------------------------------- | |
| 19 | ||
| 20 | # This tag specifies the encoding used for all characters in the config file | |
| 21 | # that follow. The default is UTF-8 which is also the encoding used for all text | |
| 22 | # before the first occurrence of this tag. Doxygen uses libiconv (or the iconv | |
| 23 | # built into libc) for the transcoding. See http://www.gnu.org/software/libiconv | |
| 24 | # for the list of possible encodings. | |
| 25 | # The default value is: UTF-8. | |
| 26 | ||
| 27 | DOXYFILE_ENCODING = UTF-8 | |
| 28 | ||
| 29 | # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by | |
| 30 | # double-quotes, unless you are using Doxywizard) that should identify the | |
| 31 | # project for which the documentation is generated. This name is used in the | |
| 32 | # title of most generated pages and in a few other places. | |
| 33 | # The default value is: My Project. | |
| 34 | ||
| 35 | PROJECT_NAME = "JsonCpp" | |
| 36 | ||
| 37 | # The PROJECT_NUMBER tag can be used to enter a project or revision number. This | |
| 38 | # could be handy for archiving the generated documentation or if some version | |
| 39 | # control system is used. | |
| 40 | ||
| 41 | PROJECT_NUMBER = %JSONCPP_VERSION% | |
| 42 | ||
| 43 | # Using the PROJECT_BRIEF tag one can provide an optional one line description | |
| 44 | # for a project that appears at the top of each page and should give viewer a | |
| 45 | # quick idea about the purpose of the project. Keep the description short. | |
| 46 | ||
| 47 | PROJECT_BRIEF = | |
| 48 | ||
| 49 | # With the PROJECT_LOGO tag one can specify an logo or icon that is included in | |
| 50 | # the documentation. The maximum height of the logo should not exceed 55 pixels | |
| 51 | # and the maximum width should not exceed 200 pixels. Doxygen will copy the logo | |
| 52 | # to the output directory. | |
| 53 | ||
| 54 | PROJECT_LOGO = | |
| 55 | ||
| 56 | # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path | |
| 57 | # into which the generated documentation will be written. If a relative path is | |
| 58 | # entered, it will be relative to the location where doxygen was started. If | |
| 59 | # left blank the current directory will be used. | |
| 60 | ||
| 61 | OUTPUT_DIRECTORY = %DOC_TOPDIR% | |
| 62 | ||
| 63 | # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- | |
| 64 | # directories (in 2 levels) under the output directory of each output format and | |
| 65 | # will distribute the generated files over these directories. Enabling this | |
| 66 | # option can be useful when feeding doxygen a huge amount of source files, where | |
| 67 | # putting all generated files in the same directory would otherwise causes | |
| 68 | # performance problems for the file system. | |
| 69 | # The default value is: NO. | |
| 70 | ||
| 71 | CREATE_SUBDIRS = NO | |
| 72 | ||
| 73 | # The OUTPUT_LANGUAGE tag is used to specify the language in which all | |
| 74 | # documentation generated by doxygen is written. Doxygen will use this | |
| 75 | # information to generate all constant output in the proper language. | |
| 76 | # Possible values are: Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese- | |
| 77 | # Traditional, Croatian, Czech, Danish, Dutch, English, Esperanto, Farsi, | |
| 78 | # Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en, | |
| 79 | # Korean, Korean-en, Latvian, Norwegian, Macedonian, Persian, Polish, | |
| 80 | # Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, | |
| 81 | # Turkish, Ukrainian and Vietnamese. | |
| 82 | # The default value is: English. | |
| 83 | ||
| 84 | OUTPUT_LANGUAGE = English | |
| 85 | ||
| 86 | # If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member | |
| 87 | # descriptions after the members that are listed in the file and class | |
| 88 | # documentation (similar to Javadoc). Set to NO to disable this. | |
| 89 | # The default value is: YES. | |
| 90 | ||
| 91 | BRIEF_MEMBER_DESC = YES | |
| 92 | ||
| 93 | # If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief | |
| 94 | # description of a member or function before the detailed description | |
| 95 | # | |
| 96 | # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the | |
| 97 | # brief descriptions will be completely suppressed. | |
| 98 | # The default value is: YES. | |
| 99 | ||
| 100 | REPEAT_BRIEF = YES | |
| 101 | ||
| 102 | # This tag implements a quasi-intelligent brief description abbreviator that is | |
| 103 | # used to form the text in various listings. Each string in this list, if found | |
| 104 | # as the leading text of the brief description, will be stripped from the text | |
| 105 | # and the result, after processing the whole list, is used as the annotated | |
| 106 | # text. Otherwise, the brief description is used as-is. If left blank, the | |
| 107 | # following values are used ($name is automatically replaced with the name of | |
| 108 | # the entity):The $name class, The $name widget, The $name file, is, provides, | |
| 109 | # specifies, contains, represents, a, an and the. | |
| 110 | ||
| 111 | ABBREVIATE_BRIEF = "The $name class" \ | |
| 112 | "The $name widget" \ | |
| 113 | "The $name file" \ | |
| 114 | is \ | |
| 115 | provides \ | |
| 116 | specifies \ | |
| 117 | contains \ | |
| 118 | represents \ | |
| 119 | a \ | |
| 120 | an \ | |
| 121 | the | |
| 122 | ||
| 123 | # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then | |
| 124 | # doxygen will generate a detailed section even if there is only a brief | |
| 125 | # description. | |
| 126 | # The default value is: NO. | |
| 127 | ||
| 128 | ALWAYS_DETAILED_SEC = NO | |
| 129 | ||
| 130 | # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all | |
| 131 | # inherited members of a class in the documentation of that class as if those | |
| 132 | # members were ordinary class members. Constructors, destructors and assignment | |
| 133 | # operators of the base classes will not be shown. | |
| 134 | # The default value is: NO. | |
| 135 | ||
| 136 | INLINE_INHERITED_MEMB = NO | |
| 137 | ||
| 138 | # If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path | |
| 139 | # before files name in the file list and in the header files. If set to NO the | |
| 140 | # shortest path that makes the file name unique will be used | |
| 141 | # The default value is: YES. | |
| 142 | ||
| 143 | FULL_PATH_NAMES = YES | |
| 144 | ||
| 145 | # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. | |
| 146 | # Stripping is only done if one of the specified strings matches the left-hand | |
| 147 | # part of the path. The tag can be used to show relative paths in the file list. | |
| 148 | # If left blank the directory from which doxygen is run is used as the path to | |
| 149 | # strip. | |
| 150 | # | |
| 151 | # Note that you can specify absolute paths here, but also relative paths, which | |
| 152 | # will be relative from the directory where doxygen is started. | |
| 153 | # This tag requires that the tag FULL_PATH_NAMES is set to YES. | |
| 154 | ||
| 155 | STRIP_FROM_PATH = %TOPDIR% | |
| 156 | ||
| 157 | # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the | |
| 158 | # path mentioned in the documentation of a class, which tells the reader which | |
| 159 | # header file to include in order to use a class. If left blank only the name of | |
| 160 | # the header file containing the class definition is used. Otherwise one should | |
| 161 | # specify the list of include paths that are normally passed to the compiler | |
| 162 | # using the -I flag. | |
| 163 | ||
| 164 | STRIP_FROM_INC_PATH = %TOPDIR%/include | |
| 165 | ||
| 166 | # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but | |
| 167 | # less readable) file names. This can be useful is your file systems doesn't | |
| 168 | # support long names like on DOS, Mac, or CD-ROM. | |
| 169 | # The default value is: NO. | |
| 170 | ||
| 171 | SHORT_NAMES = NO | |
| 172 | ||
| 173 | # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the | |
| 174 | # first line (until the first dot) of a Javadoc-style comment as the brief | |
| 175 | # description. If set to NO, the Javadoc-style will behave just like regular Qt- | |
| 176 | # style comments (thus requiring an explicit @brief command for a brief | |
| 177 | # description.) | |
| 178 | # The default value is: NO. | |
| 179 | ||
| 180 | JAVADOC_AUTOBRIEF = YES | |
| 181 | ||
| 182 | # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first | |
| 183 | # line (until the first dot) of a Qt-style comment as the brief description. If | |
| 184 | # set to NO, the Qt-style will behave just like regular Qt-style comments (thus | |
| 185 | # requiring an explicit \brief command for a brief description.) | |
| 186 | # The default value is: NO. | |
| 187 | ||
| 188 | QT_AUTOBRIEF = NO | |
| 189 | ||
| 190 | # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a | |
| 191 | # multi-line C++ special comment block (i.e. a block of //! or /// comments) as | |
| 192 | # a brief description. This used to be the default behavior. The new default is | |
| 193 | # to treat a multi-line C++ comment block as a detailed description. Set this | |
| 194 | # tag to YES if you prefer the old behavior instead. | |
| 195 | # | |
| 196 | # Note that setting this tag to YES also means that rational rose comments are | |
| 197 | # not recognized any more. | |
| 198 | # The default value is: NO. | |
| 199 | ||
| 200 | MULTILINE_CPP_IS_BRIEF = NO | |
| 201 | ||
| 202 | # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the | |
| 203 | # documentation from any documented member that it re-implements. | |
| 204 | # The default value is: YES. | |
| 205 | ||
| 206 | INHERIT_DOCS = YES | |
| 207 | ||
| 208 | # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a | |
| 209 | # new page for each member. If set to NO, the documentation of a member will be | |
| 210 | # part of the file/class/namespace that contains it. | |
| 211 | # The default value is: NO. | |
| 212 | ||
| 213 | SEPARATE_MEMBER_PAGES = NO | |
| 214 | ||
| 215 | # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen | |
| 216 | # uses this value to replace tabs by spaces in code fragments. | |
| 217 | # Minimum value: 1, maximum value: 16, default value: 4. | |
| 218 | ||
| 219 | TAB_SIZE = 3 | |
| 220 | ||
| 221 | # This tag can be used to specify a number of aliases that act as commands in | |
| 222 | # the documentation. An alias has the form: | |
| 223 | # name=value | |
| 224 | # For example adding | |
| 225 | # "sideeffect=@par Side Effects:\n" | |
| 226 | # will allow you to put the command \sideeffect (or @sideeffect) in the | |
| 227 | # documentation, which will result in a user-defined paragraph with heading | |
| 228 | # "Side Effects:". You can put \n's in the value part of an alias to insert | |
| 229 | # newlines. | |
| 230 | ||
| 231 | ALIASES = "testCaseSetup=\link CppUT::TestCase::setUp() setUp()\endlink" \ | |
| 232 | "testCaseRun=\link CppUT::TestCase::run() run()\endlink" \ | |
| 233 | "testCaseTearDown=\link CppUT::TestCase::tearDown() tearDown()\endlink" \ | |
| 234 | "json_ref=<a HREF='http://www.json.org/'>JSON (JavaScript Object Notation)</a>" | |
| 235 | ||
| 236 | # This tag can be used to specify a number of word-keyword mappings (TCL only). | |
| 237 | # A mapping has the form "name=value". For example adding "class=itcl::class" | |
| 238 | # will allow you to use the command class in the itcl::class meaning. | |
| 239 | ||
| 240 | TCL_SUBST = | |
| 241 | ||
| 242 | # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources | |
| 243 | # only. Doxygen will then generate output that is more tailored for C. For | |
| 244 | # instance, some of the names that are used will be different. The list of all | |
| 245 | # members will be omitted, etc. | |
| 246 | # The default value is: NO. | |
| 247 | ||
| 248 | OPTIMIZE_OUTPUT_FOR_C = NO | |
| 249 | ||
| 250 | # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or | |
| 251 | # Python sources only. Doxygen will then generate output that is more tailored | |
| 252 | # for that language. For instance, namespaces will be presented as packages, | |
| 253 | # qualified scopes will look different, etc. | |
| 254 | # The default value is: NO. | |
| 255 | ||
| 256 | OPTIMIZE_OUTPUT_JAVA = NO | |
| 257 | ||
| 258 | # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran | |
| 259 | # sources. Doxygen will then generate output that is tailored for Fortran. | |
| 260 | # The default value is: NO. | |
| 261 | ||
| 262 | OPTIMIZE_FOR_FORTRAN = NO | |
| 263 | ||
| 264 | # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL | |
| 265 | # sources. Doxygen will then generate output that is tailored for VHDL. | |
| 266 | # The default value is: NO. | |
| 267 | ||
| 268 | OPTIMIZE_OUTPUT_VHDL = NO | |
| 269 | ||
| 270 | # Doxygen selects the parser to use depending on the extension of the files it | |
| 271 | # parses. With this tag you can assign which parser to use for a given | |
| 272 | # extension. Doxygen has a built-in mapping, but you can override or extend it | |
| 273 | # using this tag. The format is ext=language, where ext is a file extension, and | |
| 274 | # language is one of the parsers supported by doxygen: IDL, Java, Javascript, | |
| 275 | # C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make | |
| 276 | # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C | |
| 277 | # (default is Fortran), use: inc=Fortran f=C. | |
| 278 | # | |
| 279 | # Note For files without extension you can use no_extension as a placeholder. | |
| 280 | # | |
| 281 | # Note that for custom extensions you also need to set FILE_PATTERNS otherwise | |
| 282 | # the files are not read by doxygen. | |
| 283 | ||
| 284 | EXTENSION_MAPPING = | |
| 285 | ||
| 286 | # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments | |
| 287 | # according to the Markdown format, which allows for more readable | |
| 288 | # documentation. See http://daringfireball.net/projects/markdown/ for details. | |
| 289 | # The output of markdown processing is further processed by doxygen, so you can | |
| 290 | # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in | |
| 291 | # case of backward compatibilities issues. | |
| 292 | # The default value is: YES. | |
| 293 | ||
| 294 | MARKDOWN_SUPPORT = YES | |
| 295 | ||
| 296 | # When enabled doxygen tries to link words that correspond to documented | |
| 297 | # classes, or namespaces to their corresponding documentation. Such a link can | |
| 298 | # be prevented in individual cases by by putting a % sign in front of the word | |
| 299 | # or globally by setting AUTOLINK_SUPPORT to NO. | |
| 300 | # The default value is: YES. | |
| 301 | ||
| 302 | AUTOLINK_SUPPORT = YES | |
| 303 | ||
| 304 | # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want | |
| 305 | # to include (a tag file for) the STL sources as input, then you should set this | |
| 306 | # tag to YES in order to let doxygen match functions declarations and | |
| 307 | # definitions whose arguments contain STL classes (e.g. func(std::string); | |
| 308 | # versus func(std::string) {}). This also make the inheritance and collaboration | |
| 309 | # diagrams that involve STL classes more complete and accurate. | |
| 310 | # The default value is: NO. | |
| 311 | ||
| 312 | BUILTIN_STL_SUPPORT = YES | |
| 313 | ||
| 314 | # If you use Microsoft's C++/CLI language, you should set this option to YES to | |
| 315 | # enable parsing support. | |
| 316 | # The default value is: NO. | |
| 317 | ||
| 318 | CPP_CLI_SUPPORT = NO | |
| 319 | ||
| 320 | # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: | |
| 321 | # http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen | |
| 322 | # will parse them like normal C++ but will assume all classes use public instead | |
| 323 | # of private inheritance when no explicit protection keyword is present. | |
| 324 | # The default value is: NO. | |
| 325 | ||
| 326 | SIP_SUPPORT = NO | |
| 327 | ||
| 328 | # For Microsoft's IDL there are propget and propput attributes to indicate | |
| 329 | # getter and setter methods for a property. Setting this option to YES will make | |
| 330 | # doxygen to replace the get and set methods by a property in the documentation. | |
| 331 | # This will only work if the methods are indeed getting or setting a simple | |
| 332 | # type. If this is not the case, or you want to show the methods anyway, you | |
| 333 | # should set this option to NO. | |
| 334 | # The default value is: YES. | |
| 335 | ||
| 336 | IDL_PROPERTY_SUPPORT = YES | |
| 337 | ||
| 338 | # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC | |
| 339 | # tag is set to YES, then doxygen will reuse the documentation of the first | |
| 340 | # member in the group (if any) for the other members of the group. By default | |
| 341 | # all members of a group must be documented explicitly. | |
| 342 | # The default value is: NO. | |
| 343 | ||
| 344 | DISTRIBUTE_GROUP_DOC = NO | |
| 345 | ||
| 346 | # Set the SUBGROUPING tag to YES to allow class member groups of the same type | |
| 347 | # (for instance a group of public functions) to be put as a subgroup of that | |
| 348 | # type (e.g. under the Public Functions section). Set it to NO to prevent | |
| 349 | # subgrouping. Alternatively, this can be done per class using the | |
| 350 | # \nosubgrouping command. | |
| 351 | # The default value is: YES. | |
| 352 | ||
| 353 | SUBGROUPING = YES | |
| 354 | ||
| 355 | # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions | |
| 356 | # are shown inside the group in which they are included (e.g. using \ingroup) | |
| 357 | # instead of on a separate page (for HTML and Man pages) or section (for LaTeX | |
| 358 | # and RTF). | |
| 359 | # | |
| 360 | # Note that this feature does not work in combination with | |
| 361 | # SEPARATE_MEMBER_PAGES. | |
| 362 | # The default value is: NO. | |
| 363 | ||
| 364 | INLINE_GROUPED_CLASSES = NO | |
| 365 | ||
| 366 | # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions | |
| 367 | # with only public data fields or simple typedef fields will be shown inline in | |
| 368 | # the documentation of the scope in which they are defined (i.e. file, | |
| 369 | # namespace, or group documentation), provided this scope is documented. If set | |
| 370 | # to NO, structs, classes, and unions are shown on a separate page (for HTML and | |
| 371 | # Man pages) or section (for LaTeX and RTF). | |
| 372 | # The default value is: NO. | |
| 373 | ||
| 374 | INLINE_SIMPLE_STRUCTS = NO | |
| 375 | ||
| 376 | # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or | |
| 377 | # enum is documented as struct, union, or enum with the name of the typedef. So | |
| 378 | # typedef struct TypeS {} TypeT, will appear in the documentation as a struct | |
| 379 | # with name TypeT. When disabled the typedef will appear as a member of a file, | |
| 380 | # namespace, or class. And the struct will be named TypeS. This can typically be | |
| 381 | # useful for C code in case the coding convention dictates that all compound | |
| 382 | # types are typedef'ed and only the typedef is referenced, never the tag name. | |
| 383 | # The default value is: NO. | |
| 384 | ||
| 385 | TYPEDEF_HIDES_STRUCT = NO | |
| 386 | ||
| 387 | # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This | |
| 388 | # cache is used to resolve symbols given their name and scope. Since this can be | |
| 389 | # an expensive process and often the same symbol appears multiple times in the | |
| 390 | # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small | |
| 391 | # doxygen will become slower. If the cache is too large, memory is wasted. The | |
| 392 | # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range | |
| 393 | # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 | |
| 394 | # symbols. At the end of a run doxygen will report the cache usage and suggest | |
| 395 | # the optimal cache size from a speed point of view. | |
| 396 | # Minimum value: 0, maximum value: 9, default value: 0. | |
| 397 | ||
| 398 | LOOKUP_CACHE_SIZE = 0 | |
| 399 | ||
| 400 | #--------------------------------------------------------------------------- | |
| 401 | # Build related configuration options | |
| 402 | #--------------------------------------------------------------------------- | |
| 403 | ||
| 404 | # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in | |
| 405 | # documentation are documented, even if no documentation was available. Private | |
| 406 | # class members and static file members will be hidden unless the | |
| 407 | # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. | |
| 408 | # Note: This will also disable the warnings about undocumented members that are | |
| 409 | # normally produced when WARNINGS is set to YES. | |
| 410 | # The default value is: NO. | |
| 411 | ||
| 412 | EXTRACT_ALL = YES | |
| 413 | ||
| 414 | # If the EXTRACT_PRIVATE tag is set to YES all private members of a class will | |
| 415 | # be included in the documentation. | |
| 416 | # The default value is: NO. | |
| 417 | ||
| 418 | EXTRACT_PRIVATE = NO | |
| 419 | ||
| 420 | # If the EXTRACT_PACKAGE tag is set to YES all members with package or internal | |
| 421 | # scope will be included in the documentation. | |
| 422 | # The default value is: NO. | |
| 423 | ||
| 424 | EXTRACT_PACKAGE = NO | |
| 425 | ||
| 426 | # If the EXTRACT_STATIC tag is set to YES all static members of a file will be | |
| 427 | # included in the documentation. | |
| 428 | # The default value is: NO. | |
| 429 | ||
| 430 | EXTRACT_STATIC = YES | |
| 431 | ||
| 432 | # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined | |
| 433 | # locally in source files will be included in the documentation. If set to NO | |
| 434 | # only classes defined in header files are included. Does not have any effect | |
| 435 | # for Java sources. | |
| 436 | # The default value is: YES. | |
| 437 | ||
| 438 | EXTRACT_LOCAL_CLASSES = NO | |
| 439 | ||
| 440 | # This flag is only useful for Objective-C code. When set to YES local methods, | |
| 441 | # which are defined in the implementation section but not in the interface are | |
| 442 | # included in the documentation. If set to NO only methods in the interface are | |
| 443 | # included. | |
| 444 | # The default value is: NO. | |
| 445 | ||
| 446 | EXTRACT_LOCAL_METHODS = NO | |
| 447 | ||
| 448 | # If this flag is set to YES, the members of anonymous namespaces will be | |
| 449 | # extracted and appear in the documentation as a namespace called | |
| 450 | # 'anonymous_namespace{file}', where file will be replaced with the base name of | |
| 451 | # the file that contains the anonymous namespace. By default anonymous namespace | |
| 452 | # are hidden. | |
| 453 | # The default value is: NO. | |
| 454 | ||
| 455 | EXTRACT_ANON_NSPACES = NO | |
| 456 | ||
| 457 | # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all | |
| 458 | # undocumented members inside documented classes or files. If set to NO these | |
| 459 | # members will be included in the various overviews, but no documentation | |
| 460 | # section is generated. This option has no effect if EXTRACT_ALL is enabled. | |
| 461 | # The default value is: NO. | |
| 462 | ||
| 463 | HIDE_UNDOC_MEMBERS = NO | |
| 464 | ||
| 465 | # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all | |
| 466 | # undocumented classes that are normally visible in the class hierarchy. If set | |
| 467 | # to NO these classes will be included in the various overviews. This option has | |
| 468 | # no effect if EXTRACT_ALL is enabled. | |
| 469 | # The default value is: NO. | |
| 470 | ||
| 471 | HIDE_UNDOC_CLASSES = NO | |
| 472 | ||
| 473 | # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend | |
| 474 | # (class|struct|union) declarations. If set to NO these declarations will be | |
| 475 | # included in the documentation. | |
| 476 | # The default value is: NO. | |
| 477 | ||
| 478 | HIDE_FRIEND_COMPOUNDS = NO | |
| 479 | ||
| 480 | # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any | |
| 481 | # documentation blocks found inside the body of a function. If set to NO these | |
| 482 | # blocks will be appended to the function's detailed documentation block. | |
| 483 | # The default value is: NO. | |
| 484 | ||
| 485 | HIDE_IN_BODY_DOCS = NO | |
| 486 | ||
| 487 | # The INTERNAL_DOCS tag determines if documentation that is typed after a | |
| 488 | # \internal command is included. If the tag is set to NO then the documentation | |
| 489 | # will be excluded. Set it to YES to include the internal documentation. | |
| 490 | # The default value is: NO. | |
| 491 | ||
| 492 | INTERNAL_DOCS = YES | |
| 493 | ||
| 494 | # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file | |
| 495 | # names in lower-case letters. If set to YES upper-case letters are also | |
| 496 | # allowed. This is useful if you have classes or files whose names only differ | |
| 497 | # in case and if your file system supports case sensitive file names. Windows | |
| 498 | # and Mac users are advised to set this option to NO. | |
| 499 | # The default value is: system dependent. | |
| 500 | ||
| 501 | CASE_SENSE_NAMES = NO | |
| 502 | ||
| 503 | # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with | |
| 504 | # their full class and namespace scopes in the documentation. If set to YES the | |
| 505 | # scope will be hidden. | |
| 506 | # The default value is: NO. | |
| 507 | ||
| 508 | HIDE_SCOPE_NAMES = NO | |
| 509 | ||
| 510 | # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of | |
| 511 | # the files that are included by a file in the documentation of that file. | |
| 512 | # The default value is: YES. | |
| 513 | ||
| 514 | SHOW_INCLUDE_FILES = YES | |
| 515 | ||
| 516 | # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include | |
| 517 | # files with double quotes in the documentation rather than with sharp brackets. | |
| 518 | # The default value is: NO. | |
| 519 | ||
| 520 | FORCE_LOCAL_INCLUDES = NO | |
| 521 | ||
| 522 | # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the | |
| 523 | # documentation for inline members. | |
| 524 | # The default value is: YES. | |
| 525 | ||
| 526 | INLINE_INFO = YES | |
| 527 | ||
| 528 | # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the | |
| 529 | # (detailed) documentation of file and class members alphabetically by member | |
| 530 | # name. If set to NO the members will appear in declaration order. | |
| 531 | # The default value is: YES. | |
| 532 | ||
| 533 | SORT_MEMBER_DOCS = YES | |
| 534 | ||
| 535 | # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief | |
| 536 | # descriptions of file, namespace and class members alphabetically by member | |
| 537 | # name. If set to NO the members will appear in declaration order. | |
| 538 | # The default value is: NO. | |
| 539 | ||
| 540 | SORT_BRIEF_DOCS = NO | |
| 541 | ||
| 542 | # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the | |
| 543 | # (brief and detailed) documentation of class members so that constructors and | |
| 544 | # destructors are listed first. If set to NO the constructors will appear in the | |
| 545 | # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. | |
| 546 | # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief | |
| 547 | # member documentation. | |
| 548 | # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting | |
| 549 | # detailed member documentation. | |
| 550 | # The default value is: NO. | |
| 551 | ||
| 552 | SORT_MEMBERS_CTORS_1ST = NO | |
| 553 | ||
| 554 | # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy | |
| 555 | # of group names into alphabetical order. If set to NO the group names will | |
| 556 | # appear in their defined order. | |
| 557 | # The default value is: NO. | |
| 558 | ||
| 559 | SORT_GROUP_NAMES = NO | |
| 560 | ||
| 561 | # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by | |
| 562 | # fully-qualified names, including namespaces. If set to NO, the class list will | |
| 563 | # be sorted only by class name, not including the namespace part. | |
| 564 | # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. | |
| 565 | # Note: This option applies only to the class list, not to the alphabetical | |
| 566 | # list. | |
| 567 | # The default value is: NO. | |
| 568 | ||
| 569 | SORT_BY_SCOPE_NAME = YES | |
| 570 | ||
| 571 | # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper | |
| 572 | # type resolution of all parameters of a function it will reject a match between | |
| 573 | # the prototype and the implementation of a member function even if there is | |
| 574 | # only one candidate or it is obvious which candidate to choose by doing a | |
| 575 | # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still | |
| 576 | # accept a match between prototype and implementation in such cases. | |
| 577 | # The default value is: NO. | |
| 578 | ||
| 579 | STRICT_PROTO_MATCHING = NO | |
| 580 | ||
| 581 | # The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the | |
| 582 | # todo list. This list is created by putting \todo commands in the | |
| 583 | # documentation. | |
| 584 | # The default value is: YES. | |
| 585 | ||
| 586 | GENERATE_TODOLIST = YES | |
| 587 | ||
| 588 | # The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the | |
| 589 | # test list. This list is created by putting \test commands in the | |
| 590 | # documentation. | |
| 591 | # The default value is: YES. | |
| 592 | ||
| 593 | GENERATE_TESTLIST = NO | |
| 594 | ||
| 595 | # The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug | |
| 596 | # list. This list is created by putting \bug commands in the documentation. | |
| 597 | # The default value is: YES. | |
| 598 | ||
| 599 | GENERATE_BUGLIST = NO | |
| 600 | ||
| 601 | # The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) | |
| 602 | # the deprecated list. This list is created by putting \deprecated commands in | |
| 603 | # the documentation. | |
| 604 | # The default value is: YES. | |
| 605 | ||
| 606 | GENERATE_DEPRECATEDLIST= YES | |
| 607 | ||
| 608 | # The ENABLED_SECTIONS tag can be used to enable conditional documentation | |
| 609 | # sections, marked by \if <section_label> ... \endif and \cond <section_label> | |
| 610 | # ... \endcond blocks. | |
| 611 | ||
| 612 | ENABLED_SECTIONS = | |
| 613 | ||
| 614 | # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the | |
| 615 | # initial value of a variable or macro / define can have for it to appear in the | |
| 616 | # documentation. If the initializer consists of more lines than specified here | |
| 617 | # it will be hidden. Use a value of 0 to hide initializers completely. The | |
| 618 | # appearance of the value of individual variables and macros / defines can be | |
| 619 | # controlled using \showinitializer or \hideinitializer command in the | |
| 620 | # documentation regardless of this setting. | |
| 621 | # Minimum value: 0, maximum value: 10000, default value: 30. | |
| 622 | ||
| 623 | MAX_INITIALIZER_LINES = 30 | |
| 624 | ||
| 625 | # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at | |
| 626 | # the bottom of the documentation of classes and structs. If set to YES the list | |
| 627 | # will mention the files that were used to generate the documentation. | |
| 628 | # The default value is: YES. | |
| 629 | ||
| 630 | SHOW_USED_FILES = YES | |
| 631 | ||
| 632 | # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This | |
| 633 | # will remove the Files entry from the Quick Index and from the Folder Tree View | |
| 634 | # (if specified). | |
| 635 | # The default value is: YES. | |
| 636 | ||
| 637 | SHOW_FILES = YES | |
| 638 | ||
| 639 | # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces | |
| 640 | # page. This will remove the Namespaces entry from the Quick Index and from the | |
| 641 | # Folder Tree View (if specified). | |
| 642 | # The default value is: YES. | |
| 643 | ||
| 644 | SHOW_NAMESPACES = YES | |
| 645 | ||
| 646 | # The FILE_VERSION_FILTER tag can be used to specify a program or script that | |
| 647 | # doxygen should invoke to get the current version for each file (typically from | |
| 648 | # the version control system). Doxygen will invoke the program by executing (via | |
| 649 | # popen()) the command command input-file, where command is the value of the | |
| 650 | # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided | |
| 651 | # by doxygen. Whatever the program writes to standard output is used as the file | |
| 652 | # version. For an example see the documentation. | |
| 653 | ||
| 654 | FILE_VERSION_FILTER = | |
| 655 | ||
| 656 | # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed | |
| 657 | # by doxygen. The layout file controls the global structure of the generated | |
| 658 | # output files in an output format independent way. To create the layout file | |
| 659 | # that represents doxygen's defaults, run doxygen with the -l option. You can | |
| 660 | # optionally specify a file name after the option, if omitted DoxygenLayout.xml | |
| 661 | # will be used as the name of the layout file. | |
| 662 | # | |
| 663 | # Note that if you run doxygen from a directory containing a file called | |
| 664 | # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE | |
| 665 | # tag is left empty. | |
| 666 | ||
| 667 | LAYOUT_FILE = | |
| 668 | ||
| 669 | # The CITE_BIB_FILES tag can be used to specify one or more bib files containing | |
| 670 | # the reference definitions. This must be a list of .bib files. The .bib | |
| 671 | # extension is automatically appended if omitted. This requires the bibtex tool | |
| 672 | # to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. | |
| 673 | # For LaTeX the style of the bibliography can be controlled using | |
| 674 | # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the | |
| 675 | # search path. Do not use file names with spaces, bibtex cannot handle them. See | |
| 676 | # also \cite for info how to create references. | |
| 677 | ||
| 678 | CITE_BIB_FILES = | |
| 679 | ||
| 680 | #--------------------------------------------------------------------------- | |
| 681 | # Configuration options related to warning and progress messages | |
| 682 | #--------------------------------------------------------------------------- | |
| 683 | ||
| 684 | # The QUIET tag can be used to turn on/off the messages that are generated to | |
| 685 | # standard output by doxygen. If QUIET is set to YES this implies that the | |
| 686 | # messages are off. | |
| 687 | # The default value is: NO. | |
| 688 | ||
| 689 | QUIET = NO | |
| 690 | ||
| 691 | # The WARNINGS tag can be used to turn on/off the warning messages that are | |
| 692 | # generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES | |
| 693 | # this implies that the warnings are on. | |
| 694 | # | |
| 695 | # Tip: Turn warnings on while writing the documentation. | |
| 696 | # The default value is: YES. | |
| 697 | ||
| 698 | WARNINGS = YES | |
| 699 | ||
| 700 | # If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate | |
| 701 | # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag | |
| 702 | # will automatically be disabled. | |
| 703 | # The default value is: YES. | |
| 704 | ||
| 705 | WARN_IF_UNDOCUMENTED = YES | |
| 706 | ||
| 707 | # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for | |
| 708 | # potential errors in the documentation, such as not documenting some parameters | |
| 709 | # in a documented function, or documenting parameters that don't exist or using | |
| 710 | # markup commands wrongly. | |
| 711 | # The default value is: YES. | |
| 712 | ||
| 713 | WARN_IF_DOC_ERROR = YES | |
| 714 | ||
| 715 | # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that | |
| 716 | # are documented, but have no documentation for their parameters or return | |
| 717 | # value. If set to NO doxygen will only warn about wrong or incomplete parameter | |
| 718 | # documentation, but not about the absence of documentation. | |
| 719 | # The default value is: NO. | |
| 720 | ||
| 721 | WARN_NO_PARAMDOC = NO | |
| 722 | ||
| 723 | # The WARN_FORMAT tag determines the format of the warning messages that doxygen | |
| 724 | # can produce. The string should contain the $file, $line, and $text tags, which | |
| 725 | # will be replaced by the file and line number from which the warning originated | |
| 726 | # and the warning text. Optionally the format may contain $version, which will | |
| 727 | # be replaced by the version of the file (if it could be obtained via | |
| 728 | # FILE_VERSION_FILTER) | |
| 729 | # The default value is: $file:$line: $text. | |
| 730 | ||
| 731 | WARN_FORMAT = "$file:$line: $text" | |
| 732 | ||
| 733 | # The WARN_LOGFILE tag can be used to specify a file to which warning and error | |
| 734 | # messages should be written. If left blank the output is written to standard | |
| 735 | # error (stderr). | |
| 736 | ||
| 737 | WARN_LOGFILE = %WARNING_LOG_PATH% | |
| 738 | ||
| 739 | #--------------------------------------------------------------------------- | |
| 740 | # Configuration options related to the input files | |
| 741 | #--------------------------------------------------------------------------- | |
| 742 | ||
| 743 | # The INPUT tag is used to specify the files and/or directories that contain | |
| 744 | # documented source files. You may enter file names like myfile.cpp or | |
| 745 | # directories like /usr/src/myproject. Separate the files or directories with | |
| 746 | # spaces. | |
| 747 | # Note: If this tag is empty the current directory is searched. | |
| 748 | ||
| 749 | INPUT = ../include \ | |
| 750 | ../src/lib_json \ | |
| 751 | . | |
| 752 | ||
| 753 | # This tag can be used to specify the character encoding of the source files | |
| 754 | # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses | |
| 755 | # libiconv (or the iconv built into libc) for the transcoding. See the libiconv | |
| 756 | # documentation (see: http://www.gnu.org/software/libiconv) for the list of | |
| 757 | # possible encodings. | |
| 758 | # The default value is: UTF-8. | |
| 759 | ||
| 760 | INPUT_ENCODING = UTF-8 | |
| 761 | ||
| 762 | # If the value of the INPUT tag contains directories, you can use the | |
| 763 | # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and | |
| 764 | # *.h) to filter out the source-files in the directories. If left blank the | |
| 765 | # following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, | |
| 766 | # *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, | |
| 767 | # *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, | |
| 768 | # *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, | |
| 769 | # *.qsf, *.as and *.js. | |
| 770 | ||
| 771 | FILE_PATTERNS = *.h \ | |
| 772 | *.cpp \ | |
| 773 | *.inl \ | |
| 774 | *.dox | |
| 775 | ||
| 776 | # The RECURSIVE tag can be used to specify whether or not subdirectories should | |
| 777 | # be searched for input files as well. | |
| 778 | # The default value is: NO. | |
| 779 | ||
| 780 | RECURSIVE = YES | |
| 781 | ||
| 782 | # The EXCLUDE tag can be used to specify files and/or directories that should be | |
| 783 | # excluded from the INPUT source files. This way you can easily exclude a | |
| 784 | # subdirectory from a directory tree whose root is specified with the INPUT tag. | |
| 785 | # | |
| 786 | # Note that relative paths are relative to the directory from which doxygen is | |
| 787 | # run. | |
| 788 | ||
| 789 | EXCLUDE = | |
| 790 | ||
| 791 | # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or | |
| 792 | # directories that are symbolic links (a Unix file system feature) are excluded | |
| 793 | # from the input. | |
| 794 | # The default value is: NO. | |
| 795 | ||
| 796 | EXCLUDE_SYMLINKS = NO | |
| 797 | ||
| 798 | # If the value of the INPUT tag contains directories, you can use the | |
| 799 | # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude | |
| 800 | # certain files from those directories. | |
| 801 | # | |
| 802 | # Note that the wildcards are matched against the file with absolute path, so to | |
| 803 | # exclude all test directories for example use the pattern */test/* | |
| 804 | ||
| 805 | EXCLUDE_PATTERNS = | |
| 806 | ||
| 807 | # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names | |
| 808 | # (namespaces, classes, functions, etc.) that should be excluded from the | |
| 809 | # output. The symbol name can be a fully qualified name, a word, or if the | |
| 810 | # wildcard * is used, a substring. Examples: ANamespace, AClass, | |
| 811 | # AClass::ANamespace, ANamespace::*Test | |
| 812 | # | |
| 813 | # Note that the wildcards are matched against the file with absolute path, so to | |
| 814 | # exclude all test directories use the pattern */test/* | |
| 815 | ||
| 816 | EXCLUDE_SYMBOLS = | |
| 817 | ||
| 818 | # The EXAMPLE_PATH tag can be used to specify one or more files or directories | |
| 819 | # that contain example code fragments that are included (see the \include | |
| 820 | # command). | |
| 821 | ||
| 822 | EXAMPLE_PATH = | |
| 823 | ||
| 824 | # If the value of the EXAMPLE_PATH tag contains directories, you can use the | |
| 825 | # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and | |
| 826 | # *.h) to filter out the source-files in the directories. If left blank all | |
| 827 | # files are included. | |
| 828 | ||
| 829 | EXAMPLE_PATTERNS = * | |
| 830 | ||
| 831 | # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be | |
| 832 | # searched for input files to be used with the \include or \dontinclude commands | |
| 833 | # irrespective of the value of the RECURSIVE tag. | |
| 834 | # The default value is: NO. | |
| 835 | ||
| 836 | EXAMPLE_RECURSIVE = NO | |
| 837 | ||
| 838 | # The IMAGE_PATH tag can be used to specify one or more files or directories | |
| 839 | # that contain images that are to be included in the documentation (see the | |
| 840 | # \image command). | |
| 841 | ||
| 842 | IMAGE_PATH = | |
| 843 | ||
| 844 | # The INPUT_FILTER tag can be used to specify a program that doxygen should | |
| 845 | # invoke to filter for each input file. Doxygen will invoke the filter program | |
| 846 | # by executing (via popen()) the command: | |
| 847 | # | |
| 848 | # <filter> <input-file> | |
| 849 | # | |
| 850 | # where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the | |
| 851 | # name of an input file. Doxygen will then use the output that the filter | |
| 852 | # program writes to standard output. If FILTER_PATTERNS is specified, this tag | |
| 853 | # will be ignored. | |
| 854 | # | |
| 855 | # Note that the filter must not add or remove lines; it is applied before the | |
| 856 | # code is scanned, but not when the output code is generated. If lines are added | |
| 857 | # or removed, the anchors will not be placed correctly. | |
| 858 | ||
| 859 | INPUT_FILTER = | |
| 860 | ||
| 861 | # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern | |
| 862 | # basis. Doxygen will compare the file name with each pattern and apply the | |
| 863 | # filter if there is a match. The filters are a list of the form: pattern=filter | |
| 864 | # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how | |
| 865 | # filters are used. If the FILTER_PATTERNS tag is empty or if none of the | |
| 866 | # patterns match the file name, INPUT_FILTER is applied. | |
| 867 | ||
| 868 | FILTER_PATTERNS = | |
| 869 | ||
| 870 | # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using | |
| 871 | # INPUT_FILTER ) will also be used to filter the input files that are used for | |
| 872 | # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). | |
| 873 | # The default value is: NO. | |
| 874 | ||
| 875 | FILTER_SOURCE_FILES = NO | |
| 876 | ||
| 877 | # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file | |
| 878 | # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and | |
| 879 | # it is also possible to disable source filtering for a specific pattern using | |
| 880 | # *.ext= (so without naming a filter). | |
| 881 | # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. | |
| 882 | ||
| 883 | FILTER_SOURCE_PATTERNS = | |
| 884 | ||
| 885 | # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that | |
| 886 | # is part of the input, its contents will be placed on the main page | |
| 887 | # (index.html). This can be useful if you have a project on for instance GitHub | |
| 888 | # and want to reuse the introduction page also for the doxygen output. | |
| 889 | ||
| 890 | USE_MDFILE_AS_MAINPAGE = | |
| 891 | ||
| 892 | #--------------------------------------------------------------------------- | |
| 893 | # Configuration options related to source browsing | |
| 894 | #--------------------------------------------------------------------------- | |
| 895 | ||
| 896 | # If the SOURCE_BROWSER tag is set to YES then a list of source files will be | |
| 897 | # generated. Documented entities will be cross-referenced with these sources. | |
| 898 | # | |
| 899 | # Note: To get rid of all source code in the generated output, make sure that | |
| 900 | # also VERBATIM_HEADERS is set to NO. | |
| 901 | # The default value is: NO. | |
| 902 | ||
| 903 | SOURCE_BROWSER = YES | |
| 904 | ||
| 905 | # Setting the INLINE_SOURCES tag to YES will include the body of functions, | |
| 906 | # classes and enums directly into the documentation. | |
| 907 | # The default value is: NO. | |
| 908 | ||
| 909 | INLINE_SOURCES = NO | |
| 910 | ||
| 911 | # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any | |
| 912 | # special comment blocks from generated source code fragments. Normal C, C++ and | |
| 913 | # Fortran comments will always remain visible. | |
| 914 | # The default value is: YES. | |
| 915 | ||
| 916 | STRIP_CODE_COMMENTS = YES | |
| 917 | ||
| 918 | # If the REFERENCED_BY_RELATION tag is set to YES then for each documented | |
| 919 | # function all documented functions referencing it will be listed. | |
| 920 | # The default value is: NO. | |
| 921 | ||
| 922 | REFERENCED_BY_RELATION = YES | |
| 923 | ||
| 924 | # If the REFERENCES_RELATION tag is set to YES then for each documented function | |
| 925 | # all documented entities called/used by that function will be listed. | |
| 926 | # The default value is: NO. | |
| 927 | ||
| 928 | REFERENCES_RELATION = YES | |
| 929 | ||
| 930 | # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set | |
| 931 | # to YES, then the hyperlinks from functions in REFERENCES_RELATION and | |
| 932 | # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will | |
| 933 | # link to the documentation. | |
| 934 | # The default value is: YES. | |
| 935 | ||
| 936 | REFERENCES_LINK_SOURCE = YES | |
| 937 | ||
| 938 | # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the | |
| 939 | # source code will show a tooltip with additional information such as prototype, | |
| 940 | # brief description and links to the definition and documentation. Since this | |
| 941 | # will make the HTML file larger and loading of large files a bit slower, you | |
| 942 | # can opt to disable this feature. | |
| 943 | # The default value is: YES. | |
| 944 | # This tag requires that the tag SOURCE_BROWSER is set to YES. | |
| 945 | ||
| 946 | SOURCE_TOOLTIPS = YES | |
| 947 | ||
| 948 | # If the USE_HTAGS tag is set to YES then the references to source code will | |
| 949 | # point to the HTML generated by the htags(1) tool instead of doxygen built-in | |
| 950 | # source browser. The htags tool is part of GNU's global source tagging system | |
| 951 | # (see http://www.gnu.org/software/global/global.html). You will need version | |
| 952 | # 4.8.6 or higher. | |
| 953 | # | |
| 954 | # To use it do the following: | |
| 955 | # - Install the latest version of global | |
| 956 | # - Enable SOURCE_BROWSER and USE_HTAGS in the config file | |
| 957 | # - Make sure the INPUT points to the root of the source tree | |
| 958 | # - Run doxygen as normal | |
| 959 | # | |
| 960 | # Doxygen will invoke htags (and that will in turn invoke gtags), so these | |
| 961 | # tools must be available from the command line (i.e. in the search path). | |
| 962 | # | |
| 963 | # The result: instead of the source browser generated by doxygen, the links to | |
| 964 | # source code will now point to the output of htags. | |
| 965 | # The default value is: NO. | |
| 966 | # This tag requires that the tag SOURCE_BROWSER is set to YES. | |
| 967 | ||
| 968 | USE_HTAGS = NO | |
| 969 | ||
| 970 | # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a | |
| 971 | # verbatim copy of the header file for each class for which an include is | |
| 972 | # specified. Set to NO to disable this. | |
| 973 | # See also: Section \class. | |
| 974 | # The default value is: YES. | |
| 975 | ||
| 976 | VERBATIM_HEADERS = YES | |
| 977 | ||
| 978 | #--------------------------------------------------------------------------- | |
| 979 | # Configuration options related to the alphabetical class index | |
| 980 | #--------------------------------------------------------------------------- | |
| 981 | ||
| 982 | # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all | |
| 983 | # compounds will be generated. Enable this if the project contains a lot of | |
| 984 | # classes, structs, unions or interfaces. | |
| 985 | # The default value is: YES. | |
| 986 | ||
| 987 | ALPHABETICAL_INDEX = NO | |
| 988 | ||
| 989 | # The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in | |
| 990 | # which the alphabetical index list will be split. | |
| 991 | # Minimum value: 1, maximum value: 20, default value: 5. | |
| 992 | # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. | |
| 993 | ||
| 994 | COLS_IN_ALPHA_INDEX = 5 | |
| 995 | ||
| 996 | # In case all classes in a project start with a common prefix, all classes will | |
| 997 | # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag | |
| 998 | # can be used to specify a prefix (or a list of prefixes) that should be ignored | |
| 999 | # while generating the index headers. | |
| 1000 | # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. | |
| 1001 | ||
| 1002 | IGNORE_PREFIX = | |
| 1003 | ||
| 1004 | #--------------------------------------------------------------------------- | |
| 1005 | # Configuration options related to the HTML output | |
| 1006 | #--------------------------------------------------------------------------- | |
| 1007 | ||
| 1008 | # If the GENERATE_HTML tag is set to YES doxygen will generate HTML output | |
| 1009 | # The default value is: YES. | |
| 1010 | ||
| 1011 | GENERATE_HTML = YES | |
| 1012 | ||
| 1013 | # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a | |
| 1014 | # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of | |
| 1015 | # it. | |
| 1016 | # The default directory is: html. | |
| 1017 | # This tag requires that the tag GENERATE_HTML is set to YES. | |
| 1018 | ||
| 1019 | HTML_OUTPUT = %HTML_OUTPUT% | |
| 1020 | ||
| 1021 | # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each | |
| 1022 | # generated HTML page (for example: .htm, .php, .asp). | |
| 1023 | # The default value is: .html. | |
| 1024 | # This tag requires that the tag GENERATE_HTML is set to YES. | |
| 1025 | ||
| 1026 | HTML_FILE_EXTENSION = .html | |
| 1027 | ||
| 1028 | # The HTML_HEADER tag can be used to specify a user-defined HTML header file for | |
| 1029 | # each generated HTML page. If the tag is left blank doxygen will generate a | |
| 1030 | # standard header. | |
| 1031 | # | |
| 1032 | # To get valid HTML the header file that includes any scripts and style sheets | |
| 1033 | # that doxygen needs, which is dependent on the configuration options used (e.g. | |
| 1034 | # the setting GENERATE_TREEVIEW). It is highly recommended to start with a | |
| 1035 | # default header using | |
| 1036 | # doxygen -w html new_header.html new_footer.html new_stylesheet.css | |
| 1037 | # YourConfigFile | |
| 1038 | # and then modify the file new_header.html. See also section "Doxygen usage" | |
| 1039 | # for information on how to generate the default header that doxygen normally | |
| 1040 | # uses. | |
| 1041 | # Note: The header is subject to change so you typically have to regenerate the | |
| 1042 | # default header when upgrading to a newer version of doxygen. For a description | |
| 1043 | # of the possible markers and block names see the documentation. | |
| 1044 | # This tag requires that the tag GENERATE_HTML is set to YES. | |
| 1045 | ||
| 1046 | HTML_HEADER = header.html | |
| 1047 | ||
| 1048 | # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each | |
| 1049 | # generated HTML page. If the tag is left blank doxygen will generate a standard | |
| 1050 | # footer. See HTML_HEADER for more information on how to generate a default | |
| 1051 | # footer and what special commands can be used inside the footer. See also | |
| 1052 | # section "Doxygen usage" for information on how to generate the default footer | |
| 1053 | # that doxygen normally uses. | |
| 1054 | # This tag requires that the tag GENERATE_HTML is set to YES. | |
| 1055 | ||
| 1056 | HTML_FOOTER = footer.html | |
| 1057 | ||
| 1058 | # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style | |
| 1059 | # sheet that is used by each HTML page. It can be used to fine-tune the look of | |
| 1060 | # the HTML output. If left blank doxygen will generate a default style sheet. | |
| 1061 | # See also section "Doxygen usage" for information on how to generate the style | |
| 1062 | # sheet that doxygen normally uses. | |
| 1063 | # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as | |
| 1064 | # it is more robust and this tag (HTML_STYLESHEET) will in the future become | |
| 1065 | # obsolete. | |
| 1066 | # This tag requires that the tag GENERATE_HTML is set to YES. | |
| 1067 | ||
| 1068 | HTML_STYLESHEET = | |
| 1069 | ||
| 1070 | # The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- | |
| 1071 | # defined cascading style sheet that is included after the standard style sheets | |
| 1072 | # created by doxygen. Using this option one can overrule certain style aspects. | |
| 1073 | # This is preferred over using HTML_STYLESHEET since it does not replace the | |
| 1074 | # standard style sheet and is therefor more robust against future updates. | |
| 1075 | # Doxygen will copy the style sheet file to the output directory. For an example | |
| 1076 | # see the documentation. | |
| 1077 | # This tag requires that the tag GENERATE_HTML is set to YES. | |
| 1078 | ||
| 1079 | HTML_EXTRA_STYLESHEET = | |
| 1080 | ||
| 1081 | # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or | |
| 1082 | # other source files which should be copied to the HTML output directory. Note | |
| 1083 | # that these files will be copied to the base HTML output directory. Use the | |
| 1084 | # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these | |
| 1085 | # files. In the HTML_STYLESHEET file, use the file name only. Also note that the | |
| 1086 | # files will be copied as-is; there are no commands or markers available. | |
| 1087 | # This tag requires that the tag GENERATE_HTML is set to YES. | |
| 1088 | ||
| 1089 | HTML_EXTRA_FILES = | |
| 1090 | ||
| 1091 | # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen | |
| 1092 | # will adjust the colors in the stylesheet and background images according to | |
| 1093 | # this color. Hue is specified as an angle on a colorwheel, see | |
| 1094 | # http://en.wikipedia.org/wiki/Hue for more information. For instance the value | |
| 1095 | # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 | |
| 1096 | # purple, and 360 is red again. | |
| 1097 | # Minimum value: 0, maximum value: 359, default value: 220. | |
| 1098 | # This tag requires that the tag GENERATE_HTML is set to YES. | |
| 1099 | ||
| 1100 | HTML_COLORSTYLE_HUE = 220 | |
| 1101 | ||
| 1102 | # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors | |
| 1103 | # in the HTML output. For a value of 0 the output will use grayscales only. A | |
| 1104 | # value of 255 will produce the most vivid colors. | |
| 1105 | # Minimum value: 0, maximum value: 255, default value: 100. | |
| 1106 | # This tag requires that the tag GENERATE_HTML is set to YES. | |
| 1107 | ||
| 1108 | HTML_COLORSTYLE_SAT = 100 | |
| 1109 | ||
| 1110 | # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the | |
| 1111 | # luminance component of the colors in the HTML output. Values below 100 | |
| 1112 | # gradually make the output lighter, whereas values above 100 make the output | |
| 1113 | # darker. The value divided by 100 is the actual gamma applied, so 80 represents | |
| 1114 | # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not | |
| 1115 | # change the gamma. | |
| 1116 | # Minimum value: 40, maximum value: 240, default value: 80. | |
| 1117 | # This tag requires that the tag GENERATE_HTML is set to YES. | |
| 1118 | ||
| 1119 | HTML_COLORSTYLE_GAMMA = 80 | |
| 1120 | ||
| 1121 | # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML | |
| 1122 | # page will contain the date and time when the page was generated. Setting this | |
| 1123 | # to NO can help when comparing the output of multiple runs. | |
| 1124 | # The default value is: YES. | |
| 1125 | # This tag requires that the tag GENERATE_HTML is set to YES. | |
| 1126 | ||
| 1127 | HTML_TIMESTAMP = YES | |
| 1128 | ||
| 1129 | # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML | |
| 1130 | # documentation will contain sections that can be hidden and shown after the | |
| 1131 | # page has loaded. | |
| 1132 | # The default value is: NO. | |
| 1133 | # This tag requires that the tag GENERATE_HTML is set to YES. | |
| 1134 | ||
| 1135 | HTML_DYNAMIC_SECTIONS = YES | |
| 1136 | ||
| 1137 | # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries | |
| 1138 | # shown in the various tree structured indices initially; the user can expand | |
| 1139 | # and collapse entries dynamically later on. Doxygen will expand the tree to | |
| 1140 | # such a level that at most the specified number of entries are visible (unless | |
| 1141 | # a fully collapsed tree already exceeds this amount). So setting the number of | |
| 1142 | # entries 1 will produce a full collapsed tree by default. 0 is a special value | |
| 1143 | # representing an infinite number of entries and will result in a full expanded | |
| 1144 | # tree by default. | |
| 1145 | # Minimum value: 0, maximum value: 9999, default value: 100. | |
| 1146 | # This tag requires that the tag GENERATE_HTML is set to YES. | |
| 1147 | ||
| 1148 | HTML_INDEX_NUM_ENTRIES = 100 | |
| 1149 | ||
| 1150 | # If the GENERATE_DOCSET tag is set to YES, additional index files will be | |
| 1151 | # generated that can be used as input for Apple's Xcode 3 integrated development | |
| 1152 | # environment (see: http://developer.apple.com/tools/xcode/), introduced with | |
| 1153 | # OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a | |
| 1154 | # Makefile in the HTML output directory. Running make will produce the docset in | |
| 1155 | # that directory and running make install will install the docset in | |
| 1156 | # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at | |
| 1157 | # startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html | |
| 1158 | # for more information. | |
| 1159 | # The default value is: NO. | |
| 1160 | # This tag requires that the tag GENERATE_HTML is set to YES. | |
| 1161 | ||
| 1162 | GENERATE_DOCSET = NO | |
| 1163 | ||
| 1164 | # This tag determines the name of the docset feed. A documentation feed provides | |
| 1165 | # an umbrella under which multiple documentation sets from a single provider | |
| 1166 | # (such as a company or product suite) can be grouped. | |
| 1167 | # The default value is: Doxygen generated docs. | |
| 1168 | # This tag requires that the tag GENERATE_DOCSET is set to YES. | |
| 1169 | ||
| 1170 | DOCSET_FEEDNAME = "Doxygen generated docs" | |
| 1171 | ||
| 1172 | # This tag specifies a string that should uniquely identify the documentation | |
| 1173 | # set bundle. This should be a reverse domain-name style string, e.g. | |
| 1174 | # com.mycompany.MyDocSet. Doxygen will append .docset to the name. | |
| 1175 | # The default value is: org.doxygen.Project. | |
| 1176 | # This tag requires that the tag GENERATE_DOCSET is set to YES. | |
| 1177 | ||
| 1178 | DOCSET_BUNDLE_ID = org.doxygen.Project | |
| 1179 | ||
| 1180 | # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify | |
| 1181 | # the documentation publisher. This should be a reverse domain-name style | |
| 1182 | # string, e.g. com.mycompany.MyDocSet.documentation. | |
| 1183 | # The default value is: org.doxygen.Publisher. | |
| 1184 | # This tag requires that the tag GENERATE_DOCSET is set to YES. | |
| 1185 | ||
| 1186 | DOCSET_PUBLISHER_ID = org.doxygen.Publisher | |
| 1187 | ||
| 1188 | # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. | |
| 1189 | # The default value is: Publisher. | |
| 1190 | # This tag requires that the tag GENERATE_DOCSET is set to YES. | |
| 1191 | ||
| 1192 | DOCSET_PUBLISHER_NAME = Publisher | |
| 1193 | ||
| 1194 | # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three | |
| 1195 | # additional HTML index files: index.hhp, index.hhc, and index.hhk. The | |
| 1196 | # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop | |
| 1197 | # (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on | |
| 1198 | # Windows. | |
| 1199 | # | |
| 1200 | # The HTML Help Workshop contains a compiler that can convert all HTML output | |
| 1201 | # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML | |
| 1202 | # files are now used as the Windows 98 help format, and will replace the old | |
| 1203 | # Windows help format (.hlp) on all Windows platforms in the future. Compressed | |
| 1204 | # HTML files also contain an index, a table of contents, and you can search for | |
| 1205 | # words in the documentation. The HTML workshop also contains a viewer for | |
| 1206 | # compressed HTML files. | |
| 1207 | # The default value is: NO. | |
| 1208 | # This tag requires that the tag GENERATE_HTML is set to YES. | |
| 1209 | ||
| 1210 | GENERATE_HTMLHELP = %HTML_HELP% | |
| 1211 | ||
| 1212 | # The CHM_FILE tag can be used to specify the file name of the resulting .chm | |
| 1213 | # file. You can add a path in front of the file if the result should not be | |
| 1214 | # written to the html output directory. | |
| 1215 | # This tag requires that the tag GENERATE_HTMLHELP is set to YES. | |
| 1216 | ||
| 1217 | CHM_FILE = jsoncpp-%JSONCPP_VERSION%.chm | |
| 1218 | ||
| 1219 | # The HHC_LOCATION tag can be used to specify the location (absolute path | |
| 1220 | # including file name) of the HTML help compiler ( hhc.exe). If non-empty | |
| 1221 | # doxygen will try to run the HTML help compiler on the generated index.hhp. | |
| 1222 | # The file has to be specified with full path. | |
| 1223 | # This tag requires that the tag GENERATE_HTMLHELP is set to YES. | |
| 1224 | ||
| 1225 | HHC_LOCATION = "c:\Program Files\HTML Help Workshop\hhc.exe" | |
| 1226 | ||
| 1227 | # The GENERATE_CHI flag controls if a separate .chi index file is generated ( | |
| 1228 | # YES) or that it should be included in the master .chm file ( NO). | |
| 1229 | # The default value is: NO. | |
| 1230 | # This tag requires that the tag GENERATE_HTMLHELP is set to YES. | |
| 1231 | ||
| 1232 | GENERATE_CHI = YES | |
| 1233 | ||
| 1234 | # The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) | |
| 1235 | # and project file content. | |
| 1236 | # This tag requires that the tag GENERATE_HTMLHELP is set to YES. | |
| 1237 | ||
| 1238 | CHM_INDEX_ENCODING = | |
| 1239 | ||
| 1240 | # The BINARY_TOC flag controls whether a binary table of contents is generated ( | |
| 1241 | # YES) or a normal table of contents ( NO) in the .chm file. | |
| 1242 | # The default value is: NO. | |
| 1243 | # This tag requires that the tag GENERATE_HTMLHELP is set to YES. | |
| 1244 | ||
| 1245 | BINARY_TOC = YES | |
| 1246 | ||
| 1247 | # The TOC_EXPAND flag can be set to YES to add extra items for group members to | |
| 1248 | # the table of contents of the HTML help documentation and to the tree view. | |
| 1249 | # The default value is: NO. | |
| 1250 | # This tag requires that the tag GENERATE_HTMLHELP is set to YES. | |
| 1251 | ||
| 1252 | TOC_EXPAND = YES | |
| 1253 | ||
| 1254 | # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and | |
| 1255 | # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that | |
| 1256 | # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help | |
| 1257 | # (.qch) of the generated HTML documentation. | |
| 1258 | # The default value is: NO. | |
| 1259 | # This tag requires that the tag GENERATE_HTML is set to YES. | |
| 1260 | ||
| 1261 | GENERATE_QHP = NO | |
| 1262 | ||
| 1263 | # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify | |
| 1264 | # the file name of the resulting .qch file. The path specified is relative to | |
| 1265 | # the HTML output folder. | |
| 1266 | # This tag requires that the tag GENERATE_QHP is set to YES. | |
| 1267 | ||
| 1268 | QCH_FILE = | |
| 1269 | ||
| 1270 | # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help | |
| 1271 | # Project output. For more information please see Qt Help Project / Namespace | |
| 1272 | # (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). | |
| 1273 | # The default value is: org.doxygen.Project. | |
| 1274 | # This tag requires that the tag GENERATE_QHP is set to YES. | |
| 1275 | ||
| 1276 | QHP_NAMESPACE = | |
| 1277 | ||
| 1278 | # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt | |
| 1279 | # Help Project output. For more information please see Qt Help Project / Virtual | |
| 1280 | # Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- | |
| 1281 | # folders). | |
| 1282 | # The default value is: doc. | |
| 1283 | # This tag requires that the tag GENERATE_QHP is set to YES. | |
| 1284 | ||
| 1285 | QHP_VIRTUAL_FOLDER = doc | |
| 1286 | ||
| 1287 | # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom | |
| 1288 | # filter to add. For more information please see Qt Help Project / Custom | |
| 1289 | # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- | |
| 1290 | # filters). | |
| 1291 | # This tag requires that the tag GENERATE_QHP is set to YES. | |
| 1292 | ||
| 1293 | QHP_CUST_FILTER_NAME = | |
| 1294 | ||
| 1295 | # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the | |
| 1296 | # custom filter to add. For more information please see Qt Help Project / Custom | |
| 1297 | # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- | |
| 1298 | # filters). | |
| 1299 | # This tag requires that the tag GENERATE_QHP is set to YES. | |
| 1300 | ||
| 1301 | QHP_CUST_FILTER_ATTRS = | |
| 1302 | ||
| 1303 | # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this | |
| 1304 | # project's filter section matches. Qt Help Project / Filter Attributes (see: | |
| 1305 | # http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). | |
| 1306 | # This tag requires that the tag GENERATE_QHP is set to YES. | |
| 1307 | ||
| 1308 | QHP_SECT_FILTER_ATTRS = | |
| 1309 | ||
| 1310 | # The QHG_LOCATION tag can be used to specify the location of Qt's | |
| 1311 | # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the | |
| 1312 | # generated .qhp file. | |
| 1313 | # This tag requires that the tag GENERATE_QHP is set to YES. | |
| 1314 | ||
| 1315 | QHG_LOCATION = | |
| 1316 | ||
| 1317 | # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be | |
| 1318 | # generated, together with the HTML files, they form an Eclipse help plugin. To | |
| 1319 | # install this plugin and make it available under the help contents menu in | |
| 1320 | # Eclipse, the contents of the directory containing the HTML and XML files needs | |
| 1321 | # to be copied into the plugins directory of eclipse. The name of the directory | |
| 1322 | # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. | |
| 1323 | # After copying Eclipse needs to be restarted before the help appears. | |
| 1324 | # The default value is: NO. | |
| 1325 | # This tag requires that the tag GENERATE_HTML is set to YES. | |
| 1326 | ||
| 1327 | GENERATE_ECLIPSEHELP = NO | |
| 1328 | ||
| 1329 | # A unique identifier for the Eclipse help plugin. When installing the plugin | |
| 1330 | # the directory name containing the HTML and XML files should also have this | |
| 1331 | # name. Each documentation set should have its own identifier. | |
| 1332 | # The default value is: org.doxygen.Project. | |
| 1333 | # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. | |
| 1334 | ||
| 1335 | ECLIPSE_DOC_ID = org.doxygen.Project | |
| 1336 | ||
| 1337 | # If you want full control over the layout of the generated HTML pages it might | |
| 1338 | # be necessary to disable the index and replace it with your own. The | |
| 1339 | # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top | |
| 1340 | # of each HTML page. A value of NO enables the index and the value YES disables | |
| 1341 | # it. Since the tabs in the index contain the same information as the navigation | |
| 1342 | # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. | |
| 1343 | # The default value is: NO. | |
| 1344 | # This tag requires that the tag GENERATE_HTML is set to YES. | |
| 1345 | ||
| 1346 | DISABLE_INDEX = NO | |
| 1347 | ||
| 1348 | # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index | |
| 1349 | # structure should be generated to display hierarchical information. If the tag | |
| 1350 | # value is set to YES, a side panel will be generated containing a tree-like | |
| 1351 | # index structure (just like the one that is generated for HTML Help). For this | |
| 1352 | # to work a browser that supports JavaScript, DHTML, CSS and frames is required | |
| 1353 | # (i.e. any modern browser). Windows users are probably better off using the | |
| 1354 | # HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can | |
| 1355 | # further fine-tune the look of the index. As an example, the default style | |
| 1356 | # sheet generated by doxygen has an example that shows how to put an image at | |
| 1357 | # the root of the tree instead of the PROJECT_NAME. Since the tree basically has | |
| 1358 | # the same information as the tab index, you could consider setting | |
| 1359 | # DISABLE_INDEX to YES when enabling this option. | |
| 1360 | # The default value is: NO. | |
| 1361 | # This tag requires that the tag GENERATE_HTML is set to YES. | |
| 1362 | ||
| 1363 | GENERATE_TREEVIEW = NO | |
| 1364 | ||
| 1365 | # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that | |
| 1366 | # doxygen will group on one line in the generated HTML documentation. | |
| 1367 | # | |
| 1368 | # Note that a value of 0 will completely suppress the enum values from appearing | |
| 1369 | # in the overview section. | |
| 1370 | # Minimum value: 0, maximum value: 20, default value: 4. | |
| 1371 | # This tag requires that the tag GENERATE_HTML is set to YES. | |
| 1372 | ||
| 1373 | ENUM_VALUES_PER_LINE = 4 | |
| 1374 | ||
| 1375 | # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used | |
| 1376 | # to set the initial width (in pixels) of the frame in which the tree is shown. | |
| 1377 | # Minimum value: 0, maximum value: 1500, default value: 250. | |
| 1378 | # This tag requires that the tag GENERATE_HTML is set to YES. | |
| 1379 | ||
| 1380 | TREEVIEW_WIDTH = 250 | |
| 1381 | ||
| 1382 | # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to | |
| 1383 | # external symbols imported via tag files in a separate window. | |
| 1384 | # The default value is: NO. | |
| 1385 | # This tag requires that the tag GENERATE_HTML is set to YES. | |
| 1386 | ||
| 1387 | EXT_LINKS_IN_WINDOW = NO | |
| 1388 | ||
| 1389 | # Use this tag to change the font size of LaTeX formulas included as images in | |
| 1390 | # the HTML documentation. When you change the font size after a successful | |
| 1391 | # doxygen run you need to manually remove any form_*.png images from the HTML | |
| 1392 | # output directory to force them to be regenerated. | |
| 1393 | # Minimum value: 8, maximum value: 50, default value: 10. | |
| 1394 | # This tag requires that the tag GENERATE_HTML is set to YES. | |
| 1395 | ||
| 1396 | FORMULA_FONTSIZE = 10 | |
| 1397 | ||
| 1398 | # Use the FORMULA_TRANPARENT tag to determine whether or not the images | |
| 1399 | # generated for formulas are transparent PNGs. Transparent PNGs are not | |
| 1400 | # supported properly for IE 6.0, but are supported on all modern browsers. | |
| 1401 | # | |
| 1402 | # Note that when changing this option you need to delete any form_*.png files in | |
| 1403 | # the HTML output directory before the changes have effect. | |
| 1404 | # The default value is: YES. | |
| 1405 | # This tag requires that the tag GENERATE_HTML is set to YES. | |
| 1406 | ||
| 1407 | FORMULA_TRANSPARENT = YES | |
| 1408 | ||
| 1409 | # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see | |
| 1410 | # http://www.mathjax.org) which uses client side Javascript for the rendering | |
| 1411 | # instead of using prerendered bitmaps. Use this if you do not have LaTeX | |
| 1412 | # installed or if you want to formulas look prettier in the HTML output. When | |
| 1413 | # enabled you may also need to install MathJax separately and configure the path | |
| 1414 | # to it using the MATHJAX_RELPATH option. | |
| 1415 | # The default value is: NO. | |
| 1416 | # This tag requires that the tag GENERATE_HTML is set to YES. | |
| 1417 | ||
| 1418 | USE_MATHJAX = NO | |
| 1419 | ||
| 1420 | # When MathJax is enabled you can set the default output format to be used for | |
| 1421 | # the MathJax output. See the MathJax site (see: | |
| 1422 | # http://docs.mathjax.org/en/latest/output.html) for more details. | |
| 1423 | # Possible values are: HTML-CSS (which is slower, but has the best | |
| 1424 | # compatibility), NativeMML (i.e. MathML) and SVG. | |
| 1425 | # The default value is: HTML-CSS. | |
| 1426 | # This tag requires that the tag USE_MATHJAX is set to YES. | |
| 1427 | ||
| 1428 | MATHJAX_FORMAT = HTML-CSS | |
| 1429 | ||
| 1430 | # When MathJax is enabled you need to specify the location relative to the HTML | |
| 1431 | # output directory using the MATHJAX_RELPATH option. The destination directory | |
| 1432 | # should contain the MathJax.js script. For instance, if the mathjax directory | |
| 1433 | # is located at the same level as the HTML output directory, then | |
| 1434 | # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax | |
| 1435 | # Content Delivery Network so you can quickly see the result without installing | |
| 1436 | # MathJax. However, it is strongly recommended to install a local copy of | |
| 1437 | # MathJax from http://www.mathjax.org before deployment. | |
| 1438 | # The default value is: http://cdn.mathjax.org/mathjax/latest. | |
| 1439 | # This tag requires that the tag USE_MATHJAX is set to YES. | |
| 1440 | ||
| 1441 | MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest | |
| 1442 | ||
| 1443 | # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax | |
| 1444 | # extension names that should be enabled during MathJax rendering. For example | |
| 1445 | # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols | |
| 1446 | # This tag requires that the tag USE_MATHJAX is set to YES. | |
| 1447 | ||
| 1448 | MATHJAX_EXTENSIONS = | |
| 1449 | ||
| 1450 | # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces | |
| 1451 | # of code that will be used on startup of the MathJax code. See the MathJax site | |
| 1452 | # (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an | |
| 1453 | # example see the documentation. | |
| 1454 | # This tag requires that the tag USE_MATHJAX is set to YES. | |
| 1455 | ||
| 1456 | MATHJAX_CODEFILE = | |
| 1457 | ||
| 1458 | # When the SEARCHENGINE tag is enabled doxygen will generate a search box for | |
| 1459 | # the HTML output. The underlying search engine uses javascript and DHTML and | |
| 1460 | # should work on any modern browser. Note that when using HTML help | |
| 1461 | # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) | |
| 1462 | # there is already a search function so this one should typically be disabled. | |
| 1463 | # For large projects the javascript based search engine can be slow, then | |
| 1464 | # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to | |
| 1465 | # search using the keyboard; to jump to the search box use <access key> + S | |
| 1466 | # (what the <access key> is depends on the OS and browser, but it is typically | |
| 1467 | # <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down | |
| 1468 | # key> to jump into the search results window, the results can be navigated | |
| 1469 | # using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel | |
| 1470 | # the search. The filter options can be selected when the cursor is inside the | |
| 1471 | # search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys> | |
| 1472 | # to select a filter and <Enter> or <escape> to activate or cancel the filter | |
| 1473 | # option. | |
| 1474 | # The default value is: YES. | |
| 1475 | # This tag requires that the tag GENERATE_HTML is set to YES. | |
| 1476 | ||
| 1477 | SEARCHENGINE = NO | |
| 1478 | ||
| 1479 | # When the SERVER_BASED_SEARCH tag is enabled the search engine will be | |
| 1480 | # implemented using a web server instead of a web client using Javascript. There | |
| 1481 | # are two flavours of web server based searching depending on the | |
| 1482 | # EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for | |
| 1483 | # searching and an index file used by the script. When EXTERNAL_SEARCH is | |
| 1484 | # enabled the indexing and searching needs to be provided by external tools. See | |
| 1485 | # the section "External Indexing and Searching" for details. | |
| 1486 | # The default value is: NO. | |
| 1487 | # This tag requires that the tag SEARCHENGINE is set to YES. | |
| 1488 | ||
| 1489 | SERVER_BASED_SEARCH = NO | |
| 1490 | ||
| 1491 | # When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP | |
| 1492 | # script for searching. Instead the search results are written to an XML file | |
| 1493 | # which needs to be processed by an external indexer. Doxygen will invoke an | |
| 1494 | # external search engine pointed to by the SEARCHENGINE_URL option to obtain the | |
| 1495 | # search results. | |
| 1496 | # | |
| 1497 | # Doxygen ships with an example indexer ( doxyindexer) and search engine | |
| 1498 | # (doxysearch.cgi) which are based on the open source search engine library | |
| 1499 | # Xapian (see: http://xapian.org/). | |
| 1500 | # | |
| 1501 | # See the section "External Indexing and Searching" for details. | |
| 1502 | # The default value is: NO. | |
| 1503 | # This tag requires that the tag SEARCHENGINE is set to YES. | |
| 1504 | ||
| 1505 | EXTERNAL_SEARCH = NO | |
| 1506 | ||
| 1507 | # The SEARCHENGINE_URL should point to a search engine hosted by a web server | |
| 1508 | # which will return the search results when EXTERNAL_SEARCH is enabled. | |
| 1509 | # | |
| 1510 | # Doxygen ships with an example indexer ( doxyindexer) and search engine | |
| 1511 | # (doxysearch.cgi) which are based on the open source search engine library | |
| 1512 | # Xapian (see: http://xapian.org/). See the section "External Indexing and | |
| 1513 | # Searching" for details. | |
| 1514 | # This tag requires that the tag SEARCHENGINE is set to YES. | |
| 1515 | ||
| 1516 | SEARCHENGINE_URL = | |
| 1517 | ||
| 1518 | # When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed | |
| 1519 | # search data is written to a file for indexing by an external tool. With the | |
| 1520 | # SEARCHDATA_FILE tag the name of this file can be specified. | |
| 1521 | # The default file is: searchdata.xml. | |
| 1522 | # This tag requires that the tag SEARCHENGINE is set to YES. | |
| 1523 | ||
| 1524 | SEARCHDATA_FILE = searchdata.xml | |
| 1525 | ||
| 1526 | # When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the | |
| 1527 | # EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is | |
| 1528 | # useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple | |
| 1529 | # projects and redirect the results back to the right project. | |
| 1530 | # This tag requires that the tag SEARCHENGINE is set to YES. | |
| 1531 | ||
| 1532 | EXTERNAL_SEARCH_ID = | |
| 1533 | ||
| 1534 | # The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen | |
| 1535 | # projects other than the one defined by this configuration file, but that are | |
| 1536 | # all added to the same external search index. Each project needs to have a | |
| 1537 | # unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of | |
| 1538 | # to a relative location where the documentation can be found. The format is: | |
| 1539 | # EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ... | |
| 1540 | # This tag requires that the tag SEARCHENGINE is set to YES. | |
| 1541 | ||
| 1542 | EXTRA_SEARCH_MAPPINGS = | |
| 1543 | ||
| 1544 | #--------------------------------------------------------------------------- | |
| 1545 | # Configuration options related to the LaTeX output | |
| 1546 | #--------------------------------------------------------------------------- | |
| 1547 | ||
| 1548 | # If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output. | |
| 1549 | # The default value is: YES. | |
| 1550 | ||
| 1551 | GENERATE_LATEX = NO | |
| 1552 | ||
| 1553 | # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a | |
| 1554 | # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of | |
| 1555 | # it. | |
| 1556 | # The default directory is: latex. | |
| 1557 | # This tag requires that the tag GENERATE_LATEX is set to YES. | |
| 1558 | ||
| 1559 | LATEX_OUTPUT = latex | |
| 1560 | ||
| 1561 | # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be | |
| 1562 | # invoked. | |
| 1563 | # | |
| 1564 | # Note that when enabling USE_PDFLATEX this option is only used for generating | |
| 1565 | # bitmaps for formulas in the HTML output, but not in the Makefile that is | |
| 1566 | # written to the output directory. | |
| 1567 | # The default file is: latex. | |
| 1568 | # This tag requires that the tag GENERATE_LATEX is set to YES. | |
| 1569 | ||
| 1570 | LATEX_CMD_NAME = latex | |
| 1571 | ||
| 1572 | # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate | |
| 1573 | # index for LaTeX. | |
| 1574 | # The default file is: makeindex. | |
| 1575 | # This tag requires that the tag GENERATE_LATEX is set to YES. | |
| 1576 | ||
| 1577 | MAKEINDEX_CMD_NAME = makeindex | |
| 1578 | ||
| 1579 | # If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX | |
| 1580 | # documents. This may be useful for small projects and may help to save some | |
| 1581 | # trees in general. | |
| 1582 | # The default value is: NO. | |
| 1583 | # This tag requires that the tag GENERATE_LATEX is set to YES. | |
| 1584 | ||
| 1585 | COMPACT_LATEX = NO | |
| 1586 | ||
| 1587 | # The PAPER_TYPE tag can be used to set the paper type that is used by the | |
| 1588 | # printer. | |
| 1589 | # Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x | |
| 1590 | # 14 inches) and executive (7.25 x 10.5 inches). | |
| 1591 | # The default value is: a4. | |
| 1592 | # This tag requires that the tag GENERATE_LATEX is set to YES. | |
| 1593 | ||
| 1594 | PAPER_TYPE = a4wide | |
| 1595 | ||
| 1596 | # The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names | |
| 1597 | # that should be included in the LaTeX output. To get the times font for | |
| 1598 | # instance you can specify | |
| 1599 | # EXTRA_PACKAGES=times | |
| 1600 | # If left blank no extra packages will be included. | |
| 1601 | # This tag requires that the tag GENERATE_LATEX is set to YES. | |
| 1602 | ||
| 1603 | EXTRA_PACKAGES = | |
| 1604 | ||
| 1605 | # The LATEX_HEADER tag can be used to specify a personal LaTeX header for the | |
| 1606 | # generated LaTeX document. The header should contain everything until the first | |
| 1607 | # chapter. If it is left blank doxygen will generate a standard header. See | |
| 1608 | # section "Doxygen usage" for information on how to let doxygen write the | |
| 1609 | # default header to a separate file. | |
| 1610 | # | |
| 1611 | # Note: Only use a user-defined header if you know what you are doing! The | |
| 1612 | # following commands have a special meaning inside the header: $title, | |
| 1613 | # $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will | |
| 1614 | # replace them by respectively the title of the page, the current date and time, | |
| 1615 | # only the current date, the version number of doxygen, the project name (see | |
| 1616 | # PROJECT_NAME), or the project number (see PROJECT_NUMBER). | |
| 1617 | # This tag requires that the tag GENERATE_LATEX is set to YES. | |
| 1618 | ||
| 1619 | LATEX_HEADER = | |
| 1620 | ||
| 1621 | # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the | |
| 1622 | # generated LaTeX document. The footer should contain everything after the last | |
| 1623 | # chapter. If it is left blank doxygen will generate a standard footer. | |
| 1624 | # | |
| 1625 | # Note: Only use a user-defined footer if you know what you are doing! | |
| 1626 | # This tag requires that the tag GENERATE_LATEX is set to YES. | |
| 1627 | ||
| 1628 | LATEX_FOOTER = | |
| 1629 | ||
| 1630 | # The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or | |
| 1631 | # other source files which should be copied to the LATEX_OUTPUT output | |
| 1632 | # directory. Note that the files will be copied as-is; there are no commands or | |
| 1633 | # markers available. | |
| 1634 | # This tag requires that the tag GENERATE_LATEX is set to YES. | |
| 1635 | ||
| 1636 | LATEX_EXTRA_FILES = | |
| 1637 | ||
| 1638 | # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is | |
| 1639 | # prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will | |
| 1640 | # contain links (just like the HTML output) instead of page references. This | |
| 1641 | # makes the output suitable for online browsing using a PDF viewer. | |
| 1642 | # The default value is: YES. | |
| 1643 | # This tag requires that the tag GENERATE_LATEX is set to YES. | |
| 1644 | ||
| 1645 | PDF_HYPERLINKS = NO | |
| 1646 | ||
| 1647 | # If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate | |
| 1648 | # the PDF file directly from the LaTeX files. Set this option to YES to get a | |
| 1649 | # higher quality PDF documentation. | |
| 1650 | # The default value is: YES. | |
| 1651 | # This tag requires that the tag GENERATE_LATEX is set to YES. | |
| 1652 | ||
| 1653 | USE_PDFLATEX = NO | |
| 1654 | ||
| 1655 | # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode | |
| 1656 | # command to the generated LaTeX files. This will instruct LaTeX to keep running | |
| 1657 | # if errors occur, instead of asking the user for help. This option is also used | |
| 1658 | # when generating formulas in HTML. | |
| 1659 | # The default value is: NO. | |
| 1660 | # This tag requires that the tag GENERATE_LATEX is set to YES. | |
| 1661 | ||
| 1662 | LATEX_BATCHMODE = NO | |
| 1663 | ||
| 1664 | # If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the | |
| 1665 | # index chapters (such as File Index, Compound Index, etc.) in the output. | |
| 1666 | # The default value is: NO. | |
| 1667 | # This tag requires that the tag GENERATE_LATEX is set to YES. | |
| 1668 | ||
| 1669 | LATEX_HIDE_INDICES = NO | |
| 1670 | ||
| 1671 | # If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source | |
| 1672 | # code with syntax highlighting in the LaTeX output. | |
| 1673 | # | |
| 1674 | # Note that which sources are shown also depends on other settings such as | |
| 1675 | # SOURCE_BROWSER. | |
| 1676 | # The default value is: NO. | |
| 1677 | # This tag requires that the tag GENERATE_LATEX is set to YES. | |
| 1678 | ||
| 1679 | LATEX_SOURCE_CODE = NO | |
| 1680 | ||
| 1681 | # The LATEX_BIB_STYLE tag can be used to specify the style to use for the | |
| 1682 | # bibliography, e.g. plainnat, or ieeetr. See | |
| 1683 | # http://en.wikipedia.org/wiki/BibTeX and \cite for more info. | |
| 1684 | # The default value is: plain. | |
| 1685 | # This tag requires that the tag GENERATE_LATEX is set to YES. | |
| 1686 | ||
| 1687 | LATEX_BIB_STYLE = plain | |
| 1688 | ||
| 1689 | #--------------------------------------------------------------------------- | |
| 1690 | # Configuration options related to the RTF output | |
| 1691 | #--------------------------------------------------------------------------- | |
| 1692 | ||
| 1693 | # If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The | |
| 1694 | # RTF output is optimized for Word 97 and may not look too pretty with other RTF | |
| 1695 | # readers/editors. | |
| 1696 | # The default value is: NO. | |
| 1697 | ||
| 1698 | GENERATE_RTF = NO | |
| 1699 | ||
| 1700 | # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a | |
| 1701 | # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of | |
| 1702 | # it. | |
| 1703 | # The default directory is: rtf. | |
| 1704 | # This tag requires that the tag GENERATE_RTF is set to YES. | |
| 1705 | ||
| 1706 | RTF_OUTPUT = rtf | |
| 1707 | ||
| 1708 | # If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF | |
| 1709 | # documents. This may be useful for small projects and may help to save some | |
| 1710 | # trees in general. | |
| 1711 | # The default value is: NO. | |
| 1712 | # This tag requires that the tag GENERATE_RTF is set to YES. | |
| 1713 | ||
| 1714 | COMPACT_RTF = NO | |
| 1715 | ||
| 1716 | # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will | |
| 1717 | # contain hyperlink fields. The RTF file will contain links (just like the HTML | |
| 1718 | # output) instead of page references. This makes the output suitable for online | |
| 1719 | # browsing using Word or some other Word compatible readers that support those | |
| 1720 | # fields. | |
| 1721 | # | |
| 1722 | # Note: WordPad (write) and others do not support links. | |
| 1723 | # The default value is: NO. | |
| 1724 | # This tag requires that the tag GENERATE_RTF is set to YES. | |
| 1725 | ||
| 1726 | RTF_HYPERLINKS = NO | |
| 1727 | ||
| 1728 | # Load stylesheet definitions from file. Syntax is similar to doxygen's config | |
| 1729 | # file, i.e. a series of assignments. You only have to provide replacements, | |
| 1730 | # missing definitions are set to their default value. | |
| 1731 | # | |
| 1732 | # See also section "Doxygen usage" for information on how to generate the | |
| 1733 | # default style sheet that doxygen normally uses. | |
| 1734 | # This tag requires that the tag GENERATE_RTF is set to YES. | |
| 1735 | ||
| 1736 | RTF_STYLESHEET_FILE = | |
| 1737 | ||
| 1738 | # Set optional variables used in the generation of an RTF document. Syntax is | |
| 1739 | # similar to doxygen's config file. A template extensions file can be generated | |
| 1740 | # using doxygen -e rtf extensionFile. | |
| 1741 | # This tag requires that the tag GENERATE_RTF is set to YES. | |
| 1742 | ||
| 1743 | RTF_EXTENSIONS_FILE = | |
| 1744 | ||
| 1745 | #--------------------------------------------------------------------------- | |
| 1746 | # Configuration options related to the man page output | |
| 1747 | #--------------------------------------------------------------------------- | |
| 1748 | ||
| 1749 | # If the GENERATE_MAN tag is set to YES doxygen will generate man pages for | |
| 1750 | # classes and files. | |
| 1751 | # The default value is: NO. | |
| 1752 | ||
| 1753 | GENERATE_MAN = NO | |
| 1754 | ||
| 1755 | # The MAN_OUTPUT tag is used to specify where the man pages will be put. If a | |
| 1756 | # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of | |
| 1757 | # it. A directory man3 will be created inside the directory specified by | |
| 1758 | # MAN_OUTPUT. | |
| 1759 | # The default directory is: man. | |
| 1760 | # This tag requires that the tag GENERATE_MAN is set to YES. | |
| 1761 | ||
| 1762 | MAN_OUTPUT = man | |
| 1763 | ||
| 1764 | # The MAN_EXTENSION tag determines the extension that is added to the generated | |
| 1765 | # man pages. In case the manual section does not start with a number, the number | |
| 1766 | # 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is | |
| 1767 | # optional. | |
| 1768 | # The default value is: .3. | |
| 1769 | # This tag requires that the tag GENERATE_MAN is set to YES. | |
| 1770 | ||
| 1771 | MAN_EXTENSION = .3 | |
| 1772 | ||
| 1773 | # If the MAN_LINKS tag is set to YES and doxygen generates man output, then it | |
| 1774 | # will generate one additional man file for each entity documented in the real | |
| 1775 | # man page(s). These additional files only source the real man page, but without | |
| 1776 | # them the man command would be unable to find the correct page. | |
| 1777 | # The default value is: NO. | |
| 1778 | # This tag requires that the tag GENERATE_MAN is set to YES. | |
| 1779 | ||
| 1780 | MAN_LINKS = NO | |
| 1781 | ||
| 1782 | #--------------------------------------------------------------------------- | |
| 1783 | # Configuration options related to the XML output | |
| 1784 | #--------------------------------------------------------------------------- | |
| 1785 | ||
| 1786 | # If the GENERATE_XML tag is set to YES doxygen will generate an XML file that | |
| 1787 | # captures the structure of the code including all documentation. | |
| 1788 | # The default value is: NO. | |
| 1789 | ||
| 1790 | GENERATE_XML = NO | |
| 1791 | ||
| 1792 | # The XML_OUTPUT tag is used to specify where the XML pages will be put. If a | |
| 1793 | # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of | |
| 1794 | # it. | |
| 1795 | # The default directory is: xml. | |
| 1796 | # This tag requires that the tag GENERATE_XML is set to YES. | |
| 1797 | ||
| 1798 | XML_OUTPUT = xml | |
| 1799 | ||
| 1800 | # The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a | |
| 1801 | # validating XML parser to check the syntax of the XML files. | |
| 1802 | # This tag requires that the tag GENERATE_XML is set to YES. | |
| 1803 | ||
| 1804 | XML_SCHEMA = | |
| 1805 | ||
| 1806 | # The XML_DTD tag can be used to specify a XML DTD, which can be used by a | |
| 1807 | # validating XML parser to check the syntax of the XML files. | |
| 1808 | # This tag requires that the tag GENERATE_XML is set to YES. | |
| 1809 | ||
| 1810 | XML_DTD = | |
| 1811 | ||
| 1812 | # If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program | |
| 1813 | # listings (including syntax highlighting and cross-referencing information) to | |
| 1814 | # the XML output. Note that enabling this will significantly increase the size | |
| 1815 | # of the XML output. | |
| 1816 | # The default value is: YES. | |
| 1817 | # This tag requires that the tag GENERATE_XML is set to YES. | |
| 1818 | ||
| 1819 | XML_PROGRAMLISTING = YES | |
| 1820 | ||
| 1821 | #--------------------------------------------------------------------------- | |
| 1822 | # Configuration options related to the DOCBOOK output | |
| 1823 | #--------------------------------------------------------------------------- | |
| 1824 | ||
| 1825 | # If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files | |
| 1826 | # that can be used to generate PDF. | |
| 1827 | # The default value is: NO. | |
| 1828 | ||
| 1829 | GENERATE_DOCBOOK = NO | |
| 1830 | ||
| 1831 | # The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put. | |
| 1832 | # If a relative path is entered the value of OUTPUT_DIRECTORY will be put in | |
| 1833 | # front of it. | |
| 1834 | # The default directory is: docbook. | |
| 1835 | # This tag requires that the tag GENERATE_DOCBOOK is set to YES. | |
| 1836 | ||
| 1837 | DOCBOOK_OUTPUT = docbook | |
| 1838 | ||
| 1839 | #--------------------------------------------------------------------------- | |
| 1840 | # Configuration options for the AutoGen Definitions output | |
| 1841 | #--------------------------------------------------------------------------- | |
| 1842 | ||
| 1843 | # If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen | |
| 1844 | # Definitions (see http://autogen.sf.net) file that captures the structure of | |
| 1845 | # the code including all documentation. Note that this feature is still | |
| 1846 | # experimental and incomplete at the moment. | |
| 1847 | # The default value is: NO. | |
| 1848 | ||
| 1849 | GENERATE_AUTOGEN_DEF = NO | |
| 1850 | ||
| 1851 | #--------------------------------------------------------------------------- | |
| 1852 | # Configuration options related to the Perl module output | |
| 1853 | #--------------------------------------------------------------------------- | |
| 1854 | ||
| 1855 | # If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module | |
| 1856 | # file that captures the structure of the code including all documentation. | |
| 1857 | # | |
| 1858 | # Note that this feature is still experimental and incomplete at the moment. | |
| 1859 | # The default value is: NO. | |
| 1860 | ||
| 1861 | GENERATE_PERLMOD = NO | |
| 1862 | ||
| 1863 | # If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary | |
| 1864 | # Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI | |
| 1865 | # output from the Perl module output. | |
| 1866 | # The default value is: NO. | |
| 1867 | # This tag requires that the tag GENERATE_PERLMOD is set to YES. | |
| 1868 | ||
| 1869 | PERLMOD_LATEX = NO | |
| 1870 | ||
| 1871 | # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely | |
| 1872 | # formatted so it can be parsed by a human reader. This is useful if you want to | |
| 1873 | # understand what is going on. On the other hand, if this tag is set to NO the | |
| 1874 | # size of the Perl module output will be much smaller and Perl will parse it | |
| 1875 | # just the same. | |
| 1876 | # The default value is: YES. | |
| 1877 | # This tag requires that the tag GENERATE_PERLMOD is set to YES. | |
| 1878 | ||
| 1879 | PERLMOD_PRETTY = YES | |
| 1880 | ||
| 1881 | # The names of the make variables in the generated doxyrules.make file are | |
| 1882 | # prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful | |
| 1883 | # so different doxyrules.make files included by the same Makefile don't | |
| 1884 | # overwrite each other's variables. | |
| 1885 | # This tag requires that the tag GENERATE_PERLMOD is set to YES. | |
| 1886 | ||
| 1887 | PERLMOD_MAKEVAR_PREFIX = | |
| 1888 | ||
| 1889 | #--------------------------------------------------------------------------- | |
| 1890 | # Configuration options related to the preprocessor | |
| 1891 | #--------------------------------------------------------------------------- | |
| 1892 | ||
| 1893 | # If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all | |
| 1894 | # C-preprocessor directives found in the sources and include files. | |
| 1895 | # The default value is: YES. | |
| 1896 | ||
| 1897 | ENABLE_PREPROCESSING = YES | |
| 1898 | ||
| 1899 | # If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names | |
| 1900 | # in the source code. If set to NO only conditional compilation will be | |
| 1901 | # performed. Macro expansion can be done in a controlled way by setting | |
| 1902 | # EXPAND_ONLY_PREDEF to YES. | |
| 1903 | # The default value is: NO. | |
| 1904 | # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. | |
| 1905 | ||
| 1906 | MACRO_EXPANSION = YES | |
| 1907 | ||
| 1908 | # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then | |
| 1909 | # the macro expansion is limited to the macros specified with the PREDEFINED and | |
| 1910 | # EXPAND_AS_DEFINED tags. | |
| 1911 | # The default value is: NO. | |
| 1912 | # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. | |
| 1913 | ||
| 1914 | EXPAND_ONLY_PREDEF = NO | |
| 1915 | ||
| 1916 | # If the SEARCH_INCLUDES tag is set to YES the includes files in the | |
| 1917 | # INCLUDE_PATH will be searched if a #include is found. | |
| 1918 | # The default value is: YES. | |
| 1919 | # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. | |
| 1920 | ||
| 1921 | SEARCH_INCLUDES = YES | |
| 1922 | ||
| 1923 | # The INCLUDE_PATH tag can be used to specify one or more directories that | |
| 1924 | # contain include files that are not input files but should be processed by the | |
| 1925 | # preprocessor. | |
| 1926 | # This tag requires that the tag SEARCH_INCLUDES is set to YES. | |
| 1927 | ||
| 1928 | INCLUDE_PATH = ../include | |
| 1929 | ||
| 1930 | # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard | |
| 1931 | # patterns (like *.h and *.hpp) to filter out the header-files in the | |
| 1932 | # directories. If left blank, the patterns specified with FILE_PATTERNS will be | |
| 1933 | # used. | |
| 1934 | # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. | |
| 1935 | ||
| 1936 | INCLUDE_FILE_PATTERNS = *.h | |
| 1937 | ||
| 1938 | # The PREDEFINED tag can be used to specify one or more macro names that are | |
| 1939 | # defined before the preprocessor is started (similar to the -D option of e.g. | |
| 1940 | # gcc). The argument of the tag is a list of macros of the form: name or | |
| 1941 | # name=definition (no spaces). If the definition and the "=" are omitted, "=1" | |
| 1942 | # is assumed. To prevent a macro definition from being undefined via #undef or | |
| 1943 | # recursively expanded use the := operator instead of the = operator. | |
| 1944 | # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. | |
| 1945 | ||
| 1946 | PREDEFINED = "_MSC_VER=1400" \ | |
| 1947 | _CPPRTTI \ | |
| 1948 | _WIN32 \ | |
| 1949 | JSONCPP_DOC_EXCLUDE_IMPLEMENTATION \ | |
| 1950 | JSON_VALUE_USE_INTERNAL_MAP | |
| 1951 | ||
| 1952 | # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this | |
| 1953 | # tag can be used to specify a list of macro names that should be expanded. The | |
| 1954 | # macro definition that is found in the sources will be used. Use the PREDEFINED | |
| 1955 | # tag if you want to use a different macro definition that overrules the | |
| 1956 | # definition found in the source code. | |
| 1957 | # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. | |
| 1958 | ||
| 1959 | EXPAND_AS_DEFINED = | |
| 1960 | ||
| 1961 | # If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will | |
| 1962 | # remove all refrences to function-like macros that are alone on a line, have an | |
| 1963 | # all uppercase name, and do not end with a semicolon. Such function macros are | |
| 1964 | # typically used for boiler-plate code, and will confuse the parser if not | |
| 1965 | # removed. | |
| 1966 | # The default value is: YES. | |
| 1967 | # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. | |
| 1968 | ||
| 1969 | SKIP_FUNCTION_MACROS = YES | |
| 1970 | ||
| 1971 | #--------------------------------------------------------------------------- | |
| 1972 | # Configuration options related to external references | |
| 1973 | #--------------------------------------------------------------------------- | |
| 1974 | ||
| 1975 | # The TAGFILES tag can be used to specify one or more tag files. For each tag | |
| 1976 | # file the location of the external documentation should be added. The format of | |
| 1977 | # a tag file without this location is as follows: | |
| 1978 | # TAGFILES = file1 file2 ... | |
| 1979 | # Adding location for the tag files is done as follows: | |
| 1980 | # TAGFILES = file1=loc1 "file2 = loc2" ... | |
| 1981 | # where loc1 and loc2 can be relative or absolute paths or URLs. See the | |
| 1982 | # section "Linking to external documentation" for more information about the use | |
| 1983 | # of tag files. | |
| 1984 | # Note: Each tag file must have an unique name (where the name does NOT include | |
| 1985 | # the path). If a tag file is not located in the directory in which doxygen is | |
| 1986 | # run, you must also specify the path to the tagfile here. | |
| 1987 | ||
| 1988 | TAGFILES = | |
| 1989 | ||
| 1990 | # When a file name is specified after GENERATE_TAGFILE, doxygen will create a | |
| 1991 | # tag file that is based on the input files it reads. See section "Linking to | |
| 1992 | # external documentation" for more information about the usage of tag files. | |
| 1993 | ||
| 1994 | GENERATE_TAGFILE = | |
| 1995 | ||
| 1996 | # If the ALLEXTERNALS tag is set to YES all external class will be listed in the | |
| 1997 | # class index. If set to NO only the inherited external classes will be listed. | |
| 1998 | # The default value is: NO. | |
| 1999 | ||
| 2000 | ALLEXTERNALS = NO | |
| 2001 | ||
| 2002 | # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in | |
| 2003 | # the modules index. If set to NO, only the current project's groups will be | |
| 2004 | # listed. | |
| 2005 | # The default value is: YES. | |
| 2006 | ||
| 2007 | EXTERNAL_GROUPS = YES | |
| 2008 | ||
| 2009 | # If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in | |
| 2010 | # the related pages index. If set to NO, only the current project's pages will | |
| 2011 | # be listed. | |
| 2012 | # The default value is: YES. | |
| 2013 | ||
| 2014 | EXTERNAL_PAGES = YES | |
| 2015 | ||
| 2016 | # The PERL_PATH should be the absolute path and name of the perl script | |
| 2017 | # interpreter (i.e. the result of 'which perl'). | |
| 2018 | # The default file (with absolute path) is: /usr/bin/perl. | |
| 2019 | ||
| 2020 | PERL_PATH = /usr/bin/perl | |
| 2021 | ||
| 2022 | #--------------------------------------------------------------------------- | |
| 2023 | # Configuration options related to the dot tool | |
| 2024 | #--------------------------------------------------------------------------- | |
| 2025 | ||
| 2026 | # If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram | |
| 2027 | # (in HTML and LaTeX) for classes with base or super classes. Setting the tag to | |
| 2028 | # NO turns the diagrams off. Note that this option also works with HAVE_DOT | |
| 2029 | # disabled, but it is recommended to install and use dot, since it yields more | |
| 2030 | # powerful graphs. | |
| 2031 | # The default value is: YES. | |
| 2032 | ||
| 2033 | CLASS_DIAGRAMS = NO | |
| 2034 | ||
| 2035 | # You can define message sequence charts within doxygen comments using the \msc | |
| 2036 | # command. Doxygen will then run the mscgen tool (see: | |
| 2037 | # http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the | |
| 2038 | # documentation. The MSCGEN_PATH tag allows you to specify the directory where | |
| 2039 | # the mscgen tool resides. If left empty the tool is assumed to be found in the | |
| 2040 | # default search path. | |
| 2041 | ||
| 2042 | MSCGEN_PATH = | |
| 2043 | ||
| 2044 | # If set to YES, the inheritance and collaboration graphs will hide inheritance | |
| 2045 | # and usage relations if the target is undocumented or is not a class. | |
| 2046 | # The default value is: YES. | |
| 2047 | ||
| 2048 | HIDE_UNDOC_RELATIONS = NO | |
| 2049 | ||
| 2050 | # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is | |
| 2051 | # available from the path. This tool is part of Graphviz (see: | |
| 2052 | # http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent | |
| 2053 | # Bell Labs. The other options in this section have no effect if this option is | |
| 2054 | # set to NO | |
| 2055 | # The default value is: NO. | |
| 2056 | ||
| 2057 | HAVE_DOT = %HAVE_DOT% | |
| 2058 | ||
| 2059 | # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed | |
| 2060 | # to run in parallel. When set to 0 doxygen will base this on the number of | |
| 2061 | # processors available in the system. You can set it explicitly to a value | |
| 2062 | # larger than 0 to get control over the balance between CPU load and processing | |
| 2063 | # speed. | |
| 2064 | # Minimum value: 0, maximum value: 32, default value: 0. | |
| 2065 | # This tag requires that the tag HAVE_DOT is set to YES. | |
| 2066 | ||
| 2067 | DOT_NUM_THREADS = 0 | |
| 2068 | ||
| 2069 | # When you want a differently looking font n the dot files that doxygen | |
| 2070 | # generates you can specify the font name using DOT_FONTNAME. You need to make | |
| 2071 | # sure dot is able to find the font, which can be done by putting it in a | |
| 2072 | # standard location or by setting the DOTFONTPATH environment variable or by | |
| 2073 | # setting DOT_FONTPATH to the directory containing the font. | |
| 2074 | # The default value is: Helvetica. | |
| 2075 | # This tag requires that the tag HAVE_DOT is set to YES. | |
| 2076 | ||
| 2077 | DOT_FONTNAME = FreeSans | |
| 2078 | ||
| 2079 | # The DOT_FONTSIZE tag can be used to set the size (in points) of the font of | |
| 2080 | # dot graphs. | |
| 2081 | # Minimum value: 4, maximum value: 24, default value: 10. | |
| 2082 | # This tag requires that the tag HAVE_DOT is set to YES. | |
| 2083 | ||
| 2084 | DOT_FONTSIZE = 10 | |
| 2085 | ||
| 2086 | # By default doxygen will tell dot to use the default font as specified with | |
| 2087 | # DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set | |
| 2088 | # the path where dot can find it using this tag. | |
| 2089 | # This tag requires that the tag HAVE_DOT is set to YES. | |
| 2090 | ||
| 2091 | DOT_FONTPATH = | |
| 2092 | ||
| 2093 | # If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for | |
| 2094 | # each documented class showing the direct and indirect inheritance relations. | |
| 2095 | # Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO. | |
| 2096 | # The default value is: YES. | |
| 2097 | # This tag requires that the tag HAVE_DOT is set to YES. | |
| 2098 | ||
| 2099 | CLASS_GRAPH = YES | |
| 2100 | ||
| 2101 | # If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a | |
| 2102 | # graph for each documented class showing the direct and indirect implementation | |
| 2103 | # dependencies (inheritance, containment, and class references variables) of the | |
| 2104 | # class with other documented classes. | |
| 2105 | # The default value is: YES. | |
| 2106 | # This tag requires that the tag HAVE_DOT is set to YES. | |
| 2107 | ||
| 2108 | COLLABORATION_GRAPH = YES | |
| 2109 | ||
| 2110 | # If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for | |
| 2111 | # groups, showing the direct groups dependencies. | |
| 2112 | # The default value is: YES. | |
| 2113 | # This tag requires that the tag HAVE_DOT is set to YES. | |
| 2114 | ||
| 2115 | GROUP_GRAPHS = YES | |
| 2116 | ||
| 2117 | # If the UML_LOOK tag is set to YES doxygen will generate inheritance and | |
| 2118 | # collaboration diagrams in a style similar to the OMG's Unified Modeling | |
| 2119 | # Language. | |
| 2120 | # The default value is: NO. | |
| 2121 | # This tag requires that the tag HAVE_DOT is set to YES. | |
| 2122 | ||
| 2123 | UML_LOOK = %UML_LOOK% | |
| 2124 | ||
| 2125 | # If the UML_LOOK tag is enabled, the fields and methods are shown inside the | |
| 2126 | # class node. If there are many fields or methods and many nodes the graph may | |
| 2127 | # become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the | |
| 2128 | # number of items for each type to make the size more manageable. Set this to 0 | |
| 2129 | # for no limit. Note that the threshold may be exceeded by 50% before the limit | |
| 2130 | # is enforced. So when you set the threshold to 10, up to 15 fields may appear, | |
| 2131 | # but if the number exceeds 15, the total amount of fields shown is limited to | |
| 2132 | # 10. | |
| 2133 | # Minimum value: 0, maximum value: 100, default value: 10. | |
| 2134 | # This tag requires that the tag HAVE_DOT is set to YES. | |
| 2135 | ||
| 2136 | UML_LIMIT_NUM_FIELDS = 10 | |
| 2137 | ||
| 2138 | # If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and | |
| 2139 | # collaboration graphs will show the relations between templates and their | |
| 2140 | # instances. | |
| 2141 | # The default value is: NO. | |
| 2142 | # This tag requires that the tag HAVE_DOT is set to YES. | |
| 2143 | ||
| 2144 | TEMPLATE_RELATIONS = YES | |
| 2145 | ||
| 2146 | # If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to | |
| 2147 | # YES then doxygen will generate a graph for each documented file showing the | |
| 2148 | # direct and indirect include dependencies of the file with other documented | |
| 2149 | # files. | |
| 2150 | # The default value is: YES. | |
| 2151 | # This tag requires that the tag HAVE_DOT is set to YES. | |
| 2152 | ||
| 2153 | INCLUDE_GRAPH = YES | |
| 2154 | ||
| 2155 | # If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are | |
| 2156 | # set to YES then doxygen will generate a graph for each documented file showing | |
| 2157 | # the direct and indirect include dependencies of the file with other documented | |
| 2158 | # files. | |
| 2159 | # The default value is: YES. | |
| 2160 | # This tag requires that the tag HAVE_DOT is set to YES. | |
| 2161 | ||
| 2162 | INCLUDED_BY_GRAPH = YES | |
| 2163 | ||
| 2164 | # If the CALL_GRAPH tag is set to YES then doxygen will generate a call | |
| 2165 | # dependency graph for every global function or class method. | |
| 2166 | # | |
| 2167 | # Note that enabling this option will significantly increase the time of a run. | |
| 2168 | # So in most cases it will be better to enable call graphs for selected | |
| 2169 | # functions only using the \callgraph command. | |
| 2170 | # The default value is: NO. | |
| 2171 | # This tag requires that the tag HAVE_DOT is set to YES. | |
| 2172 | ||
| 2173 | CALL_GRAPH = NO | |
| 2174 | ||
| 2175 | # If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller | |
| 2176 | # dependency graph for every global function or class method. | |
| 2177 | # | |
| 2178 | # Note that enabling this option will significantly increase the time of a run. | |
| 2179 | # So in most cases it will be better to enable caller graphs for selected | |
| 2180 | # functions only using the \callergraph command. | |
| 2181 | # The default value is: NO. | |
| 2182 | # This tag requires that the tag HAVE_DOT is set to YES. | |
| 2183 | ||
| 2184 | CALLER_GRAPH = YES | |
| 2185 | ||
| 2186 | # If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical | |
| 2187 | # hierarchy of all classes instead of a textual one. | |
| 2188 | # The default value is: YES. | |
| 2189 | # This tag requires that the tag HAVE_DOT is set to YES. | |
| 2190 | ||
| 2191 | GRAPHICAL_HIERARCHY = YES | |
| 2192 | ||
| 2193 | # If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the | |
| 2194 | # dependencies a directory has on other directories in a graphical way. The | |
| 2195 | # dependency relations are determined by the #include relations between the | |
| 2196 | # files in the directories. | |
| 2197 | # The default value is: YES. | |
| 2198 | # This tag requires that the tag HAVE_DOT is set to YES. | |
| 2199 | ||
| 2200 | DIRECTORY_GRAPH = YES | |
| 2201 | ||
| 2202 | # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images | |
| 2203 | # generated by dot. | |
| 2204 | # Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order | |
| 2205 | # to make the SVG files visible in IE 9+ (other browsers do not have this | |
| 2206 | # requirement). | |
| 2207 | # Possible values are: png, jpg, gif and svg. | |
| 2208 | # The default value is: png. | |
| 2209 | # This tag requires that the tag HAVE_DOT is set to YES. | |
| 2210 | ||
| 2211 | DOT_IMAGE_FORMAT = png | |
| 2212 | ||
| 2213 | # If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to | |
| 2214 | # enable generation of interactive SVG images that allow zooming and panning. | |
| 2215 | # | |
| 2216 | # Note that this requires a modern browser other than Internet Explorer. Tested | |
| 2217 | # and working are Firefox, Chrome, Safari, and Opera. | |
| 2218 | # Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make | |
| 2219 | # the SVG files visible. Older versions of IE do not have SVG support. | |
| 2220 | # The default value is: NO. | |
| 2221 | # This tag requires that the tag HAVE_DOT is set to YES. | |
| 2222 | ||
| 2223 | INTERACTIVE_SVG = NO | |
| 2224 | ||
| 2225 | # The DOT_PATH tag can be used to specify the path where the dot tool can be | |
| 2226 | # found. If left blank, it is assumed the dot tool can be found in the path. | |
| 2227 | # This tag requires that the tag HAVE_DOT is set to YES. | |
| 2228 | ||
| 2229 | DOT_PATH = %DOT_PATH% | |
| 2230 | ||
| 2231 | # The DOTFILE_DIRS tag can be used to specify one or more directories that | |
| 2232 | # contain dot files that are included in the documentation (see the \dotfile | |
| 2233 | # command). | |
| 2234 | # This tag requires that the tag HAVE_DOT is set to YES. | |
| 2235 | ||
| 2236 | DOTFILE_DIRS = | |
| 2237 | ||
| 2238 | # The MSCFILE_DIRS tag can be used to specify one or more directories that | |
| 2239 | # contain msc files that are included in the documentation (see the \mscfile | |
| 2240 | # command). | |
| 2241 | ||
| 2242 | MSCFILE_DIRS = | |
| 2243 | ||
| 2244 | # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes | |
| 2245 | # that will be shown in the graph. If the number of nodes in a graph becomes | |
| 2246 | # larger than this value, doxygen will truncate the graph, which is visualized | |
| 2247 | # by representing a node as a red box. Note that doxygen if the number of direct | |
| 2248 | # children of the root node in a graph is already larger than | |
| 2249 | # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that | |
| 2250 | # the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. | |
| 2251 | # Minimum value: 0, maximum value: 10000, default value: 50. | |
| 2252 | # This tag requires that the tag HAVE_DOT is set to YES. | |
| 2253 | ||
| 2254 | DOT_GRAPH_MAX_NODES = 50 | |
| 2255 | ||
| 2256 | # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs | |
| 2257 | # generated by dot. A depth value of 3 means that only nodes reachable from the | |
| 2258 | # root by following a path via at most 3 edges will be shown. Nodes that lay | |
| 2259 | # further from the root node will be omitted. Note that setting this option to 1 | |
| 2260 | # or 2 may greatly reduce the computation time needed for large code bases. Also | |
| 2261 | # note that the size of a graph can be further restricted by | |
| 2262 | # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. | |
| 2263 | # Minimum value: 0, maximum value: 1000, default value: 0. | |
| 2264 | # This tag requires that the tag HAVE_DOT is set to YES. | |
| 2265 | ||
| 2266 | MAX_DOT_GRAPH_DEPTH = 1000 | |
| 2267 | ||
| 2268 | # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent | |
| 2269 | # background. This is disabled by default, because dot on Windows does not seem | |
| 2270 | # to support this out of the box. | |
| 2271 | # | |
| 2272 | # Warning: Depending on the platform used, enabling this option may lead to | |
| 2273 | # badly anti-aliased labels on the edges of a graph (i.e. they become hard to | |
| 2274 | # read). | |
| 2275 | # The default value is: NO. | |
| 2276 | # This tag requires that the tag HAVE_DOT is set to YES. | |
| 2277 | ||
| 2278 | DOT_TRANSPARENT = NO | |
| 2279 | ||
| 2280 | # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output | |
| 2281 | # files in one run (i.e. multiple -o and -T options on the command line). This | |
| 2282 | # makes dot run faster, but since only newer versions of dot (>1.8.10) support | |
| 2283 | # this, this feature is disabled by default. | |
| 2284 | # The default value is: NO. | |
| 2285 | # This tag requires that the tag HAVE_DOT is set to YES. | |
| 2286 | ||
| 2287 | DOT_MULTI_TARGETS = YES | |
| 2288 | ||
| 2289 | # If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page | |
| 2290 | # explaining the meaning of the various boxes and arrows in the dot generated | |
| 2291 | # graphs. | |
| 2292 | # The default value is: YES. | |
| 2293 | # This tag requires that the tag HAVE_DOT is set to YES. | |
| 2294 | ||
| 2295 | GENERATE_LEGEND = YES | |
| 2296 | ||
| 2297 | # If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot | |
| 2298 | # files that are used to generate the various graphs. | |
| 2299 | # The default value is: YES. | |
| 2300 | # This tag requires that the tag HAVE_DOT is set to YES. | |
| 2301 | ||
| 2302 | DOT_CLEANUP = YES |
| r0 | r242831 | |
|---|---|---|
| 1 | <hr> | |
| 2 | </body> | |
| 3 | </html> |
| r0 | r242831 | |
|---|---|---|
| 1 | <html> | |
| 2 | <head> | |
| 3 | <title> | |
| 4 | JsonCpp - JSON data format manipulation library | |
| 5 | </title> | |
| 6 | <link href="doxygen.css" rel="stylesheet" type="text/css"> | |
| 7 | <link href="tabs.css" rel="stylesheet" type="text/css"> | |
| 8 | </head> | |
| 9 | ||
| 10 | <body bgcolor="#ffffff"> | |
| 11 | <table width="100%"> | |
| 12 | <tr> | |
| 13 | <td width="40%" align="left" valign="center"> | |
| 14 | <a href="https://github.com/open-source-parsers/jsoncpp"> | |
| 15 | JsonCpp project page | |
| 16 | </a> | |
| 17 | </td> | |
| 18 | <td width="40%" align="right" valign="center"> | |
| 19 | <a href="https://github.com/open-source-parsers/jsoncpp">JsonCpp home page</a> | |
| 20 | </td> | |
| 21 | </tr> | |
| 22 | </table> | |
| 23 | ||
| 24 | <hr> |
| r0 | r242831 | |
|---|---|---|
| 1 | /** | |
| 2 | \mainpage | |
| 3 | \section _intro Introduction | |
| 4 | ||
| 5 | <a HREF="http://www.json.org/">JSON (JavaScript Object Notation)</a> | |
| 6 | is a lightweight data-interchange format. | |
| 7 | It can represent integer, real number, string, an ordered sequence of value, and | |
| 8 | a collection of name/value pairs. | |
| 9 | ||
| 10 | Here is an example of JSON data: | |
| 11 | \verbatim | |
| 12 | // Configuration options | |
| 13 | { | |
| 14 | // Default encoding for text | |
| 15 | "encoding" : "UTF-8", | |
| 16 | ||
| 17 | // Plug-ins loaded at start-up | |
| 18 | "plug-ins" : [ | |
| 19 | "python", | |
| 20 | "c++", | |
| 21 | "ruby" | |
| 22 | ], | |
| 23 | ||
| 24 | // Tab indent size | |
| 25 | "indent" : { "length" : 3, "use_space": true } | |
| 26 | } | |
| 27 | \endverbatim | |
| 28 | <code>jsoncpp</code> supports comments as <i>meta-data</i>. | |
| 29 | ||
| 30 | \section _features Features | |
| 31 | - read and write JSON document | |
| 32 | - attach C++ style comments to element during parsing | |
| 33 | - rewrite JSON document preserving original comments | |
| 34 | ||
| 35 | Notes: Comments used to be supported in JSON but where removed for | |
| 36 | portability (C like comments are not supported in Python). Since | |
| 37 | comments are useful in configuration/input file, this feature was | |
| 38 | preserved. | |
| 39 | ||
| 40 | \section _example Code example | |
| 41 | ||
| 42 | \code | |
| 43 | Json::Value root; // will contains the root value after parsing. | |
| 44 | Json::Reader reader; | |
| 45 | bool parsingSuccessful = reader.parse( config_doc, root ); | |
| 46 | if ( !parsingSuccessful ) | |
| 47 | { | |
| 48 | // report to the user the failure and their locations in the document. | |
| 49 | std::cout << "Failed to parse configuration\n" | |
| 50 | << reader.getFormattedErrorMessages(); | |
| 51 | return; | |
| 52 | } | |
| 53 | ||
| 54 | // Get the value of the member of root named 'encoding', return 'UTF-8' if there is no | |
| 55 | // such member. | |
| 56 | std::string encoding = root.get("encoding", "UTF-8" ).asString(); | |
| 57 | // Get the value of the member of root named 'encoding', return a 'null' value if | |
| 58 | // there is no such member. | |
| 59 | const Json::Value plugins = root["plug-ins"]; | |
| 60 | for ( int index = 0; index < plugins.size(); ++index ) // Iterates over the sequence elements. | |
| 61 | loadPlugIn( plugins[index].asString() ); | |
| 62 | ||
| 63 | setIndentLength( root["indent"].get("length", 3).asInt() ); | |
| 64 | setIndentUseSpace( root["indent"].get("use_space", true).asBool() ); | |
| 65 | ||
| 66 | // ... | |
| 67 | // At application shutdown to make the new configuration document: | |
| 68 | // Since Json::Value has implicit constructor for all value types, it is not | |
| 69 | // necessary to explicitly construct the Json::Value object: | |
| 70 | root["encoding"] = getCurrentEncoding(); | |
| 71 | root["indent"]["length"] = getCurrentIndentLength(); | |
| 72 | root["indent"]["use_space"] = getCurrentIndentUseSpace(); | |
| 73 | ||
| 74 | Json::StyledWriter writer; | |
| 75 | // Make a new JSON document for the configuration. Preserve original comments. | |
| 76 | std::string outputConfig = writer.write( root ); | |
| 77 | ||
| 78 | // You can also use streams. This will put the contents of any JSON | |
| 79 | // stream at a particular sub-value, if you'd like. | |
| 80 | std::cin >> root["subtree"]; | |
| 81 | ||
| 82 | // And you can write to a stream, using the StyledWriter automatically. | |
| 83 | std::cout << root; | |
| 84 | \endcode | |
| 85 | ||
| 86 | \section _pbuild Build instructions | |
| 87 | The build instructions are located in the file | |
| 88 | <a HREF="https://github.com/open-source-parsers/jsoncpp/blob/master/README.md">README.md</a> in the top-directory of the project. | |
| 89 | ||
| 90 | The latest version of the source is available in the project's GitHub repository: | |
| 91 | <a HREF="https://github.com/open-source-parsers/jsoncpp/"> | |
| 92 | jsoncpp</a> | |
| 93 | ||
| 94 | \section _news What's New? | |
| 95 | The description of latest changes can be found in | |
| 96 | <a HREF="https://github.com/open-source-parsers/jsoncpp/wiki/NEWS"> | |
| 97 | the NEWS wiki | |
| 98 | </a>. | |
| 99 | ||
| 100 | \section _rlinks Related links | |
| 101 | - <a HREF="http://www.json.org/">JSON</a> Specification and alternate language implementations. | |
| 102 | - <a HREF="http://www.yaml.org/">YAML</a> A data format designed for human readability. | |
| 103 | - <a HREF="http://www.cl.cam.ac.uk/~mgk25/unicode.html">UTF-8 and Unicode FAQ</a>. | |
| 104 | ||
| 105 | \section _plinks Old project links | |
| 106 | - <a href="https://sourceforge.net/projects/jsoncpp/">https://sourceforge.net/projects/jsoncpp/</a> | |
| 107 | - <a href="http://jsoncpp.sourceforge.net">http://jsoncpp.sourceforge.net</a> | |
| 108 | - <a href="http://sourceforge.net/projects/jsoncpp/files/">http://sourceforge.net/projects/jsoncpp/files/</a> | |
| 109 | - <a href="http://jsoncpp.svn.sourceforge.net/svnroot/jsoncpp/trunk/">http://jsoncpp.svn.sourceforge.net/svnroot/jsoncpp/trunk/</a> | |
| 110 | - <a href="http://jsoncpp.sourceforge.net/old.html">http://jsoncpp.sourceforge.net/old.html</a> | |
| 111 | ||
| 112 | \section _license License | |
| 113 | See file <a href="https://github.com/open-source-parsers/jsoncpp/blob/master/LICENSE"><code>LICENSE</code></a> in the top-directory of the project. | |
| 114 | ||
| 115 | Basically JsonCpp is licensed under MIT license, or public domain if desired | |
| 116 | and recognized in your jurisdiction. | |
| 117 | ||
| 118 | \author Baptiste Lepilleur <blep@users.sourceforge.net> (originator) | |
| 119 | */ |
| r0 | r242831 | |
|---|---|---|
| 1 | The documentation is generated using doxygen (http://www.doxygen.org). |
| r0 | r242831 | |
|---|---|---|
| 1 | /*! \page roadmap JsonCpp roadmap | |
| 2 | Moved to: https://github.com/open-source-parsers/jsoncpp/wiki/Roadmap | |
| 3 | */ |
| r0 | r242831 | |
|---|---|---|
| 1 | """Script to generate doxygen documentation. | |
| 2 | """ | |
| 3 | from __future__ import print_function | |
| 4 | from devtools import tarball | |
| 5 | import re | |
| 6 | import os | |
| 7 | import os.path | |
| 8 | import sys | |
| 9 | import shutil | |
| 10 | ||
| 11 | def find_program(*filenames): | |
| 12 | """find a program in folders path_lst, and sets env[var] | |
| 13 | @param filenames: a list of possible names of the program to search for | |
| 14 | @return: the full path of the filename if found, or '' if filename could not be found | |
| 15 | """ | |
| 16 | paths = os.environ.get('PATH', '').split(os.pathsep) | |
| 17 | suffixes = ('win32' in sys.platform ) and '.exe .com .bat .cmd' or '' | |
| 18 | for filename in filenames: | |
| 19 | for name in [filename+ext for ext in suffixes.split()]: | |
| 20 | for directory in paths: | |
| 21 | full_path = os.path.join(directory, name) | |
| 22 | if os.path.isfile(full_path): | |
| 23 | return full_path | |
| 24 | return '' | |
| 25 | ||
| 26 | def do_subst_in_file(targetfile, sourcefile, dict): | |
| 27 | """Replace all instances of the keys of dict with their values. | |
| 28 | For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'}, | |
| 29 | then all instances of %VERSION% in the file will be replaced with 1.2345 etc. | |
| 30 | """ | |
| 31 | try: | |
| 32 | f = open(sourcefile, 'rb') | |
| 33 | contents = f.read() | |
| 34 | f.close() | |
| 35 | except: | |
| 36 | print("Can't read source file %s"%sourcefile) | |
| 37 | raise | |
| 38 | for (k,v) in list(dict.items()): | |
| 39 | v = v.replace('\\','\\\\') | |
| 40 | contents = re.sub(k, v, contents) | |
| 41 | try: | |
| 42 | f = open(targetfile, 'wb') | |
| 43 | f.write(contents) | |
| 44 | f.close() | |
| 45 | except: | |
| 46 | print("Can't write target file %s"%targetfile) | |
| 47 | raise | |
| 48 | ||
| 49 | def run_doxygen(doxygen_path, config_file, working_dir, is_silent): | |
| 50 | config_file = os.path.abspath( config_file ) | |
| 51 | doxygen_path = doxygen_path | |
| 52 | old_cwd = os.getcwd() | |
| 53 | try: | |
| 54 | os.chdir( working_dir ) | |
| 55 | cmd = [doxygen_path, config_file] | |
| 56 | print('Running:', ' '.join( cmd )) | |
| 57 | try: | |
| 58 | import subprocess | |
| 59 | except: | |
| 60 | if os.system( ' '.join( cmd ) ) != 0: | |
| 61 | print('Documentation generation failed') | |
| 62 | return False | |
| 63 | else: | |
| 64 | if is_silent: | |
| 65 | process = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT ) | |
| 66 | else: | |
| 67 | process = subprocess.Popen( cmd ) | |
| 68 | stdout, _ = process.communicate() | |
| 69 | if process.returncode: | |
| 70 | print('Documentation generation failed:') | |
| 71 | print(stdout) | |
| 72 | return False | |
| 73 | return True | |
| 74 | finally: | |
| 75 | os.chdir( old_cwd ) | |
| 76 | ||
| 77 | def build_doc( options, make_release=False ): | |
| 78 | if make_release: | |
| 79 | options.make_tarball = True | |
| 80 | options.with_dot = True | |
| 81 | options.with_html_help = True | |
| 82 | options.with_uml_look = True | |
| 83 | options.open = False | |
| 84 | options.silent = True | |
| 85 | ||
| 86 | version = open('version','rt').read().strip() | |
| 87 | output_dir = 'dist/doxygen' # relative to doc/doxyfile location. | |
| 88 | if not os.path.isdir( output_dir ): | |
| 89 | os.makedirs( output_dir ) | |
| 90 | top_dir = os.path.abspath( '.' ) | |
| 91 | html_output_dirname = 'jsoncpp-api-html-' + version | |
| 92 | tarball_path = os.path.join( 'dist', html_output_dirname + '.tar.gz' ) | |
| 93 | warning_log_path = os.path.join( output_dir, '../jsoncpp-doxygen-warning.log' ) | |
| 94 | html_output_path = os.path.join( output_dir, html_output_dirname ) | |
| 95 | def yesno( bool ): | |
| 96 | return bool and 'YES' or 'NO' | |
| 97 | subst_keys = { | |
| 98 | '%JSONCPP_VERSION%': version, | |
| 99 | '%DOC_TOPDIR%': '', | |
| 100 | '%TOPDIR%': top_dir, | |
| 101 | '%HTML_OUTPUT%': os.path.join( '..', output_dir, html_output_dirname ), | |
| 102 | '%HAVE_DOT%': yesno(options.with_dot), | |
| 103 | '%DOT_PATH%': os.path.split(options.dot_path)[0], | |
| 104 | '%HTML_HELP%': yesno(options.with_html_help), | |
| 105 | '%UML_LOOK%': yesno(options.with_uml_look), | |
| 106 | '%WARNING_LOG_PATH%': os.path.join( '..', warning_log_path ) | |
| 107 | } | |
| 108 | ||
| 109 | if os.path.isdir( output_dir ): | |
| 110 | print('Deleting directory:', output_dir) | |
| 111 | shutil.rmtree( output_dir ) | |
| 112 | if not os.path.isdir( output_dir ): | |
| 113 | os.makedirs( output_dir ) | |
| 114 | ||
| 115 | do_subst_in_file( 'doc/doxyfile', 'doc/doxyfile.in', subst_keys ) | |
| 116 | ok = run_doxygen( options.doxygen_path, 'doc/doxyfile', 'doc', is_silent=options.silent ) | |
| 117 | if not options.silent: | |
| 118 | print(open(warning_log_path, 'rb').read()) | |
| 119 | index_path = os.path.abspath(os.path.join('doc', subst_keys['%HTML_OUTPUT%'], 'index.html')) | |
| 120 | print('Generated documentation can be found in:') | |
| 121 | print(index_path) | |
| 122 | if options.open: | |
| 123 | import webbrowser | |
| 124 | webbrowser.open( 'file://' + index_path ) | |
| 125 | if options.make_tarball: | |
| 126 | print('Generating doc tarball to', tarball_path) | |
| 127 | tarball_sources = [ | |
| 128 | output_dir, | |
| 129 | 'README.txt', | |
| 130 | 'LICENSE', | |
| 131 | 'NEWS.txt', | |
| 132 | 'version' | |
| 133 | ] | |
| 134 | tarball_basedir = os.path.join( output_dir, html_output_dirname ) | |
| 135 | tarball.make_tarball( tarball_path, tarball_sources, tarball_basedir, html_output_dirname ) | |
| 136 | return tarball_path, html_output_dirname | |
| 137 | ||
| 138 | def main(): | |
| 139 | usage = """%prog | |
| 140 | Generates doxygen documentation in build/doxygen. | |
| 141 | Optionaly makes a tarball of the documentation to dist/. | |
| 142 | ||
| 143 | Must be started in the project top directory. | |
| 144 | """ | |
| 145 | from optparse import OptionParser | |
| 146 | parser = OptionParser(usage=usage) | |
| 147 | parser.allow_interspersed_args = False | |
| 148 | parser.add_option('--with-dot', dest="with_dot", action='store_true', default=False, | |
| 149 | help="""Enable usage of DOT to generate collaboration diagram""") | |
| 150 | parser.add_option('--dot', dest="dot_path", action='store', default=find_program('dot'), | |
| 151 | help="""Path to GraphViz dot tool. Must be full qualified path. [Default: %default]""") | |
| 152 | parser.add_option('--doxygen', dest="doxygen_path", action='store', default=find_program('doxygen'), | |
| 153 | help="""Path to Doxygen tool. [Default: %default]""") | |
| 154 | parser.add_option('--with-html-help', dest="with_html_help", action='store_true', default=False, | |
| 155 | help="""Enable generation of Microsoft HTML HELP""") | |
| 156 | parser.add_option('--no-uml-look', dest="with_uml_look", action='store_false', default=True, | |
| 157 | help="""Generates DOT graph without UML look [Default: False]""") | |
| 158 | parser.add_option('--open', dest="open", action='store_true', default=False, | |
| 159 | help="""Open the HTML index in the web browser after generation""") | |
| 160 | parser.add_option('--tarball', dest="make_tarball", action='store_true', default=False, | |
| 161 | help="""Generates a tarball of the documentation in dist/ directory""") | |
| 162 | parser.add_option('-s', '--silent', dest="silent", action='store_true', default=False, | |
| 163 | help="""Hides doxygen output""") | |
| 164 | parser.enable_interspersed_args() | |
| 165 | options, args = parser.parse_args() | |
| 166 | build_doc( options ) | |
| 167 | ||
| 168 | if __name__ == '__main__': | |
| 169 | main() |
| r0 | r242831 | |
|---|---|---|
| 1 | FILE(GLOB INCLUDE_FILES "json/*.h") | |
| 2 | INSTALL(FILES ${INCLUDE_FILES} DESTINATION ${INCLUDE_INSTALL_DIR}/json) |
| r0 | r242831 | |
|---|---|---|
| 1 | // Copyright 2007-2010 Baptiste Lepilleur | |
| 2 | // Distributed under MIT license, or public domain if desired and | |
| 3 | // recognized in your jurisdiction. | |
| 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE | |
| 5 | ||
| 6 | #ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED | |
| 7 | #define CPPTL_JSON_ASSERTIONS_H_INCLUDED | |
| 8 | ||
| 9 | #include <stdlib.h> | |
| 10 | ||
| 11 | #if !defined(JSON_IS_AMALGAMATION) | |
| 12 | #include "config.h" | |
| 13 | #endif // if !defined(JSON_IS_AMALGAMATION) | |
| 14 | ||
| 15 | #if JSON_USE_EXCEPTION | |
| 16 | #include <stdexcept> | |
| 17 | #define JSON_ASSERT(condition) \ | |
| 18 | assert(condition); // @todo <= change this into an exception throw | |
| 19 | #define JSON_FAIL_MESSAGE(message) throw std::runtime_error(message); | |
| 20 | #else // JSON_USE_EXCEPTION | |
| 21 | #define JSON_ASSERT(condition) assert(condition); | |
| 22 | ||
| 23 | // The call to assert() will show the failure message in debug builds. In | |
| 24 | // release bugs we write to invalid memory in order to crash hard, so that a | |
| 25 | // debugger or crash reporter gets the chance to take over. We still call exit() | |
| 26 | // afterward in order to tell the compiler that this macro doesn't return. | |
| 27 | #define JSON_FAIL_MESSAGE(message) \ | |
| 28 | { \ | |
| 29 | assert(false&& message); \ | |
| 30 | strcpy(reinterpret_cast<char*>(666), message); \ | |
| 31 | exit(123); \ | |
| 32 | } | |
| 33 | ||
| 34 | #endif | |
| 35 | ||
| 36 | #define JSON_ASSERT_MESSAGE(condition, message) \ | |
| 37 | if (!(condition)) { \ | |
| 38 | JSON_FAIL_MESSAGE(message) \ | |
| 39 | } | |
| 40 | ||
| 41 | #endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED |
| r0 | r242831 | |
|---|---|---|
| 1 | // Copyright 2007-2010 Baptiste Lepilleur | |
| 2 | // Distributed under MIT license, or public domain if desired and | |
| 3 | // recognized in your jurisdiction. | |
| 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE | |
| 5 | ||
| 6 | #ifndef JSON_AUTOLINK_H_INCLUDED | |
| 7 | #define JSON_AUTOLINK_H_INCLUDED | |
| 8 | ||
| 9 | #include "config.h" | |
| 10 | ||
| 11 | #ifdef JSON_IN_CPPTL | |
| 12 | #include <cpptl/cpptl_autolink.h> | |
| 13 | #endif | |
| 14 | ||
| 15 | #if !defined(JSON_NO_AUTOLINK) && !defined(JSON_DLL_BUILD) && \ | |
| 16 | !defined(JSON_IN_CPPTL) | |
| 17 | #define CPPTL_AUTOLINK_NAME "json" | |
| 18 | #undef CPPTL_AUTOLINK_DLL | |
| 19 | #ifdef JSON_DLL | |
| 20 | #define CPPTL_AUTOLINK_DLL | |
| 21 | #endif | |
| 22 | #include "autolink.h" | |
| 23 | #endif | |
| 24 | ||
| 25 | #endif // JSON_AUTOLINK_H_INCLUDED |
| r0 | r242831 | |
|---|---|---|
| 1 | // Copyright 2007-2010 Baptiste Lepilleur | |
| 2 | // Distributed under MIT license, or public domain if desired and | |
| 3 | // recognized in your jurisdiction. | |
| 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE | |
| 5 | ||
| 6 | #ifndef JSON_CONFIG_H_INCLUDED | |
| 7 | #define JSON_CONFIG_H_INCLUDED | |
| 8 | ||
| 9 | /// If defined, indicates that json library is embedded in CppTL library. | |
| 10 | //# define JSON_IN_CPPTL 1 | |
| 11 | ||
| 12 | /// If defined, indicates that json may leverage CppTL library | |
| 13 | //# define JSON_USE_CPPTL 1 | |
| 14 | /// If defined, indicates that cpptl vector based map should be used instead of | |
| 15 | /// std::map | |
| 16 | /// as Value container. | |
| 17 | //# define JSON_USE_CPPTL_SMALLMAP 1 | |
| 18 | /// If defined, indicates that Json specific container should be used | |
| 19 | /// (hash table & simple deque container with customizable allocator). | |
| 20 | /// THIS FEATURE IS STILL EXPERIMENTAL! There is know bugs: See #3177332 | |
| 21 | //# define JSON_VALUE_USE_INTERNAL_MAP 1 | |
| 22 | /// Force usage of standard new/malloc based allocator instead of memory pool | |
| 23 | /// based allocator. | |
| 24 | /// The memory pools allocator used optimization (initializing Value and | |
| 25 | /// ValueInternalLink | |
| 26 | /// as if it was a POD) that may cause some validation tool to report errors. | |
| 27 | /// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined. | |
| 28 | //# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1 | |
| 29 | ||
| 30 | // If non-zero, the library uses exceptions to report bad input instead of C | |
| 31 | // assertion macros. The default is to use exceptions. | |
| 32 | #ifndef JSON_USE_EXCEPTION | |
| 33 | #define JSON_USE_EXCEPTION 1 | |
| 34 | #endif | |
| 35 | ||
| 36 | /// If defined, indicates that the source file is amalgated | |
| 37 | /// to prevent private header inclusion. | |
| 38 | /// Remarks: it is automatically defined in the generated amalgated header. | |
| 39 | // #define JSON_IS_AMALGAMATION | |
| 40 | ||
| 41 | #ifdef JSON_IN_CPPTL | |
| 42 | #include <cpptl/config.h> | |
| 43 | #ifndef JSON_USE_CPPTL | |
| 44 | #define JSON_USE_CPPTL 1 | |
| 45 | #endif | |
| 46 | #endif | |
| 47 | ||
| 48 | #ifdef JSON_IN_CPPTL | |
| 49 | #define JSON_API CPPTL_API | |
| 50 | #elif defined(JSON_DLL_BUILD) | |
| 51 | #if defined(_MSC_VER) | |
| 52 | #define JSON_API __declspec(dllexport) | |
| 53 | #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING | |
| 54 | #endif // if defined(_MSC_VER) | |
| 55 | #elif defined(JSON_DLL) | |
| 56 | #if defined(_MSC_VER) | |
| 57 | #define JSON_API __declspec(dllimport) | |
| 58 | #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING | |
| 59 | #endif // if defined(_MSC_VER) | |
| 60 | #endif // ifdef JSON_IN_CPPTL | |
| 61 | #if !defined(JSON_API) | |
| 62 | #define JSON_API | |
| 63 | #endif | |
| 64 | ||
| 65 | // If JSON_NO_INT64 is defined, then Json only support C++ "int" type for | |
| 66 | // integer | |
| 67 | // Storages, and 64 bits integer support is disabled. | |
| 68 | // #define JSON_NO_INT64 1 | |
| 69 | ||
| 70 | #if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6 | |
| 71 | // Microsoft Visual Studio 6 only support conversion from __int64 to double | |
| 72 | // (no conversion from unsigned __int64). | |
| 73 | #define JSON_USE_INT64_DOUBLE_CONVERSION 1 | |
| 74 | // Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255' | |
| 75 | // characters in the debug information) | |
| 76 | // All projects I've ever seen with VS6 were using this globally (not bothering | |
| 77 | // with pragma push/pop). | |
| 78 | #pragma warning(disable : 4786) | |
| 79 | #endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6 | |
| 80 | ||
| 81 | #if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008 | |
| 82 | /// Indicates that the following function is deprecated. | |
| 83 | #define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) | |
| 84 | #endif | |
| 85 | ||
| 86 | #if !defined(JSONCPP_DEPRECATED) | |
| 87 | #define JSONCPP_DEPRECATED(message) | |
| 88 | #endif // if !defined(JSONCPP_DEPRECATED) | |
| 89 | ||
| 90 | namespace Json { | |
| 91 | typedef int Int; | |
| 92 | typedef unsigned int UInt; | |
| 93 | #if defined(JSON_NO_INT64) | |
| 94 | typedef int LargestInt; | |
| 95 | typedef unsigned int LargestUInt; | |
| 96 | #undef JSON_HAS_INT64 | |
| 97 | #else // if defined(JSON_NO_INT64) | |
| 98 | // For Microsoft Visual use specific types as long long is not supported | |
| 99 | #if defined(_MSC_VER) // Microsoft Visual Studio | |
| 100 | typedef __int64 Int64; | |
| 101 | typedef unsigned __int64 UInt64; | |
| 102 | #else // if defined(_MSC_VER) // Other platforms, use long long | |
| 103 | typedef long long int Int64; | |
| 104 | typedef unsigned long long int UInt64; | |
| 105 | #endif // if defined(_MSC_VER) | |
| 106 | typedef Int64 LargestInt; | |
| 107 | typedef UInt64 LargestUInt; | |
| 108 | #define JSON_HAS_INT64 | |
| 109 | #endif // if defined(JSON_NO_INT64) | |
| 110 | } // end namespace Json | |
| 111 | ||
| 112 | #endif // JSON_CONFIG_H_INCLUDED |
| r0 | r242831 | |
|---|---|---|
| 1 | // Copyright 2007-2010 Baptiste Lepilleur | |
| 2 | // Distributed under MIT license, or public domain if desired and | |
| 3 | // recognized in your jurisdiction. | |
| 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE | |
| 5 | ||
| 6 | #ifndef CPPTL_JSON_FEATURES_H_INCLUDED | |
| 7 | #define CPPTL_JSON_FEATURES_H_INCLUDED | |
| 8 | ||
| 9 | #if !defined(JSON_IS_AMALGAMATION) | |
| 10 | #include "forwards.h" | |
| 11 | #endif // if !defined(JSON_IS_AMALGAMATION) | |
| 12 | ||
| 13 | namespace Json { | |
| 14 | ||
| 15 | /** \brief Configuration passed to reader and writer. | |
| 16 | * This configuration object can be used to force the Reader or Writer | |
| 17 | * to behave in a standard conforming way. | |
| 18 | */ | |
| 19 | class JSON_API Features { | |
| 20 | public: | |
| 21 | /** \brief A configuration that allows all features and assumes all strings | |
| 22 | * are UTF-8. | |
| 23 | * - C & C++ comments are allowed | |
| 24 | * - Root object can be any JSON value | |
| 25 | * - Assumes Value strings are encoded in UTF-8 | |
| 26 | */ | |
| 27 | static Features all(); | |
| 28 | ||
| 29 | /** \brief A configuration that is strictly compatible with the JSON | |
| 30 | * specification. | |
| 31 | * - Comments are forbidden. | |
| 32 | * - Root object must be either an array or an object value. | |
| 33 | * - Assumes Value strings are encoded in UTF-8 | |
| 34 | */ | |
| 35 | static Features strictMode(); | |
| 36 | ||
| 37 | /** \brief Initialize the configuration like JsonConfig::allFeatures; | |
| 38 | */ | |
| 39 | Features(); | |
| 40 | ||
| 41 | /// \c true if comments are allowed. Default: \c true. | |
| 42 | bool allowComments_; | |
| 43 | ||
| 44 | /// \c true if root must be either an array or an object value. Default: \c | |
| 45 | /// false. | |
| 46 | bool strictRoot_; | |
| 47 | ||
| 48 | /// \c true if dropped null placeholders are allowed. Default: \c false. | |
| 49 | bool allowDroppedNullPlaceholders_; | |
| 50 | ||
| 51 | /// \c true if numeric object key are allowed. Default: \c false. | |
| 52 | bool allowNumericKeys_; | |
| 53 | }; | |
| 54 | ||
| 55 | } // namespace Json | |
| 56 | ||
| 57 | #endif // CPPTL_JSON_FEATURES_H_INCLUDED |
| r0 | r242831 | |
|---|---|---|
| 1 | // Copyright 2007-2010 Baptiste Lepilleur | |
| 2 | // Distributed under MIT license, or public domain if desired and | |
| 3 | // recognized in your jurisdiction. | |
| 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE | |
| 5 | ||
| 6 | #ifndef JSON_FORWARDS_H_INCLUDED | |
| 7 | #define JSON_FORWARDS_H_INCLUDED | |
| 8 | ||
| 9 | #if !defined(JSON_IS_AMALGAMATION) | |
| 10 | #include "config.h" | |
| 11 | #endif // if !defined(JSON_IS_AMALGAMATION) | |
| 12 | ||
| 13 | namespace Json { | |
| 14 | ||
| 15 | // writer.h | |
| 16 | class FastWriter; | |
| 17 | class StyledWriter; | |
| 18 | ||
| 19 | // reader.h | |
| 20 | class Reader; | |
| 21 | ||
| 22 | // features.h | |
| 23 | class Features; | |
| 24 | ||
| 25 | // value.h | |
| 26 | typedef unsigned int ArrayIndex; | |
| 27 | class StaticString; | |
| 28 | class Path; | |
| 29 | class PathArgument; | |
| 30 | class Value; | |
| 31 | class ValueIteratorBase; | |
| 32 | class ValueIterator; | |
| 33 | class ValueConstIterator; | |
| 34 | #ifdef JSON_VALUE_USE_INTERNAL_MAP | |
| 35 | class ValueMapAllocator; | |
| 36 | class ValueInternalLink; | |
| 37 | class ValueInternalArray; | |
| 38 | class ValueInternalMap; | |
| 39 | #endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP | |
| 40 | ||
| 41 | } // namespace Json | |
| 42 | ||
| 43 | #endif // JSON_FORWARDS_H_INCLUDED |
| r0 | r242831 | |
|---|---|---|
| 1 | // Copyright 2007-2010 Baptiste Lepilleur | |
| 2 | // Distributed under MIT license, or public domain if desired and | |
| 3 | // recognized in your jurisdiction. | |
| 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE | |
| 5 | ||
| 6 | #ifndef JSON_JSON_H_INCLUDED | |
| 7 | #define JSON_JSON_H_INCLUDED | |
| 8 | ||
| 9 | #include "autolink.h" | |
| 10 | #include "value.h" | |
| 11 | #include "reader.h" | |
| 12 | #include "writer.h" | |
| 13 | #include "features.h" | |
| 14 | ||
| 15 | #endif // JSON_JSON_H_INCLUDED |
| r0 | r242831 | |
|---|---|---|
| 1 | // Copyright 2007-2010 Baptiste Lepilleur | |
| 2 | // Distributed under MIT license, or public domain if desired and | |
| 3 | // recognized in your jurisdiction. | |
| 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE | |
| 5 | ||
| 6 | #ifndef CPPTL_JSON_READER_H_INCLUDED | |
| 7 | #define CPPTL_JSON_READER_H_INCLUDED | |
| 8 | ||
| 9 | #if !defined(JSON_IS_AMALGAMATION) | |
| 10 | #include "features.h" | |
| 11 | #include "value.h" | |
| 12 | #endif // if !defined(JSON_IS_AMALGAMATION) | |
| 13 | #include <deque> | |
| 14 | #include <iosfwd> | |
| 15 | #include <stack> | |
| 16 | #include <string> | |
| 17 | ||
| 18 | // Disable warning C4251: <data member>: <type> needs to have dll-interface to | |
| 19 | // be used by... | |
| 20 | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) | |
| 21 | #pragma warning(push) | |
| 22 | #pragma warning(disable : 4251) | |
| 23 | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) | |
| 24 | ||
| 25 | namespace Json { | |
| 26 | ||
| 27 | /** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a | |
| 28 | *Value. | |
| 29 | * | |
| 30 | */ | |
| 31 | class JSON_API Reader { | |
| 32 | public: | |
| 33 | typedef char Char; | |
| 34 | typedef const Char* Location; | |
| 35 | ||
| 36 | /** \brief An error tagged with where in the JSON text it was encountered. | |
| 37 | * | |
| 38 | * The offsets give the [start, limit) range of bytes within the text. Note | |
| 39 | * that this is bytes, not codepoints. | |
| 40 | * | |
| 41 | */ | |
| 42 | struct StructuredError { | |
| 43 | size_t offset_start; | |
| 44 | size_t offset_limit; | |
| 45 | std::string message; | |
| 46 | }; | |
| 47 | ||
| 48 | /** \brief Constructs a Reader allowing all features | |
| 49 | * for parsing. | |
| 50 | */ | |
| 51 | Reader(); | |
| 52 | ||
| 53 | /** \brief Constructs a Reader allowing the specified feature set | |
| 54 | * for parsing. | |
| 55 | */ | |
| 56 | Reader(const Features& features); | |
| 57 | ||
| 58 | /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> | |
| 59 | * document. | |
| 60 | * \param document UTF-8 encoded string containing the document to read. | |
| 61 | * \param root [out] Contains the root value of the document if it was | |
| 62 | * successfully parsed. | |
| 63 | * \param collectComments \c true to collect comment and allow writing them | |
| 64 | * back during | |
| 65 | * serialization, \c false to discard comments. | |
| 66 | * This parameter is ignored if | |
| 67 | * Features::allowComments_ | |
| 68 | * is \c false. | |
| 69 | * \return \c true if the document was successfully parsed, \c false if an | |
| 70 | * error occurred. | |
| 71 | */ | |
| 72 | bool | |
| 73 | parse(const std::string& document, Value& root, bool collectComments = true); | |
| 74 | ||
| 75 | /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> | |
| 76 | document. | |
| 77 | * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the | |
| 78 | document to read. | |
| 79 | * \param endDoc Pointer on the end of the UTF-8 encoded string of the | |
| 80 | document to read. | |
| 81 | \ Must be >= beginDoc. | |
| 82 | * \param root [out] Contains the root value of the document if it was | |
| 83 | * successfully parsed. | |
| 84 | * \param collectComments \c true to collect comment and allow writing them | |
| 85 | back during | |
| 86 | * serialization, \c false to discard comments. | |
| 87 | * This parameter is ignored if | |
| 88 | Features::allowComments_ | |
| 89 | * is \c false. | |
| 90 | * \return \c true if the document was successfully parsed, \c false if an | |
| 91 | error occurred. | |
| 92 | */ | |
| 93 | bool parse(const char* beginDoc, | |
| 94 | const char* endDoc, | |
| 95 | Value& root, | |
| 96 | bool collectComments = true); | |
| 97 | ||
| 98 | /// \brief Parse from input stream. | |
| 99 | /// \see Json::operator>>(std::istream&, Json::Value&). | |
| 100 | bool parse(std::istream& is, Value& root, bool collectComments = true); | |
| 101 | ||
| 102 | /** \brief Returns a user friendly string that list errors in the parsed | |
| 103 | * document. | |
| 104 | * \return Formatted error message with the list of errors with their location | |
| 105 | * in | |
| 106 | * the parsed document. An empty string is returned if no error | |
| 107 | * occurred | |
| 108 | * during parsing. | |
| 109 | * \deprecated Use getFormattedErrorMessages() instead (typo fix). | |
| 110 | */ | |
| 111 | JSONCPP_DEPRECATED("Use getFormattedErrorMessages instead") | |
| 112 | std::string getFormatedErrorMessages() const; | |
| 113 | ||
| 114 | /** \brief Returns a user friendly string that list errors in the parsed | |
| 115 | * document. | |
| 116 | * \return Formatted error message with the list of errors with their location | |
| 117 | * in | |
| 118 | * the parsed document. An empty string is returned if no error | |
| 119 | * occurred | |
| 120 | * during parsing. | |
| 121 | */ | |
| 122 | std::string getFormattedErrorMessages() const; | |
| 123 | ||
| 124 | /** \brief Returns a vector of structured erros encounted while parsing. | |
| 125 | * \return A (possibly empty) vector of StructuredError objects. Currently | |
| 126 | * only one error can be returned, but the caller should tolerate | |
| 127 | * multiple | |
| 128 | * errors. This can occur if the parser recovers from a non-fatal | |
| 129 | * parse error and then encounters additional errors. | |
| 130 | */ | |
| 131 | std::vector<StructuredError> getStructuredErrors() const; | |
| 132 | ||
| 133 | /** \brief Add a semantic error message. | |
| 134 | * \param value JSON Value location associated with the error | |
| 135 | * \param message The error message. | |
| 136 | * \return \c true if the error was successfully added, \c false if the | |
| 137 | * Value offset exceeds the document size. | |
| 138 | */ | |
| 139 | bool pushError(const Value& value, const std::string& message); | |
| 140 | ||
| 141 | /** \brief Add a semantic error message with extra context. | |
| 142 | * \param value JSON Value location associated with the error | |
| 143 | * \param message The error message. | |
| 144 | * \param extra Additional JSON Value location to contextualize the error | |
| 145 | * \return \c true if the error was successfully added, \c false if either | |
| 146 | * Value offset exceeds the document size. | |
| 147 | */ | |
| 148 | bool pushError(const Value& value, const std::string& message, const Value& extra); | |
| 149 | ||
| 150 | /** \brief Return whether there are any errors. | |
| 151 | * \return \c true if there are no errors to report \c false if | |
| 152 | * errors have occurred. | |
| 153 | */ | |
| 154 | bool good() const; | |
| 155 | ||
| 156 | private: | |
| 157 | enum TokenType { | |
| 158 | tokenEndOfStream = 0, | |
| 159 | tokenObjectBegin, | |
| 160 | tokenObjectEnd, | |
| 161 | tokenArrayBegin, | |
| 162 | tokenArrayEnd, | |
| 163 | tokenString, | |
| 164 | tokenNumber, | |
| 165 | tokenTrue, | |
| 166 | tokenFalse, | |
| 167 | tokenNull, | |
| 168 | tokenArraySeparator, | |
| 169 | tokenMemberSeparator, | |
| 170 | tokenComment, | |
| 171 | tokenError | |
| 172 | }; | |
| 173 | ||
| 174 | class Token { | |
| 175 | public: | |
| 176 | TokenType type_; | |
| 177 | Location start_; | |
| 178 | Location end_; | |
| 179 | }; | |
| 180 | ||
| 181 | class ErrorInfo { | |
| 182 | public: | |
| 183 | Token token_; | |
| 184 | std::string message_; | |
| 185 | Location extra_; | |
| 186 | }; | |
| 187 | ||
| 188 | typedef std::deque<ErrorInfo> Errors; | |
| 189 | ||
| 190 | bool expectToken(TokenType type, Token& token, const char* message); | |
| 191 | bool readToken(Token& token); | |
| 192 | void skipSpaces(); | |
| 193 | bool match(Location pattern, int patternLength); | |
| 194 | bool readComment(); | |
| 195 | bool readCStyleComment(); | |
| 196 | bool readCppStyleComment(); | |
| 197 | bool readString(); | |
| 198 | void readNumber(); | |
| 199 | bool readValue(); | |
| 200 | bool readObject(Token& token); | |
| 201 | bool readArray(Token& token); | |
| 202 | bool decodeNumber(Token& token); | |
| 203 | bool decodeNumber(Token& token, Value& decoded); | |
| 204 | bool decodeString(Token& token); | |
| 205 | bool decodeString(Token& token, std::string& decoded); | |
| 206 | bool decodeDouble(Token& token); | |
| 207 | bool decodeDouble(Token& token, Value& decoded); | |
| 208 | bool decodeUnicodeCodePoint(Token& token, | |
| 209 | Location& current, | |
| 210 | Location end, | |
| 211 | unsigned int& unicode); | |
| 212 | bool decodeUnicodeEscapeSequence(Token& token, | |
| 213 | Location& current, | |
| 214 | Location end, | |
| 215 | unsigned int& unicode); | |
| 216 | bool addError(const std::string& message, Token& token, Location extra = 0); | |
| 217 | bool recoverFromError(TokenType skipUntilToken); | |
| 218 | bool addErrorAndRecover(const std::string& message, | |
| 219 | Token& token, | |
| 220 | TokenType skipUntilToken); | |
| 221 | void skipUntilSpace(); | |
| 222 | Value& currentValue(); | |
| 223 | Char getNextChar(); | |
| 224 | void | |
| 225 | getLocationLineAndColumn(Location location, int& line, int& column) const; | |
| 226 | std::string getLocationLineAndColumn(Location location) const; | |
| 227 | void addComment(Location begin, Location end, CommentPlacement placement); | |
| 228 | void skipCommentTokens(Token& token); | |
| 229 | ||
| 230 | typedef std::stack<Value*> Nodes; | |
| 231 | Nodes nodes_; | |
| 232 | Errors errors_; | |
| 233 | std::string document_; | |
| 234 | Location begin_; | |
| 235 | Location end_; | |
| 236 | Location current_; | |
| 237 | Location lastValueEnd_; | |
| 238 | Value* lastValue_; | |
| 239 | std::string commentsBefore_; | |
| 240 | Features features_; | |
| 241 | bool collectComments_; | |
| 242 | }; | |
| 243 | ||
| 244 | /** \brief Read from 'sin' into 'root'. | |
| 245 | ||
| 246 | Always keep comments from the input JSON. | |
| 247 | ||
| 248 | This can be used to read a file into a particular sub-object. | |
| 249 | For example: | |
| 250 | \code | |
| 251 | Json::Value root; | |
| 252 | cin >> root["dir"]["file"]; | |
| 253 | cout << root; | |
| 254 | \endcode | |
| 255 | Result: | |
| 256 | \verbatim | |
| 257 | { | |
| 258 | "dir": { | |
| 259 | "file": { | |
| 260 | // The input stream JSON would be nested here. | |
| 261 | } | |
| 262 | } | |
| 263 | } | |
| 264 | \endverbatim | |
| 265 | \throw std::exception on parse error. | |
| 266 | \see Json::operator<<() | |
| 267 | */ | |
| 268 | JSON_API std::istream& operator>>(std::istream&, Value&); | |
| 269 | ||
| 270 | } // namespace Json | |
| 271 | ||
| 272 | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) | |
| 273 | #pragma warning(pop) | |
| 274 | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) | |
| 275 | ||
| 276 | #endif // CPPTL_JSON_READER_H_INCLUDED |
| r0 | r242831 | |
|---|---|---|
| 1 | // Copyright 2007-2010 Baptiste Lepilleur | |
| 2 | // Distributed under MIT license, or public domain if desired and | |
| 3 | // recognized in your jurisdiction. | |
| 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE | |
| 5 | ||
| 6 | #ifndef CPPTL_JSON_H_INCLUDED | |
| 7 | #define CPPTL_JSON_H_INCLUDED | |
| 8 | ||
| 9 | #if !defined(JSON_IS_AMALGAMATION) | |
| 10 | #include "forwards.h" | |
| 11 | #endif // if !defined(JSON_IS_AMALGAMATION) | |
| 12 | #include <string> | |
| 13 | #include <vector> | |
| 14 | ||
| 15 | #ifndef JSON_USE_CPPTL_SMALLMAP | |
| 16 | #include <map> | |
| 17 | #else | |
| 18 | #include <cpptl/smallmap.h> | |
| 19 | #endif | |
| 20 | #ifdef JSON_USE_CPPTL | |
| 21 | #include <cpptl/forwards.h> | |
| 22 | #endif | |
| 23 | ||
| 24 | // Disable warning C4251: <data member>: <type> needs to have dll-interface to | |
| 25 | // be used by... | |
| 26 | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) | |
| 27 | #pragma warning(push) | |
| 28 | #pragma warning(disable : 4251) | |
| 29 | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) | |
| 30 | ||
| 31 | /** \brief JSON (JavaScript Object Notation). | |
| 32 | */ | |
| 33 | namespace Json { | |
| 34 | ||
| 35 | /** \brief Type of the value held by a Value object. | |
| 36 | */ | |
| 37 | enum ValueType { | |
| 38 | nullValue = 0, ///< 'null' value | |
| 39 | intValue, ///< signed integer value | |
| 40 | uintValue, ///< unsigned integer value | |
| 41 | realValue, ///< double value | |
| 42 | stringValue, ///< UTF-8 string value | |
| 43 | booleanValue, ///< bool value | |
| 44 | arrayValue, ///< array value (ordered list) | |
| 45 | objectValue ///< object value (collection of name/value pairs). | |
| 46 | }; | |
| 47 | ||
| 48 | enum CommentPlacement { | |
| 49 | commentBefore = 0, ///< a comment placed on the line before a value | |
| 50 | commentAfterOnSameLine, ///< a comment just after a value on the same line | |
| 51 | commentAfter, ///< a comment on the line after a value (only make sense for | |
| 52 | /// root value) | |
| 53 | numberOfCommentPlacement | |
| 54 | }; | |
| 55 | ||
| 56 | //# ifdef JSON_USE_CPPTL | |
| 57 | // typedef CppTL::AnyEnumerator<const char *> EnumMemberNames; | |
| 58 | // typedef CppTL::AnyEnumerator<const Value &> EnumValues; | |
| 59 | //# endif | |
| 60 | ||
| 61 | /** \brief Lightweight wrapper to tag static string. | |
| 62 | * | |
| 63 | * Value constructor and objectValue member assignement takes advantage of the | |
| 64 | * StaticString and avoid the cost of string duplication when storing the | |
| 65 | * string or the member name. | |
| 66 | * | |
| 67 | * Example of usage: | |
| 68 | * \code | |
| 69 | * Json::Value aValue( StaticString("some text") ); | |
| 70 | * Json::Value object; | |
| 71 | * static const StaticString code("code"); | |
| 72 | * object[code] = 1234; | |
| 73 | * \endcode | |
| 74 | */ | |
| 75 | class JSON_API StaticString { | |
| 76 | public: | |
| 77 | explicit StaticString(const char* czstring) : str_(czstring) {} | |
| 78 | ||
| 79 | operator const char*() const { return str_; } | |
| 80 | ||
| 81 | const char* c_str() const { return str_; } | |
| 82 | ||
| 83 | private: | |
| 84 | const char* str_; | |
| 85 | }; | |
| 86 | ||
| 87 | /** \brief Represents a <a HREF="http://www.json.org">JSON</a> value. | |
| 88 | * | |
| 89 | * This class is a discriminated union wrapper that can represents a: | |
| 90 | * - signed integer [range: Value::minInt - Value::maxInt] | |
| 91 | * - unsigned integer (range: 0 - Value::maxUInt) | |
| 92 | * - double | |
| 93 | * - UTF-8 string | |
| 94 | * - boolean | |
| 95 | * - 'null' | |
| 96 | * - an ordered list of Value | |
| 97 | * - collection of name/value pairs (javascript object) | |
| 98 | * | |
| 99 | * The type of the held value is represented by a #ValueType and | |
| 100 | * can be obtained using type(). | |
| 101 | * | |
| 102 | * values of an #objectValue or #arrayValue can be accessed using operator[]() | |
| 103 | *methods. | |
| 104 | * Non const methods will automatically create the a #nullValue element | |
| 105 | * if it does not exist. | |
| 106 | * The sequence of an #arrayValue will be automatically resize and initialized | |
| 107 | * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue. | |
| 108 | * | |
| 109 | * The get() methods can be used to obtanis default value in the case the | |
| 110 | *required element | |
| 111 | * does not exist. | |
| 112 | * | |
| 113 | * It is possible to iterate over the list of a #objectValue values using | |
| 114 | * the getMemberNames() method. | |
| 115 | */ | |
| 116 | class JSON_API Value { | |
| 117 | friend class ValueIteratorBase; | |
| 118 | #ifdef JSON_VALUE_USE_INTERNAL_MAP | |
| 119 | friend class ValueInternalLink; | |
| 120 | friend class ValueInternalMap; | |
| 121 | #endif | |
| 122 | public: | |
| 123 | typedef std::vector<std::string> Members; | |
| 124 | typedef ValueIterator iterator; | |
| 125 | typedef ValueConstIterator const_iterator; | |
| 126 | typedef Json::UInt UInt; | |
| 127 | typedef Json::Int Int; | |
| 128 | #if defined(JSON_HAS_INT64) | |
| 129 | typedef Json::UInt64 UInt64; | |
| 130 | typedef Json::Int64 Int64; | |
| 131 | #endif // defined(JSON_HAS_INT64) | |
| 132 | typedef Json::LargestInt LargestInt; | |
| 133 | typedef Json::LargestUInt LargestUInt; | |
| 134 | typedef Json::ArrayIndex ArrayIndex; | |
| 135 | ||
| 136 | static const Value& null; | |
| 137 | /// Minimum signed integer value that can be stored in a Json::Value. | |
| 138 | static const LargestInt minLargestInt; | |
| 139 | /// Maximum signed integer value that can be stored in a Json::Value. | |
| 140 | static const LargestInt maxLargestInt; | |
| 141 | /// Maximum unsigned integer value that can be stored in a Json::Value. | |
| 142 | static const LargestUInt maxLargestUInt; | |
| 143 | ||
| 144 | /// Minimum signed int value that can be stored in a Json::Value. | |
| 145 | static const Int minInt; | |
| 146 | /// Maximum signed int value that can be stored in a Json::Value. | |
| 147 | static const Int maxInt; | |
| 148 | /// Maximum unsigned int value that can be stored in a Json::Value. | |
| 149 | static const UInt maxUInt; | |
| 150 | ||
| 151 | #if defined(JSON_HAS_INT64) | |
| 152 | /// Minimum signed 64 bits int value that can be stored in a Json::Value. | |
| 153 | static const Int64 minInt64; | |
| 154 | /// Maximum signed 64 bits int value that can be stored in a Json::Value. | |
| 155 | static const Int64 maxInt64; | |
| 156 | /// Maximum unsigned 64 bits int value that can be stored in a Json::Value. | |
| 157 | static const UInt64 maxUInt64; | |
| 158 | #endif // defined(JSON_HAS_INT64) | |
| 159 | ||
| 160 | private: | |
| 161 | #ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION | |
| 162 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 163 | class CZString { | |
| 164 | public: | |
| 165 | enum DuplicationPolicy { | |
| 166 | noDuplication = 0, | |
| 167 | duplicate, | |
| 168 | duplicateOnCopy | |
| 169 | }; | |
| 170 | CZString(ArrayIndex index); | |
| 171 | CZString(const char* cstr, DuplicationPolicy allocate); | |
| 172 | CZString(const CZString& other); | |
| 173 | ~CZString(); | |
| 174 | CZString& operator=(CZString other); | |
| 175 | bool operator<(const CZString& other) const; | |
| 176 | bool operator==(const CZString& other) const; | |
| 177 | ArrayIndex index() const; | |
| 178 | const char* c_str() const; | |
| 179 | bool isStaticString() const; | |
| 180 | ||
| 181 | private: | |
| 182 | void swap(CZString& other); | |
| 183 | const char* cstr_; | |
| 184 | ArrayIndex index_; | |
| 185 | }; | |
| 186 | ||
| 187 | public: | |
| 188 | #ifndef JSON_USE_CPPTL_SMALLMAP | |
| 189 | typedef std::map<CZString, Value> ObjectValues; | |
| 190 | #else | |
| 191 | typedef CppTL::SmallMap<CZString, Value> ObjectValues; | |
| 192 | #endif // ifndef JSON_USE_CPPTL_SMALLMAP | |
| 193 | #endif // ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 194 | #endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION | |
| 195 | ||
| 196 | public: | |
| 197 | /** \brief Create a default Value of the given type. | |
| 198 | ||
| 199 | This is a very useful constructor. | |
| 200 | To create an empty array, pass arrayValue. | |
| 201 | To create an empty object, pass objectValue. | |
| 202 | Another Value can then be set to this one by assignment. | |
| 203 | This is useful since clear() and resize() will not alter types. | |
| 204 | ||
| 205 | Examples: | |
| 206 | \code | |
| 207 | Json::Value null_value; // null | |
| 208 | Json::Value arr_value(Json::arrayValue); // [] | |
| 209 | Json::Value obj_value(Json::objectValue); // {} | |
| 210 | \endcode | |
| 211 | */ | |
| 212 | Value(ValueType type = nullValue); | |
| 213 | Value(Int value); | |
| 214 | Value(UInt value); | |
| 215 | #if defined(JSON_HAS_INT64) | |
| 216 | Value(Int64 value); | |
| 217 | Value(UInt64 value); | |
| 218 | #endif // if defined(JSON_HAS_INT64) | |
| 219 | Value(double value); | |
| 220 | Value(const char* value); | |
| 221 | Value(const char* beginValue, const char* endValue); | |
| 222 | /** \brief Constructs a value from a static string. | |
| 223 | ||
| 224 | * Like other value string constructor but do not duplicate the string for | |
| 225 | * internal storage. The given string must remain alive after the call to this | |
| 226 | * constructor. | |
| 227 | * Example of usage: | |
| 228 | * \code | |
| 229 | * Json::Value aValue( StaticString("some text") ); | |
| 230 | * \endcode | |
| 231 | */ | |
| 232 | Value(const StaticString& value); | |
| 233 | Value(const std::string& value); | |
| 234 | #ifdef JSON_USE_CPPTL | |
| 235 | Value(const CppTL::ConstString& value); | |
| 236 | #endif | |
| 237 | Value(bool value); | |
| 238 | Value(const Value& other); | |
| 239 | ~Value(); | |
| 240 | ||
| 241 | Value& operator=(Value other); | |
| 242 | /// Swap values. | |
| 243 | /// \note Currently, comments are intentionally not swapped, for | |
| 244 | /// both logic and efficiency. | |
| 245 | void swap(Value& other); | |
| 246 | ||
| 247 | ValueType type() const; | |
| 248 | ||
| 249 | bool operator<(const Value& other) const; | |
| 250 | bool operator<=(const Value& other) const; | |
| 251 | bool operator>=(const Value& other) const; | |
| 252 | bool operator>(const Value& other) const; | |
| 253 | ||
| 254 | bool operator==(const Value& other) const; | |
| 255 | bool operator!=(const Value& other) const; | |
| 256 | ||
| 257 | int compare(const Value& other) const; | |
| 258 | ||
| 259 | const char* asCString() const; | |
| 260 | std::string asString() const; | |
| 261 | #ifdef JSON_USE_CPPTL | |
| 262 | CppTL::ConstString asConstString() const; | |
| 263 | #endif | |
| 264 | Int asInt() const; | |
| 265 | UInt asUInt() const; | |
| 266 | #if defined(JSON_HAS_INT64) | |
| 267 | Int64 asInt64() const; | |
| 268 | UInt64 asUInt64() const; | |
| 269 | #endif // if defined(JSON_HAS_INT64) | |
| 270 | LargestInt asLargestInt() const; | |
| 271 | LargestUInt asLargestUInt() const; | |
| 272 | float asFloat() const; | |
| 273 | double asDouble() const; | |
| 274 | bool asBool() const; | |
| 275 | ||
| 276 | bool isNull() const; | |
| 277 | bool isBool() const; | |
| 278 | bool isInt() const; | |
| 279 | bool isInt64() const; | |
| 280 | bool isUInt() const; | |
| 281 | bool isUInt64() const; | |
| 282 | bool isIntegral() const; | |
| 283 | bool isDouble() const; | |
| 284 | bool isNumeric() const; | |
| 285 | bool isString() const; | |
| 286 | bool isArray() const; | |
| 287 | bool isObject() const; | |
| 288 | ||
| 289 | bool isConvertibleTo(ValueType other) const; | |
| 290 | ||
| 291 | /// Number of values in array or object | |
| 292 | ArrayIndex size() const; | |
| 293 | ||
| 294 | /// \brief Return true if empty array, empty object, or null; | |
| 295 | /// otherwise, false. | |
| 296 | bool empty() const; | |
| 297 | ||
| 298 | /// Return isNull() | |
| 299 | bool operator!() const; | |
| 300 | ||
| 301 | /// Remove all object members and array elements. | |
| 302 | /// \pre type() is arrayValue, objectValue, or nullValue | |
| 303 | /// \post type() is unchanged | |
| 304 | void clear(); | |
| 305 | ||
| 306 | /// Resize the array to size elements. | |
| 307 | /// New elements are initialized to null. | |
| 308 | /// May only be called on nullValue or arrayValue. | |
| 309 | /// \pre type() is arrayValue or nullValue | |
| 310 | /// \post type() is arrayValue | |
| 311 | void resize(ArrayIndex size); | |
| 312 | ||
| 313 | /// Access an array element (zero based index ). | |
| 314 | /// If the array contains less than index element, then null value are | |
| 315 | /// inserted | |
| 316 | /// in the array so that its size is index+1. | |
| 317 | /// (You may need to say 'value[0u]' to get your compiler to distinguish | |
| 318 | /// this from the operator[] which takes a string.) | |
| 319 | Value& operator[](ArrayIndex index); | |
| 320 | ||
| 321 | /// Access an array element (zero based index ). | |
| 322 | /// If the array contains less than index element, then null value are | |
| 323 | /// inserted | |
| 324 | /// in the array so that its size is index+1. | |
| 325 | /// (You may need to say 'value[0u]' to get your compiler to distinguish | |
| 326 | /// this from the operator[] which takes a string.) | |
| 327 | Value& operator[](int index); | |
| 328 | ||
| 329 | /// Access an array element (zero based index ) | |
| 330 | /// (You may need to say 'value[0u]' to get your compiler to distinguish | |
| 331 | /// this from the operator[] which takes a string.) | |
| 332 | const Value& operator[](ArrayIndex index) const; | |
| 333 | ||
| 334 | /// Access an array element (zero based index ) | |
| 335 | /// (You may need to say 'value[0u]' to get your compiler to distinguish | |
| 336 | /// this from the operator[] which takes a string.) | |
| 337 | const Value& operator[](int index) const; | |
| 338 | ||
| 339 | /// If the array contains at least index+1 elements, returns the element | |
| 340 | /// value, | |
| 341 | /// otherwise returns defaultValue. | |
| 342 | Value get(ArrayIndex index, const Value& defaultValue) const; | |
| 343 | /// Return true if index < size(). | |
| 344 | bool isValidIndex(ArrayIndex index) const; | |
| 345 | /// \brief Append value to array at the end. | |
| 346 | /// | |
| 347 | /// Equivalent to jsonvalue[jsonvalue.size()] = value; | |
| 348 | Value& append(const Value& value); | |
| 349 | ||
| 350 | /// Access an object value by name, create a null member if it does not exist. | |
| 351 | Value& operator[](const char* key); | |
| 352 | /// Access an object value by name, returns null if there is no member with | |
| 353 | /// that name. | |
| 354 | const Value& operator[](const char* key) const; | |
| 355 | /// Access an object value by name, create a null member if it does not exist. | |
| 356 | Value& operator[](const std::string& key); | |
| 357 | /// Access an object value by name, returns null if there is no member with | |
| 358 | /// that name. | |
| 359 | const Value& operator[](const std::string& key) const; | |
| 360 | /** \brief Access an object value by name, create a null member if it does not | |
| 361 | exist. | |
| 362 | ||
| 363 | * If the object as no entry for that name, then the member name used to store | |
| 364 | * the new entry is not duplicated. | |
| 365 | * Example of use: | |
| 366 | * \code | |
| 367 | * Json::Value object; | |
| 368 | * static const StaticString code("code"); | |
| 369 | * object[code] = 1234; | |
| 370 | * \endcode | |
| 371 | */ | |
| 372 | Value& operator[](const StaticString& key); | |
| 373 | #ifdef JSON_USE_CPPTL | |
| 374 | /// Access an object value by name, create a null member if it does not exist. | |
| 375 | Value& operator[](const CppTL::ConstString& key); | |
| 376 | /// Access an object value by name, returns null if there is no member with | |
| 377 | /// that name. | |
| 378 | const Value& operator[](const CppTL::ConstString& key) const; | |
| 379 | #endif | |
| 380 | /// Return the member named key if it exist, defaultValue otherwise. | |
| 381 | Value get(const char* key, const Value& defaultValue) const; | |
| 382 | /// Return the member named key if it exist, defaultValue otherwise. | |
| 383 | Value get(const std::string& key, const Value& defaultValue) const; | |
| 384 | #ifdef JSON_USE_CPPTL | |
| 385 | /// Return the member named key if it exist, defaultValue otherwise. | |
| 386 | Value get(const CppTL::ConstString& key, const Value& defaultValue) const; | |
| 387 | #endif | |
| 388 | /// \brief Remove and return the named member. | |
| 389 | /// | |
| 390 | /// Do nothing if it did not exist. | |
| 391 | /// \return the removed Value, or null. | |
| 392 | /// \pre type() is objectValue or nullValue | |
| 393 | /// \post type() is unchanged | |
| 394 | Value removeMember(const char* key); | |
| 395 | /// Same as removeMember(const char*) | |
| 396 | Value removeMember(const std::string& key); | |
| 397 | ||
| 398 | /// Return true if the object has a member named key. | |
| 399 | bool isMember(const char* key) const; | |
| 400 | /// Return true if the object has a member named key. | |
| 401 | bool isMember(const std::string& key) const; | |
| 402 | #ifdef JSON_USE_CPPTL | |
| 403 | /// Return true if the object has a member named key. | |
| 404 | bool isMember(const CppTL::ConstString& key) const; | |
| 405 | #endif | |
| 406 | ||
| 407 | /// \brief Return a list of the member names. | |
| 408 | /// | |
| 409 | /// If null, return an empty list. | |
| 410 | /// \pre type() is objectValue or nullValue | |
| 411 | /// \post if type() was nullValue, it remains nullValue | |
| 412 | Members getMemberNames() const; | |
| 413 | ||
| 414 | //# ifdef JSON_USE_CPPTL | |
| 415 | // EnumMemberNames enumMemberNames() const; | |
| 416 | // EnumValues enumValues() const; | |
| 417 | //# endif | |
| 418 | ||
| 419 | /// Comments must be //... or /* ... */ | |
| 420 | void setComment(const char* comment, CommentPlacement placement); | |
| 421 | /// Comments must be //... or /* ... */ | |
| 422 | void setComment(const std::string& comment, CommentPlacement placement); | |
| 423 | bool hasComment(CommentPlacement placement) const; | |
| 424 | /// Include delimiters and embedded newlines. | |
| 425 | std::string getComment(CommentPlacement placement) const; | |
| 426 | ||
| 427 | std::string toStyledString() const; | |
| 428 | ||
| 429 | const_iterator begin() const; | |
| 430 | const_iterator end() const; | |
| 431 | ||
| 432 | iterator begin(); | |
| 433 | iterator end(); | |
| 434 | ||
| 435 | // Accessors for the [start, limit) range of bytes within the JSON text from | |
| 436 | // which this value was parsed, if any. | |
| 437 | void setOffsetStart(size_t start); | |
| 438 | void setOffsetLimit(size_t limit); | |
| 439 | size_t getOffsetStart() const; | |
| 440 | size_t getOffsetLimit() const; | |
| 441 | ||
| 442 | private: | |
| 443 | void initBasic(ValueType type, bool allocated = false); | |
| 444 | ||
| 445 | Value& resolveReference(const char* key, bool isStatic); | |
| 446 | ||
| 447 | #ifdef JSON_VALUE_USE_INTERNAL_MAP | |
| 448 | inline bool isItemAvailable() const { return itemIsUsed_ == 0; } | |
| 449 | ||
| 450 | inline void setItemUsed(bool isUsed = true) { itemIsUsed_ = isUsed ? 1 : 0; } | |
| 451 | ||
| 452 | inline bool isMemberNameStatic() const { return memberNameIsStatic_ == 0; } | |
| 453 | ||
| 454 | inline void setMemberNameIsStatic(bool isStatic) { | |
| 455 | memberNameIsStatic_ = isStatic ? 1 : 0; | |
| 456 | } | |
| 457 | #endif // # ifdef JSON_VALUE_USE_INTERNAL_MAP | |
| 458 | ||
| 459 | private: | |
| 460 | struct CommentInfo { | |
| 461 | CommentInfo(); | |
| 462 | ~CommentInfo(); | |
| 463 | ||
| 464 | void setComment(const char* text); | |
| 465 | ||
| 466 | char* comment_; | |
| 467 | }; | |
| 468 | ||
| 469 | // struct MemberNamesTransform | |
| 470 | //{ | |
| 471 | // typedef const char *result_type; | |
| 472 | // const char *operator()( const CZString &name ) const | |
| 473 | // { | |
| 474 | // return name.c_str(); | |
| 475 | // } | |
| 476 | //}; | |
| 477 | ||
| 478 | union ValueHolder { | |
| 479 | LargestInt int_; | |
| 480 | LargestUInt uint_; | |
| 481 | double real_; | |
| 482 | bool bool_; | |
| 483 | char* string_; | |
| 484 | #ifdef JSON_VALUE_USE_INTERNAL_MAP | |
| 485 | ValueInternalArray* array_; | |
| 486 | ValueInternalMap* map_; | |
| 487 | #else | |
| 488 | ObjectValues* map_; | |
| 489 | #endif | |
| 490 | } value_; | |
| 491 | ValueType type_ : 8; | |
| 492 | int allocated_ : 1; // Notes: if declared as bool, bitfield is useless. | |
| 493 | #ifdef JSON_VALUE_USE_INTERNAL_MAP | |
| 494 | unsigned int itemIsUsed_ : 1; // used by the ValueInternalMap container. | |
| 495 | int memberNameIsStatic_ : 1; // used by the ValueInternalMap container. | |
| 496 | #endif | |
| 497 | CommentInfo* comments_; | |
| 498 | ||
| 499 | // [start, limit) byte offsets in the source JSON text from which this Value | |
| 500 | // was extracted. | |
| 501 | size_t start_; | |
| 502 | size_t limit_; | |
| 503 | }; | |
| 504 | ||
| 505 | /** \brief Experimental and untested: represents an element of the "path" to | |
| 506 | * access a node. | |
| 507 | */ | |
| 508 | class JSON_API PathArgument { | |
| 509 | public: | |
| 510 | friend class Path; | |
| 511 | ||
| 512 | PathArgument(); | |
| 513 | PathArgument(ArrayIndex index); | |
| 514 | PathArgument(const char* key); | |
| 515 | PathArgument(const std::string& key); | |
| 516 | ||
| 517 | private: | |
| 518 | enum Kind { | |
| 519 | kindNone = 0, | |
| 520 | kindIndex, | |
| 521 | kindKey | |
| 522 | }; | |
| 523 | std::string key_; | |
| 524 | ArrayIndex index_; | |
| 525 | Kind kind_; | |
| 526 | }; | |
| 527 | ||
| 528 | /** \brief Experimental and untested: represents a "path" to access a node. | |
| 529 | * | |
| 530 | * Syntax: | |
| 531 | * - "." => root node | |
| 532 | * - ".[n]" => elements at index 'n' of root node (an array value) | |
| 533 | * - ".name" => member named 'name' of root node (an object value) | |
| 534 | * - ".name1.name2.name3" | |
| 535 | * - ".[0][1][2].name1[3]" | |
| 536 | * - ".%" => member name is provided as parameter | |
| 537 | * - ".[%]" => index is provied as parameter | |
| 538 | */ | |
| 539 | class JSON_API Path { | |
| 540 | public: | |
| 541 | Path(const std::string& path, | |
| 542 | const PathArgument& a1 = PathArgument(), | |
| 543 | const PathArgument& a2 = PathArgument(), | |
| 544 | const PathArgument& a3 = PathArgument(), | |
| 545 | const PathArgument& a4 = PathArgument(), | |
| 546 | const PathArgument& a5 = PathArgument()); | |
| 547 | ||
| 548 | const Value& resolve(const Value& root) const; | |
| 549 | Value resolve(const Value& root, const Value& defaultValue) const; | |
| 550 | /// Creates the "path" to access the specified node and returns a reference on | |
| 551 | /// the node. | |
| 552 | Value& make(Value& root) const; | |
| 553 | ||
| 554 | private: | |
| 555 | typedef std::vector<const PathArgument*> InArgs; | |
| 556 | typedef std::vector<PathArgument> Args; | |
| 557 | ||
| 558 | void makePath(const std::string& path, const InArgs& in); | |
| 559 | void addPathInArg(const std::string& path, | |
| 560 | const InArgs& in, | |
| 561 | InArgs::const_iterator& itInArg, | |
| 562 | PathArgument::Kind kind); | |
| 563 | void invalidPath(const std::string& path, int location); | |
| 564 | ||
| 565 | Args args_; | |
| 566 | }; | |
| 567 | ||
| 568 | #ifdef JSON_VALUE_USE_INTERNAL_MAP | |
| 569 | /** \brief Allocator to customize Value internal map. | |
| 570 | * Below is an example of a simple implementation (default implementation | |
| 571 | actually | |
| 572 | * use memory pool for speed). | |
| 573 | * \code | |
| 574 | class DefaultValueMapAllocator : public ValueMapAllocator | |
| 575 | { | |
| 576 | public: // overridden from ValueMapAllocator | |
| 577 | virtual ValueInternalMap *newMap() | |
| 578 | { | |
| 579 | return new ValueInternalMap(); | |
| 580 | } | |
| 581 | ||
| 582 | virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) | |
| 583 | { | |
| 584 | return new ValueInternalMap( other ); | |
| 585 | } | |
| 586 | ||
| 587 | virtual void destructMap( ValueInternalMap *map ) | |
| 588 | { | |
| 589 | delete map; | |
| 590 | } | |
| 591 | ||
| 592 | virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) | |
| 593 | { | |
| 594 | return new ValueInternalLink[size]; | |
| 595 | } | |
| 596 | ||
| 597 | virtual void releaseMapBuckets( ValueInternalLink *links ) | |
| 598 | { | |
| 599 | delete [] links; | |
| 600 | } | |
| 601 | ||
| 602 | virtual ValueInternalLink *allocateMapLink() | |
| 603 | { | |
| 604 | return new ValueInternalLink(); | |
| 605 | } | |
| 606 | ||
| 607 | virtual void releaseMapLink( ValueInternalLink *link ) | |
| 608 | { | |
| 609 | delete link; | |
| 610 | } | |
| 611 | }; | |
| 612 | * \endcode | |
| 613 | */ | |
| 614 | class JSON_API ValueMapAllocator { | |
| 615 | public: | |
| 616 | virtual ~ValueMapAllocator(); | |
| 617 | virtual ValueInternalMap* newMap() = 0; | |
| 618 | virtual ValueInternalMap* newMapCopy(const ValueInternalMap& other) = 0; | |
| 619 | virtual void destructMap(ValueInternalMap* map) = 0; | |
| 620 | virtual ValueInternalLink* allocateMapBuckets(unsigned int size) = 0; | |
| 621 | virtual void releaseMapBuckets(ValueInternalLink* links) = 0; | |
| 622 | virtual ValueInternalLink* allocateMapLink() = 0; | |
| 623 | virtual void releaseMapLink(ValueInternalLink* link) = 0; | |
| 624 | }; | |
| 625 | ||
| 626 | /** \brief ValueInternalMap hash-map bucket chain link (for internal use only). | |
| 627 | * \internal previous_ & next_ allows for bidirectional traversal. | |
| 628 | */ | |
| 629 | class JSON_API ValueInternalLink { | |
| 630 | public: | |
| 631 | enum { | |
| 632 | itemPerLink = 6 | |
| 633 | }; // sizeof(ValueInternalLink) = 128 on 32 bits architecture. | |
| 634 | enum InternalFlags { | |
| 635 | flagAvailable = 0, | |
| 636 | flagUsed = 1 | |
| 637 | }; | |
| 638 | ||
| 639 | ValueInternalLink(); | |
| 640 | ||
| 641 | ~ValueInternalLink(); | |
| 642 | ||
| 643 | Value items_[itemPerLink]; | |
| 644 | char* keys_[itemPerLink]; | |
| 645 | ValueInternalLink* previous_; | |
| 646 | ValueInternalLink* next_; | |
| 647 | }; | |
| 648 | ||
| 649 | /** \brief A linked page based hash-table implementation used internally by | |
| 650 | *Value. | |
| 651 | * \internal ValueInternalMap is a tradional bucket based hash-table, with a | |
| 652 | *linked | |
| 653 | * list in each bucket to handle collision. There is an addional twist in that | |
| 654 | * each node of the collision linked list is a page containing a fixed amount of | |
| 655 | * value. This provides a better compromise between memory usage and speed. | |
| 656 | * | |
| 657 | * Each bucket is made up of a chained list of ValueInternalLink. The last | |
| 658 | * link of a given bucket can be found in the 'previous_' field of the following | |
| 659 | *bucket. | |
| 660 | * The last link of the last bucket is stored in tailLink_ as it has no | |
| 661 | *following bucket. | |
| 662 | * Only the last link of a bucket may contains 'available' item. The last link | |
| 663 | *always | |
| 664 | * contains at least one element unless is it the bucket one very first link. | |
| 665 | */ | |
| 666 | class JSON_API ValueInternalMap { | |
| 667 | friend class ValueIteratorBase; | |
| 668 | friend class Value; | |
| 669 | ||
| 670 | public: | |
| 671 | typedef unsigned int HashKey; | |
| 672 | typedef unsigned int BucketIndex; | |
| 673 | ||
| 674 | #ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION | |
| 675 | struct IteratorState { | |
| 676 | IteratorState() : map_(0), link_(0), itemIndex_(0), bucketIndex_(0) {} | |
| 677 | ValueInternalMap* map_; | |
| 678 | ValueInternalLink* link_; | |
| 679 | BucketIndex itemIndex_; | |
| 680 | BucketIndex bucketIndex_; | |
| 681 | }; | |
| 682 | #endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION | |
| 683 | ||
| 684 | ValueInternalMap(); | |
| 685 | ValueInternalMap(const ValueInternalMap& other); | |
| 686 | ValueInternalMap& operator=(ValueInternalMap other); | |
| 687 | ~ValueInternalMap(); | |
| 688 | ||
| 689 | void swap(ValueInternalMap& other); | |
| 690 | ||
| 691 | BucketIndex size() const; | |
| 692 | ||
| 693 | void clear(); | |
| 694 | ||
| 695 | bool reserveDelta(BucketIndex growth); | |
| 696 | ||
| 697 | bool reserve(BucketIndex newItemCount); | |
| 698 | ||
| 699 | const Value* find(const char* key) const; | |
| 700 | ||
| 701 | Value* find(const char* key); | |
| 702 | ||
| 703 | Value& resolveReference(const char* key, bool isStatic); | |
| 704 | ||
| 705 | void remove(const char* key); | |
| 706 | ||
| 707 | void doActualRemove(ValueInternalLink* link, | |
| 708 | BucketIndex index, | |
| 709 | BucketIndex bucketIndex); | |
| 710 | ||
| 711 | ValueInternalLink*& getLastLinkInBucket(BucketIndex bucketIndex); | |
| 712 | ||
| 713 | Value& setNewItem(const char* key, | |
| 714 | bool isStatic, | |
| 715 | ValueInternalLink* link, | |
| 716 | BucketIndex index); | |
| 717 | ||
| 718 | Value& unsafeAdd(const char* key, bool isStatic, HashKey hashedKey); | |
| 719 | ||
| 720 | HashKey hash(const char* key) const; | |
| 721 | ||
| 722 | int compare(const ValueInternalMap& other) const; | |
| 723 | ||
| 724 | private: | |
| 725 | void makeBeginIterator(IteratorState& it) const; | |
| 726 | void makeEndIterator(IteratorState& it) const; | |
| 727 | static bool equals(const IteratorState& x, const IteratorState& other); | |
| 728 | static void increment(IteratorState& iterator); | |
| 729 | static void incrementBucket(IteratorState& iterator); | |
| 730 | static void decrement(IteratorState& iterator); | |
| 731 | static const char* key(const IteratorState& iterator); | |
| 732 | static const char* key(const IteratorState& iterator, bool& isStatic); | |
| 733 | static Value& value(const IteratorState& iterator); | |
| 734 | static int distance(const IteratorState& x, const IteratorState& y); | |
| 735 | ||
| 736 | private: | |
| 737 | ValueInternalLink* buckets_; | |
| 738 | ValueInternalLink* tailLink_; | |
| 739 | BucketIndex bucketsSize_; | |
| 740 | BucketIndex itemCount_; | |
| 741 | }; | |
| 742 | ||
| 743 | /** \brief A simplified deque implementation used internally by Value. | |
| 744 | * \internal | |
| 745 | * It is based on a list of fixed "page", each page contains a fixed number of | |
| 746 | *items. | |
| 747 | * Instead of using a linked-list, a array of pointer is used for fast item | |
| 748 | *look-up. | |
| 749 | * Look-up for an element is as follow: | |
| 750 | * - compute page index: pageIndex = itemIndex / itemsPerPage | |
| 751 | * - look-up item in page: pages_[pageIndex][itemIndex % itemsPerPage] | |
| 752 | * | |
| 753 | * Insertion is amortized constant time (only the array containing the index of | |
| 754 | *pointers | |
| 755 | * need to be reallocated when items are appended). | |
| 756 | */ | |
| 757 | class JSON_API ValueInternalArray { | |
| 758 | friend class Value; | |
| 759 | friend class ValueIteratorBase; | |
| 760 | ||
| 761 | public: | |
| 762 | enum { | |
| 763 | itemsPerPage = 8 | |
| 764 | }; // should be a power of 2 for fast divide and modulo. | |
| 765 | typedef Value::ArrayIndex ArrayIndex; | |
| 766 | typedef unsigned int PageIndex; | |
| 767 | ||
| 768 | #ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION | |
| 769 | struct IteratorState // Must be a POD | |
| 770 | { | |
| 771 | IteratorState() : array_(0), currentPageIndex_(0), currentItemIndex_(0) {} | |
| 772 | ValueInternalArray* array_; | |
| 773 | Value** currentPageIndex_; | |
| 774 | unsigned int currentItemIndex_; | |
| 775 | }; | |
| 776 | #endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION | |
| 777 | ||
| 778 | ValueInternalArray(); | |
| 779 | ValueInternalArray(const ValueInternalArray& other); | |
| 780 | ValueInternalArray& operator=(ValueInternalArray other); | |
| 781 | ~ValueInternalArray(); | |
| 782 | void swap(ValueInternalArray& other); | |
| 783 | ||
| 784 | void clear(); | |
| 785 | void resize(ArrayIndex newSize); | |
| 786 | ||
| 787 | Value& resolveReference(ArrayIndex index); | |
| 788 | ||
| 789 | Value* find(ArrayIndex index) const; | |
| 790 | ||
| 791 | ArrayIndex size() const; | |
| 792 | ||
| 793 | int compare(const ValueInternalArray& other) const; | |
| 794 | ||
| 795 | private: | |
| 796 | static bool equals(const IteratorState& x, const IteratorState& other); | |
| 797 | static void increment(IteratorState& iterator); | |
| 798 | static void decrement(IteratorState& iterator); | |
| 799 | static Value& dereference(const IteratorState& iterator); | |
| 800 | static Value& unsafeDereference(const IteratorState& iterator); | |
| 801 | static int distance(const IteratorState& x, const IteratorState& y); | |
| 802 | static ArrayIndex indexOf(const IteratorState& iterator); | |
| 803 | void makeBeginIterator(IteratorState& it) const; | |
| 804 | void makeEndIterator(IteratorState& it) const; | |
| 805 | void makeIterator(IteratorState& it, ArrayIndex index) const; | |
| 806 | ||
| 807 | void makeIndexValid(ArrayIndex index); | |
| 808 | ||
| 809 | Value** pages_; | |
| 810 | ArrayIndex size_; | |
| 811 | PageIndex pageCount_; | |
| 812 | }; | |
| 813 | ||
| 814 | /** \brief Experimental: do not use. Allocator to customize Value internal | |
| 815 | array. | |
| 816 | * Below is an example of a simple implementation (actual implementation use | |
| 817 | * memory pool). | |
| 818 | \code | |
| 819 | class DefaultValueArrayAllocator : public ValueArrayAllocator | |
| 820 | { | |
| 821 | public: // overridden from ValueArrayAllocator | |
| 822 | virtual ~DefaultValueArrayAllocator() | |
| 823 | { | |
| 824 | } | |
| 825 | ||
| 826 | virtual ValueInternalArray *newArray() | |
| 827 | { | |
| 828 | return new ValueInternalArray(); | |
| 829 | } | |
| 830 | ||
| 831 | virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) | |
| 832 | { | |
| 833 | return new ValueInternalArray( other ); | |
| 834 | } | |
| 835 | ||
| 836 | virtual void destruct( ValueInternalArray *array ) | |
| 837 | { | |
| 838 | delete array; | |
| 839 | } | |
| 840 | ||
| 841 | virtual void reallocateArrayPageIndex( Value **&indexes, | |
| 842 | ValueInternalArray::PageIndex | |
| 843 | &indexCount, | |
| 844 | ValueInternalArray::PageIndex | |
| 845 | minNewIndexCount ) | |
| 846 | { | |
| 847 | ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1; | |
| 848 | if ( minNewIndexCount > newIndexCount ) | |
| 849 | newIndexCount = minNewIndexCount; | |
| 850 | void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount ); | |
| 851 | if ( !newIndexes ) | |
| 852 | throw std::bad_alloc(); | |
| 853 | indexCount = newIndexCount; | |
| 854 | indexes = static_cast<Value **>( newIndexes ); | |
| 855 | } | |
| 856 | virtual void releaseArrayPageIndex( Value **indexes, | |
| 857 | ValueInternalArray::PageIndex indexCount ) | |
| 858 | { | |
| 859 | if ( indexes ) | |
| 860 | free( indexes ); | |
| 861 | } | |
| 862 | ||
| 863 | virtual Value *allocateArrayPage() | |
| 864 | { | |
| 865 | return static_cast<Value *>( malloc( sizeof(Value) * | |
| 866 | ValueInternalArray::itemsPerPage ) ); | |
| 867 | } | |
| 868 | ||
| 869 | virtual void releaseArrayPage( Value *value ) | |
| 870 | { | |
| 871 | if ( value ) | |
| 872 | free( value ); | |
| 873 | } | |
| 874 | }; | |
| 875 | \endcode | |
| 876 | */ | |
| 877 | class JSON_API ValueArrayAllocator { | |
| 878 | public: | |
| 879 | virtual ~ValueArrayAllocator(); | |
| 880 | virtual ValueInternalArray* newArray() = 0; | |
| 881 | virtual ValueInternalArray* newArrayCopy(const ValueInternalArray& other) = 0; | |
| 882 | virtual void destructArray(ValueInternalArray* array) = 0; | |
| 883 | /** \brief Reallocate array page index. | |
| 884 | * Reallocates an array of pointer on each page. | |
| 885 | * \param indexes [input] pointer on the current index. May be \c NULL. | |
| 886 | * [output] pointer on the new index of at least | |
| 887 | * \a minNewIndexCount pages. | |
| 888 | * \param indexCount [input] current number of pages in the index. | |
| 889 | * [output] number of page the reallocated index can handle. | |
| 890 | * \b MUST be >= \a minNewIndexCount. | |
| 891 | * \param minNewIndexCount Minimum number of page the new index must be able | |
| 892 | * to | |
| 893 | * handle. | |
| 894 | */ | |
| 895 | virtual void | |
| 896 | reallocateArrayPageIndex(Value**& indexes, | |
| 897 | ValueInternalArray::PageIndex& indexCount, | |
| 898 | ValueInternalArray::PageIndex minNewIndexCount) = 0; | |
| 899 | virtual void | |
| 900 | releaseArrayPageIndex(Value** indexes, | |
| 901 | ValueInternalArray::PageIndex indexCount) = 0; | |
| 902 | virtual Value* allocateArrayPage() = 0; | |
| 903 | virtual void releaseArrayPage(Value* value) = 0; | |
| 904 | }; | |
| 905 | #endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP | |
| 906 | ||
| 907 | /** \brief base class for Value iterators. | |
| 908 | * | |
| 909 | */ | |
| 910 | class JSON_API ValueIteratorBase { | |
| 911 | public: | |
| 912 | typedef std::bidirectional_iterator_tag iterator_category; | |
| 913 | typedef unsigned int size_t; | |
| 914 | typedef int difference_type; | |
| 915 | typedef ValueIteratorBase SelfType; | |
| 916 | ||
| 917 | ValueIteratorBase(); | |
| 918 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 919 | explicit ValueIteratorBase(const Value::ObjectValues::iterator& current); | |
| 920 | #else | |
| 921 | ValueIteratorBase(const ValueInternalArray::IteratorState& state); | |
| 922 | ValueIteratorBase(const ValueInternalMap::IteratorState& state); | |
| 923 | #endif | |
| 924 | ||
| 925 | bool operator==(const SelfType& other) const { return isEqual(other); } | |
| 926 | ||
| 927 | bool operator!=(const SelfType& other) const { return !isEqual(other); } | |
| 928 | ||
| 929 | difference_type operator-(const SelfType& other) const { | |
| 930 | return computeDistance(other); | |
| 931 | } | |
| 932 | ||
| 933 | /// Return either the index or the member name of the referenced value as a | |
| 934 | /// Value. | |
| 935 | Value key() const; | |
| 936 | ||
| 937 | /// Return the index of the referenced Value. -1 if it is not an arrayValue. | |
| 938 | UInt index() const; | |
| 939 | ||
| 940 | /// Return the member name of the referenced Value. "" if it is not an | |
| 941 | /// objectValue. | |
| 942 | const char* memberName() const; | |
| 943 | ||
| 944 | protected: | |
| 945 | Value& deref() const; | |
| 946 | ||
| 947 | void increment(); | |
| 948 | ||
| 949 | void decrement(); | |
| 950 | ||
| 951 | difference_type computeDistance(const SelfType& other) const; | |
| 952 | ||
| 953 | bool isEqual(const SelfType& other) const; | |
| 954 | ||
| 955 | void copy(const SelfType& other); | |
| 956 | ||
| 957 | private: | |
| 958 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 959 | Value::ObjectValues::iterator current_; | |
| 960 | // Indicates that iterator is for a null value. | |
| 961 | bool isNull_; | |
| 962 | #else | |
| 963 | union { | |
| 964 | ValueInternalArray::IteratorState array_; | |
| 965 | ValueInternalMap::IteratorState map_; | |
| 966 | } iterator_; | |
| 967 | bool isArray_; | |
| 968 | #endif | |
| 969 | }; | |
| 970 | ||
| 971 | /** \brief const iterator for object and array value. | |
| 972 | * | |
| 973 | */ | |
| 974 | class JSON_API ValueConstIterator : public ValueIteratorBase { | |
| 975 | friend class Value; | |
| 976 | ||
| 977 | public: | |
| 978 | typedef const Value value_type; | |
| 979 | typedef unsigned int size_t; | |
| 980 | typedef int difference_type; | |
| 981 | typedef const Value& reference; | |
| 982 | typedef const Value* pointer; | |
| 983 | typedef ValueConstIterator SelfType; | |
| 984 | ||
| 985 | ValueConstIterator(); | |
| 986 | ||
| 987 | private: | |
| 988 | /*! \internal Use by Value to create an iterator. | |
| 989 | */ | |
| 990 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 991 | explicit ValueConstIterator(const Value::ObjectValues::iterator& current); | |
| 992 | #else | |
| 993 | ValueConstIterator(const ValueInternalArray::IteratorState& state); | |
| 994 | ValueConstIterator(const ValueInternalMap::IteratorState& state); | |
| 995 | #endif | |
| 996 | public: | |
| 997 | SelfType& operator=(const ValueIteratorBase& other); | |
| 998 | ||
| 999 | SelfType operator++(int) { | |
| 1000 | SelfType temp(*this); | |
| 1001 | ++*this; | |
| 1002 | return temp; | |
| 1003 | } | |
| 1004 | ||
| 1005 | SelfType operator--(int) { | |
| 1006 | SelfType temp(*this); | |
| 1007 | --*this; | |
| 1008 | return temp; | |
| 1009 | } | |
| 1010 | ||
| 1011 | SelfType& operator--() { | |
| 1012 | decrement(); | |
| 1013 | return *this; | |
| 1014 | } | |
| 1015 | ||
| 1016 | SelfType& operator++() { | |
| 1017 | increment(); | |
| 1018 | return *this; | |
| 1019 | } | |
| 1020 | ||
| 1021 | reference operator*() const { return deref(); } | |
| 1022 | ||
| 1023 | pointer operator->() const { return &deref(); } | |
| 1024 | }; | |
| 1025 | ||
| 1026 | /** \brief Iterator for object and array value. | |
| 1027 | */ | |
| 1028 | class JSON_API ValueIterator : public ValueIteratorBase { | |
| 1029 | friend class Value; | |
| 1030 | ||
| 1031 | public: | |
| 1032 | typedef Value value_type; | |
| 1033 | typedef unsigned int size_t; | |
| 1034 | typedef int difference_type; | |
| 1035 | typedef Value& reference; | |
| 1036 | typedef Value* pointer; | |
| 1037 | typedef ValueIterator SelfType; | |
| 1038 | ||
| 1039 | ValueIterator(); | |
| 1040 | ValueIterator(const ValueConstIterator& other); | |
| 1041 | ValueIterator(const ValueIterator& other); | |
| 1042 | ||
| 1043 | private: | |
| 1044 | /*! \internal Use by Value to create an iterator. | |
| 1045 | */ | |
| 1046 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 1047 | explicit ValueIterator(const Value::ObjectValues::iterator& current); | |
| 1048 | #else | |
| 1049 | ValueIterator(const ValueInternalArray::IteratorState& state); | |
| 1050 | ValueIterator(const ValueInternalMap::IteratorState& state); | |
| 1051 | #endif | |
| 1052 | public: | |
| 1053 | SelfType& operator=(const SelfType& other); | |
| 1054 | ||
| 1055 | SelfType operator++(int) { | |
| 1056 | SelfType temp(*this); | |
| 1057 | ++*this; | |
| 1058 | return temp; | |
| 1059 | } | |
| 1060 | ||
| 1061 | SelfType operator--(int) { | |
| 1062 | SelfType temp(*this); | |
| 1063 | --*this; | |
| 1064 | return temp; | |
| 1065 | } | |
| 1066 | ||
| 1067 | SelfType& operator--() { | |
| 1068 | decrement(); | |
| 1069 | return *this; | |
| 1070 | } | |
| 1071 | ||
| 1072 | SelfType& operator++() { | |
| 1073 | increment(); | |
| 1074 | return *this; | |
| 1075 | } | |
| 1076 | ||
| 1077 | reference operator*() const { return deref(); } | |
| 1078 | ||
| 1079 | pointer operator->() const { return &deref(); } | |
| 1080 | }; | |
| 1081 | ||
| 1082 | } // namespace Json | |
| 1083 | ||
| 1084 | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) | |
| 1085 | #pragma warning(pop) | |
| 1086 | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) | |
| 1087 | ||
| 1088 | #endif // CPPTL_JSON_H_INCLUDED |
| r0 | r242831 | |
|---|---|---|
| 1 | // DO NOT EDIT. This file is generated by CMake from "version" | |
| 2 | // and "version.h.in" files. | |
| 3 | // Run CMake configure step to update it. | |
| 4 | #ifndef JSON_VERSION_H_INCLUDED | |
| 5 | # define JSON_VERSION_H_INCLUDED | |
| 6 | ||
| 7 | # define JSONCPP_VERSION_STRING "1.1.0" | |
| 8 | # define JSONCPP_VERSION_MAJOR 1 | |
| 9 | # define JSONCPP_VERSION_MINOR 1 | |
| 10 | # define JSONCPP_VERSION_PATCH 0 | |
| 11 | # define JSONCPP_VERSION_QUALIFIER | |
| 12 | # define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8)) | |
| 13 | ||
| 14 | #endif // JSON_VERSION_H_INCLUDED |
| r0 | r242831 | |
|---|---|---|
| 1 | // Copyright 2007-2010 Baptiste Lepilleur | |
| 2 | // Distributed under MIT license, or public domain if desired and | |
| 3 | // recognized in your jurisdiction. | |
| 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE | |
| 5 | ||
| 6 | #ifndef JSON_WRITER_H_INCLUDED | |
| 7 | #define JSON_WRITER_H_INCLUDED | |
| 8 | ||
| 9 | #if !defined(JSON_IS_AMALGAMATION) | |
| 10 | #include "value.h" | |
| 11 | #endif // if !defined(JSON_IS_AMALGAMATION) | |
| 12 | #include <vector> | |
| 13 | #include <string> | |
| 14 | ||
| 15 | // Disable warning C4251: <data member>: <type> needs to have dll-interface to | |
| 16 | // be used by... | |
| 17 | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) | |
| 18 | #pragma warning(push) | |
| 19 | #pragma warning(disable : 4251) | |
| 20 | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) | |
| 21 | ||
| 22 | namespace Json { | |
| 23 | ||
| 24 | class Value; | |
| 25 | ||
| 26 | /** \brief Abstract class for writers. | |
| 27 | */ | |
| 28 | class JSON_API Writer { | |
| 29 | public: | |
| 30 | virtual ~Writer(); | |
| 31 | ||
| 32 | virtual std::string write(const Value& root) = 0; | |
| 33 | }; | |
| 34 | ||
| 35 | /** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format | |
| 36 | *without formatting (not human friendly). | |
| 37 | * | |
| 38 | * The JSON document is written in a single line. It is not intended for 'human' | |
| 39 | *consumption, | |
| 40 | * but may be usefull to support feature such as RPC where bandwith is limited. | |
| 41 | * \sa Reader, Value | |
| 42 | */ | |
| 43 | class JSON_API FastWriter : public Writer { | |
| 44 | public: | |
| 45 | FastWriter(); | |
| 46 | virtual ~FastWriter() {} | |
| 47 | ||
| 48 | void enableYAMLCompatibility(); | |
| 49 | ||
| 50 | /** \brief Drop the "null" string from the writer's output for nullValues. | |
| 51 | * Strictly speaking, this is not valid JSON. But when the output is being | |
| 52 | * fed to a browser's Javascript, it makes for smaller output and the | |
| 53 | * browser can handle the output just fine. | |
| 54 | */ | |
| 55 | void dropNullPlaceholders(); | |
| 56 | ||
| 57 | void omitEndingLineFeed(); | |
| 58 | ||
| 59 | public: // overridden from Writer | |
| 60 | virtual std::string write(const Value& root); | |
| 61 | ||
| 62 | private: | |
| 63 | void writeValue(const Value& value); | |
| 64 | ||
| 65 | std::string document_; | |
| 66 | bool yamlCompatiblityEnabled_; | |
| 67 | bool dropNullPlaceholders_; | |
| 68 | bool omitEndingLineFeed_; | |
| 69 | }; | |
| 70 | ||
| 71 | /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a | |
| 72 | *human friendly way. | |
| 73 | * | |
| 74 | * The rules for line break and indent are as follow: | |
| 75 | * - Object value: | |
| 76 | * - if empty then print {} without indent and line break | |
| 77 | * - if not empty the print '{', line break & indent, print one value per | |
| 78 | *line | |
| 79 | * and then unindent and line break and print '}'. | |
| 80 | * - Array value: | |
| 81 | * - if empty then print [] without indent and line break | |
| 82 | * - if the array contains no object value, empty array or some other value | |
| 83 | *types, | |
| 84 | * and all the values fit on one lines, then print the array on a single | |
| 85 | *line. | |
| 86 | * - otherwise, it the values do not fit on one line, or the array contains | |
| 87 | * object or non empty array, then print one value per line. | |
| 88 | * | |
| 89 | * If the Value have comments then they are outputed according to their | |
| 90 | *#CommentPlacement. | |
| 91 | * | |
| 92 | * \sa Reader, Value, Value::setComment() | |
| 93 | */ | |
| 94 | class JSON_API StyledWriter : public Writer { | |
| 95 | public: | |
| 96 | StyledWriter(); | |
| 97 | virtual ~StyledWriter() {} | |
| 98 | ||
| 99 | public: // overridden from Writer | |
| 100 | /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format. | |
| 101 | * \param root Value to serialize. | |
| 102 | * \return String containing the JSON document that represents the root value. | |
| 103 | */ | |
| 104 | virtual std::string write(const Value& root); | |
| 105 | ||
| 106 | private: | |
| 107 | void writeValue(const Value& value); | |
| 108 | void writeArrayValue(const Value& value); | |
| 109 | bool isMultineArray(const Value& value); | |
| 110 | void pushValue(const std::string& value); | |
| 111 | void writeIndent(); | |
| 112 | void writeWithIndent(const std::string& value); | |
| 113 | void indent(); | |
| 114 | void unindent(); | |
| 115 | void writeCommentBeforeValue(const Value& root); | |
| 116 | void writeCommentAfterValueOnSameLine(const Value& root); | |
| 117 | bool hasCommentForValue(const Value& value); | |
| 118 | static std::string normalizeEOL(const std::string& text); | |
| 119 | ||
| 120 | typedef std::vector<std::string> ChildValues; | |
| 121 | ||
| 122 | ChildValues childValues_; | |
| 123 | std::string document_; | |
| 124 | std::string indentString_; | |
| 125 | int rightMargin_; | |
| 126 | int indentSize_; | |
| 127 | bool addChildValues_; | |
| 128 | }; | |
| 129 | ||
| 130 | /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a | |
| 131 | human friendly way, | |
| 132 | to a stream rather than to a string. | |
| 133 | * | |
| 134 | * The rules for line break and indent are as follow: | |
| 135 | * - Object value: | |
| 136 | * - if empty then print {} without indent and line break | |
| 137 | * - if not empty the print '{', line break & indent, print one value per | |
| 138 | line | |
| 139 | * and then unindent and line break and print '}'. | |
| 140 | * - Array value: | |
| 141 | * - if empty then print [] without indent and line break | |
| 142 | * - if the array contains no object value, empty array or some other value | |
| 143 | types, | |
| 144 | * and all the values fit on one lines, then print the array on a single | |
| 145 | line. | |
| 146 | * - otherwise, it the values do not fit on one line, or the array contains | |
| 147 | * object or non empty array, then print one value per line. | |
| 148 | * | |
| 149 | * If the Value have comments then they are outputed according to their | |
| 150 | #CommentPlacement. | |
| 151 | * | |
| 152 | * \param indentation Each level will be indented by this amount extra. | |
| 153 | * \sa Reader, Value, Value::setComment() | |
| 154 | */ | |
| 155 | class JSON_API StyledStreamWriter { | |
| 156 | public: | |
| 157 | StyledStreamWriter(std::string indentation = "\t"); | |
| 158 | ~StyledStreamWriter() {} | |
| 159 | ||
| 160 | public: | |
| 161 | /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format. | |
| 162 | * \param out Stream to write to. (Can be ostringstream, e.g.) | |
| 163 | * \param root Value to serialize. | |
| 164 | * \note There is no point in deriving from Writer, since write() should not | |
| 165 | * return a value. | |
| 166 | */ | |
| 167 | void write(std::ostream& out, const Value& root); | |
| 168 | ||
| 169 | private: | |
| 170 | void writeValue(const Value& value); | |
| 171 | void writeArrayValue(const Value& value); | |
| 172 | bool isMultineArray(const Value& value); | |
| 173 | void pushValue(const std::string& value); | |
| 174 | void writeIndent(); | |
| 175 | void writeWithIndent(const std::string& value); | |
| 176 | void indent(); | |
| 177 | void unindent(); | |
| 178 | void writeCommentBeforeValue(const Value& root); | |
| 179 | void writeCommentAfterValueOnSameLine(const Value& root); | |
| 180 | bool hasCommentForValue(const Value& value); | |
| 181 | static std::string normalizeEOL(const std::string& text); | |
| 182 | ||
| 183 | typedef std::vector<std::string> ChildValues; | |
| 184 | ||
| 185 | ChildValues childValues_; | |
| 186 | std::ostream* document_; | |
| 187 | std::string indentString_; | |
| 188 | int rightMargin_; | |
| 189 | std::string indentation_; | |
| 190 | bool addChildValues_; | |
| 191 | }; | |
| 192 | ||
| 193 | #if defined(JSON_HAS_INT64) | |
| 194 | std::string JSON_API valueToString(Int value); | |
| 195 | std::string JSON_API valueToString(UInt value); | |
| 196 | #endif // if defined(JSON_HAS_INT64) | |
| 197 | std::string JSON_API valueToString(LargestInt value); | |
| 198 | std::string JSON_API valueToString(LargestUInt value); | |
| 199 | std::string JSON_API valueToString(double value); | |
| 200 | std::string JSON_API valueToString(bool value); | |
| 201 | std::string JSON_API valueToQuotedString(const char* value); | |
| 202 | ||
| 203 | /// \brief Output using the StyledStreamWriter. | |
| 204 | /// \see Json::operator>>() | |
| 205 | JSON_API std::ostream& operator<<(std::ostream&, const Value& root); | |
| 206 | ||
| 207 | } // namespace Json | |
| 208 | ||
| 209 | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) | |
| 210 | #pragma warning(pop) | |
| 211 | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) | |
| 212 | ||
| 213 | #endif // JSON_WRITER_H_INCLUDED |
| r0 | r242831 | |
|---|---|---|
| 1 |  | |
| 2 | Microsoft Visual Studio Solution File, Format Version 11.00 | |
| 3 | # Visual Studio 2010 | |
| 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lib_json", "lib_json.vcxproj", "{1E6C2C1C-6453-4129-AE3F-0EE8E6599C89}" | |
| 5 | EndProject | |
| 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jsontest", "jsontest.vcxproj", "{25AF2DD2-D396-4668-B188-488C33B8E620}" | |
| 7 | EndProject | |
| 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_lib_json", "test_lib_json.vcxproj", "{B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}" | |
| 9 | EndProject | |
| 10 | Global | |
| 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution | |
| 12 | Debug|Win32 = Debug|Win32 | |
| 13 | Debug|x64 = Debug|x64 | |
| 14 | Release|Win32 = Release|Win32 | |
| 15 | Release|x64 = Release|x64 | |
| 16 | EndGlobalSection | |
| 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution | |
| 18 | {1E6C2C1C-6453-4129-AE3F-0EE8E6599C89}.Debug|Win32.ActiveCfg = Debug|Win32 | |
| 19 | {1E6C2C1C-6453-4129-AE3F-0EE8E6599C89}.Debug|Win32.Build.0 = Debug|Win32 | |
| 20 | {1E6C2C1C-6453-4129-AE3F-0EE8E6599C89}.Debug|x64.ActiveCfg = Debug|x64 | |
| 21 | {1E6C2C1C-6453-4129-AE3F-0EE8E6599C89}.Debug|x64.Build.0 = Debug|x64 | |
| 22 | {1E6C2C1C-6453-4129-AE3F-0EE8E6599C89}.Release|Win32.ActiveCfg = Release|Win32 | |
| 23 | {1E6C2C1C-6453-4129-AE3F-0EE8E6599C89}.Release|Win32.Build.0 = Release|Win32 | |
| 24 | {1E6C2C1C-6453-4129-AE3F-0EE8E6599C89}.Release|x64.ActiveCfg = Release|x64 | |
| 25 | {1E6C2C1C-6453-4129-AE3F-0EE8E6599C89}.Release|x64.Build.0 = Release|x64 | |
| 26 | {25AF2DD2-D396-4668-B188-488C33B8E620}.Debug|Win32.ActiveCfg = Debug|Win32 | |
| 27 | {25AF2DD2-D396-4668-B188-488C33B8E620}.Debug|Win32.Build.0 = Debug|Win32 | |
| 28 | {25AF2DD2-D396-4668-B188-488C33B8E620}.Debug|x64.ActiveCfg = Debug|Win32 | |
| 29 | {25AF2DD2-D396-4668-B188-488C33B8E620}.Release|Win32.ActiveCfg = Release|Win32 | |
| 30 | {25AF2DD2-D396-4668-B188-488C33B8E620}.Release|Win32.Build.0 = Release|Win32 | |
| 31 | {25AF2DD2-D396-4668-B188-488C33B8E620}.Release|x64.ActiveCfg = Release|Win32 | |
| 32 | {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.Debug|Win32.ActiveCfg = Debug|Win32 | |
| 33 | {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.Debug|Win32.Build.0 = Debug|Win32 | |
| 34 | {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.Debug|x64.ActiveCfg = Debug|Win32 | |
| 35 | {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.Release|Win32.ActiveCfg = Release|Win32 | |
| 36 | {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.Release|Win32.Build.0 = Release|Win32 | |
| 37 | {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.Release|x64.ActiveCfg = Release|Win32 | |
| 38 | EndGlobalSection | |
| 39 | GlobalSection(SolutionProperties) = preSolution | |
| 40 | HideSolutionNode = FALSE | |
| 41 | EndGlobalSection | |
| 42 | EndGlobal |
| r0 | r242831 | |
|---|---|---|
| 1 | <?xml version="1.0" encoding="utf-8"?> | |
| 2 | <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |
| 3 | <ItemGroup Label="ProjectConfigurations"> | |
| 4 | <ProjectConfiguration Include="Debug|Win32"> | |
| 5 | <Configuration>Debug</Configuration> | |
| 6 | <Platform>Win32</Platform> | |
| 7 | </ProjectConfiguration> | |
| 8 | <ProjectConfiguration Include="Release|Win32"> | |
| 9 | <Configuration>Release</Configuration> | |
| 10 | <Platform>Win32</Platform> | |
| 11 | </ProjectConfiguration> | |
| 12 | </ItemGroup> | |
| 13 | <PropertyGroup Label="Globals"> | |
| 14 | <ProjectGuid>{25AF2DD2-D396-4668-B188-488C33B8E620}</ProjectGuid> | |
| 15 | <Keyword>Win32Proj</Keyword> | |
| 16 | </PropertyGroup> | |
| 17 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> | |
| 18 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> | |
| 19 | <ConfigurationType>Application</ConfigurationType> | |
| 20 | <CharacterSet>MultiByte</CharacterSet> | |
| 21 | </PropertyGroup> | |
| 22 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> | |
| 23 | <ConfigurationType>Application</ConfigurationType> | |
| 24 | <CharacterSet>MultiByte</CharacterSet> | |
| 25 | </PropertyGroup> | |
| 26 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> | |
| 27 | <ImportGroup Label="ExtensionSettings"> | |
| 28 | </ImportGroup> | |
| 29 | <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> | |
| 30 | <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | |
| 31 | </ImportGroup> | |
| 32 | <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets"> | |
| 33 | <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | |
| 34 | </ImportGroup> | |
| 35 | <PropertyGroup Label="UserMacros" /> | |
| 36 | <PropertyGroup> | |
| 37 | <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion> | |
| 38 | <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../build/vs71/debug/jsontest\</OutDir> | |
| 39 | <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../build/vs71/debug/jsontest\</IntDir> | |
| 40 | <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental> | |
| 41 | <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../build/vs71/release/jsontest\</OutDir> | |
| 42 | <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../build/vs71/release/jsontest\</IntDir> | |
| 43 | <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental> | |
| 44 | </PropertyGroup> | |
| 45 | <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> | |
| 46 | <ClCompile> | |
| 47 | <Optimization>Disabled</Optimization> | |
| 48 | <AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | |
| 49 | <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> | |
| 50 | <MinimalRebuild>true</MinimalRebuild> | |
| 51 | <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> | |
| 52 | <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> | |
| 53 | <PrecompiledHeader> | |
| 54 | </PrecompiledHeader> | |
| 55 | <WarningLevel>Level3</WarningLevel> | |
| 56 | <DebugInformationFormat>EditAndContinue</DebugInformationFormat> | |
| 57 | </ClCompile> | |
| 58 | <Link> | |
| 59 | <OutputFile>$(OutDir)jsontest.exe</OutputFile> | |
| 60 | <GenerateDebugInformation>true</GenerateDebugInformation> | |
| 61 | <ProgramDatabaseFile>$(OutDir)jsontest.pdb</ProgramDatabaseFile> | |
| 62 | <SubSystem>Console</SubSystem> | |
| 63 | <TargetMachine>MachineX86</TargetMachine> | |
| 64 | </Link> | |
| 65 | </ItemDefinitionGroup> | |
| 66 | <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> | |
| 67 | <ClCompile> | |
| 68 | <AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | |
| 69 | <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> | |
| 70 | <RuntimeLibrary>MultiThreaded</RuntimeLibrary> | |
| 71 | <PrecompiledHeader> | |
| 72 | </PrecompiledHeader> | |
| 73 | <WarningLevel>Level3</WarningLevel> | |
| 74 | <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> | |
| 75 | </ClCompile> | |
| 76 | <Link> | |
| 77 | <OutputFile>$(OutDir)jsontest.exe</OutputFile> | |
| 78 | <GenerateDebugInformation>true</GenerateDebugInformation> | |
| 79 | <SubSystem>Console</SubSystem> | |
| 80 | <OptimizeReferences>true</OptimizeReferences> | |
| 81 | <EnableCOMDATFolding>true</EnableCOMDATFolding> | |
| 82 | <TargetMachine>MachineX86</TargetMachine> | |
| 83 | </Link> | |
| 84 | </ItemDefinitionGroup> | |
| 85 | <ItemGroup> | |
| 86 | <ClCompile Include="..\..\src\jsontestrunner\main.cpp" /> | |
| 87 | </ItemGroup> | |
| 88 | <ItemGroup> | |
| 89 | <ProjectReference Include="lib_json.vcxproj"> | |
| 90 | <Project>{1e6c2c1c-6453-4129-ae3f-0ee8e6599c89}</Project> | |
| 91 | </ProjectReference> | |
| 92 | </ItemGroup> | |
| 93 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | |
| 94 | <ImportGroup Label="ExtensionTargets"> | |
| 95 | </ImportGroup> | |
| 96 | </Project> | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | <?xml version="1.0" encoding="utf-8"?> | |
| 2 | <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |
| 3 | <ItemGroup> | |
| 4 | <Filter Include="Source Files"> | |
| 5 | <UniqueIdentifier>{903591b3-ade3-4ce4-b1f9-1e175e62b014}</UniqueIdentifier> | |
| 6 | </Filter> | |
| 7 | </ItemGroup> | |
| 8 | <ItemGroup> | |
| 9 | <ClCompile Include="..\..\src\jsontestrunner\main.cpp"> | |
| 10 | <Filter>Source Files</Filter> | |
| 11 | </ClCompile> | |
| 12 | </ItemGroup> | |
| 13 | </Project> | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | <?xml version="1.0" encoding="utf-8"?> | |
| 2 | <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |
| 3 | <ItemGroup Label="ProjectConfigurations"> | |
| 4 | <ProjectConfiguration Include="Debug|Win32"> | |
| 5 | <Configuration>Debug</Configuration> | |
| 6 | <Platform>Win32</Platform> | |
| 7 | </ProjectConfiguration> | |
| 8 | <ProjectConfiguration Include="Debug|x64"> | |
| 9 | <Configuration>Debug</Configuration> | |
| 10 | <Platform>x64</Platform> | |
| 11 | </ProjectConfiguration> | |
| 12 | <ProjectConfiguration Include="Release|Win32"> | |
| 13 | <Configuration>Release</Configuration> | |
| 14 | <Platform>Win32</Platform> | |
| 15 | </ProjectConfiguration> | |
| 16 | <ProjectConfiguration Include="Release|x64"> | |
| 17 | <Configuration>Release</Configuration> | |
| 18 | <Platform>x64</Platform> | |
| 19 | </ProjectConfiguration> | |
| 20 | </ItemGroup> | |
| 21 | <ItemGroup> | |
| 22 | <ClCompile Include="..\..\src\lib_json\json_reader.cpp" /> | |
| 23 | <ClCompile Include="..\..\src\lib_json\json_value.cpp" /> | |
| 24 | <ClCompile Include="..\..\src\lib_json\json_writer.cpp" /> | |
| 25 | </ItemGroup> | |
| 26 | <ItemGroup> | |
| 27 | <ClInclude Include="..\..\include\json\reader.h" /> | |
| 28 | <ClInclude Include="..\..\include\json\value.h" /> | |
| 29 | <ClInclude Include="..\..\include\json\writer.h" /> | |
| 30 | </ItemGroup> | |
| 31 | <PropertyGroup Label="Globals"> | |
| 32 | <ProjectGuid>{1E6C2C1C-6453-4129-AE3F-0EE8E6599C89}</ProjectGuid> | |
| 33 | <Keyword>Win32Proj</Keyword> | |
| 34 | <RootNamespace>jsoncpp</RootNamespace> | |
| 35 | </PropertyGroup> | |
| 36 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> | |
| 37 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> | |
| 38 | <ConfigurationType>StaticLibrary</ConfigurationType> | |
| 39 | <UseDebugLibraries>true</UseDebugLibraries> | |
| 40 | <CharacterSet>Unicode</CharacterSet> | |
| 41 | </PropertyGroup> | |
| 42 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> | |
| 43 | <ConfigurationType>StaticLibrary</ConfigurationType> | |
| 44 | <UseDebugLibraries>true</UseDebugLibraries> | |
| 45 | <CharacterSet>Unicode</CharacterSet> | |
| 46 | </PropertyGroup> | |
| 47 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> | |
| 48 | <ConfigurationType>StaticLibrary</ConfigurationType> | |
| 49 | <UseDebugLibraries>false</UseDebugLibraries> | |
| 50 | <WholeProgramOptimization>true</WholeProgramOptimization> | |
| 51 | <CharacterSet>Unicode</CharacterSet> | |
| 52 | </PropertyGroup> | |
| 53 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> | |
| 54 | <ConfigurationType>StaticLibrary</ConfigurationType> | |
| 55 | <UseDebugLibraries>false</UseDebugLibraries> | |
| 56 | <WholeProgramOptimization>true</WholeProgramOptimization> | |
| 57 | <CharacterSet>Unicode</CharacterSet> | |
| 58 | </PropertyGroup> | |
| 59 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> | |
| 60 | <ImportGroup Label="ExtensionSettings"> | |
| 61 | </ImportGroup> | |
| 62 | <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> | |
| 63 | <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | |
| 64 | </ImportGroup> | |
| 65 | <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets"> | |
| 66 | <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | |
| 67 | </ImportGroup> | |
| 68 | <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> | |
| 69 | <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | |
| 70 | </ImportGroup> | |
| 71 | <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets"> | |
| 72 | <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | |
| 73 | </ImportGroup> | |
| 74 | <PropertyGroup Label="UserMacros" /> | |
| 75 | <PropertyGroup /> | |
| 76 | <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> | |
| 77 | <ClCompile> | |
| 78 | <PrecompiledHeader>NotUsing</PrecompiledHeader> | |
| 79 | <WarningLevel>Level3</WarningLevel> | |
| 80 | <Optimization>Disabled</Optimization> | |
| 81 | <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> | |
| 82 | <AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories> | |
| 83 | <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> | |
| 84 | </ClCompile> | |
| 85 | <Link> | |
| 86 | <SubSystem>Windows</SubSystem> | |
| 87 | <GenerateDebugInformation>true</GenerateDebugInformation> | |
| 88 | </Link> | |
| 89 | </ItemDefinitionGroup> | |
| 90 | <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> | |
| 91 | <ClCompile> | |
| 92 | <PrecompiledHeader>NotUsing</PrecompiledHeader> | |
| 93 | <WarningLevel>Level3</WarningLevel> | |
| 94 | <Optimization>Disabled</Optimization> | |
| 95 | <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> | |
| 96 | <AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories> | |
| 97 | <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> | |
| 98 | </ClCompile> | |
| 99 | <Link> | |
| 100 | <SubSystem>Windows</SubSystem> | |
| 101 | <GenerateDebugInformation>true</GenerateDebugInformation> | |
| 102 | </Link> | |
| 103 | </ItemDefinitionGroup> | |
| 104 | <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> | |
| 105 | <ClCompile> | |
| 106 | <WarningLevel>Level3</WarningLevel> | |
| 107 | <PrecompiledHeader>NotUsing</PrecompiledHeader> | |
| 108 | <Optimization>MaxSpeed</Optimization> | |
| 109 | <FunctionLevelLinking>true</FunctionLevelLinking> | |
| 110 | <IntrinsicFunctions>true</IntrinsicFunctions> | |
| 111 | <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> | |
| 112 | <AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories> | |
| 113 | <RuntimeLibrary>MultiThreaded</RuntimeLibrary> | |
| 114 | </ClCompile> | |
| 115 | <Link> | |
| 116 | <SubSystem>Windows</SubSystem> | |
| 117 | <GenerateDebugInformation>true</GenerateDebugInformation> | |
| 118 | <EnableCOMDATFolding>true</EnableCOMDATFolding> | |
| 119 | <OptimizeReferences>true</OptimizeReferences> | |
| 120 | </Link> | |
| 121 | </ItemDefinitionGroup> | |
| 122 | <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> | |
| 123 | <ClCompile> | |
| 124 | <WarningLevel>Level3</WarningLevel> | |
| 125 | <PrecompiledHeader>NotUsing</PrecompiledHeader> | |
| 126 | <Optimization>MaxSpeed</Optimization> | |
| 127 | <FunctionLevelLinking>true</FunctionLevelLinking> | |
| 128 | <IntrinsicFunctions>true</IntrinsicFunctions> | |
| 129 | <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> | |
| 130 | <AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories> | |
| 131 | <RuntimeLibrary>MultiThreaded</RuntimeLibrary> | |
| 132 | </ClCompile> | |
| 133 | <Link> | |
| 134 | <SubSystem>Windows</SubSystem> | |
| 135 | <GenerateDebugInformation>true</GenerateDebugInformation> | |
| 136 | <EnableCOMDATFolding>true</EnableCOMDATFolding> | |
| 137 | <OptimizeReferences>true</OptimizeReferences> | |
| 138 | </Link> | |
| 139 | </ItemDefinitionGroup> | |
| 140 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | |
| 141 | <ImportGroup Label="ExtensionTargets"> | |
| 142 | </ImportGroup> | |
| 143 | </Project> | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | <?xml version="1.0" encoding="utf-8"?> | |
| 2 | <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |
| 3 | <ItemGroup> | |
| 4 | <Filter Include="Header Files"> | |
| 5 | <UniqueIdentifier>{c110bc57-c46e-476c-97ea-84d8014f431c}</UniqueIdentifier> | |
| 6 | </Filter> | |
| 7 | <Filter Include="Source Files"> | |
| 8 | <UniqueIdentifier>{ed718592-5acf-47b5-8f2b-b8224590da6a}</UniqueIdentifier> | |
| 9 | </Filter> | |
| 10 | </ItemGroup> | |
| 11 | <ItemGroup> | |
| 12 | <ClCompile Include="..\..\src\lib_json\json_reader.cpp"> | |
| 13 | <Filter>Source Files</Filter> | |
| 14 | </ClCompile> | |
| 15 | <ClCompile Include="..\..\src\lib_json\json_value.cpp"> | |
| 16 | <Filter>Source Files</Filter> | |
| 17 | </ClCompile> | |
| 18 | <ClCompile Include="..\..\src\lib_json\json_writer.cpp"> | |
| 19 | <Filter>Source Files</Filter> | |
| 20 | </ClCompile> | |
| 21 | </ItemGroup> | |
| 22 | <ItemGroup> | |
| 23 | <ClInclude Include="..\..\include\json\reader.h"> | |
| 24 | <Filter>Header Files</Filter> | |
| 25 | </ClInclude> | |
| 26 | <ClInclude Include="..\..\include\json\value.h"> | |
| 27 | <Filter>Header Files</Filter> | |
| 28 | </ClInclude> | |
| 29 | <ClInclude Include="..\..\include\json\writer.h"> | |
| 30 | <Filter>Header Files</Filter> | |
| 31 | </ClInclude> | |
| 32 | </ItemGroup> | |
| 33 | </Project> | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | <?xml version="1.0" encoding="utf-8"?> | |
| 2 | <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |
| 3 | <ItemGroup Label="ProjectConfigurations"> | |
| 4 | <ProjectConfiguration Include="Debug|Win32"> | |
| 5 | <Configuration>Debug</Configuration> | |
| 6 | <Platform>Win32</Platform> | |
| 7 | </ProjectConfiguration> | |
| 8 | <ProjectConfiguration Include="Release|Win32"> | |
| 9 | <Configuration>Release</Configuration> | |
| 10 | <Platform>Win32</Platform> | |
| 11 | </ProjectConfiguration> | |
| 12 | </ItemGroup> | |
| 13 | <PropertyGroup Label="Globals"> | |
| 14 | <ProjectGuid>{B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}</ProjectGuid> | |
| 15 | <RootNamespace>test_lib_json</RootNamespace> | |
| 16 | <Keyword>Win32Proj</Keyword> | |
| 17 | </PropertyGroup> | |
| 18 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> | |
| 19 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> | |
| 20 | <ConfigurationType>Application</ConfigurationType> | |
| 21 | <CharacterSet>MultiByte</CharacterSet> | |
| 22 | </PropertyGroup> | |
| 23 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> | |
| 24 | <ConfigurationType>Application</ConfigurationType> | |
| 25 | <CharacterSet>MultiByte</CharacterSet> | |
| 26 | </PropertyGroup> | |
| 27 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> | |
| 28 | <ImportGroup Label="ExtensionSettings"> | |
| 29 | </ImportGroup> | |
| 30 | <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> | |
| 31 | <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | |
| 32 | </ImportGroup> | |
| 33 | <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets"> | |
| 34 | <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | |
| 35 | </ImportGroup> | |
| 36 | <PropertyGroup Label="UserMacros" /> | |
| 37 | <PropertyGroup> | |
| 38 | <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion> | |
| 39 | <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../build/vs71/debug/test_lib_json\</OutDir> | |
| 40 | <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../build/vs71/debug/test_lib_json\</IntDir> | |
| 41 | <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental> | |
| 42 | <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../build/vs71/release/test_lib_json\</OutDir> | |
| 43 | <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../build/vs71/release/test_lib_json\</IntDir> | |
| 44 | <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental> | |
| 45 | </PropertyGroup> | |
| 46 | <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> | |
| 47 | <ClCompile> | |
| 48 | <Optimization>Disabled</Optimization> | |
| 49 | <AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | |
| 50 | <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> | |
| 51 | <MinimalRebuild>true</MinimalRebuild> | |
| 52 | <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> | |
| 53 | <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> | |
| 54 | <PrecompiledHeader> | |
| 55 | </PrecompiledHeader> | |
| 56 | <WarningLevel>Level3</WarningLevel> | |
| 57 | <DebugInformationFormat>EditAndContinue</DebugInformationFormat> | |
| 58 | </ClCompile> | |
| 59 | <Link> | |
| 60 | <OutputFile>$(OutDir)test_lib_json.exe</OutputFile> | |
| 61 | <GenerateDebugInformation>true</GenerateDebugInformation> | |
| 62 | <ProgramDatabaseFile>$(OutDir)test_lib_json.pdb</ProgramDatabaseFile> | |
| 63 | <SubSystem>Console</SubSystem> | |
| 64 | <TargetMachine>MachineX86</TargetMachine> | |
| 65 | </Link> | |
| 66 | <PostBuildEvent> | |
| 67 | <Message>Running all unit tests</Message> | |
| 68 | <Command>$(TargetPath)</Command> | |
| 69 | </PostBuildEvent> | |
| 70 | </ItemDefinitionGroup> | |
| 71 | <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> | |
| 72 | <ClCompile> | |
| 73 | <AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | |
| 74 | <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> | |
| 75 | <RuntimeLibrary>MultiThreaded</RuntimeLibrary> | |
| 76 | <PrecompiledHeader> | |
| 77 | </PrecompiledHeader> | |
| 78 | <WarningLevel>Level3</WarningLevel> | |
| 79 | <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> | |
| 80 | </ClCompile> | |
| 81 | <Link> | |
| 82 | <OutputFile>$(OutDir)test_lib_json.exe</OutputFile> | |
| 83 | <GenerateDebugInformation>true</GenerateDebugInformation> | |
| 84 | <SubSystem>Console</SubSystem> | |
| 85 | <OptimizeReferences>true</OptimizeReferences> | |
| 86 | <EnableCOMDATFolding>true</EnableCOMDATFolding> | |
| 87 | <TargetMachine>MachineX86</TargetMachine> | |
| 88 | </Link> | |
| 89 | <PostBuildEvent> | |
| 90 | <Message>Running all unit tests</Message> | |
| 91 | <Command>$(TargetPath)</Command> | |
| 92 | </PostBuildEvent> | |
| 93 | </ItemDefinitionGroup> | |
| 94 | <ItemGroup> | |
| 95 | <ClCompile Include="..\..\src\test_lib_json\jsontest.cpp" /> | |
| 96 | <ClCompile Include="..\..\src\test_lib_json\main.cpp" /> | |
| 97 | </ItemGroup> | |
| 98 | <ItemGroup> | |
| 99 | <ClInclude Include="..\..\src\test_lib_json\jsontest.h" /> | |
| 100 | </ItemGroup> | |
| 101 | <ItemGroup> | |
| 102 | <ProjectReference Include="lib_json.vcxproj"> | |
| 103 | <Project>{1e6c2c1c-6453-4129-ae3f-0ee8e6599c89}</Project> | |
| 104 | </ProjectReference> | |
| 105 | </ItemGroup> | |
| 106 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | |
| 107 | <ImportGroup Label="ExtensionTargets"> | |
| 108 | </ImportGroup> | |
| 109 | </Project> | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | <?xml version="1.0" encoding="utf-8"?> | |
| 2 | <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |
| 3 | <ItemGroup> | |
| 4 | <ClCompile Include="..\..\src\test_lib_json\jsontest.cpp"> | |
| 5 | <Filter>Source Filter</Filter> | |
| 6 | </ClCompile> | |
| 7 | <ClCompile Include="..\..\src\test_lib_json\main.cpp"> | |
| 8 | <Filter>Source Filter</Filter> | |
| 9 | </ClCompile> | |
| 10 | </ItemGroup> | |
| 11 | <ItemGroup> | |
| 12 | <Filter Include="Source Filter"> | |
| 13 | <UniqueIdentifier>{bf40cbfc-8e98-40b4-b9f3-7e8d579cbae2}</UniqueIdentifier> | |
| 14 | </Filter> | |
| 15 | <Filter Include="Header Files"> | |
| 16 | <UniqueIdentifier>{5fd39074-89e6-4939-aa3f-694fefd296b1}</UniqueIdentifier> | |
| 17 | </Filter> | |
| 18 | </ItemGroup> | |
| 19 | <ItemGroup> | |
| 20 | <ClInclude Include="..\..\src\test_lib_json\jsontest.h"> | |
| 21 | <Filter>Header Files</Filter> | |
| 22 | </ClInclude> | |
| 23 | </ItemGroup> | |
| 24 | </Project> | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | Microsoft Visual Studio Solution File, Format Version 8.00 | |
| 2 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lib_json", "lib_json.vcproj", "{B84F7231-16CE-41D8-8C08-7B523FF4225B}" | |
| 3 | ProjectSection(ProjectDependencies) = postProject | |
| 4 | EndProjectSection | |
| 5 | EndProject | |
| 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jsontest", "jsontest.vcproj", "{25AF2DD2-D396-4668-B188-488C33B8E620}" | |
| 7 | ProjectSection(ProjectDependencies) = postProject | |
| 8 | {B84F7231-16CE-41D8-8C08-7B523FF4225B} = {B84F7231-16CE-41D8-8C08-7B523FF4225B} | |
| 9 | EndProjectSection | |
| 10 | EndProject | |
| 11 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_lib_json", "test_lib_json.vcproj", "{B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}" | |
| 12 | ProjectSection(ProjectDependencies) = postProject | |
| 13 | {B84F7231-16CE-41D8-8C08-7B523FF4225B} = {B84F7231-16CE-41D8-8C08-7B523FF4225B} | |
| 14 | EndProjectSection | |
| 15 | EndProject | |
| 16 | Global | |
| 17 | GlobalSection(SolutionConfiguration) = preSolution | |
| 18 | Debug = Debug | |
| 19 | dummy = dummy | |
| 20 | Release = Release | |
| 21 | EndGlobalSection | |
| 22 | GlobalSection(ProjectConfiguration) = postSolution | |
| 23 | {B84F7231-16CE-41D8-8C08-7B523FF4225B}.Debug.ActiveCfg = Debug|Win32 | |
| 24 | {B84F7231-16CE-41D8-8C08-7B523FF4225B}.Debug.Build.0 = Debug|Win32 | |
| 25 | {B84F7231-16CE-41D8-8C08-7B523FF4225B}.dummy.ActiveCfg = dummy|Win32 | |
| 26 | {B84F7231-16CE-41D8-8C08-7B523FF4225B}.dummy.Build.0 = dummy|Win32 | |
| 27 | {B84F7231-16CE-41D8-8C08-7B523FF4225B}.Release.ActiveCfg = Release|Win32 | |
| 28 | {B84F7231-16CE-41D8-8C08-7B523FF4225B}.Release.Build.0 = Release|Win32 | |
| 29 | {25AF2DD2-D396-4668-B188-488C33B8E620}.Debug.ActiveCfg = Debug|Win32 | |
| 30 | {25AF2DD2-D396-4668-B188-488C33B8E620}.Debug.Build.0 = Debug|Win32 | |
| 31 | {25AF2DD2-D396-4668-B188-488C33B8E620}.dummy.ActiveCfg = Debug|Win32 | |
| 32 | {25AF2DD2-D396-4668-B188-488C33B8E620}.dummy.Build.0 = Debug|Win32 | |
| 33 | {25AF2DD2-D396-4668-B188-488C33B8E620}.Release.ActiveCfg = Release|Win32 | |
| 34 | {25AF2DD2-D396-4668-B188-488C33B8E620}.Release.Build.0 = Release|Win32 | |
| 35 | {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.Debug.ActiveCfg = Debug|Win32 | |
| 36 | {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.Debug.Build.0 = Debug|Win32 | |
| 37 | {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.dummy.ActiveCfg = Debug|Win32 | |
| 38 | {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.dummy.Build.0 = Debug|Win32 | |
| 39 | {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.Release.ActiveCfg = Release|Win32 | |
| 40 | {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.Release.Build.0 = Release|Win32 | |
| 41 | EndGlobalSection | |
| 42 | GlobalSection(ExtensibilityGlobals) = postSolution | |
| 43 | EndGlobalSection | |
| 44 | GlobalSection(ExtensibilityAddIns) = postSolution | |
| 45 | EndGlobalSection | |
| 46 | EndGlobal |
| r0 | r242831 | |
|---|---|---|
| 1 | <?xml version="1.0" encoding="Windows-1252"?> | |
| 2 | <VisualStudioProject | |
| 3 | ProjectType="Visual C++" | |
| 4 | Version="7.10" | |
| 5 | Name="jsontest" | |
| 6 | ProjectGUID="{25AF2DD2-D396-4668-B188-488C33B8E620}" | |
| 7 | Keyword="Win32Proj"> | |
| 8 | <Platforms> | |
| 9 | <Platform | |
| 10 | Name="Win32"/> | |
| 11 | </Platforms> | |
| 12 | <Configurations> | |
| 13 | <Configuration | |
| 14 | Name="Debug|Win32" | |
| 15 | OutputDirectory="../../build/vs71/debug/jsontest" | |
| 16 | IntermediateDirectory="../../build/vs71/debug/jsontest" | |
| 17 | ConfigurationType="1" | |
| 18 | CharacterSet="2"> | |
| 19 | <Tool | |
| 20 | Name="VCCLCompilerTool" | |
| 21 | Optimization="0" | |
| 22 | AdditionalIncludeDirectories="../../include" | |
| 23 | PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" | |
| 24 | MinimalRebuild="TRUE" | |
| 25 | BasicRuntimeChecks="3" | |
| 26 | RuntimeLibrary="1" | |
| 27 | UsePrecompiledHeader="0" | |
| 28 | WarningLevel="3" | |
| 29 | Detect64BitPortabilityProblems="TRUE" | |
| 30 | DebugInformationFormat="4"/> | |
| 31 | <Tool | |
| 32 | Name="VCCustomBuildTool"/> | |
| 33 | <Tool | |
| 34 | Name="VCLinkerTool" | |
| 35 | OutputFile="$(OutDir)/jsontest.exe" | |
| 36 | LinkIncremental="2" | |
| 37 | GenerateDebugInformation="TRUE" | |
| 38 | ProgramDatabaseFile="$(OutDir)/jsontest.pdb" | |
| 39 | SubSystem="1" | |
| 40 | TargetMachine="1"/> | |
| 41 | <Tool | |
| 42 | Name="VCMIDLTool"/> | |
| 43 | <Tool | |
| 44 | Name="VCPostBuildEventTool"/> | |
| 45 | <Tool | |
| 46 | Name="VCPreBuildEventTool"/> | |
| 47 | <Tool | |
| 48 | Name="VCPreLinkEventTool"/> | |
| 49 | <Tool | |
| 50 | Name="VCResourceCompilerTool"/> | |
| 51 | <Tool | |
| 52 | Name="VCWebServiceProxyGeneratorTool"/> | |
| 53 | <Tool | |
| 54 | Name="VCXMLDataGeneratorTool"/> | |
| 55 | <Tool | |
| 56 | Name="VCWebDeploymentTool"/> | |
| 57 | <Tool | |
| 58 | Name="VCManagedWrapperGeneratorTool"/> | |
| 59 | <Tool | |
| 60 | Name="VCAuxiliaryManagedWrapperGeneratorTool"/> | |
| 61 | </Configuration> | |
| 62 | <Configuration | |
| 63 | Name="Release|Win32" | |
| 64 | OutputDirectory="../../build/vs71/release/jsontest" | |
| 65 | IntermediateDirectory="../../build/vs71/release/jsontest" | |
| 66 | ConfigurationType="1" | |
| 67 | CharacterSet="2"> | |
| 68 | <Tool | |
| 69 | Name="VCCLCompilerTool" | |
| 70 | AdditionalIncludeDirectories="../../include" | |
| 71 | PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE" | |
| 72 | RuntimeLibrary="0" | |
| 73 | UsePrecompiledHeader="0" | |
| 74 | WarningLevel="3" | |
| 75 | Detect64BitPortabilityProblems="TRUE" | |
| 76 | DebugInformationFormat="3"/> | |
| 77 | <Tool | |
| 78 | Name="VCCustomBuildTool"/> | |
| 79 | <Tool | |
| 80 | Name="VCLinkerTool" | |
| 81 | OutputFile="$(OutDir)/jsontest.exe" | |
| 82 | LinkIncremental="1" | |
| 83 | GenerateDebugInformation="TRUE" | |
| 84 | SubSystem="1" | |
| 85 | OptimizeReferences="2" | |
| 86 | EnableCOMDATFolding="2" | |
| 87 | TargetMachine="1"/> | |
| 88 | <Tool | |
| 89 | Name="VCMIDLTool"/> | |
| 90 | <Tool | |
| 91 | Name="VCPostBuildEventTool"/> | |
| 92 | <Tool | |
| 93 | Name="VCPreBuildEventTool"/> | |
| 94 | <Tool | |
| 95 | Name="VCPreLinkEventTool"/> | |
| 96 | <Tool | |
| 97 | Name="VCResourceCompilerTool"/> | |
| 98 | <Tool | |
| 99 | Name="VCWebServiceProxyGeneratorTool"/> | |
| 100 | <Tool | |
| 101 | Name="VCXMLDataGeneratorTool"/> | |
| 102 | <Tool | |
| 103 | Name="VCWebDeploymentTool"/> | |
| 104 | <Tool | |
| 105 | Name="VCManagedWrapperGeneratorTool"/> | |
| 106 | <Tool | |
| 107 | Name="VCAuxiliaryManagedWrapperGeneratorTool"/> | |
| 108 | </Configuration> | |
| 109 | </Configurations> | |
| 110 | <References> | |
| 111 | </References> | |
| 112 | <Files> | |
| 113 | <File | |
| 114 | RelativePath="..\..\src\jsontestrunner\main.cpp"> | |
| 115 | </File> | |
| 116 | </Files> | |
| 117 | <Globals> | |
| 118 | </Globals> | |
| 119 | </VisualStudioProject> |
| r0 | r242831 | |
|---|---|---|
| 1 | <?xml version="1.0" encoding="Windows-1252"?> | |
| 2 | <VisualStudioProject | |
| 3 | ProjectType="Visual C++" | |
| 4 | Version="7.10" | |
| 5 | Name="lib_json" | |
| 6 | ProjectGUID="{B84F7231-16CE-41D8-8C08-7B523FF4225B}" | |
| 7 | Keyword="Win32Proj"> | |
| 8 | <Platforms> | |
| 9 | <Platform | |
| 10 | Name="Win32"/> | |
| 11 | </Platforms> | |
| 12 | <Configurations> | |
| 13 | <Configuration | |
| 14 | Name="Debug|Win32" | |
| 15 | OutputDirectory="../../build/vs71/debug/lib_json" | |
| 16 | IntermediateDirectory="../../build/vs71/debug/lib_json" | |
| 17 | ConfigurationType="4" | |
| 18 | CharacterSet="2"> | |
| 19 | <Tool | |
| 20 | Name="VCCLCompilerTool" | |
| 21 | Optimization="0" | |
| 22 | AdditionalIncludeDirectories="../../include" | |
| 23 | PreprocessorDefinitions="WIN32;_DEBUG;_LIB" | |
| 24 | StringPooling="TRUE" | |
| 25 | MinimalRebuild="TRUE" | |
| 26 | BasicRuntimeChecks="3" | |
| 27 | RuntimeLibrary="1" | |
| 28 | EnableFunctionLevelLinking="TRUE" | |
| 29 | DisableLanguageExtensions="TRUE" | |
| 30 | ForceConformanceInForLoopScope="FALSE" | |
| 31 | RuntimeTypeInfo="TRUE" | |
| 32 | UsePrecompiledHeader="0" | |
| 33 | WarningLevel="3" | |
| 34 | Detect64BitPortabilityProblems="TRUE" | |
| 35 | DebugInformationFormat="4"/> | |
| 36 | <Tool | |
| 37 | Name="VCCustomBuildTool"/> | |
| 38 | <Tool | |
| 39 | Name="VCLibrarianTool" | |
| 40 | OutputFile="$(OutDir)/json_vc71_libmtd.lib"/> | |
| 41 | <Tool | |
| 42 | Name="VCMIDLTool"/> | |
| 43 | <Tool | |
| 44 | Name="VCPostBuildEventTool"/> | |
| 45 | <Tool | |
| 46 | Name="VCPreBuildEventTool"/> | |
| 47 | <Tool | |
| 48 | Name="VCPreLinkEventTool"/> | |
| 49 | <Tool | |
| 50 | Name="VCResourceCompilerTool"/> | |
| 51 | <Tool | |
| 52 | Name="VCWebServiceProxyGeneratorTool"/> | |
| 53 | <Tool | |
| 54 | Name="VCXMLDataGeneratorTool"/> | |
| 55 | <Tool | |
| 56 | Name="VCManagedWrapperGeneratorTool"/> | |
| 57 | <Tool | |
| 58 | Name="VCAuxiliaryManagedWrapperGeneratorTool"/> | |
| 59 | </Configuration> | |
| 60 | <Configuration | |
| 61 | Name="Release|Win32" | |
| 62 | OutputDirectory="../../build/vs71/release/lib_json" | |
| 63 | IntermediateDirectory="../../build/vs71/release/lib_json" | |
| 64 | ConfigurationType="4" | |
| 65 | CharacterSet="2" | |
| 66 | WholeProgramOptimization="TRUE"> | |
| 67 | <Tool | |
| 68 | Name="VCCLCompilerTool" | |
| 69 | GlobalOptimizations="TRUE" | |
| 70 | EnableIntrinsicFunctions="TRUE" | |
| 71 | AdditionalIncludeDirectories="../../include" | |
| 72 | PreprocessorDefinitions="WIN32;NDEBUG;_LIB" | |
| 73 | StringPooling="TRUE" | |
| 74 | RuntimeLibrary="0" | |
| 75 | EnableFunctionLevelLinking="TRUE" | |
| 76 | DisableLanguageExtensions="TRUE" | |
| 77 | ForceConformanceInForLoopScope="FALSE" | |
| 78 | RuntimeTypeInfo="TRUE" | |
| 79 | UsePrecompiledHeader="0" | |
| 80 | AssemblerOutput="4" | |
| 81 | WarningLevel="3" | |
| 82 | Detect64BitPortabilityProblems="TRUE" | |
| 83 | DebugInformationFormat="3"/> | |
| 84 | <Tool | |
| 85 | Name="VCCustomBuildTool"/> | |
| 86 | <Tool | |
| 87 | Name="VCLibrarianTool" | |
| 88 | OutputFile="$(OutDir)/json_vc71_libmt.lib"/> | |
| 89 | <Tool | |
| 90 | Name="VCMIDLTool"/> | |
| 91 | <Tool | |
| 92 | Name="VCPostBuildEventTool"/> | |
| 93 | <Tool | |
| 94 | Name="VCPreBuildEventTool"/> | |
| 95 | <Tool | |
| 96 | Name="VCPreLinkEventTool"/> | |
| 97 | <Tool | |
| 98 | Name="VCResourceCompilerTool"/> | |
| 99 | <Tool | |
| 100 | Name="VCWebServiceProxyGeneratorTool"/> | |
| 101 | <Tool | |
| 102 | Name="VCXMLDataGeneratorTool"/> | |
| 103 | <Tool | |
| 104 | Name="VCManagedWrapperGeneratorTool"/> | |
| 105 | <Tool | |
| 106 | Name="VCAuxiliaryManagedWrapperGeneratorTool"/> | |
| 107 | </Configuration> | |
| 108 | <Configuration | |
| 109 | Name="dummy|Win32" | |
| 110 | OutputDirectory="$(ConfigurationName)" | |
| 111 | IntermediateDirectory="$(ConfigurationName)" | |
| 112 | ConfigurationType="2" | |
| 113 | CharacterSet="2" | |
| 114 | WholeProgramOptimization="TRUE"> | |
| 115 | <Tool | |
| 116 | Name="VCCLCompilerTool" | |
| 117 | GlobalOptimizations="TRUE" | |
| 118 | EnableIntrinsicFunctions="TRUE" | |
| 119 | AdditionalIncludeDirectories="../../include" | |
| 120 | PreprocessorDefinitions="WIN32;NDEBUG;_LIB" | |
| 121 | StringPooling="TRUE" | |
| 122 | RuntimeLibrary="4" | |
| 123 | EnableFunctionLevelLinking="TRUE" | |
| 124 | DisableLanguageExtensions="TRUE" | |
| 125 | ForceConformanceInForLoopScope="FALSE" | |
| 126 | RuntimeTypeInfo="TRUE" | |
| 127 | UsePrecompiledHeader="0" | |
| 128 | AssemblerOutput="4" | |
| 129 | WarningLevel="3" | |
| 130 | Detect64BitPortabilityProblems="TRUE" | |
| 131 | DebugInformationFormat="3"/> | |
| 132 | <Tool | |
| 133 | Name="VCCustomBuildTool"/> | |
| 134 | <Tool | |
| 135 | Name="VCLinkerTool" | |
| 136 | GenerateDebugInformation="TRUE" | |
| 137 | SubSystem="2" | |
| 138 | OptimizeReferences="2" | |
| 139 | EnableCOMDATFolding="2" | |
| 140 | TargetMachine="1"/> | |
| 141 | <Tool | |
| 142 | Name="VCMIDLTool"/> | |
| 143 | <Tool | |
| 144 | Name="VCPostBuildEventTool"/> | |
| 145 | <Tool | |
| 146 | Name="VCPreBuildEventTool"/> | |
| 147 | <Tool | |
| 148 | Name="VCPreLinkEventTool"/> | |
| 149 | <Tool | |
| 150 | Name="VCResourceCompilerTool"/> | |
| 151 | <Tool | |
| 152 | Name="VCWebServiceProxyGeneratorTool"/> | |
| 153 | <Tool | |
| 154 | Name="VCXMLDataGeneratorTool"/> | |
| 155 | <Tool | |
| 156 | Name="VCWebDeploymentTool"/> | |
| 157 | <Tool | |
| 158 | Name="VCManagedWrapperGeneratorTool"/> | |
| 159 | <Tool | |
| 160 | Name="VCAuxiliaryManagedWrapperGeneratorTool"/> | |
| 161 | </Configuration> | |
| 162 | </Configurations> | |
| 163 | <References> | |
| 164 | </References> | |
| 165 | <Files> | |
| 166 | <File | |
| 167 | RelativePath="..\..\include\json\autolink.h"> | |
| 168 | </File> | |
| 169 | <File | |
| 170 | RelativePath="..\..\include\json\config.h"> | |
| 171 | </File> | |
| 172 | <File | |
| 173 | RelativePath="..\..\include\json\features.h"> | |
| 174 | </File> | |
| 175 | <File | |
| 176 | RelativePath="..\..\include\json\forwards.h"> | |
| 177 | </File> | |
| 178 | <File | |
| 179 | RelativePath="..\..\include\json\json.h"> | |
| 180 | </File> | |
| 181 | <File | |
| 182 | RelativePath="..\..\src\lib_json\json_batchallocator.h"> | |
| 183 | </File> | |
| 184 | <File | |
| 185 | RelativePath="..\..\src\lib_json\json_internalarray.inl"> | |
| 186 | </File> | |
| 187 | <File | |
| 188 | RelativePath="..\..\src\lib_json\json_internalmap.inl"> | |
| 189 | </File> | |
| 190 | <File | |
| 191 | RelativePath="..\..\src\lib_json\json_reader.cpp"> | |
| 192 | </File> | |
| 193 | <File | |
| 194 | RelativePath="..\..\src\lib_json\json_value.cpp"> | |
| 195 | </File> | |
| 196 | <File | |
| 197 | RelativePath="..\..\src\lib_json\json_valueiterator.inl"> | |
| 198 | </File> | |
| 199 | <File | |
| 200 | RelativePath="..\..\src\lib_json\json_writer.cpp"> | |
| 201 | </File> | |
| 202 | <File | |
| 203 | RelativePath="..\..\include\json\reader.h"> | |
| 204 | </File> | |
| 205 | <File | |
| 206 | RelativePath="..\..\include\json\value.h"> | |
| 207 | </File> | |
| 208 | <File | |
| 209 | RelativePath="..\..\include\json\writer.h"> | |
| 210 | </File> | |
| 211 | </Files> | |
| 212 | <Globals> | |
| 213 | </Globals> | |
| 214 | </VisualStudioProject> |
| r0 | r242831 | |
|---|---|---|
| 1 | <?xml version="1.0" encoding="Windows-1252"?> | |
| 2 | <VisualStudioProject | |
| 3 | ProjectType="Visual C++" | |
| 4 | Version="7.10" | |
| 5 | Name="test_lib_json" | |
| 6 | ProjectGUID="{B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}" | |
| 7 | RootNamespace="test_lib_json" | |
| 8 | Keyword="Win32Proj"> | |
| 9 | <Platforms> | |
| 10 | <Platform | |
| 11 | Name="Win32"/> | |
| 12 | </Platforms> | |
| 13 | <Configurations> | |
| 14 | <Configuration | |
| 15 | Name="Debug|Win32" | |
| 16 | OutputDirectory="../../build/vs71/debug/test_lib_json" | |
| 17 | IntermediateDirectory="../../build/vs71/debug/test_lib_json" | |
| 18 | ConfigurationType="1" | |
| 19 | CharacterSet="2"> | |
| 20 | <Tool | |
| 21 | Name="VCCLCompilerTool" | |
| 22 | Optimization="0" | |
| 23 | AdditionalIncludeDirectories="../../include" | |
| 24 | PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" | |
| 25 | MinimalRebuild="TRUE" | |
| 26 | BasicRuntimeChecks="3" | |
| 27 | RuntimeLibrary="1" | |
| 28 | UsePrecompiledHeader="0" | |
| 29 | WarningLevel="3" | |
| 30 | Detect64BitPortabilityProblems="TRUE" | |
| 31 | DebugInformationFormat="4"/> | |
| 32 | <Tool | |
| 33 | Name="VCCustomBuildTool"/> | |
| 34 | <Tool | |
| 35 | Name="VCLinkerTool" | |
| 36 | OutputFile="$(OutDir)/test_lib_json.exe" | |
| 37 | LinkIncremental="2" | |
| 38 | GenerateDebugInformation="TRUE" | |
| 39 | ProgramDatabaseFile="$(OutDir)/test_lib_json.pdb" | |
| 40 | SubSystem="1" | |
| 41 | TargetMachine="1"/> | |
| 42 | <Tool | |
| 43 | Name="VCMIDLTool"/> | |
| 44 | <Tool | |
| 45 | Name="VCPostBuildEventTool" | |
| 46 | Description="Running all unit tests" | |
| 47 | CommandLine="$(TargetPath)"/> | |
| 48 | <Tool | |
| 49 | Name="VCPreBuildEventTool"/> | |
| 50 | <Tool | |
| 51 | Name="VCPreLinkEventTool"/> | |
| 52 | <Tool | |
| 53 | Name="VCResourceCompilerTool"/> | |
| 54 | <Tool | |
| 55 | Name="VCWebServiceProxyGeneratorTool"/> | |
| 56 | <Tool | |
| 57 | Name="VCXMLDataGeneratorTool"/> | |
| 58 | <Tool | |
| 59 | Name="VCWebDeploymentTool"/> | |
| 60 | <Tool | |
| 61 | Name="VCManagedWrapperGeneratorTool"/> | |
| 62 | <Tool | |
| 63 | Name="VCAuxiliaryManagedWrapperGeneratorTool"/> | |
| 64 | </Configuration> | |
| 65 | <Configuration | |
| 66 | Name="Release|Win32" | |
| 67 | OutputDirectory="../../build/vs71/release/test_lib_json" | |
| 68 | IntermediateDirectory="../../build/vs71/release/test_lib_json" | |
| 69 | ConfigurationType="1" | |
| 70 | CharacterSet="2"> | |
| 71 | <Tool | |
| 72 | Name="VCCLCompilerTool" | |
| 73 | AdditionalIncludeDirectories="../../include" | |
| 74 | PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE" | |
| 75 | RuntimeLibrary="0" | |
| 76 | UsePrecompiledHeader="0" | |
| 77 | WarningLevel="3" | |
| 78 | Detect64BitPortabilityProblems="TRUE" | |
| 79 | DebugInformationFormat="3"/> | |
| 80 | <Tool | |
| 81 | Name="VCCustomBuildTool"/> | |
| 82 | <Tool | |
| 83 | Name="VCLinkerTool" | |
| 84 | OutputFile="$(OutDir)/test_lib_json.exe" | |
| 85 | LinkIncremental="1" | |
| 86 | GenerateDebugInformation="TRUE" | |
| 87 | SubSystem="1" | |
| 88 | OptimizeReferences="2" | |
| 89 | EnableCOMDATFolding="2" | |
| 90 | TargetMachine="1"/> | |
| 91 | <Tool | |
| 92 | Name="VCMIDLTool"/> | |
| 93 | <Tool | |
| 94 | Name="VCPostBuildEventTool" | |
| 95 | Description="Running all unit tests" | |
| 96 | CommandLine="$(TargetPath)"/> | |
| 97 | <Tool | |
| 98 | Name="VCPreBuildEventTool"/> | |
| 99 | <Tool | |
| 100 | Name="VCPreLinkEventTool"/> | |
| 101 | <Tool | |
| 102 | Name="VCResourceCompilerTool"/> | |
| 103 | <Tool | |
| 104 | Name="VCWebServiceProxyGeneratorTool"/> | |
| 105 | <Tool | |
| 106 | Name="VCXMLDataGeneratorTool"/> | |
| 107 | <Tool | |
| 108 | Name="VCWebDeploymentTool"/> | |
| 109 | <Tool | |
| 110 | Name="VCManagedWrapperGeneratorTool"/> | |
| 111 | <Tool | |
| 112 | Name="VCAuxiliaryManagedWrapperGeneratorTool"/> | |
| 113 | </Configuration> | |
| 114 | </Configurations> | |
| 115 | <References> | |
| 116 | </References> | |
| 117 | <Files> | |
| 118 | <File | |
| 119 | RelativePath="..\..\src\test_lib_json\jsontest.cpp"> | |
| 120 | </File> | |
| 121 | <File | |
| 122 | RelativePath="..\..\src\test_lib_json\jsontest.h"> | |
| 123 | </File> | |
| 124 | <File | |
| 125 | RelativePath="..\..\src\test_lib_json\main.cpp"> | |
| 126 | </File> | |
| 127 | </Files> | |
| 128 | <Globals> | |
| 129 | </Globals> | |
| 130 | </VisualStudioProject> |
| r0 | r242831 | |
|---|---|---|
| 1 | """Tag the sandbox for release, make source and doc tarballs. | |
| 2 | ||
| 3 | Requires Python 2.6 | |
| 4 | ||
| 5 | Example of invocation (use to test the script): | |
| 6 | python makerelease.py --platform=msvc6,msvc71,msvc80,msvc90,mingw -ublep 0.6.0 0.7.0-dev | |
| 7 | ||
| 8 | When testing this script: | |
| 9 | python makerelease.py --force --retag --platform=msvc6,msvc71,msvc80,mingw -ublep test-0.6.0 test-0.6.1-dev | |
| 10 | ||
| 11 | Example of invocation when doing a release: | |
| 12 | python makerelease.py 0.5.0 0.6.0-dev | |
| 13 | ||
| 14 | Note: This was for Subversion. Now that we are in GitHub, we do not | |
| 15 | need to build versioned tarballs anymore, so makerelease.py is defunct. | |
| 16 | """ | |
| 17 | from __future__ import print_function | |
| 18 | import os.path | |
| 19 | import subprocess | |
| 20 | import sys | |
| 21 | import doxybuild | |
| 22 | import subprocess | |
| 23 | import xml.etree.ElementTree as ElementTree | |
| 24 | import shutil | |
| 25 | import urllib2 | |
| 26 | import tempfile | |
| 27 | import os | |
| 28 | import time | |
| 29 | from devtools import antglob, fixeol, tarball | |
| 30 | import amalgamate | |
| 31 | ||
| 32 | SVN_ROOT = 'https://jsoncpp.svn.sourceforge.net/svnroot/jsoncpp/' | |
| 33 | SVN_TAG_ROOT = SVN_ROOT + 'tags/jsoncpp' | |
| 34 | SCONS_LOCAL_URL = 'http://sourceforge.net/projects/scons/files/scons-local/1.2.0/scons-local-1.2.0.tar.gz/download' | |
| 35 | SOURCEFORGE_PROJECT = 'jsoncpp' | |
| 36 | ||
| 37 | def set_version( version ): | |
| 38 | with open('version','wb') as f: | |
| 39 | f.write( version.strip() ) | |
| 40 | ||
| 41 | def rmdir_if_exist( dir_path ): | |
| 42 | if os.path.isdir( dir_path ): | |
| 43 | shutil.rmtree( dir_path ) | |
| 44 | ||
| 45 | class SVNError(Exception): | |
| 46 | pass | |
| 47 | ||
| 48 | def svn_command( command, *args ): | |
| 49 | cmd = ['svn', '--non-interactive', command] + list(args) | |
| 50 | print('Running:', ' '.join( cmd )) | |
| 51 | process = subprocess.Popen( cmd, | |
| 52 | stdout=subprocess.PIPE, | |
| 53 | stderr=subprocess.STDOUT ) | |
| 54 | stdout = process.communicate()[0] | |
| 55 | if process.returncode: | |
| 56 | error = SVNError( 'SVN command failed:\n' + stdout ) | |
| 57 | error.returncode = process.returncode | |
| 58 | raise error | |
| 59 | return stdout | |
| 60 | ||
| 61 | def check_no_pending_commit(): | |
| 62 | """Checks that there is no pending commit in the sandbox.""" | |
| 63 | stdout = svn_command( 'status', '--xml' ) | |
| 64 | etree = ElementTree.fromstring( stdout ) | |
| 65 | msg = [] | |
| 66 | for entry in etree.getiterator( 'entry' ): | |
| 67 | path = entry.get('path') | |
| 68 | status = entry.find('wc-status').get('item') | |
| 69 | if status != 'unversioned' and path != 'version': | |
| 70 | msg.append( 'File "%s" has pending change (status="%s")' % (path, status) ) | |
| 71 | if msg: | |
| 72 | msg.insert(0, 'Pending change to commit found in sandbox. Commit them first!' ) | |
| 73 | return '\n'.join( msg ) | |
| 74 | ||
| 75 | def svn_join_url( base_url, suffix ): | |
| 76 | if not base_url.endswith('/'): | |
| 77 | base_url += '/' | |
| 78 | if suffix.startswith('/'): | |
| 79 | suffix = suffix[1:] | |
| 80 | return base_url + suffix | |
| 81 | ||
| 82 | def svn_check_if_tag_exist( tag_url ): | |
| 83 | """Checks if a tag exist. | |
| 84 | Returns: True if the tag exist, False otherwise. | |
| 85 | """ | |
| 86 | try: | |
| 87 | list_stdout = svn_command( 'list', tag_url ) | |
| 88 | except SVNError as e: | |
| 89 | if e.returncode != 1 or not str(e).find('tag_url'): | |
| 90 | raise e | |
| 91 | # otherwise ignore error, meaning tag does not exist | |
| 92 | return False | |
| 93 | return True | |
| 94 | ||
| 95 | def svn_commit( message ): | |
| 96 | """Commit the sandbox, providing the specified comment. | |
| 97 | """ | |
| 98 | svn_command( 'ci', '-m', message ) | |
| 99 | ||
| 100 | def svn_tag_sandbox( tag_url, message ): | |
| 101 | """Makes a tag based on the sandbox revisions. | |
| 102 | """ | |
| 103 | svn_command( 'copy', '-m', message, '.', tag_url ) | |
| 104 | ||
| 105 | def svn_remove_tag( tag_url, message ): | |
| 106 | """Removes an existing tag. | |
| 107 | """ | |
| 108 | svn_command( 'delete', '-m', message, tag_url ) | |
| 109 | ||
| 110 | def svn_export( tag_url, export_dir ): | |
| 111 | """Exports the tag_url revision to export_dir. | |
| 112 | Target directory, including its parent is created if it does not exist. | |
| 113 | If the directory export_dir exist, it is deleted before export proceed. | |
| 114 | """ | |
| 115 | rmdir_if_exist( export_dir ) | |
| 116 | svn_command( 'export', tag_url, export_dir ) | |
| 117 | ||
| 118 | def fix_sources_eol( dist_dir ): | |
| 119 | """Set file EOL for tarball distribution. | |
| 120 | """ | |
| 121 | print('Preparing exported source file EOL for distribution...') | |
| 122 | prune_dirs = antglob.prune_dirs + 'scons-local* ./build* ./libs ./dist' | |
| 123 | win_sources = antglob.glob( dist_dir, | |
| 124 | includes = '**/*.sln **/*.vcproj', | |
| 125 | prune_dirs = prune_dirs ) | |
| 126 | unix_sources = antglob.glob( dist_dir, | |
| 127 | includes = '''**/*.h **/*.cpp **/*.inl **/*.txt **/*.dox **/*.py **/*.html **/*.in | |
| 128 | sconscript *.json *.expected AUTHORS LICENSE''', | |
| 129 | excludes = antglob.default_excludes + 'scons.py sconsign.py scons-*', | |
| 130 | prune_dirs = prune_dirs ) | |
| 131 | for path in win_sources: | |
| 132 | fixeol.fix_source_eol( path, is_dry_run = False, verbose = True, eol = '\r\n' ) | |
| 133 | for path in unix_sources: | |
| 134 | fixeol.fix_source_eol( path, is_dry_run = False, verbose = True, eol = '\n' ) | |
| 135 | ||
| 136 | def download( url, target_path ): | |
| 137 | """Download file represented by url to target_path. | |
| 138 | """ | |
| 139 | f = urllib2.urlopen( url ) | |
| 140 | try: | |
| 141 | data = f.read() | |
| 142 | finally: | |
| 143 | f.close() | |
| 144 | fout = open( target_path, 'wb' ) | |
| 145 | try: | |
| 146 | fout.write( data ) | |
| 147 | finally: | |
| 148 | fout.close() | |
| 149 | ||
| 150 | def check_compile( distcheck_top_dir, platform ): | |
| 151 | cmd = [sys.executable, 'scons.py', 'platform=%s' % platform, 'check'] | |
| 152 | print('Running:', ' '.join( cmd )) | |
| 153 | log_path = os.path.join( distcheck_top_dir, 'build-%s.log' % platform ) | |
| 154 | flog = open( log_path, 'wb' ) | |
| 155 | try: | |
| 156 | process = subprocess.Popen( cmd, | |
| 157 | stdout=flog, | |
| 158 | stderr=subprocess.STDOUT, | |
| 159 | cwd=distcheck_top_dir ) | |
| 160 | stdout = process.communicate()[0] | |
| 161 | status = (process.returncode == 0) | |
| 162 | finally: | |
| 163 | flog.close() | |
| 164 | return (status, log_path) | |
| 165 | ||
| 166 | def write_tempfile( content, **kwargs ): | |
| 167 | fd, path = tempfile.mkstemp( **kwargs ) | |
| 168 | f = os.fdopen( fd, 'wt' ) | |
| 169 | try: | |
| 170 | f.write( content ) | |
| 171 | finally: | |
| 172 | f.close() | |
| 173 | return path | |
| 174 | ||
| 175 | class SFTPError(Exception): | |
| 176 | pass | |
| 177 | ||
| 178 | def run_sftp_batch( userhost, sftp, batch, retry=0 ): | |
| 179 | path = write_tempfile( batch, suffix='.sftp', text=True ) | |
| 180 | # psftp -agent -C blep,jsoncpp@web.sourceforge.net -batch -b batch.sftp -bc | |
| 181 | cmd = [sftp, '-agent', '-C', '-batch', '-b', path, '-bc', userhost] | |
| 182 | error = None | |
| 183 | for retry_index in range(0, max(1,retry)): | |
| 184 | heading = retry_index == 0 and 'Running:' or 'Retrying:' | |
| 185 | print(heading, ' '.join( cmd )) | |
| 186 | process = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT ) | |
| 187 | stdout = process.communicate()[0] | |
| 188 | if process.returncode != 0: | |
| 189 | error = SFTPError( 'SFTP batch failed:\n' + stdout ) | |
| 190 | else: | |
| 191 | break | |
| 192 | if error: | |
| 193 | raise error | |
| 194 | return stdout | |
| 195 | ||
| 196 | def sourceforge_web_synchro( sourceforge_project, doc_dir, | |
| 197 | user=None, sftp='sftp' ): | |
| 198 | """Notes: does not synchronize sub-directory of doc-dir. | |
| 199 | """ | |
| 200 | userhost = '%s,%s@web.sourceforge.net' % (user, sourceforge_project) | |
| 201 | stdout = run_sftp_batch( userhost, sftp, """ | |
| 202 | cd htdocs | |
| 203 | dir | |
| 204 | exit | |
| 205 | """ ) | |
| 206 | existing_paths = set() | |
| 207 | collect = 0 | |
| 208 | for line in stdout.split('\n'): | |
| 209 | line = line.strip() | |
| 210 | if not collect and line.endswith('> dir'): | |
| 211 | collect = True | |
| 212 | elif collect and line.endswith('> exit'): | |
| 213 | break | |
| 214 | elif collect == 1: | |
| 215 | collect = 2 | |
| 216 | elif collect == 2: | |
| 217 | path = line.strip().split()[-1:] | |
| 218 | if path and path[0] not in ('.', '..'): | |
| 219 | existing_paths.add( path[0] ) | |
| 220 | upload_paths = set( [os.path.basename(p) for p in antglob.glob( doc_dir )] ) | |
| 221 | paths_to_remove = existing_paths - upload_paths | |
| 222 | if paths_to_remove: | |
| 223 | print('Removing the following file from web:') | |
| 224 | print('\n'.join( paths_to_remove )) | |
| 225 | stdout = run_sftp_batch( userhost, sftp, """cd htdocs | |
| 226 | rm %s | |
| 227 | exit""" % ' '.join(paths_to_remove) ) | |
| 228 | print('Uploading %d files:' % len(upload_paths)) | |
| 229 | batch_size = 10 | |
| 230 | upload_paths = list(upload_paths) | |
| 231 | start_time = time.time() | |
| 232 | for index in range(0,len(upload_paths),batch_size): | |
| 233 | paths = upload_paths[index:index+batch_size] | |
| 234 | file_per_sec = (time.time() - start_time) / (index+1) | |
| 235 | remaining_files = len(upload_paths) - index | |
| 236 | remaining_sec = file_per_sec * remaining_files | |
| 237 | print('%d/%d, ETA=%.1fs' % (index+1, len(upload_paths), remaining_sec)) | |
| 238 | run_sftp_batch( userhost, sftp, """cd htdocs | |
| 239 | lcd %s | |
| 240 | mput %s | |
| 241 | exit""" % (doc_dir, ' '.join(paths) ), retry=3 ) | |
| 242 | ||
| 243 | def sourceforge_release_tarball( sourceforge_project, paths, user=None, sftp='sftp' ): | |
| 244 | userhost = '%s,%s@frs.sourceforge.net' % (user, sourceforge_project) | |
| 245 | run_sftp_batch( userhost, sftp, """ | |
| 246 | mput %s | |
| 247 | exit | |
| 248 | """ % (' '.join(paths),) ) | |
| 249 | ||
| 250 | ||
| 251 | def main(): | |
| 252 | usage = """%prog release_version next_dev_version | |
| 253 | Update 'version' file to release_version and commit. | |
| 254 | Generates the document tarball. | |
| 255 | Tags the sandbox revision with release_version. | |
| 256 | Update 'version' file to next_dev_version and commit. | |
| 257 | ||
| 258 | Performs an svn export of tag release version, and build a source tarball. | |
| 259 | ||
| 260 | Must be started in the project top directory. | |
| 261 | ||
| 262 | Warning: --force should only be used when developping/testing the release script. | |
| 263 | """ | |
| 264 | from optparse import OptionParser | |
| 265 | parser = OptionParser(usage=usage) | |
| 266 | parser.allow_interspersed_args = False | |
| 267 | parser.add_option('--dot', dest="dot_path", action='store', default=doxybuild.find_program('dot'), | |
| 268 | help="""Path to GraphViz dot tool. Must be full qualified path. [Default: %default]""") | |
| 269 | parser.add_option('--doxygen', dest="doxygen_path", action='store', default=doxybuild.find_program('doxygen'), | |
| 270 | help="""Path to Doxygen tool. [Default: %default]""") | |
| 271 | parser.add_option('--force', dest="ignore_pending_commit", action='store_true', default=False, | |
| 272 | help="""Ignore pending commit. [Default: %default]""") | |
| 273 | parser.add_option('--retag', dest="retag_release", action='store_true', default=False, | |
| 274 | help="""Overwrite release existing tag if it exist. [Default: %default]""") | |
| 275 | parser.add_option('-p', '--platforms', dest="platforms", action='store', default='', | |
| 276 | help="""Comma separated list of platform passed to scons for build check.""") | |
| 277 | parser.add_option('--no-test', dest="no_test", action='store_true', default=False, | |
| 278 | help="""Skips build check.""") | |
| 279 | parser.add_option('--no-web', dest="no_web", action='store_true', default=False, | |
| 280 | help="""Do not update web site.""") | |
| 281 | parser.add_option('-u', '--upload-user', dest="user", action='store', | |
| 282 | help="""Sourceforge user for SFTP documentation upload.""") | |
| 283 | parser.add_option('--sftp', dest='sftp', action='store', default=doxybuild.find_program('psftp', 'sftp'), | |
| 284 | help="""Path of the SFTP compatible binary used to upload the documentation.""") | |
| 285 | parser.enable_interspersed_args() | |
| 286 | options, args = parser.parse_args() | |
| 287 | ||
| 288 | if len(args) != 2: | |
| 289 | parser.error( 'release_version missing on command-line.' ) | |
| 290 | release_version = args[0] | |
| 291 | next_version = args[1] | |
| 292 | ||
| 293 | if not options.platforms and not options.no_test: | |
| 294 | parser.error( 'You must specify either --platform or --no-test option.' ) | |
| 295 | ||
| 296 | if options.ignore_pending_commit: | |
| 297 | msg = '' | |
| 298 | else: | |
| 299 | msg = check_no_pending_commit() | |
| 300 | if not msg: | |
| 301 | print('Setting version to', release_version) | |
| 302 | set_version( release_version ) | |
| 303 | svn_commit( 'Release ' + release_version ) | |
| 304 | tag_url = svn_join_url( SVN_TAG_ROOT, release_version ) | |
| 305 | if svn_check_if_tag_exist( tag_url ): | |
| 306 | if options.retag_release: | |
| 307 | svn_remove_tag( tag_url, 'Overwriting previous tag' ) | |
| 308 | else: | |
| 309 | print('Aborting, tag %s already exist. Use --retag to overwrite it!' % tag_url) | |
| 310 | sys.exit( 1 ) | |
| 311 | svn_tag_sandbox( tag_url, 'Release ' + release_version ) | |
| 312 | ||
| 313 | print('Generated doxygen document...') | |
| 314 | ## doc_dirname = r'jsoncpp-api-html-0.5.0' | |
| 315 | ## doc_tarball_path = r'e:\prg\vc\Lib\jsoncpp-trunk\dist\jsoncpp-api-html-0.5.0.tar.gz' | |
| 316 | doc_tarball_path, doc_dirname = doxybuild.build_doc( options, make_release=True ) | |
| 317 | doc_distcheck_dir = 'dist/doccheck' | |
| 318 | tarball.decompress( doc_tarball_path, doc_distcheck_dir ) | |
| 319 | doc_distcheck_top_dir = os.path.join( doc_distcheck_dir, doc_dirname ) | |
| 320 | ||
| 321 | export_dir = 'dist/export' | |
| 322 | svn_export( tag_url, export_dir ) | |
| 323 | fix_sources_eol( export_dir ) | |
| 324 | ||
| 325 | source_dir = 'jsoncpp-src-' + release_version | |
| 326 | source_tarball_path = 'dist/%s.tar.gz' % source_dir | |
| 327 | print('Generating source tarball to', source_tarball_path) | |
| 328 | tarball.make_tarball( source_tarball_path, [export_dir], export_dir, prefix_dir=source_dir ) | |
| 329 | ||
| 330 | amalgamation_tarball_path = 'dist/%s-amalgamation.tar.gz' % source_dir | |
| 331 | print('Generating amalgamation source tarball to', amalgamation_tarball_path) | |
| 332 | amalgamation_dir = 'dist/amalgamation' | |
| 333 | amalgamate.amalgamate_source( export_dir, '%s/jsoncpp.cpp' % amalgamation_dir, 'json/json.h' ) | |
| 334 | amalgamation_source_dir = 'jsoncpp-src-amalgamation' + release_version | |
| 335 | tarball.make_tarball( amalgamation_tarball_path, [amalgamation_dir], | |
| 336 | amalgamation_dir, prefix_dir=amalgamation_source_dir ) | |
| 337 | ||
| 338 | # Decompress source tarball, download and install scons-local | |
| 339 | distcheck_dir = 'dist/distcheck' | |
| 340 | distcheck_top_dir = distcheck_dir + '/' + source_dir | |
| 341 | print('Decompressing source tarball to', distcheck_dir) | |
| 342 | rmdir_if_exist( distcheck_dir ) | |
| 343 | tarball.decompress( source_tarball_path, distcheck_dir ) | |
| 344 | scons_local_path = 'dist/scons-local.tar.gz' | |
| 345 | print('Downloading scons-local to', scons_local_path) | |
| 346 | download( SCONS_LOCAL_URL, scons_local_path ) | |
| 347 | print('Decompressing scons-local to', distcheck_top_dir) | |
| 348 | tarball.decompress( scons_local_path, distcheck_top_dir ) | |
| 349 | ||
| 350 | # Run compilation | |
| 351 | print('Compiling decompressed tarball') | |
| 352 | all_build_status = True | |
| 353 | for platform in options.platforms.split(','): | |
| 354 | print('Testing platform:', platform) | |
| 355 | build_status, log_path = check_compile( distcheck_top_dir, platform ) | |
| 356 | print('see build log:', log_path) | |
| 357 | print(build_status and '=> ok' or '=> FAILED') | |
| 358 | all_build_status = all_build_status and build_status | |
| 359 | if not build_status: | |
| 360 | print('Testing failed on at least one platform, aborting...') | |
| 361 | svn_remove_tag( tag_url, 'Removing tag due to failed testing' ) | |
| 362 | sys.exit(1) | |
| 363 | if options.user: | |
| 364 | if not options.no_web: | |
| 365 | print('Uploading documentation using user', options.user) | |
| 366 | sourceforge_web_synchro( SOURCEFORGE_PROJECT, doc_distcheck_top_dir, user=options.user, sftp=options.sftp ) | |
| 367 | print('Completed documentation upload') | |
| 368 | print('Uploading source and documentation tarballs for release using user', options.user) | |
| 369 | sourceforge_release_tarball( SOURCEFORGE_PROJECT, | |
| 370 | [source_tarball_path, doc_tarball_path], | |
| 371 | user=options.user, sftp=options.sftp ) | |
| 372 | print('Source and doc release tarballs uploaded') | |
| 373 | else: | |
| 374 | print('No upload user specified. Web site and download tarbal were not uploaded.') | |
| 375 | print('Tarball can be found at:', doc_tarball_path) | |
| 376 | ||
| 377 | # Set next version number and commit | |
| 378 | set_version( next_version ) | |
| 379 | svn_commit( 'Released ' + release_version ) | |
| 380 | else: | |
| 381 | sys.stderr.write( msg + '\n' ) | |
| 382 | ||
| 383 | if __name__ == '__main__': | |
| 384 | main() |
| r0 | r242831 | |
|---|---|---|
| 1 | prefix=@CMAKE_INSTALL_PREFIX@ | |
| 2 | exec_prefix=${prefix} | |
| 3 | libdir=${exec_prefix}/@LIBRARY_INSTALL_DIR@ | |
| 4 | includedir=${prefix}/@INCLUDE_INSTALL_DIR@ | |
| 5 | ||
| 6 | Name: jsoncpp | |
| 7 | Description: A C++ library for interacting with JSON | |
| 8 | Version: @JSONCPP_VERSION@ | |
| 9 | URL: https://github.com/open-source-parsers/jsoncpp | |
| 10 | Libs: -L${libdir} -ljsoncpp | |
| 11 | Cflags: -I${includedir} |
| r0 | r242831 | |
|---|---|---|
| 1 | import fnmatch | |
| 2 | import os | |
| 3 | ||
| 4 | def generate( env ): | |
| 5 | def Glob( env, includes = None, excludes = None, dir = '.' ): | |
| 6 | """Adds Glob( includes = Split( '*' ), excludes = None, dir = '.') | |
| 7 | helper function to environment. | |
| 8 | ||
| 9 | Glob both the file-system files. | |
| 10 | ||
| 11 | includes: list of file name pattern included in the return list when matched. | |
| 12 | excludes: list of file name pattern exluced from the return list. | |
| 13 | ||
| 14 | Example: | |
| 15 | sources = env.Glob( ("*.cpp", '*.h'), "~*.cpp", "#src" ) | |
| 16 | """ | |
| 17 | def filterFilename(path): | |
| 18 | abs_path = os.path.join( dir, path ) | |
| 19 | if not os.path.isfile(abs_path): | |
| 20 | return 0 | |
| 21 | fn = os.path.basename(path) | |
| 22 | match = 0 | |
| 23 | for include in includes: | |
| 24 | if fnmatch.fnmatchcase( fn, include ): | |
| 25 | match = 1 | |
| 26 | break | |
| 27 | if match == 1 and not excludes is None: | |
| 28 | for exclude in excludes: | |
| 29 | if fnmatch.fnmatchcase( fn, exclude ): | |
| 30 | match = 0 | |
| 31 | break | |
| 32 | return match | |
| 33 | if includes is None: | |
| 34 | includes = ('*',) | |
| 35 | elif type(includes) in ( type(''), type(u'') ): | |
| 36 | includes = (includes,) | |
| 37 | if type(excludes) in ( type(''), type(u'') ): | |
| 38 | excludes = (excludes,) | |
| 39 | dir = env.Dir(dir).abspath | |
| 40 | paths = os.listdir( dir ) | |
| 41 | def makeAbsFileNode( path ): | |
| 42 | return env.File( os.path.join( dir, path ) ) | |
| 43 | nodes = filter( filterFilename, paths ) | |
| 44 | return map( makeAbsFileNode, nodes ) | |
| 45 | ||
| 46 | from SCons.Script import Environment | |
| 47 | Environment.Glob = Glob | |
| 48 | ||
| 49 | def exists(env): | |
| 50 | """ | |
| 51 | Tool always exists. | |
| 52 | """ | |
| 53 | return True |
| r0 | r242831 | |
|---|---|---|
| 1 | import os | |
| 2 | import os.path | |
| 3 | from fnmatch import fnmatch | |
| 4 | import targz | |
| 5 | ||
| 6 | ##def DoxyfileParse(file_contents): | |
| 7 | ## """ | |
| 8 | ## Parse a Doxygen source file and return a dictionary of all the values. | |
| 9 | ## Values will be strings and lists of strings. | |
| 10 | ## """ | |
| 11 | ## data = {} | |
| 12 | ## | |
| 13 | ## import shlex | |
| 14 | ## lex = shlex.shlex(instream = file_contents, posix = True) | |
| 15 | ## lex.wordchars += "*+./-:" | |
| 16 | ## lex.whitespace = lex.whitespace.replace("\n", "") | |
| 17 | ## lex.escape = "" | |
| 18 | ## | |
| 19 | ## lineno = lex.lineno | |
| 20 | ## last_backslash_lineno = lineno | |
| 21 | ## token = lex.get_token() | |
| 22 | ## key = token # the first token should be a key | |
| 23 | ## last_token = "" | |
| 24 | ## key_token = False | |
| 25 | ## next_key = False | |
| 26 | ## new_data = True | |
| 27 | ## | |
| 28 | ## def append_data(data, key, new_data, token): | |
| 29 | ## if new_data or len(data[key]) == 0: | |
| 30 | ## data[key].append(token) | |
| 31 | ## else: | |
| 32 | ## data[key][-1] += token | |
| 33 | ## | |
| 34 | ## while token: | |
| 35 | ## if token in ['\n']: | |
| 36 | ## if last_token not in ['\\']: | |
| 37 | ## key_token = True | |
| 38 | ## elif token in ['\\']: | |
| 39 | ## pass | |
| 40 | ## elif key_token: | |
| 41 | ## key = token | |
| 42 | ## key_token = False | |
| 43 | ## else: | |
| 44 | ## if token == "+=": | |
| 45 | ## if not data.has_key(key): | |
| 46 | ## data[key] = list() | |
| 47 | ## elif token == "=": | |
| 48 | ## data[key] = list() | |
| 49 | ## else: | |
| 50 | ## append_data( data, key, new_data, token ) | |
| 51 | ## new_data = True | |
| 52 | ## | |
| 53 | ## last_token = token | |
| 54 | ## token = lex.get_token() | |
| 55 | ## | |
| 56 | ## if last_token == '\\' and token != '\n': | |
| 57 | ## new_data = False | |
| 58 | ## append_data( data, key, new_data, '\\' ) | |
| 59 | ## | |
| 60 | ## # compress lists of len 1 into single strings | |
| 61 | ## for (k, v) in data.items(): | |
| 62 | ## if len(v) == 0: | |
| 63 | ## data.pop(k) | |
| 64 | ## | |
| 65 | ## # items in the following list will be kept as lists and not converted to strings | |
| 66 | ## if k in ["INPUT", "FILE_PATTERNS", "EXCLUDE_PATTERNS"]: | |
| 67 | ## continue | |
| 68 | ## | |
| 69 | ## if len(v) == 1: | |
| 70 | ## data[k] = v[0] | |
| 71 | ## | |
| 72 | ## return data | |
| 73 | ## | |
| 74 | ##def DoxySourceScan(node, env, path): | |
| 75 | ## """ | |
| 76 | ## Doxygen Doxyfile source scanner. This should scan the Doxygen file and add | |
| 77 | ## any files used to generate docs to the list of source files. | |
| 78 | ## """ | |
| 79 | ## default_file_patterns = [ | |
| 80 | ## '*.c', '*.cc', '*.cxx', '*.cpp', '*.c++', '*.java', '*.ii', '*.ixx', | |
| 81 | ## '*.ipp', '*.i++', '*.inl', '*.h', '*.hh ', '*.hxx', '*.hpp', '*.h++', | |
| 82 | ## '*.idl', '*.odl', '*.cs', '*.php', '*.php3', '*.inc', '*.m', '*.mm', | |
| 83 | ## '*.py', | |
| 84 | ## ] | |
| 85 | ## | |
| 86 | ## default_exclude_patterns = [ | |
| 87 | ## '*~', | |
| 88 | ## ] | |
| 89 | ## | |
| 90 | ## sources = [] | |
| 91 | ## | |
| 92 | ## data = DoxyfileParse(node.get_contents()) | |
| 93 | ## | |
| 94 | ## if data.get("RECURSIVE", "NO") == "YES": | |
| 95 | ## recursive = True | |
| 96 | ## else: | |
| 97 | ## recursive = False | |
| 98 | ## | |
| 99 | ## file_patterns = data.get("FILE_PATTERNS", default_file_patterns) | |
| 100 | ## exclude_patterns = data.get("EXCLUDE_PATTERNS", default_exclude_patterns) | |
| 101 | ## | |
| 102 | ## for node in data.get("INPUT", []): | |
| 103 | ## if os.path.isfile(node): | |
| 104 | ## sources.add(node) | |
| 105 | ## elif os.path.isdir(node): | |
| 106 | ## if recursive: | |
| 107 | ## for root, dirs, files in os.walk(node): | |
| 108 | ## for f in files: | |
| 109 | ## filename = os.path.join(root, f) | |
| 110 | ## | |
| 111 | ## pattern_check = reduce(lambda x, y: x or bool(fnmatch(filename, y)), file_patterns, False) | |
| 112 | ## exclude_check = reduce(lambda x, y: x and fnmatch(filename, y), exclude_patterns, True) | |
| 113 | ## | |
| 114 | ## if pattern_check and not exclude_check: | |
| 115 | ## sources.append(filename) | |
| 116 | ## else: | |
| 117 | ## for pattern in file_patterns: | |
| 118 | ## sources.extend(glob.glob("/".join([node, pattern]))) | |
| 119 | ## sources = map( lambda path: env.File(path), sources ) | |
| 120 | ## return sources | |
| 121 | ## | |
| 122 | ## | |
| 123 | ##def DoxySourceScanCheck(node, env): | |
| 124 | ## """Check if we should scan this file""" | |
| 125 | ## return os.path.isfile(node.path) | |
| 126 | ||
| 127 | def srcDistEmitter(source, target, env): | |
| 128 | ## """Doxygen Doxyfile emitter""" | |
| 129 | ## # possible output formats and their default values and output locations | |
| 130 | ## output_formats = { | |
| 131 | ## "HTML": ("YES", "html"), | |
| 132 | ## "LATEX": ("YES", "latex"), | |
| 133 | ## "RTF": ("NO", "rtf"), | |
| 134 | ## "MAN": ("YES", "man"), | |
| 135 | ## "XML": ("NO", "xml"), | |
| 136 | ## } | |
| 137 | ## | |
| 138 | ## data = DoxyfileParse(source[0].get_contents()) | |
| 139 | ## | |
| 140 | ## targets = [] | |
| 141 | ## out_dir = data.get("OUTPUT_DIRECTORY", ".") | |
| 142 | ## | |
| 143 | ## # add our output locations | |
| 144 | ## for (k, v) in output_formats.items(): | |
| 145 | ## if data.get("GENERATE_" + k, v[0]) == "YES": | |
| 146 | ## targets.append(env.Dir( os.path.join(out_dir, data.get(k + "_OUTPUT", v[1]))) ) | |
| 147 | ## | |
| 148 | ## # don't clobber targets | |
| 149 | ## for node in targets: | |
| 150 | ## env.Precious(node) | |
| 151 | ## | |
| 152 | ## # set up cleaning stuff | |
| 153 | ## for node in targets: | |
| 154 | ## env.Clean(node, node) | |
| 155 | ## | |
| 156 | ## return (targets, source) | |
| 157 | return (target,source) | |
| 158 | ||
| 159 | def generate(env): | |
| 160 | """ | |
| 161 | Add builders and construction variables for the | |
| 162 | SrcDist tool. | |
| 163 | """ | |
| 164 | ## doxyfile_scanner = env.Scanner( | |
| 165 | ## DoxySourceScan, | |
| 166 | ## "DoxySourceScan", | |
| 167 | ## scan_check = DoxySourceScanCheck, | |
| 168 | ## ) | |
| 169 | ||
| 170 | if targz.exists(env): | |
| 171 | srcdist_builder = targz.makeBuilder( srcDistEmitter ) | |
| 172 | ||
| 173 | env['BUILDERS']['SrcDist'] = srcdist_builder | |
| 174 | ||
| 175 | def exists(env): | |
| 176 | """ | |
| 177 | Make sure srcdist exists. | |
| 178 | """ | |
| 179 | return targz.exists(env) |
| r0 | r242831 | |
|---|---|---|
| 1 | import re | |
| 2 | from SCons.Script import * # the usual scons stuff you get in a SConscript | |
| 3 | import collections | |
| 4 | ||
| 5 | def generate(env): | |
| 6 | """ | |
| 7 | Add builders and construction variables for the | |
| 8 | SubstInFile tool. | |
| 9 | ||
| 10 | Adds SubstInFile builder, which substitutes the keys->values of SUBST_DICT | |
| 11 | from the source to the target. | |
| 12 | The values of SUBST_DICT first have any construction variables expanded | |
| 13 | (its keys are not expanded). | |
| 14 | If a value of SUBST_DICT is a python callable function, it is called and | |
| 15 | the result is expanded as the value. | |
| 16 | If there's more than one source and more than one target, each target gets | |
| 17 | substituted from the corresponding source. | |
| 18 | """ | |
| 19 | def do_subst_in_file(targetfile, sourcefile, dict): | |
| 20 | """Replace all instances of the keys of dict with their values. | |
| 21 | For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'}, | |
| 22 | then all instances of %VERSION% in the file will be replaced with 1.2345 etc. | |
| 23 | """ | |
| 24 | try: | |
| 25 | f = open(sourcefile, 'rb') | |
| 26 | contents = f.read() | |
| 27 | f.close() | |
| 28 | except: | |
| 29 | raise SCons.Errors.UserError("Can't read source file %s"%sourcefile) | |
| 30 | for (k,v) in list(dict.items()): | |
| 31 | contents = re.sub(k, v, contents) | |
| 32 | try: | |
| 33 | f = open(targetfile, 'wb') | |
| 34 | f.write(contents) | |
| 35 | f.close() | |
| 36 | except: | |
| 37 | raise SCons.Errors.UserError("Can't write target file %s"%targetfile) | |
| 38 | return 0 # success | |
| 39 | ||
| 40 | def subst_in_file(target, source, env): | |
| 41 | if 'SUBST_DICT' not in env: | |
| 42 | raise SCons.Errors.UserError("SubstInFile requires SUBST_DICT to be set.") | |
| 43 | d = dict(env['SUBST_DICT']) # copy it | |
| 44 | for (k,v) in list(d.items()): | |
| 45 | if isinstance(v, collections.Callable): | |
| 46 | d[k] = env.subst(v()).replace('\\','\\\\') | |
| 47 | elif SCons.Util.is_String(v): | |
| 48 | d[k] = env.subst(v).replace('\\','\\\\') | |
| 49 | else: | |
| 50 | raise SCons.Errors.UserError("SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))) | |
| 51 | for (t,s) in zip(target, source): | |
| 52 | return do_subst_in_file(str(t), str(s), d) | |
| 53 | ||
| 54 | def subst_in_file_string(target, source, env): | |
| 55 | """This is what gets printed on the console.""" | |
| 56 | return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t)) | |
| 57 | for (t,s) in zip(target, source)]) | |
| 58 | ||
| 59 | def subst_emitter(target, source, env): | |
| 60 | """Add dependency from substituted SUBST_DICT to target. | |
| 61 | Returns original target, source tuple unchanged. | |
| 62 | """ | |
| 63 | d = env['SUBST_DICT'].copy() # copy it | |
| 64 | for (k,v) in list(d.items()): | |
| 65 | if isinstance(v, collections.Callable): | |
| 66 | d[k] = env.subst(v()) | |
| 67 | elif SCons.Util.is_String(v): | |
| 68 | d[k]=env.subst(v) | |
| 69 | Depends(target, SCons.Node.Python.Value(d)) | |
| 70 | return target, source | |
| 71 | ||
| 72 | ## env.Append(TOOLS = 'substinfile') # this should be automaticaly done by Scons ?!? | |
| 73 | subst_action = SCons.Action.Action( subst_in_file, subst_in_file_string ) | |
| 74 | env['BUILDERS']['SubstInFile'] = Builder(action=subst_action, emitter=subst_emitter) | |
| 75 | ||
| 76 | def exists(env): | |
| 77 | """ | |
| 78 | Make sure tool exists. | |
| 79 | """ | |
| 80 | return True |
| r0 | r242831 | |
|---|---|---|
| 1 | """tarball | |
| 2 | ||
| 3 | Tool-specific initialization for tarball. | |
| 4 | ||
| 5 | """ | |
| 6 | ||
| 7 | ## Commands to tackle a command based implementation: | |
| 8 | ##to unpack on the fly... | |
| 9 | ##gunzip < FILE.tar.gz | tar xvf - | |
| 10 | ##to pack on the fly... | |
| 11 | ##tar cvf - FILE-LIST | gzip -c > FILE.tar.gz | |
| 12 | ||
| 13 | import os.path | |
| 14 | ||
| 15 | import SCons.Builder | |
| 16 | import SCons.Node.FS | |
| 17 | import SCons.Util | |
| 18 | ||
| 19 | try: | |
| 20 | import gzip | |
| 21 | import tarfile | |
| 22 | internal_targz = 1 | |
| 23 | except ImportError: | |
| 24 | internal_targz = 0 | |
| 25 | ||
| 26 | TARGZ_DEFAULT_COMPRESSION_LEVEL = 9 | |
| 27 | ||
| 28 | if internal_targz: | |
| 29 | def targz(target, source, env): | |
| 30 | def archive_name( path ): | |
| 31 | path = os.path.normpath( os.path.abspath( path ) ) | |
| 32 | common_path = os.path.commonprefix( (base_dir, path) ) | |
| 33 | archive_name = path[len(common_path):] | |
| 34 | return archive_name | |
| 35 | ||
| 36 | def visit(tar, dirname, names): | |
| 37 | for name in names: | |
| 38 | path = os.path.join(dirname, name) | |
| 39 | if os.path.isfile(path): | |
| 40 | tar.add(path, archive_name(path) ) | |
| 41 | compression = env.get('TARGZ_COMPRESSION_LEVEL',TARGZ_DEFAULT_COMPRESSION_LEVEL) | |
| 42 | base_dir = os.path.normpath( env.get('TARGZ_BASEDIR', env.Dir('.')).abspath ) | |
| 43 | target_path = str(target[0]) | |
| 44 | fileobj = gzip.GzipFile( target_path, 'wb', compression ) | |
| 45 | tar = tarfile.TarFile(os.path.splitext(target_path)[0], 'w', fileobj) | |
| 46 | for source in source: | |
| 47 | source_path = str(source) | |
| 48 | if source.isdir(): | |
| 49 | os.path.walk(source_path, visit, tar) | |
| 50 | else: | |
| 51 | tar.add(source_path, archive_name(source_path) ) # filename, arcname | |
| 52 | tar.close() | |
| 53 | ||
| 54 | targzAction = SCons.Action.Action(targz, varlist=['TARGZ_COMPRESSION_LEVEL','TARGZ_BASEDIR']) | |
| 55 | ||
| 56 | def makeBuilder( emitter = None ): | |
| 57 | return SCons.Builder.Builder(action = SCons.Action.Action('$TARGZ_COM', '$TARGZ_COMSTR'), | |
| 58 | source_factory = SCons.Node.FS.Entry, | |
| 59 | source_scanner = SCons.Defaults.DirScanner, | |
| 60 | suffix = '$TARGZ_SUFFIX', | |
| 61 | multi = 1) | |
| 62 | TarGzBuilder = makeBuilder() | |
| 63 | ||
| 64 | def generate(env): | |
| 65 | """Add Builders and construction variables for zip to an Environment. | |
| 66 | The following environnement variables may be set: | |
| 67 | TARGZ_COMPRESSION_LEVEL: integer, [0-9]. 0: no compression, 9: best compression (same as gzip compression level). | |
| 68 | TARGZ_BASEDIR: base-directory used to determine archive name (this allow archive name to be relative | |
| 69 | to something other than top-dir). | |
| 70 | """ | |
| 71 | env['BUILDERS']['TarGz'] = TarGzBuilder | |
| 72 | env['TARGZ_COM'] = targzAction | |
| 73 | env['TARGZ_COMPRESSION_LEVEL'] = TARGZ_DEFAULT_COMPRESSION_LEVEL # range 0-9 | |
| 74 | env['TARGZ_SUFFIX'] = '.tar.gz' | |
| 75 | env['TARGZ_BASEDIR'] = env.Dir('.') # Sources archive name are made relative to that directory. | |
| 76 | else: | |
| 77 | def generate(env): | |
| 78 | pass | |
| 79 | ||
| 80 | ||
| 81 | def exists(env): | |
| 82 | return internal_targz |
| r0 | r242831 | |
|---|---|---|
| 1 | ADD_SUBDIRECTORY(lib_json) | |
| 2 | IF(JSONCPP_WITH_TESTS) | |
| 3 | ADD_SUBDIRECTORY(jsontestrunner) | |
| 4 | ADD_SUBDIRECTORY(test_lib_json) | |
| 5 | ENDIF(JSONCPP_WITH_TESTS) |
| r0 | r242831 | |
|---|---|---|
| 1 | FIND_PACKAGE(PythonInterp 2.6 REQUIRED) | |
| 2 | ||
| 3 | IF(JSONCPP_LIB_BUILD_SHARED) | |
| 4 | ADD_DEFINITIONS( -DJSON_DLL ) | |
| 5 | ENDIF(JSONCPP_LIB_BUILD_SHARED) | |
| 6 | ||
| 7 | ADD_EXECUTABLE(jsontestrunner_exe | |
| 8 | main.cpp | |
| 9 | ) | |
| 10 | TARGET_LINK_LIBRARIES(jsontestrunner_exe jsoncpp_lib) | |
| 11 | SET_TARGET_PROPERTIES(jsontestrunner_exe PROPERTIES OUTPUT_NAME jsontestrunner_exe) | |
| 12 | ||
| 13 | IF(PYTHONINTERP_FOUND) | |
| 14 | # Run end to end parser/writer tests | |
| 15 | SET(TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../test) | |
| 16 | SET(RUNJSONTESTS_PATH ${TEST_DIR}/runjsontests.py) | |
| 17 | ADD_CUSTOM_TARGET(jsoncpp_readerwriter_tests ALL | |
| 18 | "${PYTHON_EXECUTABLE}" -B "${RUNJSONTESTS_PATH}" $<TARGET_FILE:jsontestrunner_exe> "${TEST_DIR}/data" | |
| 19 | DEPENDS jsontestrunner_exe jsoncpp_test | |
| 20 | ) | |
| 21 | ADD_CUSTOM_TARGET(jsoncpp_check DEPENDS jsoncpp_readerwriter_tests) | |
| 22 | ENDIF(PYTHONINTERP_FOUND) |
| r0 | r242831 | |
|---|---|---|
| 1 | // Copyright 2007-2010 Baptiste Lepilleur | |
| 2 | // Distributed under MIT license, or public domain if desired and | |
| 3 | // recognized in your jurisdiction. | |
| 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE | |
| 5 | ||
| 6 | /* This executable is used for testing parser/writer using real JSON files. | |
| 7 | */ | |
| 8 | ||
| 9 | #include <json/json.h> | |
| 10 | #include <algorithm> // sort | |
| 11 | #include <stdio.h> | |
| 12 | ||
| 13 | #if defined(_MSC_VER) && _MSC_VER >= 1310 | |
| 14 | #pragma warning(disable : 4996) // disable fopen deprecation warning | |
| 15 | #endif | |
| 16 | ||
| 17 | static std::string normalizeFloatingPointStr(double value) { | |
| 18 | char buffer[32]; | |
| 19 | #if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) | |
| 20 | sprintf_s(buffer, sizeof(buffer), "%.16g", value); | |
| 21 | #else | |
| 22 | snprintf(buffer, sizeof(buffer), "%.16g", value); | |
| 23 | #endif | |
| 24 | buffer[sizeof(buffer) - 1] = 0; | |
| 25 | std::string s(buffer); | |
| 26 | std::string::size_type index = s.find_last_of("eE"); | |
| 27 | if (index != std::string::npos) { | |
| 28 | std::string::size_type hasSign = | |
| 29 | (s[index + 1] == '+' || s[index + 1] == '-') ? 1 : 0; | |
| 30 | std::string::size_type exponentStartIndex = index + 1 + hasSign; | |
| 31 | std::string normalized = s.substr(0, exponentStartIndex); | |
| 32 | std::string::size_type indexDigit = | |
| 33 | s.find_first_not_of('0', exponentStartIndex); | |
| 34 | std::string exponent = "0"; | |
| 35 | if (indexDigit != | |
| 36 | std::string::npos) // There is an exponent different from 0 | |
| 37 | { | |
| 38 | exponent = s.substr(indexDigit); | |
| 39 | } | |
| 40 | return normalized + exponent; | |
| 41 | } | |
| 42 | return s; | |
| 43 | } | |
| 44 | ||
| 45 | static std::string readInputTestFile(const char* path) { | |
| 46 | FILE* file = fopen(path, "rb"); | |
| 47 | if (!file) | |
| 48 | return std::string(""); | |
| 49 | fseek(file, 0, SEEK_END); | |
| 50 | long size = ftell(file); | |
| 51 | fseek(file, 0, SEEK_SET); | |
| 52 | std::string text; | |
| 53 | char* buffer = new char[size + 1]; | |
| 54 | buffer[size] = 0; | |
| 55 | if (fread(buffer, 1, size, file) == (unsigned long)size) | |
| 56 | text = buffer; | |
| 57 | fclose(file); | |
| 58 | delete[] buffer; | |
| 59 | return text; | |
| 60 | } | |
| 61 | ||
| 62 | static void | |
| 63 | printValueTree(FILE* fout, Json::Value& value, const std::string& path = ".") { | |
| 64 | if (value.hasComment(Json::commentBefore)) { | |
| 65 | fprintf(fout, "%s\n", value.getComment(Json::commentBefore).c_str()); | |
| 66 | } | |
| 67 | switch (value.type()) { | |
| 68 | case Json::nullValue: | |
| 69 | fprintf(fout, "%s=null\n", path.c_str()); | |
| 70 | break; | |
| 71 | case Json::intValue: | |
| 72 | fprintf(fout, | |
| 73 | "%s=%s\n", | |
| 74 | path.c_str(), | |
| 75 | Json::valueToString(value.asLargestInt()).c_str()); | |
| 76 | break; | |
| 77 | case Json::uintValue: | |
| 78 | fprintf(fout, | |
| 79 | "%s=%s\n", | |
| 80 | path.c_str(), | |
| 81 | Json::valueToString(value.asLargestUInt()).c_str()); | |
| 82 | break; | |
| 83 | case Json::realValue: | |
| 84 | fprintf(fout, | |
| 85 | "%s=%s\n", | |
| 86 | path.c_str(), | |
| 87 | normalizeFloatingPointStr(value.asDouble()).c_str()); | |
| 88 | break; | |
| 89 | case Json::stringValue: | |
| 90 | fprintf(fout, "%s=\"%s\"\n", path.c_str(), value.asString().c_str()); | |
| 91 | break; | |
| 92 | case Json::booleanValue: | |
| 93 | fprintf(fout, "%s=%s\n", path.c_str(), value.asBool() ? "true" : "false"); | |
| 94 | break; | |
| 95 | case Json::arrayValue: { | |
| 96 | fprintf(fout, "%s=[]\n", path.c_str()); | |
| 97 | int size = value.size(); | |
| 98 | for (int index = 0; index < size; ++index) { | |
| 99 | static char buffer[16]; | |
| 100 | #if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) | |
| 101 | sprintf_s(buffer, sizeof(buffer), "[%d]", index); | |
| 102 | #else | |
| 103 | snprintf(buffer, sizeof(buffer), "[%d]", index); | |
| 104 | #endif | |
| 105 | printValueTree(fout, value[index], path + buffer); | |
| 106 | } | |
| 107 | } break; | |
| 108 | case Json::objectValue: { | |
| 109 | fprintf(fout, "%s={}\n", path.c_str()); | |
| 110 | Json::Value::Members members(value.getMemberNames()); | |
| 111 | std::sort(members.begin(), members.end()); | |
| 112 | std::string suffix = *(path.end() - 1) == '.' ? "" : "."; | |
| 113 | for (Json::Value::Members::iterator it = members.begin(); | |
| 114 | it != members.end(); | |
| 115 | ++it) { | |
| 116 | const std::string& name = *it; | |
| 117 | printValueTree(fout, value[name], path + suffix + name); | |
| 118 | } | |
| 119 | } break; | |
| 120 | default: | |
| 121 | break; | |
| 122 | } | |
| 123 | ||
| 124 | if (value.hasComment(Json::commentAfter)) { | |
| 125 | fprintf(fout, "%s\n", value.getComment(Json::commentAfter).c_str()); | |
| 126 | } | |
| 127 | } | |
| 128 | ||
| 129 | static int parseAndSaveValueTree(const std::string& input, | |
| 130 | const std::string& actual, | |
| 131 | const std::string& kind, | |
| 132 | Json::Value& root, | |
| 133 | const Json::Features& features, | |
| 134 | bool parseOnly) { | |
| 135 | Json::Reader reader(features); | |
| 136 | bool parsingSuccessful = reader.parse(input, root); | |
| 137 | if (!parsingSuccessful) { | |
| 138 | printf("Failed to parse %s file: \n%s\n", | |
| 139 | kind.c_str(), | |
| 140 | reader.getFormattedErrorMessages().c_str()); | |
| 141 | return 1; | |
| 142 | } | |
| 143 | ||
| 144 | if (!parseOnly) { | |
| 145 | FILE* factual = fopen(actual.c_str(), "wt"); | |
| 146 | if (!factual) { | |
| 147 | printf("Failed to create %s actual file.\n", kind.c_str()); | |
| 148 | return 2; | |
| 149 | } | |
| 150 | printValueTree(factual, root); | |
| 151 | fclose(factual); | |
| 152 | } | |
| 153 | return 0; | |
| 154 | } | |
| 155 | ||
| 156 | static int rewriteValueTree(const std::string& rewritePath, | |
| 157 | const Json::Value& root, | |
| 158 | std::string& rewrite) { | |
| 159 | // Json::FastWriter writer; | |
| 160 | // writer.enableYAMLCompatibility(); | |
| 161 | Json::StyledWriter writer; | |
| 162 | rewrite = writer.write(root); | |
| 163 | FILE* fout = fopen(rewritePath.c_str(), "wt"); | |
| 164 | if (!fout) { | |
| 165 | printf("Failed to create rewrite file: %s\n", rewritePath.c_str()); | |
| 166 | return 2; | |
| 167 | } | |
| 168 | fprintf(fout, "%s\n", rewrite.c_str()); | |
| 169 | fclose(fout); | |
| 170 | return 0; | |
| 171 | } | |
| 172 | ||
| 173 | static std::string removeSuffix(const std::string& path, | |
| 174 | const std::string& extension) { | |
| 175 | if (extension.length() >= path.length()) | |
| 176 | return std::string(""); | |
| 177 | std::string suffix = path.substr(path.length() - extension.length()); | |
| 178 | if (suffix != extension) | |
| 179 | return std::string(""); | |
| 180 | return path.substr(0, path.length() - extension.length()); | |
| 181 | } | |
| 182 | ||
| 183 | static void printConfig() { | |
| 184 | // Print the configuration used to compile JsonCpp | |
| 185 | #if defined(JSON_NO_INT64) | |
| 186 | printf("JSON_NO_INT64=1\n"); | |
| 187 | #else | |
| 188 | printf("JSON_NO_INT64=0\n"); | |
| 189 | #endif | |
| 190 | } | |
| 191 | ||
| 192 | static int printUsage(const char* argv[]) { | |
| 193 | printf("Usage: %s [--strict] input-json-file", argv[0]); | |
| 194 | return 3; | |
| 195 | } | |
| 196 | ||
| 197 | int parseCommandLine(int argc, | |
| 198 | const char* argv[], | |
| 199 | Json::Features& features, | |
| 200 | std::string& path, | |
| 201 | bool& parseOnly) { | |
| 202 | parseOnly = false; | |
| 203 | if (argc < 2) { | |
| 204 | return printUsage(argv); | |
| 205 | } | |
| 206 | ||
| 207 | int index = 1; | |
| 208 | if (std::string(argv[1]) == "--json-checker") { | |
| 209 | features = Json::Features::strictMode(); | |
| 210 | parseOnly = true; | |
| 211 | ++index; | |
| 212 | } | |
| 213 | ||
| 214 | if (std::string(argv[1]) == "--json-config") { | |
| 215 | printConfig(); | |
| 216 | return 3; | |
| 217 | } | |
| 218 | ||
| 219 | if (index == argc || index + 1 < argc) { | |
| 220 | return printUsage(argv); | |
| 221 | } | |
| 222 | ||
| 223 | path = argv[index]; | |
| 224 | return 0; | |
| 225 | } | |
| 226 | ||
| 227 | int main(int argc, const char* argv[]) { | |
| 228 | std::string path; | |
| 229 | Json::Features features; | |
| 230 | bool parseOnly; | |
| 231 | int exitCode = parseCommandLine(argc, argv, features, path, parseOnly); | |
| 232 | if (exitCode != 0) { | |
| 233 | return exitCode; | |
| 234 | } | |
| 235 | ||
| 236 | try { | |
| 237 | std::string input = readInputTestFile(path.c_str()); | |
| 238 | if (input.empty()) { | |
| 239 | printf("Failed to read input or empty input: %s\n", path.c_str()); | |
| 240 | return 3; | |
| 241 | } | |
| 242 | ||
| 243 | std::string basePath = removeSuffix(argv[1], ".json"); | |
| 244 | if (!parseOnly && basePath.empty()) { | |
| 245 | printf("Bad input path. Path does not end with '.expected':\n%s\n", | |
| 246 | path.c_str()); | |
| 247 | return 3; | |
| 248 | } | |
| 249 | ||
| 250 | std::string actualPath = basePath + ".actual"; | |
| 251 | std::string rewritePath = basePath + ".rewrite"; | |
| 252 | std::string rewriteActualPath = basePath + ".actual-rewrite"; | |
| 253 | ||
| 254 | Json::Value root; | |
| 255 | exitCode = parseAndSaveValueTree( | |
| 256 | input, actualPath, "input", root, features, parseOnly); | |
| 257 | if (exitCode == 0 && !parseOnly) { | |
| 258 | std::string rewrite; | |
| 259 | exitCode = rewriteValueTree(rewritePath, root, rewrite); | |
| 260 | if (exitCode == 0) { | |
| 261 | Json::Value rewriteRoot; | |
| 262 | exitCode = parseAndSaveValueTree(rewrite, | |
| 263 | rewriteActualPath, | |
| 264 | "rewrite", | |
| 265 | rewriteRoot, | |
| 266 | features, | |
| 267 | parseOnly); | |
| 268 | } | |
| 269 | } | |
| 270 | } | |
| 271 | catch (const std::exception& e) { | |
| 272 | printf("Unhandled exception:\n%s\n", e.what()); | |
| 273 | exitCode = 1; | |
| 274 | } | |
| 275 | ||
| 276 | return exitCode; | |
| 277 | } |
| r0 | r242831 | |
|---|---|---|
| 1 | Import( 'env_testing buildJSONTests' ) | |
| 2 | ||
| 3 | buildJSONTests( env_testing, Split( """ | |
| 4 | main.cpp | |
| 5 | """ ), | |
| 6 | 'jsontestrunner' ) | |
| 7 | ||
| 8 | # For 'check' to work, 'libs' must be built first. | |
| 9 | env_testing.Depends('jsontestrunner', '#libs') |
| r0 | r242831 | |
|---|---|---|
| 1 | OPTION(JSONCPP_LIB_BUILD_SHARED "Build jsoncpp_lib as a shared library." OFF) | |
| 2 | IF(BUILD_SHARED_LIBS) | |
| 3 | SET(JSONCPP_LIB_BUILD_SHARED ON) | |
| 4 | ENDIF(BUILD_SHARED_LIBS) | |
| 5 | ||
| 6 | IF(JSONCPP_LIB_BUILD_SHARED) | |
| 7 | SET(JSONCPP_LIB_TYPE SHARED) | |
| 8 | ADD_DEFINITIONS( -DJSON_DLL_BUILD ) | |
| 9 | ELSE(JSONCPP_LIB_BUILD_SHARED) | |
| 10 | SET(JSONCPP_LIB_TYPE STATIC) | |
| 11 | ENDIF(JSONCPP_LIB_BUILD_SHARED) | |
| 12 | ||
| 13 | if( CMAKE_COMPILER_IS_GNUCXX ) | |
| 14 | #Get compiler version. | |
| 15 | execute_process( COMMAND ${CMAKE_CXX_COMPILER} -dumpversion | |
| 16 | OUTPUT_VARIABLE GNUCXX_VERSION ) | |
| 17 | ||
| 18 | #-Werror=* was introduced -after- GCC 4.1.2 | |
| 19 | if( GNUCXX_VERSION VERSION_GREATER 4.1.2 ) | |
| 20 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=strict-aliasing") | |
| 21 | endif() | |
| 22 | endif( CMAKE_COMPILER_IS_GNUCXX ) | |
| 23 | ||
| 24 | SET( JSONCPP_INCLUDE_DIR ../../include ) | |
| 25 | ||
| 26 | SET( PUBLIC_HEADERS | |
| 27 | ${JSONCPP_INCLUDE_DIR}/json/config.h | |
| 28 | ${JSONCPP_INCLUDE_DIR}/json/forwards.h | |
| 29 | ${JSONCPP_INCLUDE_DIR}/json/features.h | |
| 30 | ${JSONCPP_INCLUDE_DIR}/json/value.h | |
| 31 | ${JSONCPP_INCLUDE_DIR}/json/reader.h | |
| 32 | ${JSONCPP_INCLUDE_DIR}/json/writer.h | |
| 33 | ${JSONCPP_INCLUDE_DIR}/json/assertions.h | |
| 34 | ${JSONCPP_INCLUDE_DIR}/json/version.h | |
| 35 | ) | |
| 36 | ||
| 37 | SOURCE_GROUP( "Public API" FILES ${PUBLIC_HEADERS} ) | |
| 38 | ||
| 39 | ADD_LIBRARY( jsoncpp_lib ${JSONCPP_LIB_TYPE} | |
| 40 | ${PUBLIC_HEADERS} | |
| 41 | json_tool.h | |
| 42 | json_reader.cpp | |
| 43 | json_batchallocator.h | |
| 44 | json_valueiterator.inl | |
| 45 | json_value.cpp | |
| 46 | json_writer.cpp | |
| 47 | version.h.in | |
| 48 | ) | |
| 49 | SET_TARGET_PROPERTIES( jsoncpp_lib PROPERTIES OUTPUT_NAME jsoncpp ) | |
| 50 | SET_TARGET_PROPERTIES( jsoncpp_lib PROPERTIES VERSION ${JSONCPP_VERSION} SOVERSION ${JSONCPP_VERSION_MAJOR} ) | |
| 51 | ||
| 52 | IF(NOT CMAKE_VERSION VERSION_LESS 2.8.11) | |
| 53 | TARGET_INCLUDE_DIRECTORIES( jsoncpp_lib PUBLIC | |
| 54 | $<INSTALL_INTERFACE:${INCLUDE_INSTALL_DIR}> | |
| 55 | $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}> | |
| 56 | ) | |
| 57 | ENDIF(NOT CMAKE_VERSION VERSION_LESS 2.8.11) | |
| 58 | ||
| 59 | # Install instructions for this target | |
| 60 | IF(JSONCPP_WITH_CMAKE_PACKAGE) | |
| 61 | SET(INSTALL_EXPORT EXPORT jsoncpp) | |
| 62 | ELSE(JSONCPP_WITH_CMAKE_PACKAGE) | |
| 63 | SET(INSTALL_EXPORT) | |
| 64 | ENDIF(JSONCPP_WITH_CMAKE_PACKAGE) | |
| 65 | ||
| 66 | INSTALL( TARGETS jsoncpp_lib ${INSTALL_EXPORT} | |
| 67 | RUNTIME DESTINATION ${RUNTIME_INSTALL_DIR} | |
| 68 | LIBRARY DESTINATION ${LIBRARY_INSTALL_DIR} | |
| 69 | ARCHIVE DESTINATION ${ARCHIVE_INSTALL_DIR} | |
| 70 | ) |
| r0 | r242831 | |
|---|---|---|
| 1 | // Copyright 2007-2010 Baptiste Lepilleur | |
| 2 | // Distributed under MIT license, or public domain if desired and | |
| 3 | // recognized in your jurisdiction. | |
| 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE | |
| 5 | ||
| 6 | #ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED | |
| 7 | #define JSONCPP_BATCHALLOCATOR_H_INCLUDED | |
| 8 | ||
| 9 | #include <stdlib.h> | |
| 10 | #include <assert.h> | |
| 11 | ||
| 12 | #ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION | |
| 13 | ||
| 14 | namespace Json { | |
| 15 | ||
| 16 | /* Fast memory allocator. | |
| 17 | * | |
| 18 | * This memory allocator allocates memory for a batch of object (specified by | |
| 19 | * the page size, the number of object in each page). | |
| 20 | * | |
| 21 | * It does not allow the destruction of a single object. All the allocated | |
| 22 | * objects can be destroyed at once. The memory can be either released or reused | |
| 23 | * for future allocation. | |
| 24 | * | |
| 25 | * The in-place new operator must be used to construct the object using the | |
| 26 | * pointer returned by allocate. | |
| 27 | */ | |
| 28 | template <typename AllocatedType, const unsigned int objectPerAllocation> | |
| 29 | class BatchAllocator { | |
| 30 | public: | |
| 31 | BatchAllocator(unsigned int objectsPerPage = 255) | |
| 32 | : freeHead_(0), objectsPerPage_(objectsPerPage) { | |
| 33 | // printf( "Size: %d => %s\n", sizeof(AllocatedType), | |
| 34 | // typeid(AllocatedType).name() ); | |
| 35 | assert(sizeof(AllocatedType) * objectPerAllocation >= | |
| 36 | sizeof(AllocatedType*)); // We must be able to store a slist in the | |
| 37 | // object free space. | |
| 38 | assert(objectsPerPage >= 16); | |
| 39 | batches_ = allocateBatch(0); // allocated a dummy page | |
| 40 | currentBatch_ = batches_; | |
| 41 | } | |
| 42 | ||
| 43 | ~BatchAllocator() { | |
| 44 | for (BatchInfo* batch = batches_; batch;) { | |
| 45 | BatchInfo* nextBatch = batch->next_; | |
| 46 | free(batch); | |
| 47 | batch = nextBatch; | |
| 48 | } | |
| 49 | } | |
| 50 | ||
| 51 | /// allocate space for an array of objectPerAllocation object. | |
| 52 | /// @warning it is the responsability of the caller to call objects | |
| 53 | /// constructors. | |
| 54 | AllocatedType* allocate() { | |
| 55 | if (freeHead_) // returns node from free list. | |
| 56 | { | |
| 57 | AllocatedType* object = freeHead_; | |
| 58 | freeHead_ = *(AllocatedType**)object; | |
| 59 | return object; | |
| 60 | } | |
| 61 | if (currentBatch_->used_ == currentBatch_->end_) { | |
| 62 | currentBatch_ = currentBatch_->next_; | |
| 63 | while (currentBatch_ && currentBatch_->used_ == currentBatch_->end_) | |
| 64 | currentBatch_ = currentBatch_->next_; | |
| 65 | ||
| 66 | if (!currentBatch_) // no free batch found, allocate a new one | |
| 67 | { | |
| 68 | currentBatch_ = allocateBatch(objectsPerPage_); | |
| 69 | currentBatch_->next_ = batches_; // insert at the head of the list | |
| 70 | batches_ = currentBatch_; | |
| 71 | } | |
| 72 | } | |
| 73 | AllocatedType* allocated = currentBatch_->used_; | |
| 74 | currentBatch_->used_ += objectPerAllocation; | |
| 75 | return allocated; | |
| 76 | } | |
| 77 | ||
| 78 | /// Release the object. | |
| 79 | /// @warning it is the responsability of the caller to actually destruct the | |
| 80 | /// object. | |
| 81 | void release(AllocatedType* object) { | |
| 82 | assert(object != 0); | |
| 83 | *(AllocatedType**)object = freeHead_; | |
| 84 | freeHead_ = object; | |
| 85 | } | |
| 86 | ||
| 87 | private: | |
| 88 | struct BatchInfo { | |
| 89 | BatchInfo* next_; | |
| 90 | AllocatedType* used_; | |
| 91 | AllocatedType* end_; | |
| 92 | AllocatedType buffer_[objectPerAllocation]; | |
| 93 | }; | |
| 94 | ||
| 95 | // disabled copy constructor and assignement operator. | |
| 96 | BatchAllocator(const BatchAllocator&); | |
| 97 | void operator=(const BatchAllocator&); | |
| 98 | ||
| 99 | static BatchInfo* allocateBatch(unsigned int objectsPerPage) { | |
| 100 | const unsigned int mallocSize = | |
| 101 | sizeof(BatchInfo) - sizeof(AllocatedType) * objectPerAllocation + | |
| 102 | sizeof(AllocatedType) * objectPerAllocation * objectsPerPage; | |
| 103 | BatchInfo* batch = static_cast<BatchInfo*>(malloc(mallocSize)); | |
| 104 | batch->next_ = 0; | |
| 105 | batch->used_ = batch->buffer_; | |
| 106 | batch->end_ = batch->buffer_ + objectsPerPage; | |
| 107 | return batch; | |
| 108 | } | |
| 109 | ||
| 110 | BatchInfo* batches_; | |
| 111 | BatchInfo* currentBatch_; | |
| 112 | /// Head of a single linked list within the allocated space of freeed object | |
| 113 | AllocatedType* freeHead_; | |
| 114 | unsigned int objectsPerPage_; | |
| 115 | }; | |
| 116 | ||
| 117 | } // namespace Json | |
| 118 | ||
| 119 | #endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION | |
| 120 | ||
| 121 | #endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED |
| r0 | r242831 | |
|---|---|---|
| 1 | // Copyright 2007-2010 Baptiste Lepilleur | |
| 2 | // Distributed under MIT license, or public domain if desired and | |
| 3 | // recognized in your jurisdiction. | |
| 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE | |
| 5 | ||
| 6 | // included by json_value.cpp | |
| 7 | ||
| 8 | namespace Json { | |
| 9 | ||
| 10 | // ////////////////////////////////////////////////////////////////// | |
| 11 | // ////////////////////////////////////////////////////////////////// | |
| 12 | // ////////////////////////////////////////////////////////////////// | |
| 13 | // class ValueInternalArray | |
| 14 | // ////////////////////////////////////////////////////////////////// | |
| 15 | // ////////////////////////////////////////////////////////////////// | |
| 16 | // ////////////////////////////////////////////////////////////////// | |
| 17 | ||
| 18 | ValueArrayAllocator::~ValueArrayAllocator() {} | |
| 19 | ||
| 20 | // ////////////////////////////////////////////////////////////////// | |
| 21 | // class DefaultValueArrayAllocator | |
| 22 | // ////////////////////////////////////////////////////////////////// | |
| 23 | #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR | |
| 24 | class DefaultValueArrayAllocator : public ValueArrayAllocator { | |
| 25 | public: // overridden from ValueArrayAllocator | |
| 26 | virtual ~DefaultValueArrayAllocator() {} | |
| 27 | ||
| 28 | virtual ValueInternalArray* newArray() { return new ValueInternalArray(); } | |
| 29 | ||
| 30 | virtual ValueInternalArray* newArrayCopy(const ValueInternalArray& other) { | |
| 31 | return new ValueInternalArray(other); | |
| 32 | } | |
| 33 | ||
| 34 | virtual void destructArray(ValueInternalArray* array) { delete array; } | |
| 35 | ||
| 36 | virtual void | |
| 37 | reallocateArrayPageIndex(Value**& indexes, | |
| 38 | ValueInternalArray::PageIndex& indexCount, | |
| 39 | ValueInternalArray::PageIndex minNewIndexCount) { | |
| 40 | ValueInternalArray::PageIndex newIndexCount = (indexCount * 3) / 2 + 1; | |
| 41 | if (minNewIndexCount > newIndexCount) | |
| 42 | newIndexCount = minNewIndexCount; | |
| 43 | void* newIndexes = realloc(indexes, sizeof(Value*) * newIndexCount); | |
| 44 | JSON_ASSERT_MESSAGE(newIndexes, "Couldn't realloc."); | |
| 45 | indexCount = newIndexCount; | |
| 46 | indexes = static_cast<Value**>(newIndexes); | |
| 47 | } | |
| 48 | virtual void releaseArrayPageIndex(Value** indexes, | |
| 49 | ValueInternalArray::PageIndex indexCount) { | |
| 50 | if (indexes) | |
| 51 | free(indexes); | |
| 52 | } | |
| 53 | ||
| 54 | virtual Value* allocateArrayPage() { | |
| 55 | return static_cast<Value*>( | |
| 56 | malloc(sizeof(Value) * ValueInternalArray::itemsPerPage)); | |
| 57 | } | |
| 58 | ||
| 59 | virtual void releaseArrayPage(Value* value) { | |
| 60 | if (value) | |
| 61 | free(value); | |
| 62 | } | |
| 63 | }; | |
| 64 | ||
| 65 | #else // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR | |
| 66 | /// @todo make this thread-safe (lock when accessign batch allocator) | |
| 67 | class DefaultValueArrayAllocator : public ValueArrayAllocator { | |
| 68 | public: // overridden from ValueArrayAllocator | |
| 69 | virtual ~DefaultValueArrayAllocator() {} | |
| 70 | ||
| 71 | virtual ValueInternalArray* newArray() { | |
| 72 | ValueInternalArray* array = arraysAllocator_.allocate(); | |
| 73 | new (array) ValueInternalArray(); // placement new | |
| 74 | return array; | |
| 75 | } | |
| 76 | ||
| 77 | virtual ValueInternalArray* newArrayCopy(const ValueInternalArray& other) { | |
| 78 | ValueInternalArray* array = arraysAllocator_.allocate(); | |
| 79 | new (array) ValueInternalArray(other); // placement new | |
| 80 | return array; | |
| 81 | } | |
| 82 | ||
| 83 | virtual void destructArray(ValueInternalArray* array) { | |
| 84 | if (array) { | |
| 85 | array->~ValueInternalArray(); | |
| 86 | arraysAllocator_.release(array); | |
| 87 | } | |
| 88 | } | |
| 89 | ||
| 90 | virtual void | |
| 91 | reallocateArrayPageIndex(Value**& indexes, | |
| 92 | ValueInternalArray::PageIndex& indexCount, | |
| 93 | ValueInternalArray::PageIndex minNewIndexCount) { | |
| 94 | ValueInternalArray::PageIndex newIndexCount = (indexCount * 3) / 2 + 1; | |
| 95 | if (minNewIndexCount > newIndexCount) | |
| 96 | newIndexCount = minNewIndexCount; | |
| 97 | void* newIndexes = realloc(indexes, sizeof(Value*) * newIndexCount); | |
| 98 | JSON_ASSERT_MESSAGE(newIndexes, "Couldn't realloc."); | |
| 99 | indexCount = newIndexCount; | |
| 100 | indexes = static_cast<Value**>(newIndexes); | |
| 101 | } | |
| 102 | virtual void releaseArrayPageIndex(Value** indexes, | |
| 103 | ValueInternalArray::PageIndex indexCount) { | |
| 104 | if (indexes) | |
| 105 | free(indexes); | |
| 106 | } | |
| 107 | ||
| 108 | virtual Value* allocateArrayPage() { | |
| 109 | return static_cast<Value*>(pagesAllocator_.allocate()); | |
| 110 | } | |
| 111 | ||
| 112 | virtual void releaseArrayPage(Value* value) { | |
| 113 | if (value) | |
| 114 | pagesAllocator_.release(value); | |
| 115 | } | |
| 116 | ||
| 117 | private: | |
| 118 | BatchAllocator<ValueInternalArray, 1> arraysAllocator_; | |
| 119 | BatchAllocator<Value, ValueInternalArray::itemsPerPage> pagesAllocator_; | |
| 120 | }; | |
| 121 | #endif // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR | |
| 122 | ||
| 123 | static ValueArrayAllocator*& arrayAllocator() { | |
| 124 | static DefaultValueArrayAllocator defaultAllocator; | |
| 125 | static ValueArrayAllocator* arrayAllocator = &defaultAllocator; | |
| 126 | return arrayAllocator; | |
| 127 | } | |
| 128 | ||
| 129 | static struct DummyArrayAllocatorInitializer { | |
| 130 | DummyArrayAllocatorInitializer() { | |
| 131 | arrayAllocator(); // ensure arrayAllocator() statics are initialized before | |
| 132 | // main(). | |
| 133 | } | |
| 134 | } dummyArrayAllocatorInitializer; | |
| 135 | ||
| 136 | // ////////////////////////////////////////////////////////////////// | |
| 137 | // class ValueInternalArray | |
| 138 | // ////////////////////////////////////////////////////////////////// | |
| 139 | bool ValueInternalArray::equals(const IteratorState& x, | |
| 140 | const IteratorState& other) { | |
| 141 | return x.array_ == other.array_ && | |
| 142 | x.currentItemIndex_ == other.currentItemIndex_ && | |
| 143 | x.currentPageIndex_ == other.currentPageIndex_; | |
| 144 | } | |
| 145 | ||
| 146 | void ValueInternalArray::increment(IteratorState& it) { | |
| 147 | JSON_ASSERT_MESSAGE( | |
| 148 | it.array_ && (it.currentPageIndex_ - it.array_->pages_) * itemsPerPage + | |
| 149 | it.currentItemIndex_ != | |
| 150 | it.array_->size_, | |
| 151 | "ValueInternalArray::increment(): moving iterator beyond end"); | |
| 152 | ++(it.currentItemIndex_); | |
| 153 | if (it.currentItemIndex_ == itemsPerPage) { | |
| 154 | it.currentItemIndex_ = 0; | |
| 155 | ++(it.currentPageIndex_); | |
| 156 | } | |
| 157 | } | |
| 158 | ||
| 159 | void ValueInternalArray::decrement(IteratorState& it) { | |
| 160 | JSON_ASSERT_MESSAGE( | |
| 161 | it.array_ && it.currentPageIndex_ == it.array_->pages_ && | |
| 162 | it.currentItemIndex_ == 0, | |
| 163 | "ValueInternalArray::decrement(): moving iterator beyond end"); | |
| 164 | if (it.currentItemIndex_ == 0) { | |
| 165 | it.currentItemIndex_ = itemsPerPage - 1; | |
| 166 | --(it.currentPageIndex_); | |
| 167 | } else { | |
| 168 | --(it.currentItemIndex_); | |
| 169 | } | |
| 170 | } | |
| 171 | ||
| 172 | Value& ValueInternalArray::unsafeDereference(const IteratorState& it) { | |
| 173 | return (*(it.currentPageIndex_))[it.currentItemIndex_]; | |
| 174 | } | |
| 175 | ||
| 176 | Value& ValueInternalArray::dereference(const IteratorState& it) { | |
| 177 | JSON_ASSERT_MESSAGE( | |
| 178 | it.array_ && (it.currentPageIndex_ - it.array_->pages_) * itemsPerPage + | |
| 179 | it.currentItemIndex_ < | |
| 180 | it.array_->size_, | |
| 181 | "ValueInternalArray::dereference(): dereferencing invalid iterator"); | |
| 182 | return unsafeDereference(it); | |
| 183 | } | |
| 184 | ||
| 185 | void ValueInternalArray::makeBeginIterator(IteratorState& it) const { | |
| 186 | it.array_ = const_cast<ValueInternalArray*>(this); | |
| 187 | it.currentItemIndex_ = 0; | |
| 188 | it.currentPageIndex_ = pages_; | |
| 189 | } | |
| 190 | ||
| 191 | void ValueInternalArray::makeIterator(IteratorState& it, | |
| 192 | ArrayIndex index) const { | |
| 193 | it.array_ = const_cast<ValueInternalArray*>(this); | |
| 194 | it.currentItemIndex_ = index % itemsPerPage; | |
| 195 | it.currentPageIndex_ = pages_ + index / itemsPerPage; | |
| 196 | } | |
| 197 | ||
| 198 | void ValueInternalArray::makeEndIterator(IteratorState& it) const { | |
| 199 | makeIterator(it, size_); | |
| 200 | } | |
| 201 | ||
| 202 | ValueInternalArray::ValueInternalArray() : pages_(0), size_(0), pageCount_(0) {} | |
| 203 | ||
| 204 | ValueInternalArray::ValueInternalArray(const ValueInternalArray& other) | |
| 205 | : pages_(0), size_(other.size_), pageCount_(0) { | |
| 206 | PageIndex minNewPages = other.size_ / itemsPerPage; | |
| 207 | arrayAllocator()->reallocateArrayPageIndex(pages_, pageCount_, minNewPages); | |
| 208 | JSON_ASSERT_MESSAGE(pageCount_ >= minNewPages, | |
| 209 | "ValueInternalArray::reserve(): bad reallocation"); | |
| 210 | IteratorState itOther; | |
| 211 | other.makeBeginIterator(itOther); | |
| 212 | Value* value; | |
| 213 | for (ArrayIndex index = 0; index < size_; ++index, increment(itOther)) { | |
| 214 | if (index % itemsPerPage == 0) { | |
| 215 | PageIndex pageIndex = index / itemsPerPage; | |
| 216 | value = arrayAllocator()->allocateArrayPage(); | |
| 217 | pages_[pageIndex] = value; | |
| 218 | } | |
| 219 | new (value) Value(dereference(itOther)); | |
| 220 | } | |
| 221 | } | |
| 222 | ||
| 223 | ValueInternalArray& ValueInternalArray::operator=(ValueInternalArray other) { | |
| 224 | swap(other); | |
| 225 | return *this; | |
| 226 | } | |
| 227 | ||
| 228 | ValueInternalArray::~ValueInternalArray() { | |
| 229 | // destroy all constructed items | |
| 230 | IteratorState it; | |
| 231 | IteratorState itEnd; | |
| 232 | makeBeginIterator(it); | |
| 233 | makeEndIterator(itEnd); | |
| 234 | for (; !equals(it, itEnd); increment(it)) { | |
| 235 | Value* value = &dereference(it); | |
| 236 | value->~Value(); | |
| 237 | } | |
| 238 | // release all pages | |
| 239 | PageIndex lastPageIndex = size_ / itemsPerPage; | |
| 240 | for (PageIndex pageIndex = 0; pageIndex < lastPageIndex; ++pageIndex) | |
| 241 | arrayAllocator()->releaseArrayPage(pages_[pageIndex]); | |
| 242 | // release pages index | |
| 243 | arrayAllocator()->releaseArrayPageIndex(pages_, pageCount_); | |
| 244 | } | |
| 245 | ||
| 246 | void ValueInternalArray::swap(ValueInternalArray& other) { | |
| 247 | Value** tempPages = pages_; | |
| 248 | pages_ = other.pages_; | |
| 249 | other.pages_ = tempPages; | |
| 250 | ArrayIndex tempSize = size_; | |
| 251 | size_ = other.size_; | |
| 252 | other.size_ = tempSize; | |
| 253 | PageIndex tempPageCount = pageCount_; | |
| 254 | pageCount_ = other.pageCount_; | |
| 255 | other.pageCount_ = tempPageCount; | |
| 256 | } | |
| 257 | ||
| 258 | void ValueInternalArray::clear() { | |
| 259 | ValueInternalArray dummy; | |
| 260 | swap(dummy); | |
| 261 | } | |
| 262 | ||
| 263 | void ValueInternalArray::resize(ArrayIndex newSize) { | |
| 264 | if (newSize == 0) | |
| 265 | clear(); | |
| 266 | else if (newSize < size_) { | |
| 267 | IteratorState it; | |
| 268 | IteratorState itEnd; | |
| 269 | makeIterator(it, newSize); | |
| 270 | makeIterator(itEnd, size_); | |
| 271 | for (; !equals(it, itEnd); increment(it)) { | |
| 272 | Value* value = &dereference(it); | |
| 273 | value->~Value(); | |
| 274 | } | |
| 275 | PageIndex pageIndex = (newSize + itemsPerPage - 1) / itemsPerPage; | |
| 276 | PageIndex lastPageIndex = size_ / itemsPerPage; | |
| 277 | for (; pageIndex < lastPageIndex; ++pageIndex) | |
| 278 | arrayAllocator()->releaseArrayPage(pages_[pageIndex]); | |
| 279 | size_ = newSize; | |
| 280 | } else if (newSize > size_) | |
| 281 | resolveReference(newSize); | |
| 282 | } | |
| 283 | ||
| 284 | void ValueInternalArray::makeIndexValid(ArrayIndex index) { | |
| 285 | // Need to enlarge page index ? | |
| 286 | if (index >= pageCount_ * itemsPerPage) { | |
| 287 | PageIndex minNewPages = (index + 1) / itemsPerPage; | |
| 288 | arrayAllocator()->reallocateArrayPageIndex(pages_, pageCount_, minNewPages); | |
| 289 | JSON_ASSERT_MESSAGE(pageCount_ >= minNewPages, | |
| 290 | "ValueInternalArray::reserve(): bad reallocation"); | |
| 291 | } | |
| 292 | ||
| 293 | // Need to allocate new pages ? | |
| 294 | ArrayIndex nextPageIndex = (size_ % itemsPerPage) != 0 | |
| 295 | ? size_ - (size_ % itemsPerPage) + itemsPerPage | |
| 296 | : size_; | |
| 297 | if (nextPageIndex <= index) { | |
| 298 | PageIndex pageIndex = nextPageIndex / itemsPerPage; | |
| 299 | PageIndex pageToAllocate = (index - nextPageIndex) / itemsPerPage + 1; | |
| 300 | for (; pageToAllocate-- > 0; ++pageIndex) | |
| 301 | pages_[pageIndex] = arrayAllocator()->allocateArrayPage(); | |
| 302 | } | |
| 303 | ||
| 304 | // Initialize all new entries | |
| 305 | IteratorState it; | |
| 306 | IteratorState itEnd; | |
| 307 | makeIterator(it, size_); | |
| 308 | size_ = index + 1; | |
| 309 | makeIterator(itEnd, size_); | |
| 310 | for (; !equals(it, itEnd); increment(it)) { | |
| 311 | Value* value = &dereference(it); | |
| 312 | new (value) Value(); // Construct a default value using placement new | |
| 313 | } | |
| 314 | } | |
| 315 | ||
| 316 | Value& ValueInternalArray::resolveReference(ArrayIndex index) { | |
| 317 | if (index >= size_) | |
| 318 | makeIndexValid(index); | |
| 319 | return pages_[index / itemsPerPage][index % itemsPerPage]; | |
| 320 | } | |
| 321 | ||
| 322 | Value* ValueInternalArray::find(ArrayIndex index) const { | |
| 323 | if (index >= size_) | |
| 324 | return 0; | |
| 325 | return &(pages_[index / itemsPerPage][index % itemsPerPage]); | |
| 326 | } | |
| 327 | ||
| 328 | ValueInternalArray::ArrayIndex ValueInternalArray::size() const { | |
| 329 | return size_; | |
| 330 | } | |
| 331 | ||
| 332 | int ValueInternalArray::distance(const IteratorState& x, | |
| 333 | const IteratorState& y) { | |
| 334 | return indexOf(y) - indexOf(x); | |
| 335 | } | |
| 336 | ||
| 337 | ValueInternalArray::ArrayIndex | |
| 338 | ValueInternalArray::indexOf(const IteratorState& iterator) { | |
| 339 | if (!iterator.array_) | |
| 340 | return ArrayIndex(-1); | |
| 341 | return ArrayIndex((iterator.currentPageIndex_ - iterator.array_->pages_) * | |
| 342 | itemsPerPage + | |
| 343 | iterator.currentItemIndex_); | |
| 344 | } | |
| 345 | ||
| 346 | int ValueInternalArray::compare(const ValueInternalArray& other) const { | |
| 347 | int sizeDiff(size_ - other.size_); | |
| 348 | if (sizeDiff != 0) | |
| 349 | return sizeDiff; | |
| 350 | ||
| 351 | for (ArrayIndex index = 0; index < size_; ++index) { | |
| 352 | int diff = pages_[index / itemsPerPage][index % itemsPerPage].compare( | |
| 353 | other.pages_[index / itemsPerPage][index % itemsPerPage]); | |
| 354 | if (diff != 0) | |
| 355 | return diff; | |
| 356 | } | |
| 357 | return 0; | |
| 358 | } | |
| 359 | ||
| 360 | } // namespace Json |
| r0 | r242831 | |
|---|---|---|
| 1 | // Copyright 2007-2010 Baptiste Lepilleur | |
| 2 | // Distributed under MIT license, or public domain if desired and | |
| 3 | // recognized in your jurisdiction. | |
| 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE | |
| 5 | ||
| 6 | // included by json_value.cpp | |
| 7 | ||
| 8 | namespace Json { | |
| 9 | ||
| 10 | // ////////////////////////////////////////////////////////////////// | |
| 11 | // ////////////////////////////////////////////////////////////////// | |
| 12 | // ////////////////////////////////////////////////////////////////// | |
| 13 | // class ValueInternalMap | |
| 14 | // ////////////////////////////////////////////////////////////////// | |
| 15 | // ////////////////////////////////////////////////////////////////// | |
| 16 | // ////////////////////////////////////////////////////////////////// | |
| 17 | ||
| 18 | /** \internal MUST be safely initialized using memset( this, 0, | |
| 19 | * sizeof(ValueInternalLink) ); | |
| 20 | * This optimization is used by the fast allocator. | |
| 21 | */ | |
| 22 | ValueInternalLink::ValueInternalLink() : previous_(0), next_(0) {} | |
| 23 | ||
| 24 | ValueInternalLink::~ValueInternalLink() { | |
| 25 | for (int index = 0; index < itemPerLink; ++index) { | |
| 26 | if (!items_[index].isItemAvailable()) { | |
| 27 | if (!items_[index].isMemberNameStatic()) | |
| 28 | free(keys_[index]); | |
| 29 | } else | |
| 30 | break; | |
| 31 | } | |
| 32 | } | |
| 33 | ||
| 34 | ValueMapAllocator::~ValueMapAllocator() {} | |
| 35 | ||
| 36 | #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR | |
| 37 | class DefaultValueMapAllocator : public ValueMapAllocator { | |
| 38 | public: // overridden from ValueMapAllocator | |
| 39 | virtual ValueInternalMap* newMap() { return new ValueInternalMap(); } | |
| 40 | ||
| 41 | virtual ValueInternalMap* newMapCopy(const ValueInternalMap& other) { | |
| 42 | return new ValueInternalMap(other); | |
| 43 | } | |
| 44 | ||
| 45 | virtual void destructMap(ValueInternalMap* map) { delete map; } | |
| 46 | ||
| 47 | virtual ValueInternalLink* allocateMapBuckets(unsigned int size) { | |
| 48 | return new ValueInternalLink[size]; | |
| 49 | } | |
| 50 | ||
| 51 | virtual void releaseMapBuckets(ValueInternalLink* links) { delete[] links; } | |
| 52 | ||
| 53 | virtual ValueInternalLink* allocateMapLink() { | |
| 54 | return new ValueInternalLink(); | |
| 55 | } | |
| 56 | ||
| 57 | virtual void releaseMapLink(ValueInternalLink* link) { delete link; } | |
| 58 | }; | |
| 59 | #else | |
| 60 | /// @todo make this thread-safe (lock when accessign batch allocator) | |
| 61 | class DefaultValueMapAllocator : public ValueMapAllocator { | |
| 62 | public: // overridden from ValueMapAllocator | |
| 63 | virtual ValueInternalMap* newMap() { | |
| 64 | ValueInternalMap* map = mapsAllocator_.allocate(); | |
| 65 | new (map) ValueInternalMap(); // placement new | |
| 66 | return map; | |
| 67 | } | |
| 68 | ||
| 69 | virtual ValueInternalMap* newMapCopy(const ValueInternalMap& other) { | |
| 70 | ValueInternalMap* map = mapsAllocator_.allocate(); | |
| 71 | new (map) ValueInternalMap(other); // placement new | |
| 72 | return map; | |
| 73 | } | |
| 74 | ||
| 75 | virtual void destructMap(ValueInternalMap* map) { | |
| 76 | if (map) { | |
| 77 | map->~ValueInternalMap(); | |
| 78 | mapsAllocator_.release(map); | |
| 79 | } | |
| 80 | } | |
| 81 | ||
| 82 | virtual ValueInternalLink* allocateMapBuckets(unsigned int size) { | |
| 83 | return new ValueInternalLink[size]; | |
| 84 | } | |
| 85 | ||
| 86 | virtual void releaseMapBuckets(ValueInternalLink* links) { delete[] links; } | |
| 87 | ||
| 88 | virtual ValueInternalLink* allocateMapLink() { | |
| 89 | ValueInternalLink* link = linksAllocator_.allocate(); | |
| 90 | memset(link, 0, sizeof(ValueInternalLink)); | |
| 91 | return link; | |
| 92 | } | |
| 93 | ||
| 94 | virtual void releaseMapLink(ValueInternalLink* link) { | |
| 95 | link->~ValueInternalLink(); | |
| 96 | linksAllocator_.release(link); | |
| 97 | } | |
| 98 | ||
| 99 | private: | |
| 100 | BatchAllocator<ValueInternalMap, 1> mapsAllocator_; | |
| 101 | BatchAllocator<ValueInternalLink, 1> linksAllocator_; | |
| 102 | }; | |
| 103 | #endif | |
| 104 | ||
| 105 | static ValueMapAllocator*& mapAllocator() { | |
| 106 | static DefaultValueMapAllocator defaultAllocator; | |
| 107 | static ValueMapAllocator* mapAllocator = &defaultAllocator; | |
| 108 | return mapAllocator; | |
| 109 | } | |
| 110 | ||
| 111 | static struct DummyMapAllocatorInitializer { | |
| 112 | DummyMapAllocatorInitializer() { | |
| 113 | mapAllocator(); // ensure mapAllocator() statics are initialized before | |
| 114 | // main(). | |
| 115 | } | |
| 116 | } dummyMapAllocatorInitializer; | |
| 117 | ||
| 118 | // h(K) = value * K >> w ; with w = 32 & K prime w.r.t. 2^32. | |
| 119 | ||
| 120 | /* | |
| 121 | use linked list hash map. | |
| 122 | buckets array is a container. | |
| 123 | linked list element contains 6 key/values. (memory = (16+4) * 6 + 4 = 124) | |
| 124 | value have extra state: valid, available, deleted | |
| 125 | */ | |
| 126 | ||
| 127 | ValueInternalMap::ValueInternalMap() | |
| 128 | : buckets_(0), tailLink_(0), bucketsSize_(0), itemCount_(0) {} | |
| 129 | ||
| 130 | ValueInternalMap::ValueInternalMap(const ValueInternalMap& other) | |
| 131 | : buckets_(0), tailLink_(0), bucketsSize_(0), itemCount_(0) { | |
| 132 | reserve(other.itemCount_); | |
| 133 | IteratorState it; | |
| 134 | IteratorState itEnd; | |
| 135 | other.makeBeginIterator(it); | |
| 136 | other.makeEndIterator(itEnd); | |
| 137 | for (; !equals(it, itEnd); increment(it)) { | |
| 138 | bool isStatic; | |
| 139 | const char* memberName = key(it, isStatic); | |
| 140 | const Value& aValue = value(it); | |
| 141 | resolveReference(memberName, isStatic) = aValue; | |
| 142 | } | |
| 143 | } | |
| 144 | ||
| 145 | ValueInternalMap& ValueInternalMap::operator=(ValueInternalMap other) { | |
| 146 | swap(other); | |
| 147 | return *this; | |
| 148 | } | |
| 149 | ||
| 150 | ValueInternalMap::~ValueInternalMap() { | |
| 151 | if (buckets_) { | |
| 152 | for (BucketIndex bucketIndex = 0; bucketIndex < bucketsSize_; | |
| 153 | ++bucketIndex) { | |
| 154 | ValueInternalLink* link = buckets_[bucketIndex].next_; | |
| 155 | while (link) { | |
| 156 | ValueInternalLink* linkToRelease = link; | |
| 157 | link = link->next_; | |
| 158 | mapAllocator()->releaseMapLink(linkToRelease); | |
| 159 | } | |
| 160 | } | |
| 161 | mapAllocator()->releaseMapBuckets(buckets_); | |
| 162 | } | |
| 163 | } | |
| 164 | ||
| 165 | void ValueInternalMap::swap(ValueInternalMap& other) { | |
| 166 | ValueInternalLink* tempBuckets = buckets_; | |
| 167 | buckets_ = other.buckets_; | |
| 168 | other.buckets_ = tempBuckets; | |
| 169 | ValueInternalLink* tempTailLink = tailLink_; | |
| 170 | tailLink_ = other.tailLink_; | |
| 171 | other.tailLink_ = tempTailLink; | |
| 172 | BucketIndex tempBucketsSize = bucketsSize_; | |
| 173 | bucketsSize_ = other.bucketsSize_; | |
| 174 | other.bucketsSize_ = tempBucketsSize; | |
| 175 | BucketIndex tempItemCount = itemCount_; | |
| 176 | itemCount_ = other.itemCount_; | |
| 177 | other.itemCount_ = tempItemCount; | |
| 178 | } | |
| 179 | ||
| 180 | void ValueInternalMap::clear() { | |
| 181 | ValueInternalMap dummy; | |
| 182 | swap(dummy); | |
| 183 | } | |
| 184 | ||
| 185 | ValueInternalMap::BucketIndex ValueInternalMap::size() const { | |
| 186 | return itemCount_; | |
| 187 | } | |
| 188 | ||
| 189 | bool ValueInternalMap::reserveDelta(BucketIndex growth) { | |
| 190 | return reserve(itemCount_ + growth); | |
| 191 | } | |
| 192 | ||
| 193 | bool ValueInternalMap::reserve(BucketIndex newItemCount) { | |
| 194 | if (!buckets_ && newItemCount > 0) { | |
| 195 | buckets_ = mapAllocator()->allocateMapBuckets(1); | |
| 196 | bucketsSize_ = 1; | |
| 197 | tailLink_ = &buckets_[0]; | |
| 198 | } | |
| 199 | // BucketIndex idealBucketCount = (newItemCount + | |
| 200 | // ValueInternalLink::itemPerLink) / ValueInternalLink::itemPerLink; | |
| 201 | return true; | |
| 202 | } | |
| 203 | ||
| 204 | const Value* ValueInternalMap::find(const char* key) const { | |
| 205 | if (!bucketsSize_) | |
| 206 | return 0; | |
| 207 | HashKey hashedKey = hash(key); | |
| 208 | BucketIndex bucketIndex = hashedKey % bucketsSize_; | |
| 209 | for (const ValueInternalLink* current = &buckets_[bucketIndex]; current != 0; | |
| 210 | current = current->next_) { | |
| 211 | for (BucketIndex index = 0; index < ValueInternalLink::itemPerLink; | |
| 212 | ++index) { | |
| 213 | if (current->items_[index].isItemAvailable()) | |
| 214 | return 0; | |
| 215 | if (strcmp(key, current->keys_[index]) == 0) | |
| 216 | return ¤t->items_[index]; | |
| 217 | } | |
| 218 | } | |
| 219 | return 0; | |
| 220 | } | |
| 221 | ||
| 222 | Value* ValueInternalMap::find(const char* key) { | |
| 223 | const ValueInternalMap* constThis = this; | |
| 224 | return const_cast<Value*>(constThis->find(key)); | |
| 225 | } | |
| 226 | ||
| 227 | Value& ValueInternalMap::resolveReference(const char* key, bool isStatic) { | |
| 228 | HashKey hashedKey = hash(key); | |
| 229 | if (bucketsSize_) { | |
| 230 | BucketIndex bucketIndex = hashedKey % bucketsSize_; | |
| 231 | ValueInternalLink** previous = 0; | |
| 232 | BucketIndex index; | |
| 233 | for (ValueInternalLink* current = &buckets_[bucketIndex]; current != 0; | |
| 234 | previous = ¤t->next_, current = current->next_) { | |
| 235 | for (index = 0; index < ValueInternalLink::itemPerLink; ++index) { | |
| 236 | if (current->items_[index].isItemAvailable()) | |
| 237 | return setNewItem(key, isStatic, current, index); | |
| 238 | if (strcmp(key, current->keys_[index]) == 0) | |
| 239 | return current->items_[index]; | |
| 240 | } | |
| 241 | } | |
| 242 | } | |
| 243 | ||
| 244 | reserveDelta(1); | |
| 245 | return unsafeAdd(key, isStatic, hashedKey); | |
| 246 | } | |
| 247 | ||
| 248 | void ValueInternalMap::remove(const char* key) { | |
| 249 | HashKey hashedKey = hash(key); | |
| 250 | if (!bucketsSize_) | |
| 251 | return; | |
| 252 | BucketIndex bucketIndex = hashedKey % bucketsSize_; | |
| 253 | for (ValueInternalLink* link = &buckets_[bucketIndex]; link != 0; | |
| 254 | link = link->next_) { | |
| 255 | BucketIndex index; | |
| 256 | for (index = 0; index < ValueInternalLink::itemPerLink; ++index) { | |
| 257 | if (link->items_[index].isItemAvailable()) | |
| 258 | return; | |
| 259 | if (strcmp(key, link->keys_[index]) == 0) { | |
| 260 | doActualRemove(link, index, bucketIndex); | |
| 261 | return; | |
| 262 | } | |
| 263 | } | |
| 264 | } | |
| 265 | } | |
| 266 | ||
| 267 | void ValueInternalMap::doActualRemove(ValueInternalLink* link, | |
| 268 | BucketIndex index, | |
| 269 | BucketIndex bucketIndex) { | |
| 270 | // find last item of the bucket and swap it with the 'removed' one. | |
| 271 | // set removed items flags to 'available'. | |
| 272 | // if last page only contains 'available' items, then desallocate it (it's | |
| 273 | // empty) | |
| 274 | ValueInternalLink*& lastLink = getLastLinkInBucket(index); | |
| 275 | BucketIndex lastItemIndex = 1; // a link can never be empty, so start at 1 | |
| 276 | for (; lastItemIndex < ValueInternalLink::itemPerLink; | |
| 277 | ++lastItemIndex) // may be optimized with dicotomic search | |
| 278 | { | |
| 279 | if (lastLink->items_[lastItemIndex].isItemAvailable()) | |
| 280 | break; | |
| 281 | } | |
| 282 | ||
| 283 | BucketIndex lastUsedIndex = lastItemIndex - 1; | |
| 284 | Value* valueToDelete = &link->items_[index]; | |
| 285 | Value* valueToPreserve = &lastLink->items_[lastUsedIndex]; | |
| 286 | if (valueToDelete != valueToPreserve) | |
| 287 | valueToDelete->swap(*valueToPreserve); | |
| 288 | if (lastUsedIndex == 0) // page is now empty | |
| 289 | { // remove it from bucket linked list and delete it. | |
| 290 | ValueInternalLink* linkPreviousToLast = lastLink->previous_; | |
| 291 | if (linkPreviousToLast != 0) // can not deleted bucket link. | |
| 292 | { | |
| 293 | mapAllocator()->releaseMapLink(lastLink); | |
| 294 | linkPreviousToLast->next_ = 0; | |
| 295 | lastLink = linkPreviousToLast; | |
| 296 | } | |
| 297 | } else { | |
| 298 | Value dummy; | |
| 299 | valueToPreserve->swap(dummy); // restore deleted to default Value. | |
| 300 | valueToPreserve->setItemUsed(false); | |
| 301 | } | |
| 302 | --itemCount_; | |
| 303 | } | |
| 304 | ||
| 305 | ValueInternalLink*& | |
| 306 | ValueInternalMap::getLastLinkInBucket(BucketIndex bucketIndex) { | |
| 307 | if (bucketIndex == bucketsSize_ - 1) | |
| 308 | return tailLink_; | |
| 309 | ValueInternalLink*& previous = buckets_[bucketIndex + 1].previous_; | |
| 310 | if (!previous) | |
| 311 | previous = &buckets_[bucketIndex]; | |
| 312 | return previous; | |
| 313 | } | |
| 314 | ||
| 315 | Value& ValueInternalMap::setNewItem(const char* key, | |
| 316 | bool isStatic, | |
| 317 | ValueInternalLink* link, | |
| 318 | BucketIndex index) { | |
| 319 | char* duplicatedKey = makeMemberName(key); | |
| 320 | ++itemCount_; | |
| 321 | link->keys_[index] = duplicatedKey; | |
| 322 | link->items_[index].setItemUsed(); | |
| 323 | link->items_[index].setMemberNameIsStatic(isStatic); | |
| 324 | return link->items_[index]; // items already default constructed. | |
| 325 | } | |
| 326 | ||
| 327 | Value& | |
| 328 | ValueInternalMap::unsafeAdd(const char* key, bool isStatic, HashKey hashedKey) { | |
| 329 | JSON_ASSERT_MESSAGE(bucketsSize_ > 0, | |
| 330 | "ValueInternalMap::unsafeAdd(): internal logic error."); | |
| 331 | BucketIndex bucketIndex = hashedKey % bucketsSize_; | |
| 332 | ValueInternalLink*& previousLink = getLastLinkInBucket(bucketIndex); | |
| 333 | ValueInternalLink* link = previousLink; | |
| 334 | BucketIndex index; | |
| 335 | for (index = 0; index < ValueInternalLink::itemPerLink; ++index) { | |
| 336 | if (link->items_[index].isItemAvailable()) | |
| 337 | break; | |
| 338 | } | |
| 339 | if (index == ValueInternalLink::itemPerLink) // need to add a new page | |
| 340 | { | |
| 341 | ValueInternalLink* newLink = mapAllocator()->allocateMapLink(); | |
| 342 | index = 0; | |
| 343 | link->next_ = newLink; | |
| 344 | previousLink = newLink; | |
| 345 | link = newLink; | |
| 346 | } | |
| 347 | return setNewItem(key, isStatic, link, index); | |
| 348 | } | |
| 349 | ||
| 350 | ValueInternalMap::HashKey ValueInternalMap::hash(const char* key) const { | |
| 351 | HashKey hash = 0; | |
| 352 | while (*key) | |
| 353 | hash += *key++ * 37; | |
| 354 | return hash; | |
| 355 | } | |
| 356 | ||
| 357 | int ValueInternalMap::compare(const ValueInternalMap& other) const { | |
| 358 | int sizeDiff(itemCount_ - other.itemCount_); | |
| 359 | if (sizeDiff != 0) | |
| 360 | return sizeDiff; | |
| 361 | // Strict order guaranty is required. Compare all keys FIRST, then compare | |
| 362 | // values. | |
| 363 | IteratorState it; | |
| 364 | IteratorState itEnd; | |
| 365 | makeBeginIterator(it); | |
| 366 | makeEndIterator(itEnd); | |
| 367 | for (; !equals(it, itEnd); increment(it)) { | |
| 368 | if (!other.find(key(it))) | |
| 369 | return 1; | |
| 370 | } | |
| 371 | ||
| 372 | // All keys are equals, let's compare values | |
| 373 | makeBeginIterator(it); | |
| 374 | for (; !equals(it, itEnd); increment(it)) { | |
| 375 | const Value* otherValue = other.find(key(it)); | |
| 376 | int valueDiff = value(it).compare(*otherValue); | |
| 377 | if (valueDiff != 0) | |
| 378 | return valueDiff; | |
| 379 | } | |
| 380 | return 0; | |
| 381 | } | |
| 382 | ||
| 383 | void ValueInternalMap::makeBeginIterator(IteratorState& it) const { | |
| 384 | it.map_ = const_cast<ValueInternalMap*>(this); | |
| 385 | it.bucketIndex_ = 0; | |
| 386 | it.itemIndex_ = 0; | |
| 387 | it.link_ = buckets_; | |
| 388 | } | |
| 389 | ||
| 390 | void ValueInternalMap::makeEndIterator(IteratorState& it) const { | |
| 391 | it.map_ = const_cast<ValueInternalMap*>(this); | |
| 392 | it.bucketIndex_ = bucketsSize_; | |
| 393 | it.itemIndex_ = 0; | |
| 394 | it.link_ = 0; | |
| 395 | } | |
| 396 | ||
| 397 | bool ValueInternalMap::equals(const IteratorState& x, | |
| 398 | const IteratorState& other) { | |
| 399 | return x.map_ == other.map_ && x.bucketIndex_ == other.bucketIndex_ && | |
| 400 | x.link_ == other.link_ && x.itemIndex_ == other.itemIndex_; | |
| 401 | } | |
| 402 | ||
| 403 | void ValueInternalMap::incrementBucket(IteratorState& iterator) { | |
| 404 | ++iterator.bucketIndex_; | |
| 405 | JSON_ASSERT_MESSAGE( | |
| 406 | iterator.bucketIndex_ <= iterator.map_->bucketsSize_, | |
| 407 | "ValueInternalMap::increment(): attempting to iterate beyond end."); | |
| 408 | if (iterator.bucketIndex_ == iterator.map_->bucketsSize_) | |
| 409 | iterator.link_ = 0; | |
| 410 | else | |
| 411 | iterator.link_ = &(iterator.map_->buckets_[iterator.bucketIndex_]); | |
| 412 | iterator.itemIndex_ = 0; | |
| 413 | } | |
| 414 | ||
| 415 | void ValueInternalMap::increment(IteratorState& iterator) { | |
| 416 | JSON_ASSERT_MESSAGE(iterator.map_, | |
| 417 | "Attempting to iterator using invalid iterator."); | |
| 418 | ++iterator.itemIndex_; | |
| 419 | if (iterator.itemIndex_ == ValueInternalLink::itemPerLink) { | |
| 420 | JSON_ASSERT_MESSAGE( | |
| 421 | iterator.link_ != 0, | |
| 422 | "ValueInternalMap::increment(): attempting to iterate beyond end."); | |
| 423 | iterator.link_ = iterator.link_->next_; | |
| 424 | if (iterator.link_ == 0) | |
| 425 | incrementBucket(iterator); | |
| 426 | } else if (iterator.link_->items_[iterator.itemIndex_].isItemAvailable()) { | |
| 427 | incrementBucket(iterator); | |
| 428 | } | |
| 429 | } | |
| 430 | ||
| 431 | void ValueInternalMap::decrement(IteratorState& iterator) { | |
| 432 | if (iterator.itemIndex_ == 0) { | |
| 433 | JSON_ASSERT_MESSAGE(iterator.map_, | |
| 434 | "Attempting to iterate using invalid iterator."); | |
| 435 | if (iterator.link_ == &iterator.map_->buckets_[iterator.bucketIndex_]) { | |
| 436 | JSON_ASSERT_MESSAGE(iterator.bucketIndex_ > 0, | |
| 437 | "Attempting to iterate beyond beginning."); | |
| 438 | --(iterator.bucketIndex_); | |
| 439 | } | |
| 440 | iterator.link_ = iterator.link_->previous_; | |
| 441 | iterator.itemIndex_ = ValueInternalLink::itemPerLink - 1; | |
| 442 | } | |
| 443 | } | |
| 444 | ||
| 445 | const char* ValueInternalMap::key(const IteratorState& iterator) { | |
| 446 | JSON_ASSERT_MESSAGE(iterator.link_, | |
| 447 | "Attempting to iterate using invalid iterator."); | |
| 448 | return iterator.link_->keys_[iterator.itemIndex_]; | |
| 449 | } | |
| 450 | ||
| 451 | const char* ValueInternalMap::key(const IteratorState& iterator, | |
| 452 | bool& isStatic) { | |
| 453 | JSON_ASSERT_MESSAGE(iterator.link_, | |
| 454 | "Attempting to iterate using invalid iterator."); | |
| 455 | isStatic = iterator.link_->items_[iterator.itemIndex_].isMemberNameStatic(); | |
| 456 | return iterator.link_->keys_[iterator.itemIndex_]; | |
| 457 | } | |
| 458 | ||
| 459 | Value& ValueInternalMap::value(const IteratorState& iterator) { | |
| 460 | JSON_ASSERT_MESSAGE(iterator.link_, | |
| 461 | "Attempting to iterate using invalid iterator."); | |
| 462 | return iterator.link_->items_[iterator.itemIndex_]; | |
| 463 | } | |
| 464 | ||
| 465 | int ValueInternalMap::distance(const IteratorState& x, const IteratorState& y) { | |
| 466 | int offset = 0; | |
| 467 | IteratorState it = x; | |
| 468 | while (!equals(it, y)) | |
| 469 | increment(it); | |
| 470 | return offset; | |
| 471 | } | |
| 472 | ||
| 473 | } // namespace Json |
| r0 | r242831 | |
|---|---|---|
| 1 | // Copyright 2007-2011 Baptiste Lepilleur | |
| 2 | // Distributed under MIT license, or public domain if desired and | |
| 3 | // recognized in your jurisdiction. | |
| 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE | |
| 5 | ||
| 6 | #if !defined(JSON_IS_AMALGAMATION) | |
| 7 | #include <json/assertions.h> | |
| 8 | #include <json/reader.h> | |
| 9 | #include <json/value.h> | |
| 10 | #include "json_tool.h" | |
| 11 | #endif // if !defined(JSON_IS_AMALGAMATION) | |
| 12 | #include <utility> | |
| 13 | #include <cstdio> | |
| 14 | #include <cassert> | |
| 15 | #include <cstring> | |
| 16 | #include <istream> | |
| 17 | ||
| 18 | #if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below | |
| 19 | #define snprintf _snprintf | |
| 20 | #endif | |
| 21 | ||
| 22 | #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 | |
| 23 | // Disable warning about strdup being deprecated. | |
| 24 | #pragma warning(disable : 4996) | |
| 25 | #endif | |
| 26 | ||
| 27 | namespace Json { | |
| 28 | ||
| 29 | // Implementation of class Features | |
| 30 | // //////////////////////////////// | |
| 31 | ||
| 32 | Features::Features() | |
| 33 | : allowComments_(true), strictRoot_(false), | |
| 34 | allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {} | |
| 35 | ||
| 36 | Features Features::all() { return Features(); } | |
| 37 | ||
| 38 | Features Features::strictMode() { | |
| 39 | Features features; | |
| 40 | features.allowComments_ = false; | |
| 41 | features.strictRoot_ = true; | |
| 42 | features.allowDroppedNullPlaceholders_ = false; | |
| 43 | features.allowNumericKeys_ = false; | |
| 44 | return features; | |
| 45 | } | |
| 46 | ||
| 47 | // Implementation of class Reader | |
| 48 | // //////////////////////////////// | |
| 49 | ||
| 50 | static inline bool in(Reader::Char c, | |
| 51 | Reader::Char c1, | |
| 52 | Reader::Char c2, | |
| 53 | Reader::Char c3, | |
| 54 | Reader::Char c4) { | |
| 55 | return c == c1 || c == c2 || c == c3 || c == c4; | |
| 56 | } | |
| 57 | ||
| 58 | static inline bool in(Reader::Char c, | |
| 59 | Reader::Char c1, | |
| 60 | Reader::Char c2, | |
| 61 | Reader::Char c3, | |
| 62 | Reader::Char c4, | |
| 63 | Reader::Char c5) { | |
| 64 | return c == c1 || c == c2 || c == c3 || c == c4 || c == c5; | |
| 65 | } | |
| 66 | ||
| 67 | static bool containsNewLine(Reader::Location begin, Reader::Location end) { | |
| 68 | for (; begin < end; ++begin) | |
| 69 | if (*begin == '\n' || *begin == '\r') | |
| 70 | return true; | |
| 71 | return false; | |
| 72 | } | |
| 73 | ||
| 74 | // Class Reader | |
| 75 | // ////////////////////////////////////////////////////////////////// | |
| 76 | ||
| 77 | Reader::Reader() | |
| 78 | : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), | |
| 79 | lastValue_(), commentsBefore_(), features_(Features::all()), | |
| 80 | collectComments_() {} | |
| 81 | ||
| 82 | Reader::Reader(const Features& features) | |
| 83 | : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), | |
| 84 | lastValue_(), commentsBefore_(), features_(features), collectComments_() { | |
| 85 | } | |
| 86 | ||
| 87 | bool | |
| 88 | Reader::parse(const std::string& document, Value& root, bool collectComments) { | |
| 89 | document_ = document; | |
| 90 | const char* begin = document_.c_str(); | |
| 91 | const char* end = begin + document_.length(); | |
| 92 | return parse(begin, end, root, collectComments); | |
| 93 | } | |
| 94 | ||
| 95 | bool Reader::parse(std::istream& sin, Value& root, bool collectComments) { | |
| 96 | // std::istream_iterator<char> begin(sin); | |
| 97 | // std::istream_iterator<char> end; | |
| 98 | // Those would allow streamed input from a file, if parse() were a | |
| 99 | // template function. | |
| 100 | ||
| 101 | // Since std::string is reference-counted, this at least does not | |
| 102 | // create an extra copy. | |
| 103 | std::string doc; | |
| 104 | std::getline(sin, doc, (char)EOF); | |
| 105 | return parse(doc, root, collectComments); | |
| 106 | } | |
| 107 | ||
| 108 | bool Reader::parse(const char* beginDoc, | |
| 109 | const char* endDoc, | |
| 110 | Value& root, | |
| 111 | bool collectComments) { | |
| 112 | if (!features_.allowComments_) { | |
| 113 | collectComments = false; | |
| 114 | } | |
| 115 | ||
| 116 | begin_ = beginDoc; | |
| 117 | end_ = endDoc; | |
| 118 | collectComments_ = collectComments; | |
| 119 | current_ = begin_; | |
| 120 | lastValueEnd_ = 0; | |
| 121 | lastValue_ = 0; | |
| 122 | commentsBefore_ = ""; | |
| 123 | errors_.clear(); | |
| 124 | while (!nodes_.empty()) | |
| 125 | nodes_.pop(); | |
| 126 | nodes_.push(&root); | |
| 127 | ||
| 128 | bool successful = readValue(); | |
| 129 | Token token; | |
| 130 | skipCommentTokens(token); | |
| 131 | if (collectComments_ && !commentsBefore_.empty()) | |
| 132 | root.setComment(commentsBefore_, commentAfter); | |
| 133 | if (features_.strictRoot_) { | |
| 134 | if (!root.isArray() && !root.isObject()) { | |
| 135 | // Set error location to start of doc, ideally should be first token found | |
| 136 | // in doc | |
| 137 | token.type_ = tokenError; | |
| 138 | token.start_ = beginDoc; | |
| 139 | token.end_ = endDoc; | |
| 140 | addError( | |
| 141 | "A valid JSON document must be either an array or an object value.", | |
| 142 | token); | |
| 143 | return false; | |
| 144 | } | |
| 145 | } | |
| 146 | return successful; | |
| 147 | } | |
| 148 | ||
| 149 | bool Reader::readValue() { | |
| 150 | Token token; | |
| 151 | skipCommentTokens(token); | |
| 152 | bool successful = true; | |
| 153 | ||
| 154 | if (collectComments_ && !commentsBefore_.empty()) { | |
| 155 | // Remove newline characters at the end of the comments | |
| 156 | size_t lastNonNewline = commentsBefore_.find_last_not_of("\r\n"); | |
| 157 | if (lastNonNewline != std::string::npos) { | |
| 158 | commentsBefore_.erase(lastNonNewline + 1); | |
| 159 | } else { | |
| 160 | commentsBefore_.clear(); | |
| 161 | } | |
| 162 | ||
| 163 | currentValue().setComment(commentsBefore_, commentBefore); | |
| 164 | commentsBefore_ = ""; | |
| 165 | } | |
| 166 | ||
| 167 | switch (token.type_) { | |
| 168 | case tokenObjectBegin: | |
| 169 | successful = readObject(token); | |
| 170 | currentValue().setOffsetLimit(current_ - begin_); | |
| 171 | break; | |
| 172 | case tokenArrayBegin: | |
| 173 | successful = readArray(token); | |
| 174 | currentValue().setOffsetLimit(current_ - begin_); | |
| 175 | break; | |
| 176 | case tokenNumber: | |
| 177 | successful = decodeNumber(token); | |
| 178 | break; | |
| 179 | case tokenString: | |
| 180 | successful = decodeString(token); | |
| 181 | break; | |
| 182 | case tokenTrue: | |
| 183 | currentValue() = true; | |
| 184 | currentValue().setOffsetStart(token.start_ - begin_); | |
| 185 | currentValue().setOffsetLimit(token.end_ - begin_); | |
| 186 | break; | |
| 187 | case tokenFalse: | |
| 188 | currentValue() = false; | |
| 189 | currentValue().setOffsetStart(token.start_ - begin_); | |
| 190 | currentValue().setOffsetLimit(token.end_ - begin_); | |
| 191 | break; | |
| 192 | case tokenNull: | |
| 193 | currentValue() = Value(); | |
| 194 | currentValue().setOffsetStart(token.start_ - begin_); | |
| 195 | currentValue().setOffsetLimit(token.end_ - begin_); | |
| 196 | break; | |
| 197 | case tokenArraySeparator: | |
| 198 | if (features_.allowDroppedNullPlaceholders_) { | |
| 199 | // "Un-read" the current token and mark the current value as a null | |
| 200 | // token. | |
| 201 | current_--; | |
| 202 | currentValue() = Value(); | |
| 203 | currentValue().setOffsetStart(current_ - begin_ - 1); | |
| 204 | currentValue().setOffsetLimit(current_ - begin_); | |
| 205 | break; | |
| 206 | } | |
| 207 | // Else, fall through... | |
| 208 | default: | |
| 209 | currentValue().setOffsetStart(token.start_ - begin_); | |
| 210 | currentValue().setOffsetLimit(token.end_ - begin_); | |
| 211 | return addError("Syntax error: value, object or array expected.", token); | |
| 212 | } | |
| 213 | ||
| 214 | if (collectComments_) { | |
| 215 | lastValueEnd_ = current_; | |
| 216 | lastValue_ = ¤tValue(); | |
| 217 | } | |
| 218 | ||
| 219 | return successful; | |
| 220 | } | |
| 221 | ||
| 222 | void Reader::skipCommentTokens(Token& token) { | |
| 223 | if (features_.allowComments_) { | |
| 224 | do { | |
| 225 | readToken(token); | |
| 226 | } while (token.type_ == tokenComment); | |
| 227 | } else { | |
| 228 | readToken(token); | |
| 229 | } | |
| 230 | } | |
| 231 | ||
| 232 | bool Reader::expectToken(TokenType type, Token& token, const char* message) { | |
| 233 | readToken(token); | |
| 234 | if (token.type_ != type) | |
| 235 | return addError(message, token); | |
| 236 | return true; | |
| 237 | } | |
| 238 | ||
| 239 | bool Reader::readToken(Token& token) { | |
| 240 | skipSpaces(); | |
| 241 | token.start_ = current_; | |
| 242 | Char c = getNextChar(); | |
| 243 | bool ok = true; | |
| 244 | switch (c) { | |
| 245 | case '{': | |
| 246 | token.type_ = tokenObjectBegin; | |
| 247 | break; | |
| 248 | case '}': | |
| 249 | token.type_ = tokenObjectEnd; | |
| 250 | break; | |
| 251 | case '[': | |
| 252 | token.type_ = tokenArrayBegin; | |
| 253 | break; | |
| 254 | case ']': | |
| 255 | token.type_ = tokenArrayEnd; | |
| 256 | break; | |
| 257 | case '"': | |
| 258 | token.type_ = tokenString; | |
| 259 | ok = readString(); | |
| 260 | break; | |
| 261 | case '/': | |
| 262 | token.type_ = tokenComment; | |
| 263 | ok = readComment(); | |
| 264 | break; | |
| 265 | case '0': | |
| 266 | case '1': | |
| 267 | case '2': | |
| 268 | case '3': | |
| 269 | case '4': | |
| 270 | case '5': | |
| 271 | case '6': | |
| 272 | case '7': | |
| 273 | case '8': | |
| 274 | case '9': | |
| 275 | case '-': | |
| 276 | token.type_ = tokenNumber; | |
| 277 | readNumber(); | |
| 278 | break; | |
| 279 | case 't': | |
| 280 | token.type_ = tokenTrue; | |
| 281 | ok = match("rue", 3); | |
| 282 | break; | |
| 283 | case 'f': | |
| 284 | token.type_ = tokenFalse; | |
| 285 | ok = match("alse", 4); | |
| 286 | break; | |
| 287 | case 'n': | |
| 288 | token.type_ = tokenNull; | |
| 289 | ok = match("ull", 3); | |
| 290 | break; | |
| 291 | case ',': | |
| 292 | token.type_ = tokenArraySeparator; | |
| 293 | break; | |
| 294 | case ':': | |
| 295 | token.type_ = tokenMemberSeparator; | |
| 296 | break; | |
| 297 | case 0: | |
| 298 | token.type_ = tokenEndOfStream; | |
| 299 | break; | |
| 300 | default: | |
| 301 | ok = false; | |
| 302 | break; | |
| 303 | } | |
| 304 | if (!ok) | |
| 305 | token.type_ = tokenError; | |
| 306 | token.end_ = current_; | |
| 307 | return true; | |
| 308 | } | |
| 309 | ||
| 310 | void Reader::skipSpaces() { | |
| 311 | while (current_ != end_) { | |
| 312 | Char c = *current_; | |
| 313 | if (c == ' ' || c == '\t' || c == '\r' || c == '\n') | |
| 314 | ++current_; | |
| 315 | else | |
| 316 | break; | |
| 317 | } | |
| 318 | } | |
| 319 | ||
| 320 | bool Reader::match(Location pattern, int patternLength) { | |
| 321 | if (end_ - current_ < patternLength) | |
| 322 | return false; | |
| 323 | int index = patternLength; | |
| 324 | while (index--) | |
| 325 | if (current_[index] != pattern[index]) | |
| 326 | return false; | |
| 327 | current_ += patternLength; | |
| 328 | return true; | |
| 329 | } | |
| 330 | ||
| 331 | bool Reader::readComment() { | |
| 332 | Location commentBegin = current_ - 1; | |
| 333 | Char c = getNextChar(); | |
| 334 | bool successful = false; | |
| 335 | if (c == '*') | |
| 336 | successful = readCStyleComment(); | |
| 337 | else if (c == '/') | |
| 338 | successful = readCppStyleComment(); | |
| 339 | if (!successful) | |
| 340 | return false; | |
| 341 | ||
| 342 | if (collectComments_) { | |
| 343 | CommentPlacement placement = commentBefore; | |
| 344 | if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { | |
| 345 | if (c != '*' || !containsNewLine(commentBegin, current_)) | |
| 346 | placement = commentAfterOnSameLine; | |
| 347 | } | |
| 348 | ||
| 349 | addComment(commentBegin, current_, placement); | |
| 350 | } | |
| 351 | return true; | |
| 352 | } | |
| 353 | ||
| 354 | void | |
| 355 | Reader::addComment(Location begin, Location end, CommentPlacement placement) { | |
| 356 | assert(collectComments_); | |
| 357 | if (placement == commentAfterOnSameLine) { | |
| 358 | assert(lastValue_ != 0); | |
| 359 | lastValue_->setComment(std::string(begin, end), placement); | |
| 360 | } else { | |
| 361 | commentsBefore_ += std::string(begin, end); | |
| 362 | } | |
| 363 | } | |
| 364 | ||
| 365 | bool Reader::readCStyleComment() { | |
| 366 | while (current_ != end_) { | |
| 367 | Char c = getNextChar(); | |
| 368 | if (c == '*' && *current_ == '/') | |
| 369 | break; | |
| 370 | } | |
| 371 | return getNextChar() == '/'; | |
| 372 | } | |
| 373 | ||
| 374 | bool Reader::readCppStyleComment() { | |
| 375 | while (current_ != end_) { | |
| 376 | Char c = getNextChar(); | |
| 377 | if (c == '\r' || c == '\n') | |
| 378 | break; | |
| 379 | } | |
| 380 | return true; | |
| 381 | } | |
| 382 | ||
| 383 | void Reader::readNumber() { | |
| 384 | while (current_ != end_) { | |
| 385 | if (!(*current_ >= '0' && *current_ <= '9') && | |
| 386 | !in(*current_, '.', 'e', 'E', '+', '-')) | |
| 387 | break; | |
| 388 | ++current_; | |
| 389 | } | |
| 390 | } | |
| 391 | ||
| 392 | bool Reader::readString() { | |
| 393 | Char c = 0; | |
| 394 | while (current_ != end_) { | |
| 395 | c = getNextChar(); | |
| 396 | if (c == '\\') | |
| 397 | getNextChar(); | |
| 398 | else if (c == '"') | |
| 399 | break; | |
| 400 | } | |
| 401 | return c == '"'; | |
| 402 | } | |
| 403 | ||
| 404 | bool Reader::readObject(Token& tokenStart) { | |
| 405 | Token tokenName; | |
| 406 | std::string name; | |
| 407 | currentValue() = Value(objectValue); | |
| 408 | currentValue().setOffsetStart(tokenStart.start_ - begin_); | |
| 409 | while (readToken(tokenName)) { | |
| 410 | bool initialTokenOk = true; | |
| 411 | while (tokenName.type_ == tokenComment && initialTokenOk) | |
| 412 | initialTokenOk = readToken(tokenName); | |
| 413 | if (!initialTokenOk) | |
| 414 | break; | |
| 415 | if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object | |
| 416 | return true; | |
| 417 | name = ""; | |
| 418 | if (tokenName.type_ == tokenString) { | |
| 419 | if (!decodeString(tokenName, name)) | |
| 420 | return recoverFromError(tokenObjectEnd); | |
| 421 | } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) { | |
| 422 | Value numberName; | |
| 423 | if (!decodeNumber(tokenName, numberName)) | |
| 424 | return recoverFromError(tokenObjectEnd); | |
| 425 | name = numberName.asString(); | |
| 426 | } else { | |
| 427 | break; | |
| 428 | } | |
| 429 | ||
| 430 | Token colon; | |
| 431 | if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { | |
| 432 | return addErrorAndRecover( | |
| 433 | "Missing ':' after object member name", colon, tokenObjectEnd); | |
| 434 | } | |
| 435 | Value& value = currentValue()[name]; | |
| 436 | nodes_.push(&value); | |
| 437 | bool ok = readValue(); | |
| 438 | nodes_.pop(); | |
| 439 | if (!ok) // error already set | |
| 440 | return recoverFromError(tokenObjectEnd); | |
| 441 | ||
| 442 | Token comma; | |
| 443 | if (!readToken(comma) || | |
| 444 | (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && | |
| 445 | comma.type_ != tokenComment)) { | |
| 446 | return addErrorAndRecover( | |
| 447 | "Missing ',' or '}' in object declaration", comma, tokenObjectEnd); | |
| 448 | } | |
| 449 | bool finalizeTokenOk = true; | |
| 450 | while (comma.type_ == tokenComment && finalizeTokenOk) | |
| 451 | finalizeTokenOk = readToken(comma); | |
| 452 | if (comma.type_ == tokenObjectEnd) | |
| 453 | return true; | |
| 454 | } | |
| 455 | return addErrorAndRecover( | |
| 456 | "Missing '}' or object member name", tokenName, tokenObjectEnd); | |
| 457 | } | |
| 458 | ||
| 459 | bool Reader::readArray(Token& tokenStart) { | |
| 460 | currentValue() = Value(arrayValue); | |
| 461 | currentValue().setOffsetStart(tokenStart.start_ - begin_); | |
| 462 | skipSpaces(); | |
| 463 | if (*current_ == ']') // empty array | |
| 464 | { | |
| 465 | Token endArray; | |
| 466 | readToken(endArray); | |
| 467 | return true; | |
| 468 | } | |
| 469 | int index = 0; | |
| 470 | for (;;) { | |
| 471 | Value& value = currentValue()[index++]; | |
| 472 | nodes_.push(&value); | |
| 473 | bool ok = readValue(); | |
| 474 | nodes_.pop(); | |
| 475 | if (!ok) // error already set | |
| 476 | return recoverFromError(tokenArrayEnd); | |
| 477 | ||
| 478 | Token token; | |
| 479 | // Accept Comment after last item in the array. | |
| 480 | ok = readToken(token); | |
| 481 | while (token.type_ == tokenComment && ok) { | |
| 482 | ok = readToken(token); | |
| 483 | } | |
| 484 | bool badTokenType = | |
| 485 | (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd); | |
| 486 | if (!ok || badTokenType) { | |
| 487 | return addErrorAndRecover( | |
| 488 | "Missing ',' or ']' in array declaration", token, tokenArrayEnd); | |
| 489 | } | |
| 490 | if (token.type_ == tokenArrayEnd) | |
| 491 | break; | |
| 492 | } | |
| 493 | return true; | |
| 494 | } | |
| 495 | ||
| 496 | bool Reader::decodeNumber(Token& token) { | |
| 497 | Value decoded; | |
| 498 | if (!decodeNumber(token, decoded)) | |
| 499 | return false; | |
| 500 | currentValue() = decoded; | |
| 501 | currentValue().setOffsetStart(token.start_ - begin_); | |
| 502 | currentValue().setOffsetLimit(token.end_ - begin_); | |
| 503 | return true; | |
| 504 | } | |
| 505 | ||
| 506 | bool Reader::decodeNumber(Token& token, Value& decoded) { | |
| 507 | bool isDouble = false; | |
| 508 | for (Location inspect = token.start_; inspect != token.end_; ++inspect) { | |
| 509 | isDouble = isDouble || in(*inspect, '.', 'e', 'E', '+') || | |
| 510 | (*inspect == '-' && inspect != token.start_); | |
| 511 | } | |
| 512 | if (isDouble) | |
| 513 | return decodeDouble(token, decoded); | |
| 514 | // Attempts to parse the number as an integer. If the number is | |
| 515 | // larger than the maximum supported value of an integer then | |
| 516 | // we decode the number as a double. | |
| 517 | Location current = token.start_; | |
| 518 | bool isNegative = *current == '-'; | |
| 519 | if (isNegative) | |
| 520 | ++current; | |
| 521 | Value::LargestUInt maxIntegerValue = | |
| 522 | isNegative ? Value::LargestUInt(-Value::minLargestInt) | |
| 523 | : Value::maxLargestUInt; | |
| 524 | Value::LargestUInt threshold = maxIntegerValue / 10; | |
| 525 | Value::LargestUInt value = 0; | |
| 526 | while (current < token.end_) { | |
| 527 | Char c = *current++; | |
| 528 | if (c < '0' || c > '9') | |
| 529 | return addError("'" + std::string(token.start_, token.end_) + | |
| 530 | "' is not a number.", | |
| 531 | token); | |
| 532 | Value::UInt digit(c - '0'); | |
| 533 | if (value >= threshold) { | |
| 534 | // We've hit or exceeded the max value divided by 10 (rounded down). If | |
| 535 | // a) we've only just touched the limit, b) this is the last digit, and | |
| 536 | // c) it's small enough to fit in that rounding delta, we're okay. | |
| 537 | // Otherwise treat this number as a double to avoid overflow. | |
| 538 | if (value > threshold || current != token.end_ || | |
| 539 | digit > maxIntegerValue % 10) { | |
| 540 | return decodeDouble(token, decoded); | |
| 541 | } | |
| 542 | } | |
| 543 | value = value * 10 + digit; | |
| 544 | } | |
| 545 | if (isNegative) | |
| 546 | decoded = -Value::LargestInt(value); | |
| 547 | else if (value <= Value::LargestUInt(Value::maxInt)) | |
| 548 | decoded = Value::LargestInt(value); | |
| 549 | else | |
| 550 | decoded = value; | |
| 551 | return true; | |
| 552 | } | |
| 553 | ||
| 554 | bool Reader::decodeDouble(Token& token) { | |
| 555 | Value decoded; | |
| 556 | if (!decodeDouble(token, decoded)) | |
| 557 | return false; | |
| 558 | currentValue() = decoded; | |
| 559 | currentValue().setOffsetStart(token.start_ - begin_); | |
| 560 | currentValue().setOffsetLimit(token.end_ - begin_); | |
| 561 | return true; | |
| 562 | } | |
| 563 | ||
| 564 | bool Reader::decodeDouble(Token& token, Value& decoded) { | |
| 565 | double value = 0; | |
| 566 | const int bufferSize = 32; | |
| 567 | int count; | |
| 568 | int length = int(token.end_ - token.start_); | |
| 569 | ||
| 570 | // Sanity check to avoid buffer overflow exploits. | |
| 571 | if (length < 0) { | |
| 572 | return addError("Unable to parse token length", token); | |
| 573 | } | |
| 574 | ||
| 575 | // Avoid using a string constant for the format control string given to | |
| 576 | // sscanf, as this can cause hard to debug crashes on OS X. See here for more | |
| 577 | // info: | |
| 578 | // | |
| 579 | // http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html | |
| 580 | char format[] = "%lf"; | |
| 581 | ||
| 582 | if (length <= bufferSize) { | |
| 583 | Char buffer[bufferSize + 1]; | |
| 584 | memcpy(buffer, token.start_, length); | |
| 585 | buffer[length] = 0; | |
| 586 | count = sscanf(buffer, format, &value); | |
| 587 | } else { | |
| 588 | std::string buffer(token.start_, token.end_); | |
| 589 | count = sscanf(buffer.c_str(), format, &value); | |
| 590 | } | |
| 591 | ||
| 592 | if (count != 1) | |
| 593 | return addError("'" + std::string(token.start_, token.end_) + | |
| 594 | "' is not a number.", | |
| 595 | token); | |
| 596 | decoded = value; | |
| 597 | return true; | |
| 598 | } | |
| 599 | ||
| 600 | bool Reader::decodeString(Token& token) { | |
| 601 | std::string decoded; | |
| 602 | if (!decodeString(token, decoded)) | |
| 603 | return false; | |
| 604 | currentValue() = decoded; | |
| 605 | currentValue().setOffsetStart(token.start_ - begin_); | |
| 606 | currentValue().setOffsetLimit(token.end_ - begin_); | |
| 607 | return true; | |
| 608 | } | |
| 609 | ||
| 610 | bool Reader::decodeString(Token& token, std::string& decoded) { | |
| 611 | decoded.reserve(token.end_ - token.start_ - 2); | |
| 612 | Location current = token.start_ + 1; // skip '"' | |
| 613 | Location end = token.end_ - 1; // do not include '"' | |
| 614 | while (current != end) { | |
| 615 | Char c = *current++; | |
| 616 | if (c == '"') | |
| 617 | break; | |
| 618 | else if (c == '\\') { | |
| 619 | if (current == end) | |
| 620 | return addError("Empty escape sequence in string", token, current); | |
| 621 | Char escape = *current++; | |
| 622 | switch (escape) { | |
| 623 | case '"': | |
| 624 | decoded += '"'; | |
| 625 | break; | |
| 626 | case '/': | |
| 627 | decoded += '/'; | |
| 628 | break; | |
| 629 | case '\\': | |
| 630 | decoded += '\\'; | |
| 631 | break; | |
| 632 | case 'b': | |
| 633 | decoded += '\b'; | |
| 634 | break; | |
| 635 | case 'f': | |
| 636 | decoded += '\f'; | |
| 637 | break; | |
| 638 | case 'n': | |
| 639 | decoded += '\n'; | |
| 640 | break; | |
| 641 | case 'r': | |
| 642 | decoded += '\r'; | |
| 643 | break; | |
| 644 | case 't': | |
| 645 | decoded += '\t'; | |
| 646 | break; | |
| 647 | case 'u': { | |
| 648 | unsigned int unicode; | |
| 649 | if (!decodeUnicodeCodePoint(token, current, end, unicode)) | |
| 650 | return false; | |
| 651 | decoded += codePointToUTF8(unicode); | |
| 652 | } break; | |
| 653 | default: | |
| 654 | return addError("Bad escape sequence in string", token, current); | |
| 655 | } | |
| 656 | } else { | |
| 657 | decoded += c; | |
| 658 | } | |
| 659 | } | |
| 660 | return true; | |
| 661 | } | |
| 662 | ||
| 663 | bool Reader::decodeUnicodeCodePoint(Token& token, | |
| 664 | Location& current, | |
| 665 | Location end, | |
| 666 | unsigned int& unicode) { | |
| 667 | ||
| 668 | if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) | |
| 669 | return false; | |
| 670 | if (unicode >= 0xD800 && unicode <= 0xDBFF) { | |
| 671 | // surrogate pairs | |
| 672 | if (end - current < 6) | |
| 673 | return addError( | |
| 674 | "additional six characters expected to parse unicode surrogate pair.", | |
| 675 | token, | |
| 676 | current); | |
| 677 | unsigned int surrogatePair; | |
| 678 | if (*(current++) == '\\' && *(current++) == 'u') { | |
| 679 | if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { | |
| 680 | unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); | |
| 681 | } else | |
| 682 | return false; | |
| 683 | } else | |
| 684 | return addError("expecting another \\u token to begin the second half of " | |
| 685 | "a unicode surrogate pair", | |
| 686 | token, | |
| 687 | current); | |
| 688 | } | |
| 689 | return true; | |
| 690 | } | |
| 691 | ||
| 692 | bool Reader::decodeUnicodeEscapeSequence(Token& token, | |
| 693 | Location& current, | |
| 694 | Location end, | |
| 695 | unsigned int& unicode) { | |
| 696 | if (end - current < 4) | |
| 697 | return addError( | |
| 698 | "Bad unicode escape sequence in string: four digits expected.", | |
| 699 | token, | |
| 700 | current); | |
| 701 | unicode = 0; | |
| 702 | for (int index = 0; index < 4; ++index) { | |
| 703 | Char c = *current++; | |
| 704 | unicode *= 16; | |
| 705 | if (c >= '0' && c <= '9') | |
| 706 | unicode += c - '0'; | |
| 707 | else if (c >= 'a' && c <= 'f') | |
| 708 | unicode += c - 'a' + 10; | |
| 709 | else if (c >= 'A' && c <= 'F') | |
| 710 | unicode += c - 'A' + 10; | |
| 711 | else | |
| 712 | return addError( | |
| 713 | "Bad unicode escape sequence in string: hexadecimal digit expected.", | |
| 714 | token, | |
| 715 | current); | |
| 716 | } | |
| 717 | return true; | |
| 718 | } | |
| 719 | ||
| 720 | bool | |
| 721 | Reader::addError(const std::string& message, Token& token, Location extra) { | |
| 722 | ErrorInfo info; | |
| 723 | info.token_ = token; | |
| 724 | info.message_ = message; | |
| 725 | info.extra_ = extra; | |
| 726 | errors_.push_back(info); | |
| 727 | return false; | |
| 728 | } | |
| 729 | ||
| 730 | bool Reader::recoverFromError(TokenType skipUntilToken) { | |
| 731 | int errorCount = int(errors_.size()); | |
| 732 | Token skip; | |
| 733 | for (;;) { | |
| 734 | if (!readToken(skip)) | |
| 735 | errors_.resize(errorCount); // discard errors caused by recovery | |
| 736 | if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) | |
| 737 | break; | |
| 738 | } | |
| 739 | errors_.resize(errorCount); | |
| 740 | return false; | |
| 741 | } | |
| 742 | ||
| 743 | bool Reader::addErrorAndRecover(const std::string& message, | |
| 744 | Token& token, | |
| 745 | TokenType skipUntilToken) { | |
| 746 | addError(message, token); | |
| 747 | return recoverFromError(skipUntilToken); | |
| 748 | } | |
| 749 | ||
| 750 | Value& Reader::currentValue() { return *(nodes_.top()); } | |
| 751 | ||
| 752 | Reader::Char Reader::getNextChar() { | |
| 753 | if (current_ == end_) | |
| 754 | return 0; | |
| 755 | return *current_++; | |
| 756 | } | |
| 757 | ||
| 758 | void Reader::getLocationLineAndColumn(Location location, | |
| 759 | int& line, | |
| 760 | int& column) const { | |
| 761 | Location current = begin_; | |
| 762 | Location lastLineStart = current; | |
| 763 | line = 0; | |
| 764 | while (current < location && current != end_) { | |
| 765 | Char c = *current++; | |
| 766 | if (c == '\r') { | |
| 767 | if (*current == '\n') | |
| 768 | ++current; | |
| 769 | lastLineStart = current; | |
| 770 | ++line; | |
| 771 | } else if (c == '\n') { | |
| 772 | lastLineStart = current; | |
| 773 | ++line; | |
| 774 | } | |
| 775 | } | |
| 776 | // column & line start at 1 | |
| 777 | column = int(location - lastLineStart) + 1; | |
| 778 | ++line; | |
| 779 | } | |
| 780 | ||
| 781 | std::string Reader::getLocationLineAndColumn(Location location) const { | |
| 782 | int line, column; | |
| 783 | getLocationLineAndColumn(location, line, column); | |
| 784 | char buffer[18 + 16 + 16 + 1]; | |
| 785 | #if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) | |
| 786 | #if defined(WINCE) | |
| 787 | _snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); | |
| 788 | #else | |
| 789 | sprintf_s(buffer, sizeof(buffer), "Line %d, Column %d", line, column); | |
| 790 | #endif | |
| 791 | #else | |
| 792 | snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); | |
| 793 | #endif | |
| 794 | return buffer; | |
| 795 | } | |
| 796 | ||
| 797 | // Deprecated. Preserved for backward compatibility | |
| 798 | std::string Reader::getFormatedErrorMessages() const { | |
| 799 | return getFormattedErrorMessages(); | |
| 800 | } | |
| 801 | ||
| 802 | std::string Reader::getFormattedErrorMessages() const { | |
| 803 | std::string formattedMessage; | |
| 804 | for (Errors::const_iterator itError = errors_.begin(); | |
| 805 | itError != errors_.end(); | |
| 806 | ++itError) { | |
| 807 | const ErrorInfo& error = *itError; | |
| 808 | formattedMessage += | |
| 809 | "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; | |
| 810 | formattedMessage += " " + error.message_ + "\n"; | |
| 811 | if (error.extra_) | |
| 812 | formattedMessage += | |
| 813 | "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; | |
| 814 | } | |
| 815 | return formattedMessage; | |
| 816 | } | |
| 817 | ||
| 818 | std::vector<Reader::StructuredError> Reader::getStructuredErrors() const { | |
| 819 | std::vector<Reader::StructuredError> allErrors; | |
| 820 | for (Errors::const_iterator itError = errors_.begin(); | |
| 821 | itError != errors_.end(); | |
| 822 | ++itError) { | |
| 823 | const ErrorInfo& error = *itError; | |
| 824 | Reader::StructuredError structured; | |
| 825 | structured.offset_start = error.token_.start_ - begin_; | |
| 826 | structured.offset_limit = error.token_.end_ - begin_; | |
| 827 | structured.message = error.message_; | |
| 828 | allErrors.push_back(structured); | |
| 829 | } | |
| 830 | return allErrors; | |
| 831 | } | |
| 832 | ||
| 833 | bool Reader::pushError(const Value& value, const std::string& message) { | |
| 834 | size_t length = end_ - begin_; | |
| 835 | if(value.getOffsetStart() > length | |
| 836 | || value.getOffsetLimit() > length) | |
| 837 | return false; | |
| 838 | Token token; | |
| 839 | token.type_ = tokenError; | |
| 840 | token.start_ = begin_ + value.getOffsetStart(); | |
| 841 | token.end_ = end_ + value.getOffsetLimit(); | |
| 842 | ErrorInfo info; | |
| 843 | info.token_ = token; | |
| 844 | info.message_ = message; | |
| 845 | info.extra_ = 0; | |
| 846 | errors_.push_back(info); | |
| 847 | return true; | |
| 848 | } | |
| 849 | ||
| 850 | bool Reader::pushError(const Value& value, const std::string& message, const Value& extra) { | |
| 851 | size_t length = end_ - begin_; | |
| 852 | if(value.getOffsetStart() > length | |
| 853 | || value.getOffsetLimit() > length | |
| 854 | || extra.getOffsetLimit() > length) | |
| 855 | return false; | |
| 856 | Token token; | |
| 857 | token.type_ = tokenError; | |
| 858 | token.start_ = begin_ + value.getOffsetStart(); | |
| 859 | token.end_ = begin_ + value.getOffsetLimit(); | |
| 860 | ErrorInfo info; | |
| 861 | info.token_ = token; | |
| 862 | info.message_ = message; | |
| 863 | info.extra_ = begin_ + extra.getOffsetStart(); | |
| 864 | errors_.push_back(info); | |
| 865 | return true; | |
| 866 | } | |
| 867 | ||
| 868 | bool Reader::good() const { | |
| 869 | return !errors_.size(); | |
| 870 | } | |
| 871 | ||
| 872 | std::istream& operator>>(std::istream& sin, Value& root) { | |
| 873 | Json::Reader reader; | |
| 874 | bool ok = reader.parse(sin, root, true); | |
| 875 | if (!ok) { | |
| 876 | fprintf(stderr, | |
| 877 | "Error from reader: %s", | |
| 878 | reader.getFormattedErrorMessages().c_str()); | |
| 879 | ||
| 880 | JSON_FAIL_MESSAGE("reader error"); | |
| 881 | } | |
| 882 | return sin; | |
| 883 | } | |
| 884 | ||
| 885 | } // namespace Json |
| r0 | r242831 | |
|---|---|---|
| 1 | // Copyright 2007-2010 Baptiste Lepilleur | |
| 2 | // Distributed under MIT license, or public domain if desired and | |
| 3 | // recognized in your jurisdiction. | |
| 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE | |
| 5 | ||
| 6 | #ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED | |
| 7 | #define LIB_JSONCPP_JSON_TOOL_H_INCLUDED | |
| 8 | ||
| 9 | /* This header provides common string manipulation support, such as UTF-8, | |
| 10 | * portable conversion from/to string... | |
| 11 | * | |
| 12 | * It is an internal header that must not be exposed. | |
| 13 | */ | |
| 14 | ||
| 15 | namespace Json { | |
| 16 | ||
| 17 | /// Converts a unicode code-point to UTF-8. | |
| 18 | static inline std::string codePointToUTF8(unsigned int cp) { | |
| 19 | std::string result; | |
| 20 | ||
| 21 | // based on description from http://en.wikipedia.org/wiki/UTF-8 | |
| 22 | ||
| 23 | if (cp <= 0x7f) { | |
| 24 | result.resize(1); | |
| 25 | result[0] = static_cast<char>(cp); | |
| 26 | } else if (cp <= 0x7FF) { | |
| 27 | result.resize(2); | |
| 28 | result[1] = static_cast<char>(0x80 | (0x3f & cp)); | |
| 29 | result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6))); | |
| 30 | } else if (cp <= 0xFFFF) { | |
| 31 | result.resize(3); | |
| 32 | result[2] = static_cast<char>(0x80 | (0x3f & cp)); | |
| 33 | result[1] = 0x80 | static_cast<char>((0x3f & (cp >> 6))); | |
| 34 | result[0] = 0xE0 | static_cast<char>((0xf & (cp >> 12))); | |
| 35 | } else if (cp <= 0x10FFFF) { | |
| 36 | result.resize(4); | |
| 37 | result[3] = static_cast<char>(0x80 | (0x3f & cp)); | |
| 38 | result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6))); | |
| 39 | result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12))); | |
| 40 | result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18))); | |
| 41 | } | |
| 42 | ||
| 43 | return result; | |
| 44 | } | |
| 45 | ||
| 46 | /// Returns true if ch is a control character (in range [0,32[). | |
| 47 | static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; } | |
| 48 | ||
| 49 | enum { | |
| 50 | /// Constant that specify the size of the buffer that must be passed to | |
| 51 | /// uintToString. | |
| 52 | uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1 | |
| 53 | }; | |
| 54 | ||
| 55 | // Defines a char buffer for use with uintToString(). | |
| 56 | typedef char UIntToStringBuffer[uintToStringBufferSize]; | |
| 57 | ||
| 58 | /** Converts an unsigned integer to string. | |
| 59 | * @param value Unsigned interger to convert to string | |
| 60 | * @param current Input/Output string buffer. | |
| 61 | * Must have at least uintToStringBufferSize chars free. | |
| 62 | */ | |
| 63 | static inline void uintToString(LargestUInt value, char*& current) { | |
| 64 | *--current = 0; | |
| 65 | do { | |
| 66 | *--current = char(value % 10) + '0'; | |
| 67 | value /= 10; | |
| 68 | } while (value != 0); | |
| 69 | } | |
| 70 | ||
| 71 | /** Change ',' to '.' everywhere in buffer. | |
| 72 | * | |
| 73 | * We had a sophisticated way, but it did not work in WinCE. | |
| 74 | * @see https://github.com/open-source-parsers/jsoncpp/pull/9 | |
| 75 | */ | |
| 76 | static inline void fixNumericLocale(char* begin, char* end) { | |
| 77 | while (begin < end) { | |
| 78 | if (*begin == ',') { | |
| 79 | *begin = '.'; | |
| 80 | } | |
| 81 | ++begin; | |
| 82 | } | |
| 83 | } | |
| 84 | ||
| 85 | } // namespace Json { | |
| 86 | ||
| 87 | #endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED |
| r0 | r242831 | |
|---|---|---|
| 1 | // Copyright 2011 Baptiste Lepilleur | |
| 2 | // Distributed under MIT license, or public domain if desired and | |
| 3 | // recognized in your jurisdiction. | |
| 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE | |
| 5 | ||
| 6 | #if !defined(JSON_IS_AMALGAMATION) | |
| 7 | #include <json/assertions.h> | |
| 8 | #include <json/value.h> | |
| 9 | #include <json/writer.h> | |
| 10 | #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR | |
| 11 | #include "json_batchallocator.h" | |
| 12 | #endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR | |
| 13 | #endif // if !defined(JSON_IS_AMALGAMATION) | |
| 14 | #include <math.h> | |
| 15 | #include <sstream> | |
| 16 | #include <utility> | |
| 17 | #include <cstring> | |
| 18 | #include <cassert> | |
| 19 | #ifdef JSON_USE_CPPTL | |
| 20 | #include <cpptl/conststring.h> | |
| 21 | #endif | |
| 22 | #include <cstddef> // size_t | |
| 23 | ||
| 24 | #define JSON_ASSERT_UNREACHABLE assert(false) | |
| 25 | ||
| 26 | namespace Json { | |
| 27 | ||
| 28 | // This is a walkaround to avoid the static initialization of Value::null. | |
| 29 | // kNull must be word-aligned to avoid crashing on ARM. We use an alignment of | |
| 30 | // 8 (instead of 4) as a bit of future-proofing. | |
| 31 | #if defined(__ARMEL__) | |
| 32 | #define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment))) | |
| 33 | #else | |
| 34 | #define ALIGNAS(byte_alignment) | |
| 35 | #endif | |
| 36 | static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 }; | |
| 37 | const unsigned char& kNullRef = kNull[0]; | |
| 38 | const Value& Value::null = reinterpret_cast<const Value&>(kNullRef); | |
| 39 | ||
| 40 | const Int Value::minInt = Int(~(UInt(-1) / 2)); | |
| 41 | const Int Value::maxInt = Int(UInt(-1) / 2); | |
| 42 | const UInt Value::maxUInt = UInt(-1); | |
| 43 | #if defined(JSON_HAS_INT64) | |
| 44 | const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2)); | |
| 45 | const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2); | |
| 46 | const UInt64 Value::maxUInt64 = UInt64(-1); | |
| 47 | // The constant is hard-coded because some compiler have trouble | |
| 48 | // converting Value::maxUInt64 to a double correctly (AIX/xlC). | |
| 49 | // Assumes that UInt64 is a 64 bits integer. | |
| 50 | static const double maxUInt64AsDouble = 18446744073709551615.0; | |
| 51 | #endif // defined(JSON_HAS_INT64) | |
| 52 | const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2)); | |
| 53 | const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2); | |
| 54 | const LargestUInt Value::maxLargestUInt = LargestUInt(-1); | |
| 55 | ||
| 56 | /// Unknown size marker | |
| 57 | static const unsigned int unknown = (unsigned)-1; | |
| 58 | ||
| 59 | #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) | |
| 60 | template <typename T, typename U> | |
| 61 | static inline bool InRange(double d, T min, U max) { | |
| 62 | return d >= min && d <= max; | |
| 63 | } | |
| 64 | #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) | |
| 65 | static inline double integerToDouble(Json::UInt64 value) { | |
| 66 | return static_cast<double>(Int64(value / 2)) * 2.0 + Int64(value & 1); | |
| 67 | } | |
| 68 | ||
| 69 | template <typename T> static inline double integerToDouble(T value) { | |
| 70 | return static_cast<double>(value); | |
| 71 | } | |
| 72 | ||
| 73 | template <typename T, typename U> | |
| 74 | static inline bool InRange(double d, T min, U max) { | |
| 75 | return d >= integerToDouble(min) && d <= integerToDouble(max); | |
| 76 | } | |
| 77 | #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) | |
| 78 | ||
| 79 | /** Duplicates the specified string value. | |
| 80 | * @param value Pointer to the string to duplicate. Must be zero-terminated if | |
| 81 | * length is "unknown". | |
| 82 | * @param length Length of the value. if equals to unknown, then it will be | |
| 83 | * computed using strlen(value). | |
| 84 | * @return Pointer on the duplicate instance of string. | |
| 85 | */ | |
| 86 | static inline char* duplicateStringValue(const char* value, | |
| 87 | unsigned int length = unknown) { | |
| 88 | if (length == unknown) | |
| 89 | length = (unsigned int)strlen(value); | |
| 90 | ||
| 91 | // Avoid an integer overflow in the call to malloc below by limiting length | |
| 92 | // to a sane value. | |
| 93 | if (length >= (unsigned)Value::maxInt) | |
| 94 | length = Value::maxInt - 1; | |
| 95 | ||
| 96 | char* newString = static_cast<char*>(malloc(length + 1)); | |
| 97 | JSON_ASSERT_MESSAGE(newString != 0, | |
| 98 | "in Json::Value::duplicateStringValue(): " | |
| 99 | "Failed to allocate string value buffer"); | |
| 100 | memcpy(newString, value, length); | |
| 101 | newString[length] = 0; | |
| 102 | return newString; | |
| 103 | } | |
| 104 | ||
| 105 | /** Free the string duplicated by duplicateStringValue(). | |
| 106 | */ | |
| 107 | static inline void releaseStringValue(char* value) { free(value); } | |
| 108 | ||
| 109 | } // namespace Json | |
| 110 | ||
| 111 | // ////////////////////////////////////////////////////////////////// | |
| 112 | // ////////////////////////////////////////////////////////////////// | |
| 113 | // ////////////////////////////////////////////////////////////////// | |
| 114 | // ValueInternals... | |
| 115 | // ////////////////////////////////////////////////////////////////// | |
| 116 | // ////////////////////////////////////////////////////////////////// | |
| 117 | // ////////////////////////////////////////////////////////////////// | |
| 118 | #if !defined(JSON_IS_AMALGAMATION) | |
| 119 | #ifdef JSON_VALUE_USE_INTERNAL_MAP | |
| 120 | #include "json_internalarray.inl" | |
| 121 | #include "json_internalmap.inl" | |
| 122 | #endif // JSON_VALUE_USE_INTERNAL_MAP | |
| 123 | ||
| 124 | #include "json_valueiterator.inl" | |
| 125 | #endif // if !defined(JSON_IS_AMALGAMATION) | |
| 126 | ||
| 127 | namespace Json { | |
| 128 | ||
| 129 | // ////////////////////////////////////////////////////////////////// | |
| 130 | // ////////////////////////////////////////////////////////////////// | |
| 131 | // ////////////////////////////////////////////////////////////////// | |
| 132 | // class Value::CommentInfo | |
| 133 | // ////////////////////////////////////////////////////////////////// | |
| 134 | // ////////////////////////////////////////////////////////////////// | |
| 135 | // ////////////////////////////////////////////////////////////////// | |
| 136 | ||
| 137 | Value::CommentInfo::CommentInfo() : comment_(0) {} | |
| 138 | ||
| 139 | Value::CommentInfo::~CommentInfo() { | |
| 140 | if (comment_) | |
| 141 | releaseStringValue(comment_); | |
| 142 | } | |
| 143 | ||
| 144 | void Value::CommentInfo::setComment(const char* text) { | |
| 145 | if (comment_) | |
| 146 | releaseStringValue(comment_); | |
| 147 | JSON_ASSERT(text != 0); | |
| 148 | JSON_ASSERT_MESSAGE( | |
| 149 | text[0] == '\0' || text[0] == '/', | |
| 150 | "in Json::Value::setComment(): Comments must start with /"); | |
| 151 | // It seems that /**/ style comments are acceptable as well. | |
| 152 | comment_ = duplicateStringValue(text); | |
| 153 | } | |
| 154 | ||
| 155 | // ////////////////////////////////////////////////////////////////// | |
| 156 | // ////////////////////////////////////////////////////////////////// | |
| 157 | // ////////////////////////////////////////////////////////////////// | |
| 158 | // class Value::CZString | |
| 159 | // ////////////////////////////////////////////////////////////////// | |
| 160 | // ////////////////////////////////////////////////////////////////// | |
| 161 | // ////////////////////////////////////////////////////////////////// | |
| 162 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 163 | ||
| 164 | // Notes: index_ indicates if the string was allocated when | |
| 165 | // a string is stored. | |
| 166 | ||
| 167 | Value::CZString::CZString(ArrayIndex index) : cstr_(0), index_(index) {} | |
| 168 | ||
| 169 | Value::CZString::CZString(const char* cstr, DuplicationPolicy allocate) | |
| 170 | : cstr_(allocate == duplicate ? duplicateStringValue(cstr) : cstr), | |
| 171 | index_(allocate) {} | |
| 172 | ||
| 173 | Value::CZString::CZString(const CZString& other) | |
| 174 | : cstr_(other.index_ != noDuplication && other.cstr_ != 0 | |
| 175 | ? duplicateStringValue(other.cstr_) | |
| 176 | : other.cstr_), | |
| 177 | index_(other.cstr_ | |
| 178 | ? static_cast<ArrayIndex>(other.index_ == noDuplication | |
| 179 | ? noDuplication : duplicate) | |
| 180 | : other.index_) {} | |
| 181 | ||
| 182 | Value::CZString::~CZString() { | |
| 183 | if (cstr_ && index_ == duplicate) | |
| 184 | releaseStringValue(const_cast<char*>(cstr_)); | |
| 185 | } | |
| 186 | ||
| 187 | void Value::CZString::swap(CZString& other) { | |
| 188 | std::swap(cstr_, other.cstr_); | |
| 189 | std::swap(index_, other.index_); | |
| 190 | } | |
| 191 | ||
| 192 | Value::CZString& Value::CZString::operator=(CZString other) { | |
| 193 | swap(other); | |
| 194 | return *this; | |
| 195 | } | |
| 196 | ||
| 197 | bool Value::CZString::operator<(const CZString& other) const { | |
| 198 | if (cstr_) | |
| 199 | return strcmp(cstr_, other.cstr_) < 0; | |
| 200 | return index_ < other.index_; | |
| 201 | } | |
| 202 | ||
| 203 | bool Value::CZString::operator==(const CZString& other) const { | |
| 204 | if (cstr_) | |
| 205 | return strcmp(cstr_, other.cstr_) == 0; | |
| 206 | return index_ == other.index_; | |
| 207 | } | |
| 208 | ||
| 209 | ArrayIndex Value::CZString::index() const { return index_; } | |
| 210 | ||
| 211 | const char* Value::CZString::c_str() const { return cstr_; } | |
| 212 | ||
| 213 | bool Value::CZString::isStaticString() const { return index_ == noDuplication; } | |
| 214 | ||
| 215 | #endif // ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 216 | ||
| 217 | // ////////////////////////////////////////////////////////////////// | |
| 218 | // ////////////////////////////////////////////////////////////////// | |
| 219 | // ////////////////////////////////////////////////////////////////// | |
| 220 | // class Value::Value | |
| 221 | // ////////////////////////////////////////////////////////////////// | |
| 222 | // ////////////////////////////////////////////////////////////////// | |
| 223 | // ////////////////////////////////////////////////////////////////// | |
| 224 | ||
| 225 | /*! \internal Default constructor initialization must be equivalent to: | |
| 226 | * memset( this, 0, sizeof(Value) ) | |
| 227 | * This optimization is used in ValueInternalMap fast allocator. | |
| 228 | */ | |
| 229 | Value::Value(ValueType type) { | |
| 230 | initBasic(type); | |
| 231 | switch (type) { | |
| 232 | case nullValue: | |
| 233 | break; | |
| 234 | case intValue: | |
| 235 | case uintValue: | |
| 236 | value_.int_ = 0; | |
| 237 | break; | |
| 238 | case realValue: | |
| 239 | value_.real_ = 0.0; | |
| 240 | break; | |
| 241 | case stringValue: | |
| 242 | value_.string_ = 0; | |
| 243 | break; | |
| 244 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 245 | case arrayValue: | |
| 246 | case objectValue: | |
| 247 | value_.map_ = new ObjectValues(); | |
| 248 | break; | |
| 249 | #else | |
| 250 | case arrayValue: | |
| 251 | value_.array_ = arrayAllocator()->newArray(); | |
| 252 | break; | |
| 253 | case objectValue: | |
| 254 | value_.map_ = mapAllocator()->newMap(); | |
| 255 | break; | |
| 256 | #endif | |
| 257 | case booleanValue: | |
| 258 | value_.bool_ = false; | |
| 259 | break; | |
| 260 | default: | |
| 261 | JSON_ASSERT_UNREACHABLE; | |
| 262 | } | |
| 263 | } | |
| 264 | ||
| 265 | Value::Value(Int value) { | |
| 266 | initBasic(intValue); | |
| 267 | value_.int_ = value; | |
| 268 | } | |
| 269 | ||
| 270 | Value::Value(UInt value) { | |
| 271 | initBasic(uintValue); | |
| 272 | value_.uint_ = value; | |
| 273 | } | |
| 274 | #if defined(JSON_HAS_INT64) | |
| 275 | Value::Value(Int64 value) { | |
| 276 | initBasic(intValue); | |
| 277 | value_.int_ = value; | |
| 278 | } | |
| 279 | Value::Value(UInt64 value) { | |
| 280 | initBasic(uintValue); | |
| 281 | value_.uint_ = value; | |
| 282 | } | |
| 283 | #endif // defined(JSON_HAS_INT64) | |
| 284 | ||
| 285 | Value::Value(double value) { | |
| 286 | initBasic(realValue); | |
| 287 | value_.real_ = value; | |
| 288 | } | |
| 289 | ||
| 290 | Value::Value(const char* value) { | |
| 291 | initBasic(stringValue, true); | |
| 292 | value_.string_ = duplicateStringValue(value); | |
| 293 | } | |
| 294 | ||
| 295 | Value::Value(const char* beginValue, const char* endValue) { | |
| 296 | initBasic(stringValue, true); | |
| 297 | value_.string_ = | |
| 298 | duplicateStringValue(beginValue, (unsigned int)(endValue - beginValue)); | |
| 299 | } | |
| 300 | ||
| 301 | Value::Value(const std::string& value) { | |
| 302 | initBasic(stringValue, true); | |
| 303 | value_.string_ = | |
| 304 | duplicateStringValue(value.c_str(), (unsigned int)value.length()); | |
| 305 | } | |
| 306 | ||
| 307 | Value::Value(const StaticString& value) { | |
| 308 | initBasic(stringValue); | |
| 309 | value_.string_ = const_cast<char*>(value.c_str()); | |
| 310 | } | |
| 311 | ||
| 312 | #ifdef JSON_USE_CPPTL | |
| 313 | Value::Value(const CppTL::ConstString& value) { | |
| 314 | initBasic(stringValue, true); | |
| 315 | value_.string_ = duplicateStringValue(value, value.length()); | |
| 316 | } | |
| 317 | #endif | |
| 318 | ||
| 319 | Value::Value(bool value) { | |
| 320 | initBasic(booleanValue); | |
| 321 | value_.bool_ = value; | |
| 322 | } | |
| 323 | ||
| 324 | Value::Value(const Value& other) | |
| 325 | : type_(other.type_), allocated_(false) | |
| 326 | #ifdef JSON_VALUE_USE_INTERNAL_MAP | |
| 327 | , | |
| 328 | itemIsUsed_(0) | |
| 329 | #endif | |
| 330 | , | |
| 331 | comments_(0), start_(other.start_), limit_(other.limit_) { | |
| 332 | switch (type_) { | |
| 333 | case nullValue: | |
| 334 | case intValue: | |
| 335 | case uintValue: | |
| 336 | case realValue: | |
| 337 | case booleanValue: | |
| 338 | value_ = other.value_; | |
| 339 | break; | |
| 340 | case stringValue: | |
| 341 | if (other.value_.string_) { | |
| 342 | value_.string_ = duplicateStringValue(other.value_.string_); | |
| 343 | allocated_ = true; | |
| 344 | } else { | |
| 345 | value_.string_ = 0; | |
| 346 | allocated_ = false; | |
| 347 | } | |
| 348 | break; | |
| 349 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 350 | case arrayValue: | |
| 351 | case objectValue: | |
| 352 | value_.map_ = new ObjectValues(*other.value_.map_); | |
| 353 | break; | |
| 354 | #else | |
| 355 | case arrayValue: | |
| 356 | value_.array_ = arrayAllocator()->newArrayCopy(*other.value_.array_); | |
| 357 | break; | |
| 358 | case objectValue: | |
| 359 | value_.map_ = mapAllocator()->newMapCopy(*other.value_.map_); | |
| 360 | break; | |
| 361 | #endif | |
| 362 | default: | |
| 363 | JSON_ASSERT_UNREACHABLE; | |
| 364 | } | |
| 365 | if (other.comments_) { | |
| 366 | comments_ = new CommentInfo[numberOfCommentPlacement]; | |
| 367 | for (int comment = 0; comment < numberOfCommentPlacement; ++comment) { | |
| 368 | const CommentInfo& otherComment = other.comments_[comment]; | |
| 369 | if (otherComment.comment_) | |
| 370 | comments_[comment].setComment(otherComment.comment_); | |
| 371 | } | |
| 372 | } | |
| 373 | } | |
| 374 | ||
| 375 | Value::~Value() { | |
| 376 | switch (type_) { | |
| 377 | case nullValue: | |
| 378 | case intValue: | |
| 379 | case uintValue: | |
| 380 | case realValue: | |
| 381 | case booleanValue: | |
| 382 | break; | |
| 383 | case stringValue: | |
| 384 | if (allocated_) | |
| 385 | releaseStringValue(value_.string_); | |
| 386 | break; | |
| 387 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 388 | case arrayValue: | |
| 389 | case objectValue: | |
| 390 | delete value_.map_; | |
| 391 | break; | |
| 392 | #else | |
| 393 | case arrayValue: | |
| 394 | arrayAllocator()->destructArray(value_.array_); | |
| 395 | break; | |
| 396 | case objectValue: | |
| 397 | mapAllocator()->destructMap(value_.map_); | |
| 398 | break; | |
| 399 | #endif | |
| 400 | default: | |
| 401 | JSON_ASSERT_UNREACHABLE; | |
| 402 | } | |
| 403 | ||
| 404 | if (comments_) | |
| 405 | delete[] comments_; | |
| 406 | } | |
| 407 | ||
| 408 | Value& Value::operator=(Value other) { | |
| 409 | swap(other); | |
| 410 | return *this; | |
| 411 | } | |
| 412 | ||
| 413 | void Value::swap(Value& other) { | |
| 414 | ValueType temp = type_; | |
| 415 | type_ = other.type_; | |
| 416 | other.type_ = temp; | |
| 417 | std::swap(value_, other.value_); | |
| 418 | int temp2 = allocated_; | |
| 419 | allocated_ = other.allocated_; | |
| 420 | other.allocated_ = temp2; | |
| 421 | std::swap(start_, other.start_); | |
| 422 | std::swap(limit_, other.limit_); | |
| 423 | } | |
| 424 | ||
| 425 | ValueType Value::type() const { return type_; } | |
| 426 | ||
| 427 | int Value::compare(const Value& other) const { | |
| 428 | if (*this < other) | |
| 429 | return -1; | |
| 430 | if (*this > other) | |
| 431 | return 1; | |
| 432 | return 0; | |
| 433 | } | |
| 434 | ||
| 435 | bool Value::operator<(const Value& other) const { | |
| 436 | int typeDelta = type_ - other.type_; | |
| 437 | if (typeDelta) | |
| 438 | return typeDelta < 0 ? true : false; | |
| 439 | switch (type_) { | |
| 440 | case nullValue: | |
| 441 | return false; | |
| 442 | case intValue: | |
| 443 | return value_.int_ < other.value_.int_; | |
| 444 | case uintValue: | |
| 445 | return value_.uint_ < other.value_.uint_; | |
| 446 | case realValue: | |
| 447 | return value_.real_ < other.value_.real_; | |
| 448 | case booleanValue: | |
| 449 | return value_.bool_ < other.value_.bool_; | |
| 450 | case stringValue: | |
| 451 | return (value_.string_ == 0 && other.value_.string_) || | |
| 452 | (other.value_.string_ && value_.string_ && | |
| 453 | strcmp(value_.string_, other.value_.string_) < 0); | |
| 454 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 455 | case arrayValue: | |
| 456 | case objectValue: { | |
| 457 | int delta = int(value_.map_->size() - other.value_.map_->size()); | |
| 458 | if (delta) | |
| 459 | return delta < 0; | |
| 460 | return (*value_.map_) < (*other.value_.map_); | |
| 461 | } | |
| 462 | #else | |
| 463 | case arrayValue: | |
| 464 | return value_.array_->compare(*(other.value_.array_)) < 0; | |
| 465 | case objectValue: | |
| 466 | return value_.map_->compare(*(other.value_.map_)) < 0; | |
| 467 | #endif | |
| 468 | default: | |
| 469 | JSON_ASSERT_UNREACHABLE; | |
| 470 | } | |
| 471 | return false; // unreachable | |
| 472 | } | |
| 473 | ||
| 474 | bool Value::operator<=(const Value& other) const { return !(other < *this); } | |
| 475 | ||
| 476 | bool Value::operator>=(const Value& other) const { return !(*this < other); } | |
| 477 | ||
| 478 | bool Value::operator>(const Value& other) const { return other < *this; } | |
| 479 | ||
| 480 | bool Value::operator==(const Value& other) const { | |
| 481 | // if ( type_ != other.type_ ) | |
| 482 | // GCC 2.95.3 says: | |
| 483 | // attempt to take address of bit-field structure member `Json::Value::type_' | |
| 484 | // Beats me, but a temp solves the problem. | |
| 485 | int temp = other.type_; | |
| 486 | if (type_ != temp) | |
| 487 | return false; | |
| 488 | switch (type_) { | |
| 489 | case nullValue: | |
| 490 | return true; | |
| 491 | case intValue: | |
| 492 | return value_.int_ == other.value_.int_; | |
| 493 | case uintValue: | |
| 494 | return value_.uint_ == other.value_.uint_; | |
| 495 | case realValue: | |
| 496 | return value_.real_ == other.value_.real_; | |
| 497 | case booleanValue: | |
| 498 | return value_.bool_ == other.value_.bool_; | |
| 499 | case stringValue: | |
| 500 | return (value_.string_ == other.value_.string_) || | |
| 501 | (other.value_.string_ && value_.string_ && | |
| 502 | strcmp(value_.string_, other.value_.string_) == 0); | |
| 503 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 504 | case arrayValue: | |
| 505 | case objectValue: | |
| 506 | return value_.map_->size() == other.value_.map_->size() && | |
| 507 | (*value_.map_) == (*other.value_.map_); | |
| 508 | #else | |
| 509 | case arrayValue: | |
| 510 | return value_.array_->compare(*(other.value_.array_)) == 0; | |
| 511 | case objectValue: | |
| 512 | return value_.map_->compare(*(other.value_.map_)) == 0; | |
| 513 | #endif | |
| 514 | default: | |
| 515 | JSON_ASSERT_UNREACHABLE; | |
| 516 | } | |
| 517 | return false; // unreachable | |
| 518 | } | |
| 519 | ||
| 520 | bool Value::operator!=(const Value& other) const { return !(*this == other); } | |
| 521 | ||
| 522 | const char* Value::asCString() const { | |
| 523 | JSON_ASSERT_MESSAGE(type_ == stringValue, | |
| 524 | "in Json::Value::asCString(): requires stringValue"); | |
| 525 | return value_.string_; | |
| 526 | } | |
| 527 | ||
| 528 | std::string Value::asString() const { | |
| 529 | switch (type_) { | |
| 530 | case nullValue: | |
| 531 | return ""; | |
| 532 | case stringValue: | |
| 533 | return value_.string_ ? value_.string_ : ""; | |
| 534 | case booleanValue: | |
| 535 | return value_.bool_ ? "true" : "false"; | |
| 536 | case intValue: | |
| 537 | return valueToString(value_.int_); | |
| 538 | case uintValue: | |
| 539 | return valueToString(value_.uint_); | |
| 540 | case realValue: | |
| 541 | return valueToString(value_.real_); | |
| 542 | default: | |
| 543 | JSON_FAIL_MESSAGE("Type is not convertible to string"); | |
| 544 | } | |
| 545 | } | |
| 546 | ||
| 547 | #ifdef JSON_USE_CPPTL | |
| 548 | CppTL::ConstString Value::asConstString() const { | |
| 549 | return CppTL::ConstString(asString().c_str()); | |
| 550 | } | |
| 551 | #endif | |
| 552 | ||
| 553 | Value::Int Value::asInt() const { | |
| 554 | switch (type_) { | |
| 555 | case intValue: | |
| 556 | JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range"); | |
| 557 | return Int(value_.int_); | |
| 558 | case uintValue: | |
| 559 | JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range"); | |
| 560 | return Int(value_.uint_); | |
| 561 | case realValue: | |
| 562 | JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt), | |
| 563 | "double out of Int range"); | |
| 564 | return Int(value_.real_); | |
| 565 | case nullValue: | |
| 566 | return 0; | |
| 567 | case booleanValue: | |
| 568 | return value_.bool_ ? 1 : 0; | |
| 569 | default: | |
| 570 | break; | |
| 571 | } | |
| 572 | JSON_FAIL_MESSAGE("Value is not convertible to Int."); | |
| 573 | } | |
| 574 | ||
| 575 | Value::UInt Value::asUInt() const { | |
| 576 | switch (type_) { | |
| 577 | case intValue: | |
| 578 | JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range"); | |
| 579 | return UInt(value_.int_); | |
| 580 | case uintValue: | |
| 581 | JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range"); | |
| 582 | return UInt(value_.uint_); | |
| 583 | case realValue: | |
| 584 | JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt), | |
| 585 | "double out of UInt range"); | |
| 586 | return UInt(value_.real_); | |
| 587 | case nullValue: | |
| 588 | return 0; | |
| 589 | case booleanValue: | |
| 590 | return value_.bool_ ? 1 : 0; | |
| 591 | default: | |
| 592 | break; | |
| 593 | } | |
| 594 | JSON_FAIL_MESSAGE("Value is not convertible to UInt."); | |
| 595 | } | |
| 596 | ||
| 597 | #if defined(JSON_HAS_INT64) | |
| 598 | ||
| 599 | Value::Int64 Value::asInt64() const { | |
| 600 | switch (type_) { | |
| 601 | case intValue: | |
| 602 | return Int64(value_.int_); | |
| 603 | case uintValue: | |
| 604 | JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range"); | |
| 605 | return Int64(value_.uint_); | |
| 606 | case realValue: | |
| 607 | JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64), | |
| 608 | "double out of Int64 range"); | |
| 609 | return Int64(value_.real_); | |
| 610 | case nullValue: | |
| 611 | return 0; | |
| 612 | case booleanValue: | |
| 613 | return value_.bool_ ? 1 : 0; | |
| 614 | default: | |
| 615 | break; | |
| 616 | } | |
| 617 | JSON_FAIL_MESSAGE("Value is not convertible to Int64."); | |
| 618 | } | |
| 619 | ||
| 620 | Value::UInt64 Value::asUInt64() const { | |
| 621 | switch (type_) { | |
| 622 | case intValue: | |
| 623 | JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range"); | |
| 624 | return UInt64(value_.int_); | |
| 625 | case uintValue: | |
| 626 | return UInt64(value_.uint_); | |
| 627 | case realValue: | |
| 628 | JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64), | |
| 629 | "double out of UInt64 range"); | |
| 630 | return UInt64(value_.real_); | |
| 631 | case nullValue: | |
| 632 | return 0; | |
| 633 | case booleanValue: | |
| 634 | return value_.bool_ ? 1 : 0; | |
| 635 | default: | |
| 636 | break; | |
| 637 | } | |
| 638 | JSON_FAIL_MESSAGE("Value is not convertible to UInt64."); | |
| 639 | } | |
| 640 | #endif // if defined(JSON_HAS_INT64) | |
| 641 | ||
| 642 | LargestInt Value::asLargestInt() const { | |
| 643 | #if defined(JSON_NO_INT64) | |
| 644 | return asInt(); | |
| 645 | #else | |
| 646 | return asInt64(); | |
| 647 | #endif | |
| 648 | } | |
| 649 | ||
| 650 | LargestUInt Value::asLargestUInt() const { | |
| 651 | #if defined(JSON_NO_INT64) | |
| 652 | return asUInt(); | |
| 653 | #else | |
| 654 | return asUInt64(); | |
| 655 | #endif | |
| 656 | } | |
| 657 | ||
| 658 | double Value::asDouble() const { | |
| 659 | switch (type_) { | |
| 660 | case intValue: | |
| 661 | return static_cast<double>(value_.int_); | |
| 662 | case uintValue: | |
| 663 | #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) | |
| 664 | return static_cast<double>(value_.uint_); | |
| 665 | #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) | |
| 666 | return integerToDouble(value_.uint_); | |
| 667 | #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) | |
| 668 | case realValue: | |
| 669 | return value_.real_; | |
| 670 | case nullValue: | |
| 671 | return 0.0; | |
| 672 | case booleanValue: | |
| 673 | return value_.bool_ ? 1.0 : 0.0; | |
| 674 | default: | |
| 675 | break; | |
| 676 | } | |
| 677 | JSON_FAIL_MESSAGE("Value is not convertible to double."); | |
| 678 | } | |
| 679 | ||
| 680 | float Value::asFloat() const { | |
| 681 | switch (type_) { | |
| 682 | case intValue: | |
| 683 | return static_cast<float>(value_.int_); | |
| 684 | case uintValue: | |
| 685 | #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) | |
| 686 | return static_cast<float>(value_.uint_); | |
| 687 | #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) | |
| 688 | return integerToDouble(value_.uint_); | |
| 689 | #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) | |
| 690 | case realValue: | |
| 691 | return static_cast<float>(value_.real_); | |
| 692 | case nullValue: | |
| 693 | return 0.0; | |
| 694 | case booleanValue: | |
| 695 | return value_.bool_ ? 1.0f : 0.0f; | |
| 696 | default: | |
| 697 | break; | |
| 698 | } | |
| 699 | JSON_FAIL_MESSAGE("Value is not convertible to float."); | |
| 700 | } | |
| 701 | ||
| 702 | bool Value::asBool() const { | |
| 703 | switch (type_) { | |
| 704 | case booleanValue: | |
| 705 | return value_.bool_; | |
| 706 | case nullValue: | |
| 707 | return false; | |
| 708 | case intValue: | |
| 709 | return value_.int_ ? true : false; | |
| 710 | case uintValue: | |
| 711 | return value_.uint_ ? true : false; | |
| 712 | case realValue: | |
| 713 | return value_.real_ ? true : false; | |
| 714 | default: | |
| 715 | break; | |
| 716 | } | |
| 717 | JSON_FAIL_MESSAGE("Value is not convertible to bool."); | |
| 718 | } | |
| 719 | ||
| 720 | bool Value::isConvertibleTo(ValueType other) const { | |
| 721 | switch (other) { | |
| 722 | case nullValue: | |
| 723 | return (isNumeric() && asDouble() == 0.0) || | |
| 724 | (type_ == booleanValue && value_.bool_ == false) || | |
| 725 | (type_ == stringValue && asString() == "") || | |
| 726 | (type_ == arrayValue && value_.map_->size() == 0) || | |
| 727 | (type_ == objectValue && value_.map_->size() == 0) || | |
| 728 | type_ == nullValue; | |
| 729 | case intValue: | |
| 730 | return isInt() || | |
| 731 | (type_ == realValue && InRange(value_.real_, minInt, maxInt)) || | |
| 732 | type_ == booleanValue || type_ == nullValue; | |
| 733 | case uintValue: | |
| 734 | return isUInt() || | |
| 735 | (type_ == realValue && InRange(value_.real_, 0, maxUInt)) || | |
| 736 | type_ == booleanValue || type_ == nullValue; | |
| 737 | case realValue: | |
| 738 | return isNumeric() || type_ == booleanValue || type_ == nullValue; | |
| 739 | case booleanValue: | |
| 740 | return isNumeric() || type_ == booleanValue || type_ == nullValue; | |
| 741 | case stringValue: | |
| 742 | return isNumeric() || type_ == booleanValue || type_ == stringValue || | |
| 743 | type_ == nullValue; | |
| 744 | case arrayValue: | |
| 745 | return type_ == arrayValue || type_ == nullValue; | |
| 746 | case objectValue: | |
| 747 | return type_ == objectValue || type_ == nullValue; | |
| 748 | } | |
| 749 | JSON_ASSERT_UNREACHABLE; | |
| 750 | return false; | |
| 751 | } | |
| 752 | ||
| 753 | /// Number of values in array or object | |
| 754 | ArrayIndex Value::size() const { | |
| 755 | switch (type_) { | |
| 756 | case nullValue: | |
| 757 | case intValue: | |
| 758 | case uintValue: | |
| 759 | case realValue: | |
| 760 | case booleanValue: | |
| 761 | case stringValue: | |
| 762 | return 0; | |
| 763 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 764 | case arrayValue: // size of the array is highest index + 1 | |
| 765 | if (!value_.map_->empty()) { | |
| 766 | ObjectValues::const_iterator itLast = value_.map_->end(); | |
| 767 | --itLast; | |
| 768 | return (*itLast).first.index() + 1; | |
| 769 | } | |
| 770 | return 0; | |
| 771 | case objectValue: | |
| 772 | return ArrayIndex(value_.map_->size()); | |
| 773 | #else | |
| 774 | case arrayValue: | |
| 775 | return Int(value_.array_->size()); | |
| 776 | case objectValue: | |
| 777 | return Int(value_.map_->size()); | |
| 778 | #endif | |
| 779 | } | |
| 780 | JSON_ASSERT_UNREACHABLE; | |
| 781 | return 0; // unreachable; | |
| 782 | } | |
| 783 | ||
| 784 | bool Value::empty() const { | |
| 785 | if (isNull() || isArray() || isObject()) | |
| 786 | return size() == 0u; | |
| 787 | else | |
| 788 | return false; | |
| 789 | } | |
| 790 | ||
| 791 | bool Value::operator!() const { return isNull(); } | |
| 792 | ||
| 793 | void Value::clear() { | |
| 794 | JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue || | |
| 795 | type_ == objectValue, | |
| 796 | "in Json::Value::clear(): requires complex value"); | |
| 797 | start_ = 0; | |
| 798 | limit_ = 0; | |
| 799 | switch (type_) { | |
| 800 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 801 | case arrayValue: | |
| 802 | case objectValue: | |
| 803 | value_.map_->clear(); | |
| 804 | break; | |
| 805 | #else | |
| 806 | case arrayValue: | |
| 807 | value_.array_->clear(); | |
| 808 | break; | |
| 809 | case objectValue: | |
| 810 | value_.map_->clear(); | |
| 811 | break; | |
| 812 | #endif | |
| 813 | default: | |
| 814 | break; | |
| 815 | } | |
| 816 | } | |
| 817 | ||
| 818 | void Value::resize(ArrayIndex newSize) { | |
| 819 | JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue, | |
| 820 | "in Json::Value::resize(): requires arrayValue"); | |
| 821 | if (type_ == nullValue) | |
| 822 | *this = Value(arrayValue); | |
| 823 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 824 | ArrayIndex oldSize = size(); | |
| 825 | if (newSize == 0) | |
| 826 | clear(); | |
| 827 | else if (newSize > oldSize) | |
| 828 | (*this)[newSize - 1]; | |
| 829 | else { | |
| 830 | for (ArrayIndex index = newSize; index < oldSize; ++index) { | |
| 831 | value_.map_->erase(index); | |
| 832 | } | |
| 833 | assert(size() == newSize); | |
| 834 | } | |
| 835 | #else | |
| 836 | value_.array_->resize(newSize); | |
| 837 | #endif | |
| 838 | } | |
| 839 | ||
| 840 | Value& Value::operator[](ArrayIndex index) { | |
| 841 | JSON_ASSERT_MESSAGE( | |
| 842 | type_ == nullValue || type_ == arrayValue, | |
| 843 | "in Json::Value::operator[](ArrayIndex): requires arrayValue"); | |
| 844 | if (type_ == nullValue) | |
| 845 | *this = Value(arrayValue); | |
| 846 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 847 | CZString key(index); | |
| 848 | ObjectValues::iterator it = value_.map_->lower_bound(key); | |
| 849 | if (it != value_.map_->end() && (*it).first == key) | |
| 850 | return (*it).second; | |
| 851 | ||
| 852 | ObjectValues::value_type defaultValue(key, null); | |
| 853 | it = value_.map_->insert(it, defaultValue); | |
| 854 | return (*it).second; | |
| 855 | #else | |
| 856 | return value_.array_->resolveReference(index); | |
| 857 | #endif | |
| 858 | } | |
| 859 | ||
| 860 | Value& Value::operator[](int index) { | |
| 861 | JSON_ASSERT_MESSAGE( | |
| 862 | index >= 0, | |
| 863 | "in Json::Value::operator[](int index): index cannot be negative"); | |
| 864 | return (*this)[ArrayIndex(index)]; | |
| 865 | } | |
| 866 | ||
| 867 | const Value& Value::operator[](ArrayIndex index) const { | |
| 868 | JSON_ASSERT_MESSAGE( | |
| 869 | type_ == nullValue || type_ == arrayValue, | |
| 870 | "in Json::Value::operator[](ArrayIndex)const: requires arrayValue"); | |
| 871 | if (type_ == nullValue) | |
| 872 | return null; | |
| 873 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 874 | CZString key(index); | |
| 875 | ObjectValues::const_iterator it = value_.map_->find(key); | |
| 876 | if (it == value_.map_->end()) | |
| 877 | return null; | |
| 878 | return (*it).second; | |
| 879 | #else | |
| 880 | Value* value = value_.array_->find(index); | |
| 881 | return value ? *value : null; | |
| 882 | #endif | |
| 883 | } | |
| 884 | ||
| 885 | const Value& Value::operator[](int index) const { | |
| 886 | JSON_ASSERT_MESSAGE( | |
| 887 | index >= 0, | |
| 888 | "in Json::Value::operator[](int index) const: index cannot be negative"); | |
| 889 | return (*this)[ArrayIndex(index)]; | |
| 890 | } | |
| 891 | ||
| 892 | Value& Value::operator[](const char* key) { | |
| 893 | return resolveReference(key, false); | |
| 894 | } | |
| 895 | ||
| 896 | void Value::initBasic(ValueType type, bool allocated) { | |
| 897 | type_ = type; | |
| 898 | allocated_ = allocated; | |
| 899 | #ifdef JSON_VALUE_USE_INTERNAL_MAP | |
| 900 | itemIsUsed_ = 0; | |
| 901 | #endif | |
| 902 | comments_ = 0; | |
| 903 | start_ = 0; | |
| 904 | limit_ = 0; | |
| 905 | } | |
| 906 | ||
| 907 | Value& Value::resolveReference(const char* key, bool isStatic) { | |
| 908 | JSON_ASSERT_MESSAGE( | |
| 909 | type_ == nullValue || type_ == objectValue, | |
| 910 | "in Json::Value::resolveReference(): requires objectValue"); | |
| 911 | if (type_ == nullValue) | |
| 912 | *this = Value(objectValue); | |
| 913 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 914 | CZString actualKey( | |
| 915 | key, isStatic ? CZString::noDuplication : CZString::duplicateOnCopy); | |
| 916 | ObjectValues::iterator it = value_.map_->lower_bound(actualKey); | |
| 917 | if (it != value_.map_->end() && (*it).first == actualKey) | |
| 918 | return (*it).second; | |
| 919 | ||
| 920 | ObjectValues::value_type defaultValue(actualKey, null); | |
| 921 | it = value_.map_->insert(it, defaultValue); | |
| 922 | Value& value = (*it).second; | |
| 923 | return value; | |
| 924 | #else | |
| 925 | return value_.map_->resolveReference(key, isStatic); | |
| 926 | #endif | |
| 927 | } | |
| 928 | ||
| 929 | Value Value::get(ArrayIndex index, const Value& defaultValue) const { | |
| 930 | const Value* value = &((*this)[index]); | |
| 931 | return value == &null ? defaultValue : *value; | |
| 932 | } | |
| 933 | ||
| 934 | bool Value::isValidIndex(ArrayIndex index) const { return index < size(); } | |
| 935 | ||
| 936 | const Value& Value::operator[](const char* key) const { | |
| 937 | JSON_ASSERT_MESSAGE( | |
| 938 | type_ == nullValue || type_ == objectValue, | |
| 939 | "in Json::Value::operator[](char const*)const: requires objectValue"); | |
| 940 | if (type_ == nullValue) | |
| 941 | return null; | |
| 942 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 943 | CZString actualKey(key, CZString::noDuplication); | |
| 944 | ObjectValues::const_iterator it = value_.map_->find(actualKey); | |
| 945 | if (it == value_.map_->end()) | |
| 946 | return null; | |
| 947 | return (*it).second; | |
| 948 | #else | |
| 949 | const Value* value = value_.map_->find(key); | |
| 950 | return value ? *value : null; | |
| 951 | #endif | |
| 952 | } | |
| 953 | ||
| 954 | Value& Value::operator[](const std::string& key) { | |
| 955 | return (*this)[key.c_str()]; | |
| 956 | } | |
| 957 | ||
| 958 | const Value& Value::operator[](const std::string& key) const { | |
| 959 | return (*this)[key.c_str()]; | |
| 960 | } | |
| 961 | ||
| 962 | Value& Value::operator[](const StaticString& key) { | |
| 963 | return resolveReference(key, true); | |
| 964 | } | |
| 965 | ||
| 966 | #ifdef JSON_USE_CPPTL | |
| 967 | Value& Value::operator[](const CppTL::ConstString& key) { | |
| 968 | return (*this)[key.c_str()]; | |
| 969 | } | |
| 970 | ||
| 971 | const Value& Value::operator[](const CppTL::ConstString& key) const { | |
| 972 | return (*this)[key.c_str()]; | |
| 973 | } | |
| 974 | #endif | |
| 975 | ||
| 976 | Value& Value::append(const Value& value) { return (*this)[size()] = value; } | |
| 977 | ||
| 978 | Value Value::get(const char* key, const Value& defaultValue) const { | |
| 979 | const Value* value = &((*this)[key]); | |
| 980 | return value == &null ? defaultValue : *value; | |
| 981 | } | |
| 982 | ||
| 983 | Value Value::get(const std::string& key, const Value& defaultValue) const { | |
| 984 | return get(key.c_str(), defaultValue); | |
| 985 | } | |
| 986 | ||
| 987 | Value Value::removeMember(const char* key) { | |
| 988 | JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue, | |
| 989 | "in Json::Value::removeMember(): requires objectValue"); | |
| 990 | if (type_ == nullValue) | |
| 991 | return null; | |
| 992 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 993 | CZString actualKey(key, CZString::noDuplication); | |
| 994 | ObjectValues::iterator it = value_.map_->find(actualKey); | |
| 995 | if (it == value_.map_->end()) | |
| 996 | return null; | |
| 997 | Value old(it->second); | |
| 998 | value_.map_->erase(it); | |
| 999 | return old; | |
| 1000 | #else | |
| 1001 | Value* value = value_.map_->find(key); | |
| 1002 | if (value) { | |
| 1003 | Value old(*value); | |
| 1004 | value_.map_.remove(key); | |
| 1005 | return old; | |
| 1006 | } else { | |
| 1007 | return null; | |
| 1008 | } | |
| 1009 | #endif | |
| 1010 | } | |
| 1011 | ||
| 1012 | Value Value::removeMember(const std::string& key) { | |
| 1013 | return removeMember(key.c_str()); | |
| 1014 | } | |
| 1015 | ||
| 1016 | #ifdef JSON_USE_CPPTL | |
| 1017 | Value Value::get(const CppTL::ConstString& key, | |
| 1018 | const Value& defaultValue) const { | |
| 1019 | return get(key.c_str(), defaultValue); | |
| 1020 | } | |
| 1021 | #endif | |
| 1022 | ||
| 1023 | bool Value::isMember(const char* key) const { | |
| 1024 | const Value* value = &((*this)[key]); | |
| 1025 | return value != &null; | |
| 1026 | } | |
| 1027 | ||
| 1028 | bool Value::isMember(const std::string& key) const { | |
| 1029 | return isMember(key.c_str()); | |
| 1030 | } | |
| 1031 | ||
| 1032 | #ifdef JSON_USE_CPPTL | |
| 1033 | bool Value::isMember(const CppTL::ConstString& key) const { | |
| 1034 | return isMember(key.c_str()); | |
| 1035 | } | |
| 1036 | #endif | |
| 1037 | ||
| 1038 | Value::Members Value::getMemberNames() const { | |
| 1039 | JSON_ASSERT_MESSAGE( | |
| 1040 | type_ == nullValue || type_ == objectValue, | |
| 1041 | "in Json::Value::getMemberNames(), value must be objectValue"); | |
| 1042 | if (type_ == nullValue) | |
| 1043 | return Value::Members(); | |
| 1044 | Members members; | |
| 1045 | members.reserve(value_.map_->size()); | |
| 1046 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 1047 | ObjectValues::const_iterator it = value_.map_->begin(); | |
| 1048 | ObjectValues::const_iterator itEnd = value_.map_->end(); | |
| 1049 | for (; it != itEnd; ++it) | |
| 1050 | members.push_back(std::string((*it).first.c_str())); | |
| 1051 | #else | |
| 1052 | ValueInternalMap::IteratorState it; | |
| 1053 | ValueInternalMap::IteratorState itEnd; | |
| 1054 | value_.map_->makeBeginIterator(it); | |
| 1055 | value_.map_->makeEndIterator(itEnd); | |
| 1056 | for (; !ValueInternalMap::equals(it, itEnd); ValueInternalMap::increment(it)) | |
| 1057 | members.push_back(std::string(ValueInternalMap::key(it))); | |
| 1058 | #endif | |
| 1059 | return members; | |
| 1060 | } | |
| 1061 | // | |
| 1062 | //# ifdef JSON_USE_CPPTL | |
| 1063 | // EnumMemberNames | |
| 1064 | // Value::enumMemberNames() const | |
| 1065 | //{ | |
| 1066 | // if ( type_ == objectValue ) | |
| 1067 | // { | |
| 1068 | // return CppTL::Enum::any( CppTL::Enum::transform( | |
| 1069 | // CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ), | |
| 1070 | // MemberNamesTransform() ) ); | |
| 1071 | // } | |
| 1072 | // return EnumMemberNames(); | |
| 1073 | //} | |
| 1074 | // | |
| 1075 | // | |
| 1076 | // EnumValues | |
| 1077 | // Value::enumValues() const | |
| 1078 | //{ | |
| 1079 | // if ( type_ == objectValue || type_ == arrayValue ) | |
| 1080 | // return CppTL::Enum::anyValues( *(value_.map_), | |
| 1081 | // CppTL::Type<const Value &>() ); | |
| 1082 | // return EnumValues(); | |
| 1083 | //} | |
| 1084 | // | |
| 1085 | //# endif | |
| 1086 | ||
| 1087 | static bool IsIntegral(double d) { | |
| 1088 | double integral_part; | |
| 1089 | return modf(d, &integral_part) == 0.0; | |
| 1090 | } | |
| 1091 | ||
| 1092 | bool Value::isNull() const { return type_ == nullValue; } | |
| 1093 | ||
| 1094 | bool Value::isBool() const { return type_ == booleanValue; } | |
| 1095 | ||
| 1096 | bool Value::isInt() const { | |
| 1097 | switch (type_) { | |
| 1098 | case intValue: | |
| 1099 | return value_.int_ >= minInt && value_.int_ <= maxInt; | |
| 1100 | case uintValue: | |
| 1101 | return value_.uint_ <= UInt(maxInt); | |
| 1102 | case realValue: | |
| 1103 | return value_.real_ >= minInt && value_.real_ <= maxInt && | |
| 1104 | IsIntegral(value_.real_); | |
| 1105 | default: | |
| 1106 | break; | |
| 1107 | } | |
| 1108 | return false; | |
| 1109 | } | |
| 1110 | ||
| 1111 | bool Value::isUInt() const { | |
| 1112 | switch (type_) { | |
| 1113 | case intValue: | |
| 1114 | return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt); | |
| 1115 | case uintValue: | |
| 1116 | return value_.uint_ <= maxUInt; | |
| 1117 | case realValue: | |
| 1118 | return value_.real_ >= 0 && value_.real_ <= maxUInt && | |
| 1119 | IsIntegral(value_.real_); | |
| 1120 | default: | |
| 1121 | break; | |
| 1122 | } | |
| 1123 | return false; | |
| 1124 | } | |
| 1125 | ||
| 1126 | bool Value::isInt64() const { | |
| 1127 | #if defined(JSON_HAS_INT64) | |
| 1128 | switch (type_) { | |
| 1129 | case intValue: | |
| 1130 | return true; | |
| 1131 | case uintValue: | |
| 1132 | return value_.uint_ <= UInt64(maxInt64); | |
| 1133 | case realValue: | |
| 1134 | // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a | |
| 1135 | // double, so double(maxInt64) will be rounded up to 2^63. Therefore we | |
| 1136 | // require the value to be strictly less than the limit. | |
| 1137 | return value_.real_ >= double(minInt64) && | |
| 1138 | value_.real_ < double(maxInt64) && IsIntegral(value_.real_); | |
| 1139 | default: | |
| 1140 | break; | |
| 1141 | } | |
| 1142 | #endif // JSON_HAS_INT64 | |
| 1143 | return false; | |
| 1144 | } | |
| 1145 | ||
| 1146 | bool Value::isUInt64() const { | |
| 1147 | #if defined(JSON_HAS_INT64) | |
| 1148 | switch (type_) { | |
| 1149 | case intValue: | |
| 1150 | return value_.int_ >= 0; | |
| 1151 | case uintValue: | |
| 1152 | return true; | |
| 1153 | case realValue: | |
| 1154 | // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a | |
| 1155 | // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we | |
| 1156 | // require the value to be strictly less than the limit. | |
| 1157 | return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble && | |
| 1158 | IsIntegral(value_.real_); | |
| 1159 | default: | |
| 1160 | break; | |
| 1161 | } | |
| 1162 | #endif // JSON_HAS_INT64 | |
| 1163 | return false; | |
| 1164 | } | |
| 1165 | ||
| 1166 | bool Value::isIntegral() const { | |
| 1167 | #if defined(JSON_HAS_INT64) | |
| 1168 | return isInt64() || isUInt64(); | |
| 1169 | #else | |
| 1170 | return isInt() || isUInt(); | |
| 1171 | #endif | |
| 1172 | } | |
| 1173 | ||
| 1174 | bool Value::isDouble() const { return type_ == realValue || isIntegral(); } | |
| 1175 | ||
| 1176 | bool Value::isNumeric() const { return isIntegral() || isDouble(); } | |
| 1177 | ||
| 1178 | bool Value::isString() const { return type_ == stringValue; } | |
| 1179 | ||
| 1180 | bool Value::isArray() const { return type_ == arrayValue; } | |
| 1181 | ||
| 1182 | bool Value::isObject() const { return type_ == objectValue; } | |
| 1183 | ||
| 1184 | void Value::setComment(const char* comment, CommentPlacement placement) { | |
| 1185 | if (!comments_) | |
| 1186 | comments_ = new CommentInfo[numberOfCommentPlacement]; | |
| 1187 | comments_[placement].setComment(comment); | |
| 1188 | } | |
| 1189 | ||
| 1190 | void Value::setComment(const std::string& comment, CommentPlacement placement) { | |
| 1191 | setComment(comment.c_str(), placement); | |
| 1192 | } | |
| 1193 | ||
| 1194 | bool Value::hasComment(CommentPlacement placement) const { | |
| 1195 | return comments_ != 0 && comments_[placement].comment_ != 0; | |
| 1196 | } | |
| 1197 | ||
| 1198 | std::string Value::getComment(CommentPlacement placement) const { | |
| 1199 | if (hasComment(placement)) | |
| 1200 | return comments_[placement].comment_; | |
| 1201 | return ""; | |
| 1202 | } | |
| 1203 | ||
| 1204 | void Value::setOffsetStart(size_t start) { start_ = start; } | |
| 1205 | ||
| 1206 | void Value::setOffsetLimit(size_t limit) { limit_ = limit; } | |
| 1207 | ||
| 1208 | size_t Value::getOffsetStart() const { return start_; } | |
| 1209 | ||
| 1210 | size_t Value::getOffsetLimit() const { return limit_; } | |
| 1211 | ||
| 1212 | std::string Value::toStyledString() const { | |
| 1213 | StyledWriter writer; | |
| 1214 | return writer.write(*this); | |
| 1215 | } | |
| 1216 | ||
| 1217 | Value::const_iterator Value::begin() const { | |
| 1218 | switch (type_) { | |
| 1219 | #ifdef JSON_VALUE_USE_INTERNAL_MAP | |
| 1220 | case arrayValue: | |
| 1221 | if (value_.array_) { | |
| 1222 | ValueInternalArray::IteratorState it; | |
| 1223 | value_.array_->makeBeginIterator(it); | |
| 1224 | return const_iterator(it); | |
| 1225 | } | |
| 1226 | break; | |
| 1227 | case objectValue: | |
| 1228 | if (value_.map_) { | |
| 1229 | ValueInternalMap::IteratorState it; | |
| 1230 | value_.map_->makeBeginIterator(it); | |
| 1231 | return const_iterator(it); | |
| 1232 | } | |
| 1233 | break; | |
| 1234 | #else | |
| 1235 | case arrayValue: | |
| 1236 | case objectValue: | |
| 1237 | if (value_.map_) | |
| 1238 | return const_iterator(value_.map_->begin()); | |
| 1239 | break; | |
| 1240 | #endif | |
| 1241 | default: | |
| 1242 | break; | |
| 1243 | } | |
| 1244 | return const_iterator(); | |
| 1245 | } | |
| 1246 | ||
| 1247 | Value::const_iterator Value::end() const { | |
| 1248 | switch (type_) { | |
| 1249 | #ifdef JSON_VALUE_USE_INTERNAL_MAP | |
| 1250 | case arrayValue: | |
| 1251 | if (value_.array_) { | |
| 1252 | ValueInternalArray::IteratorState it; | |
| 1253 | value_.array_->makeEndIterator(it); | |
| 1254 | return const_iterator(it); | |
| 1255 | } | |
| 1256 | break; | |
| 1257 | case objectValue: | |
| 1258 | if (value_.map_) { | |
| 1259 | ValueInternalMap::IteratorState it; | |
| 1260 | value_.map_->makeEndIterator(it); | |
| 1261 | return const_iterator(it); | |
| 1262 | } | |
| 1263 | break; | |
| 1264 | #else | |
| 1265 | case arrayValue: | |
| 1266 | case objectValue: | |
| 1267 | if (value_.map_) | |
| 1268 | return const_iterator(value_.map_->end()); | |
| 1269 | break; | |
| 1270 | #endif | |
| 1271 | default: | |
| 1272 | break; | |
| 1273 | } | |
| 1274 | return const_iterator(); | |
| 1275 | } | |
| 1276 | ||
| 1277 | Value::iterator Value::begin() { | |
| 1278 | switch (type_) { | |
| 1279 | #ifdef JSON_VALUE_USE_INTERNAL_MAP | |
| 1280 | case arrayValue: | |
| 1281 | if (value_.array_) { | |
| 1282 | ValueInternalArray::IteratorState it; | |
| 1283 | value_.array_->makeBeginIterator(it); | |
| 1284 | return iterator(it); | |
| 1285 | } | |
| 1286 | break; | |
| 1287 | case objectValue: | |
| 1288 | if (value_.map_) { | |
| 1289 | ValueInternalMap::IteratorState it; | |
| 1290 | value_.map_->makeBeginIterator(it); | |
| 1291 | return iterator(it); | |
| 1292 | } | |
| 1293 | break; | |
| 1294 | #else | |
| 1295 | case arrayValue: | |
| 1296 | case objectValue: | |
| 1297 | if (value_.map_) | |
| 1298 | return iterator(value_.map_->begin()); | |
| 1299 | break; | |
| 1300 | #endif | |
| 1301 | default: | |
| 1302 | break; | |
| 1303 | } | |
| 1304 | return iterator(); | |
| 1305 | } | |
| 1306 | ||
| 1307 | Value::iterator Value::end() { | |
| 1308 | switch (type_) { | |
| 1309 | #ifdef JSON_VALUE_USE_INTERNAL_MAP | |
| 1310 | case arrayValue: | |
| 1311 | if (value_.array_) { | |
| 1312 | ValueInternalArray::IteratorState it; | |
| 1313 | value_.array_->makeEndIterator(it); | |
| 1314 | return iterator(it); | |
| 1315 | } | |
| 1316 | break; | |
| 1317 | case objectValue: | |
| 1318 | if (value_.map_) { | |
| 1319 | ValueInternalMap::IteratorState it; | |
| 1320 | value_.map_->makeEndIterator(it); | |
| 1321 | return iterator(it); | |
| 1322 | } | |
| 1323 | break; | |
| 1324 | #else | |
| 1325 | case arrayValue: | |
| 1326 | case objectValue: | |
| 1327 | if (value_.map_) | |
| 1328 | return iterator(value_.map_->end()); | |
| 1329 | break; | |
| 1330 | #endif | |
| 1331 | default: | |
| 1332 | break; | |
| 1333 | } | |
| 1334 | return iterator(); | |
| 1335 | } | |
| 1336 | ||
| 1337 | // class PathArgument | |
| 1338 | // ////////////////////////////////////////////////////////////////// | |
| 1339 | ||
| 1340 | PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {} | |
| 1341 | ||
| 1342 | PathArgument::PathArgument(ArrayIndex index) | |
| 1343 | : key_(), index_(index), kind_(kindIndex) {} | |
| 1344 | ||
| 1345 | PathArgument::PathArgument(const char* key) | |
| 1346 | : key_(key), index_(), kind_(kindKey) {} | |
| 1347 | ||
| 1348 | PathArgument::PathArgument(const std::string& key) | |
| 1349 | : key_(key.c_str()), index_(), kind_(kindKey) {} | |
| 1350 | ||
| 1351 | // class Path | |
| 1352 | // ////////////////////////////////////////////////////////////////// | |
| 1353 | ||
| 1354 | Path::Path(const std::string& path, | |
| 1355 | const PathArgument& a1, | |
| 1356 | const PathArgument& a2, | |
| 1357 | const PathArgument& a3, | |
| 1358 | const PathArgument& a4, | |
| 1359 | const PathArgument& a5) { | |
| 1360 | InArgs in; | |
| 1361 | in.push_back(&a1); | |
| 1362 | in.push_back(&a2); | |
| 1363 | in.push_back(&a3); | |
| 1364 | in.push_back(&a4); | |
| 1365 | in.push_back(&a5); | |
| 1366 | makePath(path, in); | |
| 1367 | } | |
| 1368 | ||
| 1369 | void Path::makePath(const std::string& path, const InArgs& in) { | |
| 1370 | const char* current = path.c_str(); | |
| 1371 | const char* end = current + path.length(); | |
| 1372 | InArgs::const_iterator itInArg = in.begin(); | |
| 1373 | while (current != end) { | |
| 1374 | if (*current == '[') { | |
| 1375 | ++current; | |
| 1376 | if (*current == '%') | |
| 1377 | addPathInArg(path, in, itInArg, PathArgument::kindIndex); | |
| 1378 | else { | |
| 1379 | ArrayIndex index = 0; | |
| 1380 | for (; current != end && *current >= '0' && *current <= '9'; ++current) | |
| 1381 | index = index * 10 + ArrayIndex(*current - '0'); | |
| 1382 | args_.push_back(index); | |
| 1383 | } | |
| 1384 | if (current == end || *current++ != ']') | |
| 1385 | invalidPath(path, int(current - path.c_str())); | |
| 1386 | } else if (*current == '%') { | |
| 1387 | addPathInArg(path, in, itInArg, PathArgument::kindKey); | |
| 1388 | ++current; | |
| 1389 | } else if (*current == '.') { | |
| 1390 | ++current; | |
| 1391 | } else { | |
| 1392 | const char* beginName = current; | |
| 1393 | while (current != end && !strchr("[.", *current)) | |
| 1394 | ++current; | |
| 1395 | args_.push_back(std::string(beginName, current)); | |
| 1396 | } | |
| 1397 | } | |
| 1398 | } | |
| 1399 | ||
| 1400 | void Path::addPathInArg(const std::string& /*path*/, | |
| 1401 | const InArgs& in, | |
| 1402 | InArgs::const_iterator& itInArg, | |
| 1403 | PathArgument::Kind kind) { | |
| 1404 | if (itInArg == in.end()) { | |
| 1405 | // Error: missing argument %d | |
| 1406 | } else if ((*itInArg)->kind_ != kind) { | |
| 1407 | // Error: bad argument type | |
| 1408 | } else { | |
| 1409 | args_.push_back(**itInArg); | |
| 1410 | } | |
| 1411 | } | |
| 1412 | ||
| 1413 | void Path::invalidPath(const std::string& /*path*/, int /*location*/) { | |
| 1414 | // Error: invalid path. | |
| 1415 | } | |
| 1416 | ||
| 1417 | const Value& Path::resolve(const Value& root) const { | |
| 1418 | const Value* node = &root; | |
| 1419 | for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { | |
| 1420 | const PathArgument& arg = *it; | |
| 1421 | if (arg.kind_ == PathArgument::kindIndex) { | |
| 1422 | if (!node->isArray() || !node->isValidIndex(arg.index_)) { | |
| 1423 | // Error: unable to resolve path (array value expected at position... | |
| 1424 | } | |
| 1425 | node = &((*node)[arg.index_]); | |
| 1426 | } else if (arg.kind_ == PathArgument::kindKey) { | |
| 1427 | if (!node->isObject()) { | |
| 1428 | // Error: unable to resolve path (object value expected at position...) | |
| 1429 | } | |
| 1430 | node = &((*node)[arg.key_]); | |
| 1431 | if (node == &Value::null) { | |
| 1432 | // Error: unable to resolve path (object has no member named '' at | |
| 1433 | // position...) | |
| 1434 | } | |
| 1435 | } | |
| 1436 | } | |
| 1437 | return *node; | |
| 1438 | } | |
| 1439 | ||
| 1440 | Value Path::resolve(const Value& root, const Value& defaultValue) const { | |
| 1441 | const Value* node = &root; | |
| 1442 | for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { | |
| 1443 | const PathArgument& arg = *it; | |
| 1444 | if (arg.kind_ == PathArgument::kindIndex) { | |
| 1445 | if (!node->isArray() || !node->isValidIndex(arg.index_)) | |
| 1446 | return defaultValue; | |
| 1447 | node = &((*node)[arg.index_]); | |
| 1448 | } else if (arg.kind_ == PathArgument::kindKey) { | |
| 1449 | if (!node->isObject()) | |
| 1450 | return defaultValue; | |
| 1451 | node = &((*node)[arg.key_]); | |
| 1452 | if (node == &Value::null) | |
| 1453 | return defaultValue; | |
| 1454 | } | |
| 1455 | } | |
| 1456 | return *node; | |
| 1457 | } | |
| 1458 | ||
| 1459 | Value& Path::make(Value& root) const { | |
| 1460 | Value* node = &root; | |
| 1461 | for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { | |
| 1462 | const PathArgument& arg = *it; | |
| 1463 | if (arg.kind_ == PathArgument::kindIndex) { | |
| 1464 | if (!node->isArray()) { | |
| 1465 | // Error: node is not an array at position ... | |
| 1466 | } | |
| 1467 | node = &((*node)[arg.index_]); | |
| 1468 | } else if (arg.kind_ == PathArgument::kindKey) { | |
| 1469 | if (!node->isObject()) { | |
| 1470 | // Error: node is not an object at position... | |
| 1471 | } | |
| 1472 | node = &((*node)[arg.key_]); | |
| 1473 | } | |
| 1474 | } | |
| 1475 | return *node; | |
| 1476 | } | |
| 1477 | ||
| 1478 | } // namespace Json |
| r0 | r242831 | |
|---|---|---|
| 1 | // Copyright 2007-2010 Baptiste Lepilleur | |
| 2 | // Distributed under MIT license, or public domain if desired and | |
| 3 | // recognized in your jurisdiction. | |
| 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE | |
| 5 | ||
| 6 | // included by json_value.cpp | |
| 7 | ||
| 8 | namespace Json { | |
| 9 | ||
| 10 | // ////////////////////////////////////////////////////////////////// | |
| 11 | // ////////////////////////////////////////////////////////////////// | |
| 12 | // ////////////////////////////////////////////////////////////////// | |
| 13 | // class ValueIteratorBase | |
| 14 | // ////////////////////////////////////////////////////////////////// | |
| 15 | // ////////////////////////////////////////////////////////////////// | |
| 16 | // ////////////////////////////////////////////////////////////////// | |
| 17 | ||
| 18 | ValueIteratorBase::ValueIteratorBase() | |
| 19 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 20 | : current_(), isNull_(true) { | |
| 21 | } | |
| 22 | #else | |
| 23 | : isArray_(true), isNull_(true) { | |
| 24 | iterator_.array_ = ValueInternalArray::IteratorState(); | |
| 25 | } | |
| 26 | #endif | |
| 27 | ||
| 28 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 29 | ValueIteratorBase::ValueIteratorBase( | |
| 30 | const Value::ObjectValues::iterator& current) | |
| 31 | : current_(current), isNull_(false) {} | |
| 32 | #else | |
| 33 | ValueIteratorBase::ValueIteratorBase( | |
| 34 | const ValueInternalArray::IteratorState& state) | |
| 35 | : isArray_(true) { | |
| 36 | iterator_.array_ = state; | |
| 37 | } | |
| 38 | ||
| 39 | ValueIteratorBase::ValueIteratorBase( | |
| 40 | const ValueInternalMap::IteratorState& state) | |
| 41 | : isArray_(false) { | |
| 42 | iterator_.map_ = state; | |
| 43 | } | |
| 44 | #endif | |
| 45 | ||
| 46 | Value& ValueIteratorBase::deref() const { | |
| 47 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 48 | return current_->second; | |
| 49 | #else | |
| 50 | if (isArray_) | |
| 51 | return ValueInternalArray::dereference(iterator_.array_); | |
| 52 | return ValueInternalMap::value(iterator_.map_); | |
| 53 | #endif | |
| 54 | } | |
| 55 | ||
| 56 | void ValueIteratorBase::increment() { | |
| 57 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 58 | ++current_; | |
| 59 | #else | |
| 60 | if (isArray_) | |
| 61 | ValueInternalArray::increment(iterator_.array_); | |
| 62 | ValueInternalMap::increment(iterator_.map_); | |
| 63 | #endif | |
| 64 | } | |
| 65 | ||
| 66 | void ValueIteratorBase::decrement() { | |
| 67 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 68 | --current_; | |
| 69 | #else | |
| 70 | if (isArray_) | |
| 71 | ValueInternalArray::decrement(iterator_.array_); | |
| 72 | ValueInternalMap::decrement(iterator_.map_); | |
| 73 | #endif | |
| 74 | } | |
| 75 | ||
| 76 | ValueIteratorBase::difference_type | |
| 77 | ValueIteratorBase::computeDistance(const SelfType& other) const { | |
| 78 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 79 | #ifdef JSON_USE_CPPTL_SMALLMAP | |
| 80 | return current_ - other.current_; | |
| 81 | #else | |
| 82 | // Iterator for null value are initialized using the default | |
| 83 | // constructor, which initialize current_ to the default | |
| 84 | // std::map::iterator. As begin() and end() are two instance | |
| 85 | // of the default std::map::iterator, they can not be compared. | |
| 86 | // To allow this, we handle this comparison specifically. | |
| 87 | if (isNull_ && other.isNull_) { | |
| 88 | return 0; | |
| 89 | } | |
| 90 | ||
| 91 | // Usage of std::distance is not portable (does not compile with Sun Studio 12 | |
| 92 | // RogueWave STL, | |
| 93 | // which is the one used by default). | |
| 94 | // Using a portable hand-made version for non random iterator instead: | |
| 95 | // return difference_type( std::distance( current_, other.current_ ) ); | |
| 96 | difference_type myDistance = 0; | |
| 97 | for (Value::ObjectValues::iterator it = current_; it != other.current_; | |
| 98 | ++it) { | |
| 99 | ++myDistance; | |
| 100 | } | |
| 101 | return myDistance; | |
| 102 | #endif | |
| 103 | #else | |
| 104 | if (isArray_) | |
| 105 | return ValueInternalArray::distance(iterator_.array_, | |
| 106 | other.iterator_.array_); | |
| 107 | return ValueInternalMap::distance(iterator_.map_, other.iterator_.map_); | |
| 108 | #endif | |
| 109 | } | |
| 110 | ||
| 111 | bool ValueIteratorBase::isEqual(const SelfType& other) const { | |
| 112 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 113 | if (isNull_) { | |
| 114 | return other.isNull_; | |
| 115 | } | |
| 116 | return current_ == other.current_; | |
| 117 | #else | |
| 118 | if (isArray_) | |
| 119 | return ValueInternalArray::equals(iterator_.array_, other.iterator_.array_); | |
| 120 | return ValueInternalMap::equals(iterator_.map_, other.iterator_.map_); | |
| 121 | #endif | |
| 122 | } | |
| 123 | ||
| 124 | void ValueIteratorBase::copy(const SelfType& other) { | |
| 125 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 126 | current_ = other.current_; | |
| 127 | isNull_ = other.isNull_; | |
| 128 | #else | |
| 129 | if (isArray_) | |
| 130 | iterator_.array_ = other.iterator_.array_; | |
| 131 | iterator_.map_ = other.iterator_.map_; | |
| 132 | #endif | |
| 133 | } | |
| 134 | ||
| 135 | Value ValueIteratorBase::key() const { | |
| 136 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 137 | const Value::CZString czstring = (*current_).first; | |
| 138 | if (czstring.c_str()) { | |
| 139 | if (czstring.isStaticString()) | |
| 140 | return Value(StaticString(czstring.c_str())); | |
| 141 | return Value(czstring.c_str()); | |
| 142 | } | |
| 143 | return Value(czstring.index()); | |
| 144 | #else | |
| 145 | if (isArray_) | |
| 146 | return Value(ValueInternalArray::indexOf(iterator_.array_)); | |
| 147 | bool isStatic; | |
| 148 | const char* memberName = ValueInternalMap::key(iterator_.map_, isStatic); | |
| 149 | if (isStatic) | |
| 150 | return Value(StaticString(memberName)); | |
| 151 | return Value(memberName); | |
| 152 | #endif | |
| 153 | } | |
| 154 | ||
| 155 | UInt ValueIteratorBase::index() const { | |
| 156 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 157 | const Value::CZString czstring = (*current_).first; | |
| 158 | if (!czstring.c_str()) | |
| 159 | return czstring.index(); | |
| 160 | return Value::UInt(-1); | |
| 161 | #else | |
| 162 | if (isArray_) | |
| 163 | return Value::UInt(ValueInternalArray::indexOf(iterator_.array_)); | |
| 164 | return Value::UInt(-1); | |
| 165 | #endif | |
| 166 | } | |
| 167 | ||
| 168 | const char* ValueIteratorBase::memberName() const { | |
| 169 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 170 | const char* name = (*current_).first.c_str(); | |
| 171 | return name ? name : ""; | |
| 172 | #else | |
| 173 | if (!isArray_) | |
| 174 | return ValueInternalMap::key(iterator_.map_); | |
| 175 | return ""; | |
| 176 | #endif | |
| 177 | } | |
| 178 | ||
| 179 | // ////////////////////////////////////////////////////////////////// | |
| 180 | // ////////////////////////////////////////////////////////////////// | |
| 181 | // ////////////////////////////////////////////////////////////////// | |
| 182 | // class ValueConstIterator | |
| 183 | // ////////////////////////////////////////////////////////////////// | |
| 184 | // ////////////////////////////////////////////////////////////////// | |
| 185 | // ////////////////////////////////////////////////////////////////// | |
| 186 | ||
| 187 | ValueConstIterator::ValueConstIterator() {} | |
| 188 | ||
| 189 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 190 | ValueConstIterator::ValueConstIterator( | |
| 191 | const Value::ObjectValues::iterator& current) | |
| 192 | : ValueIteratorBase(current) {} | |
| 193 | #else | |
| 194 | ValueConstIterator::ValueConstIterator( | |
| 195 | const ValueInternalArray::IteratorState& state) | |
| 196 | : ValueIteratorBase(state) {} | |
| 197 | ||
| 198 | ValueConstIterator::ValueConstIterator( | |
| 199 | const ValueInternalMap::IteratorState& state) | |
| 200 | : ValueIteratorBase(state) {} | |
| 201 | #endif | |
| 202 | ||
| 203 | ValueConstIterator& ValueConstIterator:: | |
| 204 | operator=(const ValueIteratorBase& other) { | |
| 205 | copy(other); | |
| 206 | return *this; | |
| 207 | } | |
| 208 | ||
| 209 | // ////////////////////////////////////////////////////////////////// | |
| 210 | // ////////////////////////////////////////////////////////////////// | |
| 211 | // ////////////////////////////////////////////////////////////////// | |
| 212 | // class ValueIterator | |
| 213 | // ////////////////////////////////////////////////////////////////// | |
| 214 | // ////////////////////////////////////////////////////////////////// | |
| 215 | // ////////////////////////////////////////////////////////////////// | |
| 216 | ||
| 217 | ValueIterator::ValueIterator() {} | |
| 218 | ||
| 219 | #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
| 220 | ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current) | |
| 221 | : ValueIteratorBase(current) {} | |
| 222 | #else | |
| 223 | ValueIterator::ValueIterator(const ValueInternalArray::IteratorState& state) | |
| 224 | : ValueIteratorBase(state) {} | |
| 225 | ||
| 226 | ValueIterator::ValueIterator(const ValueInternalMap::IteratorState& state) | |
| 227 | : ValueIteratorBase(state) {} | |
| 228 | #endif | |
| 229 | ||
| 230 | ValueIterator::ValueIterator(const ValueConstIterator& other) | |
| 231 | : ValueIteratorBase(other) {} | |
| 232 | ||
| 233 | ValueIterator::ValueIterator(const ValueIterator& other) | |
| 234 | : ValueIteratorBase(other) {} | |
| 235 | ||
| 236 | ValueIterator& ValueIterator::operator=(const SelfType& other) { | |
| 237 | copy(other); | |
| 238 | return *this; | |
| 239 | } | |
| 240 | ||
| 241 | } // namespace Json |
| r0 | r242831 | |
|---|---|---|
| 1 | // Copyright 2011 Baptiste Lepilleur | |
| 2 | // Distributed under MIT license, or public domain if desired and | |
| 3 | // recognized in your jurisdiction. | |
| 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE | |
| 5 | ||
| 6 | #if !defined(JSON_IS_AMALGAMATION) | |
| 7 | #include <json/writer.h> | |
| 8 | #include "json_tool.h" | |
| 9 | #endif // if !defined(JSON_IS_AMALGAMATION) | |
| 10 | #include <utility> | |
| 11 | #include <assert.h> | |
| 12 | #include <stdio.h> | |
| 13 | #include <string.h> | |
| 14 | #include <sstream> | |
| 15 | #include <iomanip> | |
| 16 | #include <math.h> | |
| 17 | ||
| 18 | #if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below | |
| 19 | #include <float.h> | |
| 20 | #define isfinite _finite | |
| 21 | #define snprintf _snprintf | |
| 22 | #endif | |
| 23 | ||
| 24 | #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 | |
| 25 | // Disable warning about strdup being deprecated. | |
| 26 | #pragma warning(disable : 4996) | |
| 27 | #endif | |
| 28 | ||
| 29 | #if defined(__sun) && defined(__SVR4) //Solaris | |
| 30 | #include <ieeefp.h> | |
| 31 | #define isfinite finite | |
| 32 | #endif | |
| 33 | ||
| 34 | namespace Json { | |
| 35 | ||
| 36 | static bool containsControlCharacter(const char* str) { | |
| 37 | while (*str) { | |
| 38 | if (isControlCharacter(*(str++))) | |
| 39 | return true; | |
| 40 | } | |
| 41 | return false; | |
| 42 | } | |
| 43 | ||
| 44 | std::string valueToString(LargestInt value) { | |
| 45 | UIntToStringBuffer buffer; | |
| 46 | char* current = buffer + sizeof(buffer); | |
| 47 | bool isNegative = value < 0; | |
| 48 | if (isNegative) | |
| 49 | value = -value; | |
| 50 | uintToString(LargestUInt(value), current); | |
| 51 | if (isNegative) | |
| 52 | *--current = '-'; | |
| 53 | assert(current >= buffer); | |
| 54 | return current; | |
| 55 | } | |
| 56 | ||
| 57 | std::string valueToString(LargestUInt value) { | |
| 58 | UIntToStringBuffer buffer; | |
| 59 | char* current = buffer + sizeof(buffer); | |
| 60 | uintToString(value, current); | |
| 61 | assert(current >= buffer); | |
| 62 | return current; | |
| 63 | } | |
| 64 | ||
| 65 | #if defined(JSON_HAS_INT64) | |
| 66 | ||
| 67 | std::string valueToString(Int value) { | |
| 68 | return valueToString(LargestInt(value)); | |
| 69 | } | |
| 70 | ||
| 71 | std::string valueToString(UInt value) { | |
| 72 | return valueToString(LargestUInt(value)); | |
| 73 | } | |
| 74 | ||
| 75 | #endif // # if defined(JSON_HAS_INT64) | |
| 76 | ||
| 77 | std::string valueToString(double value) { | |
| 78 | // Allocate a buffer that is more than large enough to store the 16 digits of | |
| 79 | // precision requested below. | |
| 80 | char buffer[32]; | |
| 81 | int len = -1; | |
| 82 | ||
| 83 | // Print into the buffer. We need not request the alternative representation | |
| 84 | // that always has a decimal point because JSON doesn't distingish the | |
| 85 | // concepts of reals and integers. | |
| 86 | #if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with | |
| 87 | // visual studio 2005 to | |
| 88 | // avoid warning. | |
| 89 | #if defined(WINCE) | |
| 90 | len = _snprintf(buffer, sizeof(buffer), "%.17g", value); | |
| 91 | #else | |
| 92 | len = sprintf_s(buffer, sizeof(buffer), "%.17g", value); | |
| 93 | #endif | |
| 94 | #else | |
| 95 | if (isfinite(value)) { | |
| 96 | len = snprintf(buffer, sizeof(buffer), "%.17g", value); | |
| 97 | } else { | |
| 98 | // IEEE standard states that NaN values will not compare to themselves | |
| 99 | if (value != value) { | |
| 100 | len = snprintf(buffer, sizeof(buffer), "null"); | |
| 101 | } else if (value < 0) { | |
| 102 | len = snprintf(buffer, sizeof(buffer), "-1e+9999"); | |
| 103 | } else { | |
| 104 | len = snprintf(buffer, sizeof(buffer), "1e+9999"); | |
| 105 | } | |
| 106 | // For those, we do not need to call fixNumLoc, but it is fast. | |
| 107 | } | |
| 108 | #endif | |
| 109 | assert(len >= 0); | |
| 110 | fixNumericLocale(buffer, buffer + len); | |
| 111 | return buffer; | |
| 112 | } | |
| 113 | ||
| 114 | std::string valueToString(bool value) { return value ? "true" : "false"; } | |
| 115 | ||
| 116 | std::string valueToQuotedString(const char* value) { | |
| 117 | if (value == NULL) | |
| 118 | return ""; | |
| 119 | // Not sure how to handle unicode... | |
| 120 | if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && | |
| 121 | !containsControlCharacter(value)) | |
| 122 | return std::string("\"") + value + "\""; | |
| 123 | // We have to walk value and escape any special characters. | |
| 124 | // Appending to std::string is not efficient, but this should be rare. | |
| 125 | // (Note: forward slashes are *not* rare, but I am not escaping them.) | |
| 126 | std::string::size_type maxsize = | |
| 127 | strlen(value) * 2 + 3; // allescaped+quotes+NULL | |
| 128 | std::string result; | |
| 129 | result.reserve(maxsize); // to avoid lots of mallocs | |
| 130 | result += "\""; | |
| 131 | for (const char* c = value; *c != 0; ++c) { | |
| 132 | switch (*c) { | |
| 133 | case '\"': | |
| 134 | result += "\\\""; | |
| 135 | break; | |
| 136 | case '\\': | |
| 137 | result += "\\\\"; | |
| 138 | break; | |
| 139 | case '\b': | |
| 140 | result += "\\b"; | |
| 141 | break; | |
| 142 | case '\f': | |
| 143 | result += "\\f"; | |
| 144 | break; | |
| 145 | case '\n': | |
| 146 | result += "\\n"; | |
| 147 | break; | |
| 148 | case '\r': | |
| 149 | result += "\\r"; | |
| 150 | break; | |
| 151 | case '\t': | |
| 152 | result += "\\t"; | |
| 153 | break; | |
| 154 | // case '/': | |
| 155 | // Even though \/ is considered a legal escape in JSON, a bare | |
| 156 | // slash is also legal, so I see no reason to escape it. | |
| 157 | // (I hope I am not misunderstanding something. | |
| 158 | // blep notes: actually escaping \/ may be useful in javascript to avoid </ | |
| 159 | // sequence. | |
| 160 | // Should add a flag to allow this compatibility mode and prevent this | |
| 161 | // sequence from occurring. | |
| 162 | default: | |
| 163 | if (isControlCharacter(*c)) { | |
| 164 | std::ostringstream oss; | |
| 165 | oss << "\\u" << std::hex << std::uppercase << std::setfill('0') | |
| 166 | << std::setw(4) << static_cast<int>(*c); | |
| 167 | result += oss.str(); | |
| 168 | } else { | |
| 169 | result += *c; | |
| 170 | } | |
| 171 | break; | |
| 172 | } | |
| 173 | } | |
| 174 | result += "\""; | |
| 175 | return result; | |
| 176 | } | |
| 177 | ||
| 178 | // Class Writer | |
| 179 | // ////////////////////////////////////////////////////////////////// | |
| 180 | Writer::~Writer() {} | |
| 181 | ||
| 182 | // Class FastWriter | |
| 183 | // ////////////////////////////////////////////////////////////////// | |
| 184 | ||
| 185 | FastWriter::FastWriter() | |
| 186 | : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false), | |
| 187 | omitEndingLineFeed_(false) {} | |
| 188 | ||
| 189 | void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; } | |
| 190 | ||
| 191 | void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; } | |
| 192 | ||
| 193 | void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; } | |
| 194 | ||
| 195 | std::string FastWriter::write(const Value& root) { | |
| 196 | document_ = ""; | |
| 197 | writeValue(root); | |
| 198 | if (!omitEndingLineFeed_) | |
| 199 | document_ += "\n"; | |
| 200 | return document_; | |
| 201 | } | |
| 202 | ||
| 203 | void FastWriter::writeValue(const Value& value) { | |
| 204 | switch (value.type()) { | |
| 205 | case nullValue: | |
| 206 | if (!dropNullPlaceholders_) | |
| 207 | document_ += "null"; | |
| 208 | break; | |
| 209 | case intValue: | |
| 210 | document_ += valueToString(value.asLargestInt()); | |
| 211 | break; | |
| 212 | case uintValue: | |
| 213 | document_ += valueToString(value.asLargestUInt()); | |
| 214 | break; | |
| 215 | case realValue: | |
| 216 | document_ += valueToString(value.asDouble()); | |
| 217 | break; | |
| 218 | case stringValue: | |
| 219 | document_ += valueToQuotedString(value.asCString()); | |
| 220 | break; | |
| 221 | case booleanValue: | |
| 222 | document_ += valueToString(value.asBool()); | |
| 223 | break; | |
| 224 | case arrayValue: { | |
| 225 | document_ += '['; | |
| 226 | int size = value.size(); | |
| 227 | for (int index = 0; index < size; ++index) { | |
| 228 | if (index > 0) | |
| 229 | document_ += ','; | |
| 230 | writeValue(value[index]); | |
| 231 | } | |
| 232 | document_ += ']'; | |
| 233 | } break; | |
| 234 | case objectValue: { | |
| 235 | Value::Members members(value.getMemberNames()); | |
| 236 | document_ += '{'; | |
| 237 | for (Value::Members::iterator it = members.begin(); it != members.end(); | |
| 238 | ++it) { | |
| 239 | const std::string& name = *it; | |
| 240 | if (it != members.begin()) | |
| 241 | document_ += ','; | |
| 242 | document_ += valueToQuotedString(name.c_str()); | |
| 243 | document_ += yamlCompatiblityEnabled_ ? ": " : ":"; | |
| 244 | writeValue(value[name]); | |
| 245 | } | |
| 246 | document_ += '}'; | |
| 247 | } break; | |
| 248 | } | |
| 249 | } | |
| 250 | ||
| 251 | // Class StyledWriter | |
| 252 | // ////////////////////////////////////////////////////////////////// | |
| 253 | ||
| 254 | StyledWriter::StyledWriter() | |
| 255 | : rightMargin_(74), indentSize_(3), addChildValues_() {} | |
| 256 | ||
| 257 | std::string StyledWriter::write(const Value& root) { | |
| 258 | document_ = ""; | |
| 259 | addChildValues_ = false; | |
| 260 | indentString_ = ""; | |
| 261 | writeCommentBeforeValue(root); | |
| 262 | writeValue(root); | |
| 263 | writeCommentAfterValueOnSameLine(root); | |
| 264 | document_ += "\n"; | |
| 265 | return document_; | |
| 266 | } | |
| 267 | ||
| 268 | void StyledWriter::writeValue(const Value& value) { | |
| 269 | switch (value.type()) { | |
| 270 | case nullValue: | |
| 271 | pushValue("null"); | |
| 272 | break; | |
| 273 | case intValue: | |
| 274 | pushValue(valueToString(value.asLargestInt())); | |
| 275 | break; | |
| 276 | case uintValue: | |
| 277 | pushValue(valueToString(value.asLargestUInt())); | |
| 278 | break; | |
| 279 | case realValue: | |
| 280 | pushValue(valueToString(value.asDouble())); | |
| 281 | break; | |
| 282 | case stringValue: | |
| 283 | pushValue(valueToQuotedString(value.asCString())); | |
| 284 | break; | |
| 285 | case booleanValue: | |
| 286 | pushValue(valueToString(value.asBool())); | |
| 287 | break; | |
| 288 | case arrayValue: | |
| 289 | writeArrayValue(value); | |
| 290 | break; | |
| 291 | case objectValue: { | |
| 292 | Value::Members members(value.getMemberNames()); | |
| 293 | if (members.empty()) | |
| 294 | pushValue("{}"); | |
| 295 | else { | |
| 296 | writeWithIndent("{"); | |
| 297 | indent(); | |
| 298 | Value::Members::iterator it = members.begin(); | |
| 299 | for (;;) { | |
| 300 | const std::string& name = *it; | |
| 301 | const Value& childValue = value[name]; | |
| 302 | writeCommentBeforeValue(childValue); | |
| 303 | writeWithIndent(valueToQuotedString(name.c_str())); | |
| 304 | document_ += " : "; | |
| 305 | writeValue(childValue); | |
| 306 | if (++it == members.end()) { | |
| 307 | writeCommentAfterValueOnSameLine(childValue); | |
| 308 | break; | |
| 309 | } | |
| 310 | document_ += ','; | |
| 311 | writeCommentAfterValueOnSameLine(childValue); | |
| 312 | } | |
| 313 | unindent(); | |
| 314 | writeWithIndent("}"); | |
| 315 | } | |
| 316 | } break; | |
| 317 | } | |
| 318 | } | |
| 319 | ||
| 320 | void StyledWriter::writeArrayValue(const Value& value) { | |
| 321 | unsigned size = value.size(); | |
| 322 | if (size == 0) | |
| 323 | pushValue("[]"); | |
| 324 | else { | |
| 325 | bool isArrayMultiLine = isMultineArray(value); | |
| 326 | if (isArrayMultiLine) { | |
| 327 | writeWithIndent("["); | |
| 328 | indent(); | |
| 329 | bool hasChildValue = !childValues_.empty(); | |
| 330 | unsigned index = 0; | |
| 331 | for (;;) { | |
| 332 | const Value& childValue = value[index]; | |
| 333 | writeCommentBeforeValue(childValue); | |
| 334 | if (hasChildValue) | |
| 335 | writeWithIndent(childValues_[index]); | |
| 336 | else { | |
| 337 | writeIndent(); | |
| 338 | writeValue(childValue); | |
| 339 | } | |
| 340 | if (++index == size) { | |
| 341 | writeCommentAfterValueOnSameLine(childValue); | |
| 342 | break; | |
| 343 | } | |
| 344 | document_ += ','; | |
| 345 | writeCommentAfterValueOnSameLine(childValue); | |
| 346 | } | |
| 347 | unindent(); | |
| 348 | writeWithIndent("]"); | |
| 349 | } else // output on a single line | |
| 350 | { | |
| 351 | assert(childValues_.size() == size); | |
| 352 | document_ += "[ "; | |
| 353 | for (unsigned index = 0; index < size; ++index) { | |
| 354 | if (index > 0) | |
| 355 | document_ += ", "; | |
| 356 | document_ += childValues_[index]; | |
| 357 | } | |
| 358 | document_ += " ]"; | |
| 359 | } | |
| 360 | } | |
| 361 | } | |
| 362 | ||
| 363 | bool StyledWriter::isMultineArray(const Value& value) { | |
| 364 | int size = value.size(); | |
| 365 | bool isMultiLine = size * 3 >= rightMargin_; | |
| 366 | childValues_.clear(); | |
| 367 | for (int index = 0; index < size && !isMultiLine; ++index) { | |
| 368 | const Value& childValue = value[index]; | |
| 369 | isMultiLine = | |
| 370 | isMultiLine || ((childValue.isArray() || childValue.isObject()) && | |
| 371 | childValue.size() > 0); | |
| 372 | } | |
| 373 | if (!isMultiLine) // check if line length > max line length | |
| 374 | { | |
| 375 | childValues_.reserve(size); | |
| 376 | addChildValues_ = true; | |
| 377 | int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' | |
| 378 | for (int index = 0; index < size; ++index) { | |
| 379 | writeValue(value[index]); | |
| 380 | lineLength += int(childValues_[index].length()); | |
| 381 | } | |
| 382 | addChildValues_ = false; | |
| 383 | isMultiLine = isMultiLine || lineLength >= rightMargin_; | |
| 384 | } | |
| 385 | return isMultiLine; | |
| 386 | } | |
| 387 | ||
| 388 | void StyledWriter::pushValue(const std::string& value) { | |
| 389 | if (addChildValues_) | |
| 390 | childValues_.push_back(value); | |
| 391 | else | |
| 392 | document_ += value; | |
| 393 | } | |
| 394 | ||
| 395 | void StyledWriter::writeIndent() { | |
| 396 | if (!document_.empty()) { | |
| 397 | char last = document_[document_.length() - 1]; | |
| 398 | if (last == ' ') // already indented | |
| 399 | return; | |
| 400 | if (last != '\n') // Comments may add new-line | |
| 401 | document_ += '\n'; | |
| 402 | } | |
| 403 | document_ += indentString_; | |
| 404 | } | |
| 405 | ||
| 406 | void StyledWriter::writeWithIndent(const std::string& value) { | |
| 407 | writeIndent(); | |
| 408 | document_ += value; | |
| 409 | } | |
| 410 | ||
| 411 | void StyledWriter::indent() { indentString_ += std::string(indentSize_, ' '); } | |
| 412 | ||
| 413 | void StyledWriter::unindent() { | |
| 414 | assert(int(indentString_.size()) >= indentSize_); | |
| 415 | indentString_.resize(indentString_.size() - indentSize_); | |
| 416 | } | |
| 417 | ||
| 418 | void StyledWriter::writeCommentBeforeValue(const Value& root) { | |
| 419 | if (!root.hasComment(commentBefore)) | |
| 420 | return; | |
| 421 | ||
| 422 | document_ += "\n"; | |
| 423 | writeIndent(); | |
| 424 | std::string normalizedComment = normalizeEOL(root.getComment(commentBefore)); | |
| 425 | std::string::const_iterator iter = normalizedComment.begin(); | |
| 426 | while (iter != normalizedComment.end()) { | |
| 427 | document_ += *iter; | |
| 428 | if (*iter == '\n' && *(iter + 1) == '/') | |
| 429 | writeIndent(); | |
| 430 | ++iter; | |
| 431 | } | |
| 432 | ||
| 433 | // Comments are stripped of newlines, so add one here | |
| 434 | document_ += "\n"; | |
| 435 | } | |
| 436 | ||
| 437 | void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) { | |
| 438 | if (root.hasComment(commentAfterOnSameLine)) | |
| 439 | document_ += " " + normalizeEOL(root.getComment(commentAfterOnSameLine)); | |
| 440 | ||
| 441 | if (root.hasComment(commentAfter)) { | |
| 442 | document_ += "\n"; | |
| 443 | document_ += normalizeEOL(root.getComment(commentAfter)); | |
| 444 | document_ += "\n"; | |
| 445 | } | |
| 446 | } | |
| 447 | ||
| 448 | bool StyledWriter::hasCommentForValue(const Value& value) { | |
| 449 | return value.hasComment(commentBefore) || | |
| 450 | value.hasComment(commentAfterOnSameLine) || | |
| 451 | value.hasComment(commentAfter); | |
| 452 | } | |
| 453 | ||
| 454 | std::string StyledWriter::normalizeEOL(const std::string& text) { | |
| 455 | std::string normalized; | |
| 456 | normalized.reserve(text.length()); | |
| 457 | const char* begin = text.c_str(); | |
| 458 | const char* end = begin + text.length(); | |
| 459 | const char* current = begin; | |
| 460 | while (current != end) { | |
| 461 | char c = *current++; | |
| 462 | if (c == '\r') // mac or dos EOL | |
| 463 | { | |
| 464 | if (*current == '\n') // convert dos EOL | |
| 465 | ++current; | |
| 466 | normalized += '\n'; | |
| 467 | } else // handle unix EOL & other char | |
| 468 | normalized += c; | |
| 469 | } | |
| 470 | return normalized; | |
| 471 | } | |
| 472 | ||
| 473 | // Class StyledStreamWriter | |
| 474 | // ////////////////////////////////////////////////////////////////// | |
| 475 | ||
| 476 | StyledStreamWriter::StyledStreamWriter(std::string indentation) | |
| 477 | : document_(NULL), rightMargin_(74), indentation_(indentation), | |
| 478 | addChildValues_() {} | |
| 479 | ||
| 480 | void StyledStreamWriter::write(std::ostream& out, const Value& root) { | |
| 481 | document_ = &out; | |
| 482 | addChildValues_ = false; | |
| 483 | indentString_ = ""; | |
| 484 | writeCommentBeforeValue(root); | |
| 485 | writeValue(root); | |
| 486 | writeCommentAfterValueOnSameLine(root); | |
| 487 | *document_ << "\n"; | |
| 488 | document_ = NULL; // Forget the stream, for safety. | |
| 489 | } | |
| 490 | ||
| 491 | void StyledStreamWriter::writeValue(const Value& value) { | |
| 492 | switch (value.type()) { | |
| 493 | case nullValue: | |
| 494 | pushValue("null"); | |
| 495 | break; | |
| 496 | case intValue: | |
| 497 | pushValue(valueToString(value.asLargestInt())); | |
| 498 | break; | |
| 499 | case uintValue: | |
| 500 | pushValue(valueToString(value.asLargestUInt())); | |
| 501 | break; | |
| 502 | case realValue: | |
| 503 | pushValue(valueToString(value.asDouble())); | |
| 504 | break; | |
| 505 | case stringValue: | |
| 506 | pushValue(valueToQuotedString(value.asCString())); | |
| 507 | break; | |
| 508 | case booleanValue: | |
| 509 | pushValue(valueToString(value.asBool())); | |
| 510 | break; | |
| 511 | case arrayValue: | |
| 512 | writeArrayValue(value); | |
| 513 | break; | |
| 514 | case objectValue: { | |
| 515 | Value::Members members(value.getMemberNames()); | |
| 516 | if (members.empty()) | |
| 517 | pushValue("{}"); | |
| 518 | else { | |
| 519 | writeWithIndent("{"); | |
| 520 | indent(); | |
| 521 | Value::Members::iterator it = members.begin(); | |
| 522 | for (;;) { | |
| 523 | const std::string& name = *it; | |
| 524 | const Value& childValue = value[name]; | |
| 525 | writeCommentBeforeValue(childValue); | |
| 526 | writeWithIndent(valueToQuotedString(name.c_str())); | |
| 527 | *document_ << " : "; | |
| 528 | writeValue(childValue); | |
| 529 | if (++it == members.end()) { | |
| 530 | writeCommentAfterValueOnSameLine(childValue); | |
| 531 | break; | |
| 532 | } | |
| 533 | *document_ << ","; | |
| 534 | writeCommentAfterValueOnSameLine(childValue); | |
| 535 | } | |
| 536 | unindent(); | |
| 537 | writeWithIndent("}"); | |
| 538 | } | |
| 539 | } break; | |
| 540 | } | |
| 541 | } | |
| 542 | ||
| 543 | void StyledStreamWriter::writeArrayValue(const Value& value) { | |
| 544 | unsigned size = value.size(); | |
| 545 | if (size == 0) | |
| 546 | pushValue("[]"); | |
| 547 | else { | |
| 548 | bool isArrayMultiLine = isMultineArray(value); | |
| 549 | if (isArrayMultiLine) { | |
| 550 | writeWithIndent("["); | |
| 551 | indent(); | |
| 552 | bool hasChildValue = !childValues_.empty(); | |
| 553 | unsigned index = 0; | |
| 554 | for (;;) { | |
| 555 | const Value& childValue = value[index]; | |
| 556 | writeCommentBeforeValue(childValue); | |
| 557 | if (hasChildValue) | |
| 558 | writeWithIndent(childValues_[index]); | |
| 559 | else { | |
| 560 | writeIndent(); | |
| 561 | writeValue(childValue); | |
| 562 | } | |
| 563 | if (++index == size) { | |
| 564 | writeCommentAfterValueOnSameLine(childValue); | |
| 565 | break; | |
| 566 | } | |
| 567 | *document_ << ","; | |
| 568 | writeCommentAfterValueOnSameLine(childValue); | |
| 569 | } | |
| 570 | unindent(); | |
| 571 | writeWithIndent("]"); | |
| 572 | } else // output on a single line | |
| 573 | { | |
| 574 | assert(childValues_.size() == size); | |
| 575 | *document_ << "[ "; | |
| 576 | for (unsigned index = 0; index < size; ++index) { | |
| 577 | if (index > 0) | |
| 578 | *document_ << ", "; | |
| 579 | *document_ << childValues_[index]; | |
| 580 | } | |
| 581 | *document_ << " ]"; | |
| 582 | } | |
| 583 | } | |
| 584 | } | |
| 585 | ||
| 586 | bool StyledStreamWriter::isMultineArray(const Value& value) { | |
| 587 | int size = value.size(); | |
| 588 | bool isMultiLine = size * 3 >= rightMargin_; | |
| 589 | childValues_.clear(); | |
| 590 | for (int index = 0; index < size && !isMultiLine; ++index) { | |
| 591 | const Value& childValue = value[index]; | |
| 592 | isMultiLine = | |
| 593 | isMultiLine || ((childValue.isArray() || childValue.isObject()) && | |
| 594 | childValue.size() > 0); | |
| 595 | } | |
| 596 | if (!isMultiLine) // check if line length > max line length | |
| 597 | { | |
| 598 | childValues_.reserve(size); | |
| 599 | addChildValues_ = true; | |
| 600 | int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' | |
| 601 | for (int index = 0; index < size; ++index) { | |
| 602 | writeValue(value[index]); | |
| 603 | lineLength += int(childValues_[index].length()); | |
| 604 | } | |
| 605 | addChildValues_ = false; | |
| 606 | isMultiLine = isMultiLine || lineLength >= rightMargin_; | |
| 607 | } | |
| 608 | return isMultiLine; | |
| 609 | } | |
| 610 | ||
| 611 | void StyledStreamWriter::pushValue(const std::string& value) { | |
| 612 | if (addChildValues_) | |
| 613 | childValues_.push_back(value); | |
| 614 | else | |
| 615 | *document_ << value; | |
| 616 | } | |
| 617 | ||
| 618 | void StyledStreamWriter::writeIndent() { | |
| 619 | /* | |
| 620 | Some comments in this method would have been nice. ;-) | |
| 621 | ||
| 622 | if ( !document_.empty() ) | |
| 623 | { | |
| 624 | char last = document_[document_.length()-1]; | |
| 625 | if ( last == ' ' ) // already indented | |
| 626 | return; | |
| 627 | if ( last != '\n' ) // Comments may add new-line | |
| 628 | *document_ << '\n'; | |
| 629 | } | |
| 630 | */ | |
| 631 | *document_ << '\n' << indentString_; | |
| 632 | } | |
| 633 | ||
| 634 | void StyledStreamWriter::writeWithIndent(const std::string& value) { | |
| 635 | writeIndent(); | |
| 636 | *document_ << value; | |
| 637 | } | |
| 638 | ||
| 639 | void StyledStreamWriter::indent() { indentString_ += indentation_; } | |
| 640 | ||
| 641 | void StyledStreamWriter::unindent() { | |
| 642 | assert(indentString_.size() >= indentation_.size()); | |
| 643 | indentString_.resize(indentString_.size() - indentation_.size()); | |
| 644 | } | |
| 645 | ||
| 646 | void StyledStreamWriter::writeCommentBeforeValue(const Value& root) { | |
| 647 | if (!root.hasComment(commentBefore)) | |
| 648 | return; | |
| 649 | *document_ << normalizeEOL(root.getComment(commentBefore)); | |
| 650 | *document_ << "\n"; | |
| 651 | } | |
| 652 | ||
| 653 | void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) { | |
| 654 | if (root.hasComment(commentAfterOnSameLine)) | |
| 655 | *document_ << " " + normalizeEOL(root.getComment(commentAfterOnSameLine)); | |
| 656 | ||
| 657 | if (root.hasComment(commentAfter)) { | |
| 658 | *document_ << "\n"; | |
| 659 | *document_ << normalizeEOL(root.getComment(commentAfter)); | |
| 660 | *document_ << "\n"; | |
| 661 | } | |
| 662 | } | |
| 663 | ||
| 664 | bool StyledStreamWriter::hasCommentForValue(const Value& value) { | |
| 665 | return value.hasComment(commentBefore) || | |
| 666 | value.hasComment(commentAfterOnSameLine) || | |
| 667 | value.hasComment(commentAfter); | |
| 668 | } | |
| 669 | ||
| 670 | std::string StyledStreamWriter::normalizeEOL(const std::string& text) { | |
| 671 | std::string normalized; | |
| 672 | normalized.reserve(text.length()); | |
| 673 | const char* begin = text.c_str(); | |
| 674 | const char* end = begin + text.length(); | |
| 675 | const char* current = begin; | |
| 676 | while (current != end) { | |
| 677 | char c = *current++; | |
| 678 | if (c == '\r') // mac or dos EOL | |
| 679 | { | |
| 680 | if (*current == '\n') // convert dos EOL | |
| 681 | ++current; | |
| 682 | normalized += '\n'; | |
| 683 | } else // handle unix EOL & other char | |
| 684 | normalized += c; | |
| 685 | } | |
| 686 | return normalized; | |
| 687 | } | |
| 688 | ||
| 689 | std::ostream& operator<<(std::ostream& sout, const Value& root) { | |
| 690 | Json::StyledStreamWriter writer; | |
| 691 | writer.write(sout, root); | |
| 692 | return sout; | |
| 693 | } | |
| 694 | ||
| 695 | } // namespace Json |
| r0 | r242831 | |
|---|---|---|
| 1 | Import( 'env buildLibrary' ) | |
| 2 | ||
| 3 | buildLibrary( env, Split( """ | |
| 4 | json_reader.cpp | |
| 5 | json_value.cpp | |
| 6 | json_writer.cpp | |
| 7 | """ ), | |
| 8 | 'json' ) |
| r0 | r242831 | |
|---|---|---|
| 1 | // DO NOT EDIT. This file is generated by CMake from "version" | |
| 2 | // and "version.h.in" files. | |
| 3 | // Run CMake configure step to update it. | |
| 4 | #ifndef JSON_VERSION_H_INCLUDED | |
| 5 | # define JSON_VERSION_H_INCLUDED | |
| 6 | ||
| 7 | # define JSONCPP_VERSION_STRING "@JSONCPP_VERSION@" | |
| 8 | # define JSONCPP_VERSION_MAJOR @JSONCPP_VERSION_MAJOR@ | |
| 9 | # define JSONCPP_VERSION_MINOR @JSONCPP_VERSION_MINOR@ | |
| 10 | # define JSONCPP_VERSION_PATCH @JSONCPP_VERSION_PATCH@ | |
| 11 | # define JSONCPP_VERSION_QUALIFIER | |
| 12 | # define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8)) | |
| 13 | ||
| 14 | #endif // JSON_VERSION_H_INCLUDED |
| r0 | r242831 | |
|---|---|---|
| 1 | ||
| 2 | IF(JSONCPP_LIB_BUILD_SHARED) | |
| 3 | ADD_DEFINITIONS( -DJSON_DLL ) | |
| 4 | ENDIF(JSONCPP_LIB_BUILD_SHARED) | |
| 5 | ||
| 6 | ADD_EXECUTABLE( jsoncpp_test | |
| 7 | jsontest.cpp | |
| 8 | jsontest.h | |
| 9 | main.cpp | |
| 10 | ) | |
| 11 | ||
| 12 | TARGET_LINK_LIBRARIES(jsoncpp_test jsoncpp_lib) | |
| 13 | ||
| 14 | # Run unit tests in post-build | |
| 15 | # (default cmake workflow hides away the test result into a file, resulting in poor dev workflow?!?) | |
| 16 | IF(JSONCPP_WITH_POST_BUILD_UNITTEST) | |
| 17 | ADD_CUSTOM_COMMAND( TARGET jsoncpp_test | |
| 18 | POST_BUILD | |
| 19 | COMMAND $<TARGET_FILE:jsoncpp_test>) | |
| 20 | ENDIF(JSONCPP_WITH_POST_BUILD_UNITTEST) | |
| 21 | ||
| 22 | SET_TARGET_PROPERTIES(jsoncpp_test PROPERTIES OUTPUT_NAME jsoncpp_test) |
| r0 | r242831 | |
|---|---|---|
| 1 | // Copyright 2007-2010 Baptiste Lepilleur | |
| 2 | // Distributed under MIT license, or public domain if desired and | |
| 3 | // recognized in your jurisdiction. | |
| 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE | |
| 5 | ||
| 6 | #define _CRT_SECURE_NO_WARNINGS 1 // Prevents deprecation warning with MSVC | |
| 7 | #include "jsontest.h" | |
| 8 | #include <stdio.h> | |
| 9 | #include <string> | |
| 10 | ||
| 11 | #if defined(_MSC_VER) | |
| 12 | // Used to install a report hook that prevent dialog on assertion and error. | |
| 13 | #include <crtdbg.h> | |
| 14 | #endif // if defined(_MSC_VER) | |
| 15 | ||
| 16 | #if defined(_WIN32) | |
| 17 | // Used to prevent dialog on memory fault. | |
| 18 | // Limits headers included by Windows.h | |
| 19 | #define WIN32_LEAN_AND_MEAN | |
| 20 | #define NOSERVICE | |
| 21 | #define NOMCX | |
| 22 | #define NOIME | |
| 23 | #define NOSOUND | |
| 24 | #define NOCOMM | |
| 25 | #define NORPC | |
| 26 | #define NOGDI | |
| 27 | #define NOUSER | |
| 28 | #define NODRIVERS | |
| 29 | #define NOLOGERROR | |
| 30 | #define NOPROFILER | |
| 31 | #define NOMEMMGR | |
| 32 | #define NOLFILEIO | |
| 33 | #define NOOPENFILE | |
| 34 | #define NORESOURCE | |
| 35 | #define NOATOM | |
| 36 | #define NOLANGUAGE | |
| 37 | #define NOLSTRING | |
| 38 | #define NODBCS | |
| 39 | #define NOKEYBOARDINFO | |
| 40 | #define NOGDICAPMASKS | |
| 41 | #define NOCOLOR | |
| 42 | #define NOGDIOBJ | |
| 43 | #define NODRAWTEXT | |
| 44 | #define NOTEXTMETRIC | |
| 45 | #define NOSCALABLEFONT | |
| 46 | #define NOBITMAP | |
| 47 | #define NORASTEROPS | |
| 48 | #define NOMETAFILE | |
| 49 | #define NOSYSMETRICS | |
| 50 | #define NOSYSTEMPARAMSINFO | |
| 51 | #define NOMSG | |
| 52 | #define NOWINSTYLES | |
| 53 | #define NOWINOFFSETS | |
| 54 | #define NOSHOWWINDOW | |
| 55 | #define NODEFERWINDOWPOS | |
| 56 | #define NOVIRTUALKEYCODES | |
| 57 | #define NOKEYSTATES | |
| 58 | #define NOWH | |
| 59 | #define NOMENUS | |
| 60 | #define NOSCROLL | |
| 61 | #define NOCLIPBOARD | |
| 62 | #define NOICONS | |
| 63 | #define NOMB | |
| 64 | #define NOSYSCOMMANDS | |
| 65 | #define NOMDI | |
| 66 | #define NOCTLMGR | |
| 67 | #define NOWINMESSAGES | |
| 68 | #include <windows.h> | |
| 69 | #endif // if defined(_WIN32) | |
| 70 | ||
| 71 | namespace JsonTest { | |
| 72 | ||
| 73 | // class TestResult | |
| 74 | // ////////////////////////////////////////////////////////////////// | |
| 75 | ||
| 76 | TestResult::TestResult() | |
| 77 | : predicateId_(1), lastUsedPredicateId_(0), messageTarget_(0) { | |
| 78 | // The root predicate has id 0 | |
| 79 | rootPredicateNode_.id_ = 0; | |
| 80 | rootPredicateNode_.next_ = 0; | |
| 81 | predicateStackTail_ = &rootPredicateNode_; | |
| 82 | } | |
| 83 | ||
| 84 | void TestResult::setTestName(const std::string& name) { name_ = name; } | |
| 85 | ||
| 86 | TestResult& | |
| 87 | TestResult::addFailure(const char* file, unsigned int line, const char* expr) { | |
| 88 | /// Walks the PredicateContext stack adding them to failures_ if not already | |
| 89 | /// added. | |
| 90 | unsigned int nestingLevel = 0; | |
| 91 | PredicateContext* lastNode = rootPredicateNode_.next_; | |
| 92 | for (; lastNode != 0; lastNode = lastNode->next_) { | |
| 93 | if (lastNode->id_ > lastUsedPredicateId_) // new PredicateContext | |
| 94 | { | |
| 95 | lastUsedPredicateId_ = lastNode->id_; | |
| 96 | addFailureInfo( | |
| 97 | lastNode->file_, lastNode->line_, lastNode->expr_, nestingLevel); | |
| 98 | // Link the PredicateContext to the failure for message target when | |
| 99 | // popping the PredicateContext. | |
| 100 | lastNode->failure_ = &(failures_.back()); | |
| 101 | } | |
| 102 | ++nestingLevel; | |
| 103 | } | |
| 104 | ||
| 105 | // Adds the failed assertion | |
| 106 | addFailureInfo(file, line, expr, nestingLevel); | |
| 107 | messageTarget_ = &(failures_.back()); | |
| 108 | return *this; | |
| 109 | } | |
| 110 | ||
| 111 | void TestResult::addFailureInfo(const char* file, | |
| 112 | unsigned int line, | |
| 113 | const char* expr, | |
| 114 | unsigned int nestingLevel) { | |
| 115 | Failure failure; | |
| 116 | failure.file_ = file; | |
| 117 | failure.line_ = line; | |
| 118 | if (expr) { | |
| 119 | failure.expr_ = expr; | |
| 120 | } | |
| 121 | failure.nestingLevel_ = nestingLevel; | |
| 122 | failures_.push_back(failure); | |
| 123 | } | |
| 124 | ||
| 125 | TestResult& TestResult::popPredicateContext() { | |
| 126 | PredicateContext* lastNode = &rootPredicateNode_; | |
| 127 | while (lastNode->next_ != 0 && lastNode->next_->next_ != 0) { | |
| 128 | lastNode = lastNode->next_; | |
| 129 | } | |
| 130 | // Set message target to popped failure | |
| 131 | PredicateContext* tail = lastNode->next_; | |
| 132 | if (tail != 0 && tail->failure_ != 0) { | |
| 133 | messageTarget_ = tail->failure_; | |
| 134 | } | |
| 135 | // Remove tail from list | |
| 136 | predicateStackTail_ = lastNode; | |
| 137 | lastNode->next_ = 0; | |
| 138 | return *this; | |
| 139 | } | |
| 140 | ||
| 141 | bool TestResult::failed() const { return !failures_.empty(); } | |
| 142 | ||
| 143 | unsigned int TestResult::getAssertionNestingLevel() const { | |
| 144 | unsigned int level = 0; | |
| 145 | const PredicateContext* lastNode = &rootPredicateNode_; | |
| 146 | while (lastNode->next_ != 0) { | |
| 147 | lastNode = lastNode->next_; | |
| 148 | ++level; | |
| 149 | } | |
| 150 | return level; | |
| 151 | } | |
| 152 | ||
| 153 | void TestResult::printFailure(bool printTestName) const { | |
| 154 | if (failures_.empty()) { | |
| 155 | return; | |
| 156 | } | |
| 157 | ||
| 158 | if (printTestName) { | |
| 159 | printf("* Detail of %s test failure:\n", name_.c_str()); | |
| 160 | } | |
| 161 | ||
| 162 | // Print in reverse to display the callstack in the right order | |
| 163 | Failures::const_iterator itEnd = failures_.end(); | |
| 164 | for (Failures::const_iterator it = failures_.begin(); it != itEnd; ++it) { | |
| 165 | const Failure& failure = *it; | |
| 166 | std::string indent(failure.nestingLevel_ * 2, ' '); | |
| 167 | if (failure.file_) { | |
| 168 | printf("%s%s(%d): ", indent.c_str(), failure.file_, failure.line_); | |
| 169 | } | |
| 170 | if (!failure.expr_.empty()) { | |
| 171 | printf("%s\n", failure.expr_.c_str()); | |
| 172 | } else if (failure.file_) { | |
| 173 | printf("\n"); | |
| 174 | } | |
| 175 | if (!failure.message_.empty()) { | |
| 176 | std::string reindented = indentText(failure.message_, indent + " "); | |
| 177 | printf("%s\n", reindented.c_str()); | |
| 178 | } | |
| 179 | } | |
| 180 | } | |
| 181 | ||
| 182 | std::string TestResult::indentText(const std::string& text, | |
| 183 | const std::string& indent) { | |
| 184 | std::string reindented; | |
| 185 | std::string::size_type lastIndex = 0; | |
| 186 | while (lastIndex < text.size()) { | |
| 187 | std::string::size_type nextIndex = text.find('\n', lastIndex); | |
| 188 | if (nextIndex == std::string::npos) { | |
| 189 | nextIndex = text.size() - 1; | |
| 190 | } | |
| 191 | reindented += indent; | |
| 192 | reindented += text.substr(lastIndex, nextIndex - lastIndex + 1); | |
| 193 | lastIndex = nextIndex + 1; | |
| 194 | } | |
| 195 | return reindented; | |
| 196 | } | |
| 197 | ||
| 198 | TestResult& TestResult::addToLastFailure(const std::string& message) { | |
| 199 | if (messageTarget_ != 0) { | |
| 200 | messageTarget_->message_ += message; | |
| 201 | } | |
| 202 | return *this; | |
| 203 | } | |
| 204 | ||
| 205 | TestResult& TestResult::operator<<(Json::Int64 value) { | |
| 206 | return addToLastFailure(Json::valueToString(value)); | |
| 207 | } | |
| 208 | ||
| 209 | TestResult& TestResult::operator<<(Json::UInt64 value) { | |
| 210 | return addToLastFailure(Json::valueToString(value)); | |
| 211 | } | |
| 212 | ||
| 213 | TestResult& TestResult::operator<<(bool value) { | |
| 214 | return addToLastFailure(value ? "true" : "false"); | |
| 215 | } | |
| 216 | ||
| 217 | // class TestCase | |
| 218 | // ////////////////////////////////////////////////////////////////// | |
| 219 | ||
| 220 | TestCase::TestCase() : result_(0) {} | |
| 221 | ||
| 222 | TestCase::~TestCase() {} | |
| 223 | ||
| 224 | void TestCase::run(TestResult& result) { | |
| 225 | result_ = &result; | |
| 226 | runTestCase(); | |
| 227 | } | |
| 228 | ||
| 229 | // class Runner | |
| 230 | // ////////////////////////////////////////////////////////////////// | |
| 231 | ||
| 232 | Runner::Runner() {} | |
| 233 | ||
| 234 | Runner& Runner::add(TestCaseFactory factory) { | |
| 235 | tests_.push_back(factory); | |
| 236 | return *this; | |
| 237 | } | |
| 238 | ||
| 239 | unsigned int Runner::testCount() const { | |
| 240 | return static_cast<unsigned int>(tests_.size()); | |
| 241 | } | |
| 242 | ||
| 243 | std::string Runner::testNameAt(unsigned int index) const { | |
| 244 | TestCase* test = tests_[index](); | |
| 245 | std::string name = test->testName(); | |
| 246 | delete test; | |
| 247 | return name; | |
| 248 | } | |
| 249 | ||
| 250 | void Runner::runTestAt(unsigned int index, TestResult& result) const { | |
| 251 | TestCase* test = tests_[index](); | |
| 252 | result.setTestName(test->testName()); | |
| 253 | printf("Testing %s: ", test->testName()); | |
| 254 | fflush(stdout); | |
| 255 | #if JSON_USE_EXCEPTION | |
| 256 | try { | |
| 257 | #endif // if JSON_USE_EXCEPTION | |
| 258 | test->run(result); | |
| 259 | #if JSON_USE_EXCEPTION | |
| 260 | } | |
| 261 | catch (const std::exception& e) { | |
| 262 | result.addFailure(__FILE__, __LINE__, "Unexpected exception caught:") | |
| 263 | << e.what(); | |
| 264 | } | |
| 265 | #endif // if JSON_USE_EXCEPTION | |
| 266 | delete test; | |
| 267 | const char* status = result.failed() ? "FAILED" : "OK"; | |
| 268 | printf("%s\n", status); | |
| 269 | fflush(stdout); | |
| 270 | } | |
| 271 | ||
| 272 | bool Runner::runAllTest(bool printSummary) const { | |
| 273 | unsigned int count = testCount(); | |
| 274 | std::deque<TestResult> failures; | |
| 275 | for (unsigned int index = 0; index < count; ++index) { | |
| 276 | TestResult result; | |
| 277 | runTestAt(index, result); | |
| 278 | if (result.failed()) { | |
| 279 | failures.push_back(result); | |
| 280 | } | |
| 281 | } | |
| 282 | ||
| 283 | if (failures.empty()) { | |
| 284 | if (printSummary) { | |
| 285 | printf("All %d tests passed\n", count); | |
| 286 | } | |
| 287 | return true; | |
| 288 | } else { | |
| 289 | for (unsigned int index = 0; index < failures.size(); ++index) { | |
| 290 | TestResult& result = failures[index]; | |
| 291 | result.printFailure(count > 1); | |
| 292 | } | |
| 293 | ||
| 294 | if (printSummary) { | |
| 295 | unsigned int failedCount = static_cast<unsigned int>(failures.size()); | |
| 296 | unsigned int passedCount = count - failedCount; | |
| 297 | printf("%d/%d tests passed (%d failure(s))\n", | |
| 298 | passedCount, | |
| 299 | count, | |
| 300 | failedCount); | |
| 301 | } | |
| 302 | return false; | |
| 303 | } | |
| 304 | } | |
| 305 | ||
| 306 | bool Runner::testIndex(const std::string& testName, | |
| 307 | unsigned int& indexOut) const { | |
| 308 | unsigned int count = testCount(); | |
| 309 | for (unsigned int index = 0; index < count; ++index) { | |
| 310 | if (testNameAt(index) == testName) { | |
| 311 | indexOut = index; | |
| 312 | return true; | |
| 313 | } | |
| 314 | } | |
| 315 | return false; | |
| 316 | } | |
| 317 | ||
| 318 | void Runner::listTests() const { | |
| 319 | unsigned int count = testCount(); | |
| 320 | for (unsigned int index = 0; index < count; ++index) { | |
| 321 | printf("%s\n", testNameAt(index).c_str()); | |
| 322 | } | |
| 323 | } | |
| 324 | ||
| 325 | int Runner::runCommandLine(int argc, const char* argv[]) const { | |
| 326 | typedef std::deque<std::string> TestNames; | |
| 327 | Runner subrunner; | |
| 328 | for (int index = 1; index < argc; ++index) { | |
| 329 | std::string opt = argv[index]; | |
| 330 | if (opt == "--list-tests") { | |
| 331 | listTests(); | |
| 332 | return 0; | |
| 333 | } else if (opt == "--test-auto") { | |
| 334 | preventDialogOnCrash(); | |
| 335 | } else if (opt == "--test") { | |
| 336 | ++index; | |
| 337 | if (index < argc) { | |
| 338 | unsigned int testNameIndex; | |
| 339 | if (testIndex(argv[index], testNameIndex)) { | |
| 340 | subrunner.add(tests_[testNameIndex]); | |
| 341 | } else { | |
| 342 | fprintf(stderr, "Test '%s' does not exist!\n", argv[index]); | |
| 343 | return 2; | |
| 344 | } | |
| 345 | } else { | |
| 346 | printUsage(argv[0]); | |
| 347 | return 2; | |
| 348 | } | |
| 349 | } else { | |
| 350 | printUsage(argv[0]); | |
| 351 | return 2; | |
| 352 | } | |
| 353 | } | |
| 354 | bool succeeded; | |
| 355 | if (subrunner.testCount() > 0) { | |
| 356 | succeeded = subrunner.runAllTest(subrunner.testCount() > 1); | |
| 357 | } else { | |
| 358 | succeeded = runAllTest(true); | |
| 359 | } | |
| 360 | return succeeded ? 0 : 1; | |
| 361 | } | |
| 362 | ||
| 363 | #if defined(_MSC_VER) && defined(_DEBUG) | |
| 364 | // Hook MSVCRT assertions to prevent dialog from appearing | |
| 365 | static int | |
| 366 | msvcrtSilentReportHook(int reportType, char* message, int* /*returnValue*/) { | |
| 367 | // The default CRT handling of error and assertion is to display | |
| 368 | // an error dialog to the user. | |
| 369 | // Instead, when an error or an assertion occurs, we force the | |
| 370 | // application to terminate using abort() after display | |
| 371 | // the message on stderr. | |
| 372 | if (reportType == _CRT_ERROR || reportType == _CRT_ASSERT) { | |
| 373 | // calling abort() cause the ReportHook to be called | |
| 374 | // The following is used to detect this case and let's the | |
| 375 | // error handler fallback on its default behaviour ( | |
| 376 | // display a warning message) | |
| 377 | static volatile bool isAborting = false; | |
| 378 | if (isAborting) { | |
| 379 | return TRUE; | |
| 380 | } | |
| 381 | isAborting = true; | |
| 382 | ||
| 383 | fprintf(stderr, "CRT Error/Assert:\n%s\n", message); | |
| 384 | fflush(stderr); | |
| 385 | abort(); | |
| 386 | } | |
| 387 | // Let's other reportType (_CRT_WARNING) be handled as they would by default | |
| 388 | return FALSE; | |
| 389 | } | |
| 390 | #endif // if defined(_MSC_VER) | |
| 391 | ||
| 392 | void Runner::preventDialogOnCrash() { | |
| 393 | #if defined(_MSC_VER) && defined(_DEBUG) | |
| 394 | // Install a hook to prevent MSVCRT error and assertion from | |
| 395 | // popping a dialog | |
| 396 | // This function a NO-OP in release configuration | |
| 397 | // (which cause warning since msvcrtSilentReportHook is not referenced) | |
| 398 | _CrtSetReportHook(&msvcrtSilentReportHook); | |
| 399 | #endif // if defined(_MSC_VER) | |
| 400 | ||
| 401 | // @todo investiguate this handler (for buffer overflow) | |
| 402 | // _set_security_error_handler | |
| 403 | ||
| 404 | #if defined(_WIN32) | |
| 405 | // Prevents the system from popping a dialog for debugging if the | |
| 406 | // application fails due to invalid memory access. | |
| 407 | SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | | |
| 408 | SEM_NOOPENFILEERRORBOX); | |
| 409 | #endif // if defined(_WIN32) | |
| 410 | } | |
| 411 | ||
| 412 | void Runner::printUsage(const char* appName) { | |
| 413 | printf("Usage: %s [options]\n" | |
| 414 | "\n" | |
| 415 | "If --test is not specified, then all the test cases be run.\n" | |
| 416 | "\n" | |
| 417 | "Valid options:\n" | |
| 418 | "--list-tests: print the name of all test cases on the standard\n" | |
| 419 | " output and exit.\n" | |
| 420 | "--test TESTNAME: executes the test case with the specified name.\n" | |
| 421 | " May be repeated.\n" | |
| 422 | "--test-auto: prevent dialog prompting for debugging on crash.\n", | |
| 423 | appName); | |
| 424 | } | |
| 425 | ||
| 426 | // Assertion functions | |
| 427 | // ////////////////////////////////////////////////////////////////// | |
| 428 | ||
| 429 | TestResult& checkStringEqual(TestResult& result, | |
| 430 | const std::string& expected, | |
| 431 | const std::string& actual, | |
| 432 | const char* file, | |
| 433 | unsigned int line, | |
| 434 | const char* expr) { | |
| 435 | if (expected != actual) { | |
| 436 | result.addFailure(file, line, expr); | |
| 437 | result << "Expected: '" << expected << "'\n"; | |
| 438 | result << "Actual : '" << actual << "'"; | |
| 439 | } | |
| 440 | return result; | |
| 441 | } | |
| 442 | ||
| 443 | } // namespace JsonTest |
| r0 | r242831 | |
|---|---|---|
| 1 | // Copyright 2007-2010 Baptiste Lepilleur | |
| 2 | // Distributed under MIT license, or public domain if desired and | |
| 3 | // recognized in your jurisdiction. | |
| 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE | |
| 5 | ||
| 6 | #ifndef JSONTEST_H_INCLUDED | |
| 7 | #define JSONTEST_H_INCLUDED | |
| 8 | ||
| 9 | #include <json/config.h> | |
| 10 | #include <json/value.h> | |
| 11 | #include <json/writer.h> | |
| 12 | #include <stdio.h> | |
| 13 | #include <deque> | |
| 14 | #include <sstream> | |
| 15 | #include <string> | |
| 16 | ||
| 17 | // ////////////////////////////////////////////////////////////////// | |
| 18 | // ////////////////////////////////////////////////////////////////// | |
| 19 | // Mini Unit Testing framework | |
| 20 | // ////////////////////////////////////////////////////////////////// | |
| 21 | // ////////////////////////////////////////////////////////////////// | |
| 22 | ||
| 23 | /** \brief Unit testing framework. | |
| 24 | * \warning: all assertions are non-aborting, test case execution will continue | |
| 25 | * even if an assertion namespace. | |
| 26 | * This constraint is for portability: the framework needs to compile | |
| 27 | * on Visual Studio 6 and must not require exception usage. | |
| 28 | */ | |
| 29 | namespace JsonTest { | |
| 30 | ||
| 31 | class Failure { | |
| 32 | public: | |
| 33 | const char* file_; | |
| 34 | unsigned int line_; | |
| 35 | std::string expr_; | |
| 36 | std::string message_; | |
| 37 | unsigned int nestingLevel_; | |
| 38 | }; | |
| 39 | ||
| 40 | /// Context used to create the assertion callstack on failure. | |
| 41 | /// Must be a POD to allow inline initialisation without stepping | |
| 42 | /// into the debugger. | |
| 43 | struct PredicateContext { | |
| 44 | typedef unsigned int Id; | |
| 45 | Id id_; | |
| 46 | const char* file_; | |
| 47 | unsigned int line_; | |
| 48 | const char* expr_; | |
| 49 | PredicateContext* next_; | |
| 50 | /// Related Failure, set when the PredicateContext is converted | |
| 51 | /// into a Failure. | |
| 52 | Failure* failure_; | |
| 53 | }; | |
| 54 | ||
| 55 | class TestResult { | |
| 56 | public: | |
| 57 | TestResult(); | |
| 58 | ||
| 59 | /// \internal Implementation detail for assertion macros | |
| 60 | /// Not encapsulated to prevent step into when debugging failed assertions | |
| 61 | /// Incremented by one on assertion predicate entry, decreased by one | |
| 62 | /// by addPredicateContext(). | |
| 63 | PredicateContext::Id predicateId_; | |
| 64 | ||
| 65 | /// \internal Implementation detail for predicate macros | |
| 66 | PredicateContext* predicateStackTail_; | |
| 67 | ||
| 68 | void setTestName(const std::string& name); | |
| 69 | ||
| 70 | /// Adds an assertion failure. | |
| 71 | TestResult& | |
| 72 | addFailure(const char* file, unsigned int line, const char* expr = 0); | |
| 73 | ||
| 74 | /// Removes the last PredicateContext added to the predicate stack | |
| 75 | /// chained list. | |
| 76 | /// Next messages will be targed at the PredicateContext that was removed. | |
| 77 | TestResult& popPredicateContext(); | |
| 78 | ||
| 79 | bool failed() const; | |
| 80 | ||
| 81 | void printFailure(bool printTestName) const; | |
| 82 | ||
| 83 | // Generic operator that will work with anything ostream can deal with. | |
| 84 | template <typename T> TestResult& operator<<(const T& value) { | |
| 85 | std::ostringstream oss; | |
| 86 | oss.precision(16); | |
| 87 | oss.setf(std::ios_base::floatfield); | |
| 88 | oss << value; | |
| 89 | return addToLastFailure(oss.str()); | |
| 90 | } | |
| 91 | ||
| 92 | // Specialized versions. | |
| 93 | TestResult& operator<<(bool value); | |
| 94 | // std:ostream does not support 64bits integers on all STL implementation | |
| 95 | TestResult& operator<<(Json::Int64 value); | |
| 96 | TestResult& operator<<(Json::UInt64 value); | |
| 97 | ||
| 98 | private: | |
| 99 | TestResult& addToLastFailure(const std::string& message); | |
| 100 | unsigned int getAssertionNestingLevel() const; | |
| 101 | /// Adds a failure or a predicate context | |
| 102 | void addFailureInfo(const char* file, | |
| 103 | unsigned int line, | |
| 104 | const char* expr, | |
| 105 | unsigned int nestingLevel); | |
| 106 | static std::string indentText(const std::string& text, | |
| 107 | const std::string& indent); | |
| 108 | ||
| 109 | typedef std::deque<Failure> Failures; | |
| 110 | Failures failures_; | |
| 111 | std::string name_; | |
| 112 | PredicateContext rootPredicateNode_; | |
| 113 | PredicateContext::Id lastUsedPredicateId_; | |
| 114 | /// Failure which is the target of the messages added using operator << | |
| 115 | Failure* messageTarget_; | |
| 116 | }; | |
| 117 | ||
| 118 | class TestCase { | |
| 119 | public: | |
| 120 | TestCase(); | |
| 121 | ||
| 122 | virtual ~TestCase(); | |
| 123 | ||
| 124 | void run(TestResult& result); | |
| 125 | ||
| 126 | virtual const char* testName() const = 0; | |
| 127 | ||
| 128 | protected: | |
| 129 | TestResult* result_; | |
| 130 | ||
| 131 | private: | |
| 132 | virtual void runTestCase() = 0; | |
| 133 | }; | |
| 134 | ||
| 135 | /// Function pointer type for TestCase factory | |
| 136 | typedef TestCase* (*TestCaseFactory)(); | |
| 137 | ||
| 138 | class Runner { | |
| 139 | public: | |
| 140 | Runner(); | |
| 141 | ||
| 142 | /// Adds a test to the suite | |
| 143 | Runner& add(TestCaseFactory factory); | |
| 144 | ||
| 145 | /// Runs test as specified on the command-line | |
| 146 | /// If no command-line arguments are provided, run all tests. | |
| 147 | /// If --list-tests is provided, then print the list of all test cases | |
| 148 | /// If --test <testname> is provided, then run test testname. | |
| 149 | int runCommandLine(int argc, const char* argv[]) const; | |
| 150 | ||
| 151 | /// Runs all the test cases | |
| 152 | bool runAllTest(bool printSummary) const; | |
| 153 | ||
| 154 | /// Returns the number of test case in the suite | |
| 155 | unsigned int testCount() const; | |
| 156 | ||
| 157 | /// Returns the name of the test case at the specified index | |
| 158 | std::string testNameAt(unsigned int index) const; | |
| 159 | ||
| 160 | /// Runs the test case at the specified index using the specified TestResult | |
| 161 | void runTestAt(unsigned int index, TestResult& result) const; | |
| 162 | ||
| 163 | static void printUsage(const char* appName); | |
| 164 | ||
| 165 | private: // prevents copy construction and assignment | |
| 166 | Runner(const Runner& other); | |
| 167 | Runner& operator=(const Runner& other); | |
| 168 | ||
| 169 | private: | |
| 170 | void listTests() const; | |
| 171 | bool testIndex(const std::string& testName, unsigned int& index) const; | |
| 172 | static void preventDialogOnCrash(); | |
| 173 | ||
| 174 | private: | |
| 175 | typedef std::deque<TestCaseFactory> Factories; | |
| 176 | Factories tests_; | |
| 177 | }; | |
| 178 | ||
| 179 | template <typename T, typename U> | |
| 180 | TestResult& checkEqual(TestResult& result, | |
| 181 | const T& expected, | |
| 182 | const U& actual, | |
| 183 | const char* file, | |
| 184 | unsigned int line, | |
| 185 | const char* expr) { | |
| 186 | if (static_cast<U>(expected) != actual) { | |
| 187 | result.addFailure(file, line, expr); | |
| 188 | result << "Expected: " << static_cast<U>(expected) << "\n"; | |
| 189 | result << "Actual : " << actual; | |
| 190 | } | |
| 191 | return result; | |
| 192 | } | |
| 193 | ||
| 194 | TestResult& checkStringEqual(TestResult& result, | |
| 195 | const std::string& expected, | |
| 196 | const std::string& actual, | |
| 197 | const char* file, | |
| 198 | unsigned int line, | |
| 199 | const char* expr); | |
| 200 | ||
| 201 | } // namespace JsonTest | |
| 202 | ||
| 203 | /// \brief Asserts that the given expression is true. | |
| 204 | /// JSONTEST_ASSERT( x == y ) << "x=" << x << ", y=" << y; | |
| 205 | /// JSONTEST_ASSERT( x == y ); | |
| 206 | #define JSONTEST_ASSERT(expr) \ | |
| 207 | if (expr) { \ | |
| 208 | } else \ | |
| 209 | result_->addFailure(__FILE__, __LINE__, #expr) | |
| 210 | ||
| 211 | /// \brief Asserts that the given predicate is true. | |
| 212 | /// The predicate may do other assertions and be a member function of the | |
| 213 | /// fixture. | |
| 214 | #define JSONTEST_ASSERT_PRED(expr) \ | |
| 215 | { \ | |
| 216 | JsonTest::PredicateContext _minitest_Context = { \ | |
| 217 | result_->predicateId_, __FILE__, __LINE__, #expr \ | |
| 218 | }; \ | |
| 219 | result_->predicateStackTail_->next_ = &_minitest_Context; \ | |
| 220 | result_->predicateId_ += 1; \ | |
| 221 | result_->predicateStackTail_ = &_minitest_Context; \ | |
| 222 | (expr); \ | |
| 223 | result_->popPredicateContext(); \ | |
| 224 | } | |
| 225 | ||
| 226 | /// \brief Asserts that two values are equals. | |
| 227 | #define JSONTEST_ASSERT_EQUAL(expected, actual) \ | |
| 228 | JsonTest::checkEqual(*result_, \ | |
| 229 | expected, \ | |
| 230 | actual, \ | |
| 231 | __FILE__, \ | |
| 232 | __LINE__, \ | |
| 233 | #expected " == " #actual) | |
| 234 | ||
| 235 | /// \brief Asserts that two values are equals. | |
| 236 | #define JSONTEST_ASSERT_STRING_EQUAL(expected, actual) \ | |
| 237 | JsonTest::checkStringEqual(*result_, \ | |
| 238 | std::string(expected), \ | |
| 239 | std::string(actual), \ | |
| 240 | __FILE__, \ | |
| 241 | __LINE__, \ | |
| 242 | #expected " == " #actual) | |
| 243 | ||
| 244 | /// \brief Asserts that a given expression throws an exception | |
| 245 | #define JSONTEST_ASSERT_THROWS(expr) \ | |
| 246 | { \ | |
| 247 | bool _threw = false; \ | |
| 248 | try { \ | |
| 249 | expr; \ | |
| 250 | } \ | |
| 251 | catch (...) { \ | |
| 252 | _threw = true; \ | |
| 253 | } \ | |
| 254 | if (!_threw) \ | |
| 255 | result_->addFailure( \ | |
| 256 | __FILE__, __LINE__, "expected exception thrown: " #expr); \ | |
| 257 | } | |
| 258 | ||
| 259 | /// \brief Begin a fixture test case. | |
| 260 | #define JSONTEST_FIXTURE(FixtureType, name) \ | |
| 261 | class Test##FixtureType##name : public FixtureType { \ | |
| 262 | public: \ | |
| 263 | static JsonTest::TestCase* factory() { \ | |
| 264 | return new Test##FixtureType##name(); \ | |
| 265 | } \ | |
| 266 | \ | |
| 267 | public: /* overidden from TestCase */ \ | |
| 268 | virtual const char* testName() const { return #FixtureType "/" #name; } \ | |
| 269 | virtual void runTestCase(); \ | |
| 270 | }; \ | |
| 271 | \ | |
| 272 | void Test##FixtureType##name::runTestCase() | |
| 273 | ||
| 274 | #define JSONTEST_FIXTURE_FACTORY(FixtureType, name) \ | |
| 275 | &Test##FixtureType##name::factory | |
| 276 | ||
| 277 | #define JSONTEST_REGISTER_FIXTURE(runner, FixtureType, name) \ | |
| 278 | (runner).add(JSONTEST_FIXTURE_FACTORY(FixtureType, name)) | |
| 279 | ||
| 280 | #endif // ifndef JSONTEST_H_INCLUDED |
| r0 | r242831 | |
|---|---|---|
| 1 | // Copyright 2007-2010 Baptiste Lepilleur | |
| 2 | // Distributed under MIT license, or public domain if desired and | |
| 3 | // recognized in your jurisdiction. | |
| 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE | |
| 5 | ||
| 6 | #include "jsontest.h" | |
| 7 | #include <json/config.h> | |
| 8 | #include <json/json.h> | |
| 9 | #include <stdexcept> | |
| 10 | ||
| 11 | // Make numeric limits more convenient to talk about. | |
| 12 | // Assumes int type in 32 bits. | |
| 13 | #define kint32max Json::Value::maxInt | |
| 14 | #define kint32min Json::Value::minInt | |
| 15 | #define kuint32max Json::Value::maxUInt | |
| 16 | #define kint64max Json::Value::maxInt64 | |
| 17 | #define kint64min Json::Value::minInt64 | |
| 18 | #define kuint64max Json::Value::maxUInt64 | |
| 19 | ||
| 20 | static const double kdint64max = double(kint64max); | |
| 21 | static const float kfint64max = float(kint64max); | |
| 22 | static const float kfint32max = float(kint32max); | |
| 23 | static const float kfuint32max = float(kuint32max); | |
| 24 | ||
| 25 | // ////////////////////////////////////////////////////////////////// | |
| 26 | // ////////////////////////////////////////////////////////////////// | |
| 27 | // Json Library test cases | |
| 28 | // ////////////////////////////////////////////////////////////////// | |
| 29 | // ////////////////////////////////////////////////////////////////// | |
| 30 | ||
| 31 | #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) | |
| 32 | static inline double uint64ToDouble(Json::UInt64 value) { | |
| 33 | return static_cast<double>(value); | |
| 34 | } | |
| 35 | #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) | |
| 36 | static inline double uint64ToDouble(Json::UInt64 value) { | |
| 37 | return static_cast<double>(Json::Int64(value / 2)) * 2.0 + | |
| 38 | Json::Int64(value & 1); | |
| 39 | } | |
| 40 | #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) | |
| 41 | ||
| 42 | struct ValueTest : JsonTest::TestCase { | |
| 43 | Json::Value null_; | |
| 44 | Json::Value emptyArray_; | |
| 45 | Json::Value emptyObject_; | |
| 46 | Json::Value integer_; | |
| 47 | Json::Value unsignedInteger_; | |
| 48 | Json::Value smallUnsignedInteger_; | |
| 49 | Json::Value real_; | |
| 50 | Json::Value float_; | |
| 51 | Json::Value array1_; | |
| 52 | Json::Value object1_; | |
| 53 | Json::Value emptyString_; | |
| 54 | Json::Value string1_; | |
| 55 | Json::Value string_; | |
| 56 | Json::Value true_; | |
| 57 | Json::Value false_; | |
| 58 | ||
| 59 | ValueTest() | |
| 60 | : emptyArray_(Json::arrayValue), emptyObject_(Json::objectValue), | |
| 61 | integer_(123456789), unsignedInteger_(34567890u), | |
| 62 | smallUnsignedInteger_(Json::Value::UInt(Json::Value::maxInt)), | |
| 63 | real_(1234.56789), float_(0.00390625f), emptyString_(""), string1_("a"), | |
| 64 | string_("sometext with space"), true_(true), false_(false) { | |
| 65 | array1_.append(1234); | |
| 66 | object1_["id"] = 1234; | |
| 67 | } | |
| 68 | ||
| 69 | struct IsCheck { | |
| 70 | /// Initialize all checks to \c false by default. | |
| 71 | IsCheck(); | |
| 72 | ||
| 73 | bool isObject_; | |
| 74 | bool isArray_; | |
| 75 | bool isBool_; | |
| 76 | bool isString_; | |
| 77 | bool isNull_; | |
| 78 | ||
| 79 | bool isInt_; | |
| 80 | bool isInt64_; | |
| 81 | bool isUInt_; | |
| 82 | bool isUInt64_; | |
| 83 | bool isIntegral_; | |
| 84 | bool isDouble_; | |
| 85 | bool isNumeric_; | |
| 86 | }; | |
| 87 | ||
| 88 | void checkConstMemberCount(const Json::Value& value, | |
| 89 | unsigned int expectedCount); | |
| 90 | ||
| 91 | void checkMemberCount(Json::Value& value, unsigned int expectedCount); | |
| 92 | ||
| 93 | void checkIs(const Json::Value& value, const IsCheck& check); | |
| 94 | ||
| 95 | void checkIsLess(const Json::Value& x, const Json::Value& y); | |
| 96 | ||
| 97 | void checkIsEqual(const Json::Value& x, const Json::Value& y); | |
| 98 | ||
| 99 | /// Normalize the representation of floating-point number by stripped leading | |
| 100 | /// 0 in exponent. | |
| 101 | static std::string normalizeFloatingPointStr(const std::string& s); | |
| 102 | }; | |
| 103 | ||
| 104 | std::string ValueTest::normalizeFloatingPointStr(const std::string& s) { | |
| 105 | std::string::size_type index = s.find_last_of("eE"); | |
| 106 | if (index != std::string::npos) { | |
| 107 | std::string::size_type hasSign = | |
| 108 | (s[index + 1] == '+' || s[index + 1] == '-') ? 1 : 0; | |
| 109 | std::string::size_type exponentStartIndex = index + 1 + hasSign; | |
| 110 | std::string normalized = s.substr(0, exponentStartIndex); | |
| 111 | std::string::size_type indexDigit = | |
| 112 | s.find_first_not_of('0', exponentStartIndex); | |
| 113 | std::string exponent = "0"; | |
| 114 | if (indexDigit != | |
| 115 | std::string::npos) // There is an exponent different from 0 | |
| 116 | { | |
| 117 | exponent = s.substr(indexDigit); | |
| 118 | } | |
| 119 | return normalized + exponent; | |
| 120 | } | |
| 121 | return s; | |
| 122 | } | |
| 123 | ||
| 124 | JSONTEST_FIXTURE(ValueTest, checkNormalizeFloatingPointStr) { | |
| 125 | JSONTEST_ASSERT_STRING_EQUAL("0.0", normalizeFloatingPointStr("0.0")); | |
| 126 | JSONTEST_ASSERT_STRING_EQUAL("0e0", normalizeFloatingPointStr("0e0")); | |
| 127 | JSONTEST_ASSERT_STRING_EQUAL("1234.0", normalizeFloatingPointStr("1234.0")); | |
| 128 | JSONTEST_ASSERT_STRING_EQUAL("1234.0e0", | |
| 129 | normalizeFloatingPointStr("1234.0e0")); | |
| 130 | JSONTEST_ASSERT_STRING_EQUAL("1234.0e+0", | |
| 131 | normalizeFloatingPointStr("1234.0e+0")); | |
| 132 | JSONTEST_ASSERT_STRING_EQUAL("1234e-1", normalizeFloatingPointStr("1234e-1")); | |
| 133 | JSONTEST_ASSERT_STRING_EQUAL("1234e10", normalizeFloatingPointStr("1234e10")); | |
| 134 | JSONTEST_ASSERT_STRING_EQUAL("1234e10", | |
| 135 | normalizeFloatingPointStr("1234e010")); | |
| 136 | JSONTEST_ASSERT_STRING_EQUAL("1234e+10", | |
| 137 | normalizeFloatingPointStr("1234e+010")); | |
| 138 | JSONTEST_ASSERT_STRING_EQUAL("1234e-10", | |
| 139 | normalizeFloatingPointStr("1234e-010")); | |
| 140 | JSONTEST_ASSERT_STRING_EQUAL("1234e+100", | |
| 141 | normalizeFloatingPointStr("1234e+100")); | |
| 142 | JSONTEST_ASSERT_STRING_EQUAL("1234e-100", | |
| 143 | normalizeFloatingPointStr("1234e-100")); | |
| 144 | JSONTEST_ASSERT_STRING_EQUAL("1234e+1", | |
| 145 | normalizeFloatingPointStr("1234e+001")); | |
| 146 | } | |
| 147 | ||
| 148 | JSONTEST_FIXTURE(ValueTest, memberCount) { | |
| 149 | JSONTEST_ASSERT_PRED(checkMemberCount(emptyArray_, 0)); | |
| 150 | JSONTEST_ASSERT_PRED(checkMemberCount(emptyObject_, 0)); | |
| 151 | JSONTEST_ASSERT_PRED(checkMemberCount(array1_, 1)); | |
| 152 | JSONTEST_ASSERT_PRED(checkMemberCount(object1_, 1)); | |
| 153 | JSONTEST_ASSERT_PRED(checkMemberCount(null_, 0)); | |
| 154 | JSONTEST_ASSERT_PRED(checkMemberCount(integer_, 0)); | |
| 155 | JSONTEST_ASSERT_PRED(checkMemberCount(unsignedInteger_, 0)); | |
| 156 | JSONTEST_ASSERT_PRED(checkMemberCount(smallUnsignedInteger_, 0)); | |
| 157 | JSONTEST_ASSERT_PRED(checkMemberCount(real_, 0)); | |
| 158 | JSONTEST_ASSERT_PRED(checkMemberCount(emptyString_, 0)); | |
| 159 | JSONTEST_ASSERT_PRED(checkMemberCount(string_, 0)); | |
| 160 | JSONTEST_ASSERT_PRED(checkMemberCount(true_, 0)); | |
| 161 | } | |
| 162 | ||
| 163 | JSONTEST_FIXTURE(ValueTest, objects) { | |
| 164 | // Types | |
| 165 | IsCheck checks; | |
| 166 | checks.isObject_ = true; | |
| 167 | JSONTEST_ASSERT_PRED(checkIs(emptyObject_, checks)); | |
| 168 | JSONTEST_ASSERT_PRED(checkIs(object1_, checks)); | |
| 169 | ||
| 170 | JSONTEST_ASSERT_EQUAL(Json::objectValue, emptyObject_.type()); | |
| 171 | ||
| 172 | // Empty object okay | |
| 173 | JSONTEST_ASSERT(emptyObject_.isConvertibleTo(Json::nullValue)); | |
| 174 | ||
| 175 | // Non-empty object not okay | |
| 176 | JSONTEST_ASSERT(!object1_.isConvertibleTo(Json::nullValue)); | |
| 177 | ||
| 178 | // Always okay | |
| 179 | JSONTEST_ASSERT(emptyObject_.isConvertibleTo(Json::objectValue)); | |
| 180 | ||
| 181 | // Never okay | |
| 182 | JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::arrayValue)); | |
| 183 | JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::intValue)); | |
| 184 | JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::uintValue)); | |
| 185 | JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::realValue)); | |
| 186 | JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::booleanValue)); | |
| 187 | JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::stringValue)); | |
| 188 | ||
| 189 | // Access through const reference | |
| 190 | const Json::Value& constObject = object1_; | |
| 191 | ||
| 192 | JSONTEST_ASSERT_EQUAL(Json::Value(1234), constObject["id"]); | |
| 193 | JSONTEST_ASSERT_EQUAL(Json::Value(), constObject["unknown id"]); | |
| 194 | ||
| 195 | // Access through non-const reference | |
| 196 | JSONTEST_ASSERT_EQUAL(Json::Value(1234), object1_["id"]); | |
| 197 | JSONTEST_ASSERT_EQUAL(Json::Value(), object1_["unknown id"]); | |
| 198 | ||
| 199 | object1_["some other id"] = "foo"; | |
| 200 | JSONTEST_ASSERT_EQUAL(Json::Value("foo"), object1_["some other id"]); | |
| 201 | } | |
| 202 | ||
| 203 | JSONTEST_FIXTURE(ValueTest, arrays) { | |
| 204 | const unsigned int index0 = 0; | |
| 205 | ||
| 206 | // Types | |
| 207 | IsCheck checks; | |
| 208 | checks.isArray_ = true; | |
| 209 | JSONTEST_ASSERT_PRED(checkIs(emptyArray_, checks)); | |
| 210 | JSONTEST_ASSERT_PRED(checkIs(array1_, checks)); | |
| 211 | ||
| 212 | JSONTEST_ASSERT_EQUAL(Json::arrayValue, array1_.type()); | |
| 213 | ||
| 214 | // Empty array okay | |
| 215 | JSONTEST_ASSERT(emptyArray_.isConvertibleTo(Json::nullValue)); | |
| 216 | ||
| 217 | // Non-empty array not okay | |
| 218 | JSONTEST_ASSERT(!array1_.isConvertibleTo(Json::nullValue)); | |
| 219 | ||
| 220 | // Always okay | |
| 221 | JSONTEST_ASSERT(emptyArray_.isConvertibleTo(Json::arrayValue)); | |
| 222 | ||
| 223 | // Never okay | |
| 224 | JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::objectValue)); | |
| 225 | JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::intValue)); | |
| 226 | JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::uintValue)); | |
| 227 | JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::realValue)); | |
| 228 | JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::booleanValue)); | |
| 229 | JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::stringValue)); | |
| 230 | ||
| 231 | // Access through const reference | |
| 232 | const Json::Value& constArray = array1_; | |
| 233 | JSONTEST_ASSERT_EQUAL(Json::Value(1234), constArray[index0]); | |
| 234 | JSONTEST_ASSERT_EQUAL(Json::Value(1234), constArray[0]); | |
| 235 | ||
| 236 | // Access through non-const reference | |
| 237 | JSONTEST_ASSERT_EQUAL(Json::Value(1234), array1_[index0]); | |
| 238 | JSONTEST_ASSERT_EQUAL(Json::Value(1234), array1_[0]); | |
| 239 | ||
| 240 | array1_[2] = Json::Value(17); | |
| 241 | JSONTEST_ASSERT_EQUAL(Json::Value(), array1_[1]); | |
| 242 | JSONTEST_ASSERT_EQUAL(Json::Value(17), array1_[2]); | |
| 243 | } | |
| 244 | ||
| 245 | JSONTEST_FIXTURE(ValueTest, null) { | |
| 246 | JSONTEST_ASSERT_EQUAL(Json::nullValue, null_.type()); | |
| 247 | ||
| 248 | IsCheck checks; | |
| 249 | checks.isNull_ = true; | |
| 250 | JSONTEST_ASSERT_PRED(checkIs(null_, checks)); | |
| 251 | ||
| 252 | JSONTEST_ASSERT(null_.isConvertibleTo(Json::nullValue)); | |
| 253 | JSONTEST_ASSERT(null_.isConvertibleTo(Json::intValue)); | |
| 254 | JSONTEST_ASSERT(null_.isConvertibleTo(Json::uintValue)); | |
| 255 | JSONTEST_ASSERT(null_.isConvertibleTo(Json::realValue)); | |
| 256 | JSONTEST_ASSERT(null_.isConvertibleTo(Json::booleanValue)); | |
| 257 | JSONTEST_ASSERT(null_.isConvertibleTo(Json::stringValue)); | |
| 258 | JSONTEST_ASSERT(null_.isConvertibleTo(Json::arrayValue)); | |
| 259 | JSONTEST_ASSERT(null_.isConvertibleTo(Json::objectValue)); | |
| 260 | ||
| 261 | JSONTEST_ASSERT_EQUAL(Json::Int(0), null_.asInt()); | |
| 262 | JSONTEST_ASSERT_EQUAL(Json::LargestInt(0), null_.asLargestInt()); | |
| 263 | JSONTEST_ASSERT_EQUAL(Json::UInt(0), null_.asUInt()); | |
| 264 | JSONTEST_ASSERT_EQUAL(Json::LargestUInt(0), null_.asLargestUInt()); | |
| 265 | JSONTEST_ASSERT_EQUAL(0.0, null_.asDouble()); | |
| 266 | JSONTEST_ASSERT_EQUAL(0.0, null_.asFloat()); | |
| 267 | JSONTEST_ASSERT_STRING_EQUAL("", null_.asString()); | |
| 268 | } | |
| 269 | ||
| 270 | JSONTEST_FIXTURE(ValueTest, strings) { | |
| 271 | JSONTEST_ASSERT_EQUAL(Json::stringValue, string1_.type()); | |
| 272 | ||
| 273 | IsCheck checks; | |
| 274 | checks.isString_ = true; | |
| 275 | JSONTEST_ASSERT_PRED(checkIs(emptyString_, checks)); | |
| 276 | JSONTEST_ASSERT_PRED(checkIs(string_, checks)); | |
| 277 | JSONTEST_ASSERT_PRED(checkIs(string1_, checks)); | |
| 278 | ||
| 279 | // Empty string okay | |
| 280 | JSONTEST_ASSERT(emptyString_.isConvertibleTo(Json::nullValue)); | |
| 281 | ||
| 282 | // Non-empty string not okay | |
| 283 | JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::nullValue)); | |
| 284 | ||
| 285 | // Always okay | |
| 286 | JSONTEST_ASSERT(string1_.isConvertibleTo(Json::stringValue)); | |
| 287 | ||
| 288 | // Never okay | |
| 289 | JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::objectValue)); | |
| 290 | JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::arrayValue)); | |
| 291 | JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::intValue)); | |
| 292 | JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::uintValue)); | |
| 293 | JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::realValue)); | |
| 294 | ||
| 295 | JSONTEST_ASSERT_STRING_EQUAL("a", string1_.asString()); | |
| 296 | JSONTEST_ASSERT_STRING_EQUAL("a", string1_.asCString()); | |
| 297 | } | |
| 298 | ||
| 299 | JSONTEST_FIXTURE(ValueTest, bools) { | |
| 300 | JSONTEST_ASSERT_EQUAL(Json::booleanValue, false_.type()); | |
| 301 | ||
| 302 | IsCheck checks; | |
| 303 | checks.isBool_ = true; | |
| 304 | JSONTEST_ASSERT_PRED(checkIs(false_, checks)); | |
| 305 | JSONTEST_ASSERT_PRED(checkIs(true_, checks)); | |
| 306 | ||
| 307 | // False okay | |
| 308 | JSONTEST_ASSERT(false_.isConvertibleTo(Json::nullValue)); | |
| 309 | ||
| 310 | // True not okay | |
| 311 | JSONTEST_ASSERT(!true_.isConvertibleTo(Json::nullValue)); | |
| 312 | ||
| 313 | // Always okay | |
| 314 | JSONTEST_ASSERT(true_.isConvertibleTo(Json::intValue)); | |
| 315 | JSONTEST_ASSERT(true_.isConvertibleTo(Json::uintValue)); | |
| 316 | JSONTEST_ASSERT(true_.isConvertibleTo(Json::realValue)); | |
| 317 | JSONTEST_ASSERT(true_.isConvertibleTo(Json::booleanValue)); | |
| 318 | JSONTEST_ASSERT(true_.isConvertibleTo(Json::stringValue)); | |
| 319 | ||
| 320 | // Never okay | |
| 321 | JSONTEST_ASSERT(!true_.isConvertibleTo(Json::arrayValue)); | |
| 322 | JSONTEST_ASSERT(!true_.isConvertibleTo(Json::objectValue)); | |
| 323 | ||
| 324 | JSONTEST_ASSERT_EQUAL(true, true_.asBool()); | |
| 325 | JSONTEST_ASSERT_EQUAL(1, true_.asInt()); | |
| 326 | JSONTEST_ASSERT_EQUAL(1, true_.asLargestInt()); | |
| 327 | JSONTEST_ASSERT_EQUAL(1, true_.asUInt()); | |
| 328 | JSONTEST_ASSERT_EQUAL(1, true_.asLargestUInt()); | |
| 329 | JSONTEST_ASSERT_EQUAL(1.0, true_.asDouble()); | |
| 330 | JSONTEST_ASSERT_EQUAL(1.0, true_.asFloat()); | |
| 331 | ||
| 332 | JSONTEST_ASSERT_EQUAL(false, false_.asBool()); | |
| 333 | JSONTEST_ASSERT_EQUAL(0, false_.asInt()); | |
| 334 | JSONTEST_ASSERT_EQUAL(0, false_.asLargestInt()); | |
| 335 | JSONTEST_ASSERT_EQUAL(0, false_.asUInt()); | |
| 336 | JSONTEST_ASSERT_EQUAL(0, false_.asLargestUInt()); | |
| 337 | JSONTEST_ASSERT_EQUAL(0.0, false_.asDouble()); | |
| 338 | JSONTEST_ASSERT_EQUAL(0.0, false_.asFloat()); | |
| 339 | } | |
| 340 | ||
| 341 | JSONTEST_FIXTURE(ValueTest, integers) { | |
| 342 | IsCheck checks; | |
| 343 | Json::Value val; | |
| 344 | ||
| 345 | // Conversions that don't depend on the value. | |
| 346 | JSONTEST_ASSERT(Json::Value(17).isConvertibleTo(Json::realValue)); | |
| 347 | JSONTEST_ASSERT(Json::Value(17).isConvertibleTo(Json::stringValue)); | |
| 348 | JSONTEST_ASSERT(Json::Value(17).isConvertibleTo(Json::booleanValue)); | |
| 349 | JSONTEST_ASSERT(!Json::Value(17).isConvertibleTo(Json::arrayValue)); | |
| 350 | JSONTEST_ASSERT(!Json::Value(17).isConvertibleTo(Json::objectValue)); | |
| 351 | ||
| 352 | JSONTEST_ASSERT(Json::Value(17U).isConvertibleTo(Json::realValue)); | |
| 353 | JSONTEST_ASSERT(Json::Value(17U).isConvertibleTo(Json::stringValue)); | |
| 354 | JSONTEST_ASSERT(Json::Value(17U).isConvertibleTo(Json::booleanValue)); | |
| 355 | JSONTEST_ASSERT(!Json::Value(17U).isConvertibleTo(Json::arrayValue)); | |
| 356 | JSONTEST_ASSERT(!Json::Value(17U).isConvertibleTo(Json::objectValue)); | |
| 357 | ||
| 358 | JSONTEST_ASSERT(Json::Value(17.0).isConvertibleTo(Json::realValue)); | |
| 359 | JSONTEST_ASSERT(Json::Value(17.0).isConvertibleTo(Json::stringValue)); | |
| 360 | JSONTEST_ASSERT(Json::Value(17.0).isConvertibleTo(Json::booleanValue)); | |
| 361 | JSONTEST_ASSERT(!Json::Value(17.0).isConvertibleTo(Json::arrayValue)); | |
| 362 | JSONTEST_ASSERT(!Json::Value(17.0).isConvertibleTo(Json::objectValue)); | |
| 363 | ||
| 364 | // Default int | |
| 365 | val = Json::Value(Json::intValue); | |
| 366 | ||
| 367 | JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); | |
| 368 | ||
| 369 | checks = IsCheck(); | |
| 370 | checks.isInt_ = true; | |
| 371 | checks.isInt64_ = true; | |
| 372 | checks.isUInt_ = true; | |
| 373 | checks.isUInt64_ = true; | |
| 374 | checks.isIntegral_ = true; | |
| 375 | checks.isDouble_ = true; | |
| 376 | checks.isNumeric_ = true; | |
| 377 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 378 | ||
| 379 | JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue)); | |
| 380 | JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); | |
| 381 | JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); | |
| 382 | ||
| 383 | JSONTEST_ASSERT_EQUAL(0, val.asInt()); | |
| 384 | JSONTEST_ASSERT_EQUAL(0, val.asLargestInt()); | |
| 385 | JSONTEST_ASSERT_EQUAL(0, val.asUInt()); | |
| 386 | JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt()); | |
| 387 | JSONTEST_ASSERT_EQUAL(0.0, val.asDouble()); | |
| 388 | JSONTEST_ASSERT_EQUAL(0.0, val.asFloat()); | |
| 389 | JSONTEST_ASSERT_EQUAL(false, val.asBool()); | |
| 390 | JSONTEST_ASSERT_STRING_EQUAL("0", val.asString()); | |
| 391 | ||
| 392 | // Default uint | |
| 393 | val = Json::Value(Json::uintValue); | |
| 394 | ||
| 395 | JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type()); | |
| 396 | ||
| 397 | checks = IsCheck(); | |
| 398 | checks.isInt_ = true; | |
| 399 | checks.isInt64_ = true; | |
| 400 | checks.isUInt_ = true; | |
| 401 | checks.isUInt64_ = true; | |
| 402 | checks.isIntegral_ = true; | |
| 403 | checks.isDouble_ = true; | |
| 404 | checks.isNumeric_ = true; | |
| 405 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 406 | ||
| 407 | JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue)); | |
| 408 | JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); | |
| 409 | JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); | |
| 410 | ||
| 411 | JSONTEST_ASSERT_EQUAL(0, val.asInt()); | |
| 412 | JSONTEST_ASSERT_EQUAL(0, val.asLargestInt()); | |
| 413 | JSONTEST_ASSERT_EQUAL(0, val.asUInt()); | |
| 414 | JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt()); | |
| 415 | JSONTEST_ASSERT_EQUAL(0.0, val.asDouble()); | |
| 416 | JSONTEST_ASSERT_EQUAL(0.0, val.asFloat()); | |
| 417 | JSONTEST_ASSERT_EQUAL(false, val.asBool()); | |
| 418 | JSONTEST_ASSERT_STRING_EQUAL("0", val.asString()); | |
| 419 | ||
| 420 | // Default real | |
| 421 | val = Json::Value(Json::realValue); | |
| 422 | ||
| 423 | JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); | |
| 424 | ||
| 425 | JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue)); | |
| 426 | JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); | |
| 427 | JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); | |
| 428 | ||
| 429 | checks = IsCheck(); | |
| 430 | checks.isInt_ = true; | |
| 431 | checks.isInt64_ = true; | |
| 432 | checks.isUInt_ = true; | |
| 433 | checks.isUInt64_ = true; | |
| 434 | checks.isIntegral_ = true; | |
| 435 | checks.isDouble_ = true; | |
| 436 | checks.isNumeric_ = true; | |
| 437 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 438 | ||
| 439 | JSONTEST_ASSERT_EQUAL(0, val.asInt()); | |
| 440 | JSONTEST_ASSERT_EQUAL(0, val.asLargestInt()); | |
| 441 | JSONTEST_ASSERT_EQUAL(0, val.asUInt()); | |
| 442 | JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt()); | |
| 443 | JSONTEST_ASSERT_EQUAL(0.0, val.asDouble()); | |
| 444 | JSONTEST_ASSERT_EQUAL(0.0, val.asFloat()); | |
| 445 | JSONTEST_ASSERT_EQUAL(false, val.asBool()); | |
| 446 | JSONTEST_ASSERT_STRING_EQUAL("0", val.asString()); | |
| 447 | ||
| 448 | // Zero (signed constructor arg) | |
| 449 | val = Json::Value(0); | |
| 450 | ||
| 451 | JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); | |
| 452 | ||
| 453 | checks = IsCheck(); | |
| 454 | checks.isInt_ = true; | |
| 455 | checks.isInt64_ = true; | |
| 456 | checks.isUInt_ = true; | |
| 457 | checks.isUInt64_ = true; | |
| 458 | checks.isIntegral_ = true; | |
| 459 | checks.isDouble_ = true; | |
| 460 | checks.isNumeric_ = true; | |
| 461 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 462 | ||
| 463 | JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue)); | |
| 464 | JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); | |
| 465 | JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); | |
| 466 | ||
| 467 | JSONTEST_ASSERT_EQUAL(0, val.asInt()); | |
| 468 | JSONTEST_ASSERT_EQUAL(0, val.asLargestInt()); | |
| 469 | JSONTEST_ASSERT_EQUAL(0, val.asUInt()); | |
| 470 | JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt()); | |
| 471 | JSONTEST_ASSERT_EQUAL(0.0, val.asDouble()); | |
| 472 | JSONTEST_ASSERT_EQUAL(0.0, val.asFloat()); | |
| 473 | JSONTEST_ASSERT_EQUAL(false, val.asBool()); | |
| 474 | JSONTEST_ASSERT_STRING_EQUAL("0", val.asString()); | |
| 475 | ||
| 476 | // Zero (unsigned constructor arg) | |
| 477 | val = Json::Value(0u); | |
| 478 | ||
| 479 | JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type()); | |
| 480 | ||
| 481 | checks = IsCheck(); | |
| 482 | checks.isInt_ = true; | |
| 483 | checks.isInt64_ = true; | |
| 484 | checks.isUInt_ = true; | |
| 485 | checks.isUInt64_ = true; | |
| 486 | checks.isIntegral_ = true; | |
| 487 | checks.isDouble_ = true; | |
| 488 | checks.isNumeric_ = true; | |
| 489 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 490 | ||
| 491 | JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue)); | |
| 492 | JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); | |
| 493 | JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); | |
| 494 | ||
| 495 | JSONTEST_ASSERT_EQUAL(0, val.asInt()); | |
| 496 | JSONTEST_ASSERT_EQUAL(0, val.asLargestInt()); | |
| 497 | JSONTEST_ASSERT_EQUAL(0, val.asUInt()); | |
| 498 | JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt()); | |
| 499 | JSONTEST_ASSERT_EQUAL(0.0, val.asDouble()); | |
| 500 | JSONTEST_ASSERT_EQUAL(0.0, val.asFloat()); | |
| 501 | JSONTEST_ASSERT_EQUAL(false, val.asBool()); | |
| 502 | JSONTEST_ASSERT_STRING_EQUAL("0", val.asString()); | |
| 503 | ||
| 504 | // Zero (floating-point constructor arg) | |
| 505 | val = Json::Value(0.0); | |
| 506 | ||
| 507 | JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); | |
| 508 | ||
| 509 | checks = IsCheck(); | |
| 510 | checks.isInt_ = true; | |
| 511 | checks.isInt64_ = true; | |
| 512 | checks.isUInt_ = true; | |
| 513 | checks.isUInt64_ = true; | |
| 514 | checks.isIntegral_ = true; | |
| 515 | checks.isDouble_ = true; | |
| 516 | checks.isNumeric_ = true; | |
| 517 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 518 | ||
| 519 | JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue)); | |
| 520 | JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); | |
| 521 | JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); | |
| 522 | ||
| 523 | JSONTEST_ASSERT_EQUAL(0, val.asInt()); | |
| 524 | JSONTEST_ASSERT_EQUAL(0, val.asLargestInt()); | |
| 525 | JSONTEST_ASSERT_EQUAL(0, val.asUInt()); | |
| 526 | JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt()); | |
| 527 | JSONTEST_ASSERT_EQUAL(0.0, val.asDouble()); | |
| 528 | JSONTEST_ASSERT_EQUAL(0.0, val.asFloat()); | |
| 529 | JSONTEST_ASSERT_EQUAL(false, val.asBool()); | |
| 530 | JSONTEST_ASSERT_STRING_EQUAL("0", val.asString()); | |
| 531 | ||
| 532 | // 2^20 (signed constructor arg) | |
| 533 | val = Json::Value(1 << 20); | |
| 534 | ||
| 535 | JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); | |
| 536 | checks = IsCheck(); | |
| 537 | checks.isInt_ = true; | |
| 538 | checks.isInt64_ = true; | |
| 539 | checks.isUInt_ = true; | |
| 540 | checks.isUInt64_ = true; | |
| 541 | checks.isIntegral_ = true; | |
| 542 | checks.isDouble_ = true; | |
| 543 | checks.isNumeric_ = true; | |
| 544 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 545 | ||
| 546 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); | |
| 547 | JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); | |
| 548 | JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); | |
| 549 | ||
| 550 | JSONTEST_ASSERT_EQUAL((1 << 20), val.asInt()); | |
| 551 | JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestInt()); | |
| 552 | JSONTEST_ASSERT_EQUAL((1 << 20), val.asUInt()); | |
| 553 | JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestUInt()); | |
| 554 | JSONTEST_ASSERT_EQUAL((1 << 20), val.asDouble()); | |
| 555 | JSONTEST_ASSERT_EQUAL((1 << 20), val.asFloat()); | |
| 556 | JSONTEST_ASSERT_EQUAL(true, val.asBool()); | |
| 557 | JSONTEST_ASSERT_STRING_EQUAL("1048576", val.asString()); | |
| 558 | ||
| 559 | // 2^20 (unsigned constructor arg) | |
| 560 | val = Json::Value(Json::UInt(1 << 20)); | |
| 561 | ||
| 562 | JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type()); | |
| 563 | ||
| 564 | checks = IsCheck(); | |
| 565 | checks.isInt_ = true; | |
| 566 | checks.isInt64_ = true; | |
| 567 | checks.isUInt_ = true; | |
| 568 | checks.isUInt64_ = true; | |
| 569 | checks.isIntegral_ = true; | |
| 570 | checks.isDouble_ = true; | |
| 571 | checks.isNumeric_ = true; | |
| 572 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 573 | ||
| 574 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); | |
| 575 | JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); | |
| 576 | JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); | |
| 577 | ||
| 578 | JSONTEST_ASSERT_EQUAL((1 << 20), val.asInt()); | |
| 579 | JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestInt()); | |
| 580 | JSONTEST_ASSERT_EQUAL((1 << 20), val.asUInt()); | |
| 581 | JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestUInt()); | |
| 582 | JSONTEST_ASSERT_EQUAL((1 << 20), val.asDouble()); | |
| 583 | JSONTEST_ASSERT_EQUAL((1 << 20), val.asFloat()); | |
| 584 | JSONTEST_ASSERT_EQUAL(true, val.asBool()); | |
| 585 | JSONTEST_ASSERT_STRING_EQUAL("1048576", val.asString()); | |
| 586 | ||
| 587 | // 2^20 (floating-point constructor arg) | |
| 588 | val = Json::Value((1 << 20) / 1.0); | |
| 589 | ||
| 590 | JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); | |
| 591 | ||
| 592 | checks = IsCheck(); | |
| 593 | checks.isInt_ = true; | |
| 594 | checks.isInt64_ = true; | |
| 595 | checks.isUInt_ = true; | |
| 596 | checks.isUInt64_ = true; | |
| 597 | checks.isIntegral_ = true; | |
| 598 | checks.isDouble_ = true; | |
| 599 | checks.isNumeric_ = true; | |
| 600 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 601 | ||
| 602 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); | |
| 603 | JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); | |
| 604 | JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); | |
| 605 | ||
| 606 | JSONTEST_ASSERT_EQUAL((1 << 20), val.asInt()); | |
| 607 | JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestInt()); | |
| 608 | JSONTEST_ASSERT_EQUAL((1 << 20), val.asUInt()); | |
| 609 | JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestUInt()); | |
| 610 | JSONTEST_ASSERT_EQUAL((1 << 20), val.asDouble()); | |
| 611 | JSONTEST_ASSERT_EQUAL((1 << 20), val.asFloat()); | |
| 612 | JSONTEST_ASSERT_EQUAL(true, val.asBool()); | |
| 613 | JSONTEST_ASSERT_STRING_EQUAL("1048576", | |
| 614 | normalizeFloatingPointStr(val.asString())); | |
| 615 | ||
| 616 | // -2^20 | |
| 617 | val = Json::Value(-(1 << 20)); | |
| 618 | ||
| 619 | JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); | |
| 620 | ||
| 621 | checks = IsCheck(); | |
| 622 | checks.isInt_ = true; | |
| 623 | checks.isInt64_ = true; | |
| 624 | checks.isIntegral_ = true; | |
| 625 | checks.isDouble_ = true; | |
| 626 | checks.isNumeric_ = true; | |
| 627 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 628 | ||
| 629 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); | |
| 630 | JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); | |
| 631 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); | |
| 632 | ||
| 633 | JSONTEST_ASSERT_EQUAL(-(1 << 20), val.asInt()); | |
| 634 | JSONTEST_ASSERT_EQUAL(-(1 << 20), val.asLargestInt()); | |
| 635 | JSONTEST_ASSERT_EQUAL(-(1 << 20), val.asDouble()); | |
| 636 | JSONTEST_ASSERT_EQUAL(-(1 << 20), val.asFloat()); | |
| 637 | JSONTEST_ASSERT_EQUAL(true, val.asBool()); | |
| 638 | JSONTEST_ASSERT_STRING_EQUAL("-1048576", val.asString()); | |
| 639 | ||
| 640 | // int32 max | |
| 641 | val = Json::Value(kint32max); | |
| 642 | ||
| 643 | JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); | |
| 644 | ||
| 645 | checks = IsCheck(); | |
| 646 | checks.isInt_ = true; | |
| 647 | checks.isInt64_ = true; | |
| 648 | checks.isUInt_ = true; | |
| 649 | checks.isUInt64_ = true; | |
| 650 | checks.isIntegral_ = true; | |
| 651 | checks.isDouble_ = true; | |
| 652 | checks.isNumeric_ = true; | |
| 653 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 654 | ||
| 655 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); | |
| 656 | JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); | |
| 657 | JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); | |
| 658 | ||
| 659 | JSONTEST_ASSERT_EQUAL(kint32max, val.asInt()); | |
| 660 | JSONTEST_ASSERT_EQUAL(kint32max, val.asLargestInt()); | |
| 661 | JSONTEST_ASSERT_EQUAL(kint32max, val.asUInt()); | |
| 662 | JSONTEST_ASSERT_EQUAL(kint32max, val.asLargestUInt()); | |
| 663 | JSONTEST_ASSERT_EQUAL(kint32max, val.asDouble()); | |
| 664 | JSONTEST_ASSERT_EQUAL(kfint32max, val.asFloat()); | |
| 665 | JSONTEST_ASSERT_EQUAL(true, val.asBool()); | |
| 666 | JSONTEST_ASSERT_STRING_EQUAL("2147483647", val.asString()); | |
| 667 | ||
| 668 | // int32 min | |
| 669 | val = Json::Value(kint32min); | |
| 670 | ||
| 671 | JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); | |
| 672 | ||
| 673 | checks = IsCheck(); | |
| 674 | checks.isInt_ = true; | |
| 675 | checks.isInt64_ = true; | |
| 676 | checks.isIntegral_ = true; | |
| 677 | checks.isDouble_ = true; | |
| 678 | checks.isNumeric_ = true; | |
| 679 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 680 | ||
| 681 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); | |
| 682 | JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); | |
| 683 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); | |
| 684 | ||
| 685 | JSONTEST_ASSERT_EQUAL(kint32min, val.asInt()); | |
| 686 | JSONTEST_ASSERT_EQUAL(kint32min, val.asLargestInt()); | |
| 687 | JSONTEST_ASSERT_EQUAL(kint32min, val.asDouble()); | |
| 688 | JSONTEST_ASSERT_EQUAL(kint32min, val.asFloat()); | |
| 689 | JSONTEST_ASSERT_EQUAL(true, val.asBool()); | |
| 690 | JSONTEST_ASSERT_STRING_EQUAL("-2147483648", val.asString()); | |
| 691 | ||
| 692 | // uint32 max | |
| 693 | val = Json::Value(kuint32max); | |
| 694 | ||
| 695 | JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type()); | |
| 696 | ||
| 697 | checks = IsCheck(); | |
| 698 | checks.isInt64_ = true; | |
| 699 | checks.isUInt_ = true; | |
| 700 | checks.isUInt64_ = true; | |
| 701 | checks.isIntegral_ = true; | |
| 702 | checks.isDouble_ = true; | |
| 703 | checks.isNumeric_ = true; | |
| 704 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 705 | ||
| 706 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); | |
| 707 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); | |
| 708 | JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); | |
| 709 | ||
| 710 | #ifndef JSON_NO_INT64 | |
| 711 | JSONTEST_ASSERT_EQUAL(kuint32max, val.asLargestInt()); | |
| 712 | #endif | |
| 713 | JSONTEST_ASSERT_EQUAL(kuint32max, val.asUInt()); | |
| 714 | JSONTEST_ASSERT_EQUAL(kuint32max, val.asLargestUInt()); | |
| 715 | JSONTEST_ASSERT_EQUAL(kuint32max, val.asDouble()); | |
| 716 | JSONTEST_ASSERT_EQUAL(kfuint32max, val.asFloat()); | |
| 717 | JSONTEST_ASSERT_EQUAL(true, val.asBool()); | |
| 718 | JSONTEST_ASSERT_STRING_EQUAL("4294967295", val.asString()); | |
| 719 | ||
| 720 | #ifdef JSON_NO_INT64 | |
| 721 | // int64 max | |
| 722 | val = Json::Value(double(kint64max)); | |
| 723 | ||
| 724 | JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); | |
| 725 | ||
| 726 | checks = IsCheck(); | |
| 727 | checks.isDouble_ = true; | |
| 728 | checks.isNumeric_ = true; | |
| 729 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 730 | ||
| 731 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); | |
| 732 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); | |
| 733 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); | |
| 734 | ||
| 735 | JSONTEST_ASSERT_EQUAL(double(kint64max), val.asDouble()); | |
| 736 | JSONTEST_ASSERT_EQUAL(float(kint64max), val.asFloat()); | |
| 737 | JSONTEST_ASSERT_EQUAL(true, val.asBool()); | |
| 738 | JSONTEST_ASSERT_STRING_EQUAL("9.22337e+18", val.asString()); | |
| 739 | ||
| 740 | // int64 min | |
| 741 | val = Json::Value(double(kint64min)); | |
| 742 | ||
| 743 | JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); | |
| 744 | ||
| 745 | checks = IsCheck(); | |
| 746 | checks.isDouble_ = true; | |
| 747 | checks.isNumeric_ = true; | |
| 748 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 749 | ||
| 750 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); | |
| 751 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); | |
| 752 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); | |
| 753 | ||
| 754 | JSONTEST_ASSERT_EQUAL(double(kint64min), val.asDouble()); | |
| 755 | JSONTEST_ASSERT_EQUAL(float(kint64min), val.asFloat()); | |
| 756 | JSONTEST_ASSERT_EQUAL(true, val.asBool()); | |
| 757 | JSONTEST_ASSERT_STRING_EQUAL("-9.22337e+18", val.asString()); | |
| 758 | ||
| 759 | // uint64 max | |
| 760 | val = Json::Value(double(kuint64max)); | |
| 761 | ||
| 762 | JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); | |
| 763 | ||
| 764 | checks = IsCheck(); | |
| 765 | checks.isDouble_ = true; | |
| 766 | checks.isNumeric_ = true; | |
| 767 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 768 | ||
| 769 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); | |
| 770 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); | |
| 771 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); | |
| 772 | ||
| 773 | JSONTEST_ASSERT_EQUAL(double(kuint64max), val.asDouble()); | |
| 774 | JSONTEST_ASSERT_EQUAL(float(kuint64max), val.asFloat()); | |
| 775 | JSONTEST_ASSERT_EQUAL(true, val.asBool()); | |
| 776 | JSONTEST_ASSERT_STRING_EQUAL("1.84467e+19", val.asString()); | |
| 777 | #else // ifdef JSON_NO_INT64 | |
| 778 | // 2^40 (signed constructor arg) | |
| 779 | val = Json::Value(Json::Int64(1) << 40); | |
| 780 | ||
| 781 | JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); | |
| 782 | ||
| 783 | checks = IsCheck(); | |
| 784 | checks.isInt64_ = true; | |
| 785 | checks.isUInt64_ = true; | |
| 786 | checks.isIntegral_ = true; | |
| 787 | checks.isDouble_ = true; | |
| 788 | checks.isNumeric_ = true; | |
| 789 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 790 | ||
| 791 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); | |
| 792 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); | |
| 793 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); | |
| 794 | ||
| 795 | JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asInt64()); | |
| 796 | JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asLargestInt()); | |
| 797 | JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asUInt64()); | |
| 798 | JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asLargestUInt()); | |
| 799 | JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asDouble()); | |
| 800 | JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asFloat()); | |
| 801 | JSONTEST_ASSERT_EQUAL(true, val.asBool()); | |
| 802 | JSONTEST_ASSERT_STRING_EQUAL("1099511627776", val.asString()); | |
| 803 | ||
| 804 | // 2^40 (unsigned constructor arg) | |
| 805 | val = Json::Value(Json::UInt64(1) << 40); | |
| 806 | ||
| 807 | JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type()); | |
| 808 | ||
| 809 | checks = IsCheck(); | |
| 810 | checks.isInt64_ = true; | |
| 811 | checks.isUInt64_ = true; | |
| 812 | checks.isIntegral_ = true; | |
| 813 | checks.isDouble_ = true; | |
| 814 | checks.isNumeric_ = true; | |
| 815 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 816 | ||
| 817 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); | |
| 818 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); | |
| 819 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); | |
| 820 | ||
| 821 | JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asInt64()); | |
| 822 | JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asLargestInt()); | |
| 823 | JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asUInt64()); | |
| 824 | JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asLargestUInt()); | |
| 825 | JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asDouble()); | |
| 826 | JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asFloat()); | |
| 827 | JSONTEST_ASSERT_EQUAL(true, val.asBool()); | |
| 828 | JSONTEST_ASSERT_STRING_EQUAL("1099511627776", val.asString()); | |
| 829 | ||
| 830 | // 2^40 (floating-point constructor arg) | |
| 831 | val = Json::Value((Json::Int64(1) << 40) / 1.0); | |
| 832 | ||
| 833 | JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); | |
| 834 | ||
| 835 | checks = IsCheck(); | |
| 836 | checks.isInt64_ = true; | |
| 837 | checks.isUInt64_ = true; | |
| 838 | checks.isIntegral_ = true; | |
| 839 | checks.isDouble_ = true; | |
| 840 | checks.isNumeric_ = true; | |
| 841 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 842 | ||
| 843 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); | |
| 844 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); | |
| 845 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); | |
| 846 | ||
| 847 | JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asInt64()); | |
| 848 | JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asLargestInt()); | |
| 849 | JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asUInt64()); | |
| 850 | JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asLargestUInt()); | |
| 851 | JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asDouble()); | |
| 852 | JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asFloat()); | |
| 853 | JSONTEST_ASSERT_EQUAL(true, val.asBool()); | |
| 854 | JSONTEST_ASSERT_STRING_EQUAL("1099511627776", | |
| 855 | normalizeFloatingPointStr(val.asString())); | |
| 856 | ||
| 857 | // -2^40 | |
| 858 | val = Json::Value(-(Json::Int64(1) << 40)); | |
| 859 | ||
| 860 | JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); | |
| 861 | ||
| 862 | checks = IsCheck(); | |
| 863 | checks.isInt64_ = true; | |
| 864 | checks.isIntegral_ = true; | |
| 865 | checks.isDouble_ = true; | |
| 866 | checks.isNumeric_ = true; | |
| 867 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 868 | ||
| 869 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); | |
| 870 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); | |
| 871 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); | |
| 872 | ||
| 873 | JSONTEST_ASSERT_EQUAL(-(Json::Int64(1) << 40), val.asInt64()); | |
| 874 | JSONTEST_ASSERT_EQUAL(-(Json::Int64(1) << 40), val.asLargestInt()); | |
| 875 | JSONTEST_ASSERT_EQUAL(-(Json::Int64(1) << 40), val.asDouble()); | |
| 876 | JSONTEST_ASSERT_EQUAL(-(Json::Int64(1) << 40), val.asFloat()); | |
| 877 | JSONTEST_ASSERT_EQUAL(true, val.asBool()); | |
| 878 | JSONTEST_ASSERT_STRING_EQUAL("-1099511627776", val.asString()); | |
| 879 | ||
| 880 | // int64 max | |
| 881 | val = Json::Value(Json::Int64(kint64max)); | |
| 882 | ||
| 883 | JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); | |
| 884 | ||
| 885 | checks = IsCheck(); | |
| 886 | checks.isInt64_ = true; | |
| 887 | checks.isUInt64_ = true; | |
| 888 | checks.isIntegral_ = true; | |
| 889 | checks.isDouble_ = true; | |
| 890 | checks.isNumeric_ = true; | |
| 891 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 892 | ||
| 893 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); | |
| 894 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); | |
| 895 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); | |
| 896 | ||
| 897 | JSONTEST_ASSERT_EQUAL(kint64max, val.asInt64()); | |
| 898 | JSONTEST_ASSERT_EQUAL(kint64max, val.asLargestInt()); | |
| 899 | JSONTEST_ASSERT_EQUAL(kint64max, val.asUInt64()); | |
| 900 | JSONTEST_ASSERT_EQUAL(kint64max, val.asLargestUInt()); | |
| 901 | JSONTEST_ASSERT_EQUAL(double(kint64max), val.asDouble()); | |
| 902 | JSONTEST_ASSERT_EQUAL(float(kint64max), val.asFloat()); | |
| 903 | JSONTEST_ASSERT_EQUAL(true, val.asBool()); | |
| 904 | JSONTEST_ASSERT_STRING_EQUAL("9223372036854775807", val.asString()); | |
| 905 | ||
| 906 | // int64 max (floating point constructor). Note that kint64max is not exactly | |
| 907 | // representable as a double, and will be rounded up to be higher. | |
| 908 | val = Json::Value(double(kint64max)); | |
| 909 | ||
| 910 | JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); | |
| 911 | ||
| 912 | checks = IsCheck(); | |
| 913 | checks.isUInt64_ = true; | |
| 914 | checks.isIntegral_ = true; | |
| 915 | checks.isDouble_ = true; | |
| 916 | checks.isNumeric_ = true; | |
| 917 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 918 | ||
| 919 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); | |
| 920 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); | |
| 921 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); | |
| 922 | ||
| 923 | JSONTEST_ASSERT_EQUAL(Json::UInt64(1) << 63, val.asUInt64()); | |
| 924 | JSONTEST_ASSERT_EQUAL(Json::UInt64(1) << 63, val.asLargestUInt()); | |
| 925 | JSONTEST_ASSERT_EQUAL(uint64ToDouble(Json::UInt64(1) << 63), val.asDouble()); | |
| 926 | JSONTEST_ASSERT_EQUAL(float(uint64ToDouble(Json::UInt64(1) << 63)), | |
| 927 | val.asFloat()); | |
| 928 | JSONTEST_ASSERT_EQUAL(true, val.asBool()); | |
| 929 | JSONTEST_ASSERT_STRING_EQUAL("9.2233720368547758e+18", | |
| 930 | normalizeFloatingPointStr(val.asString())); | |
| 931 | ||
| 932 | // int64 min | |
| 933 | val = Json::Value(Json::Int64(kint64min)); | |
| 934 | ||
| 935 | JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); | |
| 936 | ||
| 937 | checks = IsCheck(); | |
| 938 | checks.isInt64_ = true; | |
| 939 | checks.isIntegral_ = true; | |
| 940 | checks.isDouble_ = true; | |
| 941 | checks.isNumeric_ = true; | |
| 942 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 943 | ||
| 944 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); | |
| 945 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); | |
| 946 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); | |
| 947 | ||
| 948 | JSONTEST_ASSERT_EQUAL(kint64min, val.asInt64()); | |
| 949 | JSONTEST_ASSERT_EQUAL(kint64min, val.asLargestInt()); | |
| 950 | JSONTEST_ASSERT_EQUAL(double(kint64min), val.asDouble()); | |
| 951 | JSONTEST_ASSERT_EQUAL(float(kint64min), val.asFloat()); | |
| 952 | JSONTEST_ASSERT_EQUAL(true, val.asBool()); | |
| 953 | JSONTEST_ASSERT_STRING_EQUAL("-9223372036854775808", val.asString()); | |
| 954 | ||
| 955 | // int64 min (floating point constructor). Note that kint64min *is* exactly | |
| 956 | // representable as a double. | |
| 957 | val = Json::Value(double(kint64min)); | |
| 958 | ||
| 959 | JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); | |
| 960 | ||
| 961 | checks = IsCheck(); | |
| 962 | checks.isInt64_ = true; | |
| 963 | checks.isIntegral_ = true; | |
| 964 | checks.isDouble_ = true; | |
| 965 | checks.isNumeric_ = true; | |
| 966 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 967 | ||
| 968 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); | |
| 969 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); | |
| 970 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); | |
| 971 | ||
| 972 | JSONTEST_ASSERT_EQUAL(kint64min, val.asInt64()); | |
| 973 | JSONTEST_ASSERT_EQUAL(kint64min, val.asLargestInt()); | |
| 974 | JSONTEST_ASSERT_EQUAL(-9223372036854775808.0, val.asDouble()); | |
| 975 | JSONTEST_ASSERT_EQUAL(-9223372036854775808.0, val.asFloat()); | |
| 976 | JSONTEST_ASSERT_EQUAL(true, val.asBool()); | |
| 977 | JSONTEST_ASSERT_STRING_EQUAL("-9.2233720368547758e+18", | |
| 978 | normalizeFloatingPointStr(val.asString())); | |
| 979 | ||
| 980 | // 10^19 | |
| 981 | const Json::UInt64 ten_to_19 = static_cast<Json::UInt64>(1e19); | |
| 982 | val = Json::Value(Json::UInt64(ten_to_19)); | |
| 983 | ||
| 984 | JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type()); | |
| 985 | ||
| 986 | checks = IsCheck(); | |
| 987 | checks.isUInt64_ = true; | |
| 988 | checks.isIntegral_ = true; | |
| 989 | checks.isDouble_ = true; | |
| 990 | checks.isNumeric_ = true; | |
| 991 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 992 | ||
| 993 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); | |
| 994 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); | |
| 995 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); | |
| 996 | ||
| 997 | JSONTEST_ASSERT_EQUAL(ten_to_19, val.asUInt64()); | |
| 998 | JSONTEST_ASSERT_EQUAL(ten_to_19, val.asLargestUInt()); | |
| 999 | JSONTEST_ASSERT_EQUAL(uint64ToDouble(ten_to_19), val.asDouble()); | |
| 1000 | JSONTEST_ASSERT_EQUAL(float(uint64ToDouble(ten_to_19)), val.asFloat()); | |
| 1001 | JSONTEST_ASSERT_EQUAL(true, val.asBool()); | |
| 1002 | JSONTEST_ASSERT_STRING_EQUAL("10000000000000000000", val.asString()); | |
| 1003 | ||
| 1004 | // 10^19 (double constructor). Note that 10^19 is not exactly representable | |
| 1005 | // as a double. | |
| 1006 | val = Json::Value(uint64ToDouble(ten_to_19)); | |
| 1007 | ||
| 1008 | JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); | |
| 1009 | ||
| 1010 | checks = IsCheck(); | |
| 1011 | checks.isUInt64_ = true; | |
| 1012 | checks.isIntegral_ = true; | |
| 1013 | checks.isDouble_ = true; | |
| 1014 | checks.isNumeric_ = true; | |
| 1015 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 1016 | ||
| 1017 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); | |
| 1018 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); | |
| 1019 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); | |
| 1020 | ||
| 1021 | JSONTEST_ASSERT_EQUAL(1e19, val.asDouble()); | |
| 1022 | JSONTEST_ASSERT_EQUAL(1e19, val.asFloat()); | |
| 1023 | JSONTEST_ASSERT_EQUAL(true, val.asBool()); | |
| 1024 | JSONTEST_ASSERT_STRING_EQUAL("1e+19", | |
| 1025 | normalizeFloatingPointStr(val.asString())); | |
| 1026 | ||
| 1027 | // uint64 max | |
| 1028 | val = Json::Value(Json::UInt64(kuint64max)); | |
| 1029 | ||
| 1030 | JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type()); | |
| 1031 | ||
| 1032 | checks = IsCheck(); | |
| 1033 | checks.isUInt64_ = true; | |
| 1034 | checks.isIntegral_ = true; | |
| 1035 | checks.isDouble_ = true; | |
| 1036 | checks.isNumeric_ = true; | |
| 1037 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 1038 | ||
| 1039 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); | |
| 1040 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); | |
| 1041 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); | |
| 1042 | ||
| 1043 | JSONTEST_ASSERT_EQUAL(kuint64max, val.asUInt64()); | |
| 1044 | JSONTEST_ASSERT_EQUAL(kuint64max, val.asLargestUInt()); | |
| 1045 | JSONTEST_ASSERT_EQUAL(uint64ToDouble(kuint64max), val.asDouble()); | |
| 1046 | JSONTEST_ASSERT_EQUAL(float(uint64ToDouble(kuint64max)), val.asFloat()); | |
| 1047 | JSONTEST_ASSERT_EQUAL(true, val.asBool()); | |
| 1048 | JSONTEST_ASSERT_STRING_EQUAL("18446744073709551615", val.asString()); | |
| 1049 | ||
| 1050 | // uint64 max (floating point constructor). Note that kuint64max is not | |
| 1051 | // exactly representable as a double, and will be rounded up to be higher. | |
| 1052 | val = Json::Value(uint64ToDouble(kuint64max)); | |
| 1053 | ||
| 1054 | JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); | |
| 1055 | ||
| 1056 | checks = IsCheck(); | |
| 1057 | checks.isDouble_ = true; | |
| 1058 | checks.isNumeric_ = true; | |
| 1059 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 1060 | ||
| 1061 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); | |
| 1062 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); | |
| 1063 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); | |
| 1064 | ||
| 1065 | JSONTEST_ASSERT_EQUAL(18446744073709551616.0, val.asDouble()); | |
| 1066 | JSONTEST_ASSERT_EQUAL(18446744073709551616.0, val.asFloat()); | |
| 1067 | JSONTEST_ASSERT_EQUAL(true, val.asBool()); | |
| 1068 | JSONTEST_ASSERT_STRING_EQUAL("1.8446744073709552e+19", | |
| 1069 | normalizeFloatingPointStr(val.asString())); | |
| 1070 | #endif | |
| 1071 | } | |
| 1072 | ||
| 1073 | JSONTEST_FIXTURE(ValueTest, nonIntegers) { | |
| 1074 | IsCheck checks; | |
| 1075 | Json::Value val; | |
| 1076 | ||
| 1077 | // Small positive number | |
| 1078 | val = Json::Value(1.5); | |
| 1079 | ||
| 1080 | JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); | |
| 1081 | ||
| 1082 | checks = IsCheck(); | |
| 1083 | checks.isDouble_ = true; | |
| 1084 | checks.isNumeric_ = true; | |
| 1085 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 1086 | ||
| 1087 | JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); | |
| 1088 | JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); | |
| 1089 | JSONTEST_ASSERT(val.isConvertibleTo(Json::realValue)); | |
| 1090 | JSONTEST_ASSERT(val.isConvertibleTo(Json::booleanValue)); | |
| 1091 | JSONTEST_ASSERT(val.isConvertibleTo(Json::stringValue)); | |
| 1092 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); | |
| 1093 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::arrayValue)); | |
| 1094 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::objectValue)); | |
| 1095 | ||
| 1096 | JSONTEST_ASSERT_EQUAL(1.5, val.asDouble()); | |
| 1097 | JSONTEST_ASSERT_EQUAL(1.5, val.asFloat()); | |
| 1098 | JSONTEST_ASSERT_EQUAL(1, val.asInt()); | |
| 1099 | JSONTEST_ASSERT_EQUAL(1, val.asLargestInt()); | |
| 1100 | JSONTEST_ASSERT_EQUAL(1, val.asUInt()); | |
| 1101 | JSONTEST_ASSERT_EQUAL(1, val.asLargestUInt()); | |
| 1102 | JSONTEST_ASSERT_EQUAL(true, val.asBool()); | |
| 1103 | JSONTEST_ASSERT_EQUAL("1.5", val.asString()); | |
| 1104 | ||
| 1105 | // Small negative number | |
| 1106 | val = Json::Value(-1.5); | |
| 1107 | ||
| 1108 | JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); | |
| 1109 | ||
| 1110 | checks = IsCheck(); | |
| 1111 | checks.isDouble_ = true; | |
| 1112 | checks.isNumeric_ = true; | |
| 1113 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 1114 | ||
| 1115 | JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); | |
| 1116 | JSONTEST_ASSERT(val.isConvertibleTo(Json::realValue)); | |
| 1117 | JSONTEST_ASSERT(val.isConvertibleTo(Json::booleanValue)); | |
| 1118 | JSONTEST_ASSERT(val.isConvertibleTo(Json::stringValue)); | |
| 1119 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); | |
| 1120 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); | |
| 1121 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::arrayValue)); | |
| 1122 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::objectValue)); | |
| 1123 | ||
| 1124 | JSONTEST_ASSERT_EQUAL(-1.5, val.asDouble()); | |
| 1125 | JSONTEST_ASSERT_EQUAL(-1.5, val.asFloat()); | |
| 1126 | JSONTEST_ASSERT_EQUAL(-1, val.asInt()); | |
| 1127 | JSONTEST_ASSERT_EQUAL(-1, val.asLargestInt()); | |
| 1128 | JSONTEST_ASSERT_EQUAL(true, val.asBool()); | |
| 1129 | JSONTEST_ASSERT_EQUAL("-1.5", val.asString()); | |
| 1130 | ||
| 1131 | // A bit over int32 max | |
| 1132 | val = Json::Value(kint32max + 0.5); | |
| 1133 | ||
| 1134 | JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); | |
| 1135 | ||
| 1136 | checks = IsCheck(); | |
| 1137 | checks.isDouble_ = true; | |
| 1138 | checks.isNumeric_ = true; | |
| 1139 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 1140 | ||
| 1141 | JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); | |
| 1142 | JSONTEST_ASSERT(val.isConvertibleTo(Json::realValue)); | |
| 1143 | JSONTEST_ASSERT(val.isConvertibleTo(Json::booleanValue)); | |
| 1144 | JSONTEST_ASSERT(val.isConvertibleTo(Json::stringValue)); | |
| 1145 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); | |
| 1146 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); | |
| 1147 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::arrayValue)); | |
| 1148 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::objectValue)); | |
| 1149 | ||
| 1150 | JSONTEST_ASSERT_EQUAL(2147483647.5, val.asDouble()); | |
| 1151 | JSONTEST_ASSERT_EQUAL(float(2147483647.5), val.asFloat()); | |
| 1152 | JSONTEST_ASSERT_EQUAL(2147483647U, val.asUInt()); | |
| 1153 | #ifdef JSON_HAS_INT64 | |
| 1154 | JSONTEST_ASSERT_EQUAL(2147483647L, val.asLargestInt()); | |
| 1155 | JSONTEST_ASSERT_EQUAL(2147483647U, val.asLargestUInt()); | |
| 1156 | #endif | |
| 1157 | JSONTEST_ASSERT_EQUAL(true, val.asBool()); | |
| 1158 | JSONTEST_ASSERT_EQUAL("2147483647.5", | |
| 1159 | normalizeFloatingPointStr(val.asString())); | |
| 1160 | ||
| 1161 | // A bit under int32 min | |
| 1162 | val = Json::Value(kint32min - 0.5); | |
| 1163 | ||
| 1164 | JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); | |
| 1165 | ||
| 1166 | checks = IsCheck(); | |
| 1167 | checks.isDouble_ = true; | |
| 1168 | checks.isNumeric_ = true; | |
| 1169 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 1170 | ||
| 1171 | JSONTEST_ASSERT(val.isConvertibleTo(Json::realValue)); | |
| 1172 | JSONTEST_ASSERT(val.isConvertibleTo(Json::booleanValue)); | |
| 1173 | JSONTEST_ASSERT(val.isConvertibleTo(Json::stringValue)); | |
| 1174 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); | |
| 1175 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); | |
| 1176 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); | |
| 1177 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::arrayValue)); | |
| 1178 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::objectValue)); | |
| 1179 | ||
| 1180 | JSONTEST_ASSERT_EQUAL(-2147483648.5, val.asDouble()); | |
| 1181 | JSONTEST_ASSERT_EQUAL(float(-2147483648.5), val.asFloat()); | |
| 1182 | #ifdef JSON_HAS_INT64 | |
| 1183 | JSONTEST_ASSERT_EQUAL(-Json::Int64(1) << 31, val.asLargestInt()); | |
| 1184 | #endif | |
| 1185 | JSONTEST_ASSERT_EQUAL(true, val.asBool()); | |
| 1186 | JSONTEST_ASSERT_EQUAL("-2147483648.5", | |
| 1187 | normalizeFloatingPointStr(val.asString())); | |
| 1188 | ||
| 1189 | // A bit over uint32 max | |
| 1190 | val = Json::Value(kuint32max + 0.5); | |
| 1191 | ||
| 1192 | JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); | |
| 1193 | ||
| 1194 | checks = IsCheck(); | |
| 1195 | checks.isDouble_ = true; | |
| 1196 | checks.isNumeric_ = true; | |
| 1197 | JSONTEST_ASSERT_PRED(checkIs(val, checks)); | |
| 1198 | ||
| 1199 | JSONTEST_ASSERT(val.isConvertibleTo(Json::realValue)); | |
| 1200 | JSONTEST_ASSERT(val.isConvertibleTo(Json::booleanValue)); | |
| 1201 | JSONTEST_ASSERT(val.isConvertibleTo(Json::stringValue)); | |
| 1202 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); | |
| 1203 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); | |
| 1204 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); | |
| 1205 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::arrayValue)); | |
| 1206 | JSONTEST_ASSERT(!val.isConvertibleTo(Json::objectValue)); | |
| 1207 | ||
| 1208 | JSONTEST_ASSERT_EQUAL(4294967295.5, val.asDouble()); | |
| 1209 | JSONTEST_ASSERT_EQUAL(float(4294967295.5), val.asFloat()); | |
| 1210 | #ifdef JSON_HAS_INT64 | |
| 1211 | JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 32) - 1, val.asLargestInt()); | |
| 1212 | JSONTEST_ASSERT_EQUAL((Json::UInt64(1) << 32) - Json::UInt64(1), | |
| 1213 | val.asLargestUInt()); | |
| 1214 | #endif | |
| 1215 | JSONTEST_ASSERT_EQUAL(true, val.asBool()); | |
| 1216 | JSONTEST_ASSERT_EQUAL("4294967295.5", | |
| 1217 | normalizeFloatingPointStr(val.asString())); | |
| 1218 | ||
| 1219 | val = Json::Value(1.2345678901234); | |
| 1220 | JSONTEST_ASSERT_STRING_EQUAL("1.2345678901234001", | |
| 1221 | normalizeFloatingPointStr(val.asString())); | |
| 1222 | ||
| 1223 | // A 16-digit floating point number. | |
| 1224 | val = Json::Value(2199023255552000.0f); | |
| 1225 | JSONTEST_ASSERT_EQUAL(float(2199023255552000), val.asFloat()); | |
| 1226 | JSONTEST_ASSERT_STRING_EQUAL("2199023255552000", | |
| 1227 | normalizeFloatingPointStr(val.asString())); | |
| 1228 | ||
| 1229 | // A very large floating point number. | |
| 1230 | val = Json::Value(3.402823466385289e38); | |
| 1231 | JSONTEST_ASSERT_EQUAL(float(3.402823466385289e38), val.asFloat()); | |
| 1232 | JSONTEST_ASSERT_STRING_EQUAL("3.402823466385289e+38", | |
| 1233 | normalizeFloatingPointStr(val.asString())); | |
| 1234 | ||
| 1235 | // An even larger floating point number. | |
| 1236 | val = Json::Value(1.2345678e300); | |
| 1237 | JSONTEST_ASSERT_EQUAL(double(1.2345678e300), val.asDouble()); | |
| 1238 | JSONTEST_ASSERT_STRING_EQUAL("1.2345678e+300", | |
| 1239 | normalizeFloatingPointStr(val.asString())); | |
| 1240 | } | |
| 1241 | ||
| 1242 | void ValueTest::checkConstMemberCount(const Json::Value& value, | |
| 1243 | unsigned int expectedCount) { | |
| 1244 | unsigned int count = 0; | |
| 1245 | Json::Value::const_iterator itEnd = value.end(); | |
| 1246 | for (Json::Value::const_iterator it = value.begin(); it != itEnd; ++it) { | |
| 1247 | ++count; | |
| 1248 | } | |
| 1249 | JSONTEST_ASSERT_EQUAL(expectedCount, count) << "Json::Value::const_iterator"; | |
| 1250 | } | |
| 1251 | ||
| 1252 | void ValueTest::checkMemberCount(Json::Value& value, | |
| 1253 | unsigned int expectedCount) { | |
| 1254 | JSONTEST_ASSERT_EQUAL(expectedCount, value.size()); | |
| 1255 | ||
| 1256 | unsigned int count = 0; | |
| 1257 | Json::Value::iterator itEnd = value.end(); | |
| 1258 | for (Json::Value::iterator it = value.begin(); it != itEnd; ++it) { | |
| 1259 | ++count; | |
| 1260 | } | |
| 1261 | JSONTEST_ASSERT_EQUAL(expectedCount, count) << "Json::Value::iterator"; | |
| 1262 | ||
| 1263 | JSONTEST_ASSERT_PRED(checkConstMemberCount(value, expectedCount)); | |
| 1264 | } | |
| 1265 | ||
| 1266 | ValueTest::IsCheck::IsCheck() | |
| 1267 | : isObject_(false), isArray_(false), isBool_(false), isString_(false), | |
| 1268 | isNull_(false), isInt_(false), isInt64_(false), isUInt_(false), | |
| 1269 | isUInt64_(false), isIntegral_(false), isDouble_(false), | |
| 1270 | isNumeric_(false) {} | |
| 1271 | ||
| 1272 | void ValueTest::checkIs(const Json::Value& value, const IsCheck& check) { | |
| 1273 | JSONTEST_ASSERT_EQUAL(check.isObject_, value.isObject()); | |
| 1274 | JSONTEST_ASSERT_EQUAL(check.isArray_, value.isArray()); | |
| 1275 | JSONTEST_ASSERT_EQUAL(check.isBool_, value.isBool()); | |
| 1276 | JSONTEST_ASSERT_EQUAL(check.isDouble_, value.isDouble()); | |
| 1277 | JSONTEST_ASSERT_EQUAL(check.isInt_, value.isInt()); | |
| 1278 | JSONTEST_ASSERT_EQUAL(check.isUInt_, value.isUInt()); | |
| 1279 | JSONTEST_ASSERT_EQUAL(check.isIntegral_, value.isIntegral()); | |
| 1280 | JSONTEST_ASSERT_EQUAL(check.isNumeric_, value.isNumeric()); | |
| 1281 | JSONTEST_ASSERT_EQUAL(check.isString_, value.isString()); | |
| 1282 | JSONTEST_ASSERT_EQUAL(check.isNull_, value.isNull()); | |
| 1283 | ||
| 1284 | #ifdef JSON_HAS_INT64 | |
| 1285 | JSONTEST_ASSERT_EQUAL(check.isInt64_, value.isInt64()); | |
| 1286 | JSONTEST_ASSERT_EQUAL(check.isUInt64_, value.isUInt64()); | |
| 1287 | #else | |
| 1288 | JSONTEST_ASSERT_EQUAL(false, value.isInt64()); | |
| 1289 | JSONTEST_ASSERT_EQUAL(false, value.isUInt64()); | |
| 1290 | #endif | |
| 1291 | } | |
| 1292 | ||
| 1293 | JSONTEST_FIXTURE(ValueTest, compareNull) { | |
| 1294 | JSONTEST_ASSERT_PRED(checkIsEqual(Json::Value(), Json::Value())); | |
| 1295 | } | |
| 1296 | ||
| 1297 | JSONTEST_FIXTURE(ValueTest, compareInt) { | |
| 1298 | JSONTEST_ASSERT_PRED(checkIsLess(0, 10)); | |
| 1299 | JSONTEST_ASSERT_PRED(checkIsEqual(10, 10)); | |
| 1300 | JSONTEST_ASSERT_PRED(checkIsEqual(-10, -10)); | |
| 1301 | JSONTEST_ASSERT_PRED(checkIsLess(-10, 0)); | |
| 1302 | } | |
| 1303 | ||
| 1304 | JSONTEST_FIXTURE(ValueTest, compareUInt) { | |
| 1305 | JSONTEST_ASSERT_PRED(checkIsLess(0u, 10u)); | |
| 1306 | JSONTEST_ASSERT_PRED(checkIsLess(0u, Json::Value::maxUInt)); | |
| 1307 | JSONTEST_ASSERT_PRED(checkIsEqual(10u, 10u)); | |
| 1308 | } | |
| 1309 | ||
| 1310 | JSONTEST_FIXTURE(ValueTest, compareDouble) { | |
| 1311 | JSONTEST_ASSERT_PRED(checkIsLess(0.0, 10.0)); | |
| 1312 | JSONTEST_ASSERT_PRED(checkIsEqual(10.0, 10.0)); | |
| 1313 | JSONTEST_ASSERT_PRED(checkIsEqual(-10.0, -10.0)); | |
| 1314 | JSONTEST_ASSERT_PRED(checkIsLess(-10.0, 0.0)); | |
| 1315 | } | |
| 1316 | ||
| 1317 | JSONTEST_FIXTURE(ValueTest, compareString) { | |
| 1318 | JSONTEST_ASSERT_PRED(checkIsLess("", " ")); | |
| 1319 | JSONTEST_ASSERT_PRED(checkIsLess("", "a")); | |
| 1320 | JSONTEST_ASSERT_PRED(checkIsLess("abcd", "zyui")); | |
| 1321 | JSONTEST_ASSERT_PRED(checkIsLess("abc", "abcd")); | |
| 1322 | JSONTEST_ASSERT_PRED(checkIsEqual("abcd", "abcd")); | |
| 1323 | JSONTEST_ASSERT_PRED(checkIsEqual(" ", " ")); | |
| 1324 | JSONTEST_ASSERT_PRED(checkIsLess("ABCD", "abcd")); | |
| 1325 | JSONTEST_ASSERT_PRED(checkIsEqual("ABCD", "ABCD")); | |
| 1326 | } | |
| 1327 | ||
| 1328 | JSONTEST_FIXTURE(ValueTest, compareBoolean) { | |
| 1329 | JSONTEST_ASSERT_PRED(checkIsLess(false, true)); | |
| 1330 | JSONTEST_ASSERT_PRED(checkIsEqual(false, false)); | |
| 1331 | JSONTEST_ASSERT_PRED(checkIsEqual(true, true)); | |
| 1332 | } | |
| 1333 | ||
| 1334 | JSONTEST_FIXTURE(ValueTest, compareArray) { | |
| 1335 | // array compare size then content | |
| 1336 | Json::Value emptyArray(Json::arrayValue); | |
| 1337 | Json::Value l1aArray; | |
| 1338 | l1aArray.append(0); | |
| 1339 | Json::Value l1bArray; | |
| 1340 | l1bArray.append(10); | |
| 1341 | Json::Value l2aArray; | |
| 1342 | l2aArray.append(0); | |
| 1343 | l2aArray.append(0); | |
| 1344 | Json::Value l2bArray; | |
| 1345 | l2bArray.append(0); | |
| 1346 | l2bArray.append(10); | |
| 1347 | JSONTEST_ASSERT_PRED(checkIsLess(emptyArray, l1aArray)); | |
| 1348 | JSONTEST_ASSERT_PRED(checkIsLess(emptyArray, l2aArray)); | |
| 1349 | JSONTEST_ASSERT_PRED(checkIsLess(l1aArray, l2aArray)); | |
| 1350 | JSONTEST_ASSERT_PRED(checkIsLess(l2aArray, l2bArray)); | |
| 1351 | JSONTEST_ASSERT_PRED(checkIsEqual(emptyArray, Json::Value(emptyArray))); | |
| 1352 | JSONTEST_ASSERT_PRED(checkIsEqual(l1aArray, Json::Value(l1aArray))); | |
| 1353 | JSONTEST_ASSERT_PRED(checkIsEqual(l2bArray, Json::Value(l2bArray))); | |
| 1354 | } | |
| 1355 | ||
| 1356 | JSONTEST_FIXTURE(ValueTest, compareObject) { | |
| 1357 | // object compare size then content | |
| 1358 | Json::Value emptyObject(Json::objectValue); | |
| 1359 | Json::Value l1aObject; | |
| 1360 | l1aObject["key1"] = 0; | |
| 1361 | Json::Value l1bObject; | |
| 1362 | l1aObject["key1"] = 10; | |
| 1363 | Json::Value l2aObject; | |
| 1364 | l2aObject["key1"] = 0; | |
| 1365 | l2aObject["key2"] = 0; | |
| 1366 | JSONTEST_ASSERT_PRED(checkIsLess(emptyObject, l1aObject)); | |
| 1367 | JSONTEST_ASSERT_PRED(checkIsLess(emptyObject, l2aObject)); | |
| 1368 | JSONTEST_ASSERT_PRED(checkIsLess(l1aObject, l2aObject)); | |
| 1369 | JSONTEST_ASSERT_PRED(checkIsEqual(emptyObject, Json::Value(emptyObject))); | |
| 1370 | JSONTEST_ASSERT_PRED(checkIsEqual(l1aObject, Json::Value(l1aObject))); | |
| 1371 | JSONTEST_ASSERT_PRED(checkIsEqual(l2aObject, Json::Value(l2aObject))); | |
| 1372 | } | |
| 1373 | ||
| 1374 | JSONTEST_FIXTURE(ValueTest, compareType) { | |
| 1375 | // object of different type are ordered according to their type | |
| 1376 | JSONTEST_ASSERT_PRED(checkIsLess(Json::Value(), Json::Value(1))); | |
| 1377 | JSONTEST_ASSERT_PRED(checkIsLess(Json::Value(1), Json::Value(1u))); | |
| 1378 | JSONTEST_ASSERT_PRED(checkIsLess(Json::Value(1u), Json::Value(1.0))); | |
| 1379 | JSONTEST_ASSERT_PRED(checkIsLess(Json::Value(1.0), Json::Value("a"))); | |
| 1380 | JSONTEST_ASSERT_PRED(checkIsLess(Json::Value("a"), Json::Value(true))); | |
| 1381 | JSONTEST_ASSERT_PRED( | |
| 1382 | checkIsLess(Json::Value(true), Json::Value(Json::arrayValue))); | |
| 1383 | JSONTEST_ASSERT_PRED(checkIsLess(Json::Value(Json::arrayValue), | |
| 1384 | Json::Value(Json::objectValue))); | |
| 1385 | } | |
| 1386 | ||
| 1387 | void ValueTest::checkIsLess(const Json::Value& x, const Json::Value& y) { | |
| 1388 | JSONTEST_ASSERT(x < y); | |
| 1389 | JSONTEST_ASSERT(y > x); | |
| 1390 | JSONTEST_ASSERT(x <= y); | |
| 1391 | JSONTEST_ASSERT(y >= x); | |
| 1392 | JSONTEST_ASSERT(!(x == y)); | |
| 1393 | JSONTEST_ASSERT(!(y == x)); | |
| 1394 | JSONTEST_ASSERT(!(x >= y)); | |
| 1395 | JSONTEST_ASSERT(!(y <= x)); | |
| 1396 | JSONTEST_ASSERT(!(x > y)); | |
| 1397 | JSONTEST_ASSERT(!(y < x)); | |
| 1398 | JSONTEST_ASSERT(x.compare(y) < 0); | |
| 1399 | JSONTEST_ASSERT(y.compare(x) >= 0); | |
| 1400 | } | |
| 1401 | ||
| 1402 | void ValueTest::checkIsEqual(const Json::Value& x, const Json::Value& y) { | |
| 1403 | JSONTEST_ASSERT(x == y); | |
| 1404 | JSONTEST_ASSERT(y == x); | |
| 1405 | JSONTEST_ASSERT(x <= y); | |
| 1406 | JSONTEST_ASSERT(y <= x); | |
| 1407 | JSONTEST_ASSERT(x >= y); | |
| 1408 | JSONTEST_ASSERT(y >= x); | |
| 1409 | JSONTEST_ASSERT(!(x < y)); | |
| 1410 | JSONTEST_ASSERT(!(y < x)); | |
| 1411 | JSONTEST_ASSERT(!(x > y)); | |
| 1412 | JSONTEST_ASSERT(!(y > x)); | |
| 1413 | JSONTEST_ASSERT(x.compare(y) == 0); | |
| 1414 | JSONTEST_ASSERT(y.compare(x) == 0); | |
| 1415 | } | |
| 1416 | ||
| 1417 | JSONTEST_FIXTURE(ValueTest, typeChecksThrowExceptions) { | |
| 1418 | #if JSON_USE_EXCEPTION | |
| 1419 | ||
| 1420 | Json::Value intVal(1); | |
| 1421 | Json::Value strVal("Test"); | |
| 1422 | Json::Value objVal(Json::objectValue); | |
| 1423 | Json::Value arrVal(Json::arrayValue); | |
| 1424 | ||
| 1425 | JSONTEST_ASSERT_THROWS(intVal["test"]); | |
| 1426 | JSONTEST_ASSERT_THROWS(strVal["test"]); | |
| 1427 | JSONTEST_ASSERT_THROWS(arrVal["test"]); | |
| 1428 | ||
| 1429 | JSONTEST_ASSERT_THROWS(intVal.removeMember("test")); | |
| 1430 | JSONTEST_ASSERT_THROWS(strVal.removeMember("test")); | |
| 1431 | JSONTEST_ASSERT_THROWS(arrVal.removeMember("test")); | |
| 1432 | ||
| 1433 | JSONTEST_ASSERT_THROWS(intVal.getMemberNames()); | |
| 1434 | JSONTEST_ASSERT_THROWS(strVal.getMemberNames()); | |
| 1435 | JSONTEST_ASSERT_THROWS(arrVal.getMemberNames()); | |
| 1436 | ||
| 1437 | JSONTEST_ASSERT_THROWS(intVal[0]); | |
| 1438 | JSONTEST_ASSERT_THROWS(objVal[0]); | |
| 1439 | JSONTEST_ASSERT_THROWS(strVal[0]); | |
| 1440 | ||
| 1441 | JSONTEST_ASSERT_THROWS(intVal.clear()); | |
| 1442 | ||
| 1443 | JSONTEST_ASSERT_THROWS(intVal.resize(1)); | |
| 1444 | JSONTEST_ASSERT_THROWS(strVal.resize(1)); | |
| 1445 | JSONTEST_ASSERT_THROWS(objVal.resize(1)); | |
| 1446 | ||
| 1447 | JSONTEST_ASSERT_THROWS(intVal.asCString()); | |
| 1448 | ||
| 1449 | JSONTEST_ASSERT_THROWS(objVal.asString()); | |
| 1450 | JSONTEST_ASSERT_THROWS(arrVal.asString()); | |
| 1451 | ||
| 1452 | JSONTEST_ASSERT_THROWS(strVal.asInt()); | |
| 1453 | JSONTEST_ASSERT_THROWS(objVal.asInt()); | |
| 1454 | JSONTEST_ASSERT_THROWS(arrVal.asInt()); | |
| 1455 | ||
| 1456 | JSONTEST_ASSERT_THROWS(strVal.asUInt()); | |
| 1457 | JSONTEST_ASSERT_THROWS(objVal.asUInt()); | |
| 1458 | JSONTEST_ASSERT_THROWS(arrVal.asUInt()); | |
| 1459 | ||
| 1460 | JSONTEST_ASSERT_THROWS(strVal.asInt64()); | |
| 1461 | JSONTEST_ASSERT_THROWS(objVal.asInt64()); | |
| 1462 | JSONTEST_ASSERT_THROWS(arrVal.asInt64()); | |
| 1463 | ||
| 1464 | JSONTEST_ASSERT_THROWS(strVal.asUInt64()); | |
| 1465 | JSONTEST_ASSERT_THROWS(objVal.asUInt64()); | |
| 1466 | JSONTEST_ASSERT_THROWS(arrVal.asUInt64()); | |
| 1467 | ||
| 1468 | JSONTEST_ASSERT_THROWS(strVal.asDouble()); | |
| 1469 | JSONTEST_ASSERT_THROWS(objVal.asDouble()); | |
| 1470 | JSONTEST_ASSERT_THROWS(arrVal.asDouble()); | |
| 1471 | ||
| 1472 | JSONTEST_ASSERT_THROWS(strVal.asFloat()); | |
| 1473 | JSONTEST_ASSERT_THROWS(objVal.asFloat()); | |
| 1474 | JSONTEST_ASSERT_THROWS(arrVal.asFloat()); | |
| 1475 | ||
| 1476 | JSONTEST_ASSERT_THROWS(strVal.asBool()); | |
| 1477 | JSONTEST_ASSERT_THROWS(objVal.asBool()); | |
| 1478 | JSONTEST_ASSERT_THROWS(arrVal.asBool()); | |
| 1479 | ||
| 1480 | #endif | |
| 1481 | } | |
| 1482 | ||
| 1483 | JSONTEST_FIXTURE(ValueTest, offsetAccessors) { | |
| 1484 | Json::Value x; | |
| 1485 | JSONTEST_ASSERT(x.getOffsetStart() == 0); | |
| 1486 | JSONTEST_ASSERT(x.getOffsetLimit() == 0); | |
| 1487 | x.setOffsetStart(10); | |
| 1488 | x.setOffsetLimit(20); | |
| 1489 | JSONTEST_ASSERT(x.getOffsetStart() == 10); | |
| 1490 | JSONTEST_ASSERT(x.getOffsetLimit() == 20); | |
| 1491 | Json::Value y(x); | |
| 1492 | JSONTEST_ASSERT(y.getOffsetStart() == 10); | |
| 1493 | JSONTEST_ASSERT(y.getOffsetLimit() == 20); | |
| 1494 | Json::Value z; | |
| 1495 | z.swap(y); | |
| 1496 | JSONTEST_ASSERT(z.getOffsetStart() == 10); | |
| 1497 | JSONTEST_ASSERT(z.getOffsetLimit() == 20); | |
| 1498 | JSONTEST_ASSERT(y.getOffsetStart() == 0); | |
| 1499 | JSONTEST_ASSERT(y.getOffsetLimit() == 0); | |
| 1500 | } | |
| 1501 | ||
| 1502 | struct WriterTest : JsonTest::TestCase {}; | |
| 1503 | ||
| 1504 | JSONTEST_FIXTURE(WriterTest, dropNullPlaceholders) { | |
| 1505 | Json::FastWriter writer; | |
| 1506 | Json::Value nullValue; | |
| 1507 | JSONTEST_ASSERT(writer.write(nullValue) == "null\n"); | |
| 1508 | ||
| 1509 | writer.dropNullPlaceholders(); | |
| 1510 | JSONTEST_ASSERT(writer.write(nullValue) == "\n"); | |
| 1511 | } | |
| 1512 | ||
| 1513 | struct ReaderTest : JsonTest::TestCase {}; | |
| 1514 | ||
| 1515 | JSONTEST_FIXTURE(ReaderTest, parseWithNoErrors) { | |
| 1516 | Json::Reader reader; | |
| 1517 | Json::Value root; | |
| 1518 | bool ok = reader.parse("{ \"property\" : \"value\" }", root); | |
| 1519 | JSONTEST_ASSERT(ok); | |
| 1520 | JSONTEST_ASSERT(reader.getFormattedErrorMessages().size() == 0); | |
| 1521 | JSONTEST_ASSERT(reader.getStructuredErrors().size() == 0); | |
| 1522 | } | |
| 1523 | ||
| 1524 | JSONTEST_FIXTURE(ReaderTest, parseWithNoErrorsTestingOffsets) { | |
| 1525 | Json::Reader reader; | |
| 1526 | Json::Value root; | |
| 1527 | bool ok = reader.parse("{ \"property\" : [\"value\", \"value2\"], \"obj\" : " | |
| 1528 | "{ \"nested\" : 123, \"bool\" : true}, \"null\" : " | |
| 1529 | "null, \"false\" : false }", | |
| 1530 | root); | |
| 1531 | JSONTEST_ASSERT(ok); | |
| 1532 | JSONTEST_ASSERT(reader.getFormattedErrorMessages().size() == 0); | |
| 1533 | JSONTEST_ASSERT(reader.getStructuredErrors().size() == 0); | |
| 1534 | JSONTEST_ASSERT(root["property"].getOffsetStart() == 15); | |
| 1535 | JSONTEST_ASSERT(root["property"].getOffsetLimit() == 34); | |
| 1536 | JSONTEST_ASSERT(root["property"][0].getOffsetStart() == 16); | |
| 1537 | JSONTEST_ASSERT(root["property"][0].getOffsetLimit() == 23); | |
| 1538 | JSONTEST_ASSERT(root["property"][1].getOffsetStart() == 25); | |
| 1539 | JSONTEST_ASSERT(root["property"][1].getOffsetLimit() == 33); | |
| 1540 | JSONTEST_ASSERT(root["obj"].getOffsetStart() == 44); | |
| 1541 | JSONTEST_ASSERT(root["obj"].getOffsetLimit() == 76); | |
| 1542 | JSONTEST_ASSERT(root["obj"]["nested"].getOffsetStart() == 57); | |
| 1543 | JSONTEST_ASSERT(root["obj"]["nested"].getOffsetLimit() == 60); | |
| 1544 | JSONTEST_ASSERT(root["obj"]["bool"].getOffsetStart() == 71); | |
| 1545 | JSONTEST_ASSERT(root["obj"]["bool"].getOffsetLimit() == 75); | |
| 1546 | JSONTEST_ASSERT(root["null"].getOffsetStart() == 87); | |
| 1547 | JSONTEST_ASSERT(root["null"].getOffsetLimit() == 91); | |
| 1548 | JSONTEST_ASSERT(root["false"].getOffsetStart() == 103); | |
| 1549 | JSONTEST_ASSERT(root["false"].getOffsetLimit() == 108); | |
| 1550 | JSONTEST_ASSERT(root.getOffsetStart() == 0); | |
| 1551 | JSONTEST_ASSERT(root.getOffsetLimit() == 110); | |
| 1552 | } | |
| 1553 | ||
| 1554 | JSONTEST_FIXTURE(ReaderTest, parseWithOneError) { | |
| 1555 | Json::Reader reader; | |
| 1556 | Json::Value root; | |
| 1557 | bool ok = reader.parse("{ \"property\" :: \"value\" }", root); | |
| 1558 | JSONTEST_ASSERT(!ok); | |
| 1559 | JSONTEST_ASSERT(reader.getFormattedErrorMessages() == | |
| 1560 | "* Line 1, Column 15\n Syntax error: value, object or array " | |
| 1561 | "expected.\n"); | |
| 1562 | std::vector<Json::Reader::StructuredError> errors = | |
| 1563 | reader.getStructuredErrors(); | |
| 1564 | JSONTEST_ASSERT(errors.size() == 1); | |
| 1565 | JSONTEST_ASSERT(errors.at(0).offset_start == 14); | |
| 1566 | JSONTEST_ASSERT(errors.at(0).offset_limit == 15); | |
| 1567 | JSONTEST_ASSERT(errors.at(0).message == | |
| 1568 | "Syntax error: value, object or array expected."); | |
| 1569 | } | |
| 1570 | ||
| 1571 | JSONTEST_FIXTURE(ReaderTest, parseChineseWithOneError) { | |
| 1572 | Json::Reader reader; | |
| 1573 | Json::Value root; | |
| 1574 | bool ok = reader.parse("{ \"pr佐藤erty\" :: \"value\" }", root); | |
| 1575 | JSONTEST_ASSERT(!ok); | |
| 1576 | JSONTEST_ASSERT(reader.getFormattedErrorMessages() == | |
| 1577 | "* Line 1, Column 19\n Syntax error: value, object or array " | |
| 1578 | "expected.\n"); | |
| 1579 | std::vector<Json::Reader::StructuredError> errors = | |
| 1580 | reader.getStructuredErrors(); | |
| 1581 | JSONTEST_ASSERT(errors.size() == 1); | |
| 1582 | JSONTEST_ASSERT(errors.at(0).offset_start == 18); | |
| 1583 | JSONTEST_ASSERT(errors.at(0).offset_limit == 19); | |
| 1584 | JSONTEST_ASSERT(errors.at(0).message == | |
| 1585 | "Syntax error: value, object or array expected."); | |
| 1586 | } | |
| 1587 | ||
| 1588 | JSONTEST_FIXTURE(ReaderTest, parseWithDetailError) { | |
| 1589 | Json::Reader reader; | |
| 1590 | Json::Value root; | |
| 1591 | bool ok = reader.parse("{ \"property\" : \"v\\alue\" }", root); | |
| 1592 | JSONTEST_ASSERT(!ok); | |
| 1593 | JSONTEST_ASSERT(reader.getFormattedErrorMessages() == | |
| 1594 | "* Line 1, Column 16\n Bad escape sequence in string\nSee " | |
| 1595 | "Line 1, Column 20 for detail.\n"); | |
| 1596 | std::vector<Json::Reader::StructuredError> errors = | |
| 1597 | reader.getStructuredErrors(); | |
| 1598 | JSONTEST_ASSERT(errors.size() == 1); | |
| 1599 | JSONTEST_ASSERT(errors.at(0).offset_start == 15); | |
| 1600 | JSONTEST_ASSERT(errors.at(0).offset_limit == 23); | |
| 1601 | JSONTEST_ASSERT(errors.at(0).message == "Bad escape sequence in string"); | |
| 1602 | } | |
| 1603 | ||
| 1604 | int main(int argc, const char* argv[]) { | |
| 1605 | JsonTest::Runner runner; | |
| 1606 | JSONTEST_REGISTER_FIXTURE(runner, ValueTest, checkNormalizeFloatingPointStr); | |
| 1607 | JSONTEST_REGISTER_FIXTURE(runner, ValueTest, memberCount); | |
| 1608 | JSONTEST_REGISTER_FIXTURE(runner, ValueTest, objects); | |
| 1609 | JSONTEST_REGISTER_FIXTURE(runner, ValueTest, arrays); | |
| 1610 | JSONTEST_REGISTER_FIXTURE(runner, ValueTest, null); | |
| 1611 | JSONTEST_REGISTER_FIXTURE(runner, ValueTest, strings); | |
| 1612 | JSONTEST_REGISTER_FIXTURE(runner, ValueTest, bools); | |
| 1613 | JSONTEST_REGISTER_FIXTURE(runner, ValueTest, integers); | |
| 1614 | JSONTEST_REGISTER_FIXTURE(runner, ValueTest, nonIntegers); | |
| 1615 | JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareNull); | |
| 1616 | JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareInt); | |
| 1617 | JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareUInt); | |
| 1618 | JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareDouble); | |
| 1619 | JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareString); | |
| 1620 | JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareBoolean); | |
| 1621 | JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareArray); | |
| 1622 | JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareObject); | |
| 1623 | JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareType); | |
| 1624 | JSONTEST_REGISTER_FIXTURE(runner, ValueTest, offsetAccessors); | |
| 1625 | JSONTEST_REGISTER_FIXTURE(runner, ValueTest, typeChecksThrowExceptions); | |
| 1626 | ||
| 1627 | JSONTEST_REGISTER_FIXTURE(runner, ReaderTest, parseWithNoErrors); | |
| 1628 | JSONTEST_REGISTER_FIXTURE( | |
| 1629 | runner, ReaderTest, parseWithNoErrorsTestingOffsets); | |
| 1630 | JSONTEST_REGISTER_FIXTURE(runner, ReaderTest, parseWithOneError); | |
| 1631 | JSONTEST_REGISTER_FIXTURE(runner, ReaderTest, parseChineseWithOneError); | |
| 1632 | JSONTEST_REGISTER_FIXTURE(runner, ReaderTest, parseWithDetailError); | |
| 1633 | ||
| 1634 | JSONTEST_REGISTER_FIXTURE(runner, WriterTest, dropNullPlaceholders); | |
| 1635 | ||
| 1636 | return runner.runCommandLine(argc, argv); | |
| 1637 | } |
| r0 | r242831 | |
|---|---|---|
| 1 | Import( 'env_testing buildUnitTests' ) | |
| 2 | ||
| 3 | buildUnitTests( env_testing, Split( """ | |
| 4 | main.cpp | |
| 5 | jsontest.cpp | |
| 6 | """ ), | |
| 7 | 'test_lib_json' ) | |
| 8 | ||
| 9 | # For 'check' to work, 'libs' must be built first. | |
| 10 | env_testing.Depends('test_lib_json', '#libs') |
| r0 | r242831 | |
|---|---|---|
| 1 | # removes all files created during testing | |
| 2 | import glob | |
| 3 | import os | |
| 4 | ||
| 5 | paths = [] | |
| 6 | for pattern in [ '*.actual', '*.actual-rewrite', '*.rewrite', '*.process-output' ]: | |
| 7 | paths += glob.glob( 'data/' + pattern ) | |
| 8 | ||
| 9 | for path in paths: | |
| 10 | os.unlink( path ) |
| r0 | r242831 | |
|---|---|---|
| 1 | [ 1 2 3] |
| r0 | r242831 | |
|---|---|---|
| 1 | .=[] |
| r0 | r242831 | |
|---|---|---|
| 1 | [] |
| r0 | r242831 | |
|---|---|---|
| 1 | .=[] | |
| 2 | .[0]=1 |
| r0 | r242831 | |
|---|---|---|
| 1 | [1] |
| r0 | r242831 | |
|---|---|---|
| 1 | .=[] | |
| 2 | .[0]=1 | |
| 3 | .[1]=2 | |
| 4 | .[2]=3 | |
| 5 | .[3]=4 | |
| 6 | .[4]=5 |
| r0 | r242831 | |
|---|---|---|
| 1 | [ 1, 2 , 3,4,5] |
| r0 | r242831 | |
|---|---|---|
| 1 | .=[] | |
| 2 | .[0]=1 | |
| 3 | .[1]="abc" | |
| 4 | .[2]=12.3 | |
| 5 | .[3]=-4 |
| r0 | r242831 | |
|---|---|---|
| 1 | [1, "abc" , 12.3, -4] |
| r0 | r242831 | |
|---|---|---|
| 1 | .=[] | |
| 2 | .[0]=1 | |
| 3 | .[1]=2 | |
| 4 | .[2]=3 | |
| 5 | .[3]=4 | |
| 6 | .[4]=5 | |
| 7 | .[5]=6 | |
| 8 | .[6]=7 | |
| 9 | .[7]=8 | |
| 10 | .[8]=9 | |
| 11 | .[9]=10 | |
| 12 | .[10]=11 | |
| 13 | .[11]=12 | |
| 14 | .[12]=13 | |
| 15 | .[13]=14 | |
| 16 | .[14]=15 | |
| 17 | .[15]=16 | |
| 18 | .[16]=17 | |
| 19 | .[17]=18 | |
| 20 | .[18]=19 | |
| 21 | .[19]=20 | |
| 22 | .[20]=21 | |
| 23 | .[21]=22 | |
| 24 | .[22]=23 | |
| 25 | .[23]=24 | |
| 26 | .[24]=25 | |
| 27 | .[25]=26 | |
| 28 | .[26]=27 | |
| 29 | .[27]=28 | |
| 30 | .[28]=29 | |
| 31 | .[29]=30 | |
| 32 | .[30]=31 | |
| 33 | .[31]=32 | |
| 34 | .[32]=33 | |
| 35 | .[33]=34 | |
| 36 | .[34]=35 | |
| 37 | .[35]=36 | |
| 38 | .[36]=37 | |
| 39 | .[37]=38 | |
| 40 | .[38]=39 | |
| 41 | .[39]=40 | |
| 42 | .[40]=41 | |
| 43 | .[41]=42 | |
| 44 | .[42]=43 | |
| 45 | .[43]=44 | |
| 46 | .[44]=45 | |
| 47 | .[45]=46 | |
| 48 | .[46]=47 | |
| 49 | .[47]=48 | |
| 50 | .[48]=49 | |
| 51 | .[49]=50 | |
| 52 | .[50]=51 | |
| 53 | .[51]=52 | |
| 54 | .[52]=53 | |
| 55 | .[53]=54 | |
| 56 | .[54]=55 | |
| 57 | .[55]=56 | |
| 58 | .[56]=57 | |
| 59 | .[57]=58 | |
| 60 | .[58]=59 | |
| 61 | .[59]=60 | |
| 62 | .[60]=61 | |
| 63 | .[61]=62 | |
| 64 | .[62]=63 | |
| 65 | .[63]=64 | |
| 66 | .[64]=65 | |
| 67 | .[65]=66 | |
| 68 | .[66]=67 | |
| 69 | .[67]=68 | |
| 70 | .[68]=69 | |
| 71 | .[69]=70 | |
| 72 | .[70]=71 | |
| 73 | .[71]=72 | |
| 74 | .[72]=73 | |
| 75 | .[73]=74 | |
| 76 | .[74]=75 | |
| 77 | .[75]=76 | |
| 78 | .[76]=77 | |
| 79 | .[77]=78 | |
| 80 | .[78]=79 | |
| 81 | .[79]=80 | |
| 82 | .[80]=81 | |
| 83 | .[81]=82 | |
| 84 | .[82]=83 | |
| 85 | .[83]=84 | |
| 86 | .[84]=85 | |
| 87 | .[85]=86 | |
| 88 | .[86]=87 | |
| 89 | .[87]=88 | |
| 90 | .[88]=89 | |
| 91 | .[89]=90 | |
| 92 | .[90]=91 | |
| 93 | .[91]=92 | |
| 94 | .[92]=93 | |
| 95 | .[93]=94 | |
| 96 | .[94]=95 | |
| 97 | .[95]=96 | |
| 98 | .[96]=97 | |
| 99 | .[97]=98 | |
| 100 | .[98]=99 |
| r0 | r242831 | |
|---|---|---|
| 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 |
| r0 | r242831 | |
|---|---|---|
| 1 | .=[] | |
| 2 | .[0]="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" | |
| 3 | .[1]="bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" | |
| 4 | .[2]="ccccccccccccccccccccccc" | |
| 5 | .[3]="dddddddddddddddddddddddddddddddddddddddddddddddddddd" |
| r0 | r242831 | |
|---|---|---|
| 1 | [ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", | |
| 2 | "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
| 3 | "ccccccccccccccccccccccc", | |
| 4 | "dddddddddddddddddddddddddddddddddddddddddddddddddddd" ] | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | .=[] | |
| 2 | .[0]=[] | |
| 3 | .[0][0]="A" | |
| 4 | .[0][1]=0 | |
| 5 | .[0][2]=1 | |
| 6 | .[0][3]=2 | |
| 7 | .[0][4]=3 | |
| 8 | .[0][5]=4 | |
| 9 | .[0][6]=5 | |
| 10 | .[0][7]=6 | |
| 11 | .[0][8]=7 | |
| 12 | .[0][9]=8 | |
| 13 | .[0][10]=9 | |
| 14 | .[0][11]=10 | |
| 15 | .[0][12]=11 | |
| 16 | .[0][13]=12 | |
| 17 | .[0][14]=13 | |
| 18 | .[0][15]=14 | |
| 19 | .[0][16]=15 | |
| 20 | .[0][17]=16 | |
| 21 | .[0][18]=17 | |
| 22 | .[0][19]=18 | |
| 23 | .[0][20]=19 | |
| 24 | .[0][21]=20 | |
| 25 | .[0][22]=21 | |
| 26 | .[0][23]=22 | |
| 27 | .[0][24]=23 | |
| 28 | .[0][25]=24 | |
| 29 | .[0][26]=25 | |
| 30 | .[0][27]=26 | |
| 31 | .[0][28]=27 | |
| 32 | .[0][29]=28 | |
| 33 | .[0][30]=29 | |
| 34 | .[0][31]=30 | |
| 35 | .[0][32]=31 | |
| 36 | .[0][33]=32 | |
| 37 | .[0][34]=33 | |
| 38 | .[0][35]=34 | |
| 39 | .[0][36]=35 | |
| 40 | .[0][37]=36 | |
| 41 | .[0][38]=37 | |
| 42 | .[0][39]=38 | |
| 43 | .[0][40]=39 | |
| 44 | .[0][41]=40 | |
| 45 | .[0][42]=41 | |
| 46 | .[0][43]=42 | |
| 47 | .[0][44]=43 | |
| 48 | .[0][45]=44 | |
| 49 | .[0][46]=45 | |
| 50 | .[0][47]=46 | |
| 51 | .[0][48]=47 | |
| 52 | .[0][49]=48 | |
| 53 | .[0][50]=49 | |
| 54 | .[0][51]=50 | |
| 55 | .[0][52]=51 | |
| 56 | .[0][53]=52 | |
| 57 | .[0][54]=53 | |
| 58 | .[0][55]=54 | |
| 59 | .[0][56]=55 | |
| 60 | .[0][57]=56 | |
| 61 | .[0][58]=57 | |
| 62 | .[0][59]=58 | |
| 63 | .[0][60]=59 | |
| 64 | .[0][61]=60 | |
| 65 | .[0][62]=61 | |
| 66 | .[0][63]=62 | |
| 67 | .[0][64]=63 | |
| 68 | .[0][65]=64 | |
| 69 | .[0][66]=65 | |
| 70 | .[0][67]=66 | |
| 71 | .[0][68]=67 | |
| 72 | .[0][69]=68 | |
| 73 | .[0][70]=69 | |
| 74 | .[0][71]=70 | |
| 75 | .[0][72]=71 | |
| 76 | .[0][73]=72 | |
| 77 | .[0][74]=73 | |
| 78 | .[0][75]=74 | |
| 79 | .[0][76]=75 | |
| 80 | .[0][77]=76 | |
| 81 | .[0][78]=77 | |
| 82 | .[0][79]=78 | |
| 83 | .[0][80]=79 | |
| 84 | .[0][81]=80 | |
| 85 | .[0][82]=81 | |
| 86 | .[0][83]=82 | |
| 87 | .[0][84]=83 | |
| 88 | .[0][85]=84 | |
| 89 | .[0][86]=85 | |
| 90 | .[0][87]=86 | |
| 91 | .[0][88]=87 | |
| 92 | .[0][89]=88 | |
| 93 | .[0][90]=89 | |
| 94 | .[0][91]=90 | |
| 95 | .[0][92]=91 | |
| 96 | .[0][93]=92 | |
| 97 | .[0][94]=93 | |
| 98 | .[0][95]=94 | |
| 99 | .[0][96]=95 | |
| 100 | .[0][97]=96 | |
| 101 | .[0][98]=97 | |
| 102 | .[0][99]=98 | |
| 103 | .[0][100]=99 | |
| 104 | .[0][101]=100 | |
| 105 | .[0][102]=101 | |
| 106 | .[0][103]=102 | |
| 107 | .[0][104]=103 | |
| 108 | .[0][105]=104 | |
| 109 | .[0][106]=105 | |
| 110 | .[0][107]=106 | |
| 111 | .[0][108]=107 | |
| 112 | .[0][109]=108 | |
| 113 | .[0][110]=109 | |
| 114 | .[0][111]=110 | |
| 115 | .[0][112]=111 | |
| 116 | .[0][113]=112 | |
| 117 | .[0][114]=113 | |
| 118 | .[0][115]=114 | |
| 119 | .[0][116]=115 | |
| 120 | .[0][117]=116 | |
| 121 | .[0][118]=117 | |
| 122 | .[0][119]=118 | |
| 123 | .[0][120]=119 | |
| 124 | .[0][121]=120 | |
| 125 | .[0][122]=121 | |
| 126 | .[0][123]=122 | |
| 127 | .[0][124]=123 | |
| 128 | .[0][125]=124 | |
| 129 | .[0][126]=125 | |
| 130 | .[0][127]=126 | |
| 131 | .[0][128]=127 | |
| 132 | .[0][129]=128 | |
| 133 | .[0][130]=129 | |
| 134 | .[0][131]=130 | |
| 135 | .[0][132]=131 | |
| 136 | .[0][133]=132 | |
| 137 | .[0][134]=133 | |
| 138 | .[0][135]=134 | |
| 139 | .[0][136]=135 | |
| 140 | .[0][137]=136 | |
| 141 | .[0][138]=137 | |
| 142 | .[0][139]=138 | |
| 143 | .[0][140]=139 | |
| 144 | .[0][141]=140 | |
| 145 | .[0][142]=141 | |
| 146 | .[0][143]=142 | |
| 147 | .[0][144]=143 | |
| 148 | .[0][145]=144 | |
| 149 | .[0][146]=145 | |
| 150 | .[0][147]=146 | |
| 151 | .[0][148]=147 | |
| 152 | .[0][149]=148 | |
| 153 | .[0][150]=149 | |
| 154 | .[0][151]=150 | |
| 155 | .[0][152]=151 | |
| 156 | .[0][153]=152 | |
| 157 | .[0][154]=153 | |
| 158 | .[0][155]=154 | |
| 159 | .[0][156]=155 | |
| 160 | .[0][157]=156 | |
| 161 | .[0][158]=157 | |
| 162 | .[0][159]=158 | |
| 163 | .[0][160]=159 | |
| 164 | .[0][161]=160 | |
| 165 | .[0][162]=161 | |
| 166 | .[0][163]=162 | |
| 167 | .[0][164]=163 | |
| 168 | .[0][165]=164 | |
| 169 | .[0][166]=165 | |
| 170 | .[0][167]=166 | |
| 171 | .[0][168]=167 | |
| 172 | .[0][169]=168 | |
| 173 | .[0][170]=169 | |
| 174 | .[0][171]=170 | |
| 175 | .[0][172]=171 | |
| 176 | .[0][173]=172 | |
| 177 | .[0][174]=173 | |
| 178 | .[0][175]=174 | |
| 179 | .[0][176]=175 | |
| 180 | .[0][177]=176 | |
| 181 | .[0][178]=177 | |
| 182 | .[0][179]=178 | |
| 183 | .[0][180]=179 | |
| 184 | .[0][181]=180 | |
| 185 | .[0][182]=181 | |
| 186 | .[0][183]=182 | |
| 187 | .[0][184]=183 | |
| 188 | .[0][185]=184 | |
| 189 | .[0][186]=185 | |
| 190 | .[0][187]=186 | |
| 191 | .[0][188]=187 | |
| 192 | .[0][189]=188 | |
| 193 | .[0][190]=189 | |
| 194 | .[0][191]=190 | |
| 195 | .[0][192]=191 | |
| 196 | .[0][193]=192 | |
| 197 | .[0][194]=193 | |
| 198 | .[0][195]=194 | |
| 199 | .[0][196]=195 | |
| 200 | .[0][197]=196 | |
| 201 | .[0][198]=197 | |
| 202 | .[0][199]=198 | |
| 203 | .[0][200]=199 | |
| 204 | .[0][201]=200 | |
| 205 | .[0][202]=201 | |
| 206 | .[0][203]=202 | |
| 207 | .[0][204]=203 | |
| 208 | .[0][205]=204 | |
| 209 | .[0][206]=205 | |
| 210 | .[0][207]=206 | |
| 211 | .[0][208]=207 | |
| 212 | .[0][209]=208 | |
| 213 | .[0][210]=209 | |
| 214 | .[0][211]=210 | |
| 215 | .[0][212]=211 | |
| 216 | .[0][213]=212 | |
| 217 | .[0][214]=213 | |
| 218 | .[0][215]=214 | |
| 219 | .[0][216]=215 | |
| 220 | .[0][217]=216 | |
| 221 | .[0][218]=217 | |
| 222 | .[0][219]=218 | |
| 223 | .[0][220]=219 | |
| 224 | .[0][221]=220 | |
| 225 | .[0][222]=221 | |
| 226 | .[0][223]=222 | |
| 227 | .[0][224]=223 | |
| 228 | .[0][225]=224 | |
| 229 | .[0][226]=225 | |
| 230 | .[0][227]=226 | |
| 231 | .[0][228]=227 | |
| 232 | .[0][229]=228 | |
| 233 | .[0][230]=229 | |
| 234 | .[0][231]=230 | |
| 235 | .[0][232]=231 | |
| 236 | .[0][233]=232 | |
| 237 | .[0][234]=233 | |
| 238 | .[0][235]=234 | |
| 239 | .[0][236]=235 | |
| 240 | .[0][237]=236 | |
| 241 | .[0][238]=237 | |
| 242 | .[0][239]=238 | |
| 243 | .[0][240]=239 | |
| 244 | .[0][241]=240 | |
| 245 | .[0][242]=241 | |
| 246 | .[0][243]=242 | |
| 247 | .[0][244]=243 | |
| 248 | .[0][245]=244 | |
| 249 | .[0][246]=245 | |
| 250 | .[0][247]=246 | |
| 251 | .[0][248]=247 | |
| 252 | .[0][249]=248 | |
| 253 | .[0][250]=249 | |
| 254 | .[0][251]=250 | |
| 255 | .[0][252]=251 | |
| 256 | .[0][253]=252 | |
| 257 | .[0][254]=253 | |
| 258 | .[0][255]=254 | |
| 259 | .[0][256]=255 | |
| 260 | .[0][257]=256 | |
| 261 | .[0][258]=257 | |
| 262 | .[0][259]=258 | |
| 263 | .[0][260]=259 | |
| 264 | .[0][261]=260 | |
| 265 | .[0][262]=261 | |
| 266 | .[0][263]=262 | |
| 267 | .[0][264]=263 | |
| 268 | .[0][265]=264 | |
| 269 | .[0][266]=265 | |
| 270 | .[0][267]=266 | |
| 271 | .[0][268]=267 | |
| 272 | .[0][269]=268 | |
| 273 | .[0][270]=269 | |
| 274 | .[0][271]=270 | |
| 275 | .[0][272]=271 | |
| 276 | .[0][273]=272 | |
| 277 | .[0][274]=273 | |
| 278 | .[0][275]=274 | |
| 279 | .[0][276]=275 | |
| 280 | .[0][277]=276 | |
| 281 | .[0][278]=277 | |
| 282 | .[0][279]=278 | |
| 283 | .[0][280]=279 | |
| 284 | .[0][281]=280 | |
| 285 | .[0][282]=281 | |
| 286 | .[0][283]=282 | |
| 287 | .[0][284]=283 | |
| 288 | .[0][285]=284 | |
| 289 | .[0][286]=285 | |
| 290 | .[0][287]=286 | |
| 291 | .[0][288]=287 | |
| 292 | .[0][289]=288 | |
| 293 | .[0][290]=289 | |
| 294 | .[0][291]=290 | |
| 295 | .[0][292]=291 | |
| 296 | .[0][293]=292 | |
| 297 | .[0][294]=293 | |
| 298 | .[0][295]=294 | |
| 299 | .[0][296]=295 | |
| 300 | .[0][297]=296 | |
| 301 | .[0][298]=297 | |
| 302 | .[0][299]=298 | |
| 303 | .[0][300]=299 | |
| 304 | .[0][301]=300 | |
| 305 | .[0][302]=301 | |
| 306 | .[0][303]=302 | |
| 307 | .[0][304]=303 | |
| 308 | .[0][305]=304 | |
| 309 | .[0][306]=305 | |
| 310 | .[0][307]=306 | |
| 311 | .[0][308]=307 | |
| 312 | .[0][309]=308 | |
| 313 | .[0][310]=309 | |
| 314 | .[0][311]=310 | |
| 315 | .[0][312]=311 | |
| 316 | .[0][313]=312 | |
| 317 | .[0][314]=313 | |
| 318 | .[0][315]=314 | |
| 319 | .[0][316]=315 | |
| 320 | .[0][317]=316 | |
| 321 | .[0][318]=317 | |
| 322 | .[0][319]=318 | |
| 323 | .[0][320]=319 | |
| 324 | .[0][321]=320 | |
| 325 | .[0][322]=321 | |
| 326 | .[0][323]=322 | |
| 327 | .[0][324]=323 | |
| 328 | .[0][325]=324 | |
| 329 | .[0][326]=325 | |
| 330 | .[0][327]=326 | |
| 331 | .[0][328]=327 | |
| 332 | .[0][329]=328 | |
| 333 | .[0][330]=329 | |
| 334 | .[0][331]=330 | |
| 335 | .[0][332]=331 | |
| 336 | .[0][333]=332 | |
| 337 | .[0][334]=333 | |
| 338 | .[0][335]=334 | |
| 339 | .[0][336]=335 | |
| 340 | .[0][337]=336 | |
| 341 | .[0][338]=337 | |
| 342 | .[0][339]=338 | |
| 343 | .[0][340]=339 | |
| 344 | .[0][341]=340 | |
| 345 | .[0][342]=341 | |
| 346 | .[0][343]=342 | |
| 347 | .[0][344]=343 | |
| 348 | .[0][345]=344 | |
| 349 | .[0][346]=345 | |
| 350 | .[0][347]=346 | |
| 351 | .[0][348]=347 | |
| 352 | .[0][349]=348 | |
| 353 | .[0][350]=349 | |
| 354 | .[0][351]=350 | |
| 355 | .[0][352]=351 | |
| 356 | .[0][353]=352 | |
| 357 | .[0][354]=353 | |
| 358 | .[0][355]=354 | |
| 359 | .[0][356]=355 | |
| 360 | .[0][357]=356 | |
| 361 | .[0][358]=357 | |
| 362 | .[0][359]=358 | |
| 363 | .[0][360]=359 | |
| 364 | .[0][361]=360 | |
| 365 | .[0][362]=361 | |
| 366 | .[0][363]=362 | |
| 367 | .[0][364]=363 | |
| 368 | .[0][365]=364 | |
| 369 | .[0][366]=365 | |
| 370 | .[0][367]=366 | |
| 371 | .[0][368]=367 | |
| 372 | .[0][369]=368 | |
| 373 | .[0][370]=369 | |
| 374 | .[0][371]=370 | |
| 375 | .[0][372]=371 | |
| 376 | .[0][373]=372 | |
| 377 | .[0][374]=373 | |
| 378 | .[0][375]=374 | |
| 379 | .[0][376]=375 | |
| 380 | .[0][377]=376 | |
| 381 | .[0][378]=377 | |
| 382 | .[0][379]=378 | |
| 383 | .[0][380]=379 | |
| 384 | .[0][381]=380 | |
| 385 | .[0][382]=381 | |
| 386 | .[0][383]=382 | |
| 387 | .[0][384]=383 | |
| 388 | .[0][385]=384 | |
| 389 | .[0][386]=385 | |
| 390 | .[0][387]=386 | |
| 391 | .[0][388]=387 | |
| 392 | .[0][389]=388 | |
| 393 | .[0][390]=389 | |
| 394 | .[0][391]=390 | |
| 395 | .[0][392]=391 | |
| 396 | .[0][393]=392 | |
| 397 | .[0][394]=393 | |
| 398 | .[0][395]=394 | |
| 399 | .[0][396]=395 | |
| 400 | .[0][397]=396 | |
| 401 | .[0][398]=397 | |
| 402 | .[0][399]=398 | |
| 403 | .[0][400]=399 | |
| 404 | .[0][401]=400 | |
| 405 | .[0][402]=401 | |
| 406 | .[0][403]=402 | |
| 407 | .[0][404]=403 | |
| 408 | .[0][405]=404 | |
| 409 | .[0][406]=405 | |
| 410 | .[0][407]=406 | |
| 411 | .[0][408]=407 | |
| 412 | .[0][409]=408 | |
| 413 | .[0][410]=409 | |
| 414 | .[0][411]=410 | |
| 415 | .[0][412]=411 | |
| 416 | .[0][413]=412 | |
| 417 | .[0][414]=413 | |
| 418 | .[0][415]=414 | |
| 419 | .[0][416]=415 | |
| 420 | .[0][417]=416 | |
| 421 | .[0][418]=417 | |
| 422 | .[0][419]=418 | |
| 423 | .[0][420]=419 | |
| 424 | .[0][421]=420 | |
| 425 | .[0][422]=421 | |
| 426 | .[0][423]=422 | |
| 427 | .[0][424]=423 | |
| 428 | .[0][425]=424 | |
| 429 | .[0][426]=425 | |
| 430 | .[0][427]=426 | |
| 431 | .[0][428]=427 | |
| 432 | .[0][429]=428 | |
| 433 | .[0][430]=429 | |
| 434 | .[0][431]=430 | |
| 435 | .[0][432]=431 | |
| 436 | .[0][433]=432 | |
| 437 | .[0][434]=433 | |
| 438 | .[0][435]=434 | |
| 439 | .[0][436]=435 | |
| 440 | .[0][437]=436 | |
| 441 | .[0][438]=437 | |
| 442 | .[0][439]=438 | |
| 443 | .[0][440]=439 | |
| 444 | .[0][441]=440 | |
| 445 | .[0][442]=441 | |
| 446 | .[0][443]=442 | |
| 447 | .[0][444]=443 | |
| 448 | .[0][445]=444 | |
| 449 | .[0][446]=445 | |
| 450 | .[0][447]=446 | |
| 451 | .[0][448]=447 | |
| 452 | .[0][449]=448 | |
| 453 | .[0][450]=449 | |
| 454 | .[0][451]=450 | |
| 455 | .[0][452]=451 | |
| 456 | .[0][453]=452 | |
| 457 | .[0][454]=453 | |
| 458 | .[0][455]=454 | |
| 459 | .[0][456]=455 | |
| 460 | .[0][457]=456 | |
| 461 | .[0][458]=457 | |
| 462 | .[0][459]=458 | |
| 463 | .[0][460]=459 | |
| 464 | .[0][461]=460 | |
| 465 | .[0][462]=461 | |
| 466 | .[0][463]=462 | |
| 467 | .[0][464]=463 | |
| 468 | .[0][465]=464 | |
| 469 | .[0][466]=465 | |
| 470 | .[0][467]=466 | |
| 471 | .[0][468]=467 | |
| 472 | .[0][469]=468 | |
| 473 | .[0][470]=469 | |
| 474 | .[0][471]=470 | |
| 475 | .[0][472]=471 | |
| 476 | .[0][473]=472 | |
| 477 | .[0][474]=473 | |
| 478 | .[0][475]=474 | |
| 479 | .[0][476]=475 | |
| 480 | .[0][477]=476 | |
| 481 | .[0][478]=477 | |
| 482 | .[0][479]=478 | |
| 483 | .[0][480]=479 | |
| 484 | .[0][481]=480 | |
| 485 | .[0][482]=481 | |
| 486 | .[0][483]=482 | |
| 487 | .[0][484]=483 | |
| 488 | .[0][485]=484 | |
| 489 | .[0][486]=485 | |
| 490 | .[0][487]=486 | |
| 491 | .[0][488]=487 | |
| 492 | .[0][489]=488 | |
| 493 | .[0][490]=489 | |
| 494 | .[0][491]=490 | |
| 495 | .[0][492]=491 | |
| 496 | .[0][493]=492 | |
| 497 | .[0][494]=493 | |
| 498 | .[0][495]=494 | |
| 499 | .[0][496]=495 | |
| 500 | .[0][497]=496 | |
| 501 | .[0][498]=497 | |
| 502 | .[0][499]=498 | |
| 503 | .[0][500]=499 | |
| 504 | .[0][501]=500 | |
| 505 | .[0][502]=501 | |
| 506 | .[0][503]=502 | |
| 507 | .[0][504]=503 | |
| 508 | .[0][505]=504 | |
| 509 | .[0][506]=505 | |
| 510 | .[0][507]=506 | |
| 511 | .[0][508]=507 | |
| 512 | .[0][509]=508 | |
| 513 | .[0][510]=509 | |
| 514 | .[0][511]=510 | |
| 515 | .[0][512]=511 | |
| 516 | .[0][513]=512 | |
| 517 | .[0][514]=513 | |
| 518 | .[0][515]=514 | |
| 519 | .[0][516]=515 | |
| 520 | .[0][517]=516 | |
| 521 | .[0][518]=517 | |
| 522 | .[0][519]=518 | |
| 523 | .[0][520]=519 | |
| 524 | .[0][521]=520 | |
| 525 | .[0][522]=521 | |
| 526 | .[0][523]=522 | |
| 527 | .[0][524]=523 | |
| 528 | .[0][525]=524 | |
| 529 | .[0][526]=525 | |
| 530 | .[0][527]=526 | |
| 531 | .[0][528]=527 | |
| 532 | .[0][529]=528 | |
| 533 | .[0][530]=529 | |
| 534 | .[0][531]=530 | |
| 535 | .[0][532]=531 | |
| 536 | .[0][533]=532 | |
| 537 | .[0][534]=533 | |
| 538 | .[0][535]=534 | |
| 539 | .[0][536]=535 | |
| 540 | .[0][537]=536 | |
| 541 | .[0][538]=537 | |
| 542 | .[0][539]=538 | |
| 543 | .[0][540]=539 | |
| 544 | .[0][541]=540 | |
| 545 | .[0][542]=541 | |
| 546 | .[0][543]=542 | |
| 547 | .[0][544]=543 | |
| 548 | .[0][545]=544 | |
| 549 | .[0][546]=545 | |
| 550 | .[0][547]=546 | |
| 551 | .[0][548]=547 | |
| 552 | .[0][549]=548 | |
| 553 | .[0][550]=549 | |
| 554 | .[0][551]=550 | |
| 555 | .[0][552]=551 | |
| 556 | .[0][553]=552 | |
| 557 | .[0][554]=553 | |
| 558 | .[0][555]=554 | |
| 559 | .[0][556]=555 | |
| 560 | .[0][557]=556 | |
| 561 | .[0][558]=557 | |
| 562 | .[0][559]=558 | |
| 563 | .[0][560]=559 | |
| 564 | .[0][561]=560 | |
| 565 | .[0][562]=561 | |
| 566 | .[0][563]=562 | |
| 567 | .[0][564]=563 | |
| 568 | .[0][565]=564 | |
| 569 | .[0][566]=565 | |
| 570 | .[0][567]=566 | |
| 571 | .[0][568]=567 | |
| 572 | .[0][569]=568 | |
| 573 | .[0][570]=569 | |
| 574 | .[0][571]=570 | |
| 575 | .[0][572]=571 | |
| 576 | .[0][573]=572 | |
| 577 | .[0][574]=573 | |
| 578 | .[0][575]=574 | |
| 579 | .[0][576]=575 | |
| 580 | .[0][577]=576 | |
| 581 | .[0][578]=577 | |
| 582 | .[0][579]=578 | |
| 583 | .[0][580]=579 | |
| 584 | .[0][581]=580 | |
| 585 | .[0][582]=581 | |
| 586 | .[0][583]=582 | |
| 587 | .[0][584]=583 | |
| 588 | .[0][585]=584 | |
| 589 | .[0][586]=585 | |
| 590 | .[0][587]=586 | |
| 591 | .[0][588]=587 | |
| 592 | .[0][589]=588 | |
| 593 | .[0][590]=589 | |
| 594 | .[0][591]=590 | |
| 595 | .[0][592]=591 | |
| 596 | .[0][593]=592 | |
| 597 | .[0][594]=593 | |
| 598 | .[0][595]=594 | |
| 599 | .[0][596]=595 | |
| 600 | .[0][597]=596 | |
| 601 | .[0][598]=597 | |
| 602 | .[0][599]=598 | |
| 603 | .[0][600]=599 | |
| 604 | .[0][601]=600 | |
| 605 | .[0][602]=601 | |
| 606 | .[0][603]=602 | |
| 607 | .[0][604]=603 | |
| 608 | .[0][605]=604 | |
| 609 | .[0][606]=605 | |
| 610 | .[0][607]=606 | |
| 611 | .[0][608]=607 | |
| 612 | .[0][609]=608 | |
| 613 | .[0][610]=609 | |
| 614 | .[0][611]=610 | |
| 615 | .[0][612]=611 | |
| 616 | .[0][613]=612 | |
| 617 | .[0][614]=613 | |
| 618 | .[0][615]=614 | |
| 619 | .[0][616]=615 | |
| 620 | .[0][617]=616 | |
| 621 | .[0][618]=617 | |
| 622 | .[0][619]=618 | |
| 623 | .[0][620]=619 | |
| 624 | .[0][621]=620 | |
| 625 | .[0][622]=621 | |
| 626 | .[0][623]=622 | |
| 627 | .[0][624]=623 | |
| 628 | .[0][625]=624 | |
| 629 | .[0][626]=625 | |
| 630 | .[0][627]=626 | |
| 631 | .[0][628]=627 | |
| 632 | .[0][629]=628 | |
| 633 | .[0][630]=629 | |
| 634 | .[0][631]=630 | |
| 635 | .[0][632]=631 | |
| 636 | .[0][633]=632 | |
| 637 | .[0][634]=633 | |
| 638 | .[0][635]=634 | |
| 639 | .[0][636]=635 | |
| 640 | .[0][637]=636 | |
| 641 | .[0][638]=637 | |
| 642 | .[0][639]=638 | |
| 643 | .[0][640]=639 | |
| 644 | .[0][641]=640 | |
| 645 | .[0][642]=641 | |
| 646 | .[0][643]=642 | |
| 647 | .[0][644]=643 | |
| 648 | .[0][645]=644 | |
| 649 | .[0][646]=645 | |
| 650 | .[0][647]=646 | |
| 651 | .[0][648]=647 | |
| 652 | .[0][649]=648 | |
| 653 | .[0][650]=649 | |
| 654 | .[0][651]=650 | |
| 655 | .[0][652]=651 | |
| 656 | .[0][653]=652 | |
| 657 | .[0][654]=653 | |
| 658 | .[0][655]=654 | |
| 659 | .[0][656]=655 | |
| 660 | .[0][657]=656 | |
| 661 | .[0][658]=657 | |
| 662 | .[0][659]=658 | |
| 663 | .[0][660]=659 | |
| 664 | .[0][661]=660 | |
| 665 | .[0][662]=661 | |
| 666 | .[0][663]=662 | |
| 667 | .[0][664]=663 | |
| 668 | .[0][665]=664 | |
| 669 | .[0][666]=665 | |
| 670 | .[0][667]=666 | |
| 671 | .[0][668]=667 | |
| 672 | .[0][669]=668 | |
| 673 | .[0][670]=669 | |
| 674 | .[0][671]=670 | |
| 675 | .[0][672]=671 | |
| 676 | .[0][673]=672 | |
| 677 | .[0][674]=673 | |
| 678 | .[0][675]=674 | |
| 679 | .[0][676]=675 | |
| 680 | .[0][677]=676 | |
| 681 | .[0][678]=677 | |
| 682 | .[0][679]=678 | |
| 683 | .[0][680]=679 | |
| 684 | .[0][681]=680 | |
| 685 | .[0][682]=681 | |
| 686 | .[0][683]=682 | |
| 687 | .[0][684]=683 | |
| 688 | .[0][685]=684 | |
| 689 | .[0][686]=685 | |
| 690 | .[0][687]=686 | |
| 691 | .[0][688]=687 | |
| 692 | .[0][689]=688 | |
| 693 | .[0][690]=689 | |
| 694 | .[0][691]=690 | |
| 695 | .[0][692]=691 | |
| 696 | .[0][693]=692 | |
| 697 | .[0][694]=693 | |
| 698 | .[0][695]=694 | |
| 699 | .[0][696]=695 | |
| 700 | .[0][697]=696 | |
| 701 | .[0][698]=697 | |
| 702 | .[0][699]=698 | |
| 703 | .[0][700]=699 | |
| 704 | .[0][701]=700 | |
| 705 | .[0][702]=701 | |
| 706 | .[0][703]=702 | |
| 707 | .[0][704]=703 | |
| 708 | .[0][705]=704 | |
| 709 | .[0][706]=705 | |
| 710 | .[0][707]=706 | |
| 711 | .[0][708]=707 | |
| 712 | .[0][709]=708 | |
| 713 | .[0][710]=709 | |
| 714 | .[0][711]=710 | |
| 715 | .[0][712]=711 | |
| 716 | .[0][713]=712 | |
| 717 | .[0][714]=713 | |
| 718 | .[0][715]=714 | |
| 719 | .[0][716]=715 | |
| 720 | .[0][717]=716 | |
| 721 | .[0][718]=717 | |
| 722 | .[0][719]=718 | |
| 723 | .[0][720]=719 | |
| 724 | .[0][721]=720 | |
| 725 | .[0][722]=721 | |
| 726 | .[0][723]=722 | |
| 727 | .[0][724]=723 | |
| 728 | .[0][725]=724 | |
| 729 | .[0][726]=725 | |
| 730 | .[0][727]=726 | |
| 731 | .[0][728]=727 | |
| 732 | .[0][729]=728 | |
| 733 | .[0][730]=729 | |
| 734 | .[0][731]=730 | |
| 735 | .[0][732]=731 | |
| 736 | .[0][733]=732 | |
| 737 | .[0][734]=733 | |
| 738 | .[0][735]=734 | |
| 739 | .[0][736]=735 | |
| 740 | .[0][737]=736 | |
| 741 | .[0][738]=737 | |
| 742 | .[0][739]=738 | |
| 743 | .[0][740]=739 | |
| 744 | .[0][741]=740 | |
| 745 | .[0][742]=741 | |
| 746 | .[0][743]=742 | |
| 747 | .[0][744]=743 | |
| 748 | .[0][745]=744 | |
| 749 | .[0][746]=745 | |
| 750 | .[0][747]=746 | |
| 751 | .[0][748]=747 | |
| 752 | .[0][749]=748 | |
| 753 | .[0][750]=749 | |
| 754 | .[0][751]=750 | |
| 755 | .[0][752]=751 | |
| 756 | .[0][753]=752 | |
| 757 | .[0][754]=753 | |
| 758 | .[0][755]=754 | |
| 759 | .[0][756]=755 | |
| 760 | .[0][757]=756 | |
| 761 | .[0][758]=757 | |
| 762 | .[0][759]=758 | |
| 763 | .[0][760]=759 | |
| 764 | .[0][761]=760 | |
| 765 | .[0][762]=761 | |
| 766 | .[0][763]=762 | |
| 767 | .[0][764]=763 | |
| 768 | .[0][765]=764 | |
| 769 | .[0][766]=765 | |
| 770 | .[0][767]=766 | |
| 771 | .[0][768]=767 | |
| 772 | .[0][769]=768 | |
| 773 | .[0][770]=769 | |
| 774 | .[0][771]=770 | |
| 775 | .[0][772]=771 | |
| 776 | .[0][773]=772 | |
| 777 | .[0][774]=773 | |
| 778 | .[0][775]=774 | |
| 779 | .[0][776]=775 | |
| 780 | .[0][777]=776 | |
| 781 | .[0][778]=777 | |
| 782 | .[0][779]=778 | |
| 783 | .[0][780]=779 | |
| 784 | .[0][781]=780 | |
| 785 | .[0][782]=781 | |
| 786 | .[0][783]=782 | |
| 787 | .[0][784]=783 | |
| 788 | .[0][785]=784 | |
| 789 | .[0][786]=785 | |
| 790 | .[0][787]=786 | |
| 791 | .[0][788]=787 | |
| 792 | .[0][789]=788 | |
| 793 | .[0][790]=789 | |
| 794 | .[0][791]=790 | |
| 795 | .[0][792]=791 | |
| 796 | .[0][793]=792 | |
| 797 | .[0][794]=793 | |
| 798 | .[0][795]=794 | |
| 799 | .[0][796]=795 | |
| 800 | .[0][797]=796 | |
| 801 | .[0][798]=797 | |
| 802 | .[0][799]=798 | |
| 803 | .[0][800]=799 | |
| 804 | .[0][801]=800 | |
| 805 | .[0][802]=801 | |
| 806 | .[0][803]=802 | |
| 807 | .[0][804]=803 | |
| 808 | .[0][805]=804 | |
| 809 | .[0][806]=805 | |
| 810 | .[0][807]=806 | |
| 811 | .[0][808]=807 | |
| 812 | .[0][809]=808 | |
| 813 | .[0][810]=809 | |
| 814 | .[0][811]=810 | |
| 815 | .[0][812]=811 | |
| 816 | .[0][813]=812 | |
| 817 | .[0][814]=813 | |
| 818 | .[0][815]=814 | |
| 819 | .[0][816]=815 | |
| 820 | .[0][817]=816 | |
| 821 | .[0][818]=817 | |
| 822 | .[0][819]=818 | |
| 823 | .[0][820]=819 | |
| 824 | .[0][821]=820 | |
| 825 | .[0][822]=821 | |
| 826 | .[0][823]=822 | |
| 827 | .[0][824]=823 | |
| 828 | .[0][825]=824 | |
| 829 | .[0][826]=825 | |
| 830 | .[0][827]=826 | |
| 831 | .[0][828]=827 | |
| 832 | .[0][829]=828 | |
| 833 | .[0][830]=829 | |
| 834 | .[0][831]=830 | |
| 835 | .[0][832]=831 | |
| 836 | .[0][833]=832 | |
| 837 | .[0][834]=833 | |
| 838 | .[0][835]=834 | |
| 839 | .[0][836]=835 | |
| 840 | .[0][837]=836 | |
| 841 | .[0][838]=837 | |
| 842 | .[0][839]=838 | |
| 843 | .[0][840]=839 | |
| 844 | .[0][841]=840 | |
| 845 | .[0][842]=841 | |
| 846 | .[0][843]=842 | |
| 847 | .[0][844]=843 | |
| 848 | .[0][845]=844 | |
| 849 | .[0][846]=845 | |
| 850 | .[0][847]=846 | |
| 851 | .[0][848]=847 | |
| 852 | .[0][849]=848 | |
| 853 | .[0][850]=849 | |
| 854 | .[0][851]=850 | |
| 855 | .[0][852]=851 | |
| 856 | .[0][853]=852 | |
| 857 | .[0][854]=853 | |
| 858 | .[0][855]=854 | |
| 859 | .[0][856]=855 | |
| 860 | .[0][857]=856 | |
| 861 | .[0][858]=857 | |
| 862 | .[0][859]=858 | |
| 863 | .[0][860]=859 | |
| 864 | .[0][861]=860 | |
| 865 | .[0][862]=861 | |
| 866 | .[0][863]=862 | |
| 867 | .[0][864]=863 | |
| 868 | .[0][865]=864 | |
| 869 | .[0][866]=865 | |
| 870 | .[0][867]=866 | |
| 871 | .[0][868]=867 | |
| 872 | .[0][869]=868 | |
| 873 | .[0][870]=869 | |
| 874 | .[0][871]=870 | |
| 875 | .[0][872]=871 | |
| 876 | .[0][873]=872 | |
| 877 | .[0][874]=873 | |
| 878 | .[0][875]=874 | |
| 879 | .[0][876]=875 | |
| 880 | .[0][877]=876 | |
| 881 | .[0][878]=877 | |
| 882 | .[0][879]=878 | |
| 883 | .[0][880]=879 | |
| 884 | .[0][881]=880 | |
| 885 | .[0][882]=881 | |
| 886 | .[0][883]=882 | |
| 887 | .[0][884]=883 | |
| 888 | .[0][885]=884 | |
| 889 | .[0][886]=885 | |
| 890 | .[0][887]=886 | |
| 891 | .[0][888]=887 | |
| 892 | .[0][889]=888 | |
| 893 | .[0][890]=889 | |
| 894 | .[0][891]=890 | |
| 895 | .[0][892]=891 | |
| 896 | .[0][893]=892 | |
| 897 | .[0][894]=893 | |
| 898 | .[0][895]=894 | |
| 899 | .[0][896]=895 | |
| 900 | .[0][897]=896 | |
| 901 | .[0][898]=897 | |
| 902 | .[0][899]=898 | |
| 903 | .[0][900]=899 | |
| 904 | .[0][901]=900 | |
| 905 | .[0][902]=901 | |
| 906 | .[0][903]=902 | |
| 907 | .[0][904]=903 | |
| 908 | .[0][905]=904 | |
| 909 | .[0][906]=905 | |
| 910 | .[0][907]=906 | |
| 911 | .[0][908]=907 | |
| 912 | .[0][909]=908 | |
| 913 | .[0][910]=909 | |
| 914 | .[0][911]=910 | |
| 915 | .[0][912]=911 | |
| 916 | .[0][913]=912 | |
| 917 | .[0][914]=913 | |
| 918 | .[0][915]=914 | |
| 919 | .[0][916]=915 | |
| 920 | .[0][917]=916 | |
| 921 | .[0][918]=917 | |
| 922 | .[0][919]=918 | |
| 923 | .[0][920]=919 | |
| 924 | .[0][921]=920 | |
| 925 | .[0][922]=921 | |
| 926 | .[0][923]=922 | |
| 927 | .[0][924]=923 | |
| 928 | .[0][925]=924 | |
| 929 | .[0][926]=925 | |
| 930 | .[0][927]=926 | |
| 931 | .[0][928]=927 | |
| 932 | .[0][929]=928 | |
| 933 | .[0][930]=929 | |
| 934 | .[0][931]=930 | |
| 935 | .[0][932]=931 | |
| 936 | .[0][933]=932 | |
| 937 | .[0][934]=933 | |
| 938 | .[0][935]=934 | |
| 939 | .[0][936]=935 | |
| 940 | .[0][937]=936 | |
| 941 | .[0][938]=937 | |
| 942 | .[0][939]=938 | |
| 943 | .[0][940]=939 | |
| 944 | .[0][941]=940 | |
| 945 | .[0][942]=941 | |
| 946 | .[0][943]=942 | |
| 947 | .[0][944]=943 | |
| 948 | .[0][945]=944 | |
| 949 | .[0][946]=945 | |
| 950 | .[0][947]=946 | |
| 951 | .[0][948]=947 | |
| 952 | .[0][949]=948 | |
| 953 | .[0][950]=949 | |
| 954 | .[0][951]=950 | |
| 955 | .[0][952]=951 | |
| 956 | .[0][953]=952 | |
| 957 | .[0][954]=953 | |
| 958 | .[0][955]=954 | |
| 959 | .[0][956]=955 | |
| 960 | .[0][957]=956 | |
| 961 | .[0][958]=957 | |
| 962 | .[0][959]=958 | |
| 963 | .[0][960]=959 | |
| 964 | .[0][961]=960 | |
| 965 | .[0][962]=961 | |
| 966 | .[0][963]=962 | |
| 967 | .[0][964]=963 | |
| 968 | .[0][965]=964 | |
| 969 | .[0][966]=965 | |
| 970 | .[0][967]=966 | |
| 971 | .[0][968]=967 | |
| 972 | .[0][969]=968 | |
| 973 | .[0][970]=969 | |
| 974 | .[0][971]=970 | |
| 975 | .[0][972]=971 | |
| 976 | .[0][973]=972 | |
| 977 | .[0][974]=973 | |
| 978 | .[0][975]=974 | |
| 979 | .[0][976]=975 | |
| 980 | .[0][977]=976 | |
| 981 | .[0][978]=977 | |
| 982 | .[0][979]=978 | |
| 983 | .[0][980]=979 | |
| 984 | .[0][981]=980 | |
| 985 | .[0][982]=981 | |
| 986 | .[0][983]=982 | |
| 987 | .[0][984]=983 | |
| 988 | .[0][985]=984 | |
| 989 | .[0][986]=985 | |
| 990 | .[0][987]=986 | |
| 991 | .[0][988]=987 | |
| 992 | .[0][989]=988 | |
| 993 | .[0][990]=989 | |
| 994 | .[0][991]=990 | |
| 995 | .[0][992]=991 | |
| 996 | .[0][993]=992 | |
| 997 | .[0][994]=993 | |
| 998 | .[0][995]=994 | |
| 999 | .[0][996]=995 | |
| 1000 | .[0][997]=996 | |
| 1001 | .[0][998]=997 | |
| 1002 | .[0][999]=998 | |
| 1003 | .[0][1000]=999 | |
| 1004 | .[0][1001]=1000 | |
| 1005 | .[0][1002]=1001 | |
| 1006 | .[0][1003]=1002 | |
| 1007 | .[0][1004]=1003 | |
| 1008 | .[0][1005]=1004 | |
| 1009 | .[0][1006]=1005 | |
| 1010 | .[0][1007]=1006 | |
| 1011 | .[0][1008]=1007 | |
| 1012 | .[0][1009]=1008 | |
| 1013 | .[0][1010]=1009 | |
| 1014 | .[0][1011]=1010 | |
| 1015 | .[0][1012]=1011 | |
| 1016 | .[0][1013]=1012 | |
| 1017 | .[0][1014]=1013 | |
| 1018 | .[0][1015]=1014 | |
| 1019 | .[0][1016]=1015 | |
| 1020 | .[0][1017]=1016 | |
| 1021 | .[0][1018]=1017 | |
| 1022 | .[0][1019]=1018 | |
| 1023 | .[0][1020]=1019 | |
| 1024 | .[0][1021]=1020 | |
| 1025 | .[0][1022]=1021 | |
| 1026 | .[0][1023]=1022 | |
| 1027 | .[0][1024]=1023 | |
| 1028 | .[0][1025]=1024 | |
| 1029 | .[0][1026]=1025 | |
| 1030 | .[0][1027]=1026 | |
| 1031 | .[0][1028]=1027 | |
| 1032 | .[0][1029]=1028 | |
| 1033 | .[0][1030]=1029 | |
| 1034 | .[0][1031]=1030 | |
| 1035 | .[0][1032]=1031 | |
| 1036 | .[0][1033]=1032 | |
| 1037 | .[0][1034]=1033 | |
| 1038 | .[0][1035]=1034 | |
| 1039 | .[0][1036]=1035 | |
| 1040 | .[0][1037]=1036 | |
| 1041 | .[0][1038]=1037 | |
| 1042 | .[0][1039]=1038 | |
| 1043 | .[0][1040]=1039 | |
| 1044 | .[0][1041]=1040 | |
| 1045 | .[0][1042]=1041 | |
| 1046 | .[0][1043]=1042 | |
| 1047 | .[0][1044]=1043 | |
| 1048 | .[0][1045]=1044 | |
| 1049 | .[0][1046]=1045 | |
| 1050 | .[0][1047]=1046 | |
| 1051 | .[0][1048]=1047 | |
| 1052 | .[0][1049]=1048 | |
| 1053 | .[0][1050]=1049 | |
| 1054 | .[0][1051]=1050 | |
| 1055 | .[0][1052]=1051 | |
| 1056 | .[0][1053]=1052 | |
| 1057 | .[0][1054]=1053 | |
| 1058 | .[0][1055]=1054 | |
| 1059 | .[0][1056]=1055 | |
| 1060 | .[0][1057]=1056 | |
| 1061 | .[0][1058]=1057 | |
| 1062 | .[0][1059]=1058 | |
| 1063 | .[0][1060]=1059 | |
| 1064 | .[0][1061]=1060 | |
| 1065 | .[0][1062]=1061 | |
| 1066 | .[0][1063]=1062 | |
| 1067 | .[0][1064]=1063 | |
| 1068 | .[0][1065]=1064 | |
| 1069 | .[0][1066]=1065 | |
| 1070 | .[0][1067]=1066 | |
| 1071 | .[0][1068]=1067 | |
| 1072 | .[0][1069]=1068 | |
| 1073 | .[0][1070]=1069 | |
| 1074 | .[0][1071]=1070 | |
| 1075 | .[0][1072]=1071 | |
| 1076 | .[0][1073]=1072 | |
| 1077 | .[0][1074]=1073 | |
| 1078 | .[0][1075]=1074 | |
| 1079 | .[0][1076]=1075 | |
| 1080 | .[0][1077]=1076 | |
| 1081 | .[0][1078]=1077 | |
| 1082 | .[0][1079]=1078 | |
| 1083 | .[0][1080]=1079 | |
| 1084 | .[0][1081]=1080 | |
| 1085 | .[0][1082]=1081 | |
| 1086 | .[0][1083]=1082 | |
| 1087 | .[0][1084]=1083 | |
| 1088 | .[0][1085]=1084 | |
| 1089 | .[0][1086]=1085 | |
| 1090 | .[0][1087]=1086 | |
| 1091 | .[0][1088]=1087 | |
| 1092 | .[0][1089]=1088 | |
| 1093 | .[0][1090]=1089 | |
| 1094 | .[0][1091]=1090 | |
| 1095 | .[0][1092]=1091 | |
| 1096 | .[0][1093]=1092 | |
| 1097 | .[0][1094]=1093 | |
| 1098 | .[0][1095]=1094 | |
| 1099 | .[0][1096]=1095 | |
| 1100 | .[0][1097]=1096 | |
| 1101 | .[0][1098]=1097 | |
| 1102 | .[0][1099]=1098 | |
| 1103 | .[0][1100]=1099 | |
| 1104 | .[0][1101]=1100 | |
| 1105 | .[0][1102]=1101 | |
| 1106 | .[0][1103]=1102 | |
| 1107 | .[0][1104]=1103 | |
| 1108 | .[0][1105]=1104 | |
| 1109 | .[0][1106]=1105 | |
| 1110 | .[0][1107]=1106 | |
| 1111 | .[0][1108]=1107 | |
| 1112 | .[0][1109]=1108 | |
| 1113 | .[0][1110]=1109 | |
| 1114 | .[0][1111]=1110 | |
| 1115 | .[0][1112]=1111 | |
| 1116 | .[0][1113]=1112 | |
| 1117 | .[0][1114]=1113 | |
| 1118 | .[0][1115]=1114 | |
| 1119 | .[0][1116]=1115 | |
| 1120 | .[0][1117]=1116 | |
| 1121 | .[0][1118]=1117 | |
| 1122 | .[0][1119]=1118 | |
| 1123 | .[0][1120]=1119 | |
| 1124 | .[0][1121]=1120 | |
| 1125 | .[0][1122]=1121 | |
| 1126 | .[0][1123]=1122 | |
| 1127 | .[0][1124]=1123 | |
| 1128 | .[0][1125]=1124 | |
| 1129 | .[0][1126]=1125 | |
| 1130 | .[0][1127]=1126 | |
| 1131 | .[0][1128]=1127 | |
| 1132 | .[0][1129]=1128 | |
| 1133 | .[0][1130]=1129 | |
| 1134 | .[0][1131]=1130 | |
| 1135 | .[0][1132]=1131 | |
| 1136 | .[0][1133]=1132 | |
| 1137 | .[0][1134]=1133 | |
| 1138 | .[0][1135]=1134 | |
| 1139 | .[0][1136]=1135 | |
| 1140 | .[0][1137]=1136 | |
| 1141 | .[0][1138]=1137 | |
| 1142 | .[0][1139]=1138 | |
| 1143 | .[0][1140]=1139 | |
| 1144 | .[0][1141]=1140 | |
| 1145 | .[0][1142]=1141 | |
| 1146 | .[0][1143]=1142 | |
| 1147 | .[0][1144]=1143 | |
| 1148 | .[0][1145]=1144 | |
| 1149 | .[0][1146]=1145 | |
| 1150 | .[0][1147]=1146 | |
| 1151 | .[0][1148]=1147 | |
| 1152 | .[0][1149]=1148 | |
| 1153 | .[0][1150]=1149 | |
| 1154 | .[0][1151]=1150 | |
| 1155 | .[0][1152]=1151 | |
| 1156 | .[0][1153]=1152 | |
| 1157 | .[0][1154]=1153 | |
| 1158 | .[0][1155]=1154 | |
| 1159 | .[0][1156]=1155 | |
| 1160 | .[0][1157]=1156 | |
| 1161 | .[0][1158]=1157 | |
| 1162 | .[0][1159]=1158 | |
| 1163 | .[0][1160]=1159 | |
| 1164 | .[0][1161]=1160 | |
| 1165 | .[0][1162]=1161 | |
| 1166 | .[0][1163]=1162 | |
| 1167 | .[0][1164]=1163 | |
| 1168 | .[0][1165]=1164 | |
| 1169 | .[0][1166]=1165 | |
| 1170 | .[0][1167]=1166 | |
| 1171 | .[0][1168]=1167 | |
| 1172 | .[0][1169]=1168 | |
| 1173 | .[0][1170]=1169 | |
| 1174 | .[0][1171]=1170 | |
| 1175 | .[0][1172]=1171 | |
| 1176 | .[0][1173]=1172 | |
| 1177 | .[0][1174]=1173 | |
| 1178 | .[0][1175]=1174 | |
| 1179 | .[0][1176]=1175 | |
| 1180 | .[0][1177]=1176 | |
| 1181 | .[0][1178]=1177 | |
| 1182 | .[0][1179]=1178 | |
| 1183 | .[0][1180]=1179 | |
| 1184 | .[0][1181]=1180 | |
| 1185 | .[0][1182]=1181 | |
| 1186 | .[0][1183]=1182 | |
| 1187 | .[0][1184]=1183 | |
| 1188 | .[0][1185]=1184 | |
| 1189 | .[0][1186]=1185 | |
| 1190 | .[0][1187]=1186 | |
| 1191 | .[0][1188]=1187 | |
| 1192 | .[0][1189]=1188 | |
| 1193 | .[0][1190]=1189 | |
| 1194 | .[0][1191]=1190 | |
| 1195 | .[0][1192]=1191 | |
| 1196 | .[0][1193]=1192 | |
| 1197 | .[0][1194]=1193 | |
| 1198 | .[0][1195]=1194 | |
| 1199 | .[0][1196]=1195 | |
| 1200 | .[0][1197]=1196 | |
| 1201 | .[0][1198]=1197 | |
| 1202 | .[0][1199]=1198 | |
| 1203 | .[0][1200]=1199 | |
| 1204 | .[0][1201]=1200 | |
| 1205 | .[0][1202]=1201 | |
| 1206 | .[0][1203]=1202 | |
| 1207 | .[0][1204]=1203 | |
| 1208 | .[0][1205]=1204 | |
| 1209 | .[0][1206]=1205 | |
| 1210 | .[0][1207]=1206 | |
| 1211 | .[0][1208]=1207 | |
| 1212 | .[0][1209]=1208 | |
| 1213 | .[0][1210]=1209 | |
| 1214 | .[0][1211]=1210 | |
| 1215 | .[0][1212]=1211 | |
| 1216 | .[0][1213]=1212 | |
| 1217 | .[0][1214]=1213 | |
| 1218 | .[0][1215]=1214 | |
| 1219 | .[0][1216]=1215 | |
| 1220 | .[0][1217]=1216 | |
| 1221 | .[0][1218]=1217 | |
| 1222 | .[0][1219]=1218 | |
| 1223 | .[0][1220]=1219 | |
| 1224 | .[0][1221]=1220 | |
| 1225 | .[0][1222]=1221 | |
| 1226 | .[0][1223]=1222 | |
| 1227 | .[0][1224]=1223 | |
| 1228 | .[0][1225]=1224 | |
| 1229 | .[0][1226]=1225 | |
| 1230 | .[0][1227]=1226 | |
| 1231 | .[0][1228]=1227 | |
| 1232 | .[0][1229]=1228 | |
| 1233 | .[0][1230]=1229 | |
| 1234 | .[0][1231]=1230 | |
| 1235 | .[0][1232]=1231 | |
| 1236 | .[0][1233]=1232 | |
| 1237 | .[0][1234]=1233 | |
| 1238 | .[0][1235]=1234 | |
| 1239 | .[0][1236]=1235 | |
| 1240 | .[0][1237]=1236 | |
| 1241 | .[0][1238]=1237 | |
| 1242 | .[0][1239]=1238 | |
| 1243 | .[0][1240]=1239 | |
| 1244 | .[0][1241]=1240 | |
| 1245 | .[0][1242]=1241 | |
| 1246 | .[0][1243]=1242 | |
| 1247 | .[0][1244]=1243 | |
| 1248 | .[0][1245]=1244 | |
| 1249 | .[0][1246]=1245 | |
| 1250 | .[0][1247]=1246 | |
| 1251 | .[0][1248]=1247 | |
| 1252 | .[0][1249]=1248 | |
| 1253 | .[0][1250]=1249 | |
| 1254 | .[0][1251]=1250 | |
| 1255 | .[0][1252]=1251 | |
| 1256 | .[0][1253]=1252 | |
| 1257 | .[0][1254]=1253 | |
| 1258 | .[0][1255]=1254 | |
| 1259 | .[0][1256]=1255 | |
| 1260 | .[0][1257]=1256 | |
| 1261 | .[0][1258]=1257 | |
| 1262 | .[0][1259]=1258 | |
| 1263 | .[0][1260]=1259 | |
| 1264 | .[0][1261]=1260 | |
| 1265 | .[0][1262]=1261 | |
| 1266 | .[0][1263]=1262 | |
| 1267 | .[0][1264]=1263 | |
| 1268 | .[0][1265]=1264 | |
| 1269 | .[0][1266]=1265 | |
| 1270 | .[0][1267]=1266 | |
| 1271 | .[0][1268]=1267 | |
| 1272 | .[0][1269]=1268 | |
| 1273 | .[0][1270]=1269 | |
| 1274 | .[0][1271]=1270 | |
| 1275 | .[0][1272]=1271 | |
| 1276 | .[0][1273]=1272 | |
| 1277 | .[0][1274]=1273 | |
| 1278 | .[0][1275]=1274 | |
| 1279 | .[0][1276]=1275 | |
| 1280 | .[0][1277]=1276 | |
| 1281 | .[0][1278]=1277 | |
| 1282 | .[0][1279]=1278 | |
| 1283 | .[0][1280]=1279 | |
| 1284 | .[0][1281]=1280 | |
| 1285 | .[0][1282]=1281 | |
| 1286 | .[0][1283]=1282 | |
| 1287 | .[0][1284]=1283 | |
| 1288 | .[0][1285]=1284 | |
| 1289 | .[0][1286]=1285 | |
| 1290 | .[0][1287]=1286 | |
| 1291 | .[0][1288]=1287 | |
| 1292 | .[0][1289]=1288 | |
| 1293 | .[0][1290]=1289 | |
| 1294 | .[0][1291]=1290 | |
| 1295 | .[0][1292]=1291 | |
| 1296 | .[0][1293]=1292 | |
| 1297 | .[0][1294]=1293 | |
| 1298 | .[0][1295]=1294 | |
| 1299 | .[0][1296]=1295 | |
| 1300 | .[0][1297]=1296 | |
| 1301 | .[0][1298]=1297 | |
| 1302 | .[0][1299]=1298 | |
| 1303 | .[0][1300]=1299 | |
| 1304 | .[0][1301]=1300 | |
| 1305 | .[0][1302]=1301 | |
| 1306 | .[0][1303]=1302 | |
| 1307 | .[0][1304]=1303 | |
| 1308 | .[0][1305]=1304 | |
| 1309 | .[0][1306]=1305 | |
| 1310 | .[0][1307]=1306 | |
| 1311 | .[0][1308]=1307 | |
| 1312 | .[0][1309]=1308 | |
| 1313 | .[0][1310]=1309 | |
| 1314 | .[0][1311]=1310 | |
| 1315 | .[0][1312]=1311 | |
| 1316 | .[0][1313]=1312 | |
| 1317 | .[0][1314]=1313 | |
| 1318 | .[0][1315]=1314 | |
| 1319 | .[0][1316]=1315 | |
| 1320 | .[0][1317]=1316 | |
| 1321 | .[0][1318]=1317 | |
| 1322 | .[0][1319]=1318 | |
| 1323 | .[0][1320]=1319 | |
| 1324 | .[0][1321]=1320 | |
| 1325 | .[0][1322]=1321 | |
| 1326 | .[0][1323]=1322 | |
| 1327 | .[0][1324]=1323 | |
| 1328 | .[0][1325]=1324 | |
| 1329 | .[0][1326]=1325 | |
| 1330 | .[0][1327]=1326 | |
| 1331 | .[0][1328]=1327 | |
| 1332 | .[0][1329]=1328 | |
| 1333 | .[0][1330]=1329 | |
| 1334 | .[0][1331]=1330 | |
| 1335 | .[0][1332]=1331 | |
| 1336 | .[0][1333]=1332 | |
| 1337 | .[0][1334]=1333 | |
| 1338 | .[0][1335]=1334 | |
| 1339 | .[0][1336]=1335 | |
| 1340 | .[0][1337]=1336 | |
| 1341 | .[0][1338]=1337 | |
| 1342 | .[0][1339]=1338 | |
| 1343 | .[0][1340]=1339 | |
| 1344 | .[0][1341]=1340 | |
| 1345 | .[0][1342]=1341 | |
| 1346 | .[0][1343]=1342 | |
| 1347 | .[0][1344]=1343 | |
| 1348 | .[0][1345]=1344 | |
| 1349 | .[0][1346]=1345 | |
| 1350 | .[0][1347]=1346 | |
| 1351 | .[0][1348]=1347 | |
| 1352 | .[0][1349]=1348 | |
| 1353 | .[0][1350]=1349 | |
| 1354 | .[0][1351]=1350 | |
| 1355 | .[0][1352]=1351 | |
| 1356 | .[0][1353]=1352 | |
| 1357 | .[0][1354]=1353 | |
| 1358 | .[0][1355]=1354 | |
| 1359 | .[0][1356]=1355 | |
| 1360 | .[0][1357]=1356 | |
| 1361 | .[0][1358]=1357 | |
| 1362 | .[0][1359]=1358 | |
| 1363 | .[0][1360]=1359 | |
| 1364 | .[0][1361]=1360 | |
| 1365 | .[0][1362]=1361 | |
| 1366 | .[0][1363]=1362 | |
| 1367 | .[0][1364]=1363 | |
| 1368 | .[0][1365]=1364 | |
| 1369 | .[0][1366]=1365 | |
| 1370 | .[0][1367]=1366 | |
| 1371 | .[0][1368]=1367 | |
| 1372 | .[0][1369]=1368 | |
| 1373 | .[0][1370]=1369 | |
| 1374 | .[0][1371]=1370 | |
| 1375 | .[0][1372]=1371 | |
| 1376 | .[0][1373]=1372 | |
| 1377 | .[0][1374]=1373 | |
| 1378 | .[0][1375]=1374 | |
| 1379 | .[0][1376]=1375 | |
| 1380 | .[0][1377]=1376 | |
| 1381 | .[0][1378]=1377 | |
| 1382 | .[0][1379]=1378 | |
| 1383 | .[0][1380]=1379 | |
| 1384 | .[0][1381]=1380 | |
| 1385 | .[0][1382]=1381 | |
| 1386 | .[0][1383]=1382 | |
| 1387 | .[0][1384]=1383 | |
| 1388 | .[0][1385]=1384 | |
| 1389 | .[0][1386]=1385 | |
| 1390 | .[0][1387]=1386 | |
| 1391 | .[0][1388]=1387 | |
| 1392 | .[0][1389]=1388 | |
| 1393 | .[0][1390]=1389 | |
| 1394 | .[0][1391]=1390 | |
| 1395 | .[0][1392]=1391 | |
| 1396 | .[0][1393]=1392 | |
| 1397 | .[0][1394]=1393 | |
| 1398 | .[0][1395]=1394 | |
| 1399 | .[0][1396]=1395 | |
| 1400 | .[0][1397]=1396 | |
| 1401 | .[0][1398]=1397 | |
| 1402 | .[0][1399]=1398 | |
| 1403 | .[0][1400]=1399 | |
| 1404 | .[0][1401]=1400 | |
| 1405 | .[0][1402]=1401 | |
| 1406 | .[0][1403]=1402 | |
| 1407 | .[0][1404]=1403 | |
| 1408 | .[0][1405]=1404 | |
| 1409 | .[0][1406]=1405 | |
| 1410 | .[0][1407]=1406 | |
| 1411 | .[0][1408]=1407 | |
| 1412 | .[0][1409]=1408 | |
| 1413 | .[0][1410]=1409 | |
| 1414 | .[0][1411]=1410 | |
| 1415 | .[0][1412]=1411 | |
| 1416 | .[0][1413]=1412 | |
| 1417 | .[0][1414]=1413 | |
| 1418 | .[0][1415]=1414 | |
| 1419 | .[0][1416]=1415 | |
| 1420 | .[0][1417]=1416 | |
| 1421 | .[0][1418]=1417 | |
| 1422 | .[0][1419]=1418 | |
| 1423 | .[0][1420]=1419 | |
| 1424 | .[0][1421]=1420 | |
| 1425 | .[0][1422]=1421 | |
| 1426 | .[0][1423]=1422 | |
| 1427 | .[0][1424]=1423 | |
| 1428 | .[0][1425]=1424 | |
| 1429 | .[0][1426]=1425 | |
| 1430 | .[0][1427]=1426 | |
| 1431 | .[0][1428]=1427 | |
| 1432 | .[0][1429]=1428 | |
| 1433 | .[0][1430]=1429 | |
| 1434 | .[0][1431]=1430 | |
| 1435 | .[0][1432]=1431 | |
| 1436 | .[0][1433]=1432 | |
| 1437 | .[0][1434]=1433 | |
| 1438 | .[0][1435]=1434 | |
| 1439 | .[0][1436]=1435 | |
| 1440 | .[0][1437]=1436 | |
| 1441 | .[0][1438]=1437 | |
| 1442 | .[0][1439]=1438 | |
| 1443 | .[0][1440]=1439 | |
| 1444 | .[0][1441]=1440 | |
| 1445 | .[0][1442]=1441 | |
| 1446 | .[0][1443]=1442 | |
| 1447 | .[0][1444]=1443 | |
| 1448 | .[0][1445]=1444 | |
| 1449 | .[0][1446]=1445 | |
| 1450 | .[0][1447]=1446 | |
| 1451 | .[0][1448]=1447 | |
| 1452 | .[0][1449]=1448 | |
| 1453 | .[0][1450]=1449 | |
| 1454 | .[0][1451]=1450 | |
| 1455 | .[0][1452]=1451 | |
| 1456 | .[0][1453]=1452 | |
| 1457 | .[0][1454]=1453 | |
| 1458 | .[0][1455]=1454 | |
| 1459 | .[0][1456]=1455 | |
| 1460 | .[0][1457]=1456 | |
| 1461 | .[0][1458]=1457 | |
| 1462 | .[0][1459]=1458 | |
| 1463 | .[0][1460]=1459 | |
| 1464 | .[0][1461]=1460 | |
| 1465 | .[0][1462]=1461 | |
| 1466 | .[0][1463]=1462 | |
| 1467 | .[0][1464]=1463 | |
| 1468 | .[0][1465]=1464 | |
| 1469 | .[0][1466]=1465 | |
| 1470 | .[0][1467]=1466 | |
| 1471 | .[0][1468]=1467 | |
| 1472 | .[0][1469]=1468 | |
| 1473 | .[0][1470]=1469 | |
| 1474 | .[0][1471]=1470 | |
| 1475 | .[0][1472]=1471 | |
| 1476 | .[0][1473]=1472 | |
| 1477 | .[0][1474]=1473 | |
| 1478 | .[0][1475]=1474 | |
| 1479 | .[0][1476]=1475 | |
| 1480 | .[0][1477]=1476 | |
| 1481 | .[0][1478]=1477 | |
| 1482 | .[0][1479]=1478 | |
| 1483 | .[0][1480]=1479 | |
| 1484 | .[0][1481]=1480 | |
| 1485 | .[0][1482]=1481 | |
| 1486 | .[0][1483]=1482 | |
| 1487 | .[0][1484]=1483 | |
| 1488 | .[0][1485]=1484 | |
| 1489 | .[0][1486]=1485 | |
| 1490 | .[0][1487]=1486 | |
| 1491 | .[0][1488]=1487 | |
| 1492 | .[0][1489]=1488 | |
| 1493 | .[0][1490]=1489 | |
| 1494 | .[0][1491]=1490 | |
| 1495 | .[0][1492]=1491 | |
| 1496 | .[0][1493]=1492 | |
| 1497 | .[0][1494]=1493 | |
| 1498 | .[0][1495]=1494 | |
| 1499 | .[0][1496]=1495 | |
| 1500 | .[0][1497]=1496 | |
| 1501 | .[0][1498]=1497 | |
| 1502 | .[0][1499]=1498 | |
| 1503 | .[0][1500]=1499 | |
| 1504 | .[0][1501]=1500 | |
| 1505 | .[0][1502]=1501 | |
| 1506 | .[0][1503]=1502 | |
| 1507 | .[0][1504]=1503 | |
| 1508 | .[0][1505]=1504 | |
| 1509 | .[0][1506]=1505 | |
| 1510 | .[0][1507]=1506 | |
| 1511 | .[0][1508]=1507 | |
| 1512 | .[0][1509]=1508 | |
| 1513 | .[0][1510]=1509 | |
| 1514 | .[0][1511]=1510 | |
| 1515 | .[0][1512]=1511 | |
| 1516 | .[0][1513]=1512 | |
| 1517 | .[0][1514]=1513 | |
| 1518 | .[0][1515]=1514 | |
| 1519 | .[0][1516]=1515 | |
| 1520 | .[0][1517]=1516 | |
| 1521 | .[0][1518]=1517 | |
| 1522 | .[0][1519]=1518 | |
| 1523 | .[0][1520]=1519 | |
| 1524 | .[0][1521]=1520 | |
| 1525 | .[0][1522]=1521 | |
| 1526 | .[0][1523]=1522 | |
| 1527 | .[0][1524]=1523 | |
| 1528 | .[0][1525]=1524 | |
| 1529 | .[0][1526]=1525 | |
| 1530 | .[0][1527]=1526 | |
| 1531 | .[0][1528]=1527 | |
| 1532 | .[0][1529]=1528 | |
| 1533 | .[0][1530]=1529 | |
| 1534 | .[0][1531]=1530 | |
| 1535 | .[0][1532]=1531 | |
| 1536 | .[0][1533]=1532 | |
| 1537 | .[0][1534]=1533 | |
| 1538 | .[0][1535]=1534 | |
| 1539 | .[0][1536]=1535 | |
| 1540 | .[0][1537]=1536 | |
| 1541 | .[0][1538]=1537 | |
| 1542 | .[0][1539]=1538 | |
| 1543 | .[0][1540]=1539 | |
| 1544 | .[0][1541]=1540 | |
| 1545 | .[0][1542]=1541 | |
| 1546 | .[0][1543]=1542 | |
| 1547 | .[0][1544]=1543 | |
| 1548 | .[0][1545]=1544 | |
| 1549 | .[0][1546]=1545 | |
| 1550 | .[0][1547]=1546 | |
| 1551 | .[0][1548]=1547 | |
| 1552 | .[0][1549]=1548 | |
| 1553 | .[0][1550]=1549 | |
| 1554 | .[0][1551]=1550 | |
| 1555 | .[0][1552]=1551 | |
| 1556 | .[0][1553]=1552 | |
| 1557 | .[0][1554]=1553 | |
| 1558 | .[0][1555]=1554 | |
| 1559 | .[0][1556]=1555 | |
| 1560 | .[0][1557]=1556 | |
| 1561 | .[0][1558]=1557 | |
| 1562 | .[0][1559]=1558 | |
| 1563 | .[0][1560]=1559 | |
| 1564 | .[0][1561]=1560 | |
| 1565 | .[0][1562]=1561 | |
| 1566 | .[0][1563]=1562 | |
| 1567 | .[0][1564]=1563 | |
| 1568 | .[0][1565]=1564 | |
| 1569 | .[0][1566]=1565 | |
| 1570 | .[0][1567]=1566 | |
| 1571 | .[0][1568]=1567 | |
| 1572 | .[0][1569]=1568 | |
| 1573 | .[0][1570]=1569 | |
| 1574 | .[0][1571]=1570 | |
| 1575 | .[0][1572]=1571 | |
| 1576 | .[0][1573]=1572 | |
| 1577 | .[0][1574]=1573 | |
| 1578 | .[0][1575]=1574 | |
| 1579 | .[0][1576]=1575 | |
| 1580 | .[0][1577]=1576 | |
| 1581 | .[0][1578]=1577 | |
| 1582 | .[0][1579]=1578 | |
| 1583 | .[0][1580]=1579 | |
| 1584 | .[0][1581]=1580 | |
| 1585 | .[0][1582]=1581 | |
| 1586 | .[0][1583]=1582 | |
| 1587 | .[0][1584]=1583 | |
| 1588 | .[0][1585]=1584 | |
| 1589 | .[0][1586]=1585 | |
| 1590 | .[0][1587]=1586 | |
| 1591 | .[0][1588]=1587 | |
| 1592 | .[0][1589]=1588 | |
| 1593 | .[0][1590]=1589 | |
| 1594 | .[0][1591]=1590 | |
| 1595 | .[0][1592]=1591 | |
| 1596 | .[0][1593]=1592 | |
| 1597 | .[0][1594]=1593 | |
| 1598 | .[0][1595]=1594 | |
| 1599 | .[0][1596]=1595 | |
| 1600 | .[0][1597]=1596 | |
| 1601 | .[0][1598]=1597 | |
| 1602 | .[0][1599]=1598 | |
| 1603 | .[0][1600]=1599 | |
| 1604 | .[0][1601]=1600 | |
| 1605 | .[0][1602]=1601 | |
| 1606 | .[0][1603]=1602 | |
| 1607 | .[0][1604]=1603 | |
| 1608 | .[0][1605]=1604 | |
| 1609 | .[0][1606]=1605 | |
| 1610 | .[0][1607]=1606 | |
| 1611 | .[0][1608]=1607 | |
| 1612 | .[0][1609]=1608 | |
| 1613 | .[0][1610]=1609 | |
| 1614 | .[0][1611]=1610 | |
| 1615 | .[0][1612]=1611 | |
| 1616 | .[0][1613]=1612 | |
| 1617 | .[0][1614]=1613 | |
| 1618 | .[0][1615]=1614 | |
| 1619 | .[0][1616]=1615 | |
| 1620 | .[0][1617]=1616 | |
| 1621 | .[0][1618]=1617 | |
| 1622 | .[0][1619]=1618 | |
| 1623 | .[0][1620]=1619 | |
| 1624 | .[0][1621]=1620 | |
| 1625 | .[0][1622]=1621 | |
| 1626 | .[0][1623]=1622 | |
| 1627 | .[0][1624]=1623 | |
| 1628 | .[0][1625]=1624 | |
| 1629 | .[0][1626]=1625 | |
| 1630 | .[0][1627]=1626 | |
| 1631 | .[0][1628]=1627 | |
| 1632 | .[0][1629]=1628 | |
| 1633 | .[0][1630]=1629 | |
| 1634 | .[0][1631]=1630 | |
| 1635 | .[0][1632]=1631 | |
| 1636 | .[0][1633]=1632 | |
| 1637 | .[0][1634]=1633 | |
| 1638 | .[0][1635]=1634 | |
| 1639 | .[0][1636]=1635 | |
| 1640 | .[0][1637]=1636 | |
| 1641 | .[0][1638]=1637 | |
| 1642 | .[0][1639]=1638 | |
| 1643 | .[0][1640]=1639 | |
| 1644 | .[0][1641]=1640 | |
| 1645 | .[0][1642]=1641 | |
| 1646 | .[0][1643]=1642 | |
| 1647 | .[0][1644]=1643 | |
| 1648 | .[0][1645]=1644 | |
| 1649 | .[0][1646]=1645 | |
| 1650 | .[0][1647]=1646 | |
| 1651 | .[0][1648]=1647 | |
| 1652 | .[0][1649]=1648 | |
| 1653 | .[0][1650]=1649 | |
| 1654 | .[0][1651]=1650 | |
| 1655 | .[0][1652]=1651 | |
| 1656 | .[0][1653]=1652 | |
| 1657 | .[0][1654]=1653 | |
| 1658 | .[0][1655]=1654 | |
| 1659 | .[0][1656]=1655 | |
| 1660 | .[0][1657]=1656 | |
| 1661 | .[0][1658]=1657 | |
| 1662 | .[0][1659]=1658 | |
| 1663 | .[0][1660]=1659 | |
| 1664 | .[0][1661]=1660 | |
| 1665 | .[0][1662]=1661 | |
| 1666 | .[0][1663]=1662 | |
| 1667 | .[0][1664]=1663 | |
| 1668 | .[0][1665]=1664 | |
| 1669 | .[0][1666]=1665 | |
| 1670 | .[0][1667]=1666 | |
| 1671 | .[0][1668]=1667 | |
| 1672 | .[0][1669]=1668 | |
| 1673 | .[0][1670]=1669 | |
| 1674 | .[0][1671]=1670 | |
| 1675 | .[0][1672]=1671 | |
| 1676 | .[0][1673]=1672 | |
| 1677 | .[0][1674]=1673 | |
| 1678 | .[0][1675]=1674 | |
| 1679 | .[0][1676]=1675 | |
| 1680 | .[0][1677]=1676 | |
| 1681 | .[0][1678]=1677 | |
| 1682 | .[0][1679]=1678 | |
| 1683 | .[0][1680]=1679 | |
| 1684 | .[0][1681]=1680 | |
| 1685 | .[0][1682]=1681 | |
| 1686 | .[0][1683]=1682 | |
| 1687 | .[0][1684]=1683 | |
| 1688 | .[0][1685]=1684 | |
| 1689 | .[0][1686]=1685 | |
| 1690 | .[0][1687]=1686 | |
| 1691 | .[0][1688]=1687 | |
| 1692 | .[0][1689]=1688 | |
| 1693 | .[0][1690]=1689 | |
| 1694 | .[0][1691]=1690 | |
| 1695 | .[0][1692]=1691 | |
| 1696 | .[0][1693]=1692 | |
| 1697 | .[0][1694]=1693 | |
| 1698 | .[0][1695]=1694 | |
| 1699 | .[0][1696]=1695 | |
| 1700 | .[0][1697]=1696 | |
| 1701 | .[0][1698]=1697 | |
| 1702 | .[0][1699]=1698 | |
| 1703 | .[0][1700]=1699 | |
| 1704 | .[0][1701]=1700 | |
| 1705 | .[0][1702]=1701 | |
| 1706 | .[0][1703]=1702 | |
| 1707 | .[0][1704]=1703 | |
| 1708 | .[0][1705]=1704 | |
| 1709 | .[0][1706]=1705 | |
| 1710 | .[0][1707]=1706 | |
| 1711 | .[0][1708]=1707 | |
| 1712 | .[0][1709]=1708 | |
| 1713 | .[0][1710]=1709 | |
| 1714 | .[0][1711]=1710 | |
| 1715 | .[0][1712]=1711 | |
| 1716 | .[0][1713]=1712 | |
| 1717 | .[0][1714]=1713 | |
| 1718 | .[0][1715]=1714 | |
| 1719 | .[0][1716]=1715 | |
| 1720 | .[0][1717]=1716 | |
| 1721 | .[0][1718]=1717 | |
| 1722 | .[0][1719]=1718 | |
| 1723 | .[0][1720]=1719 | |
| 1724 | .[0][1721]=1720 | |
| 1725 | .[0][1722]=1721 | |
| 1726 | .[0][1723]=1722 | |
| 1727 | .[0][1724]=1723 | |
| 1728 | .[0][1725]=1724 | |
| 1729 | .[0][1726]=1725 | |
| 1730 | .[0][1727]=1726 | |
| 1731 | .[0][1728]=1727 | |
| 1732 | .[0][1729]=1728 | |
| 1733 | .[0][1730]=1729 | |
| 1734 | .[0][1731]=1730 | |
| 1735 | .[0][1732]=1731 | |
| 1736 | .[0][1733]=1732 | |
| 1737 | .[0][1734]=1733 | |
| 1738 | .[0][1735]=1734 | |
| 1739 | .[0][1736]=1735 | |
| 1740 | .[0][1737]=1736 | |
| 1741 | .[0][1738]=1737 | |
| 1742 | .[0][1739]=1738 | |
| 1743 | .[0][1740]=1739 | |
| 1744 | .[0][1741]=1740 | |
| 1745 | .[0][1742]=1741 | |
| 1746 | .[0][1743]=1742 | |
| 1747 | .[0][1744]=1743 | |
| 1748 | .[0][1745]=1744 | |
| 1749 | .[0][1746]=1745 | |
| 1750 | .[0][1747]=1746 | |
| 1751 | .[0][1748]=1747 | |
| 1752 | .[0][1749]=1748 | |
| 1753 | .[0][1750]=1749 | |
| 1754 | .[0][1751]=1750 | |
| 1755 | .[0][1752]=1751 | |
| 1756 | .[0][1753]=1752 | |
| 1757 | .[0][1754]=1753 | |
| 1758 | .[0][1755]=1754 | |
| 1759 | .[0][1756]=1755 | |
| 1760 | .[0][1757]=1756 | |
| 1761 | .[0][1758]=1757 | |
| 1762 | .[0][1759]=1758 | |
| 1763 | .[0][1760]=1759 | |
| 1764 | .[0][1761]=1760 | |
| 1765 | .[0][1762]=1761 | |
| 1766 | .[0][1763]=1762 | |
| 1767 | .[0][1764]=1763 | |
| 1768 | .[0][1765]=1764 | |
| 1769 | .[0][1766]=1765 | |
| 1770 | .[0][1767]=1766 | |
| 1771 | .[0][1768]=1767 | |
| 1772 | .[0][1769]=1768 | |
| 1773 | .[0][1770]=1769 | |
| 1774 | .[0][1771]=1770 | |
| 1775 | .[0][1772]=1771 | |
| 1776 | .[0][1773]=1772 | |
| 1777 | .[0][1774]=1773 | |
| 1778 | .[0][1775]=1774 | |
| 1779 | .[0][1776]=1775 | |
| 1780 | .[0][1777]=1776 | |
| 1781 | .[0][1778]=1777 | |
| 1782 | .[0][1779]=1778 | |
| 1783 | .[0][1780]=1779 | |
| 1784 | .[0][1781]=1780 | |
| 1785 | .[0][1782]=1781 | |
| 1786 | .[0][1783]=1782 | |
| 1787 | .[0][1784]=1783 | |
| 1788 | .[0][1785]=1784 | |
| 1789 | .[0][1786]=1785 | |
| 1790 | .[0][1787]=1786 | |
| 1791 | .[0][1788]=1787 | |
| 1792 | .[0][1789]=1788 | |
| 1793 | .[0][1790]=1789 | |
| 1794 | .[0][1791]=1790 | |
| 1795 | .[0][1792]=1791 | |
| 1796 | .[0][1793]=1792 | |
| 1797 | .[0][1794]=1793 | |
| 1798 | .[0][1795]=1794 | |
| 1799 | .[0][1796]=1795 | |
| 1800 | .[0][1797]=1796 | |
| 1801 | .[0][1798]=1797 | |
| 1802 | .[0][1799]=1798 | |
| 1803 | .[0][1800]=1799 | |
| 1804 | .[0][1801]=1800 | |
| 1805 | .[0][1802]=1801 | |
| 1806 | .[0][1803]=1802 | |
| 1807 | .[0][1804]=1803 | |
| 1808 | .[0][1805]=1804 | |
| 1809 | .[0][1806]=1805 | |
| 1810 | .[0][1807]=1806 | |
| 1811 | .[0][1808]=1807 | |
| 1812 | .[0][1809]=1808 | |
| 1813 | .[0][1810]=1809 | |
| 1814 | .[0][1811]=1810 | |
| 1815 | .[0][1812]=1811 | |
| 1816 | .[0][1813]=1812 | |
| 1817 | .[0][1814]=1813 | |
| 1818 | .[0][1815]=1814 | |
| 1819 | .[0][1816]=1815 | |
| 1820 | .[0][1817]=1816 | |
| 1821 | .[0][1818]=1817 | |
| 1822 | .[0][1819]=1818 | |
| 1823 | .[0][1820]=1819 | |
| 1824 | .[0][1821]=1820 | |
| 1825 | .[0][1822]=1821 | |
| 1826 | .[0][1823]=1822 | |
| 1827 | .[0][1824]=1823 | |
| 1828 | .[0][1825]=1824 | |
| 1829 | .[0][1826]=1825 | |
| 1830 | .[0][1827]=1826 | |
| 1831 | .[0][1828]=1827 | |
| 1832 | .[0][1829]=1828 | |
| 1833 | .[0][1830]=1829 | |
| 1834 | .[0][1831]=1830 | |
| 1835 | .[0][1832]=1831 | |
| 1836 | .[0][1833]=1832 | |
| 1837 | .[0][1834]=1833 | |
| 1838 | .[0][1835]=1834 | |
| 1839 | .[0][1836]=1835 | |
| 1840 | .[0][1837]=1836 | |
| 1841 | .[0][1838]=1837 | |
| 1842 | .[0][1839]=1838 | |
| 1843 | .[0][1840]=1839 | |
| 1844 | .[0][1841]=1840 | |
| 1845 | .[0][1842]=1841 | |
| 1846 | .[0][1843]=1842 | |
| 1847 | .[0][1844]=1843 | |
| 1848 | .[0][1845]=1844 | |
| 1849 | .[0][1846]=1845 | |
| 1850 | .[0][1847]=1846 | |
| 1851 | .[0][1848]=1847 | |
| 1852 | .[0][1849]=1848 | |
| 1853 | .[0][1850]=1849 | |
| 1854 | .[0][1851]=1850 | |
| 1855 | .[0][1852]=1851 | |
| 1856 | .[0][1853]=1852 | |
| 1857 | .[0][1854]=1853 | |
| 1858 | .[0][1855]=1854 | |
| 1859 | .[0][1856]=1855 | |
| 1860 | .[0][1857]=1856 | |
| 1861 | .[0][1858]=1857 | |
| 1862 | .[0][1859]=1858 | |
| 1863 | .[0][1860]=1859 | |
| 1864 | .[0][1861]=1860 | |
| 1865 | .[0][1862]=1861 | |
| 1866 | .[0][1863]=1862 | |
| 1867 | .[0][1864]=1863 | |
| 1868 | .[0][1865]=1864 | |
| 1869 | .[0][1866]=1865 | |
| 1870 | .[0][1867]=1866 | |
| 1871 | .[0][1868]=1867 | |
| 1872 | .[0][1869]=1868 | |
| 1873 | .[0][1870]=1869 | |
| 1874 | .[0][1871]=1870 | |
| 1875 | .[0][1872]=1871 | |
| 1876 | .[0][1873]=1872 | |
| 1877 | .[0][1874]=1873 | |
| 1878 | .[0][1875]=1874 | |
| 1879 | .[0][1876]=1875 | |
| 1880 | .[0][1877]=1876 | |
| 1881 | .[0][1878]=1877 | |
| 1882 | .[0][1879]=1878 | |
| 1883 | .[0][1880]=1879 | |
| 1884 | .[0][1881]=1880 | |
| 1885 | .[0][1882]=1881 | |
| 1886 | .[0][1883]=1882 | |
| 1887 | .[0][1884]=1883 | |
| 1888 | .[0][1885]=1884 | |
| 1889 | .[0][1886]=1885 | |
| 1890 | .[0][1887]=1886 | |
| 1891 | .[0][1888]=1887 | |
| 1892 | .[0][1889]=1888 | |
| 1893 | .[0][1890]=1889 | |
| 1894 | .[0][1891]=1890 | |
| 1895 | .[0][1892]=1891 | |
| 1896 | .[0][1893]=1892 | |
| 1897 | .[0][1894]=1893 | |
| 1898 | .[0][1895]=1894 | |
| 1899 | .[0][1896]=1895 | |
| 1900 | .[0][1897]=1896 | |
| 1901 | .[0][1898]=1897 | |
| 1902 | .[0][1899]=1898 | |
| 1903 | .[0][1900]=1899 | |
| 1904 | .[0][1901]=1900 | |
| 1905 | .[0][1902]=1901 | |
| 1906 | .[0][1903]=1902 | |
| 1907 | .[0][1904]=1903 | |
| 1908 | .[0][1905]=1904 | |
| 1909 | .[0][1906]=1905 | |
| 1910 | .[0][1907]=1906 | |
| 1911 | .[0][1908]=1907 | |
| 1912 | .[0][1909]=1908 | |
| 1913 | .[0][1910]=1909 | |
| 1914 | .[0][1911]=1910 | |
| 1915 | .[0][1912]=1911 | |
| 1916 | .[0][1913]=1912 | |
| 1917 | .[0][1914]=1913 | |
| 1918 | .[0][1915]=1914 | |
| 1919 | .[0][1916]=1915 | |
| 1920 | .[0][1917]=1916 | |
| 1921 | .[0][1918]=1917 | |
| 1922 | .[0][1919]=1918 | |
| 1923 | .[0][1920]=1919 | |
| 1924 | .[0][1921]=1920 | |
| 1925 | .[0][1922]=1921 | |
| 1926 | .[0][1923]=1922 | |
| 1927 | .[0][1924]=1923 | |
| 1928 | .[0][1925]=1924 | |
| 1929 | .[0][1926]=1925 | |
| 1930 | .[0][1927]=1926 | |
| 1931 | .[0][1928]=1927 | |
| 1932 | .[0][1929]=1928 | |
| 1933 | .[0][1930]=1929 | |
| 1934 | .[0][1931]=1930 | |
| 1935 | .[0][1932]=1931 | |
| 1936 | .[0][1933]=1932 | |
| 1937 | .[0][1934]=1933 | |
| 1938 | .[0][1935]=1934 | |
| 1939 | .[0][1936]=1935 | |
| 1940 | .[0][1937]=1936 | |
| 1941 | .[0][1938]=1937 | |
| 1942 | .[0][1939]=1938 | |
| 1943 | .[0][1940]=1939 | |
| 1944 | .[0][1941]=1940 | |
| 1945 | .[0][1942]=1941 | |
| 1946 | .[0][1943]=1942 | |
| 1947 | .[0][1944]=1943 | |
| 1948 | .[0][1945]=1944 | |
| 1949 | .[0][1946]=1945 | |
| 1950 | .[0][1947]=1946 | |
| 1951 | .[0][1948]=1947 | |
| 1952 | .[0][1949]=1948 | |
| 1953 | .[0][1950]=1949 | |
| 1954 | .[0][1951]=1950 | |
| 1955 | .[0][1952]=1951 | |
| 1956 | .[0][1953]=1952 | |
| 1957 | .[0][1954]=1953 | |
| 1958 | .[0][1955]=1954 | |
| 1959 | .[0][1956]=1955 | |
| 1960 | .[0][1957]=1956 | |
| 1961 | .[0][1958]=1957 | |
| 1962 | .[0][1959]=1958 | |
| 1963 | .[0][1960]=1959 | |
| 1964 | .[0][1961]=1960 | |
| 1965 | .[0][1962]=1961 | |
| 1966 | .[0][1963]=1962 | |
| 1967 | .[0][1964]=1963 | |
| 1968 | .[0][1965]=1964 | |
| 1969 | .[0][1966]=1965 | |
| 1970 | .[0][1967]=1966 | |
| 1971 | .[0][1968]=1967 | |
| 1972 | .[0][1969]=1968 | |
| 1973 | .[0][1970]=1969 | |
| 1974 | .[0][1971]=1970 | |
| 1975 | .[0][1972]=1971 | |
| 1976 | .[0][1973]=1972 | |
| 1977 | .[0][1974]=1973 | |
| 1978 | .[0][1975]=1974 | |
| 1979 | .[0][1976]=1975 | |
| 1980 | .[0][1977]=1976 | |
| 1981 | .[0][1978]=1977 | |
| 1982 | .[0][1979]=1978 | |
| 1983 | .[0][1980]=1979 | |
| 1984 | .[0][1981]=1980 | |
| 1985 | .[0][1982]=1981 | |
| 1986 | .[0][1983]=1982 | |
| 1987 | .[0][1984]=1983 | |
| 1988 | .[0][1985]=1984 | |
| 1989 | .[0][1986]=1985 | |
| 1990 | .[0][1987]=1986 | |
| 1991 | .[0][1988]=1987 | |
| 1992 | .[0][1989]=1988 | |
| 1993 | .[0][1990]=1989 | |
| 1994 | .[0][1991]=1990 | |
| 1995 | .[0][1992]=1991 | |
| 1996 | .[0][1993]=1992 | |
| 1997 | .[0][1994]=1993 | |
| 1998 | .[0][1995]=1994 | |
| 1999 | .[0][1996]=1995 | |
| 2000 | .[0][1997]=1996 | |
| 2001 | .[0][1998]=1997 | |
| 2002 | .[0][1999]=1998 | |
| 2003 | .[0][2000]=1999 | |
| 2004 | .[0][2001]=2000 | |
| 2005 | .[0][2002]=2001 | |
| 2006 | .[0][2003]=2002 | |
| 2007 | .[0][2004]=2003 | |
| 2008 | .[0][2005]=2004 | |
| 2009 | .[0][2006]=2005 | |
| 2010 | .[0][2007]=2006 | |
| 2011 | .[0][2008]=2007 | |
| 2012 | .[0][2009]=2008 | |
| 2013 | .[0][2010]=2009 | |
| 2014 | .[0][2011]=2010 | |
| 2015 | .[0][2012]=2011 | |
| 2016 | .[0][2013]=2012 | |
| 2017 | .[0][2014]=2013 | |
| 2018 | .[0][2015]=2014 | |
| 2019 | .[0][2016]=2015 | |
| 2020 | .[0][2017]=2016 | |
| 2021 | .[0][2018]=2017 | |
| 2022 | .[0][2019]=2018 | |
| 2023 | .[0][2020]=2019 | |
| 2024 | .[0][2021]=2020 | |
| 2025 | .[0][2022]=2021 | |
| 2026 | .[0][2023]=2022 | |
| 2027 | .[0][2024]=2023 | |
| 2028 | .[0][2025]=2024 | |
| 2029 | .[0][2026]=2025 | |
| 2030 | .[0][2027]=2026 | |
| 2031 | .[0][2028]=2027 | |
| 2032 | .[0][2029]=2028 | |
| 2033 | .[0][2030]=2029 | |
| 2034 | .[0][2031]=2030 | |
| 2035 | .[0][2032]=2031 | |
| 2036 | .[0][2033]=2032 | |
| 2037 | .[0][2034]=2033 | |
| 2038 | .[0][2035]=2034 | |
| 2039 | .[0][2036]=2035 | |
| 2040 | .[0][2037]=2036 | |
| 2041 | .[0][2038]=2037 | |
| 2042 | .[0][2039]=2038 | |
| 2043 | .[0][2040]=2039 | |
| 2044 | .[0][2041]=2040 | |
| 2045 | .[0][2042]=2041 | |
| 2046 | .[0][2043]=2042 | |
| 2047 | .[0][2044]=2043 | |
| 2048 | .[0][2045]=2044 | |
| 2049 | .[0][2046]=2045 | |
| 2050 | .[0][2047]=2046 | |
| 2051 | .[0][2048]=2047 | |
| 2052 | .[0][2049]=2048 | |
| 2053 | .[0][2050]=2049 | |
| 2054 | .[0][2051]=2050 | |
| 2055 | .[0][2052]=2051 | |
| 2056 | .[0][2053]=2052 | |
| 2057 | .[0][2054]=2053 | |
| 2058 | .[0][2055]=2054 | |
| 2059 | .[0][2056]=2055 | |
| 2060 | .[0][2057]=2056 | |
| 2061 | .[0][2058]=2057 | |
| 2062 | .[0][2059]=2058 | |
| 2063 | .[0][2060]=2059 | |
| 2064 | .[0][2061]=2060 | |
| 2065 | .[0][2062]=2061 | |
| 2066 | .[0][2063]=2062 | |
| 2067 | .[0][2064]=2063 | |
| 2068 | .[0][2065]=2064 | |
| 2069 | .[0][2066]=2065 | |
| 2070 | .[0][2067]=2066 | |
| 2071 | .[0][2068]=2067 | |
| 2072 | .[0][2069]=2068 | |
| 2073 | .[0][2070]=2069 | |
| 2074 | .[0][2071]=2070 | |
| 2075 | .[0][2072]=2071 | |
| 2076 | .[0][2073]=2072 | |
| 2077 | .[0][2074]=2073 | |
| 2078 | .[0][2075]=2074 | |
| 2079 | .[0][2076]=2075 | |
| 2080 | .[0][2077]=2076 | |
| 2081 | .[0][2078]=2077 | |
| 2082 | .[0][2079]=2078 | |
| 2083 | .[0][2080]=2079 | |
| 2084 | .[0][2081]=2080 | |
| 2085 | .[0][2082]=2081 | |
| 2086 | .[0][2083]=2082 | |
| 2087 | .[0][2084]=2083 | |
| 2088 | .[0][2085]=2084 | |
| 2089 | .[0][2086]=2085 | |
| 2090 | .[0][2087]=2086 | |
| 2091 | .[0][2088]=2087 | |
| 2092 | .[0][2089]=2088 | |
| 2093 | .[0][2090]=2089 | |
| 2094 | .[0][2091]=2090 | |
| 2095 | .[0][2092]=2091 | |
| 2096 | .[0][2093]=2092 | |
| 2097 | .[0][2094]=2093 | |
| 2098 | .[0][2095]=2094 | |
| 2099 | .[0][2096]=2095 | |
| 2100 | .[0][2097]=2096 | |
| 2101 | .[0][2098]=2097 | |
| 2102 | .[0][2099]=2098 | |
| 2103 | .[0][2100]=2099 | |
| 2104 | .[0][2101]=2100 | |
| 2105 | .[0][2102]=2101 | |
| 2106 | .[0][2103]=2102 | |
| 2107 | .[0][2104]=2103 | |
| 2108 | .[0][2105]=2104 | |
| 2109 | .[0][2106]=2105 | |
| 2110 | .[0][2107]=2106 | |
| 2111 | .[0][2108]=2107 | |
| 2112 | .[0][2109]=2108 | |
| 2113 | .[0][2110]=2109 | |
| 2114 | .[0][2111]=2110 | |
| 2115 | .[0][2112]=2111 | |
| 2116 | .[0][2113]=2112 | |
| 2117 | .[0][2114]=2113 | |
| 2118 | .[0][2115]=2114 | |
| 2119 | .[0][2116]=2115 | |
| 2120 | .[0][2117]=2116 | |
| 2121 | .[0][2118]=2117 | |
| 2122 | .[0][2119]=2118 |
| r0 | r242831 | |
|---|---|---|
| 1 | [["A",0,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,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,1104,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,1117,1118,1119,1120,1121,1122,1123,1124,1125,1126,1127,1128,1129,1130,1131,1132,1133,1134,1135,1136,1137,1138,1139,1140,1141,1142,1143,1144,1145,1146,1147,1148,1149,1150,1151,1152,1153,1154,1155,1156,1157,1158,1159,1160,1161,1162,1163,1164,1165,1166,1167,1168,1169,1170,1171,1172,1173,1174,1175,1176,1177,1178,1179,1180,1181,1182,1183,1184,1185,1186,1187,1188,1189,1190,1191,1192,1193,1194,1195,1196,1197,1198,1199,1200,1201,1202,1203,1204,1205,1206,1207,1208,1209,1210,1211,1212,1213,1214,1215,1216,1217,1218,1219,1220,1221,1222,1223,1224,1225,1226,1227,1228,1229,1230,1231,1232,1233,1234,1235,1236,1237,1238,1239,1240,1241,1242,1243,1244,1245,1246,1247,1248,1249,1250,1251,1252,1253,1254,1255,1256,1257,1258,1259,1260,1261,1262,1263,1264,1265,1266,1267,1268,1269,1270,1271,1272,1273,1274,1275,1276,1277,1278,1279,1280,1281,1282,1283,1284,1285,1286,1287,1288,1289,1290,1291,1292,1293,1294,1295,1296,1297,1298,1299,1300,1301,1302,1303,1304,1305,1306,1307,1308,1309,1310,1311,1312,1313,1314,1315,1316,1317,1318,1319,1320,1321,1322,1323,1324,1325,1326,1327,1328,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1360,1361,1362,1363,1364,1365,1366,1367,1368,1369,1370,1371,1372,1373,1374,1375,1376,1377,1378,1379,1380,1381,1382,1383,1384,1385,1386,1387,1388,1389,1390,1391,1392,1393,1394,1395,1396,1397,1398,1399,1400,1401,1402,1403,1404,1405,1406,1407,1408,1409,1410,1411,1412,1413,1414,1415,1416,1417,1418,1419,1420,1421,1422,1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,2079,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,2109,2110,2111,2112,2113,2114,2115,2116,2117,2118] | |
| 2 | ] | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | .=123456789 |
| r0 | r242831 | |
|---|---|---|
| 1 | 0123456789 |
| r0 | r242831 | |
|---|---|---|
| 1 | .=-123456789 |
| r0 | r242831 | |
|---|---|---|
| 1 | -0123456789 |
| r0 | r242831 | |
|---|---|---|
| 1 | .=1.2345678 | |
| 2 | ||
| 3 |
| r0 | r242831 | |
|---|---|---|
| 1 | 1.2345678 | |
| 2 | ||
| 3 |
| r0 | r242831 | |
|---|---|---|
| 1 | .="abcdef" | |
| 2 |
| r0 | r242831 | |
|---|---|---|
| 1 | "abcdef" | |
| 2 |
| r0 | r242831 | |
|---|---|---|
| 1 | .=null | |
| 2 |
| r0 | r242831 | |
|---|---|---|
| 1 | null | |
| 2 |
| r0 | r242831 | |
|---|---|---|
| 1 | .=true | |
| 2 |
| r0 | r242831 | |
|---|---|---|
| 1 | true | |
| 2 |
| r0 | r242831 | |
|---|---|---|
| 1 | .=false | |
| 2 |
| r0 | r242831 | |
|---|---|---|
| 1 | false | |
| 2 |
| r0 | r242831 | |
|---|---|---|
| 1 | // C++ style comment | |
| 2 | .=null | |
| 3 |
| r0 | r242831 | |
|---|---|---|
| 1 | // C++ style comment | |
| 2 | null | |
| 3 |
| r0 | r242831 | |
|---|---|---|
| 1 | /* C style comment | |
| 2 | */ | |
| 3 | .=null | |
| 4 |
| r0 | r242831 | |
|---|---|---|
| 1 | /* C style comment | |
| 2 | */ | |
| 3 | null | |
| 4 |
| r0 | r242831 | |
|---|---|---|
| 1 | .={} | |
| 2 | .test=[] | |
| 3 | .test[0]={} | |
| 4 | .test[0].a="aaa" | |
| 5 | .test[1]={} | |
| 6 | .test[1].b="bbb" | |
| 7 | .test[2]={} | |
| 8 | .test[2].c="ccc" |
| r0 | r242831 | |
|---|---|---|
| 1 | { | |
| 2 | "test": | |
| 3 | [ | |
| 4 | { "a" : "aaa" }, // Comment for a | |
| 5 | { "b" : "bbb" }, // Comment for b | |
| 6 | { "c" : "ccc" } // Comment for c | |
| 7 | ] | |
| 8 | } |
| r0 | r242831 | |
|---|---|---|
| 1 | .={} | |
| 2 | /* C-style comment | |
| 3 | ||
| 4 | C-style-2 comment */ | |
| 5 | .c-test={} | |
| 6 | .c-test.a=1 | |
| 7 | /* Internal comment c-style */ | |
| 8 | .c-test.b=2 | |
| 9 | // C++-style comment | |
| 10 | .cpp-test={} | |
| 11 | // Multiline comment cpp-style | |
| 12 | // Second line | |
| 13 | .cpp-test.c=3 | |
| 14 | .cpp-test.d=4 |
| r0 | r242831 | |
|---|---|---|
| 1 | { | |
| 2 | /* C-style comment | |
| 3 | ||
| 4 | C-style-2 comment */ | |
| 5 | "c-test" : { | |
| 6 | "a" : 1, | |
| 7 | /* Internal comment c-style */ | |
| 8 | "b" : 2 | |
| 9 | }, | |
| 10 | // C++-style comment | |
| 11 | "cpp-test" : { | |
| 12 | // Multiline comment cpp-style | |
| 13 | // Second line | |
| 14 | "c" : 3, | |
| 15 | "d" : 4 | |
| 16 | } | |
| 17 | } |
| r0 | r242831 | |
|---|---|---|
| 1 | .={} | |
| 2 | .attribute=[] | |
| 3 | .attribute[0]="random" | |
| 4 | .attribute[1]="short" | |
| 5 | .attribute[2]="bold" | |
| 6 | .attribute[3]=12 | |
| 7 | .attribute[4]={} | |
| 8 | .attribute[4].height=7 | |
| 9 | .attribute[4].width=64 | |
| 10 | .count=1234 | |
| 11 | .name={} | |
| 12 | .name.aka="T.E.S.T." | |
| 13 | .name.id=123987 | |
| 14 | .test={} | |
| 15 | .test.1={} | |
| 16 | .test.1.2={} | |
| 17 | .test.1.2.3={} | |
| 18 | .test.1.2.3.coord=[] | |
| 19 | .test.1.2.3.coord[0]=1 | |
| 20 | .test.1.2.3.coord[1]=2 |
| r0 | r242831 | |
|---|---|---|
| 1 | { | |
| 2 | "count" : 1234, | |
| 3 | "name" : { "aka" : "T.E.S.T.", "id" : 123987 }, | |
| 4 | "attribute" : [ | |
| 5 | "random", | |
| 6 | "short", | |
| 7 | "bold", | |
| 8 | 12, | |
| 9 | { "height" : 7, "width" : 64 } | |
| 10 | ], | |
| 11 | "test": { "1" : | |
| 12 | { "2" : | |
| 13 | { "3" : { "coord" : [ 1,2] } | |
| 14 | } | |
| 15 | } | |
| 16 | } | |
| 17 | } |
| r0 | r242831 | |
|---|---|---|
| 1 | // Max signed integer | |
| 2 | .=2147483647 |
| r0 | r242831 | |
|---|---|---|
| 1 | // Max signed integer | |
| 2 | 2147483647 |
| r0 | r242831 | |
|---|---|---|
| 1 | // Min signed integer | |
| 2 | .=-2147483648 |
| r0 | r242831 | |
|---|---|---|
| 1 | // Min signed integer | |
| 2 | -2147483648 |
| r0 | r242831 | |
|---|---|---|
| 1 | // Max unsigned integer | |
| 2 | .=4294967295 |
| r0 | r242831 | |
|---|---|---|
| 1 | // Max unsigned integer | |
| 2 | 4294967295 |
| r0 | r242831 | |
|---|---|---|
| 1 | // Min unsigned integer | |
| 2 | .=0 | |
| 3 |
| r0 | r242831 | |
|---|---|---|
| 1 | // Min unsigned integer | |
| 2 | 0 | |
| 3 |
| r0 | r242831 | |
|---|---|---|
| 1 | .=1 | |
| 2 |
| r0 | r242831 | |
|---|---|---|
| 1 | 1 | |
| 2 |
| r0 | r242831 | |
|---|---|---|
| 1 | .=9223372036854775808 |
| r0 | r242831 | |
|---|---|---|
| 1 | 9223372036854775808 | |
| 2 |
| r0 | r242831 | |
|---|---|---|
| 1 | .=-9223372036854775808 |
| r0 | r242831 | |
|---|---|---|
| 1 | -9223372036854775808 | |
| 2 |
| r0 | r242831 | |
|---|---|---|
| 1 | .=18446744073709551615 |
| r0 | r242831 | |
|---|---|---|
| 1 | 18446744073709551615 | |
| 2 |
| r0 | r242831 | |
|---|---|---|
| 1 | .=[] | |
| 2 | .[0]=[] | |
| 3 | .[0][0]="A" | |
| 4 | .[0][1]=0 | |
| 5 | .[0][2]=1 | |
| 6 | .[0][3]=2 | |
| 7 | .[0][4]=3 | |
| 8 | .[0][5]=4 | |
| 9 | .[0][6]=5 | |
| 10 | .[0][7]=6 | |
| 11 | .[0][8]=7 | |
| 12 | .[0][9]=8 | |
| 13 | .[0][10]=9 | |
| 14 | .[0][11]=10 | |
| 15 | .[0][12]=11 | |
| 16 | .[0][13]=12 | |
| 17 | .[0][14]=13 | |
| 18 | .[0][15]=14 | |
| 19 | .[0][16]=15 | |
| 20 | .[0][17]=16 | |
| 21 | .[0][18]=17 | |
| 22 | .[0][19]=18 | |
| 23 | .[0][20]=19 | |
| 24 | .[0][21]=20 | |
| 25 | .[0][22]=21 | |
| 26 | .[0][23]=22 | |
| 27 | .[0][24]=23 | |
| 28 | .[0][25]=24 | |
| 29 | .[0][26]=25 | |
| 30 | .[0][27]=26 | |
| 31 | .[0][28]=27 | |
| 32 | .[0][29]=28 | |
| 33 | .[0][30]=29 | |
| 34 | .[0][31]=30 | |
| 35 | .[0][32]=31 | |
| 36 | .[0][33]=32 | |
| 37 | .[0][34]=33 | |
| 38 | .[0][35]=34 | |
| 39 | .[0][36]=35 | |
| 40 | .[0][37]=36 | |
| 41 | .[0][38]=37 | |
| 42 | .[0][39]=38 | |
| 43 | .[0][40]=39 | |
| 44 | .[0][41]=40 | |
| 45 | .[0][42]=41 | |
| 46 | .[0][43]=42 | |
| 47 | .[0][44]=43 | |
| 48 | .[0][45]=44 | |
| 49 | .[0][46]=45 | |
| 50 | .[0][47]=46 | |
| 51 | .[0][48]=47 | |
| 52 | .[0][49]=48 | |
| 53 | .[0][50]=49 | |
| 54 | .[0][51]=50 | |
| 55 | .[0][52]=51 | |
| 56 | .[0][53]=52 | |
| 57 | .[0][54]=53 | |
| 58 | .[0][55]=54 | |
| 59 | .[0][56]=55 | |
| 60 | .[0][57]=56 | |
| 61 | .[0][58]=57 | |
| 62 | .[0][59]=58 | |
| 63 | .[0][60]=59 | |
| 64 | .[0][61]=60 | |
| 65 | .[0][62]=61 | |
| 66 | .[0][63]=62 | |
| 67 | .[0][64]=63 | |
| 68 | .[0][65]=64 | |
| 69 | .[0][66]=65 | |
| 70 | .[0][67]=66 | |
| 71 | .[0][68]=67 | |
| 72 | .[0][69]=68 | |
| 73 | .[0][70]=69 | |
| 74 | .[0][71]=70 | |
| 75 | .[0][72]=71 | |
| 76 | .[0][73]=72 | |
| 77 | .[0][74]=73 | |
| 78 | .[0][75]=74 | |
| 79 | .[0][76]=75 | |
| 80 | .[0][77]=76 | |
| 81 | .[0][78]=77 | |
| 82 | .[0][79]=78 | |
| 83 | .[0][80]=79 | |
| 84 | .[0][81]=80 | |
| 85 | .[0][82]=81 | |
| 86 | .[0][83]=82 | |
| 87 | .[0][84]=83 | |
| 88 | .[0][85]=84 | |
| 89 | .[0][86]=85 | |
| 90 | .[0][87]=86 | |
| 91 | .[0][88]=87 | |
| 92 | .[0][89]=88 | |
| 93 | .[0][90]=89 | |
| 94 | .[0][91]=90 | |
| 95 | .[0][92]=91 | |
| 96 | .[0][93]=92 | |
| 97 | .[0][94]=93 | |
| 98 | .[0][95]=94 | |
| 99 | .[0][96]=95 | |
| 100 | .[0][97]=96 | |
| 101 | .[0][98]=97 | |
| 102 | .[0][99]=98 | |
| 103 | .[0][100]=99 | |
| 104 | .[0][101]=100 | |
| 105 | .[0][102]=101 | |
| 106 | .[0][103]=102 | |
| 107 | .[0][104]=103 | |
| 108 | .[0][105]=104 | |
| 109 | .[0][106]=105 | |
| 110 | .[0][107]=106 | |
| 111 | .[0][108]=107 | |
| 112 | .[0][109]=108 | |
| 113 | .[0][110]=109 | |
| 114 | .[0][111]=110 | |
| 115 | .[0][112]=111 | |
| 116 | .[0][113]=112 | |
| 117 | .[0][114]=113 | |
| 118 | .[0][115]=114 | |
| 119 | .[0][116]=115 | |
| 120 | .[0][117]=116 | |
| 121 | .[0][118]=117 | |
| 122 | .[0][119]=118 | |
| 123 | .[0][120]=119 | |
| 124 | .[0][121]=120 | |
| 125 | .[0][122]=121 | |
| 126 | .[0][123]=122 | |
| 127 | .[0][124]=123 | |
| 128 | .[0][125]=124 | |
| 129 | .[0][126]=125 | |
| 130 | .[0][127]=126 | |
| 131 | .[0][128]=127 | |
| 132 | .[0][129]=128 | |
| 133 | .[0][130]=129 | |
| 134 | .[0][131]=130 | |
| 135 | .[0][132]=131 | |
| 136 | .[0][133]=132 | |
| 137 | .[0][134]=133 | |
| 138 | .[0][135]=134 | |
| 139 | .[0][136]=135 | |
| 140 | .[0][137]=136 | |
| 141 | .[0][138]=137 | |
| 142 | .[0][139]=138 | |
| 143 | .[0][140]=139 | |
| 144 | .[0][141]=140 | |
| 145 | .[0][142]=141 | |
| 146 | .[0][143]=142 | |
| 147 | .[0][144]=143 | |
| 148 | .[0][145]=144 | |
| 149 | .[0][146]=145 | |
| 150 | .[0][147]=146 | |
| 151 | .[0][148]=147 | |
| 152 | .[0][149]=148 | |
| 153 | .[0][150]=149 | |
| 154 | .[0][151]=150 | |
| 155 | .[0][152]=151 | |
| 156 | .[0][153]=152 | |
| 157 | .[0][154]=153 | |
| 158 | .[0][155]=154 | |
| 159 | .[0][156]=155 | |
| 160 | .[0][157]=156 | |
| 161 | .[0][158]=157 | |
| 162 | .[0][159]=158 | |
| 163 | .[0][160]=159 | |
| 164 | .[0][161]=160 | |
| 165 | .[0][162]=161 | |
| 166 | .[0][163]=162 | |
| 167 | .[0][164]=163 | |
| 168 | .[0][165]=164 | |
| 169 | .[0][166]=165 | |
| 170 | .[0][167]=166 | |
| 171 | .[0][168]=167 | |
| 172 | .[0][169]=168 | |
| 173 | .[0][170]=169 | |
| 174 | .[0][171]=170 | |
| 175 | .[0][172]=171 | |
| 176 | .[0][173]=172 | |
| 177 | .[0][174]=173 | |
| 178 | .[0][175]=174 | |
| 179 | .[0][176]=175 | |
| 180 | .[0][177]=176 | |
| 181 | .[0][178]=177 | |
| 182 | .[0][179]=178 | |
| 183 | .[0][180]=179 | |
| 184 | .[0][181]=180 | |
| 185 | .[0][182]=181 | |
| 186 | .[0][183]=182 | |
| 187 | .[0][184]=183 | |
| 188 | .[0][185]=184 | |
| 189 | .[0][186]=185 | |
| 190 | .[0][187]=186 | |
| 191 | .[0][188]=187 | |
| 192 | .[0][189]=188 | |
| 193 | .[0][190]=189 | |
| 194 | .[0][191]=190 | |
| 195 | .[0][192]=191 | |
| 196 | .[0][193]=192 | |
| 197 | .[0][194]=193 | |
| 198 | .[0][195]=194 | |
| 199 | .[0][196]=195 | |
| 200 | .[0][197]=196 | |
| 201 | .[0][198]=197 | |
| 202 | .[0][199]=198 | |
| 203 | .[0][200]=199 | |
| 204 | .[0][201]=200 | |
| 205 | .[0][202]=201 | |
| 206 | .[0][203]=202 | |
| 207 | .[0][204]=203 | |
| 208 | .[0][205]=204 | |
| 209 | .[0][206]=205 | |
| 210 | .[0][207]=206 | |
| 211 | .[0][208]=207 | |
| 212 | .[0][209]=208 | |
| 213 | .[0][210]=209 | |
| 214 | .[0][211]=210 | |
| 215 | .[0][212]=211 | |
| 216 | .[0][213]=212 | |
| 217 | .[0][214]=213 | |
| 218 | .[0][215]=214 | |
| 219 | .[0][216]=215 | |
| 220 | .[0][217]=216 | |
| 221 | .[0][218]=217 | |
| 222 | .[0][219]=218 | |
| 223 | .[0][220]=219 | |
| 224 | .[0][221]=220 | |
| 225 | .[0][222]=221 | |
| 226 | .[0][223]=222 | |
| 227 | .[0][224]=223 | |
| 228 | .[0][225]=224 | |
| 229 | .[0][226]=225 | |
| 230 | .[0][227]=226 | |
| 231 | .[0][228]=227 | |
| 232 | .[0][229]=228 | |
| 233 | .[0][230]=229 | |
| 234 | .[0][231]=230 | |
| 235 | .[0][232]=231 | |
| 236 | .[0][233]=232 | |
| 237 | .[0][234]=233 | |
| 238 | .[0][235]=234 | |
| 239 | .[0][236]=235 | |
| 240 | .[0][237]=236 | |
| 241 | .[0][238]=237 | |
| 242 | .[0][239]=238 | |
| 243 | .[0][240]=239 | |
| 244 | .[0][241]=240 | |
| 245 | .[0][242]=241 | |
| 246 | .[0][243]=242 | |
| 247 | .[0][244]=243 | |
| 248 | .[0][245]=244 | |
| 249 | .[0][246]=245 | |
| 250 | .[0][247]=246 | |
| 251 | .[0][248]=247 | |
| 252 | .[0][249]=248 | |
| 253 | .[0][250]=249 | |
| 254 | .[0][251]=250 | |
| 255 | .[0][252]=251 | |
| 256 | .[0][253]=252 | |
| 257 | .[0][254]=253 | |
| 258 | .[0][255]=254 | |
| 259 | .[0][256]=255 | |
| 260 | .[0][257]=256 | |
| 261 | .[0][258]=257 | |
| 262 | .[0][259]=258 | |
| 263 | .[0][260]=259 | |
| 264 | .[0][261]=260 | |
| 265 | .[0][262]=261 | |
| 266 | .[0][263]=262 | |
| 267 | .[0][264]=263 | |
| 268 | .[0][265]=264 | |
| 269 | .[0][266]=265 | |
| 270 | .[0][267]=266 | |
| 271 | .[0][268]=267 | |
| 272 | .[0][269]=268 | |
| 273 | .[0][270]=269 | |
| 274 | .[0][271]=270 | |
| 275 | .[0][272]=271 | |
| 276 | .[0][273]=272 | |
| 277 | .[0][274]=273 | |
| 278 | .[0][275]=274 | |
| 279 | .[0][276]=275 | |
| 280 | .[0][277]=276 | |
| 281 | .[0][278]=277 | |
| 282 | .[0][279]=278 | |
| 283 | .[0][280]=279 | |
| 284 | .[0][281]=280 | |
| 285 | .[0][282]=281 | |
| 286 | .[0][283]=282 | |
| 287 | .[0][284]=283 | |
| 288 | .[0][285]=284 | |
| 289 | .[0][286]=285 | |
| 290 | .[0][287]=286 | |
| 291 | .[0][288]=287 | |
| 292 | .[0][289]=288 | |
| 293 | .[0][290]=289 | |
| 294 | .[0][291]=290 | |
| 295 | .[0][292]=291 | |
| 296 | .[0][293]=292 | |
| 297 | .[0][294]=293 | |
| 298 | .[0][295]=294 | |
| 299 | .[0][296]=295 | |
| 300 | .[0][297]=296 | |
| 301 | .[0][298]=297 | |
| 302 | .[0][299]=298 | |
| 303 | .[0][300]=299 | |
| 304 | .[0][301]=300 | |
| 305 | .[0][302]=301 | |
| 306 | .[0][303]=302 | |
| 307 | .[0][304]=303 | |
| 308 | .[0][305]=304 | |
| 309 | .[0][306]=305 | |
| 310 | .[0][307]=306 | |
| 311 | .[0][308]=307 | |
| 312 | .[0][309]=308 | |
| 313 | .[0][310]=309 | |
| 314 | .[0][311]=310 | |
| 315 | .[0][312]=311 | |
| 316 | .[0][313]=312 | |
| 317 | .[0][314]=313 | |
| 318 | .[0][315]=314 | |
| 319 | .[0][316]=315 | |
| 320 | .[0][317]=316 | |
| 321 | .[0][318]=317 | |
| 322 | .[0][319]=318 | |
| 323 | .[0][320]=319 | |
| 324 | .[0][321]=320 | |
| 325 | .[0][322]=321 | |
| 326 | .[0][323]=322 | |
| 327 | .[0][324]=323 | |
| 328 | .[0][325]=324 | |
| 329 | .[0][326]=325 | |
| 330 | .[0][327]=326 | |
| 331 | .[0][328]=327 | |
| 332 | .[0][329]=328 | |
| 333 | .[0][330]=329 | |
| 334 | .[0][331]=330 | |
| 335 | .[0][332]=331 | |
| 336 | .[0][333]=332 | |
| 337 | .[0][334]=333 | |
| 338 | .[0][335]=334 | |
| 339 | .[0][336]=335 | |
| 340 | .[0][337]=336 | |
| 341 | .[0][338]=337 | |
| 342 | .[0][339]=338 | |
| 343 | .[0][340]=339 | |
| 344 | .[0][341]=340 | |
| 345 | .[0][342]=341 | |
| 346 | .[0][343]=342 | |
| 347 | .[0][344]=343 | |
| 348 | .[0][345]=344 | |
| 349 | .[0][346]=345 | |
| 350 | .[0][347]=346 | |
| 351 | .[0][348]=347 | |
| 352 | .[0][349]=348 | |
| 353 | .[0][350]=349 | |
| 354 | .[0][351]=350 | |
| 355 | .[0][352]=351 | |
| 356 | .[0][353]=352 | |
| 357 | .[0][354]=353 | |
| 358 | .[0][355]=354 | |
| 359 | .[0][356]=355 | |
| 360 | .[0][357]=356 | |
| 361 | .[0][358]=357 | |
| 362 | .[0][359]=358 | |
| 363 | .[0][360]=359 | |
| 364 | .[0][361]=360 | |
| 365 | .[0][362]=361 | |
| 366 | .[0][363]=362 | |
| 367 | .[0][364]=363 | |
| 368 | .[0][365]=364 | |
| 369 | .[0][366]=365 | |
| 370 | .[0][367]=366 | |
| 371 | .[0][368]=367 | |
| 372 | .[0][369]=368 | |
| 373 | .[0][370]=369 | |
| 374 | .[0][371]=370 | |
| 375 | .[0][372]=371 | |
| 376 | .[0][373]=372 | |
| 377 | .[0][374]=373 | |
| 378 | .[0][375]=374 | |
| 379 | .[0][376]=375 | |
| 380 | .[0][377]=376 | |
| 381 | .[0][378]=377 | |
| 382 | .[0][379]=378 | |
| 383 | .[0][380]=379 | |
| 384 | .[0][381]=380 | |
| 385 | .[0][382]=381 | |
| 386 | .[0][383]=382 | |
| 387 | .[0][384]=383 | |
| 388 | .[0][385]=384 | |
| 389 | .[0][386]=385 | |
| 390 | .[0][387]=386 | |
| 391 | .[0][388]=387 | |
| 392 | .[0][389]=388 | |
| 393 | .[0][390]=389 | |
| 394 | .[0][391]=390 | |
| 395 | .[0][392]=391 | |
| 396 | .[0][393]=392 | |
| 397 | .[0][394]=393 | |
| 398 | .[0][395]=394 | |
| 399 | .[0][396]=395 | |
| 400 | .[0][397]=396 | |
| 401 | .[0][398]=397 | |
| 402 | .[0][399]=398 | |
| 403 | .[0][400]=399 | |
| 404 | .[0][401]=400 | |
| 405 | .[0][402]=401 | |
| 406 | .[0][403]=402 | |
| 407 | .[0][404]=403 | |
| 408 | .[0][405]=404 | |
| 409 | .[0][406]=405 | |
| 410 | .[0][407]=406 | |
| 411 | .[0][408]=407 | |
| 412 | .[0][409]=408 | |
| 413 | .[0][410]=409 | |
| 414 | .[0][411]=410 | |
| 415 | .[0][412]=411 | |
| 416 | .[0][413]=412 | |
| 417 | .[0][414]=413 | |
| 418 | .[0][415]=414 | |
| 419 | .[0][416]=415 | |
| 420 | .[0][417]=416 | |
| 421 | .[0][418]=417 | |
| 422 | .[0][419]=418 | |
| 423 | .[0][420]=419 | |
| 424 | .[0][421]=420 | |
| 425 | .[0][422]=421 | |
| 426 | .[0][423]=422 | |
| 427 | .[0][424]=423 | |
| 428 | .[0][425]=424 | |
| 429 | .[0][426]=425 | |
| 430 | .[0][427]=426 | |
| 431 | .[0][428]=427 | |
| 432 | .[0][429]=428 | |
| 433 | .[0][430]=429 | |
| 434 | .[0][431]=430 | |
| 435 | .[0][432]=431 | |
| 436 | .[0][433]=432 | |
| 437 | .[0][434]=433 | |
| 438 | .[0][435]=434 | |
| 439 | .[0][436]=435 | |
| 440 | .[0][437]=436 | |
| 441 | .[0][438]=437 | |
| 442 | .[0][439]=438 | |
| 443 | .[0][440]=439 | |
| 444 | .[0][441]=440 | |
| 445 | .[0][442]=441 | |
| 446 | .[0][443]=442 | |
| 447 | .[0][444]=443 | |
| 448 | .[0][445]=444 | |
| 449 | .[0][446]=445 | |
| 450 | .[0][447]=446 | |
| 451 | .[0][448]=447 | |
| 452 | .[0][449]=448 | |
| 453 | .[0][450]=449 | |
| 454 | .[0][451]=450 | |
| 455 | .[0][452]=451 | |
| 456 | .[0][453]=452 | |
| 457 | .[0][454]=453 | |
| 458 | .[0][455]=454 | |
| 459 | .[0][456]=455 | |
| 460 | .[0][457]=456 | |
| 461 | .[0][458]=457 | |
| 462 | .[0][459]=458 | |
| 463 | .[0][460]=459 | |
| 464 | .[0][461]=460 | |
| 465 | .[0][462]=461 | |
| 466 | .[0][463]=462 | |
| 467 | .[0][464]=463 | |
| 468 | .[0][465]=464 | |
| 469 | .[0][466]=465 | |
| 470 | .[0][467]=466 | |
| 471 | .[0][468]=467 | |
| 472 | .[0][469]=468 | |
| 473 | .[0][470]=469 | |
| 474 | .[0][471]=470 | |
| 475 | .[0][472]=471 | |
| 476 | .[0][473]=472 | |
| 477 | .[0][474]=473 | |
| 478 | .[0][475]=474 | |
| 479 | .[0][476]=475 | |
| 480 | .[0][477]=476 | |
| 481 | .[0][478]=477 | |
| 482 | .[0][479]=478 | |
| 483 | .[0][480]=479 | |
| 484 | .[0][481]=480 | |
| 485 | .[0][482]=481 | |
| 486 | .[0][483]=482 | |
| 487 | .[0][484]=483 | |
| 488 | .[0][485]=484 | |
| 489 | .[0][486]=485 | |
| 490 | .[0][487]=486 | |
| 491 | .[0][488]=487 | |
| 492 | .[0][489]=488 | |
| 493 | .[0][490]=489 | |
| 494 | .[0][491]=490 | |
| 495 | .[0][492]=491 | |
| 496 | .[0][493]=492 | |
| 497 | .[0][494]=493 | |
| 498 | .[0][495]=494 | |
| 499 | .[0][496]=495 | |
| 500 | .[0][497]=496 | |
| 501 | .[0][498]=497 | |
| 502 | .[0][499]=498 | |
| 503 | .[0][500]=499 | |
| 504 | .[0][501]=500 | |
| 505 | .[0][502]=501 | |
| 506 | .[0][503]=502 | |
| 507 | .[0][504]=503 | |
| 508 | .[0][505]=504 | |
| 509 | .[0][506]=505 | |
| 510 | .[0][507]=506 | |
| 511 | .[0][508]=507 | |
| 512 | .[0][509]=508 | |
| 513 | .[0][510]=509 | |
| 514 | .[0][511]=510 | |
| 515 | .[0][512]=511 | |
| 516 | .[0][513]=512 | |
| 517 | .[0][514]=513 | |
| 518 | .[0][515]=514 | |
| 519 | .[0][516]=515 | |
| 520 | .[0][517]=516 | |
| 521 | .[0][518]=517 | |
| 522 | .[0][519]=518 | |
| 523 | .[0][520]=519 | |
| 524 | .[0][521]=520 | |
| 525 | .[0][522]=521 | |
| 526 | .[0][523]=522 | |
| 527 | .[0][524]=523 | |
| 528 | .[0][525]=524 | |
| 529 | .[0][526]=525 | |
| 530 | .[0][527]=526 | |
| 531 | .[0][528]=527 | |
| 532 | .[0][529]=528 | |
| 533 | .[0][530]=529 | |
| 534 | .[0][531]=530 | |
| 535 | .[0][532]=531 | |
| 536 | .[0][533]=532 | |
| 537 | .[0][534]=533 | |
| 538 | .[0][535]=534 | |
| 539 | .[0][536]=535 | |
| 540 | .[0][537]=536 | |
| 541 | .[0][538]=537 | |
| 542 | .[0][539]=538 | |
| 543 | .[0][540]=539 | |
| 544 | .[0][541]=540 | |
| 545 | .[0][542]=541 | |
| 546 | .[0][543]=542 | |
| 547 | .[0][544]=543 | |
| 548 | .[0][545]=544 | |
| 549 | .[0][546]=545 | |
| 550 | .[0][547]=546 | |
| 551 | .[0][548]=547 | |
| 552 | .[0][549]=548 | |
| 553 | .[0][550]=549 | |
| 554 | .[0][551]=550 | |
| 555 | .[0][552]=551 | |
| 556 | .[0][553]=552 | |
| 557 | .[0][554]=553 | |
| 558 | .[0][555]=554 | |
| 559 | .[0][556]=555 | |
| 560 | .[0][557]=556 | |
| 561 | .[0][558]=557 | |
| 562 | .[0][559]=558 | |
| 563 | .[0][560]=559 | |
| 564 | .[0][561]=560 | |
| 565 | .[0][562]=561 | |
| 566 | .[0][563]=562 | |
| 567 | .[0][564]=563 | |
| 568 | .[0][565]=564 | |
| 569 | .[0][566]=565 | |
| 570 | .[0][567]=566 | |
| 571 | .[0][568]=567 | |
| 572 | .[0][569]=568 | |
| 573 | .[0][570]=569 | |
| 574 | .[0][571]=570 | |
| 575 | .[0][572]=571 | |
| 576 | .[0][573]=572 | |
| 577 | .[0][574]=573 | |
| 578 | .[0][575]=574 | |
| 579 | .[0][576]=575 | |
| 580 | .[0][577]=576 | |
| 581 | .[0][578]=577 | |
| 582 | .[0][579]=578 | |
| 583 | .[0][580]=579 | |
| 584 | .[0][581]=580 | |
| 585 | .[0][582]=581 | |
| 586 | .[0][583]=582 | |
| 587 | .[0][584]=583 | |
| 588 | .[0][585]=584 | |
| 589 | .[0][586]=585 | |
| 590 | .[0][587]=586 | |
| 591 | .[0][588]=587 | |
| 592 | .[0][589]=588 | |
| 593 | .[0][590]=589 | |
| 594 | .[0][591]=590 | |
| 595 | .[0][592]=591 | |
| 596 | .[0][593]=592 | |
| 597 | .[0][594]=593 | |
| 598 | .[0][595]=594 | |
| 599 | .[0][596]=595 | |
| 600 | .[0][597]=596 | |
| 601 | .[0][598]=597 | |
| 602 | .[0][599]=598 | |
| 603 | .[0][600]=599 | |
| 604 | .[0][601]=600 | |
| 605 | .[0][602]=601 | |
| 606 | .[0][603]=602 | |
| 607 | .[0][604]=603 | |
| 608 | .[0][605]=604 | |
| 609 | .[0][606]=605 | |
| 610 | .[0][607]=606 | |
| 611 | .[0][608]=607 | |
| 612 | .[0][609]=608 | |
| 613 | .[0][610]=609 | |
| 614 | .[0][611]=610 | |
| 615 | .[0][612]=611 | |
| 616 | .[0][613]=612 | |
| 617 | .[0][614]=613 | |
| 618 | .[0][615]=614 | |
| 619 | .[0][616]=615 | |
| 620 | .[0][617]=616 | |
| 621 | .[0][618]=617 | |
| 622 | .[0][619]=618 | |
| 623 | .[0][620]=619 | |
| 624 | .[0][621]=620 | |
| 625 | .[0][622]=621 | |
| 626 | .[0][623]=622 | |
| 627 | .[0][624]=623 | |
| 628 | .[0][625]=624 | |
| 629 | .[0][626]=625 | |
| 630 | .[0][627]=626 | |
| 631 | .[0][628]=627 | |
| 632 | .[0][629]=628 | |
| 633 | .[0][630]=629 | |
| 634 | .[0][631]=630 | |
| 635 | .[0][632]=631 | |
| 636 | .[0][633]=632 | |
| 637 | .[0][634]=633 | |
| 638 | .[0][635]=634 | |
| 639 | .[0][636]=635 | |
| 640 | .[0][637]=636 | |
| 641 | .[0][638]=637 | |
| 642 | .[0][639]=638 | |
| 643 | .[0][640]=639 | |
| 644 | .[0][641]=640 | |
| 645 | .[0][642]=641 | |
| 646 | .[0][643]=642 | |
| 647 | .[0][644]=643 | |
| 648 | .[0][645]=644 | |
| 649 | .[0][646]=645 | |
| 650 | .[0][647]=646 | |
| 651 | .[0][648]=647 | |
| 652 | .[0][649]=648 | |
| 653 | .[0][650]=649 | |
| 654 | .[0][651]=650 | |
| 655 | .[0][652]=651 | |
| 656 | .[0][653]=652 | |
| 657 | .[0][654]=653 | |
| 658 | .[0][655]=654 | |
| 659 | .[0][656]=655 | |
| 660 | .[0][657]=656 | |
| 661 | .[0][658]=657 | |
| 662 | .[0][659]=658 | |
| 663 | .[0][660]=659 | |
| 664 | .[0][661]=660 | |
| 665 | .[0][662]=661 | |
| 666 | .[0][663]=662 | |
| 667 | .[0][664]=663 | |
| 668 | .[0][665]=664 | |
| 669 | .[0][666]=665 | |
| 670 | .[0][667]=666 | |
| 671 | .[0][668]=667 | |
| 672 | .[0][669]=668 | |
| 673 | .[0][670]=669 | |
| 674 | .[0][671]=670 | |
| 675 | .[0][672]=671 | |
| 676 | .[0][673]=672 | |
| 677 | .[0][674]=673 | |
| 678 | .[0][675]=674 | |
| 679 | .[0][676]=675 | |
| 680 | .[0][677]=676 | |
| 681 | .[0][678]=677 | |
| 682 | .[0][679]=678 | |
| 683 | .[0][680]=679 | |
| 684 | .[0][681]=680 | |
| 685 | .[0][682]=681 | |
| 686 | .[0][683]=682 | |
| 687 | .[0][684]=683 | |
| 688 | .[0][685]=684 | |
| 689 | .[0][686]=685 | |
| 690 | .[0][687]=686 | |
| 691 | .[0][688]=687 | |
| 692 | .[0][689]=688 | |
| 693 | .[0][690]=689 | |
| 694 | .[0][691]=690 | |
| 695 | .[0][692]=691 | |
| 696 | .[0][693]=692 | |
| 697 | .[0][694]=693 | |
| 698 | .[0][695]=694 | |
| 699 | .[0][696]=695 | |
| 700 | .[0][697]=696 | |
| 701 | .[0][698]=697 | |
| 702 | .[0][699]=698 | |
| 703 | .[0][700]=699 | |
| 704 | .[0][701]=700 | |
| 705 | .[0][702]=701 | |
| 706 | .[0][703]=702 | |
| 707 | .[0][704]=703 | |
| 708 | .[0][705]=704 | |
| 709 | .[0][706]=705 | |
| 710 | .[0][707]=706 | |
| 711 | .[0][708]=707 | |
| 712 | .[0][709]=708 | |
| 713 | .[0][710]=709 | |
| 714 | .[0][711]=710 | |
| 715 | .[0][712]=711 | |
| 716 | .[0][713]=712 | |
| 717 | .[0][714]=713 | |
| 718 | .[0][715]=714 | |
| 719 | .[0][716]=715 | |
| 720 | .[0][717]=716 | |
| 721 | .[0][718]=717 | |
| 722 | .[0][719]=718 | |
| 723 | .[0][720]=719 | |
| 724 | .[0][721]=720 | |
| 725 | .[0][722]=721 | |
| 726 | .[0][723]=722 | |
| 727 | .[0][724]=723 | |
| 728 | .[0][725]=724 | |
| 729 | .[0][726]=725 | |
| 730 | .[0][727]=726 | |
| 731 | .[0][728]=727 | |
| 732 | .[0][729]=728 | |
| 733 | .[0][730]=729 | |
| 734 | .[0][731]=730 | |
| 735 | .[0][732]=731 | |
| 736 | .[0][733]=732 | |
| 737 | .[0][734]=733 | |
| 738 | .[0][735]=734 | |
| 739 | .[0][736]=735 | |
| 740 | .[0][737]=736 | |
| 741 | .[0][738]=737 | |
| 742 | .[0][739]=738 | |
| 743 | .[0][740]=739 | |
| 744 | .[0][741]=740 | |
| 745 | .[0][742]=741 | |
| 746 | .[0][743]=742 | |
| 747 | .[0][744]=743 | |
| 748 | .[0][745]=744 | |
| 749 | .[0][746]=745 | |
| 750 | .[0][747]=746 | |
| 751 | .[0][748]=747 | |
| 752 | .[0][749]=748 | |
| 753 | .[0][750]=749 | |
| 754 | .[0][751]=750 | |
| 755 | .[0][752]=751 | |
| 756 | .[0][753]=752 | |
| 757 | .[0][754]=753 | |
| 758 | .[0][755]=754 | |
| 759 | .[0][756]=755 | |
| 760 | .[0][757]=756 | |
| 761 | .[0][758]=757 | |
| 762 | .[0][759]=758 | |
| 763 | .[0][760]=759 | |
| 764 | .[0][761]=760 | |
| 765 | .[0][762]=761 | |
| 766 | .[0][763]=762 | |
| 767 | .[0][764]=763 | |
| 768 | .[0][765]=764 | |
| 769 | .[0][766]=765 | |
| 770 | .[0][767]=766 | |
| 771 | .[0][768]=767 | |
| 772 | .[0][769]=768 | |
| 773 | .[0][770]=769 | |
| 774 | .[0][771]=770 | |
| 775 | .[0][772]=771 | |
| 776 | .[0][773]=772 | |
| 777 | .[0][774]=773 | |
| 778 | .[0][775]=774 | |
| 779 | .[0][776]=775 | |
| 780 | .[0][777]=776 | |
| 781 | .[0][778]=777 | |
| 782 | .[0][779]=778 | |
| 783 | .[0][780]=779 | |
| 784 | .[0][781]=780 | |
| 785 | .[0][782]=781 | |
| 786 | .[0][783]=782 | |
| 787 | .[0][784]=783 | |
| 788 | .[0][785]=784 | |
| 789 | .[0][786]=785 | |
| 790 | .[0][787]=786 | |
| 791 | .[0][788]=787 | |
| 792 | .[0][789]=788 | |
| 793 | .[0][790]=789 | |
| 794 | .[0][791]=790 | |
| 795 | .[0][792]=791 | |
| 796 | .[0][793]=792 | |
| 797 | .[0][794]=793 | |
| 798 | .[0][795]=794 | |
| 799 | .[0][796]=795 | |
| 800 | .[0][797]=796 | |
| 801 | .[0][798]=797 | |
| 802 | .[0][799]=798 | |
| 803 | .[0][800]=799 | |
| 804 | .[0][801]=800 | |
| 805 | .[0][802]=801 | |
| 806 | .[0][803]=802 | |
| 807 | .[0][804]=803 | |
| 808 | .[0][805]=804 | |
| 809 | .[0][806]=805 | |
| 810 | .[0][807]=806 | |
| 811 | .[0][808]=807 | |
| 812 | .[0][809]=808 | |
| 813 | .[0][810]=809 | |
| 814 | .[0][811]=810 | |
| 815 | .[0][812]=811 | |
| 816 | .[0][813]=812 | |
| 817 | .[0][814]=813 | |
| 818 | .[0][815]=814 | |
| 819 | .[0][816]=815 | |
| 820 | .[0][817]=816 | |
| 821 | .[0][818]=817 | |
| 822 | .[0][819]=818 | |
| 823 | .[0][820]=819 | |
| 824 | .[0][821]=820 | |
| 825 | .[0][822]=821 | |
| 826 | .[0][823]=822 | |
| 827 | .[0][824]=823 | |
| 828 | .[0][825]=824 | |
| 829 | .[0][826]=825 | |
| 830 | .[0][827]=826 | |
| 831 | .[0][828]=827 | |
| 832 | .[0][829]=828 | |
| 833 | .[0][830]=829 | |
| 834 | .[0][831]=830 | |
| 835 | .[0][832]=831 | |
| 836 | .[0][833]=832 | |
| 837 | .[0][834]=833 | |
| 838 | .[0][835]=834 | |
| 839 | .[0][836]=835 | |
| 840 | .[0][837]=836 | |
| 841 | .[0][838]=837 | |
| 842 | .[0][839]=838 | |
| 843 | .[0][840]=839 | |
| 844 | .[0][841]=840 | |
| 845 | .[0][842]=841 | |
| 846 | .[0][843]=842 | |
| 847 | .[0][844]=843 | |
| 848 | .[0][845]=844 | |
| 849 | .[0][846]=845 | |
| 850 | .[0][847]=846 | |
| 851 | .[0][848]=847 | |
| 852 | .[0][849]=848 | |
| 853 | .[0][850]=849 | |
| 854 | .[0][851]=850 | |
| 855 | .[0][852]=851 | |
| 856 | .[0][853]=852 | |
| 857 | .[0][854]=853 | |
| 858 | .[0][855]=854 | |
| 859 | .[0][856]=855 | |
| 860 | .[0][857]=856 | |
| 861 | .[0][858]=857 | |
| 862 | .[0][859]=858 | |
| 863 | .[0][860]=859 | |
| 864 | .[0][861]=860 | |
| 865 | .[0][862]=861 | |
| 866 | .[0][863]=862 | |
| 867 | .[0][864]=863 | |
| 868 | .[0][865]=864 | |
| 869 | .[0][866]=865 | |
| 870 | .[0][867]=866 | |
| 871 | .[0][868]=867 | |
| 872 | .[0][869]=868 | |
| 873 | .[0][870]=869 | |
| 874 | .[0][871]=870 | |
| 875 | .[0][872]=871 | |
| 876 | .[0][873]=872 | |
| 877 | .[0][874]=873 | |
| 878 | .[0][875]=874 | |
| 879 | .[0][876]=875 | |
| 880 | .[0][877]=876 | |
| 881 | .[0][878]=877 | |
| 882 | .[0][879]=878 | |
| 883 | .[0][880]=879 | |
| 884 | .[0][881]=880 | |
| 885 | .[0][882]=881 | |
| 886 | .[0][883]=882 | |
| 887 | .[0][884]=883 | |
| 888 | .[0][885]=884 | |
| 889 | .[0][886]=885 | |
| 890 | .[0][887]=886 | |
| 891 | .[0][888]=887 | |
| 892 | .[0][889]=888 | |
| 893 | .[0][890]=889 | |
| 894 | .[0][891]=890 | |
| 895 | .[0][892]=891 | |
| 896 | .[0][893]=892 | |
| 897 | .[0][894]=893 | |
| 898 | .[0][895]=894 | |
| 899 | .[0][896]=895 | |
| 900 | .[0][897]=896 | |
| 901 | .[0][898]=897 | |
| 902 | .[0][899]=898 | |
| 903 | .[0][900]=899 | |
| 904 | .[0][901]=900 | |
| 905 | .[0][902]=901 | |
| 906 | .[0][903]=902 | |
| 907 | .[0][904]=903 | |
| 908 | .[0][905]=904 | |
| 909 | .[0][906]=905 | |
| 910 | .[0][907]=906 | |
| 911 | .[0][908]=907 | |
| 912 | .[0][909]=908 | |
| 913 | .[0][910]=909 | |
| 914 | .[0][911]=910 | |
| 915 | .[0][912]=911 | |
| 916 | .[0][913]=912 | |
| 917 | .[0][914]=913 | |
| 918 | .[0][915]=914 | |
| 919 | .[0][916]=915 | |
| 920 | .[0][917]=916 | |
| 921 | .[0][918]=917 | |
| 922 | .[0][919]=918 | |
| 923 | .[0][920]=919 | |
| 924 | .[0][921]=920 | |
| 925 | .[0][922]=921 | |
| 926 | .[0][923]=922 | |
| 927 | .[0][924]=923 | |
| 928 | .[0][925]=924 | |
| 929 | .[0][926]=925 | |
| 930 | .[0][927]=926 | |
| 931 | .[0][928]=927 | |
| 932 | .[0][929]=928 | |
| 933 | .[0][930]=929 | |
| 934 | .[0][931]=930 | |
| 935 | .[0][932]=931 | |
| 936 | .[0][933]=932 | |
| 937 | .[0][934]=933 | |
| 938 | .[0][935]=934 | |
| 939 | .[0][936]=935 | |
| 940 | .[0][937]=936 | |
| 941 | .[0][938]=937 | |
| 942 | .[0][939]=938 | |
| 943 | .[0][940]=939 | |
| 944 | .[0][941]=940 | |
| 945 | .[0][942]=941 | |
| 946 | .[0][943]=942 | |
| 947 | .[0][944]=943 | |
| 948 | .[0][945]=944 | |
| 949 | .[0][946]=945 | |
| 950 | .[0][947]=946 | |
| 951 | .[0][948]=947 | |
| 952 | .[0][949]=948 | |
| 953 | .[0][950]=949 | |
| 954 | .[0][951]=950 | |
| 955 | .[0][952]=951 | |
| 956 | .[0][953]=952 | |
| 957 | .[0][954]=953 | |
| 958 | .[0][955]=954 | |
| 959 | .[0][956]=955 | |
| 960 | .[0][957]=956 | |
| 961 | .[0][958]=957 | |
| 962 | .[0][959]=958 | |
| 963 | .[0][960]=959 | |
| 964 | .[0][961]=960 | |
| 965 | .[0][962]=961 | |
| 966 | .[0][963]=962 | |
| 967 | .[0][964]=963 | |
| 968 | .[0][965]=964 | |
| 969 | .[0][966]=965 | |
| 970 | .[0][967]=966 | |
| 971 | .[0][968]=967 | |
| 972 | .[0][969]=968 | |
| 973 | .[0][970]=969 | |
| 974 | .[0][971]=970 | |
| 975 | .[0][972]=971 | |
| 976 | .[0][973]=972 | |
| 977 | .[0][974]=973 | |
| 978 | .[0][975]=974 | |
| 979 | .[0][976]=975 | |
| 980 | .[0][977]=976 | |
| 981 | .[0][978]=977 | |
| 982 | .[0][979]=978 | |
| 983 | .[0][980]=979 | |
| 984 | .[0][981]=980 | |
| 985 | .[0][982]=981 | |
| 986 | .[0][983]=982 | |
| 987 | .[0][984]=983 | |
| 988 | .[0][985]=984 | |
| 989 | .[0][986]=985 | |
| 990 | .[0][987]=986 | |
| 991 | .[0][988]=987 | |
| 992 | .[0][989]=988 | |
| 993 | .[0][990]=989 | |
| 994 | .[0][991]=990 | |
| 995 | .[0][992]=991 | |
| 996 | .[0][993]=992 | |
| 997 | .[0][994]=993 | |
| 998 | .[0][995]=994 | |
| 999 | .[0][996]=995 | |
| 1000 | .[0][997]=996 | |
| 1001 | .[0][998]=997 | |
| 1002 | .[0][999]=998 | |
| 1003 | .[0][1000]=999 | |
| 1004 | .[0][1001]=1000 | |
| 1005 | .[0][1002]=1001 | |
| 1006 | .[0][1003]=1002 | |
| 1007 | .[0][1004]=1003 | |
| 1008 | .[0][1005]=1004 | |
| 1009 | .[0][1006]=1005 | |
| 1010 | .[0][1007]=1006 | |
| 1011 | .[0][1008]=1007 | |
| 1012 | .[0][1009]=1008 | |
| 1013 | .[0][1010]=1009 | |
| 1014 | .[0][1011]=1010 | |
| 1015 | .[0][1012]=1011 | |
| 1016 | .[0][1013]=1012 | |
| 1017 | .[0][1014]=1013 | |
| 1018 | .[0][1015]=1014 | |
| 1019 | .[0][1016]=1015 | |
| 1020 | .[0][1017]=1016 | |
| 1021 | .[0][1018]=1017 | |
| 1022 | .[0][1019]=1018 | |
| 1023 | .[0][1020]=1019 | |
| 1024 | .[0][1021]=1020 | |
| 1025 | .[0][1022]=1021 | |
| 1026 | .[0][1023]=1022 | |
| 1027 | .[0][1024]=1023 | |
| 1028 | .[0][1025]=1024 | |
| 1029 | .[0][1026]=1025 | |
| 1030 | .[0][1027]=1026 | |
| 1031 | .[0][1028]=1027 | |
| 1032 | .[0][1029]=1028 | |
| 1033 | .[0][1030]=1029 | |
| 1034 | .[0][1031]=1030 | |
| 1035 | .[0][1032]=1031 | |
| 1036 | .[0][1033]=1032 | |
| 1037 | .[0][1034]=1033 | |
| 1038 | .[0][1035]=1034 | |
| 1039 | .[0][1036]=1035 | |
| 1040 | .[0][1037]=1036 | |
| 1041 | .[0][1038]=1037 | |
| 1042 | .[0][1039]=1038 | |
| 1043 | .[0][1040]=1039 | |
| 1044 | .[0][1041]=1040 | |
| 1045 | .[0][1042]=1041 | |
| 1046 | .[0][1043]=1042 | |
| 1047 | .[0][1044]=1043 | |
| 1048 | .[0][1045]=1044 | |
| 1049 | .[0][1046]=1045 | |
| 1050 | .[0][1047]=1046 | |
| 1051 | .[0][1048]=1047 | |
| 1052 | .[0][1049]=1048 | |
| 1053 | .[0][1050]=1049 | |
| 1054 | .[0][1051]=1050 | |
| 1055 | .[0][1052]=1051 | |
| 1056 | .[0][1053]=1052 | |
| 1057 | .[0][1054]=1053 | |
| 1058 | .[0][1055]=1054 | |
| 1059 | .[0][1056]=1055 | |
| 1060 | .[0][1057]=1056 | |
| 1061 | .[0][1058]=1057 | |
| 1062 | .[0][1059]=1058 | |
| 1063 | .[0][1060]=1059 | |
| 1064 | .[0][1061]=1060 | |
| 1065 | .[0][1062]=1061 | |
| 1066 | .[0][1063]=1062 | |
| 1067 | .[0][1064]=1063 | |
| 1068 | .[0][1065]=1064 | |
| 1069 | .[0][1066]=1065 | |
| 1070 | .[0][1067]=1066 | |
| 1071 | .[0][1068]=1067 | |
| 1072 | .[0][1069]=1068 | |
| 1073 | .[0][1070]=1069 | |
| 1074 | .[0][1071]=1070 | |
| 1075 | .[0][1072]=1071 | |
| 1076 | .[0][1073]=1072 | |
| 1077 | .[0][1074]=1073 | |
| 1078 | .[0][1075]=1074 | |
| 1079 | .[0][1076]=1075 | |
| 1080 | .[0][1077]=1076 | |
| 1081 | .[0][1078]=1077 | |
| 1082 | .[0][1079]=1078 | |
| 1083 | .[0][1080]=1079 | |
| 1084 | .[0][1081]=1080 | |
| 1085 | .[0][1082]=1081 | |
| 1086 | .[0][1083]=1082 | |
| 1087 | .[0][1084]=1083 | |
| 1088 | .[0][1085]=1084 | |
| 1089 | .[0][1086]=1085 | |
| 1090 | .[0][1087]=1086 | |
| 1091 | .[0][1088]=1087 | |
| 1092 | .[0][1089]=1088 | |
| 1093 | .[0][1090]=1089 | |
| 1094 | .[0][1091]=1090 | |
| 1095 | .[0][1092]=1091 | |
| 1096 | .[0][1093]=1092 | |
| 1097 | .[0][1094]=1093 | |
| 1098 | .[0][1095]=1094 | |
| 1099 | .[0][1096]=1095 | |
| 1100 | .[0][1097]=1096 | |
| 1101 | .[0][1098]=1097 | |
| 1102 | .[0][1099]=1098 | |
| 1103 | .[0][1100]=1099 | |
| 1104 | .[0][1101]=1100 | |
| 1105 | .[0][1102]=1101 | |
| 1106 | .[0][1103]=1102 | |
| 1107 | .[0][1104]=1103 | |
| 1108 | .[0][1105]=1104 | |
| 1109 | .[0][1106]=1105 | |
| 1110 | .[0][1107]=1106 | |
| 1111 | .[0][1108]=1107 | |
| 1112 | .[0][1109]=1108 | |
| 1113 | .[0][1110]=1109 | |
| 1114 | .[0][1111]=1110 | |
| 1115 | .[0][1112]=1111 | |
| 1116 | .[0][1113]=1112 | |
| 1117 | .[0][1114]=1113 | |
| 1118 | .[0][1115]=1114 | |
| 1119 | .[0][1116]=1115 | |
| 1120 | .[0][1117]=1116 | |
| 1121 | .[0][1118]=1117 | |
| 1122 | .[0][1119]=1118 | |
| 1123 | .[0][1120]=1119 | |
| 1124 | .[0][1121]=1120 | |
| 1125 | .[0][1122]=1121 | |
| 1126 | .[0][1123]=1122 | |
| 1127 | .[0][1124]=1123 | |
| 1128 | .[0][1125]=1124 | |
| 1129 | .[0][1126]=1125 | |
| 1130 | .[0][1127]=1126 | |
| 1131 | .[0][1128]=1127 | |
| 1132 | .[0][1129]=1128 | |
| 1133 | .[0][1130]=1129 | |
| 1134 | .[0][1131]=1130 | |
| 1135 | .[0][1132]=1131 | |
| 1136 | .[0][1133]=1132 | |
| 1137 | .[0][1134]=1133 | |
| 1138 | .[0][1135]=1134 | |
| 1139 | .[0][1136]=1135 | |
| 1140 | .[0][1137]=1136 | |
| 1141 | .[0][1138]=1137 | |
| 1142 | .[0][1139]=1138 | |
| 1143 | .[0][1140]=1139 | |
| 1144 | .[0][1141]=1140 | |
| 1145 | .[0][1142]=1141 | |
| 1146 | .[0][1143]=1142 | |
| 1147 | .[0][1144]=1143 | |
| 1148 | .[0][1145]=1144 | |
| 1149 | .[0][1146]=1145 | |
| 1150 | .[0][1147]=1146 | |
| 1151 | .[0][1148]=1147 | |
| 1152 | .[0][1149]=1148 | |
| 1153 | .[0][1150]=1149 | |
| 1154 | .[0][1151]=1150 | |
| 1155 | .[0][1152]=1151 | |
| 1156 | .[0][1153]=1152 | |
| 1157 | .[0][1154]=1153 | |
| 1158 | .[0][1155]=1154 | |
| 1159 | .[0][1156]=1155 | |
| 1160 | .[0][1157]=1156 | |
| 1161 | .[0][1158]=1157 | |
| 1162 | .[0][1159]=1158 | |
| 1163 | .[0][1160]=1159 | |
| 1164 | .[0][1161]=1160 | |
| 1165 | .[0][1162]=1161 | |
| 1166 | .[0][1163]=1162 | |
| 1167 | .[0][1164]=1163 | |
| 1168 | .[0][1165]=1164 | |
| 1169 | .[0][1166]=1165 | |
| 1170 | .[0][1167]=1166 | |
| 1171 | .[0][1168]=1167 | |
| 1172 | .[0][1169]=1168 | |
| 1173 | .[0][1170]=1169 | |
| 1174 | .[0][1171]=1170 | |
| 1175 | .[0][1172]=1171 | |
| 1176 | .[0][1173]=1172 | |
| 1177 | .[0][1174]=1173 | |
| 1178 | .[0][1175]=1174 | |
| 1179 | .[0][1176]=1175 | |
| 1180 | .[0][1177]=1176 | |
| 1181 | .[0][1178]=1177 | |
| 1182 | .[0][1179]=1178 | |
| 1183 | .[0][1180]=1179 | |
| 1184 | .[0][1181]=1180 | |
| 1185 | .[0][1182]=1181 | |
| 1186 | .[0][1183]=1182 | |
| 1187 | .[0][1184]=1183 | |
| 1188 | .[0][1185]=1184 | |
| 1189 | .[0][1186]=1185 | |
| 1190 | .[0][1187]=1186 | |
| 1191 | .[0][1188]=1187 | |
| 1192 | .[0][1189]=1188 | |
| 1193 | .[0][1190]=1189 | |
| 1194 | .[0][1191]=1190 | |
| 1195 | .[0][1192]=1191 | |
| 1196 | .[0][1193]=1192 | |
| 1197 | .[0][1194]=1193 | |
| 1198 | .[0][1195]=1194 | |
| 1199 | .[0][1196]=1195 | |
| 1200 | .[0][1197]=1196 | |
| 1201 | .[0][1198]=1197 | |
| 1202 | .[0][1199]=1198 | |
| 1203 | .[0][1200]=1199 | |
| 1204 | .[0][1201]=1200 | |
| 1205 | .[0][1202]=1201 | |
| 1206 | .[0][1203]=1202 | |
| 1207 | .[0][1204]=1203 | |
| 1208 | .[0][1205]=1204 | |
| 1209 | .[0][1206]=1205 | |
| 1210 | .[0][1207]=1206 | |
| 1211 | .[0][1208]=1207 | |
| 1212 | .[0][1209]=1208 | |
| 1213 | .[0][1210]=1209 | |
| 1214 | .[0][1211]=1210 | |
| 1215 | .[0][1212]=1211 | |
| 1216 | .[0][1213]=1212 | |
| 1217 | .[0][1214]=1213 | |
| 1218 | .[0][1215]=1214 | |
| 1219 | .[0][1216]=1215 | |
| 1220 | .[0][1217]=1216 | |
| 1221 | .[0][1218]=1217 | |
| 1222 | .[0][1219]=1218 | |
| 1223 | .[0][1220]=1219 | |
| 1224 | .[0][1221]=1220 | |
| 1225 | .[0][1222]=1221 | |
| 1226 | .[0][1223]=1222 | |
| 1227 | .[0][1224]=1223 | |
| 1228 | .[0][1225]=1224 | |
| 1229 | .[0][1226]=1225 | |
| 1230 | .[0][1227]=1226 | |
| 1231 | .[0][1228]=1227 | |
| 1232 | .[0][1229]=1228 | |
| 1233 | .[0][1230]=1229 | |
| 1234 | .[0][1231]=1230 | |
| 1235 | .[0][1232]=1231 | |
| 1236 | .[0][1233]=1232 | |
| 1237 | .[0][1234]=1233 | |
| 1238 | .[0][1235]=1234 | |
| 1239 | .[0][1236]=1235 | |
| 1240 | .[0][1237]=1236 | |
| 1241 | .[0][1238]=1237 | |
| 1242 | .[0][1239]=1238 | |
| 1243 | .[0][1240]=1239 | |
| 1244 | .[0][1241]=1240 | |
| 1245 | .[0][1242]=1241 | |
| 1246 | .[0][1243]=1242 | |
| 1247 | .[0][1244]=1243 | |
| 1248 | .[0][1245]=1244 | |
| 1249 | .[0][1246]=1245 | |
| 1250 | .[0][1247]=1246 | |
| 1251 | .[0][1248]=1247 | |
| 1252 | .[0][1249]=1248 | |
| 1253 | .[0][1250]=1249 | |
| 1254 | .[0][1251]=1250 | |
| 1255 | .[0][1252]=1251 | |
| 1256 | .[0][1253]=1252 | |
| 1257 | .[0][1254]=1253 | |
| 1258 | .[0][1255]=1254 | |
| 1259 | .[0][1256]=1255 | |
| 1260 | .[0][1257]=1256 | |
| 1261 | .[0][1258]=1257 | |
| 1262 | .[0][1259]=1258 | |
| 1263 | .[0][1260]=1259 | |
| 1264 | .[0][1261]=1260 | |
| 1265 | .[0][1262]=1261 | |
| 1266 | .[0][1263]=1262 | |
| 1267 | .[0][1264]=1263 | |
| 1268 | .[0][1265]=1264 | |
| 1269 | .[0][1266]=1265 | |
| 1270 | .[0][1267]=1266 | |
| 1271 | .[0][1268]=1267 | |
| 1272 | .[0][1269]=1268 | |
| 1273 | .[0][1270]=1269 | |
| 1274 | .[0][1271]=1270 | |
| 1275 | .[0][1272]=1271 | |
| 1276 | .[0][1273]=1272 | |
| 1277 | .[0][1274]=1273 | |
| 1278 | .[0][1275]=1274 | |
| 1279 | .[0][1276]=1275 | |
| 1280 | .[0][1277]=1276 | |
| 1281 | .[0][1278]=1277 | |
| 1282 | .[0][1279]=1278 | |
| 1283 | .[0][1280]=1279 | |
| 1284 | .[0][1281]=1280 | |
| 1285 | .[0][1282]=1281 | |
| 1286 | .[0][1283]=1282 | |
| 1287 | .[0][1284]=1283 | |
| 1288 | .[0][1285]=1284 | |
| 1289 | .[0][1286]=1285 | |
| 1290 | .[0][1287]=1286 | |
| 1291 | .[0][1288]=1287 | |
| 1292 | .[0][1289]=1288 | |
| 1293 | .[0][1290]=1289 | |
| 1294 | .[0][1291]=1290 | |
| 1295 | .[0][1292]=1291 | |
| 1296 | .[0][1293]=1292 | |
| 1297 | .[0][1294]=1293 | |
| 1298 | .[0][1295]=1294 | |
| 1299 | .[0][1296]=1295 | |
| 1300 | .[0][1297]=1296 | |
| 1301 | .[0][1298]=1297 | |
| 1302 | .[0][1299]=1298 | |
| 1303 | .[0][1300]=1299 | |
| 1304 | .[0][1301]=1300 | |
| 1305 | .[0][1302]=1301 | |
| 1306 | .[0][1303]=1302 | |
| 1307 | .[0][1304]=1303 | |
| 1308 | .[0][1305]=1304 | |
| 1309 | .[0][1306]=1305 | |
| 1310 | .[0][1307]=1306 | |
| 1311 | .[0][1308]=1307 | |
| 1312 | .[0][1309]=1308 | |
| 1313 | .[0][1310]=1309 | |
| 1314 | .[0][1311]=1310 | |
| 1315 | .[0][1312]=1311 | |
| 1316 | .[0][1313]=1312 | |
| 1317 | .[0][1314]=1313 | |
| 1318 | .[0][1315]=1314 | |
| 1319 | .[0][1316]=1315 | |
| 1320 | .[0][1317]=1316 | |
| 1321 | .[0][1318]=1317 | |
| 1322 | .[0][1319]=1318 | |
| 1323 | .[0][1320]=1319 | |
| 1324 | .[0][1321]=1320 | |
| 1325 | .[0][1322]=1321 | |
| 1326 | .[0][1323]=1322 | |
| 1327 | .[0][1324]=1323 | |
| 1328 | .[0][1325]=1324 | |
| 1329 | .[0][1326]=1325 | |
| 1330 | .[0][1327]=1326 | |
| 1331 | .[0][1328]=1327 | |
| 1332 | .[0][1329]=1328 | |
| 1333 | .[0][1330]=1329 | |
| 1334 | .[0][1331]=1330 | |
| 1335 | .[0][1332]=1331 | |
| 1336 | .[0][1333]=1332 | |
| 1337 | .[0][1334]=1333 | |
| 1338 | .[0][1335]=1334 | |
| 1339 | .[0][1336]=1335 | |
| 1340 | .[0][1337]=1336 | |
| 1341 | .[0][1338]=1337 | |
| 1342 | .[0][1339]=1338 | |
| 1343 | .[0][1340]=1339 | |
| 1344 | .[0][1341]=1340 | |
| 1345 | .[0][1342]=1341 | |
| 1346 | .[0][1343]=1342 | |
| 1347 | .[0][1344]=1343 | |
| 1348 | .[0][1345]=1344 | |
| 1349 | .[0][1346]=1345 | |
| 1350 | .[0][1347]=1346 | |
| 1351 | .[0][1348]=1347 | |
| 1352 | .[0][1349]=1348 | |
| 1353 | .[0][1350]=1349 | |
| 1354 | .[0][1351]=1350 | |
| 1355 | .[0][1352]=1351 | |
| 1356 | .[0][1353]=1352 | |
| 1357 | .[0][1354]=1353 | |
| 1358 | .[0][1355]=1354 | |
| 1359 | .[0][1356]=1355 | |
| 1360 | .[0][1357]=1356 | |
| 1361 | .[0][1358]=1357 | |
| 1362 | .[0][1359]=1358 | |
| 1363 | .[0][1360]=1359 | |
| 1364 | .[0][1361]=1360 | |
| 1365 | .[0][1362]=1361 | |
| 1366 | .[0][1363]=1362 | |
| 1367 | .[0][1364]=1363 | |
| 1368 | .[0][1365]=1364 | |
| 1369 | .[0][1366]=1365 | |
| 1370 | .[0][1367]=1366 | |
| 1371 | .[0][1368]=1367 | |
| 1372 | .[0][1369]=1368 | |
| 1373 | .[0][1370]=1369 | |
| 1374 | .[0][1371]=1370 | |
| 1375 | .[0][1372]=1371 | |
| 1376 | .[0][1373]=1372 | |
| 1377 | .[0][1374]=1373 | |
| 1378 | .[0][1375]=1374 | |
| 1379 | .[0][1376]=1375 | |
| 1380 | .[0][1377]=1376 | |
| 1381 | .[0][1378]=1377 | |
| 1382 | .[0][1379]=1378 | |
| 1383 | .[0][1380]=1379 | |
| 1384 | .[0][1381]=1380 | |
| 1385 | .[0][1382]=1381 | |
| 1386 | .[0][1383]=1382 | |
| 1387 | .[0][1384]=1383 | |
| 1388 | .[0][1385]=1384 | |
| 1389 | .[0][1386]=1385 | |
| 1390 | .[0][1387]=1386 | |
| 1391 | .[0][1388]=1387 | |
| 1392 | .[0][1389]=1388 | |
| 1393 | .[0][1390]=1389 | |
| 1394 | .[0][1391]=1390 | |
| 1395 | .[0][1392]=1391 | |
| 1396 | .[0][1393]=1392 | |
| 1397 | .[0][1394]=1393 | |
| 1398 | .[0][1395]=1394 | |
| 1399 | .[0][1396]=1395 | |
| 1400 | .[0][1397]=1396 | |
| 1401 | .[0][1398]=1397 | |
| 1402 | .[0][1399]=1398 | |
| 1403 | .[0][1400]=1399 | |
| 1404 | .[0][1401]=1400 | |
| 1405 | .[0][1402]=1401 | |
| 1406 | .[0][1403]=1402 | |
| 1407 | .[0][1404]=1403 | |
| 1408 | .[0][1405]=1404 | |
| 1409 | .[0][1406]=1405 | |
| 1410 | .[0][1407]=1406 | |
| 1411 | .[0][1408]=1407 | |
| 1412 | .[0][1409]=1408 | |
| 1413 | .[0][1410]=1409 | |
| 1414 | .[0][1411]=1410 | |
| 1415 | .[0][1412]=1411 | |
| 1416 | .[0][1413]=1412 | |
| 1417 | .[0][1414]=1413 | |
| 1418 | .[0][1415]=1414 | |
| 1419 | .[0][1416]=1415 | |
| 1420 | .[0][1417]=1416 | |
| 1421 | .[0][1418]=1417 | |
| 1422 | .[0][1419]=1418 | |
| 1423 | .[0][1420]=1419 | |
| 1424 | .[0][1421]=1420 | |
| 1425 | .[0][1422]=1421 | |
| 1426 | .[0][1423]=1422 | |
| 1427 | .[0][1424]=1423 | |
| 1428 | .[0][1425]=1424 | |
| 1429 | .[0][1426]=1425 | |
| 1430 | .[0][1427]=1426 | |
| 1431 | .[0][1428]=1427 | |
| 1432 | .[0][1429]=1428 | |
| 1433 | .[0][1430]=1429 | |
| 1434 | .[0][1431]=1430 | |
| 1435 | .[0][1432]=1431 | |
| 1436 | .[0][1433]=1432 | |
| 1437 | .[0][1434]=1433 | |
| 1438 | .[0][1435]=1434 | |
| 1439 | .[0][1436]=1435 | |
| 1440 | .[0][1437]=1436 | |
| 1441 | .[0][1438]=1437 | |
| 1442 | .[0][1439]=1438 | |
| 1443 | .[0][1440]=1439 | |
| 1444 | .[0][1441]=1440 | |
| 1445 | .[0][1442]=1441 | |
| 1446 | .[0][1443]=1442 | |
| 1447 | .[0][1444]=1443 | |
| 1448 | .[0][1445]=1444 | |
| 1449 | .[0][1446]=1445 | |
| 1450 | .[0][1447]=1446 | |
| 1451 | .[0][1448]=1447 | |
| 1452 | .[0][1449]=1448 | |
| 1453 | .[0][1450]=1449 | |
| 1454 | .[0][1451]=1450 | |
| 1455 | .[0][1452]=1451 | |
| 1456 | .[0][1453]=1452 | |
| 1457 | .[0][1454]=1453 | |
| 1458 | .[0][1455]=1454 | |
| 1459 | .[0][1456]=1455 | |
| 1460 | .[0][1457]=1456 | |
| 1461 | .[0][1458]=1457 | |
| 1462 | .[0][1459]=1458 | |
| 1463 | .[0][1460]=1459 | |
| 1464 | .[0][1461]=1460 | |
| 1465 | .[0][1462]=1461 | |
| 1466 | .[0][1463]=1462 | |
| 1467 | .[0][1464]=1463 | |
| 1468 | .[0][1465]=1464 | |
| 1469 | .[0][1466]=1465 | |
| 1470 | .[0][1467]=1466 | |
| 1471 | .[0][1468]=1467 | |
| 1472 | .[0][1469]=1468 | |
| 1473 | .[0][1470]=1469 | |
| 1474 | .[0][1471]=1470 | |
| 1475 | .[0][1472]=1471 | |
| 1476 | .[0][1473]=1472 | |
| 1477 | .[0][1474]=1473 | |
| 1478 | .[0][1475]=1474 | |
| 1479 | .[0][1476]=1475 | |
| 1480 | .[0][1477]=1476 | |
| 1481 | .[0][1478]=1477 | |
| 1482 | .[0][1479]=1478 | |
| 1483 | .[0][1480]=1479 | |
| 1484 | .[0][1481]=1480 | |
| 1485 | .[0][1482]=1481 | |
| 1486 | .[0][1483]=1482 | |
| 1487 | .[0][1484]=1483 | |
| 1488 | .[0][1485]=1484 | |
| 1489 | .[0][1486]=1485 | |
| 1490 | .[0][1487]=1486 | |
| 1491 | .[0][1488]=1487 | |
| 1492 | .[0][1489]=1488 | |
| 1493 | .[0][1490]=1489 | |
| 1494 | .[0][1491]=1490 | |
| 1495 | .[0][1492]=1491 | |
| 1496 | .[0][1493]=1492 | |
| 1497 | .[0][1494]=1493 | |
| 1498 | .[0][1495]=1494 | |
| 1499 | .[0][1496]=1495 | |
| 1500 | .[0][1497]=1496 | |
| 1501 | .[0][1498]=1497 | |
| 1502 | .[0][1499]=1498 | |
| 1503 | .[0][1500]=1499 | |
| 1504 | .[0][1501]=1500 | |
| 1505 | .[0][1502]=1501 | |
| 1506 | .[0][1503]=1502 | |
| 1507 | .[0][1504]=1503 | |
| 1508 | .[0][1505]=1504 | |
| 1509 | .[0][1506]=1505 | |
| 1510 | .[0][1507]=1506 | |
| 1511 | .[0][1508]=1507 | |
| 1512 | .[0][1509]=1508 | |
| 1513 | .[0][1510]=1509 | |
| 1514 | .[0][1511]=1510 | |
| 1515 | .[0][1512]=1511 | |
| 1516 | .[0][1513]=1512 | |
| 1517 | .[0][1514]=1513 | |
| 1518 | .[0][1515]=1514 | |
| 1519 | .[0][1516]=1515 | |
| 1520 | .[0][1517]=1516 | |
| 1521 | .[0][1518]=1517 | |
| 1522 | .[0][1519]=1518 | |
| 1523 | .[0][1520]=1519 | |
| 1524 | .[0][1521]=1520 | |
| 1525 | .[0][1522]=1521 | |
| 1526 | .[0][1523]=1522 | |
| 1527 | .[0][1524]=1523 | |
| 1528 | .[0][1525]=1524 | |
| 1529 | .[0][1526]=1525 | |
| 1530 | .[0][1527]=1526 | |
| 1531 | .[0][1528]=1527 | |
| 1532 | .[0][1529]=1528 | |
| 1533 | .[0][1530]=1529 | |
| 1534 | .[0][1531]=1530 | |
| 1535 | .[0][1532]=1531 | |
| 1536 | .[0][1533]=1532 | |
| 1537 | .[0][1534]=1533 | |
| 1538 | .[0][1535]=1534 | |
| 1539 | .[0][1536]=1535 | |
| 1540 | .[0][1537]=1536 | |
| 1541 | .[0][1538]=1537 | |
| 1542 | .[0][1539]=1538 | |
| 1543 | .[0][1540]=1539 | |
| 1544 | .[0][1541]=1540 | |
| 1545 | .[0][1542]=1541 | |
| 1546 | .[0][1543]=1542 | |
| 1547 | .[0][1544]=1543 | |
| 1548 | .[0][1545]=1544 | |
| 1549 | .[0][1546]=1545 | |
| 1550 | .[0][1547]=1546 | |
| 1551 | .[0][1548]=1547 | |
| 1552 | .[0][1549]=1548 | |
| 1553 | .[0][1550]=1549 | |
| 1554 | .[0][1551]=1550 | |
| 1555 | .[0][1552]=1551 | |
| 1556 | .[0][1553]=1552 | |
| 1557 | .[0][1554]=1553 | |
| 1558 | .[0][1555]=1554 | |
| 1559 | .[0][1556]=1555 | |
| 1560 | .[0][1557]=1556 | |
| 1561 | .[0][1558]=1557 | |
| 1562 | .[0][1559]=1558 | |
| 1563 | .[0][1560]=1559 | |
| 1564 | .[0][1561]=1560 | |
| 1565 | .[0][1562]=1561 | |
| 1566 | .[0][1563]=1562 | |
| 1567 | .[0][1564]=1563 | |
| 1568 | .[0][1565]=1564 | |
| 1569 | .[0][1566]=1565 | |
| 1570 | .[0][1567]=1566 | |
| 1571 | .[0][1568]=1567 | |
| 1572 | .[0][1569]=1568 | |
| 1573 | .[0][1570]=1569 | |
| 1574 | .[0][1571]=1570 | |
| 1575 | .[0][1572]=1571 | |
| 1576 | .[0][1573]=1572 | |
| 1577 | .[0][1574]=1573 | |
| 1578 | .[0][1575]=1574 | |
| 1579 | .[0][1576]=1575 | |
| 1580 | .[0][1577]=1576 | |
| 1581 | .[0][1578]=1577 | |
| 1582 | .[0][1579]=1578 | |
| 1583 | .[0][1580]=1579 | |
| 1584 | .[0][1581]=1580 | |
| 1585 | .[0][1582]=1581 | |
| 1586 | .[0][1583]=1582 | |
| 1587 | .[0][1584]=1583 | |
| 1588 | .[0][1585]=1584 | |
| 1589 | .[0][1586]=1585 | |
| 1590 | .[0][1587]=1586 | |
| 1591 | .[0][1588]=1587 | |
| 1592 | .[0][1589]=1588 | |
| 1593 | .[0][1590]=1589 | |
| 1594 | .[0][1591]=1590 | |
| 1595 | .[0][1592]=1591 | |
| 1596 | .[0][1593]=1592 | |
| 1597 | .[0][1594]=1593 | |
| 1598 | .[0][1595]=1594 | |
| 1599 | .[0][1596]=1595 | |
| 1600 | .[0][1597]=1596 | |
| 1601 | .[0][1598]=1597 | |
| 1602 | .[0][1599]=1598 | |
| 1603 | .[0][1600]=1599 | |
| 1604 | .[0][1601]=1600 | |
| 1605 | .[0][1602]=1601 | |
| 1606 | .[0][1603]=1602 | |
| 1607 | .[0][1604]=1603 | |
| 1608 | .[0][1605]=1604 | |
| 1609 | .[0][1606]=1605 | |
| 1610 | .[0][1607]=1606 | |
| 1611 | .[0][1608]=1607 | |
| 1612 | .[0][1609]=1608 | |
| 1613 | .[0][1610]=1609 | |
| 1614 | .[0][1611]=1610 | |
| 1615 | .[0][1612]=1611 | |
| 1616 | .[0][1613]=1612 | |
| 1617 | .[0][1614]=1613 | |
| 1618 | .[0][1615]=1614 | |
| 1619 | .[0][1616]=1615 | |
| 1620 | .[0][1617]=1616 | |
| 1621 | .[0][1618]=1617 | |
| 1622 | .[0][1619]=1618 | |
| 1623 | .[0][1620]=1619 | |
| 1624 | .[0][1621]=1620 | |
| 1625 | .[0][1622]=1621 | |
| 1626 | .[0][1623]=1622 | |
| 1627 | .[0][1624]=1623 | |
| 1628 | .[0][1625]=1624 | |
| 1629 | .[0][1626]=1625 | |
| 1630 | .[0][1627]=1626 | |
| 1631 | .[0][1628]=1627 | |
| 1632 | .[0][1629]=1628 | |
| 1633 | .[0][1630]=1629 | |
| 1634 | .[0][1631]=1630 | |
| 1635 | .[0][1632]=1631 | |
| 1636 | .[0][1633]=1632 | |
| 1637 | .[0][1634]=1633 | |
| 1638 | .[0][1635]=1634 | |
| 1639 | .[0][1636]=1635 | |
| 1640 | .[0][1637]=1636 | |
| 1641 | .[0][1638]=1637 | |
| 1642 | .[0][1639]=1638 | |
| 1643 | .[0][1640]=1639 | |
| 1644 | .[0][1641]=1640 | |
| 1645 | .[0][1642]=1641 | |
| 1646 | .[0][1643]=1642 | |
| 1647 | .[0][1644]=1643 | |
| 1648 | .[0][1645]=1644 | |
| 1649 | .[0][1646]=1645 | |
| 1650 | .[0][1647]=1646 | |
| 1651 | .[0][1648]=1647 | |
| 1652 | .[0][1649]=1648 | |
| 1653 | .[0][1650]=1649 | |
| 1654 | .[0][1651]=1650 | |
| 1655 | .[0][1652]=1651 | |
| 1656 | .[0][1653]=1652 | |
| 1657 | .[0][1654]=1653 | |
| 1658 | .[0][1655]=1654 | |
| 1659 | .[0][1656]=1655 | |
| 1660 | .[0][1657]=1656 | |
| 1661 | .[0][1658]=1657 | |
| 1662 | .[0][1659]=1658 | |
| 1663 | .[0][1660]=1659 | |
| 1664 | .[0][1661]=1660 | |
| 1665 | .[0][1662]=1661 | |
| 1666 | .[0][1663]=1662 | |
| 1667 | .[0][1664]=1663 | |
| 1668 | .[0][1665]=1664 | |
| 1669 | .[0][1666]=1665 | |
| 1670 | .[0][1667]=1666 | |
| 1671 | .[0][1668]=1667 | |
| 1672 | .[0][1669]=1668 | |
| 1673 | .[0][1670]=1669 | |
| 1674 | .[0][1671]=1670 | |
| 1675 | .[0][1672]=1671 | |
| 1676 | .[0][1673]=1672 | |
| 1677 | .[0][1674]=1673 | |
| 1678 | .[0][1675]=1674 | |
| 1679 | .[0][1676]=1675 | |
| 1680 | .[0][1677]=1676 | |
| 1681 | .[0][1678]=1677 | |
| 1682 | .[0][1679]=1678 | |
| 1683 | .[0][1680]=1679 | |
| 1684 | .[0][1681]=1680 | |
| 1685 | .[0][1682]=1681 | |
| 1686 | .[0][1683]=1682 | |
| 1687 | .[0][1684]=1683 | |
| 1688 | .[0][1685]=1684 | |
| 1689 | .[0][1686]=1685 | |
| 1690 | .[0][1687]=1686 | |
| 1691 | .[0][1688]=1687 | |
| 1692 | .[0][1689]=1688 | |
| 1693 | .[0][1690]=1689 | |
| 1694 | .[0][1691]=1690 | |
| 1695 | .[0][1692]=1691 | |
| 1696 | .[0][1693]=1692 | |
| 1697 | .[0][1694]=1693 | |
| 1698 | .[0][1695]=1694 | |
| 1699 | .[0][1696]=1695 | |
| 1700 | .[0][1697]=1696 | |
| 1701 | .[0][1698]=1697 | |
| 1702 | .[0][1699]=1698 | |
| 1703 | .[0][1700]=1699 | |
| 1704 | .[0][1701]=1700 | |
| 1705 | .[0][1702]=1701 | |
| 1706 | .[0][1703]=1702 | |
| 1707 | .[0][1704]=1703 | |
| 1708 | .[0][1705]=1704 | |
| 1709 | .[0][1706]=1705 | |
| 1710 | .[0][1707]=1706 | |
| 1711 | .[0][1708]=1707 | |
| 1712 | .[0][1709]=1708 | |
| 1713 | .[0][1710]=1709 | |
| 1714 | .[0][1711]=1710 | |
| 1715 | .[0][1712]=1711 | |
| 1716 | .[0][1713]=1712 | |
| 1717 | .[0][1714]=1713 | |
| 1718 | .[0][1715]=1714 | |
| 1719 | .[0][1716]=1715 | |
| 1720 | .[0][1717]=1716 | |
| 1721 | .[0][1718]=1717 | |
| 1722 | .[0][1719]=1718 | |
| 1723 | .[0][1720]=1719 | |
| 1724 | .[0][1721]=1720 | |
| 1725 | .[0][1722]=1721 | |
| 1726 | .[0][1723]=1722 | |
| 1727 | .[0][1724]=1723 | |
| 1728 | .[0][1725]=1724 | |
| 1729 | .[0][1726]=1725 | |
| 1730 | .[0][1727]=1726 | |
| 1731 | .[0][1728]=1727 | |
| 1732 | .[0][1729]=1728 | |
| 1733 | .[0][1730]=1729 | |
| 1734 | .[0][1731]=1730 | |
| 1735 | .[0][1732]=1731 | |
| 1736 | .[0][1733]=1732 | |
| 1737 | .[0][1734]=1733 | |
| 1738 | .[0][1735]=1734 | |
| 1739 | .[0][1736]=1735 | |
| 1740 | .[0][1737]=1736 | |
| 1741 | .[0][1738]=1737 | |
| 1742 | .[0][1739]=1738 | |
| 1743 | .[0][1740]=1739 | |
| 1744 | .[0][1741]=1740 | |
| 1745 | .[0][1742]=1741 | |
| 1746 | .[0][1743]=1742 | |
| 1747 | .[0][1744]=1743 | |
| 1748 | .[0][1745]=1744 | |
| 1749 | .[0][1746]=1745 | |
| 1750 | .[0][1747]=1746 | |
| 1751 | .[0][1748]=1747 | |
| 1752 | .[0][1749]=1748 | |
| 1753 | .[0][1750]=1749 | |
| 1754 | .[0][1751]=1750 | |
| 1755 | .[0][1752]=1751 | |
| 1756 | .[0][1753]=1752 | |
| 1757 | .[0][1754]=1753 | |
| 1758 | .[0][1755]=1754 | |
| 1759 | .[0][1756]=1755 | |
| 1760 | .[0][1757]=1756 | |
| 1761 | .[0][1758]=1757 | |
| 1762 | .[0][1759]=1758 | |
| 1763 | .[0][1760]=1759 | |
| 1764 | .[0][1761]=1760 | |
| 1765 | .[0][1762]=1761 | |
| 1766 | .[0][1763]=1762 | |
| 1767 | .[0][1764]=1763 | |
| 1768 | .[0][1765]=1764 | |
| 1769 | .[0][1766]=1765 | |
| 1770 | .[0][1767]=1766 | |
| 1771 | .[0][1768]=1767 | |
| 1772 | .[0][1769]=1768 | |
| 1773 | .[0][1770]=1769 | |
| 1774 | .[0][1771]=1770 | |
| 1775 | .[0][1772]=1771 | |
| 1776 | .[0][1773]=1772 | |
| 1777 | .[0][1774]=1773 | |
| 1778 | .[0][1775]=1774 | |
| 1779 | .[0][1776]=1775 | |
| 1780 | .[0][1777]=1776 | |
| 1781 | .[0][1778]=1777 | |
| 1782 | .[0][1779]=1778 | |
| 1783 | .[0][1780]=1779 | |
| 1784 | .[0][1781]=1780 | |
| 1785 | .[0][1782]=1781 | |
| 1786 | .[0][1783]=1782 | |
| 1787 | .[0][1784]=1783 | |
| 1788 | .[0][1785]=1784 | |
| 1789 | .[0][1786]=1785 | |
| 1790 | .[0][1787]=1786 | |
| 1791 | .[0][1788]=1787 | |
| 1792 | .[0][1789]=1788 | |
| 1793 | .[0][1790]=1789 | |
| 1794 | .[0][1791]=1790 | |
| 1795 | .[0][1792]=1791 | |
| 1796 | .[0][1793]=1792 | |
| 1797 | .[0][1794]=1793 | |
| 1798 | .[0][1795]=1794 | |
| 1799 | .[0][1796]=1795 | |
| 1800 | .[0][1797]=1796 | |
| 1801 | .[0][1798]=1797 | |
| 1802 | .[0][1799]=1798 | |
| 1803 | .[0][1800]=1799 | |
| 1804 | .[0][1801]=1800 | |
| 1805 | .[0][1802]=1801 | |
| 1806 | .[0][1803]=1802 | |
| 1807 | .[0][1804]=1803 | |
| 1808 | .[0][1805]=1804 | |
| 1809 | .[0][1806]=1805 | |
| 1810 | .[0][1807]=1806 | |
| 1811 | .[0][1808]=1807 | |
| 1812 | .[0][1809]=1808 | |
| 1813 | .[0][1810]=1809 | |
| 1814 | .[0][1811]=1810 | |
| 1815 | .[0][1812]=1811 | |
| 1816 | .[0][1813]=1812 | |
| 1817 | .[0][1814]=1813 | |
| 1818 | .[0][1815]=1814 | |
| 1819 | .[0][1816]=1815 | |
| 1820 | .[0][1817]=1816 | |
| 1821 | .[0][1818]=1817 | |
| 1822 | .[0][1819]=1818 | |
| 1823 | .[0][1820]=1819 | |
| 1824 | .[0][1821]=1820 | |
| 1825 | .[0][1822]=1821 | |
| 1826 | .[0][1823]=1822 | |
| 1827 | .[0][1824]=1823 | |
| 1828 | .[0][1825]=1824 | |
| 1829 | .[0][1826]=1825 | |
| 1830 | .[0][1827]=1826 | |
| 1831 | .[0][1828]=1827 | |
| 1832 | .[0][1829]=1828 | |
| 1833 | .[0][1830]=1829 | |
| 1834 | .[0][1831]=1830 | |
| 1835 | .[0][1832]=1831 | |
| 1836 | .[0][1833]=1832 | |
| 1837 | .[0][1834]=1833 | |
| 1838 | .[0][1835]=1834 | |
| 1839 | .[0][1836]=1835 | |
| 1840 | .[0][1837]=1836 | |
| 1841 | .[0][1838]=1837 | |
| 1842 | .[0][1839]=1838 | |
| 1843 | .[0][1840]=1839 | |
| 1844 | .[0][1841]=1840 | |
| 1845 | .[0][1842]=1841 | |
| 1846 | .[0][1843]=1842 | |
| 1847 | .[0][1844]=1843 | |
| 1848 | .[0][1845]=1844 | |
| 1849 | .[0][1846]=1845 | |
| 1850 | .[0][1847]=1846 | |
| 1851 | .[0][1848]=1847 | |
| 1852 | .[0][1849]=1848 | |
| 1853 | .[0][1850]=1849 | |
| 1854 | .[0][1851]=1850 | |
| 1855 | .[0][1852]=1851 | |
| 1856 | .[0][1853]=1852 | |
| 1857 | .[0][1854]=1853 | |
| 1858 | .[0][1855]=1854 | |
| 1859 | .[0][1856]=1855 | |
| 1860 | .[0][1857]=1856 | |
| 1861 | .[0][1858]=1857 | |
| 1862 | .[0][1859]=1858 | |
| 1863 | .[0][1860]=1859 | |
| 1864 | .[0][1861]=1860 | |
| 1865 | .[0][1862]=1861 | |
| 1866 | .[0][1863]=1862 | |
| 1867 | .[0][1864]=1863 | |
| 1868 | .[0][1865]=1864 | |
| 1869 | .[0][1866]=1865 | |
| 1870 | .[0][1867]=1866 | |
| 1871 | .[0][1868]=1867 | |
| 1872 | .[0][1869]=1868 | |
| 1873 | .[0][1870]=1869 | |
| 1874 | .[0][1871]=1870 | |
| 1875 | .[0][1872]=1871 | |
| 1876 | .[0][1873]=1872 | |
| 1877 | .[0][1874]=1873 | |
| 1878 | .[0][1875]=1874 | |
| 1879 | .[0][1876]=1875 | |
| 1880 | .[0][1877]=1876 | |
| 1881 | .[0][1878]=1877 | |
| 1882 | .[0][1879]=1878 | |
| 1883 | .[0][1880]=1879 | |
| 1884 | .[0][1881]=1880 | |
| 1885 | .[0][1882]=1881 | |
| 1886 | .[0][1883]=1882 | |
| 1887 | .[0][1884]=1883 | |
| 1888 | .[0][1885]=1884 | |
| 1889 | .[0][1886]=1885 | |
| 1890 | .[0][1887]=1886 | |
| 1891 | .[0][1888]=1887 | |
| 1892 | .[0][1889]=1888 | |
| 1893 | .[0][1890]=1889 | |
| 1894 | .[0][1891]=1890 | |
| 1895 | .[0][1892]=1891 | |
| 1896 | .[0][1893]=1892 | |
| 1897 | .[0][1894]=1893 | |
| 1898 | .[0][1895]=1894 | |
| 1899 | .[0][1896]=1895 | |
| 1900 | .[0][1897]=1896 | |
| 1901 | .[0][1898]=1897 | |
| 1902 | .[0][1899]=1898 | |
| 1903 | .[0][1900]=1899 | |
| 1904 | .[0][1901]=1900 | |
| 1905 | .[0][1902]=1901 | |
| 1906 | .[0][1903]=1902 | |
| 1907 | .[0][1904]=1903 | |
| 1908 | .[0][1905]=1904 | |
| 1909 | .[0][1906]=1905 | |
| 1910 | .[0][1907]=1906 | |
| 1911 | .[0][1908]=1907 | |
| 1912 | .[0][1909]=1908 | |
| 1913 | .[0][1910]=1909 | |
| 1914 | .[0][1911]=1910 | |
| 1915 | .[0][1912]=1911 | |
| 1916 | .[0][1913]=1912 | |
| 1917 | .[0][1914]=1913 | |
| 1918 | .[0][1915]=1914 | |
| 1919 | .[0][1916]=1915 | |
| 1920 | .[0][1917]=1916 | |
| 1921 | .[0][1918]=1917 | |
| 1922 | .[0][1919]=1918 | |
| 1923 | .[0][1920]=1919 | |
| 1924 | .[0][1921]=1920 | |
| 1925 | .[0][1922]=1921 | |
| 1926 | .[0][1923]=1922 | |
| 1927 | .[0][1924]=1923 | |
| 1928 | .[0][1925]=1924 | |
| 1929 | .[0][1926]=1925 | |
| 1930 | .[0][1927]=1926 | |
| 1931 | .[0][1928]=1927 | |
| 1932 | .[0][1929]=1928 | |
| 1933 | .[0][1930]=1929 | |
| 1934 | .[0][1931]=1930 | |
| 1935 | .[0][1932]=1931 | |
| 1936 | .[0][1933]=1932 | |
| 1937 | .[0][1934]=1933 | |
| 1938 | .[0][1935]=1934 | |
| 1939 | .[0][1936]=1935 | |
| 1940 | .[0][1937]=1936 | |
| 1941 | .[0][1938]=1937 | |
| 1942 | .[0][1939]=1938 | |
| 1943 | .[0][1940]=1939 | |
| 1944 | .[0][1941]=1940 | |
| 1945 | .[0][1942]=1941 | |
| 1946 | .[0][1943]=1942 | |
| 1947 | .[0][1944]=1943 | |
| 1948 | .[0][1945]=1944 | |
| 1949 | .[0][1946]=1945 | |
| 1950 | .[0][1947]=1946 | |
| 1951 | .[0][1948]=1947 | |
| 1952 | .[0][1949]=1948 | |
| 1953 | .[0][1950]=1949 | |
| 1954 | .[0][1951]=1950 | |
| 1955 | .[0][1952]=1951 | |
| 1956 | .[0][1953]=1952 | |
| 1957 | .[0][1954]=1953 | |
| 1958 | .[0][1955]=1954 | |
| 1959 | .[0][1956]=1955 | |
| 1960 | .[0][1957]=1956 | |
| 1961 | .[0][1958]=1957 | |
| 1962 | .[0][1959]=1958 | |
| 1963 | .[0][1960]=1959 | |
| 1964 | .[0][1961]=1960 | |
| 1965 | .[0][1962]=1961 | |
| 1966 | .[0][1963]=1962 | |
| 1967 | .[0][1964]=1963 | |
| 1968 | .[0][1965]=1964 | |
| 1969 | .[0][1966]=1965 | |
| 1970 | .[0][1967]=1966 | |
| 1971 | .[0][1968]=1967 | |
| 1972 | .[0][1969]=1968 | |
| 1973 | .[0][1970]=1969 | |
| 1974 | .[0][1971]=1970 | |
| 1975 | .[0][1972]=1971 | |
| 1976 | .[0][1973]=1972 | |
| 1977 | .[0][1974]=1973 | |
| 1978 | .[0][1975]=1974 | |
| 1979 | .[0][1976]=1975 | |
| 1980 | .[0][1977]=1976 | |
| 1981 | .[0][1978]=1977 | |
| 1982 | .[0][1979]=1978 | |
| 1983 | .[0][1980]=1979 | |
| 1984 | .[0][1981]=1980 | |
| 1985 | .[0][1982]=1981 | |
| 1986 | .[0][1983]=1982 | |
| 1987 | .[0][1984]=1983 | |
| 1988 | .[0][1985]=1984 | |
| 1989 | .[0][1986]=1985 | |
| 1990 | .[0][1987]=1986 | |
| 1991 | .[0][1988]=1987 | |
| 1992 | .[0][1989]=1988 | |
| 1993 | .[0][1990]=1989 | |
| 1994 | .[0][1991]=1990 | |
| 1995 | .[0][1992]=1991 | |
| 1996 | .[0][1993]=1992 | |
| 1997 | .[0][1994]=1993 | |
| 1998 | .[0][1995]=1994 | |
| 1999 | .[0][1996]=1995 | |
| 2000 | .[0][1997]=1996 | |
| 2001 | .[0][1998]=1997 | |
| 2002 | .[0][1999]=1998 | |
| 2003 | .[0][2000]=1999 | |
| 2004 | .[0][2001]=2000 | |
| 2005 | .[0][2002]=2001 | |
| 2006 | .[0][2003]=2002 | |
| 2007 | .[0][2004]=2003 | |
| 2008 | .[0][2005]=2004 | |
| 2009 | .[0][2006]=2005 | |
| 2010 | .[0][2007]=2006 | |
| 2011 | .[0][2008]=2007 | |
| 2012 | .[0][2009]=2008 | |
| 2013 | .[0][2010]=2009 | |
| 2014 | .[0][2011]=2010 | |
| 2015 | .[0][2012]=2011 | |
| 2016 | .[0][2013]=2012 | |
| 2017 | .[0][2014]=2013 | |
| 2018 | .[0][2015]=2014 | |
| 2019 | .[0][2016]=2015 | |
| 2020 | .[0][2017]=2016 | |
| 2021 | .[0][2018]=2017 | |
| 2022 | .[0][2019]=2018 | |
| 2023 | .[0][2020]=2019 | |
| 2024 | .[0][2021]=2020 | |
| 2025 | .[0][2022]=2021 | |
| 2026 | .[0][2023]=2022 | |
| 2027 | .[0][2024]=2023 | |
| 2028 | .[0][2025]=2024 | |
| 2029 | .[0][2026]=2025 | |
| 2030 | .[0][2027]=2026 | |
| 2031 | .[0][2028]=2027 | |
| 2032 | .[0][2029]=2028 | |
| 2033 | .[0][2030]=2029 | |
| 2034 | .[0][2031]=2030 | |
| 2035 | .[0][2032]=2031 | |
| 2036 | .[0][2033]=2032 | |
| 2037 | .[0][2034]=2033 | |
| 2038 | .[0][2035]=2034 | |
| 2039 | .[0][2036]=2035 | |
| 2040 | .[0][2037]=2036 | |
| 2041 | .[0][2038]=2037 | |
| 2042 | .[0][2039]=2038 | |
| 2043 | .[0][2040]=2039 | |
| 2044 | .[0][2041]=2040 | |
| 2045 | .[0][2042]=2041 | |
| 2046 | .[0][2043]=2042 | |
| 2047 | .[0][2044]=2043 | |
| 2048 | .[0][2045]=2044 | |
| 2049 | .[0][2046]=2045 | |
| 2050 | .[0][2047]=2046 | |
| 2051 | .[0][2048]=2047 | |
| 2052 | .[0][2049]=2048 | |
| 2053 | .[0][2050]=2049 | |
| 2054 | .[0][2051]=2050 | |
| 2055 | .[0][2052]=2051 | |
| 2056 | .[0][2053]=2052 | |
| 2057 | .[0][2054]=2053 | |
| 2058 | .[0][2055]=2054 | |
| 2059 | .[0][2056]=2055 | |
| 2060 | .[0][2057]=2056 | |
| 2061 | .[0][2058]=2057 | |
| 2062 | .[0][2059]=2058 | |
| 2063 | .[0][2060]=2059 | |
| 2064 | .[0][2061]=2060 | |
| 2065 | .[0][2062]=2061 | |
| 2066 | .[0][2063]=2062 | |
| 2067 | .[0][2064]=2063 | |
| 2068 | .[0][2065]=2064 | |
| 2069 | .[0][2066]=2065 | |
| 2070 | .[0][2067]=2066 | |
| 2071 | .[0][2068]=2067 | |
| 2072 | .[0][2069]=2068 | |
| 2073 | .[0][2070]=2069 | |
| 2074 | .[0][2071]=2070 | |
| 2075 | .[0][2072]=2071 | |
| 2076 | .[0][2073]=2072 | |
| 2077 | .[0][2074]=2073 | |
| 2078 | .[0][2075]=2074 | |
| 2079 | .[0][2076]=2075 | |
| 2080 | .[0][2077]=2076 | |
| 2081 | .[0][2078]=2077 | |
| 2082 | .[0][2079]=2078 | |
| 2083 | .[0][2080]=2079 | |
| 2084 | .[0][2081]=2080 | |
| 2085 | .[0][2082]=2081 | |
| 2086 | .[0][2083]=2082 | |
| 2087 | .[0][2084]=2083 | |
| 2088 | .[0][2085]=2084 | |
| 2089 | .[0][2086]=2085 | |
| 2090 | .[0][2087]=2086 | |
| 2091 | .[0][2088]=2087 | |
| 2092 | .[0][2089]=2088 | |
| 2093 | .[0][2090]=2089 | |
| 2094 | .[0][2091]=2090 | |
| 2095 | .[0][2092]=2091 | |
| 2096 | .[0][2093]=2092 | |
| 2097 | .[0][2094]=2093 | |
| 2098 | .[0][2095]=2094 | |
| 2099 | .[0][2096]=2095 | |
| 2100 | .[0][2097]=2096 | |
| 2101 | .[0][2098]=2097 | |
| 2102 | .[0][2099]=2098 | |
| 2103 | .[0][2100]=2099 | |
| 2104 | .[0][2101]=2100 | |
| 2105 | .[0][2102]=2101 | |
| 2106 | .[0][2103]=2102 | |
| 2107 | .[0][2104]=2103 | |
| 2108 | .[0][2105]=2104 | |
| 2109 | .[0][2106]=2105 | |
| 2110 | .[0][2107]=2106 | |
| 2111 | .[0][2108]=2107 | |
| 2112 | .[0][2109]=2108 | |
| 2113 | .[0][2110]=2109 | |
| 2114 | .[0][2111]=2110 | |
| 2115 | .[0][2112]=2111 | |
| 2116 | .[0][2113]=2112 | |
| 2117 | .[0][2114]=2113 | |
| 2118 | .[0][2115]=2114 | |
| 2119 | .[0][2116]=2115 | |
| 2120 | .[0][2117]=2116 | |
| 2121 | .[0][2118]=2117 | |
| 2122 | .[0][2119]=2118 |
| r0 | r242831 | |
|---|---|---|
| 1 | [["A",0,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,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,1104,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,1117,1118,1119,1120,1121,1122,1123,1124,1125,1126,1127,1128,1129,1130,1131,1132,1133,1134,1135,1136,1137,1138,1139,1140,1141,1142,1143,1144,1145,1146,1147,1148,1149,1150,1151,1152,1153,1154,1155,1156,1157,1158,1159,1160,1161,1162,1163,1164,1165,1166,1167,1168,1169,1170,1171,1172,1173,1174,1175,1176,1177,1178,1179,1180,1181,1182,1183,1184,1185,1186,1187,1188,1189,1190,1191,1192,1193,1194,1195,1196,1197,1198,1199,1200,1201,1202,1203,1204,1205,1206,1207,1208,1209,1210,1211,1212,1213,1214,1215,1216,1217,1218,1219,1220,1221,1222,1223,1224,1225,1226,1227,1228,1229,1230,1231,1232,1233,1234,1235,1236,1237,1238,1239,1240,1241,1242,1243,1244,1245,1246,1247,1248,1249,1250,1251,1252,1253,1254,1255,1256,1257,1258,1259,1260,1261,1262,1263,1264,1265,1266,1267,1268,1269,1270,1271,1272,1273,1274,1275,1276,1277,1278,1279,1280,1281,1282,1283,1284,1285,1286,1287,1288,1289,1290,1291,1292,1293,1294,1295,1296,1297,1298,1299,1300,1301,1302,1303,1304,1305,1306,1307,1308,1309,1310,1311,1312,1313,1314,1315,1316,1317,1318,1319,1320,1321,1322,1323,1324,1325,1326,1327,1328,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1360,1361,1362,1363,1364,1365,1366,1367,1368,1369,1370,1371,1372,1373,1374,1375,1376,1377,1378,1379,1380,1381,1382,1383,1384,1385,1386,1387,1388,1389,1390,1391,1392,1393,1394,1395,1396,1397,1398,1399,1400,1401,1402,1403,1404,1405,1406,1407,1408,1409,1410,1411,1412,1413,1414,1415,1416,1417,1418,1419,1420,1421,1422,1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,2079,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,2109,2110,2111,2112,2113,2114,2115,2116,2117,2118] | |
| 2 | ] | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | .={} |
| r0 | r242831 | |
|---|---|---|
| 1 | {} |
| r0 | r242831 | |
|---|---|---|
| 1 | .={} | |
| 2 | .count=1234 |
| r0 | r242831 | |
|---|---|---|
| 1 | { "count" : 1234 } |
| r0 | r242831 | |
|---|---|---|
| 1 | .={} | |
| 2 | .attribute="random" | |
| 3 | .count=1234 | |
| 4 | .name="test" |
| r0 | r242831 | |
|---|---|---|
| 1 | { | |
| 2 | "count" : 1234, | |
| 3 | "name" : "test", | |
| 4 | "attribute" : "random" | |
| 5 | } |
| r0 | r242831 | |
|---|---|---|
| 1 | .={} | |
| 2 | .=1234 |
| r0 | r242831 | |
|---|---|---|
| 1 | { | |
| 2 | "" : 1234 | |
| 3 | } |
| r0 | r242831 | |
|---|---|---|
| 1 | /* A comment | |
| 2 | at the beginning of the file. | |
| 3 | */ | |
| 4 | .={} | |
| 5 | .first=1 | |
| 6 | /* Comment before 'second' | |
| 7 | */ | |
| 8 | .second=2 | |
| 9 | /* A comment at | |
| 10 | the end of the file. | |
| 11 | */ |
| r0 | r242831 | |
|---|---|---|
| 1 | /* A comment | |
| 2 | at the beginning of the file. | |
| 3 | */ | |
| 4 | { | |
| 5 | "first" : 1, // comment after 'first' on the same line | |
| 6 | ||
| 7 | /* Comment before 'second' | |
| 8 | */ | |
| 9 | "second" : 2 | |
| 10 | } | |
| 11 | ||
| 12 | /* A comment at | |
| 13 | the end of the file. | |
| 14 | */ |
| r0 | r242831 | |
|---|---|---|
| 1 | // 2^33 => out of integer range, switch to double | |
| 2 | .=8589934592 | |
| 3 |
| r0 | r242831 | |
|---|---|---|
| 1 | // 2^33 => out of integer range, switch to double | |
| 2 | 8589934592 | |
| 3 |
| r0 | r242831 | |
|---|---|---|
| 1 | // -2^32 => out of signed integer range, switch to double | |
| 2 | .=-4294967295 | |
| 3 |
| r0 | r242831 | |
|---|---|---|
| 1 | // -2^32 => out of signed integer range, switch to double | |
| 2 | -4294967295 | |
| 3 |
| r0 | r242831 | |
|---|---|---|
| 1 | // -2^32 => out of signed integer range, switch to double | |
| 2 | .=-4294967295 | |
| 3 |
| r0 | r242831 | |
|---|---|---|
| 1 | // -2^32 => out of signed integer range, switch to double | |
| 2 | -4294967295 | |
| 3 |
| r0 | r242831 | |
|---|---|---|
| 1 | // 1.2345678 | |
| 2 | .=1.2345678 | |
| 3 |
| r0 | r242831 | |
|---|---|---|
| 1 | // 1.2345678 | |
| 2 | 12345678e-7 | |
| 3 |
| r0 | r242831 | |
|---|---|---|
| 1 | // 1234567.8 | |
| 2 | .=1234567.8 | |
| 3 | ||
| 4 |
| r0 | r242831 | |
|---|---|---|
| 1 | // 1234567.8 | |
| 2 | 0.12345678e7 | |
| 3 |
| r0 | r242831 | |
|---|---|---|
| 1 | // -1.2345678 | |
| 2 | .=-1.2345678 | |
| 3 | ||
| 4 |
| r0 | r242831 | |
|---|---|---|
| 1 | // -1.2345678 | |
| 2 | -12345678e-7 | |
| 3 |
| r0 | r242831 | |
|---|---|---|
| 1 | // -1234567.8 | |
| 2 | .=-1234567.8 | |
| 3 | ||
| 4 |
| r0 | r242831 | |
|---|---|---|
| 1 | // -1234567.8 | |
| 2 | -0.12345678e7 | |
| 3 |
| r0 | r242831 | |
|---|---|---|
| 1 | // Out of 32-bit integer range, switch to double in 32-bit mode. Length the | |
| 2 | // same as UINT_MAX in base 10 and digit less than UINT_MAX's last digit in | |
| 3 | // order to catch a bug in the parsing code. | |
| 4 | .=4300000001 |
| r0 | r242831 | |
|---|---|---|
| 1 | // Out of 32-bit integer range, switch to double in 32-bit mode. Length the | |
| 2 | // same as UINT_MAX in base 10 and digit less than UINT_MAX's last digit in | |
| 3 | // order to catch a bug in the parsing code. | |
| 4 | 4300000001 |
| r0 | r242831 | |
|---|---|---|
| 1 | // Out of 64-bit integer range, switch to double in all modes. Length the same | |
| 2 | // as ULONG_MAX in base 10 and digit less than ULONG_MAX's last digit in order | |
| 3 | // to catch a bug in the parsing code. | |
| 4 | .=1.9e+19 |
| r0 | r242831 | |
|---|---|---|
| 1 | // Out of 64-bit integer range, switch to double in all modes. Length the same | |
| 2 | // as ULONG_MAX in base 10 and digit less than ULONG_MAX's last digit in order | |
| 3 | // to catch a bug in the parsing code. | |
| 4 | 19000000000000000001 |
| r0 | r242831 | |
|---|---|---|
| 1 | // Out of 32-bit signed integer range, switch to double in all modes. Length | |
| 2 | // the same as INT_MIN in base 10 and digit less than INT_MIN's last digit in | |
| 3 | // order to catch a bug in the parsing code. | |
| 4 | .=-2200000001 |
| r0 | r242831 | |
|---|---|---|
| 1 | // Out of 32-bit signed integer range, switch to double in all modes. Length | |
| 2 | // the same as INT_MIN in base 10 and digit less than INT_MIN's last digit in | |
| 3 | // order to catch a bug in the parsing code. | |
| 4 | -2200000001 |
| r0 | r242831 | |
|---|---|---|
| 1 | // Out of 64-bit signed integer range, switch to double in all modes. Length | |
| 2 | // the same as LONG_MIN in base 10 and digit less than LONG_MIN's last digit in | |
| 3 | // order to catch a bug in the parsing code. | |
| 4 | .=-9.3e+18 |
| r0 | r242831 | |
|---|---|---|
| 1 | // Out of 64-bit signed integer range, switch to double in all modes. Length | |
| 2 | // the same as LONG_MIN in base 10 and digit less than LONG_MIN's last digit in | |
| 3 | // order to catch a bug in the parsing code. | |
| 4 | -9300000000000000001 |
| r0 | r242831 | |
|---|---|---|
| 1 | // 2^64 -> switch to double. | |
| 2 | .=1.844674407370955e+19 |
| r0 | r242831 | |
|---|---|---|
| 1 | // 2^64 -> switch to double. | |
| 2 | 18446744073709551616 |
| r0 | r242831 | |
|---|---|---|
| 1 | .="!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~" | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" |
| r0 | r242831 | |
|---|---|---|
| 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 |
| r0 | r242831 | |
|---|---|---|
| 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{|}~" |
| r0 | r242831 | |
|---|---|---|
| 1 | .="http://jsoncpp.sourceforge.net/" | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | "http:\/\/jsoncpp.sourceforge.net\/" |
| r0 | r242831 | |
|---|---|---|
| 1 | .=""abc\def"" | |
| 2 |
| r0 | r242831 | |
|---|---|---|
| 1 | "\"abc\\def\"" | |
| 2 |
| r0 | r242831 | |
|---|---|---|
| 1 | .="\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" | |
| 2 |
| r0 | r242831 | |
|---|---|---|
| 1 | "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" | |
| 2 |
| r0 | r242831 | |
|---|---|---|
| 1 | .="a" |
| r0 | r242831 | |
|---|---|---|
| 1 | "\u0061" | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | .="¢" |
| r0 | r242831 | |
|---|---|---|
| 1 | "\u00A2" | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | .="€" |
| r0 | r242831 | |
|---|---|---|
| 1 | "\u20AC" | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | .="𝄞" |
| r0 | r242831 | |
|---|---|---|
| 1 | "\uD834\uDD1E" | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | .="Zażółć gęślą jaźń" | |
| 2 |
| r0 | r242831 | |
|---|---|---|
| 1 | "Zażółć gęślą jaźń" | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | from __future__ import print_function | |
| 2 | import glob | |
| 3 | import os.path | |
| 4 | for path in glob.glob( '*.json' ): | |
| 5 | text = file(path,'rt').read() | |
| 6 | target = os.path.splitext(path)[0] + '.expected' | |
| 7 | if os.path.exists( target ): | |
| 8 | print('skipping:', target) | |
| 9 | else: | |
| 10 | print('creating:', target) | |
| 11 | file(target,'wt').write(text) | |
| 12 |
| r0 | r242831 | |
|---|---|---|
| 1 | "A JSON payload should be an object or array, not a string." | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | {"Extra value after close": true} "misplaced quoted value" | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | {"Illegal expression": 1 + 2} | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | {"Illegal invocation": alert()} | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | {"Numbers cannot have leading zeroes": 013} | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | {"Numbers cannot be hex": 0x14} | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | ["Illegal backslash escape: \x15"] | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | [\naked] | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | ["Illegal backslash escape: \017"] | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | [[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]] | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | {"Missing colon" null} | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | ["Unclosed array" | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | {"Double colon":: null} | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | {"Comma instead of colon", null} | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | ["Colon instead of comma": false] | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | ["Bad value", truth] | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | ['single quote'] | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | [" tab character in string "] | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | ["tab\ character\ in\ string\ "] | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | ["line | |
| 2 | break"] | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | ["line\ | |
| 2 | break"] | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | [0e] | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | {unquoted_key: "keys must be quoted"} | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | [0e+] | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | [0e+-1] | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | {"Comma instead if closing brace": true, | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | ["mismatch"} | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | ["extra comma",] | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | ["double extra comma",,] | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | [ , "<-- missing value"] | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | ["Comma after the close"], | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | ["Extra close"]] | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | {"Extra comma": true,} | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | [ | |
| 2 | "JSON Test Pattern pass1", | |
| 3 | {"object with 1 member":["array with 1 element"]}, | |
| 4 | {}, | |
| 5 | [], | |
| 6 | -42, | |
| 7 | true, | |
| 8 | false, | |
| 9 | null, | |
| 10 | { | |
| 11 | "integer": 1234567890, | |
| 12 | "real": -9876.543210, | |
| 13 | "e": 0.123456789e-12, | |
| 14 | "E": 1.234567890E+34, | |
| 15 | "": 23456789012E66, | |
| 16 | "zero": 0, | |
| 17 | "one": 1, | |
| 18 | "space": " ", | |
| 19 | "quote": "\"", | |
| 20 | "backslash": "\\", | |
| 21 | "controls": "\b\f\n\r\t", | |
| 22 | "slash": "/ & \/", | |
| 23 | "alpha": "abcdefghijklmnopqrstuvwyz", | |
| 24 | "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ", | |
| 25 | "digit": "0123456789", | |
| 26 | "0123456789": "digit", | |
| 27 | "special": "`1~!@#$%^&*()_+-={':[,]}|;.</>?", | |
| 28 | "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A", | |
| 29 | "true": true, | |
| 30 | "false": false, | |
| 31 | "null": null, | |
| 32 | "array":[ ], | |
| 33 | "object":{ }, | |
| 34 | "address": "50 St. James Street", | |
| 35 | "url": "http://www.JSON.org/", | |
| 36 | "comment": "// /* <!-- --", | |
| 37 | "# -- --> */": " ", | |
| 38 | " s p a c e d " :[1,2 , 3 | |
| 39 | ||
| 40 | , | |
| 41 | ||
| 42 | 4 , 5 , 6 ,7 ],"compact":[1,2,3,4,5,6,7], | |
| 43 | "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}", | |
| 44 | "quotes": "" \u0022 %22 0x22 034 "", | |
| 45 | "\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?" | |
| 46 | : "A key can be any string" | |
| 47 | }, | |
| 48 | 0.5 ,98.6 | |
| 49 | , | |
| 50 | 99.44 | |
| 51 | , | |
| 52 | ||
| 53 | 1066, | |
| 54 | 1e1, | |
| 55 | 0.1e1, | |
| 56 | 1e-1, | |
| 57 | 1e00,2e+00,2e-00 | |
| 58 | ,"rosebud"] | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | [[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]] | |
| No newline at end of file |
| r0 | r242831 | |
|---|---|---|
| 1 | { | |
| 2 | "JSON Test Pattern pass3": { | |
| 3 | "The outermost value": "must be an object or array.", | |
| 4 | "In this test": "It is an object." | |
| 5 | } | |
| 6 | } |
| r0 | r242831 | |
|---|---|---|
| 1 | Test suite from http://json.org/JSON_checker/. | |
| 2 | ||
| 3 | If the JSON_checker is working correctly, it must accept all of the pass*.json files and reject all of the fail*.json files. |
| r0 | r242831 | |
|---|---|---|
| 1 | # Simple implementation of a json test runner to run the test against json-py. | |
| 2 | from __future__ import print_function | |
| 3 | import sys | |
| 4 | import os.path | |
| 5 | import json | |
| 6 | import types | |
| 7 | ||
| 8 | if len(sys.argv) != 2: | |
| 9 | print("Usage: %s input-json-file", sys.argv[0]) | |
| 10 | sys.exit(3) | |
| 11 | ||
| 12 | input_path = sys.argv[1] | |
| 13 | base_path = os.path.splitext(input_path)[0] | |
| 14 | actual_path = base_path + '.actual' | |
| 15 | rewrite_path = base_path + '.rewrite' | |
| 16 | rewrite_actual_path = base_path + '.actual-rewrite' | |
| 17 | ||
| 18 | def valueTreeToString( fout, value, path = '.' ): | |
| 19 | ty = type(value) | |
| 20 | if ty is types.DictType: | |
| 21 | fout.write( '%s={}\n' % path ) | |
| 22 | suffix = path[-1] != '.' and '.' or '' | |
| 23 | names = value.keys() | |
| 24 | names.sort() | |
| 25 | for name in names: | |
| 26 | valueTreeToString( fout, value[name], path + suffix + name ) | |
| 27 | elif ty is types.ListType: | |
| 28 | fout.write( '%s=[]\n' % path ) | |
| 29 | for index, childValue in zip( xrange(0,len(value)), value ): | |
| 30 | valueTreeToString( fout, childValue, path + '[%d]' % index ) | |
| 31 | elif ty is types.StringType: | |
| 32 | fout.write( '%s="%s"\n' % (path,value) ) | |
| 33 | elif ty is types.IntType: | |
| 34 | fout.write( '%s=%d\n' % (path,value) ) | |
| 35 | elif ty is types.FloatType: | |
| 36 | fout.write( '%s=%.16g\n' % (path,value) ) | |
| 37 | elif value is True: | |
| 38 | fout.write( '%s=true\n' % path ) | |
| 39 | elif value is False: | |
| 40 | fout.write( '%s=false\n' % path ) | |
| 41 | elif value is None: | |
| 42 | fout.write( '%s=null\n' % path ) | |
| 43 | else: | |
| 44 | assert False and "Unexpected value type" | |
| 45 | ||
| 46 | def parseAndSaveValueTree( input, actual_path ): | |
| 47 | root = json.loads( input ) | |
| 48 | fout = file( actual_path, 'wt' ) | |
| 49 | valueTreeToString( fout, root ) | |
| 50 | fout.close() | |
| 51 | return root | |
| 52 | ||
| 53 | def rewriteValueTree( value, rewrite_path ): | |
| 54 | rewrite = json.dumps( value ) | |
| 55 | #rewrite = rewrite[1:-1] # Somehow the string is quoted ! jsonpy bug ? | |
| 56 | file( rewrite_path, 'wt').write( rewrite + '\n' ) | |
| 57 | return rewrite | |
| 58 | ||
| 59 | input = file( input_path, 'rt' ).read() | |
| 60 | root = parseAndSaveValueTree( input, actual_path ) | |
| 61 | rewrite = rewriteValueTree( json.write( root ), rewrite_path ) | |
| 62 | rewrite_root = parseAndSaveValueTree( rewrite, rewrite_actual_path ) | |
| 63 | ||
| 64 | sys.exit( 0 ) |
| r0 | r242831 | |
|---|---|---|
| 1 | from __future__ import print_function | |
| 2 | import sys | |
| 3 | import os | |
| 4 | import os.path | |
| 5 | from glob import glob | |
| 6 | import optparse | |
| 7 | ||
| 8 | VALGRIND_CMD = 'valgrind --tool=memcheck --leak-check=yes --undef-value-errors=yes ' | |
| 9 | ||
| 10 | def compareOutputs( expected, actual, message ): | |
| 11 | expected = expected.strip().replace('\r','').split('\n') | |
| 12 | actual = actual.strip().replace('\r','').split('\n') | |
| 13 | diff_line = 0 | |
| 14 | max_line_to_compare = min( len(expected), len(actual) ) | |
| 15 | for index in range(0,max_line_to_compare): | |
| 16 | if expected[index].strip() != actual[index].strip(): | |
| 17 | diff_line = index + 1 | |
| 18 | break | |
| 19 | if diff_line == 0 and len(expected) != len(actual): | |
| 20 | diff_line = max_line_to_compare+1 | |
| 21 | if diff_line == 0: | |
| 22 | return None | |
| 23 | def safeGetLine( lines, index ): | |
| 24 | index += -1 | |
| 25 | if index >= len(lines): | |
| 26 | return '' | |
| 27 | return lines[index].strip() | |
| 28 | return """ Difference in %s at line %d: | |
| 29 | Expected: '%s' | |
| 30 | Actual: '%s' | |
| 31 | """ % (message, diff_line, | |
| 32 | safeGetLine(expected,diff_line), | |
| 33 | safeGetLine(actual,diff_line) ) | |
| 34 | ||
| 35 | def safeReadFile( path ): | |
| 36 | try: | |
| 37 | return file( path, 'rt' ).read() | |
| 38 | except IOError as e: | |
| 39 | return '<File "%s" is missing: %s>' % (path,e) | |
| 40 | ||
| 41 | def runAllTests( jsontest_executable_path, input_dir = None, | |
| 42 | use_valgrind=False, with_json_checker=False ): | |
| 43 | if not input_dir: | |
| 44 | input_dir = os.path.join( os.getcwd(), 'data' ) | |
| 45 | tests = glob( os.path.join( input_dir, '*.json' ) ) | |
| 46 | if with_json_checker: | |
| 47 | test_jsonchecker = glob( os.path.join( input_dir, '../jsonchecker', '*.json' ) ) | |
| 48 | else: | |
| 49 | test_jsonchecker = [] | |
| 50 | failed_tests = [] | |
| 51 | valgrind_path = use_valgrind and VALGRIND_CMD or '' | |
| 52 | for input_path in tests + test_jsonchecker: | |
| 53 | expect_failure = os.path.basename( input_path ).startswith( 'fail' ) | |
| 54 | is_json_checker_test = (input_path in test_jsonchecker) or expect_failure | |
| 55 | print('TESTING:', input_path, end=' ') | |
| 56 | options = is_json_checker_test and '--json-checker' or '' | |
| 57 | pipe = os.popen( '%s%s %s "%s"' % ( | |
| 58 | valgrind_path, jsontest_executable_path, options, | |
| 59 | input_path) ) | |
| 60 | process_output = pipe.read() | |
| 61 | status = pipe.close() | |
| 62 | if is_json_checker_test: | |
| 63 | if expect_failure: | |
| 64 | if status is None: | |
| 65 | print('FAILED') | |
| 66 | failed_tests.append( (input_path, 'Parsing should have failed:\n%s' % | |
| 67 | safeReadFile(input_path)) ) | |
| 68 | else: | |
| 69 | print('OK') | |
| 70 | else: | |
| 71 | if status is not None: | |
| 72 | print('FAILED') | |
| 73 | failed_tests.append( (input_path, 'Parsing failed:\n' + process_output) ) | |
| 74 | else: | |
| 75 | print('OK') | |
| 76 | else: | |
| 77 | base_path = os.path.splitext(input_path)[0] | |
| 78 | actual_output = safeReadFile( base_path + '.actual' ) | |
| 79 | actual_rewrite_output = safeReadFile( base_path + '.actual-rewrite' ) | |
| 80 | file(base_path + '.process-output','wt').write( process_output ) | |
| 81 | if status: | |
| 82 | print('parsing failed') | |
| 83 | failed_tests.append( (input_path, 'Parsing failed:\n' + process_output) ) | |
| 84 | else: | |
| 85 | expected_output_path = os.path.splitext(input_path)[0] + '.expected' | |
| 86 | expected_output = file( expected_output_path, 'rt' ).read() | |
| 87 | detail = ( compareOutputs( expected_output, actual_output, 'input' ) | |
| 88 | or compareOutputs( expected_output, actual_rewrite_output, 'rewrite' ) ) | |
| 89 | if detail: | |
| 90 | print('FAILED') | |
| 91 | failed_tests.append( (input_path, detail) ) | |
| 92 | else: | |
| 93 | print('OK') | |
| 94 | ||
| 95 | if failed_tests: | |
| 96 | print() | |
| 97 | print('Failure details:') | |
| 98 | for failed_test in failed_tests: | |
| 99 | print('* Test', failed_test[0]) | |
| 100 | print(failed_test[1]) | |
| 101 | print() | |
| 102 | print('Test results: %d passed, %d failed.' % (len(tests)-len(failed_tests), | |
| 103 | len(failed_tests) )) | |
| 104 | return 1 | |
| 105 | else: | |
| 106 | print('All %d tests passed.' % len(tests)) | |
| 107 | return 0 | |
| 108 | ||
| 109 | def main(): | |
| 110 | from optparse import OptionParser | |
| 111 | parser = OptionParser( usage="%prog [options] <path to jsontestrunner.exe> [test case directory]" ) | |
| 112 | parser.add_option("--valgrind", | |
| 113 | action="store_true", dest="valgrind", default=False, | |
| 114 | help="run all the tests using valgrind to detect memory leaks") | |
| 115 | parser.add_option("-c", "--with-json-checker", | |
| 116 | action="store_true", dest="with_json_checker", default=False, | |
| 117 | help="run all the tests from the official JSONChecker test suite of json.org") | |
| 118 | parser.enable_interspersed_args() | |
| 119 | options, args = parser.parse_args() | |
| 120 | ||
| 121 | if len(args) < 1 or len(args) > 2: | |
| 122 | parser.error( 'Must provides at least path to jsontestrunner executable.' ) | |
| 123 | sys.exit( 1 ) | |
| 124 | ||
| 125 | jsontest_executable_path = os.path.normpath( os.path.abspath( args[0] ) ) | |
| 126 | if len(args) > 1: | |
| 127 | input_path = os.path.normpath( os.path.abspath( args[1] ) ) | |
| 128 | else: | |
| 129 | input_path = None | |
| 130 | status = runAllTests( jsontest_executable_path, input_path, | |
| 131 | use_valgrind=options.valgrind, with_json_checker=options.with_json_checker ) | |
| 132 | sys.exit( status ) | |
| 133 | ||
| 134 | if __name__ == '__main__': | |
| 135 | main() |
| r0 | r242831 | |
|---|---|---|
| 1 | from __future__ import print_function | |
| 2 | from glob import glob | |
| 3 | import sys | |
| 4 | import os | |
| 5 | import os.path | |
| 6 | import subprocess | |
| 7 | import optparse | |
| 8 | ||
| 9 | VALGRIND_CMD = 'valgrind --tool=memcheck --leak-check=yes --undef-value-errors=yes' | |
| 10 | ||
| 11 | class TestProxy(object): | |
| 12 | def __init__( self, test_exe_path, use_valgrind=False ): | |
| 13 | self.test_exe_path = os.path.normpath( os.path.abspath( test_exe_path ) ) | |
| 14 | self.use_valgrind = use_valgrind | |
| 15 | ||
| 16 | def run( self, options ): | |
| 17 | if self.use_valgrind: | |
| 18 | cmd = VALGRIND_CMD.split() | |
| 19 | else: | |
| 20 | cmd = [] | |
| 21 | cmd.extend( [self.test_exe_path, '--test-auto'] + options ) | |
| 22 | process = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT ) | |
| 23 | stdout = process.communicate()[0] | |
| 24 | if process.returncode: | |
| 25 | return False, stdout | |
| 26 | return True, stdout | |
| 27 | ||
| 28 | def runAllTests( exe_path, use_valgrind=False ): | |
| 29 | test_proxy = TestProxy( exe_path, use_valgrind=use_valgrind ) | |
| 30 | status, test_names = test_proxy.run( ['--list-tests'] ) | |
| 31 | if not status: | |
| 32 | print("Failed to obtain unit tests list:\n" + test_names, file=sys.stderr) | |
| 33 | return 1 | |
| 34 | test_names = [name.strip() for name in test_names.strip().split('\n')] | |
| 35 | failures = [] | |
| 36 | for name in test_names: | |
| 37 | print('TESTING %s:' % name, end=' ') | |
| 38 | succeed, result = test_proxy.run( ['--test', name] ) | |
| 39 | if succeed: | |
| 40 | print('OK') | |
| 41 | else: | |
| 42 | failures.append( (name, result) ) | |
| 43 | print('FAILED') | |
| 44 | failed_count = len(failures) | |
| 45 | pass_count = len(test_names) - failed_count | |
| 46 | if failed_count: | |
| 47 | print() | |
| 48 | for name, result in failures: | |
| 49 | print(result) | |
| 50 | print('%d/%d tests passed (%d failure(s))' % ( | |
| 51 | pass_count, len(test_names), failed_count)) | |
| 52 | return 1 | |
| 53 | else: | |
| 54 | print('All %d tests passed' % len(test_names)) | |
| 55 | return 0 | |
| 56 | ||
| 57 | def main(): | |
| 58 | from optparse import OptionParser | |
| 59 | parser = OptionParser( usage="%prog [options] <path to test_lib_json.exe>" ) | |
| 60 | parser.add_option("--valgrind", | |
| 61 | action="store_true", dest="valgrind", default=False, | |
| 62 | help="run all the tests using valgrind to detect memory leaks") | |
| 63 | parser.enable_interspersed_args() | |
| 64 | options, args = parser.parse_args() | |
| 65 | ||
| 66 | if len(args) != 1: | |
| 67 | parser.error( 'Must provides at least path to test_lib_json executable.' ) | |
| 68 | sys.exit( 1 ) | |
| 69 | ||
| 70 | exit_code = runAllTests( args[0], use_valgrind=options.valgrind ) | |
| 71 | sys.exit( exit_code ) | |
| 72 | ||
| 73 | if __name__ == '__main__': | |
| 74 | main() |
| r0 | r242831 | |
|---|---|---|
| 1 | 1.1.0 Index: trunk/src/emu/webengine.c | |
| r0 | r242831 | |
| 9 | 9 | ***************************************************************************/ |
| 10 | 10 | |
| 11 | 11 | #include "mongoose/mongoose.h" |
| 12 | #include " | |
| 12 | #include "jsoncpp/include/json/json.h" | |
| 13 | 13 | #include "emu.h" |
| 14 | 14 | #include "emuopts.h" |
| 15 | 15 | #include "ui/ui.h" |
| r242830 | r242831 | |
|---|---|---|
| 26 | 26 | $(LIBOBJ)/lua \ |
| 27 | 27 | $(LIBOBJ)/lua/lib \ |
| 28 | 28 | $(LIBOBJ)/mongoose \ |
| 29 | $(LIBOBJ)/web \ | |
| 30 | $(LIBOBJ)/web/json \ | |
| 29 | $(LIBOBJ)/jsoncpp \ | |
| 31 | 30 | $(LIBOBJ)/sqlite3 \ |
| 32 | 31 | |
| 33 | 32 | #------------------------------------------------- |
| r242830 | r242831 | |
| 537 | 536 | |
| 538 | 537 | WEBOBJS = \ |
| 539 | 538 | $(LIBOBJ)/mongoose/mongoose.o \ |
| 540 | $(LIBOBJ)/web/json/json_reader.o \ | |
| 541 | $(LIBOBJ)/web/json/json_value.o \ | |
| 542 | $(LIBOBJ)/web/json/json_writer.o \ | |
| 539 | $(LIBOBJ)/jsoncpp/json_reader.o \ | |
| 540 | $(LIBOBJ)/jsoncpp/json_value.o \ | |
| 541 | $(LIBOBJ)/jsoncpp/json_writer.o \ | |
| 543 | 542 | |
| 544 | 543 | $(OBJ)/libweb.a: $(WEBOBJS) |
| 545 | 544 | |
| 546 | $(LIBOBJ)/ | |
| 545 | $(LIBOBJ)/jsoncpp/%.o: $(3RDPARTY)/jsoncpp/src/lib_json/%.cpp | $(OSPREBUILD) | |
| 547 | 546 | @echo Compiling $<... |
| 548 | $(CC) $(CDEFS) $(CFLAGS) -I$( | |
| 547 | $(CC) $(CDEFS) $(CFLAGS) -I$(3RDPARTY)/jsoncpp/include -c $< -o $@ | |
| 549 | 548 | |
| 550 | 549 | $(LIBOBJ)/mongoose/%.o: $(3RDPARTY)/mongoose/%.c | $(OSPREBUILD) |
| 551 | 550 | @echo Compiling $<... |
| https://github.com/mamedev/mame/commit/02d37b6915e453fbc40afc80830d9a2cbb459d1f |
| Previous | 199869 Revisions | Next |