├── .gitignore ├── .gitmodules ├── .travis.yml ├── CHANGELOG.md ├── CMakeLists.txt ├── CMakeModules └── FindGTestSrc.cmake ├── RapidJSON.pc.in ├── RapidJSONConfig.cmake.in ├── RapidJSONConfigVersion.cmake.in ├── appveyor.yml ├── bin ├── data │ ├── glossary.json │ ├── menu.json │ ├── readme.txt │ ├── sample.json │ ├── webapp.json │ └── widget.json ├── encodings │ ├── utf16be.json │ ├── utf16bebom.json │ ├── utf16le.json │ ├── utf16lebom.json │ ├── utf32be.json │ ├── utf32bebom.json │ ├── utf32le.json │ ├── utf32lebom.json │ ├── utf8.json │ └── utf8bom.json └── 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 ├── doc ├── CMakeLists.txt ├── Doxyfile.in ├── Doxyfile.zh-cn.in ├── diagram │ ├── architecture.dot │ ├── architecture.png │ ├── insituparsing.dot │ ├── insituparsing.png │ ├── iterative-parser-states-diagram.dot │ ├── iterative-parser-states-diagram.png │ ├── makefile │ ├── move1.dot │ ├── move1.png │ ├── move2.dot │ ├── move2.png │ ├── move3.dot │ ├── move3.png │ ├── normalparsing.dot │ ├── normalparsing.png │ ├── simpledom.dot │ ├── simpledom.png │ ├── tutorial.dot │ ├── tutorial.png │ ├── utilityclass.dot │ └── utilityclass.png ├── dom.md ├── dom.zh-cn.md ├── encoding.md ├── encoding.zh-cn.md ├── faq.md ├── faq.zh-cn.md ├── features.md ├── features.zh-cn.md ├── internals.md ├── logo │ ├── rapidjson.png │ └── rapidjson.svg ├── misc │ ├── DoxygenLayout.xml │ ├── doxygenextra.css │ ├── footer.html │ └── header.html ├── performance.md ├── performance.zh-cn.md ├── sax.md ├── sax.zh-cn.md ├── stream.md ├── stream.zh-cn.md ├── tutorial.md └── tutorial.zh-cn.md ├── example ├── CMakeLists.txt ├── capitalize │ └── capitalize.cpp ├── condense │ └── condense.cpp ├── messagereader │ └── messagereader.cpp ├── pretty │ └── pretty.cpp ├── prettyauto │ └── prettyauto.cpp ├── serialize │ └── serialize.cpp ├── simpledom │ └── simpledom.cpp ├── simplereader │ └── simplereader.cpp ├── simplewriter │ └── simplewriter.cpp └── tutorial │ └── tutorial.cpp ├── include └── rapidjson │ ├── allocators.h │ ├── document.h │ ├── encodedstream.h │ ├── encodings.h │ ├── error │ ├── en.h │ └── error.h │ ├── filereadstream.h │ ├── filewritestream.h │ ├── internal │ ├── biginteger.h │ ├── diyfp.h │ ├── dtoa.h │ ├── ieee754.h │ ├── itoa.h │ ├── meta.h │ ├── pow10.h │ ├── stack.h │ ├── strfunc.h │ └── strtod.h │ ├── memorybuffer.h │ ├── memorystream.h │ ├── msinttypes │ ├── inttypes.h │ └── stdint.h │ ├── prettywriter.h │ ├── rapidjson.h │ ├── reader.h │ ├── stringbuffer.h │ └── writer.h ├── license.txt ├── readme.md ├── readme.zh-cn.md ├── test ├── CMakeLists.txt ├── perftest │ ├── CMakeLists.txt │ ├── misctest.cpp │ ├── perftest.cpp │ ├── perftest.h │ ├── platformtest.cpp │ └── rapidjsontest.cpp └── unittest │ ├── CMakeLists.txt │ ├── allocatorstest.cpp │ ├── bigintegertest.cpp │ ├── documenttest.cpp │ ├── encodedstreamtest.cpp │ ├── encodingstest.cpp │ ├── filestreamtest.cpp │ ├── itoatest.cpp │ ├── jsoncheckertest.cpp │ ├── namespacetest.cpp │ ├── prettywritertest.cpp │ ├── readertest.cpp │ ├── simdtest.cpp │ ├── stringbuffertest.cpp │ ├── strtodtest.cpp │ ├── unittest.cpp │ ├── unittest.h │ ├── valuetest.cpp │ └── writertest.cpp └── travis-doxygen.sh /.gitignore: -------------------------------------------------------------------------------- 1 | /bin/* 2 | !/bin/data 3 | !/bin/encodings 4 | !/bin/jsonchecker 5 | /build 6 | /doc/html 7 | /doc/doxygen_*.db 8 | *.a 9 | 10 | # Temporary files created during CMake build 11 | CMakeCache.txt 12 | CMakeFiles 13 | cmake_install.cmake 14 | CTestTestfile.cmake 15 | Makefile 16 | RapidJSON*.cmake 17 | RapidJSON.pc 18 | Testing 19 | /googletest 20 | install_manifest.txt 21 | Doxyfile 22 | DartConfiguration.tcl 23 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "thirdparty/gtest"] 2 | path = thirdparty/gtest 3 | url = https://chromium.googlesource.com/external/googletest.git 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | 3 | compiler: 4 | - clang 5 | - gcc 6 | 7 | env: 8 | matrix: 9 | - CONF=debug ARCH=x86_64 10 | - CONF=release ARCH=x86_64 11 | - CONF=debug ARCH=x86 12 | - CONF=release ARCH=x86 13 | global: 14 | - ARCH_FLAGS_x86='-m32' # #266: don't use SSE on 32-bit 15 | - ARCH_FLAGS_x86_64='-msse4.2' # use SSE4.2 on 64-bit 16 | - GITHUB_REPO='miloyip/rapidjson' 17 | - secure: "HrsaCb+N66EG1HR+LWH1u51SjaJyRwJEDzqJGYMB7LJ/bfqb9mWKF1fLvZGk46W5t7TVaXRDD5KHFx9DPWvKn4gRUVkwTHEy262ah5ORh8M6n/6VVVajeV/AYt2C0sswdkDBDO4Xq+xy5gdw3G8s1A4Inbm73pUh+6vx+7ltBbk=" 18 | 19 | before_install: 20 | - sudo apt-get update -qq 21 | - sudo apt-get install -qq cmake valgrind 22 | - sudo apt-get --no-install-recommends install doxygen # Don't install LaTeX stuffs 23 | - if [ "$ARCH" = "x86" ]; then sudo apt-get install -qq g++-multilib libc6-dbg:i386; fi 24 | - if [ "$CC" = "gcc" ] && [ "$CONF" = "debug" ]; then sudo pip install cpp-coveralls; export GCOV_FLAGS='--coverage'; fi 25 | 26 | install: true 27 | 28 | before_script: 29 | # hack to avoid Valgrind bug (https://bugs.kde.org/show_bug.cgi?id=326469), 30 | # exposed by merging PR#163 (using -march=native) 31 | - sed -i "s/-march=native//" CMakeLists.txt 32 | - mkdir build 33 | - > 34 | eval "ARCH_FLAGS=\${ARCH_FLAGS_${ARCH}}" ; 35 | (cd build && cmake 36 | -DRAPIDJSON_HAS_STDSTRING=ON 37 | -DCMAKE_VERBOSE_MAKEFILE=ON 38 | -DCMAKE_BUILD_TYPE=$CONF 39 | -DCMAKE_CXX_FLAGS="$ARCH_FLAGS $GCOV_FLAGS" 40 | -DCMAKE_EXE_LINKER_FLAGS=$GCOV_FLAGS 41 | ..) 42 | 43 | script: 44 | - cd build 45 | - make tests 46 | - make examples 47 | - ctest -V `[ "$CONF" = "release" ] || echo "-E perftest"` 48 | - make travis_doc 49 | 50 | after_success: 51 | - coveralls -r .. --gcov-options '\-lp' -e thirdparty -e example -e test -e build/CMakeFiles -e include/rapidjson/msinttypes -e include/rapidjson/internal/meta.h -e include/rapidjson/error/en.h 52 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. 3 | This project adheres to [Semantic Versioning](http://semver.org/). 4 | 5 | ## [Unreleased] 6 | 7 | * Include rapidjson.h for all internal/error headers. 8 | 9 | ## [1.0.1] - 2015-04-25 10 | 11 | ### Added 12 | * Changelog following [Keep a CHANGELOG](https://github.com/olivierlacan/keep-a-changelog) suggestions. 13 | 14 | ### Fixed 15 | * Parsing of some numbers (e.g. "1e-00011111111111") causing assertion (#314). 16 | * Visual C++ 32-bit compilation error in `diyfp.h` (#317). 17 | 18 | ## [1.0.0] - 2015-04-22 19 | 20 | ### Added 21 | * 100% [Coverall](https://coveralls.io/r/miloyip/rapidjson?branch=master) coverage. 22 | * Version macros (#311) 23 | 24 | ### Fixed 25 | * A bug in trimming long number sequence (4824f12efbf01af72b8cb6fc96fae7b097b73015). 26 | * Double quote in unicode escape (#288). 27 | * Negative zero roundtrip (double only) (#289). 28 | * Standardize behavior of `memcpy()` and `malloc()` (0c5c1538dcfc7f160e5a4aa208ddf092c787be5a, #305, 0e8bbe5e3ef375e7f052f556878be0bd79e9062d). 29 | 30 | ### Removed 31 | * Remove an invalid `Document::ParseInsitu()` API (e7f1c6dd08b522cfcf9aed58a333bd9a0c0ccbeb). 32 | 33 | ## 1.0-beta - 2015-04-8 34 | 35 | ### Added 36 | * RFC 7159 (#101) 37 | * Optional Iterative Parser (#76) 38 | * Deep-copy values (#20) 39 | * Error code and message (#27) 40 | * ASCII Encoding (#70) 41 | * `kParseStopWhenDoneFlag` (#83) 42 | * `kParseFullPrecisionFlag` (881c91d696f06b7f302af6d04ec14dd08db66ceb) 43 | * Add `Key()` to handler concept (#134) 44 | * C++11 compatibility and support (#128) 45 | * Optimized number-to-string and vice versa conversions (#137, #80) 46 | * Short-String Optimization (#131) 47 | * Local stream optimization by traits (#32) 48 | * Travis & Appveyor Continuous Integration, with Valgrind verification (#24, #242) 49 | * Redo all documentation (English, Simplified Chinese) 50 | 51 | ### Changed 52 | * Copyright ownership transfered to THL A29 Limited (a Tencent company). 53 | * Migrating from Premake to CMAKE (#192) 54 | * Resolve all warning reports 55 | 56 | ### Removed 57 | * Remove other JSON libraries for performance comparison (#180) 58 | 59 | ## 0.11 - 2012-11-16 60 | 61 | ## 0.1 - 2011-11-18 62 | 63 | [Unreleased]: https://github.com/miloyip/rapidjson/compare/v1.0.1...HEAD 64 | [1.0.1]: https://github.com/miloyip/rapidjson/compare/v1.0.0...v1.0.1 65 | [1.0.0]: https://github.com/miloyip/rapidjson/compare/v1.0-beta...v1.0.0 66 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 2 | SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMakeModules) 3 | 4 | PROJECT(RapidJSON CXX) 5 | 6 | set(LIB_MAJOR_VERSION "1") 7 | set(LIB_MINOR_VERSION "0") 8 | set(LIB_PATCH_VERSION "1") 9 | set(LIB_VERSION_STRING "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_PATCH_VERSION}") 10 | 11 | # compile in release with debug info mode by default 12 | SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Build Type") 13 | 14 | # Build all binaries in a separate directory 15 | SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) 16 | 17 | option(RAPIDJSON_BUILD_DOC "Build rapidjson documentation." ON) 18 | option(RAPIDJSON_BUILD_EXAMPLES "Build rapidjson examples." ON) 19 | option(RAPIDJSON_BUILD_TESTS "Build rapidjson perftests and unittests." ON) 20 | option(RAPIDJSON_BUILD_THIRDPARTY_GTEST 21 | "Use gtest installation in `thirdparty/gtest` by default if available" OFF) 22 | 23 | option(RAPIDJSON_HAS_STDSTRING "" OFF) 24 | if(RAPIDJSON_HAS_STDSTRING) 25 | add_definitions(-DRAPIDJSON_HAS_STDSTRING) 26 | endif() 27 | 28 | if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") 29 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra") 30 | elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") 31 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra") 32 | elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") 33 | add_definitions(-D_CRT_SECURE_NO_WARNINGS=1) 34 | endif() 35 | 36 | #add extra search paths for libraries and includes 37 | SET(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "The directory the headers are installed in") 38 | SET(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE STRING "Directory where lib will install") 39 | SET(DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/share/doc/${PROJECT_NAME}" CACHE PATH "Path to the documentation") 40 | 41 | IF(UNIX OR CYGWIN) 42 | SET(_CMAKE_INSTALL_DIR "${LIB_INSTALL_DIR}/cmake/${PROJECT_NAME}") 43 | ELSEIF(WIN32) 44 | SET(_CMAKE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/cmake") 45 | ENDIF() 46 | SET(CMAKE_INSTALL_DIR "${_CMAKE_INSTALL_DIR}" CACHE PATH "The directory cmake fiels are installed in") 47 | 48 | include_directories(${CMAKE_SOURCE_DIR}/include) 49 | 50 | if(RAPIDJSON_BUILD_DOC) 51 | add_subdirectory(doc) 52 | endif() 53 | 54 | add_custom_target(travis_doc) 55 | add_custom_command(TARGET travis_doc 56 | COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/travis-doxygen.sh) 57 | 58 | if(RAPIDJSON_BUILD_EXAMPLES) 59 | add_subdirectory(example) 60 | endif() 61 | 62 | if(RAPIDJSON_BUILD_TESTS) 63 | if(MSVC11) 64 | # required for VS2012 due to missing support for variadic templates 65 | add_definitions(-D_VARIADIC_MAX=10) 66 | endif(MSVC11) 67 | add_subdirectory(test) 68 | include(CTest) 69 | endif() 70 | 71 | # pkg-config 72 | IF (UNIX OR CYGWIN) 73 | CONFIGURE_FILE (${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc.in 74 | ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc 75 | @ONLY) 76 | INSTALL (FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc 77 | DESTINATION "${LIB_INSTALL_DIR}/pkgconfig" 78 | COMPONENT pkgconfig) 79 | ENDIF() 80 | 81 | install(FILES readme.md 82 | DESTINATION "${DOC_INSTALL_DIR}" 83 | COMPONENT doc) 84 | 85 | install(DIRECTORY include/rapidjson 86 | DESTINATION "${INCLUDE_INSTALL_DIR}" 87 | COMPONENT dev) 88 | 89 | install(DIRECTORY example/ 90 | DESTINATION "${DOC_INSTALL_DIR}/examples" 91 | COMPONENT examples 92 | # Following patterns are for excluding the intermediate/object files 93 | # from an install of in-source CMake build. 94 | PATTERN "CMakeFiles" EXCLUDE 95 | PATTERN "Makefile" EXCLUDE 96 | PATTERN "cmake_install.cmake" EXCLUDE) 97 | 98 | # Provide config and version files to be used by other applications 99 | # =============================== 100 | 101 | export(PACKAGE ${PROJECT_NAME}) 102 | 103 | # cmake-modules 104 | CONFIGURE_FILE(${PROJECT_NAME}Config.cmake.in 105 | ${PROJECT_NAME}Config.cmake 106 | @ONLY) 107 | CONFIGURE_FILE(${PROJECT_NAME}ConfigVersion.cmake.in 108 | ${PROJECT_NAME}ConfigVersion.cmake 109 | @ONLY) 110 | INSTALL(FILES 111 | ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake 112 | ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake 113 | DESTINATION "${CMAKE_INSTALL_DIR}" 114 | COMPONENT dev) 115 | -------------------------------------------------------------------------------- /CMakeModules/FindGTestSrc.cmake: -------------------------------------------------------------------------------- 1 | 2 | SET(GTEST_SEARCH_PATH 3 | "${GTEST_SOURCE_DIR}" 4 | "${CMAKE_SOURCE_DIR}/thirdparty/gtest") 5 | 6 | IF(UNIX) 7 | IF(RAPIDJSON_BUILD_THIRDPARTY_GTEST) 8 | LIST(APPEND GTEST_SEARCH_PATH "/usr/src/gtest") 9 | ELSE() 10 | LIST(INSERT GTEST_SEARCH_PATH 1 "/usr/src/gtest") 11 | ENDIF() 12 | ENDIF() 13 | 14 | FIND_PATH(GTEST_SOURCE_DIR 15 | NAMES CMakeLists.txt src/gtest_main.cc 16 | PATHS ${GTEST_SEARCH_PATH}) 17 | 18 | # Debian installs gtest include directory in /usr/include, thus need to look 19 | # for include directory separately from source directory. 20 | FIND_PATH(GTEST_INCLUDE_DIR 21 | NAMES gtest/gtest.h 22 | PATH_SUFFIXES include 23 | HINTS ${GTEST_SOURCE_DIR} 24 | PATHS ${GTEST_SEARCH_PATH}) 25 | 26 | INCLUDE(FindPackageHandleStandardArgs) 27 | find_package_handle_standard_args(GTestSrc DEFAULT_MSG 28 | GTEST_SOURCE_DIR 29 | GTEST_INCLUDE_DIR) 30 | -------------------------------------------------------------------------------- /RapidJSON.pc.in: -------------------------------------------------------------------------------- 1 | includedir=@INCLUDE_INSTALL_DIR@ 2 | 3 | Name: @PROJECT_NAME@ 4 | Description: A fast JSON parser/generator for C++ with both SAX/DOM style API 5 | Version: @LIB_VERSION_STRING@ 6 | URL: https://github.com/miloyip/rapidjson 7 | Cflags: -I${includedir} 8 | -------------------------------------------------------------------------------- /RapidJSONConfig.cmake.in: -------------------------------------------------------------------------------- 1 | get_filename_component(RAPIDJSON_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) 2 | set(RAPIDJSON_INCLUDE_DIRS "@INCLUDE_INSTALL_DIR@") 3 | message(STATUS "RapidJSON found. Headers: ${RAPIDJSON_INCLUDE_DIRS}") 4 | -------------------------------------------------------------------------------- /RapidJSONConfigVersion.cmake.in: -------------------------------------------------------------------------------- 1 | SET(PACKAGE_VERSION "@LIB_VERSION_STRING@") 2 | 3 | IF (PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION) 4 | SET(PACKAGE_VERSION_EXACT "true") 5 | ENDIF (PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION) 6 | IF (NOT PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION) 7 | SET(PACKAGE_VERSION_COMPATIBLE "true") 8 | ELSE (NOT PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION) 9 | SET(PACKAGE_VERSION_UNSUITABLE "true") 10 | ENDIF (NOT PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION) 11 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 1.0.1.{build} 2 | 3 | configuration: 4 | - Debug 5 | - Release 6 | 7 | environment: 8 | matrix: 9 | - VS_VERSION: 11 10 | VS_PLATFORM: win32 11 | - VS_VERSION: 11 12 | VS_PLATFORM: x64 13 | - VS_VERSION: 12 14 | VS_PLATFORM: win32 15 | - VS_VERSION: 12 16 | VS_PLATFORM: x64 17 | 18 | before_build: 19 | - git submodule update --init --recursive 20 | - cmake -H. -BBuild/VS -G "Visual Studio %VS_VERSION%" -DCMAKE_GENERATOR_PLATFORM=%VS_PLATFORM% -DBUILD_SHARED_LIBS=true -Wno-dev 21 | 22 | build: 23 | project: Build\VS\RapidJSON.sln 24 | parallel: true 25 | verbosity: minimal 26 | 27 | test_script: 28 | - cd Build\VS && if %CONFIGURATION%==Debug (ctest --verbose -E perftest --build-config %CONFIGURATION%) else (ctest --verbose --build-config %CONFIGURATION%) 29 | -------------------------------------------------------------------------------- /bin/data/glossary.json: -------------------------------------------------------------------------------- 1 | { 2 | "glossary": { 3 | "title": "example glossary", 4 | "GlossDiv": { 5 | "title": "S", 6 | "GlossList": { 7 | "GlossEntry": { 8 | "ID": "SGML", 9 | "SortAs": "SGML", 10 | "GlossTerm": "Standard Generalized Markup Language", 11 | "Acronym": "SGML", 12 | "Abbrev": "ISO 8879:1986", 13 | "GlossDef": { 14 | "para": "A meta-markup language, used to create markup languages such as DocBook.", 15 | "GlossSeeAlso": ["GML", "XML"] 16 | }, 17 | "GlossSee": "markup" 18 | } 19 | } 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /bin/data/menu.json: -------------------------------------------------------------------------------- 1 | {"menu": { 2 | "header": "SVG Viewer", 3 | "items": [ 4 | {"id": "Open"}, 5 | {"id": "OpenNew", "label": "Open New"}, 6 | null, 7 | {"id": "ZoomIn", "label": "Zoom In"}, 8 | {"id": "ZoomOut", "label": "Zoom Out"}, 9 | {"id": "OriginalView", "label": "Original View"}, 10 | null, 11 | {"id": "Quality"}, 12 | {"id": "Pause"}, 13 | {"id": "Mute"}, 14 | null, 15 | {"id": "Find", "label": "Find..."}, 16 | {"id": "FindAgain", "label": "Find Again"}, 17 | {"id": "Copy"}, 18 | {"id": "CopyAgain", "label": "Copy Again"}, 19 | {"id": "CopySVG", "label": "Copy SVG"}, 20 | {"id": "ViewSVG", "label": "View SVG"}, 21 | {"id": "ViewSource", "label": "View Source"}, 22 | {"id": "SaveAs", "label": "Save As"}, 23 | null, 24 | {"id": "Help"}, 25 | {"id": "About", "label": "About Adobe CVG Viewer..."} 26 | ] 27 | }} -------------------------------------------------------------------------------- /bin/data/readme.txt: -------------------------------------------------------------------------------- 1 | sample.json is obtained from http://code.google.com/p/json-test-suite/downloads/detail?name=sample.zip 2 | -------------------------------------------------------------------------------- /bin/data/webapp.json: -------------------------------------------------------------------------------- 1 | {"web-app": { 2 | "servlet": [ 3 | { 4 | "servlet-name": "cofaxCDS", 5 | "servlet-class": "org.cofax.cds.CDSServlet", 6 | "init-param": { 7 | "configGlossary:installationAt": "Philadelphia, PA", 8 | "configGlossary:adminEmail": "ksm@pobox.com", 9 | "configGlossary:poweredBy": "Cofax", 10 | "configGlossary:poweredByIcon": "/images/cofax.gif", 11 | "configGlossary:staticPath": "/content/static", 12 | "templateProcessorClass": "org.cofax.WysiwygTemplate", 13 | "templateLoaderClass": "org.cofax.FilesTemplateLoader", 14 | "templatePath": "templates", 15 | "templateOverridePath": "", 16 | "defaultListTemplate": "listTemplate.htm", 17 | "defaultFileTemplate": "articleTemplate.htm", 18 | "useJSP": false, 19 | "jspListTemplate": "listTemplate.jsp", 20 | "jspFileTemplate": "articleTemplate.jsp", 21 | "cachePackageTagsTrack": 200, 22 | "cachePackageTagsStore": 200, 23 | "cachePackageTagsRefresh": 60, 24 | "cacheTemplatesTrack": 100, 25 | "cacheTemplatesStore": 50, 26 | "cacheTemplatesRefresh": 15, 27 | "cachePagesTrack": 200, 28 | "cachePagesStore": 100, 29 | "cachePagesRefresh": 10, 30 | "cachePagesDirtyRead": 10, 31 | "searchEngineListTemplate": "forSearchEnginesList.htm", 32 | "searchEngineFileTemplate": "forSearchEngines.htm", 33 | "searchEngineRobotsDb": "WEB-INF/robots.db", 34 | "useDataStore": true, 35 | "dataStoreClass": "org.cofax.SqlDataStore", 36 | "redirectionClass": "org.cofax.SqlRedirection", 37 | "dataStoreName": "cofax", 38 | "dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver", 39 | "dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon", 40 | "dataStoreUser": "sa", 41 | "dataStorePassword": "dataStoreTestQuery", 42 | "dataStoreTestQuery": "SET NOCOUNT ON;select test='test';", 43 | "dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log", 44 | "dataStoreInitConns": 10, 45 | "dataStoreMaxConns": 100, 46 | "dataStoreConnUsageLimit": 100, 47 | "dataStoreLogLevel": "debug", 48 | "maxUrlLength": 500}}, 49 | { 50 | "servlet-name": "cofaxEmail", 51 | "servlet-class": "org.cofax.cds.EmailServlet", 52 | "init-param": { 53 | "mailHost": "mail1", 54 | "mailHostOverride": "mail2"}}, 55 | { 56 | "servlet-name": "cofaxAdmin", 57 | "servlet-class": "org.cofax.cds.AdminServlet"}, 58 | 59 | { 60 | "servlet-name": "fileServlet", 61 | "servlet-class": "org.cofax.cds.FileServlet"}, 62 | { 63 | "servlet-name": "cofaxTools", 64 | "servlet-class": "org.cofax.cms.CofaxToolsServlet", 65 | "init-param": { 66 | "templatePath": "toolstemplates/", 67 | "log": 1, 68 | "logLocation": "/usr/local/tomcat/logs/CofaxTools.log", 69 | "logMaxSize": "", 70 | "dataLog": 1, 71 | "dataLogLocation": "/usr/local/tomcat/logs/dataLog.log", 72 | "dataLogMaxSize": "", 73 | "removePageCache": "/content/admin/remove?cache=pages&id=", 74 | "removeTemplateCache": "/content/admin/remove?cache=templates&id=", 75 | "fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFolder", 76 | "lookInContext": 1, 77 | "adminGroupID": 4, 78 | "betaServer": true}}], 79 | "servlet-mapping": { 80 | "cofaxCDS": "/", 81 | "cofaxEmail": "/cofaxutil/aemail/*", 82 | "cofaxAdmin": "/admin/*", 83 | "fileServlet": "/static/*", 84 | "cofaxTools": "/tools/*"}, 85 | 86 | "taglib": { 87 | "taglib-uri": "cofax.tld", 88 | "taglib-location": "/WEB-INF/tlds/cofax.tld"}}} -------------------------------------------------------------------------------- /bin/data/widget.json: -------------------------------------------------------------------------------- 1 | {"widget": { 2 | "debug": "on", 3 | "window": { 4 | "title": "Sample Konfabulator Widget", 5 | "name": "main_window", 6 | "width": 500, 7 | "height": 500 8 | }, 9 | "image": { 10 | "src": "Images/Sun.png", 11 | "name": "sun1", 12 | "hOffset": 250, 13 | "vOffset": 250, 14 | "alignment": "center" 15 | }, 16 | "text": { 17 | "data": "Click Here", 18 | "size": 36, 19 | "style": "bold", 20 | "name": "text1", 21 | "hOffset": 250, 22 | "vOffset": 100, 23 | "alignment": "center", 24 | "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;" 25 | } 26 | }} -------------------------------------------------------------------------------- /bin/encodings/utf16be.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TencentAPI/rapidjson_bk/1ef0f98f6a42212f11e461935cff1b8ea291cd88/bin/encodings/utf16be.json -------------------------------------------------------------------------------- /bin/encodings/utf16bebom.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TencentAPI/rapidjson_bk/1ef0f98f6a42212f11e461935cff1b8ea291cd88/bin/encodings/utf16bebom.json -------------------------------------------------------------------------------- /bin/encodings/utf16le.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TencentAPI/rapidjson_bk/1ef0f98f6a42212f11e461935cff1b8ea291cd88/bin/encodings/utf16le.json -------------------------------------------------------------------------------- /bin/encodings/utf16lebom.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TencentAPI/rapidjson_bk/1ef0f98f6a42212f11e461935cff1b8ea291cd88/bin/encodings/utf16lebom.json -------------------------------------------------------------------------------- /bin/encodings/utf32be.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TencentAPI/rapidjson_bk/1ef0f98f6a42212f11e461935cff1b8ea291cd88/bin/encodings/utf32be.json -------------------------------------------------------------------------------- /bin/encodings/utf32bebom.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TencentAPI/rapidjson_bk/1ef0f98f6a42212f11e461935cff1b8ea291cd88/bin/encodings/utf32bebom.json -------------------------------------------------------------------------------- /bin/encodings/utf32le.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TencentAPI/rapidjson_bk/1ef0f98f6a42212f11e461935cff1b8ea291cd88/bin/encodings/utf32le.json -------------------------------------------------------------------------------- /bin/encodings/utf32lebom.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TencentAPI/rapidjson_bk/1ef0f98f6a42212f11e461935cff1b8ea291cd88/bin/encodings/utf32lebom.json -------------------------------------------------------------------------------- /bin/encodings/utf8.json: -------------------------------------------------------------------------------- 1 | { 2 | "en":"I can eat glass and it doesn't hurt me.", 3 | "zh-Hant":"我能吞下玻璃而不傷身體。", 4 | "zh-Hans":"我能吞下玻璃而不伤身体。", 5 | "ja":"私はガラスを食べられます。それは私を傷つけません。", 6 | "ko":"나는 유리를 먹을 수 있어요. 그래도 아프지 않아요" 7 | } -------------------------------------------------------------------------------- /bin/encodings/utf8bom.json: -------------------------------------------------------------------------------- 1 | { 2 | "en":"I can eat glass and it doesn't hurt me.", 3 | "zh-Hant":"我能吞下玻璃而不傷身體。", 4 | "zh-Hans":"我能吞下玻璃而不伤身体。", 5 | "ja":"私はガラスを食べられます。それは私を傷つけません。", 6 | "ko":"나는 유리를 먹을 수 있어요. 그래도 아프지 않아요" 7 | } -------------------------------------------------------------------------------- /bin/jsonchecker/fail1.json: -------------------------------------------------------------------------------- 1 | "A JSON payload should be an object or array, not a string." -------------------------------------------------------------------------------- /bin/jsonchecker/fail10.json: -------------------------------------------------------------------------------- 1 | {"Extra value after close": true} "misplaced quoted value" -------------------------------------------------------------------------------- /bin/jsonchecker/fail11.json: -------------------------------------------------------------------------------- 1 | {"Illegal expression": 1 + 2} -------------------------------------------------------------------------------- /bin/jsonchecker/fail12.json: -------------------------------------------------------------------------------- 1 | {"Illegal invocation": alert()} -------------------------------------------------------------------------------- /bin/jsonchecker/fail13.json: -------------------------------------------------------------------------------- 1 | {"Numbers cannot have leading zeroes": 013} -------------------------------------------------------------------------------- /bin/jsonchecker/fail14.json: -------------------------------------------------------------------------------- 1 | {"Numbers cannot be hex": 0x14} -------------------------------------------------------------------------------- /bin/jsonchecker/fail15.json: -------------------------------------------------------------------------------- 1 | ["Illegal backslash escape: \x15"] -------------------------------------------------------------------------------- /bin/jsonchecker/fail16.json: -------------------------------------------------------------------------------- 1 | [\naked] -------------------------------------------------------------------------------- /bin/jsonchecker/fail17.json: -------------------------------------------------------------------------------- 1 | ["Illegal backslash escape: \017"] -------------------------------------------------------------------------------- /bin/jsonchecker/fail18.json: -------------------------------------------------------------------------------- 1 | [[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]] -------------------------------------------------------------------------------- /bin/jsonchecker/fail19.json: -------------------------------------------------------------------------------- 1 | {"Missing colon" null} -------------------------------------------------------------------------------- /bin/jsonchecker/fail2.json: -------------------------------------------------------------------------------- 1 | ["Unclosed array" -------------------------------------------------------------------------------- /bin/jsonchecker/fail20.json: -------------------------------------------------------------------------------- 1 | {"Double colon":: null} -------------------------------------------------------------------------------- /bin/jsonchecker/fail21.json: -------------------------------------------------------------------------------- 1 | {"Comma instead of colon", null} -------------------------------------------------------------------------------- /bin/jsonchecker/fail22.json: -------------------------------------------------------------------------------- 1 | ["Colon instead of comma": false] -------------------------------------------------------------------------------- /bin/jsonchecker/fail23.json: -------------------------------------------------------------------------------- 1 | ["Bad value", truth] -------------------------------------------------------------------------------- /bin/jsonchecker/fail24.json: -------------------------------------------------------------------------------- 1 | ['single quote'] -------------------------------------------------------------------------------- /bin/jsonchecker/fail25.json: -------------------------------------------------------------------------------- 1 | [" tab character in string "] -------------------------------------------------------------------------------- /bin/jsonchecker/fail26.json: -------------------------------------------------------------------------------- 1 | ["tab\ character\ in\ string\ "] -------------------------------------------------------------------------------- /bin/jsonchecker/fail27.json: -------------------------------------------------------------------------------- 1 | ["line 2 | break"] -------------------------------------------------------------------------------- /bin/jsonchecker/fail28.json: -------------------------------------------------------------------------------- 1 | ["line\ 2 | break"] -------------------------------------------------------------------------------- /bin/jsonchecker/fail29.json: -------------------------------------------------------------------------------- 1 | [0e] -------------------------------------------------------------------------------- /bin/jsonchecker/fail3.json: -------------------------------------------------------------------------------- 1 | {unquoted_key: "keys must be quoted"} -------------------------------------------------------------------------------- /bin/jsonchecker/fail30.json: -------------------------------------------------------------------------------- 1 | [0e+] -------------------------------------------------------------------------------- /bin/jsonchecker/fail31.json: -------------------------------------------------------------------------------- 1 | [0e+-1] -------------------------------------------------------------------------------- /bin/jsonchecker/fail32.json: -------------------------------------------------------------------------------- 1 | {"Comma instead if closing brace": true, -------------------------------------------------------------------------------- /bin/jsonchecker/fail33.json: -------------------------------------------------------------------------------- 1 | ["mismatch"} -------------------------------------------------------------------------------- /bin/jsonchecker/fail4.json: -------------------------------------------------------------------------------- 1 | ["extra comma",] -------------------------------------------------------------------------------- /bin/jsonchecker/fail5.json: -------------------------------------------------------------------------------- 1 | ["double extra comma",,] -------------------------------------------------------------------------------- /bin/jsonchecker/fail6.json: -------------------------------------------------------------------------------- 1 | [ , "<-- missing value"] -------------------------------------------------------------------------------- /bin/jsonchecker/fail7.json: -------------------------------------------------------------------------------- 1 | ["Comma after the close"], -------------------------------------------------------------------------------- /bin/jsonchecker/fail8.json: -------------------------------------------------------------------------------- 1 | ["Extra close"]] -------------------------------------------------------------------------------- /bin/jsonchecker/fail9.json: -------------------------------------------------------------------------------- 1 | {"Extra comma": true,} -------------------------------------------------------------------------------- /bin/jsonchecker/pass1.json: -------------------------------------------------------------------------------- 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": "// /* */": " ", 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"] -------------------------------------------------------------------------------- /bin/jsonchecker/pass2.json: -------------------------------------------------------------------------------- 1 | [[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]] -------------------------------------------------------------------------------- /bin/jsonchecker/pass3.json: -------------------------------------------------------------------------------- 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 | } 7 | -------------------------------------------------------------------------------- /bin/jsonchecker/readme.txt: -------------------------------------------------------------------------------- 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. 4 | -------------------------------------------------------------------------------- /doc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(Doxygen) 2 | 3 | IF(NOT DOXYGEN_FOUND) 4 | MESSAGE(STATUS "No Doxygen found. Documentation won't be built") 5 | ELSE() 6 | file(GLOB SOURCES ${CMAKE_SOURCE_DIR}/include/*) 7 | file(GLOB MARKDOWN_DOC ${CMAKE_SOURCE_DIR}/doc/*.md) 8 | list(APPEND MARKDOWN_DOC ${CMAKE_SOURCE_DIR}/readme.md) 9 | 10 | CONFIGURE_FILE(Doxyfile.in Doxyfile @ONLY) 11 | CONFIGURE_FILE(Doxyfile.zh-cn.in Doxyfile.zh-cn @ONLY) 12 | 13 | add_custom_command(OUTPUT html 14 | COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile 15 | COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile.zh-cn 16 | COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/html 17 | DEPENDS ${MARKDOWN_DOC} ${SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile* 18 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 19 | ) 20 | 21 | add_custom_target(doc ALL DEPENDS html) 22 | install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html 23 | DESTINATION ${DOC_INSTALL_DIR} 24 | COMPONENT doc) 25 | ENDIF() 26 | -------------------------------------------------------------------------------- /doc/diagram/architecture.dot: -------------------------------------------------------------------------------- 1 | digraph { 2 | compound=true 3 | fontname="Inconsolata, Consolas" 4 | fontsize=10 5 | margin="0,0" 6 | ranksep=0.2 7 | nodesep=0.5 8 | penwidth=0.5 9 | colorscheme=spectral7 10 | 11 | node [shape=box, fontname="Inconsolata, Consolas", fontsize=10, penwidth=0.5, style=filled, fillcolor=white] 12 | edge [fontname="Inconsolata, Consolas", fontsize=10, penwidth=0.5] 13 | 14 | subgraph cluster1 { 15 | margin="10,10" 16 | labeljust="left" 17 | label = "SAX" 18 | style=filled 19 | fillcolor=6 20 | 21 | Reader -> Writer [style=invis] 22 | } 23 | 24 | subgraph cluster2 { 25 | margin="10,10" 26 | labeljust="left" 27 | label = "DOM" 28 | style=filled 29 | fillcolor=7 30 | 31 | Value 32 | Document 33 | } 34 | 35 | Handler [label="<>\nHandler"] 36 | 37 | { 38 | edge [arrowtail=onormal, dir=back] 39 | Value -> Document 40 | Handler -> Document 41 | Handler -> Writer 42 | } 43 | 44 | { 45 | edge [arrowhead=vee, style=dashed, constraint=false] 46 | Reader -> Handler [label="calls"] 47 | Value -> Handler [label="calls"] 48 | Document -> Reader [label="uses"] 49 | } 50 | } -------------------------------------------------------------------------------- /doc/diagram/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TencentAPI/rapidjson_bk/1ef0f98f6a42212f11e461935cff1b8ea291cd88/doc/diagram/architecture.png -------------------------------------------------------------------------------- /doc/diagram/insituparsing.dot: -------------------------------------------------------------------------------- 1 | digraph { 2 | compound=true 3 | fontname="Inconsolata, Consolas" 4 | fontsize=10 5 | margin="0,0" 6 | ranksep=0.2 7 | penwidth=0.5 8 | 9 | node [fontname="Inconsolata, Consolas", fontsize=10, penwidth=0.5] 10 | edge [fontname="Inconsolata, Consolas", fontsize=10, arrowhead=normal] 11 | 12 | { 13 | node [shape=record, fontsize="8", margin="0.04", height=0.2, color=gray] 14 | oldjson [label="\{|\"|m|s|g|\"|:|\"|H|e|l|l|o|\\|n|W|o|r|l|d|!|\"|,|\"|\\|u|0|0|7|3|t|a|r|s|\"|:|1|0|\}", xlabel="Before Parsing"] 15 | //newjson [label="\{|\"|m|s|g|\\0|:|\"|H|e|l|l|o|\\n|W|o|r|l|d|!|\\0|\"|,|\"|s|t|a|r|s|\\0|t|a|r|s|:|1|0|\}", xlabel="After Parsing"] 16 | newjson [shape=plaintext, label=< 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
{"msg\\0:"Hello\\nWorld!\\0","stars\\0tars:10}
28 | >, xlabel="After Parsing"] 29 | } 30 | 31 | subgraph cluster1 { 32 | margin="10,10" 33 | labeljust="left" 34 | label = "Document by In situ Parsing" 35 | style=filled 36 | fillcolor=gray95 37 | node [shape=Mrecord, style=filled, colorscheme=spectral7] 38 | 39 | root [label="{object|}", fillcolor=3] 40 | 41 | { 42 | msg [label="{string|
}", fillcolor=5] 43 | helloworld [label="{string|}", fillcolor=5] 44 | stars [label="{string|}", fillcolor=5] 45 | ten [label="{number|10}", fillcolor=6] 46 | } 47 | } 48 | 49 | oldjson -> root [label=" ParseInsitu()" lhead="cluster1"] 50 | edge [arrowhead=vee] 51 | root -> { msg; stars } 52 | 53 | edge [arrowhead="none"] 54 | msg -> helloworld 55 | stars -> ten 56 | 57 | { 58 | edge [arrowhead=vee, arrowtail=dot, arrowsize=0.5, dir=both, tailclip=false] 59 | msg:a:c -> newjson:a 60 | helloworld:a:c -> newjson:b 61 | stars:a:c -> newjson:c 62 | } 63 | 64 | //oldjson -> newjson [style=invis] 65 | } -------------------------------------------------------------------------------- /doc/diagram/insituparsing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TencentAPI/rapidjson_bk/1ef0f98f6a42212f11e461935cff1b8ea291cd88/doc/diagram/insituparsing.png -------------------------------------------------------------------------------- /doc/diagram/iterative-parser-states-diagram.dot: -------------------------------------------------------------------------------- 1 | digraph { 2 | fontname="Inconsolata, Consolas" 3 | fontsize=10 4 | margin="0,0" 5 | penwidth=0.0 6 | 7 | node [fontname="Inconsolata, Consolas", fontsize=10, penwidth=0.5] 8 | edge [fontname="Inconsolata, Consolas", fontsize=10, penwidth=0.5] 9 | 10 | node [shape = doublecircle]; Start; Finish; 11 | node [shape = box; style = "rounded, filled"; fillcolor=white ]; 12 | 13 | Start -> ArrayInitial [label=" ["]; 14 | Start -> ObjectInitial [label=" {"]; 15 | 16 | subgraph clusterArray { 17 | margin="10,10" 18 | style=filled 19 | fillcolor=gray95 20 | label = "Array" 21 | 22 | ArrayInitial; Element; ElementDelimiter; ArrayFinish; 23 | } 24 | 25 | subgraph clusterObject { 26 | margin="10,10" 27 | style=filled 28 | fillcolor=gray95 29 | label = "Object" 30 | 31 | ObjectInitial; MemberKey; KeyValueDelimiter; MemberValue; MemberDelimiter; ObjectFinish; 32 | } 33 | 34 | ArrayInitial -> ArrayInitial [label="["]; 35 | ArrayInitial -> ArrayFinish [label=" ]"]; 36 | ArrayInitial -> ObjectInitial [label="{", constraint=false]; 37 | ArrayInitial -> Element [label="string\nfalse\ntrue\nnull\nnumber"]; 38 | 39 | Element -> ArrayFinish [label="]"]; 40 | Element -> ElementDelimiter [label=","]; 41 | 42 | ElementDelimiter -> ArrayInitial [label=" ["]; 43 | ElementDelimiter -> ObjectInitial [label="{"]; 44 | ElementDelimiter -> Element [label="string\nfalse\ntrue\nnull\nnumber"]; 45 | 46 | ObjectInitial -> ObjectFinish [label=" }"]; 47 | ObjectInitial -> MemberKey [label=" string "]; 48 | 49 | MemberKey -> KeyValueDelimiter [label=":"]; 50 | 51 | KeyValueDelimiter -> ArrayInitial [label="["]; 52 | KeyValueDelimiter -> ObjectInitial [label=" {"]; 53 | KeyValueDelimiter -> MemberValue [label=" string\n false\n true\n null\n number"]; 54 | 55 | MemberValue -> ObjectFinish [label="}"]; 56 | MemberValue -> MemberDelimiter [label=","]; 57 | 58 | MemberDelimiter -> MemberKey [label=" string "]; 59 | 60 | ArrayFinish -> Finish; 61 | ObjectFinish -> Finish; 62 | } 63 | -------------------------------------------------------------------------------- /doc/diagram/iterative-parser-states-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TencentAPI/rapidjson_bk/1ef0f98f6a42212f11e461935cff1b8ea291cd88/doc/diagram/iterative-parser-states-diagram.png -------------------------------------------------------------------------------- /doc/diagram/makefile: -------------------------------------------------------------------------------- 1 | %.pdf: %.dot 2 | dot $< -Tpdf -o $@ 3 | 4 | %.png: %.dot 5 | dot $< -Tpng -o $@ 6 | 7 | DOTFILES = $(basename $(wildcard *.dot)) 8 | all: $(addsuffix .png, $(DOTFILES)) $(addsuffix .pdf, $(DOTFILES)) 9 | -------------------------------------------------------------------------------- /doc/diagram/move1.dot: -------------------------------------------------------------------------------- 1 | digraph { 2 | compound=true 3 | fontname="Inconsolata, Consolas" 4 | fontsize=10 5 | margin="0,0" 6 | ranksep=0.2 7 | penwidth=0.5 8 | 9 | node [fontname="Inconsolata, Consolas", fontsize=10, penwidth=0.5] 10 | edge [fontname="Inconsolata, Consolas", fontsize=10, arrowhead=normal] 11 | 12 | subgraph cluster1 { 13 | margin="10,10" 14 | labeljust="left" 15 | label = "Before" 16 | style=filled 17 | fillcolor=gray95 18 | 19 | node [shape=Mrecord, style=filled, colorscheme=spectral7] 20 | 21 | { 22 | rank = same 23 | b1 [label="{b:number|456}", fillcolor=6] 24 | a1 [label="{a:number|123}", fillcolor=6] 25 | } 26 | 27 | a1 -> b1 [style="dashed", label="Move", dir=back] 28 | } 29 | 30 | subgraph cluster2 { 31 | margin="10,10" 32 | labeljust="left" 33 | label = "After" 34 | style=filled 35 | fillcolor=gray95 36 | 37 | node [shape=Mrecord, style=filled, colorscheme=spectral7] 38 | 39 | { 40 | rank = same 41 | b2 [label="{b:null|}", fillcolor=1] 42 | a2 [label="{a:number|456}", fillcolor=6] 43 | } 44 | a2 -> b2 [style=invis, dir=back] 45 | } 46 | b1 -> b2 [style=invis] 47 | } -------------------------------------------------------------------------------- /doc/diagram/move1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TencentAPI/rapidjson_bk/1ef0f98f6a42212f11e461935cff1b8ea291cd88/doc/diagram/move1.png -------------------------------------------------------------------------------- /doc/diagram/move2.dot: -------------------------------------------------------------------------------- 1 | digraph { 2 | compound=true 3 | fontname="Inconsolata, Consolas" 4 | fontsize=10 5 | margin="0,0" 6 | ranksep=0.2 7 | penwidth=0.5 8 | 9 | node [fontname="Inconsolata, Consolas", fontsize=10, penwidth=0.5] 10 | edge [fontname="Inconsolata, Consolas", fontsize=10, arrowhead=normal] 11 | 12 | subgraph cluster1 { 13 | margin="10,10" 14 | labeljust="left" 15 | label = "Before Copying (Hypothetic)" 16 | style=filled 17 | fillcolor=gray95 18 | 19 | node [shape=Mrecord, style=filled, colorscheme=spectral7] 20 | 21 | c1 [label="{contact:array|}", fillcolor=4] 22 | c11 [label="{|}"] 23 | c12 [label="{|}"] 24 | c13 [shape="none", label="...", style="solid"] 25 | o1 [label="{o:object|}", fillcolor=3] 26 | ghost [label="{o:object|}", style=invis] 27 | 28 | c1 -> o1 [style="dashed", label="AddMember", constraint=false] 29 | 30 | edge [arrowhead=vee] 31 | c1 -> { c11; c12; c13 } 32 | o1 -> ghost [style=invis] 33 | } 34 | 35 | subgraph cluster2 { 36 | margin="10,10" 37 | labeljust="left" 38 | label = "After Copying (Hypothetic)" 39 | style=filled 40 | fillcolor=gray95 41 | 42 | node [shape=Mrecord, style=filled, colorscheme=spectral7] 43 | 44 | c2 [label="{contact:array|}", fillcolor=4] 45 | c3 [label="{array|}", fillcolor=4] 46 | c21 [label="{|}"] 47 | c22 [label="{|}"] 48 | c23 [shape=none, label="...", style="solid"] 49 | o2 [label="{o:object|}", fillcolor=3] 50 | cs [label="{string|\"contact\"}", fillcolor=5] 51 | c31 [label="{|}"] 52 | c32 [label="{|}"] 53 | c33 [shape="none", label="...", style="solid"] 54 | 55 | edge [arrowhead=vee] 56 | c2 -> { c21; c22; c23 } 57 | o2 -> cs 58 | cs -> c3 [arrowhead=none] 59 | c3 -> { c31; c32; c33 } 60 | } 61 | ghost -> o2 [style=invis] 62 | } -------------------------------------------------------------------------------- /doc/diagram/move2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TencentAPI/rapidjson_bk/1ef0f98f6a42212f11e461935cff1b8ea291cd88/doc/diagram/move2.png -------------------------------------------------------------------------------- /doc/diagram/move3.dot: -------------------------------------------------------------------------------- 1 | digraph { 2 | compound=true 3 | fontname="Inconsolata, Consolas" 4 | fontsize=10 5 | margin="0,0" 6 | ranksep=0.2 7 | penwidth=0.5 8 | forcelabels=true 9 | 10 | node [fontname="Inconsolata, Consolas", fontsize=10, penwidth=0.5] 11 | edge [fontname="Inconsolata, Consolas", fontsize=10, arrowhead=normal] 12 | 13 | subgraph cluster1 { 14 | margin="10,10" 15 | labeljust="left" 16 | label = "Before Moving" 17 | style=filled 18 | fillcolor=gray95 19 | 20 | node [shape=Mrecord, style=filled, colorscheme=spectral7] 21 | 22 | c1 [label="{contact:array|}", fillcolor=4] 23 | c11 [label="{|}"] 24 | c12 [label="{|}"] 25 | c13 [shape=none, label="...", style="solid"] 26 | o1 [label="{o:object|}", fillcolor=3] 27 | ghost [label="{o:object|}", style=invis] 28 | 29 | c1 -> o1 [style="dashed", constraint=false, label="AddMember"] 30 | 31 | edge [arrowhead=vee] 32 | c1 -> { c11; c12; c13 } 33 | o1 -> ghost [style=invis] 34 | } 35 | 36 | subgraph cluster2 { 37 | margin="10,10" 38 | labeljust="left" 39 | label = "After Moving" 40 | style=filled 41 | fillcolor=gray95 42 | 43 | node [shape=Mrecord, style=filled, colorscheme=spectral7] 44 | 45 | c2 [label="{contact:null|}", fillcolor=1] 46 | c3 [label="{array|}", fillcolor=4] 47 | c21 [label="{|}"] 48 | c22 [label="{|}"] 49 | c23 [shape="none", label="...", style="solid"] 50 | o2 [label="{o:object|}", fillcolor=3] 51 | cs [label="{string|\"contact\"}", fillcolor=5] 52 | c2 -> o2 [style="dashed", constraint=false, label="AddMember", style=invis] 53 | 54 | edge [arrowhead=vee] 55 | c3 -> { c21; c22; c23 } 56 | o2 -> cs 57 | cs -> c3 [arrowhead=none] 58 | } 59 | ghost -> o2 [style=invis] 60 | } -------------------------------------------------------------------------------- /doc/diagram/move3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TencentAPI/rapidjson_bk/1ef0f98f6a42212f11e461935cff1b8ea291cd88/doc/diagram/move3.png -------------------------------------------------------------------------------- /doc/diagram/normalparsing.dot: -------------------------------------------------------------------------------- 1 | digraph { 2 | compound=true 3 | fontname="Inconsolata, Consolas" 4 | fontsize=10 5 | margin="0,0" 6 | ranksep=0.2 7 | penwidth=0.5 8 | 9 | node [fontname="Inconsolata, Consolas", fontsize=10, penwidth=0.5] 10 | edge [fontname="Inconsolata, Consolas", fontsize=10, arrowhead=normal] 11 | 12 | { 13 | node [shape=record, fontsize="8", margin="0.04", height=0.2, color=gray] 14 | normaljson [label="\{|\"|m|s|g|\"|:|\"|H|e|l|l|o|\\|n|W|o|r|l|d|!|\"|,|\"|\\|u|0|0|7|3|t|a|r|s\"|:|1|0|\}"] 15 | 16 | { 17 | rank = same 18 | msgstring [label="m|s|g|\\0"] 19 | helloworldstring [label="H|e|l|l|o|\\n|W|o|r|l|d|!|\\0"] 20 | starsstring [label="s|t|a|r|s\\0"] 21 | } 22 | } 23 | 24 | subgraph cluster1 { 25 | margin="10,10" 26 | labeljust="left" 27 | label = "Document by Normal Parsing" 28 | style=filled 29 | fillcolor=gray95 30 | node [shape=Mrecord, style=filled, colorscheme=spectral7] 31 | 32 | root [label="{object|}", fillcolor=3] 33 | 34 | { 35 | msg [label="{string|}", fillcolor=5] 36 | helloworld [label="{string|}", fillcolor=5] 37 | stars [label="{string|}", fillcolor=5] 38 | ten [label="{number|10}", fillcolor=6] 39 | } 40 | } 41 | 42 | normaljson -> root [label=" Parse()" lhead="cluster1"] 43 | edge [arrowhead=vee] 44 | root -> { msg; stars } 45 | 46 | edge [arrowhead="none"] 47 | msg -> helloworld 48 | stars -> ten 49 | 50 | edge [arrowhead=vee, arrowtail=dot, arrowsize=0.5, dir=both, tailclip=false] 51 | msg:a:c -> msgstring:w 52 | helloworld:a:c -> helloworldstring:w 53 | stars:a:c -> starsstring:w 54 | 55 | msgstring -> helloworldstring -> starsstring [style=invis] 56 | } -------------------------------------------------------------------------------- /doc/diagram/normalparsing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TencentAPI/rapidjson_bk/1ef0f98f6a42212f11e461935cff1b8ea291cd88/doc/diagram/normalparsing.png -------------------------------------------------------------------------------- /doc/diagram/simpledom.dot: -------------------------------------------------------------------------------- 1 | digraph { 2 | compound=true 3 | fontname="Inconsolata, Consolas" 4 | fontsize=10 5 | margin="0,0" 6 | ranksep=0.2 7 | penwidth=0.5 8 | 9 | node [fontname="Inconsolata, Consolas", fontsize=10, penwidth=0.5] 10 | edge [fontname="Inconsolata, Consolas", fontsize=10, arrowhead=normal] 11 | 12 | { 13 | node [shape=record, fontsize="8", margin="0.04", height=0.2, color=gray] 14 | srcjson [label="\{|\"|p|r|o|j|e|c|t|\"|:|\"|r|a|p|i|d|j|s|o|n|\"|,|\"|s|t|a|r|s|\"|:|1|0|\}"] 15 | dstjson [label="\{|\"|p|r|o|j|e|c|t|\"|:|\"|r|a|p|i|d|j|s|o|n|\"|,|\"|s|t|a|r|s|\"|:|1|1|\}"] 16 | } 17 | 18 | { 19 | node [shape="box", style="filled", fillcolor="gray95"] 20 | Document2 [label="(Modified) Document"] 21 | Writer 22 | } 23 | 24 | subgraph cluster1 { 25 | margin="10,10" 26 | labeljust="left" 27 | label = "Document" 28 | style=filled 29 | fillcolor=gray95 30 | node [shape=Mrecord, style=filled, colorscheme=spectral7] 31 | 32 | root [label="{object|}", fillcolor=3] 33 | 34 | { 35 | project [label="{string|\"project\"}", fillcolor=5] 36 | rapidjson [label="{string|\"rapidjson\"}", fillcolor=5] 37 | stars [label="{string|\"stars\"}", fillcolor=5] 38 | ten [label="{number|10}", fillcolor=6] 39 | } 40 | 41 | edge [arrowhead=vee] 42 | root -> { project; stars } 43 | 44 | edge [arrowhead="none"] 45 | project -> rapidjson 46 | stars -> ten 47 | } 48 | 49 | srcjson -> root [label=" Parse()", lhead="cluster1"] 50 | 51 | ten -> Document2 [label=" Increase \"stars\"", ltail="cluster1" ] 52 | Document2 -> Writer [label=" Traverse DOM by Accept()"] 53 | Writer -> dstjson [label=" Output to StringBuffer"] 54 | } -------------------------------------------------------------------------------- /doc/diagram/simpledom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TencentAPI/rapidjson_bk/1ef0f98f6a42212f11e461935cff1b8ea291cd88/doc/diagram/simpledom.png -------------------------------------------------------------------------------- /doc/diagram/tutorial.dot: -------------------------------------------------------------------------------- 1 | digraph { 2 | compound=true 3 | fontname="Inconsolata, Consolas" 4 | fontsize=10 5 | margin="0,0" 6 | ranksep=0.2 7 | penwidth=0.5 8 | 9 | node [fontname="Inconsolata, Consolas", fontsize=10, penwidth=0.5] 10 | edge [fontname="Inconsolata, Consolas", fontsize=10] 11 | 12 | subgraph cluster1 { 13 | margin="10,10" 14 | labeljust="left" 15 | label = "Document" 16 | style=filled 17 | fillcolor=gray95 18 | node [shape=Mrecord, style=filled, colorscheme=spectral7] 19 | 20 | root [label="{object|}", fillcolor=3] 21 | 22 | { 23 | hello [label="{string|\"hello\"}", fillcolor=5] 24 | t [label="{string|\"t\"}", fillcolor=5] 25 | f [label="{string|\"f\"}", fillcolor=5] 26 | n [label="{string|\"n\"}", fillcolor=5] 27 | i [label="{string|\"i\"}", fillcolor=5] 28 | pi [label="{string|\"pi\"}", fillcolor=5] 29 | a [label="{string|\"a\"}", fillcolor=5] 30 | 31 | world [label="{string|\"world\"}", fillcolor=5] 32 | true [label="{true|}", fillcolor=7] 33 | false [label="{false|}", fillcolor=2] 34 | null [label="{null|}", fillcolor=1] 35 | i1 [label="{number|123}", fillcolor=6] 36 | pi1 [label="{number|3.1416}", fillcolor=6] 37 | array [label="{array|size=4}", fillcolor=4] 38 | 39 | a1 [label="{number|1}", fillcolor=6] 40 | a2 [label="{number|2}", fillcolor=6] 41 | a3 [label="{number|3}", fillcolor=6] 42 | a4 [label="{number|4}", fillcolor=6] 43 | } 44 | 45 | edge [arrowhead=vee] 46 | root -> { hello; t; f; n; i; pi; a } 47 | array -> { a1; a2; a3; a4 } 48 | 49 | edge [arrowhead=none] 50 | hello -> world 51 | t -> true 52 | f -> false 53 | n -> null 54 | i -> i1 55 | pi -> pi1 56 | a -> array 57 | } 58 | } -------------------------------------------------------------------------------- /doc/diagram/tutorial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TencentAPI/rapidjson_bk/1ef0f98f6a42212f11e461935cff1b8ea291cd88/doc/diagram/tutorial.png -------------------------------------------------------------------------------- /doc/diagram/utilityclass.dot: -------------------------------------------------------------------------------- 1 | digraph { 2 | rankdir=LR 3 | compound=true 4 | fontname="Inconsolata, Consolas" 5 | fontsize=10 6 | margin="0,0" 7 | ranksep=0.3 8 | nodesep=0.15 9 | penwidth=0.5 10 | colorscheme=spectral7 11 | 12 | node [shape=box, fontname="Inconsolata, Consolas", fontsize=10, penwidth=0.5, style=filled, fillcolor=white] 13 | edge [fontname="Inconsolata, Consolas", fontsize=10, penwidth=0.5] 14 | 15 | subgraph cluster0 { 16 | style=filled 17 | fillcolor=4 18 | 19 | Encoding [label="<>\nEncoding"] 20 | 21 | edge [arrowtail=onormal, dir=back] 22 | Encoding -> { UTF8; UTF16; UTF32; ASCII; AutoUTF } 23 | UTF16 -> { UTF16LE; UTF16BE } 24 | UTF32 -> { UTF32LE; UTF32BE } 25 | } 26 | 27 | subgraph cluster1 { 28 | style=filled 29 | fillcolor=5 30 | 31 | Stream [label="<>\nStream"] 32 | InputByteStream [label="<>\nInputByteStream"] 33 | OutputByteStream [label="<>\nOutputByteStream"] 34 | 35 | edge [arrowtail=onormal, dir=back] 36 | Stream -> { 37 | StringStream; InsituStringStream; StringBuffer; 38 | EncodedInputStream; EncodedOutputStream; 39 | AutoUTFInputStream; AutoUTFOutputStream 40 | InputByteStream; OutputByteStream 41 | } 42 | 43 | InputByteStream -> { MemoryStream; FlieReadStream } 44 | OutputByteStream -> { MemoryBuffer; FileWriteStream } 45 | } 46 | 47 | subgraph cluster2 { 48 | style=filled 49 | fillcolor=3 50 | 51 | Allocator [label="<>\nAllocator"] 52 | 53 | edge [arrowtail=onormal, dir=back] 54 | Allocator -> { CrtAllocator; MemoryPoolAllocator } 55 | } 56 | 57 | { 58 | edge [arrowtail=odiamond, arrowhead=vee, dir=both] 59 | EncodedInputStream -> InputByteStream 60 | EncodedOutputStream -> OutputByteStream 61 | AutoUTFInputStream -> InputByteStream 62 | AutoUTFOutputStream -> OutputByteStream 63 | MemoryPoolAllocator -> Allocator [label="base", tailport=s] 64 | } 65 | 66 | { 67 | edge [arrowhead=vee, style=dashed] 68 | AutoUTFInputStream -> AutoUTF 69 | AutoUTFOutputStream -> AutoUTF 70 | } 71 | 72 | //UTF32LE -> Stream [style=invis] 73 | } -------------------------------------------------------------------------------- /doc/diagram/utilityclass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TencentAPI/rapidjson_bk/1ef0f98f6a42212f11e461935cff1b8ea291cd88/doc/diagram/utilityclass.png -------------------------------------------------------------------------------- /doc/encoding.zh-cn.md: -------------------------------------------------------------------------------- 1 | # 编码 2 | 3 | 根据[ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf): 4 | 5 | > (in Introduction) JSON text is a sequence of Unicode code points. 6 | > 7 | > 翻译:JSON文本是Unicode码点的序列。 8 | 9 | 较早的[RFC4627](http://www.ietf.org/rfc/rfc4627.txt)申明: 10 | 11 | > (in §3) JSON text SHALL be encoded in Unicode. The default encoding is UTF-8. 12 | > 13 | > 翻译:JSON文本应该以Unicode编码。缺省的编码为UTF-8。 14 | 15 | > (in §6) JSON may be represented using UTF-8, UTF-16, or UTF-32. When JSON is written in UTF-8, JSON is 8bit compatible. When JSON is written in UTF-16 or UTF-32, the binary content-transfer-encoding must be used. 16 | > 17 | > 翻译:JSON可使用UTF-8、UTF-16或UTF-18表示。当JSON以UTF-8写入,该JSON是8位兼容的。当JSON以UTF-16或UTF-32写入,就必须使用二进制的内容传送编码。 18 | 19 | RapidJSON支持多种编码。它也能检查JSON的编码,以及在不同编码中进行转码。所有这些功能都是在内部实现,无需使用外部的程序库(如[ICU](http://site.icu-project.org/))。 20 | 21 | [TOC] 22 | 23 | # Unicode {#Unicode} 24 | 根据 [Unicode的官方网站](http://www.unicode.org/standard/translations/t-chinese.html): 25 | >Unicode给每个字符提供了一个唯一的数字, 26 | 不论是什么平台、 27 | 不论是什么程序、 28 | 不论是什么语言。 29 | 30 | 这些唯一数字称为码点(code point),其范围介乎`0x0`至`0x10FFFF`之间。 31 | 32 | ## Unicode转换格式 {#UTF} 33 | 34 | 存储Unicode码点有多种编码方式。这些称为Unicode转换格式(Unicode Transformation Format, UTF)。RapidJSON支持最常用的UTF,包括: 35 | 36 | * UTF-8:8位可变长度编码。它把一个码点映射至1至4个字节。 37 | * UTF-16:16位可变长度编码。它把一个码点映射至1至2个16位编码单元(即2至4个字节)。 38 | * UTF-32:32位固定长度编码。它直接把码点映射至单个32位编码单元(即4字节)。 39 | 40 | 对于UTF-16及UTF-32来说,字节序(endianness)是有影响的。在内存中,它们通常都是以该计算机的字节序来存储。然而,当要储存在文件中或在网上传输,我们需要指明字节序列的字节序,是小端(little endian, LE)还是大端(big-endian, BE)。 41 | 42 | RapidJSON通过`rapidjson/encodings.h`中的struct去提供各种编码: 43 | 44 | ~~~~~~~~~~cpp 45 | namespace rapidjson { 46 | 47 | template 48 | struct UTF8; 49 | 50 | template 51 | struct UTF16; 52 | 53 | template 54 | struct UTF16LE; 55 | 56 | template 57 | struct UTF16BE; 58 | 59 | template 60 | struct UTF32; 61 | 62 | template 63 | struct UTF32LE; 64 | 65 | template 66 | struct UTF32BE; 67 | 68 | } // namespace rapidjson 69 | ~~~~~~~~~~ 70 | 71 | 对于在内存中的文本,我们正常会使用`UTF8`、`UTF16`或`UTF32`。对于处理经过I/O的文本,我们可使用`UTF8`、`UTF16LE`、`UTF16BE`、`UTF32LE`或`UTF32BE`。 72 | 73 | 当使用DOM风格的API,`GenericValue`及`GenericDocument`里的`Encoding`模板参数是用于指明内存中存储的JSON字符串使用哪种编码。因此通常我们会在此参数中使用`UTF8`、`UTF16`或`UTF32`。如何选择,视乎应用软件所使用的操作系统及其他程序库。例如,Windows API使用UTF-16表示Unicode字符,而多数的Linux发行版本及应用软件则更喜欢UTF-8。 74 | 75 | 使用UTF-16的DOM声明例子: 76 | 77 | ~~~~~~~~~~cpp 78 | typedef GenericDocument > WDocument; 79 | typedef GenericValue > WValue; 80 | ~~~~~~~~~~ 81 | 82 | 可以在[DOM's Encoding](doc/stream.md)一节看到更详细的使用例子。 83 | 84 | ## 字符类型 {#CharacterType} 85 | 86 | 从之前的声明中可以看到,每个编码都有一个`CharType`模板参数。这可能比较容易混淆,实际上,每个`CharType`存储一个编码单元,而不是一个字符(码点)。如之前所谈及,在UTF-8中一个码点可能会编码成1至4个编码单元。 87 | 88 | 对于`UTF16(LE|BE)`及`UTF32(LE|BE)`来说,`CharType`必须分别是一个至少2及4字节的整数类型。 89 | 90 | 注意C++11新添了`char16_t`及`char32_t`类型,也可分别用于`UTF16`及`UTF32`。 91 | 92 | ## AutoUTF {#AutoUTF} 93 | 94 | 上述所介绍的编码都是在编译期静态挷定的。换句话说,使用者必须知道内存或流之中使用了哪种编码。然而,有时候我们可能需要读写不同编码的文件,而且这些编码需要在运行时才能决定。 95 | 96 | `AutoUTF`是为此而设计的编码。它根据输入或输出流来选择使用哪种编码。目前它应该与`EncodedInputStream`及`EncodedOutputStream`结合使用。 97 | 98 | ## ASCII {#ASCII} 99 | 100 | 虽然JSON标准并未提及[ASCII](http://en.wikipedia.org/wiki/ASCII),有时候我们希望写入7位的ASCII JSON,以供未能处理UTF-8的应用程序使用。由于任JSON都可以把Unicode字符表示为`\uXXXX`转义序列,JSON总是可用ASCII来编码。 101 | 102 | 以下的例子把UTF-8的DOM写成ASCII的JSON: 103 | 104 | ~~~~~~~~~~cpp 105 | using namespace rapidjson; 106 | Document d; // UTF8<> 107 | // ... 108 | StringBuffer buffer; 109 | Writer > writer(buffer); 110 | d.Accept(writer); 111 | std::cout << buffer.GetString(); 112 | ~~~~~~~~~~ 113 | 114 | ASCII可用于输入流。当输入流包含大于127的字节,就会导致`kParseErrorStringInvalidEncoding`错误。 115 | 116 | ASCII *不能* 用于内存(`Document`的编码,或`Reader`的目标编码),因为它不能表示Unicode码点。 117 | 118 | # 校验及转码 {#ValidationTranscoding} 119 | 120 | 当RapidJSON解析一个JSON时,它能校验输入JSON,判断它是否所标明编码的合法序列。要开启此选项,请把`kParseValidateEncodingFlag`加入`parseFlags`模板参数。 121 | 122 | 若输入编码和输出编码并不相同,`Reader`及`Writer`会算把文本转码。在这种情况下,并不需要`kParseValidateEncodingFlag`,因为它必须解码输入序列。若序列不能被解码,它必然是不合法的。 123 | 124 | ## 转码器 {#Transcoder} 125 | 126 | 虽然RapidJSON的编码功能是为JSON解析/生成而设计,使用者也可以“滥用”它们来为非JSON字符串转码。 127 | 128 | 以下的例子把UTF-8字符串转码成UTF-16: 129 | 130 | ~~~~~~~~~~cpp 131 | #include "rapidjson/encodings.h" 132 | 133 | using namespace rapidjson; 134 | 135 | const char* s = "..."; // UTF-8 string 136 | StringStream source(s); 137 | GenericStringBuffer > target; 138 | 139 | bool hasError = false; 140 | while (source.Peak() != '\0') 141 | if (!Transcoder::Transcode, UTF16<> >(source, target)) { 142 | hasError = true; 143 | break; 144 | } 145 | 146 | if (!hasError) { 147 | const wchar_t* t = target.GetString(); 148 | // ... 149 | } 150 | ~~~~~~~~~~ 151 | 152 | 你也可以用`AutoUTF`及对应的流来在运行时设置内源/目的之编码。 153 | -------------------------------------------------------------------------------- /doc/features.md: -------------------------------------------------------------------------------- 1 | # Features 2 | 3 | ## General 4 | 5 | * Cross-platform 6 | * Compilers: Visual Studio, gcc, clang, etc. 7 | * Architectures: x86, x64, ARM, etc. 8 | * Operating systems: Windows, Mac OS X, Linux, iOS, Android, etc. 9 | * Easy installation 10 | * Header files only library. Just copy the headers to your project. 11 | * Self-contained, minimal dependences 12 | * No STL, BOOST, etc. 13 | * Only included ``, ``, ``, ``, ``, ``. 14 | * Without C++ exception, RTTI 15 | * High performance 16 | * Use template and inline functions to reduce function call overheads. 17 | * Internal optimized Grisu2 and floating point parsing implementations. 18 | * Optional SSE2/SSE4.2 support. 19 | 20 | ## Standard compliance 21 | 22 | * RapidJSON should be fully RFC4627/ECMA-404 compliance. 23 | * Support Unicode surrogate. 24 | * Support null character (`"\u0000"`) 25 | * For example, `["Hello\u0000World"]` can be parsed and handled gracefully. There is API for getting/setting lengths of string. 26 | 27 | ## Unicode 28 | 29 | * Support UTF-8, UTF-16, UTF-32 encodings, including little endian and big endian. 30 | * These encodings are used in input/output streams and in-memory representation. 31 | * Support automatic detection of encodings in input stream. 32 | * Support transcoding between encodings internally. 33 | * For example, you can read a UTF-8 file and let RapidJSON transcode the JSON strings into UTF-16 in the DOM. 34 | * Support encoding validation internally. 35 | * For example, you can read a UTF-8 file, and let RapidJSON check whether all JSON strings are valid UTF-8 byte sequence. 36 | * Support custom character types. 37 | * By default the character types are `char` for UTF8, `wchar_t` for UTF16, `uint32_t` for UTF32. 38 | * Support custom encodings. 39 | 40 | ## API styles 41 | 42 | * SAX (Simple API for XML) style API 43 | * Similar to [SAX](http://en.wikipedia.org/wiki/Simple_API_for_XML), RapidJSON provides a event sequential access parser API (`rapidjson::GenericReader`). It also provides a generator API (`rapidjson::Writer`) which consumes the same set of events. 44 | * DOM (Document Object Model) style API 45 | * Similar to [DOM](http://en.wikipedia.org/wiki/Document_Object_Model) for HTML/XML, RapidJSON can parse JSON into a DOM representation (`rapidjson::GenericDocument`), for easy manipulation, and finally stringify back to JSON if needed. 46 | * The DOM style API (`rapidjson::GenericDocument`) is actually implemented with SAX style API (`rapidjson::GenericReader`). SAX is faster but sometimes DOM is easier. Users can pick their choices according to scenarios. 47 | 48 | ## Parsing 49 | 50 | * Recursive (default) and iterative parser 51 | * Recursive parser is faster but prone to stack overflow in extreme cases. 52 | * Iterative parser use custom stack to keep parsing state. 53 | * Support *in situ* parsing. 54 | * Parse JSON string values in-place at the source JSON, and then the DOM points to addresses of those strings. 55 | * Faster than convention parsing: no allocation for strings, no copy (if string does not contain escapes), cache-friendly. 56 | * Support 32-bit/64-bit signed/unsigned integer and `double` for JSON number type. 57 | * Support parsing multiple JSONs in input stream (`kParseStopWhenDoneFlag`). 58 | * Error Handling 59 | * Support comprehensive error code if parsing failed. 60 | * Support error message localization. 61 | 62 | ## DOM (Document) 63 | 64 | * RapidJSON checks range of numerical values for conversions. 65 | * Optimization for string literal 66 | * Only store pointer instead of copying 67 | * Optimization for "short" strings 68 | * Store short string in `Value` internally without additional allocation. 69 | * For UTF-8 string: maximum 11 characters in 32-bit, 15 characters in 64-bit. 70 | * Optionally support `std::string` (define `RAPIDJSON_HAS_STDSTRING=1`) 71 | 72 | ## Generation 73 | 74 | * Support `rapidjson::PrettyWriter` for adding newlines and indentations. 75 | 76 | ## Stream 77 | 78 | * Support `rapidjson::GenericStringBuffer` for storing the output JSON as string. 79 | * Support `rapidjson::FileReadStream` and `rapidjson::FileWriteStream` for input/output `FILE` object. 80 | * Support custom streams. 81 | 82 | ## Memory 83 | 84 | * Minimize memory overheads for DOM. 85 | * Each JSON value occupies exactly 16/20 bytes for most 32/64-bit machines (excluding text string). 86 | * Support fast default allocator. 87 | * A stack-based allocator (allocate sequentially, prohibit to free individual allocations, suitable for parsing). 88 | * User can provide a pre-allocated buffer. (Possible to parse a number of JSONs without any CRT allocation) 89 | * Support standard CRT(C-runtime) allocator. 90 | * Support custom allocators. 91 | 92 | ## Miscellaneous 93 | 94 | * Some C++11 support (optional) 95 | * Rvalue reference 96 | * `noexcept` specifier 97 | -------------------------------------------------------------------------------- /doc/features.zh-cn.md: -------------------------------------------------------------------------------- 1 | # 特点 2 | 3 | ## 总体 4 | 5 | * 跨平台 6 | * 编译器:Visual Studio、gcc、clang等 7 | * 架构:x86、x64、ARM等 8 | * 操作系统:Windows、Mac OS X、Linux、iOS、Android等 9 | * 容易安装 10 | * 只有头文件的库。只需把头文件复制至你的项目中。 11 | * 独立、最小依赖 12 | * 不需依赖STL、BOOST等。 13 | * 只包含``, ``, ``, ``, ``, ``。 14 | * 没使用C++异常、RTTI 15 | * 高性能 16 | * 使用模版及内联函数去降低函数调用开销。 17 | * 内部经优化的Grisu2及浮点数解析实现。 18 | * 可选的SSE2/SSE4.2支持。 19 | 20 | ## 符合标准 21 | 22 | * RapidJSON应完全符合RFC4627/ECMA-404标准。 23 | * 支持Unicod代理对(surrogate pair)。 24 | * 支持空字符(`"\u0000"`)。 25 | * 例如,可以优雅地解析及处理`["Hello\u0000World"]`。含读写字符串长度的API。 26 | 27 | ## Unicode 28 | 29 | * 支持UTF-8、UTF-16、UTF-32编码,包括小端序和大端序。 30 | * 这些编码用于输入输出流,以及内存中的表示。 31 | * 支持从输入流自动检测编码。 32 | * 内部支持编码的转换。 33 | * 例如,你可以读取一个UTF-8文件,让RapidJSON把JSON字符串转换至UTF-16的DOM。 34 | * 内部支持编码校验。 35 | * 例如,你可以读取一个UTF-8文件,让RapidJSON检查是否所有JSON字符串是合法的UTF-8字节序列。 36 | * 支持自定义的字符类型。 37 | * 预设的字符类型是:UTF-8为`char`,UTF-16为`wchar_t`,UTF32为`uint32_t`。 38 | * 支持自定义的编码。 39 | 40 | ## API风格 41 | 42 | * SAX(Simple API for XML)风格API 43 | * 类似于[SAX](http://en.wikipedia.org/wiki/Simple_API_for_XML), RapidJSON提供一个事件循序访问的解析器API(`rapidjson::GenericReader`)。RapidJSON也提供一个生成器API(`rapidjson::Writer`),可以处理相同的事件集合。 44 | * DOM(Document Object Model)风格API 45 | * 类似于HTML/XML的[DOM](http://en.wikipedia.org/wiki/Document_Object_Model),RapidJSON可把JSON解析至一个DOM表示方式(`rapidjson::GenericDocument`),以方便操作。如有需要,可把DOM转换(stringify)回JSON。 46 | * DOM风格API(`rapidjson::GenericDocument`)实际上是由SAX风格API(`rapidjson::GenericReader`)实现的。SAX更快,但有时DOM更易用。用户可根据情况作出选择。 47 | 48 | ## 解析 49 | 50 | * 递归式(预设)及迭代式解析器 51 | * 递归式解析器较快,但在极端情况下可出现堆栈溢出。 52 | * 迭代式解析器使用自定义的堆栈去维持解析状态。 53 | * 支持原位(*in situ*)解析。 54 | * 把JSON字符串的值解析至原JSON之中,然后让DOM指向那些字符串。 55 | * 比常规分析更快:不需字符串的内存分配、不需复制(如字符串不含转义符)、缓存友好。 56 | * 对于JSON数字类型,支持32-bit/64-bit的有号/无号整数,以及`double`。 57 | * 错误处理 58 | * 支持详尽的解析错误代号。 59 | * 支持本地化错误信息。 60 | 61 | ## DOM (Document) 62 | 63 | * RapidJSON在类型转换时会检查数值的范围。 64 | * 字符串字面量的优化 65 | * 只储存指针,不作复制 66 | * 优化“短”字符串 67 | * 在`Value`内储存短字符串,无需额外分配。 68 | * 对UTF-8字符串来说,32位架构下可存储最多11字符,64位下15字符。 69 | * 可选地支持`std::string`(定义`RAPIDJSON_HAS_STDSTRING=1`) 70 | 71 | ## 生成 72 | 73 | * 支持`rapidjson::PrettyWriter`去加入换行及缩进。 74 | 75 | ## 输入输出流 76 | 77 | * 支持`rapidjson::GenericStringBuffer`,把输出的JSON储存于字符串内。 78 | * 支持`rapidjson::FileReadStream`及`rapidjson::FileWriteStream`,使用`FILE`对象作输入输出。 79 | * 支持自定义输入输出流。 80 | 81 | ## 内存 82 | 83 | * 最小化DOM的内存开销。 84 | * 对大部分32/64位机器而言,每个JSON值只占16或20字节(不包含字符串)。 85 | * 支持快速的预设分配器。 86 | * 它是一个堆栈形式的分配器(顺序分配,不容许单独释放,适合解析过程之用)。 87 | * 使用者也可提供一个预分配的缓冲区。(有可能达至无需CRT分配就能解析多个JSON) 88 | * 支持标准CRT(C-runtime)分配器。 89 | * 支持自定义分配器。 90 | 91 | ## 其他 92 | 93 | * 一些C++11的支持(可选) 94 | * 右值引用(rvalue reference) 95 | * `noexcept`修饰符 96 | -------------------------------------------------------------------------------- /doc/logo/rapidjson.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TencentAPI/rapidjson_bk/1ef0f98f6a42212f11e461935cff1b8ea291cd88/doc/logo/rapidjson.png -------------------------------------------------------------------------------- /doc/logo/rapidjson.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 23 | 27 | 31 | 32 | 42 | 52 | 62 | 63 | 85 | 87 | 88 | 90 | image/svg+xml 91 | 93 | 94 | 95 | 96 | 97 | 102 | RapidJSON 118 | 119 | 120 | -------------------------------------------------------------------------------- /doc/misc/DoxygenLayout.xml: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /doc/misc/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /doc/misc/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | $projectname: $title 9 | $title 10 | 11 | 12 | 13 | $treeview 14 | $search 15 | $mathjax 16 | 17 | $extrastylesheet 18 | 19 | 20 |
21 |
22 | $searchbox 23 | 24 | 25 | -------------------------------------------------------------------------------- /doc/performance.md: -------------------------------------------------------------------------------- 1 | # Performance 2 | 3 | There is a [native JSON benchmark collection] [1] which evaluates speed, memory usage and code size of various operations among 20 JSON libaries. 4 | 5 | [1]: https://github.com/miloyip/nativejson-benchmark 6 | 7 | The old performance article for RapidJSON 0.1 is provided [here](https://code.google.com/p/rapidjson/wiki/Performance). 8 | 9 | Additionally, you may refer to the following third-party benchmarks. 10 | 11 | ## Third-party benchmarks 12 | 13 | * [Basic benchmarks for miscellaneous C++ JSON parsers and generators](https://github.com/mloskot/json_benchmark) by Mateusz Loskot (Jun 2013) 14 | * [casablanca](https://casablanca.codeplex.com/) 15 | * [json_spirit](https://github.com/cierelabs/json_spirit) 16 | * [jsoncpp](http://jsoncpp.sourceforge.net/) 17 | * [libjson](http://sourceforge.net/projects/libjson/) 18 | * [rapidjson](https://github.com/miloyip/rapidjson/) 19 | * [QJsonDocument](http://qt-project.org/doc/qt-5.0/qtcore/qjsondocument.html) 20 | 21 | * [JSON Parser Benchmarking](http://chadaustin.me/2013/01/json-parser-benchmarking/) by Chad Austin (Jan 2013) 22 | * [sajson](https://github.com/chadaustin/sajson) 23 | * [rapidjson](https://github.com/miloyip/rapidjson/) 24 | * [vjson](https://code.google.com/p/vjson/) 25 | * [YAJL](http://lloyd.github.com/yajl/) 26 | * [Jansson](http://www.digip.org/jansson/) 27 | -------------------------------------------------------------------------------- /doc/performance.zh-cn.md: -------------------------------------------------------------------------------- 1 | # 性能 2 | 3 | 有一个[native JSON benchmark collection][1]项目,能评估20个JSON库在不同操作下的速度、內存用量及代码大小。 4 | 5 | [1]: https://github.com/miloyip/nativejson-benchmark 6 | 7 | RapidJSON 0.1版本的性能测试文章位于[这里](https://code.google.com/p/rapidjson/wiki/Performance). 8 | 9 | 此外,你也可以参考以下这些第三方的评测。 10 | 11 | ## 第三方评测 12 | 13 | * [Basic benchmarks for miscellaneous C++ JSON parsers and generators](https://github.com/mloskot/json_benchmark) by Mateusz Loskot (Jun 2013) 14 | * [casablanca](https://casablanca.codeplex.com/) 15 | * [json_spirit](https://github.com/cierelabs/json_spirit) 16 | * [jsoncpp](http://jsoncpp.sourceforge.net/) 17 | * [libjson](http://sourceforge.net/projects/libjson/) 18 | * [rapidjson](https://github.com/miloyip/rapidjson/) 19 | * [QJsonDocument](http://qt-project.org/doc/qt-5.0/qtcore/qjsondocument.html) 20 | 21 | * [JSON Parser Benchmarking](http://chadaustin.me/2013/01/json-parser-benchmarking/) by Chad Austin (Jan 2013) 22 | * [sajson](https://github.com/chadaustin/sajson) 23 | * [rapidjson](https://github.com/miloyip/rapidjson/) 24 | * [vjson](https://code.google.com/p/vjson/) 25 | * [YAJL](http://lloyd.github.com/yajl/) 26 | * [Jansson](http://www.digip.org/jansson/) 27 | -------------------------------------------------------------------------------- /example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2011 Milo Yip (miloyip@gmail.com) 2 | # Copyright (c) 2013 Rafal Jeczalik (rjeczalik@gmail.com) 3 | # Distributed under the MIT License (see license.txt file) 4 | 5 | set(EXAMPLES 6 | capitalize 7 | condense 8 | messagereader 9 | pretty 10 | prettyauto 11 | serialize 12 | simpledom 13 | simplereader 14 | simplewriter 15 | tutorial) 16 | 17 | if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") 18 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default") 19 | elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") 20 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default") 21 | elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") 22 | add_definitions(-D_CRT_SECURE_NO_WARNINGS=1) 23 | endif() 24 | 25 | foreach (example ${EXAMPLES}) 26 | add_executable(${example} ${example}/${example}.cpp) 27 | endforeach() 28 | 29 | add_custom_target(examples ALL DEPENDS ${EXAMPLES}) 30 | -------------------------------------------------------------------------------- /example/capitalize/capitalize.cpp: -------------------------------------------------------------------------------- 1 | // JSON condenser example 2 | 3 | // This example parses JSON from stdin with validation, 4 | // and re-output the JSON content to stdout with all string capitalized, and without whitespace. 5 | 6 | #include "rapidjson/reader.h" 7 | #include "rapidjson/writer.h" 8 | #include "rapidjson/filereadstream.h" 9 | #include "rapidjson/filewritestream.h" 10 | #include "rapidjson/error/en.h" 11 | #include 12 | #include 13 | 14 | using namespace rapidjson; 15 | 16 | template 17 | struct CapitalizeFilter { 18 | CapitalizeFilter(OutputHandler& out) : out_(out), buffer_() {} 19 | 20 | bool Null() { return out_.Null(); } 21 | bool Bool(bool b) { return out_.Bool(b); } 22 | bool Int(int i) { return out_.Int(i); } 23 | bool Uint(unsigned u) { return out_.Uint(u); } 24 | bool Int64(int64_t i) { return out_.Int64(i); } 25 | bool Uint64(uint64_t u) { return out_.Uint64(u); } 26 | bool Double(double d) { return out_.Double(d); } 27 | bool String(const char* str, SizeType length, bool) { 28 | buffer_.clear(); 29 | for (SizeType i = 0; i < length; i++) 30 | buffer_.push_back(std::toupper(str[i])); 31 | return out_.String(&buffer_.front(), length, true); // true = output handler need to copy the string 32 | } 33 | bool StartObject() { return out_.StartObject(); } 34 | bool Key(const char* str, SizeType length, bool copy) { return String(str, length, copy); } 35 | bool EndObject(SizeType memberCount) { return out_.EndObject(memberCount); } 36 | bool StartArray() { return out_.StartArray(); } 37 | bool EndArray(SizeType elementCount) { return out_.EndArray(elementCount); } 38 | 39 | OutputHandler& out_; 40 | std::vector buffer_; 41 | 42 | private: 43 | CapitalizeFilter(const CapitalizeFilter&); 44 | CapitalizeFilter& operator=(const CapitalizeFilter&); 45 | }; 46 | 47 | int main(int, char*[]) { 48 | // Prepare JSON reader and input stream. 49 | Reader reader; 50 | char readBuffer[65536]; 51 | FileReadStream is(stdin, readBuffer, sizeof(readBuffer)); 52 | 53 | // Prepare JSON writer and output stream. 54 | char writeBuffer[65536]; 55 | FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer)); 56 | Writer writer(os); 57 | 58 | // JSON reader parse from the input stream and let writer generate the output. 59 | CapitalizeFilter > filter(writer); 60 | if (!reader.Parse(is, filter)) { 61 | fprintf(stderr, "\nError(%u): %s\n", (unsigned)reader.GetErrorOffset(), GetParseError_En(reader.GetParseErrorCode())); 62 | return 1; 63 | } 64 | 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /example/condense/condense.cpp: -------------------------------------------------------------------------------- 1 | // JSON condenser example 2 | 3 | // This example parses JSON text from stdin with validation, 4 | // and re-output the JSON content to stdout without whitespace. 5 | 6 | #include "rapidjson/reader.h" 7 | #include "rapidjson/writer.h" 8 | #include "rapidjson/filereadstream.h" 9 | #include "rapidjson/filewritestream.h" 10 | #include "rapidjson/error/en.h" 11 | 12 | using namespace rapidjson; 13 | 14 | int main(int, char*[]) { 15 | // Prepare JSON reader and input stream. 16 | Reader reader; 17 | char readBuffer[65536]; 18 | FileReadStream is(stdin, readBuffer, sizeof(readBuffer)); 19 | 20 | // Prepare JSON writer and output stream. 21 | char writeBuffer[65536]; 22 | FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer)); 23 | Writer writer(os); 24 | 25 | // JSON reader parse from the input stream and let writer generate the output. 26 | if (!reader.Parse(is, writer)) { 27 | fprintf(stderr, "\nError(%u): %s\n", (unsigned)reader.GetErrorOffset(), GetParseError_En(reader.GetParseErrorCode())); 28 | return 1; 29 | } 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /example/messagereader/messagereader.cpp: -------------------------------------------------------------------------------- 1 | // Reading a message JSON with Reader (SAX-style API). 2 | // The JSON should be an object with key-string pairs. 3 | 4 | #include "rapidjson/reader.h" 5 | #include "rapidjson/error/en.h" 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | using namespace rapidjson; 12 | 13 | typedef map MessageMap; 14 | 15 | #if defined(__GNUC__) 16 | RAPIDJSON_DIAG_PUSH 17 | RAPIDJSON_DIAG_OFF(effc++) 18 | #endif 19 | 20 | struct MessageHandler 21 | : public BaseReaderHandler, MessageHandler> { 22 | MessageHandler() : messages_(), state_(kExpectObjectStart), name_() {} 23 | 24 | bool StartObject() { 25 | switch (state_) { 26 | case kExpectObjectStart: 27 | state_ = kExpectNameOrObjectEnd; 28 | return true; 29 | default: 30 | return false; 31 | } 32 | } 33 | 34 | bool String(const char* str, SizeType length, bool) { 35 | switch (state_) { 36 | case kExpectNameOrObjectEnd: 37 | name_ = string(str, length); 38 | state_ = kExpectValue; 39 | return true; 40 | case kExpectValue: 41 | messages_.insert(MessageMap::value_type(name_, string(str, length))); 42 | state_ = kExpectNameOrObjectEnd; 43 | return true; 44 | default: 45 | return false; 46 | } 47 | } 48 | 49 | bool EndObject(SizeType) { return state_ == kExpectNameOrObjectEnd; } 50 | 51 | bool Default() { return false; } // All other events are invalid. 52 | 53 | MessageMap messages_; 54 | enum State { 55 | kExpectObjectStart, 56 | kExpectNameOrObjectEnd, 57 | kExpectValue 58 | }state_; 59 | std::string name_; 60 | }; 61 | 62 | #if defined(__GNUC__) 63 | RAPIDJSON_DIAG_POP 64 | #endif 65 | 66 | void ParseMessages(const char* json, MessageMap& messages) { 67 | Reader reader; 68 | MessageHandler handler; 69 | StringStream ss(json); 70 | if (reader.Parse(ss, handler)) 71 | messages.swap(handler.messages_); // Only change it if success. 72 | else { 73 | ParseErrorCode e = reader.GetParseErrorCode(); 74 | size_t o = reader.GetErrorOffset(); 75 | cout << "Error: " << GetParseError_En(e) << endl;; 76 | cout << " at offset " << o << " near '" << string(json).substr(o, 10) << "...'" << endl; 77 | } 78 | } 79 | 80 | int main() { 81 | MessageMap messages; 82 | 83 | const char* json1 = "{ \"greeting\" : \"Hello!\", \"farewell\" : \"bye-bye!\" }"; 84 | cout << json1 << endl; 85 | ParseMessages(json1, messages); 86 | 87 | for (MessageMap::const_iterator itr = messages.begin(); itr != messages.end(); ++itr) 88 | cout << itr->first << ": " << itr->second << endl; 89 | 90 | cout << endl << "Parse a JSON with invalid schema." << endl; 91 | const char* json2 = "{ \"greeting\" : \"Hello!\", \"farewell\" : \"bye-bye!\", \"foo\" : {} }"; 92 | cout << json2 << endl; 93 | ParseMessages(json2, messages); 94 | 95 | return 0; 96 | } 97 | -------------------------------------------------------------------------------- /example/pretty/pretty.cpp: -------------------------------------------------------------------------------- 1 | // JSON pretty formatting example 2 | // This example can only handle UTF-8. For handling other encodings, see prettyauto example. 3 | 4 | #include "rapidjson/reader.h" 5 | #include "rapidjson/prettywriter.h" 6 | #include "rapidjson/filereadstream.h" 7 | #include "rapidjson/filewritestream.h" 8 | #include "rapidjson/error/en.h" 9 | 10 | using namespace rapidjson; 11 | 12 | int main(int, char*[]) { 13 | // Prepare reader and input stream. 14 | Reader reader; 15 | char readBuffer[65536]; 16 | FileReadStream is(stdin, readBuffer, sizeof(readBuffer)); 17 | 18 | // Prepare writer and output stream. 19 | char writeBuffer[65536]; 20 | FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer)); 21 | PrettyWriter writer(os); 22 | 23 | // JSON reader parse from the input stream and let writer generate the output. 24 | if (!reader.Parse(is, writer)) { 25 | fprintf(stderr, "\nError(%u): %s\n", (unsigned)reader.GetErrorOffset(), GetParseError_En(reader.GetParseErrorCode())); 26 | return 1; 27 | } 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /example/prettyauto/prettyauto.cpp: -------------------------------------------------------------------------------- 1 | // JSON pretty formatting example 2 | // This example can handle UTF-8/UTF-16LE/UTF-16BE/UTF-32LE/UTF-32BE. 3 | // The input firstly convert to UTF8, and then write to the original encoding with pretty formatting. 4 | 5 | #include "rapidjson/reader.h" 6 | #include "rapidjson/prettywriter.h" 7 | #include "rapidjson/filereadstream.h" 8 | #include "rapidjson/filewritestream.h" 9 | #include "rapidjson/encodedstream.h" // NEW 10 | #include "rapidjson/error/en.h" 11 | #ifdef _WIN32 12 | #include 13 | #include 14 | #endif 15 | 16 | using namespace rapidjson; 17 | 18 | int main(int, char*[]) { 19 | #ifdef _WIN32 20 | // Prevent Windows converting between CR+LF and LF 21 | _setmode(_fileno(stdin), _O_BINARY); // NEW 22 | _setmode(_fileno(stdout), _O_BINARY); // NEW 23 | #endif 24 | 25 | // Prepare reader and input stream. 26 | //Reader reader; 27 | GenericReader, UTF8<> > reader; // CHANGED 28 | char readBuffer[65536]; 29 | FileReadStream is(stdin, readBuffer, sizeof(readBuffer)); 30 | AutoUTFInputStream eis(is); // NEW 31 | 32 | // Prepare writer and output stream. 33 | char writeBuffer[65536]; 34 | FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer)); 35 | 36 | #if 1 37 | // Use the same Encoding of the input. Also use BOM according to input. 38 | typedef AutoUTFOutputStream OutputStream; // NEW 39 | OutputStream eos(os, eis.GetType(), eis.HasBOM()); // NEW 40 | PrettyWriter, AutoUTF > writer(eos); // CHANGED 41 | #else 42 | // You may also use static bound encoding type, such as output to UTF-16LE with BOM 43 | typedef EncodedOutputStream,FileWriteStream> OutputStream; // NEW 44 | OutputStream eos(os, true); // NEW 45 | PrettyWriter, UTF16LE<> > writer(eos); // CHANGED 46 | #endif 47 | 48 | // JSON reader parse from the input stream and let writer generate the output. 49 | //if (!reader.Parse(is, writer)) { 50 | if (!reader.Parse(eis, writer)) { // CHANGED 51 | fprintf(stderr, "\nError(%u): %s\n", (unsigned)reader.GetErrorOffset(), GetParseError_En(reader.GetParseErrorCode())); 52 | return 1; 53 | } 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /example/serialize/serialize.cpp: -------------------------------------------------------------------------------- 1 | // Serialize example 2 | // This example shows writing JSON string with writer directly. 3 | 4 | #include "rapidjson/prettywriter.h" // for stringify JSON 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace rapidjson; 10 | 11 | class Person { 12 | public: 13 | Person(const std::string& name, unsigned age) : name_(name), age_(age) {} 14 | virtual ~Person(); 15 | 16 | protected: 17 | template 18 | void Serialize(Writer& writer) const { 19 | // This base class just write out name-value pairs, without wrapping within an object. 20 | writer.String("name"); 21 | #ifdef RAPIDJSON_HAS_STDSTRING 22 | writer.String(name_); 23 | #else 24 | writer.String(name_.c_str(), (SizeType)name_.length()); // Supplying length of string is faster. 25 | #endif 26 | writer.String("age"); 27 | writer.Uint(age_); 28 | } 29 | 30 | private: 31 | std::string name_; 32 | unsigned age_; 33 | }; 34 | 35 | Person::~Person() { 36 | } 37 | 38 | class Education { 39 | public: 40 | Education(const std::string& school, double GPA) : school_(school), GPA_(GPA) {} 41 | 42 | template 43 | void Serialize(Writer& writer) const { 44 | writer.StartObject(); 45 | 46 | writer.String("school"); 47 | #ifdef RAPIDJSON_HAS_STDSTRING 48 | writer.String(school_); 49 | #else 50 | writer.String(school_.c_str(), (SizeType)school_.length()); 51 | #endif 52 | 53 | writer.String("GPA"); 54 | writer.Double(GPA_); 55 | 56 | writer.EndObject(); 57 | } 58 | 59 | private: 60 | std::string school_; 61 | double GPA_; 62 | }; 63 | 64 | class Dependent : public Person { 65 | public: 66 | Dependent(const std::string& name, unsigned age, Education* education = 0) : Person(name, age), education_(education) {} 67 | Dependent(const Dependent& rhs) : Person(rhs), education_(0) { education_ = (rhs.education_ == 0) ? 0 : new Education(*rhs.education_); } 68 | virtual ~Dependent(); 69 | 70 | Dependent& operator=(const Dependent& rhs) { 71 | if (this == &rhs) 72 | return *this; 73 | delete education_; 74 | education_ = (rhs.education_ == 0) ? 0 : new Education(*rhs.education_); 75 | return *this; 76 | } 77 | 78 | template 79 | void Serialize(Writer& writer) const { 80 | writer.StartObject(); 81 | 82 | Person::Serialize(writer); 83 | 84 | writer.String("education"); 85 | if (education_) 86 | education_->Serialize(writer); 87 | else 88 | writer.Null(); 89 | 90 | writer.EndObject(); 91 | } 92 | 93 | private: 94 | 95 | Education *education_; 96 | }; 97 | 98 | Dependent::~Dependent() { 99 | delete education_; 100 | } 101 | 102 | class Employee : public Person { 103 | public: 104 | Employee(const std::string& name, unsigned age, bool married) : Person(name, age), dependents_(), married_(married) {} 105 | virtual ~Employee(); 106 | 107 | void AddDependent(const Dependent& dependent) { 108 | dependents_.push_back(dependent); 109 | } 110 | 111 | template 112 | void Serialize(Writer& writer) const { 113 | writer.StartObject(); 114 | 115 | Person::Serialize(writer); 116 | 117 | writer.String("married"); 118 | writer.Bool(married_); 119 | 120 | writer.String(("dependents")); 121 | writer.StartArray(); 122 | for (std::vector::const_iterator dependentItr = dependents_.begin(); dependentItr != dependents_.end(); ++dependentItr) 123 | dependentItr->Serialize(writer); 124 | writer.EndArray(); 125 | 126 | writer.EndObject(); 127 | } 128 | 129 | private: 130 | std::vector dependents_; 131 | bool married_; 132 | }; 133 | 134 | Employee::~Employee() { 135 | } 136 | 137 | int main(int, char*[]) { 138 | std::vector employees; 139 | 140 | employees.push_back(Employee("Milo YIP", 34, true)); 141 | employees.back().AddDependent(Dependent("Lua YIP", 3, new Education("Happy Kindergarten", 3.5))); 142 | employees.back().AddDependent(Dependent("Mio YIP", 1)); 143 | 144 | employees.push_back(Employee("Percy TSE", 30, false)); 145 | 146 | StringBuffer sb; 147 | PrettyWriter writer(sb); 148 | 149 | writer.StartArray(); 150 | for (std::vector::const_iterator employeeItr = employees.begin(); employeeItr != employees.end(); ++employeeItr) 151 | employeeItr->Serialize(writer); 152 | writer.EndArray(); 153 | 154 | puts(sb.GetString()); 155 | 156 | return 0; 157 | } 158 | -------------------------------------------------------------------------------- /example/simpledom/simpledom.cpp: -------------------------------------------------------------------------------- 1 | // JSON simple example 2 | // This example does not handle errors. 3 | 4 | #include "rapidjson/document.h" 5 | #include "rapidjson/writer.h" 6 | #include "rapidjson/stringbuffer.h" 7 | #include 8 | 9 | using namespace rapidjson; 10 | 11 | int main() { 12 | // 1. Parse a JSON string into DOM. 13 | const char* json = "{\"project\":\"rapidjson\",\"stars\":10}"; 14 | Document d; 15 | d.Parse(json); 16 | 17 | // 2. Modify it by DOM. 18 | Value& s = d["stars"]; 19 | s.SetInt(s.GetInt() + 1); 20 | 21 | // 3. Stringify the DOM 22 | StringBuffer buffer; 23 | Writer writer(buffer); 24 | d.Accept(writer); 25 | 26 | // Output {"project":"rapidjson","stars":11} 27 | std::cout << buffer.GetString() << std::endl; 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /example/simplereader/simplereader.cpp: -------------------------------------------------------------------------------- 1 | #include "rapidjson/reader.h" 2 | #include 3 | 4 | using namespace rapidjson; 5 | using namespace std; 6 | 7 | struct MyHandler { 8 | bool Null() { cout << "Null()" << endl; return true; } 9 | bool Bool(bool b) { cout << "Bool(" << boolalpha << b << ")" << endl; return true; } 10 | bool Int(int i) { cout << "Int(" << i << ")" << endl; return true; } 11 | bool Uint(unsigned u) { cout << "Uint(" << u << ")" << endl; return true; } 12 | bool Int64(int64_t i) { cout << "Int64(" << i << ")" << endl; return true; } 13 | bool Uint64(uint64_t u) { cout << "Uint64(" << u << ")" << endl; return true; } 14 | bool Double(double d) { cout << "Double(" << d << ")" << endl; return true; } 15 | bool String(const char* str, SizeType length, bool copy) { 16 | cout << "String(" << str << ", " << length << ", " << boolalpha << copy << ")" << endl; 17 | return true; 18 | } 19 | bool StartObject() { cout << "StartObject()" << endl; return true; } 20 | bool Key(const char* str, SizeType length, bool copy) { 21 | cout << "Key(" << str << ", " << length << ", " << boolalpha << copy << ")" << endl; 22 | return true; 23 | } 24 | bool EndObject(SizeType memberCount) { cout << "EndObject(" << memberCount << ")" << endl; return true; } 25 | bool StartArray() { cout << "StartArray()" << endl; return true; } 26 | bool EndArray(SizeType elementCount) { cout << "EndArray(" << elementCount << ")" << endl; return true; } 27 | }; 28 | 29 | int main() { 30 | const char json[] = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } "; 31 | 32 | MyHandler handler; 33 | Reader reader; 34 | StringStream ss(json); 35 | reader.Parse(ss, handler); 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /example/simplewriter/simplewriter.cpp: -------------------------------------------------------------------------------- 1 | #include "rapidjson/writer.h" 2 | #include "rapidjson/stringbuffer.h" 3 | #include 4 | 5 | using namespace rapidjson; 6 | using namespace std; 7 | 8 | int main() { 9 | StringBuffer s; 10 | Writer writer(s); 11 | 12 | writer.StartObject(); 13 | writer.String("hello"); 14 | writer.String("world"); 15 | writer.String("t"); 16 | writer.Bool(true); 17 | writer.String("f"); 18 | writer.Bool(false); 19 | writer.String("n"); 20 | writer.Null(); 21 | writer.String("i"); 22 | writer.Uint(123); 23 | writer.String("pi"); 24 | writer.Double(3.1416); 25 | writer.String("a"); 26 | writer.StartArray(); 27 | for (unsigned i = 0; i < 4; i++) 28 | writer.Uint(i); 29 | writer.EndArray(); 30 | writer.EndObject(); 31 | 32 | cout << s.GetString() << endl; 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /include/rapidjson/error/en.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_ERROR_EN_H__ 16 | #define RAPIDJSON_ERROR_EN_H__ 17 | 18 | #include "error.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | 22 | //! Maps error code of parsing into error message. 23 | /*! 24 | \ingroup RAPIDJSON_ERRORS 25 | \param parseErrorCode Error code obtained in parsing. 26 | \return the error message. 27 | \note User can make a copy of this function for localization. 28 | Using switch-case is safer for future modification of error codes. 29 | */ 30 | inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) { 31 | switch (parseErrorCode) { 32 | case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error."); 33 | 34 | case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty."); 35 | case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not follow by other values."); 36 | 37 | case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value."); 38 | 39 | case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member."); 40 | case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member."); 41 | case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member."); 42 | 43 | case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element."); 44 | 45 | case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string."); 46 | case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid."); 47 | case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string."); 48 | case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string."); 49 | case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string."); 50 | 51 | case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double."); 52 | case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number."); 53 | case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number."); 54 | 55 | case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error."); 56 | case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error."); 57 | 58 | default: 59 | return RAPIDJSON_ERROR_STRING("Unknown error."); 60 | } 61 | } 62 | 63 | RAPIDJSON_NAMESPACE_END 64 | 65 | #endif // RAPIDJSON_ERROR_EN_H__ 66 | -------------------------------------------------------------------------------- /include/rapidjson/error/error.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_ERROR_ERROR_H__ 16 | #define RAPIDJSON_ERROR_ERROR_H__ 17 | 18 | #include "../rapidjson.h" 19 | 20 | /*! \file error.h */ 21 | 22 | /*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */ 23 | 24 | /////////////////////////////////////////////////////////////////////////////// 25 | // RAPIDJSON_ERROR_CHARTYPE 26 | 27 | //! Character type of error messages. 28 | /*! \ingroup RAPIDJSON_ERRORS 29 | The default character type is \c char. 30 | On Windows, user can define this macro as \c TCHAR for supporting both 31 | unicode/non-unicode settings. 32 | */ 33 | #ifndef RAPIDJSON_ERROR_CHARTYPE 34 | #define RAPIDJSON_ERROR_CHARTYPE char 35 | #endif 36 | 37 | /////////////////////////////////////////////////////////////////////////////// 38 | // RAPIDJSON_ERROR_STRING 39 | 40 | //! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[]. 41 | /*! \ingroup RAPIDJSON_ERRORS 42 | By default this conversion macro does nothing. 43 | On Windows, user can define this macro as \c _T(x) for supporting both 44 | unicode/non-unicode settings. 45 | */ 46 | #ifndef RAPIDJSON_ERROR_STRING 47 | #define RAPIDJSON_ERROR_STRING(x) x 48 | #endif 49 | 50 | RAPIDJSON_NAMESPACE_BEGIN 51 | 52 | /////////////////////////////////////////////////////////////////////////////// 53 | // ParseErrorCode 54 | 55 | //! Error code of parsing. 56 | /*! \ingroup RAPIDJSON_ERRORS 57 | \see GenericReader::Parse, GenericReader::GetParseErrorCode 58 | */ 59 | enum ParseErrorCode { 60 | kParseErrorNone = 0, //!< No error. 61 | 62 | kParseErrorDocumentEmpty, //!< The document is empty. 63 | kParseErrorDocumentRootNotSingular, //!< The document root must not follow by other values. 64 | 65 | kParseErrorValueInvalid, //!< Invalid value. 66 | 67 | kParseErrorObjectMissName, //!< Missing a name for object member. 68 | kParseErrorObjectMissColon, //!< Missing a colon after a name of object member. 69 | kParseErrorObjectMissCommaOrCurlyBracket, //!< Missing a comma or '}' after an object member. 70 | 71 | kParseErrorArrayMissCommaOrSquareBracket, //!< Missing a comma or ']' after an array element. 72 | 73 | kParseErrorStringUnicodeEscapeInvalidHex, //!< Incorrect hex digit after \\u escape in string. 74 | kParseErrorStringUnicodeSurrogateInvalid, //!< The surrogate pair in string is invalid. 75 | kParseErrorStringEscapeInvalid, //!< Invalid escape character in string. 76 | kParseErrorStringMissQuotationMark, //!< Missing a closing quotation mark in string. 77 | kParseErrorStringInvalidEncoding, //!< Invalid encoding in string. 78 | 79 | kParseErrorNumberTooBig, //!< Number too big to be stored in double. 80 | kParseErrorNumberMissFraction, //!< Miss fraction part in number. 81 | kParseErrorNumberMissExponent, //!< Miss exponent in number. 82 | 83 | kParseErrorTermination, //!< Parsing was terminated. 84 | kParseErrorUnspecificSyntaxError //!< Unspecific syntax error. 85 | }; 86 | 87 | //! Result of parsing (wraps ParseErrorCode) 88 | /*! 89 | \ingroup RAPIDJSON_ERRORS 90 | \code 91 | Document doc; 92 | ParseResult ok = doc.Parse("[42]"); 93 | if (!ok) { 94 | fprintf(stderr, "JSON parse error: %s (%u)", 95 | GetParseError_En(ok.Code()), ok.Offset()); 96 | exit(EXIT_FAILURE); 97 | } 98 | \endcode 99 | \see GenericReader::Parse, GenericDocument::Parse 100 | */ 101 | struct ParseResult { 102 | 103 | //! Default constructor, no error. 104 | ParseResult() : code_(kParseErrorNone), offset_(0) {} 105 | //! Constructor to set an error. 106 | ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {} 107 | 108 | //! Get the error code. 109 | ParseErrorCode Code() const { return code_; } 110 | //! Get the error offset, if \ref IsError(), 0 otherwise. 111 | size_t Offset() const { return offset_; } 112 | 113 | //! Conversion to \c bool, returns \c true, iff !\ref IsError(). 114 | operator bool() const { return !IsError(); } 115 | //! Whether the result is an error. 116 | bool IsError() const { return code_ != kParseErrorNone; } 117 | 118 | bool operator==(const ParseResult& that) const { return code_ == that.code_; } 119 | bool operator==(ParseErrorCode code) const { return code_ == code; } 120 | friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; } 121 | 122 | //! Reset error code. 123 | void Clear() { Set(kParseErrorNone); } 124 | //! Update error code and offset. 125 | void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; } 126 | 127 | private: 128 | ParseErrorCode code_; 129 | size_t offset_; 130 | }; 131 | 132 | //! Function pointer type of GetParseError(). 133 | /*! \ingroup RAPIDJSON_ERRORS 134 | 135 | This is the prototype for \c GetParseError_X(), where \c X is a locale. 136 | User can dynamically change locale in runtime, e.g.: 137 | \code 138 | GetParseErrorFunc GetParseError = GetParseError_En; // or whatever 139 | const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode()); 140 | \endcode 141 | */ 142 | typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode); 143 | 144 | RAPIDJSON_NAMESPACE_END 145 | 146 | #endif // RAPIDJSON_ERROR_ERROR_H__ 147 | -------------------------------------------------------------------------------- /include/rapidjson/filereadstream.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_FILEREADSTREAM_H_ 16 | #define RAPIDJSON_FILEREADSTREAM_H_ 17 | 18 | #include "rapidjson.h" 19 | #include 20 | 21 | RAPIDJSON_NAMESPACE_BEGIN 22 | 23 | //! File byte stream for input using fread(). 24 | /*! 25 | \note implements Stream concept 26 | */ 27 | class FileReadStream { 28 | public: 29 | typedef char Ch; //!< Character type (byte). 30 | 31 | //! Constructor. 32 | /*! 33 | \param fp File pointer opened for read. 34 | \param buffer user-supplied buffer. 35 | \param bufferSize size of buffer in bytes. Must >=4 bytes. 36 | */ 37 | FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { 38 | RAPIDJSON_ASSERT(fp_ != 0); 39 | RAPIDJSON_ASSERT(bufferSize >= 4); 40 | Read(); 41 | } 42 | 43 | Ch Peek() const { return *current_; } 44 | Ch Take() { Ch c = *current_; Read(); return c; } 45 | size_t Tell() const { return count_ + static_cast(current_ - buffer_); } 46 | 47 | // Not implemented 48 | void Put(Ch) { RAPIDJSON_ASSERT(false); } 49 | void Flush() { RAPIDJSON_ASSERT(false); } 50 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 51 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } 52 | 53 | // For encoding detection only. 54 | const Ch* Peek4() const { 55 | return (current_ + 4 <= bufferLast_) ? current_ : 0; 56 | } 57 | 58 | private: 59 | void Read() { 60 | if (current_ < bufferLast_) 61 | ++current_; 62 | else if (!eof_) { 63 | count_ += readCount_; 64 | readCount_ = fread(buffer_, 1, bufferSize_, fp_); 65 | bufferLast_ = buffer_ + readCount_ - 1; 66 | current_ = buffer_; 67 | 68 | if (readCount_ < bufferSize_) { 69 | buffer_[readCount_] = '\0'; 70 | ++bufferLast_; 71 | eof_ = true; 72 | } 73 | } 74 | } 75 | 76 | std::FILE* fp_; 77 | Ch *buffer_; 78 | size_t bufferSize_; 79 | Ch *bufferLast_; 80 | Ch *current_; 81 | size_t readCount_; 82 | size_t count_; //!< Number of characters read 83 | bool eof_; 84 | }; 85 | 86 | RAPIDJSON_NAMESPACE_END 87 | 88 | #endif // RAPIDJSON_FILESTREAM_H_ 89 | -------------------------------------------------------------------------------- /include/rapidjson/filewritestream.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_FILEWRITESTREAM_H_ 16 | #define RAPIDJSON_FILEWRITESTREAM_H_ 17 | 18 | #include "rapidjson.h" 19 | #include 20 | 21 | RAPIDJSON_NAMESPACE_BEGIN 22 | 23 | //! Wrapper of C file stream for input using fread(). 24 | /*! 25 | \note implements Stream concept 26 | */ 27 | class FileWriteStream { 28 | public: 29 | typedef char Ch; //!< Character type. Only support char. 30 | 31 | FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) { 32 | RAPIDJSON_ASSERT(fp_ != 0); 33 | } 34 | 35 | void Put(char c) { 36 | if (current_ >= bufferEnd_) 37 | Flush(); 38 | 39 | *current_++ = c; 40 | } 41 | 42 | void PutN(char c, size_t n) { 43 | size_t avail = static_cast(bufferEnd_ - current_); 44 | while (n > avail) { 45 | std::memset(current_, c, avail); 46 | current_ += avail; 47 | Flush(); 48 | n -= avail; 49 | avail = static_cast(bufferEnd_ - current_); 50 | } 51 | 52 | if (n > 0) { 53 | std::memset(current_, c, n); 54 | current_ += n; 55 | } 56 | } 57 | 58 | void Flush() { 59 | if (current_ != buffer_) { 60 | fwrite(buffer_, 1, static_cast(current_ - buffer_), fp_); 61 | current_ = buffer_; 62 | } 63 | } 64 | 65 | // Not implemented 66 | char Peek() const { RAPIDJSON_ASSERT(false); return 0; } 67 | char Take() { RAPIDJSON_ASSERT(false); return 0; } 68 | size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } 69 | char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 70 | size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } 71 | 72 | private: 73 | // Prohibit copy constructor & assignment operator. 74 | FileWriteStream(const FileWriteStream&); 75 | FileWriteStream& operator=(const FileWriteStream&); 76 | 77 | std::FILE* fp_; 78 | char *buffer_; 79 | char *bufferEnd_; 80 | char *current_; 81 | }; 82 | 83 | //! Implement specialized version of PutN() with memset() for better performance. 84 | template<> 85 | inline void PutN(FileWriteStream& stream, char c, size_t n) { 86 | stream.PutN(c, n); 87 | } 88 | 89 | RAPIDJSON_NAMESPACE_END 90 | 91 | #endif // RAPIDJSON_FILESTREAM_H_ 92 | -------------------------------------------------------------------------------- /include/rapidjson/internal/ieee754.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_IEEE754_ 16 | #define RAPIDJSON_IEEE754_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | namespace internal { 22 | 23 | class Double { 24 | public: 25 | Double() {} 26 | Double(double d) : d(d) {} 27 | Double(uint64_t u) : u(u) {} 28 | 29 | double Value() const { return d; } 30 | uint64_t Uint64Value() const { return u; } 31 | 32 | double NextPositiveDouble() const { 33 | RAPIDJSON_ASSERT(!Sign()); 34 | return Double(u + 1).Value(); 35 | } 36 | 37 | bool Sign() const { return (u & kSignMask) != 0; } 38 | uint64_t Significand() const { return u & kSignificandMask; } 39 | int Exponent() const { return ((u & kExponentMask) >> kSignificandSize) - kExponentBias; } 40 | 41 | bool IsNan() const { return (u & kExponentMask) == kExponentMask && Significand() != 0; } 42 | bool IsInf() const { return (u & kExponentMask) == kExponentMask && Significand() == 0; } 43 | bool IsNormal() const { return (u & kExponentMask) != 0 || Significand() == 0; } 44 | bool IsZero() const { return (u & (kExponentMask | kSignificandMask)) == 0; } 45 | 46 | uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); } 47 | int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; } 48 | uint64_t ToBias() const { return (u & kSignMask) ? ~u + 1 : u | kSignMask; } 49 | 50 | static unsigned EffectiveSignificandSize(int order) { 51 | if (order >= -1021) 52 | return 53; 53 | else if (order <= -1074) 54 | return 0; 55 | else 56 | return order + 1074; 57 | } 58 | 59 | private: 60 | static const int kSignificandSize = 52; 61 | static const int kExponentBias = 0x3FF; 62 | static const int kDenormalExponent = 1 - kExponentBias; 63 | static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000); 64 | static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); 65 | static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); 66 | static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); 67 | 68 | union { 69 | double d; 70 | uint64_t u; 71 | }; 72 | }; 73 | 74 | } // namespace internal 75 | RAPIDJSON_NAMESPACE_END 76 | 77 | #endif // RAPIDJSON_IEEE754_ 78 | -------------------------------------------------------------------------------- /include/rapidjson/internal/pow10.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_POW10_ 16 | #define RAPIDJSON_POW10_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | namespace internal { 22 | 23 | //! Computes integer powers of 10 in double (10.0^n). 24 | /*! This function uses lookup table for fast and accurate results. 25 | \param n non-negative exponent. Must <= 308. 26 | \return 10.0^n 27 | */ 28 | inline double Pow10(int n) { 29 | static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes 30 | 1e+0, 31 | 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, 32 | 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40, 33 | 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60, 34 | 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80, 35 | 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100, 36 | 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120, 37 | 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140, 38 | 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160, 39 | 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180, 40 | 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200, 41 | 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220, 42 | 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240, 43 | 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260, 44 | 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280, 45 | 1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300, 46 | 1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308 47 | }; 48 | RAPIDJSON_ASSERT(n >= 0 && n <= 308); 49 | return e[n]; 50 | } 51 | 52 | } // namespace internal 53 | RAPIDJSON_NAMESPACE_END 54 | 55 | #endif // RAPIDJSON_POW10_ 56 | -------------------------------------------------------------------------------- /include/rapidjson/internal/stack.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_INTERNAL_STACK_H_ 16 | #define RAPIDJSON_INTERNAL_STACK_H_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | namespace internal { 22 | 23 | /////////////////////////////////////////////////////////////////////////////// 24 | // Stack 25 | 26 | //! A type-unsafe stack for storing different types of data. 27 | /*! \tparam Allocator Allocator for allocating stack memory. 28 | */ 29 | template 30 | class Stack { 31 | public: 32 | // Optimization note: Do not allocate memory for stack_ in constructor. 33 | // Do it lazily when first Push() -> Expand() -> Resize(). 34 | Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) { 35 | RAPIDJSON_ASSERT(stackCapacity > 0); 36 | } 37 | 38 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 39 | Stack(Stack&& rhs) 40 | : allocator_(rhs.allocator_), 41 | ownAllocator_(rhs.ownAllocator_), 42 | stack_(rhs.stack_), 43 | stackTop_(rhs.stackTop_), 44 | stackEnd_(rhs.stackEnd_), 45 | initialCapacity_(rhs.initialCapacity_) 46 | { 47 | rhs.allocator_ = 0; 48 | rhs.ownAllocator_ = 0; 49 | rhs.stack_ = 0; 50 | rhs.stackTop_ = 0; 51 | rhs.stackEnd_ = 0; 52 | rhs.initialCapacity_ = 0; 53 | } 54 | #endif 55 | 56 | ~Stack() { 57 | Destroy(); 58 | } 59 | 60 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 61 | Stack& operator=(Stack&& rhs) { 62 | if (&rhs != this) 63 | { 64 | Destroy(); 65 | 66 | allocator_ = rhs.allocator_; 67 | ownAllocator_ = rhs.ownAllocator_; 68 | stack_ = rhs.stack_; 69 | stackTop_ = rhs.stackTop_; 70 | stackEnd_ = rhs.stackEnd_; 71 | initialCapacity_ = rhs.initialCapacity_; 72 | 73 | rhs.allocator_ = 0; 74 | rhs.ownAllocator_ = 0; 75 | rhs.stack_ = 0; 76 | rhs.stackTop_ = 0; 77 | rhs.stackEnd_ = 0; 78 | rhs.initialCapacity_ = 0; 79 | } 80 | return *this; 81 | } 82 | #endif 83 | 84 | void Clear() { stackTop_ = stack_; } 85 | 86 | void ShrinkToFit() { 87 | if (Empty()) { 88 | // If the stack is empty, completely deallocate the memory. 89 | Allocator::Free(stack_); 90 | stack_ = 0; 91 | stackTop_ = 0; 92 | stackEnd_ = 0; 93 | } 94 | else 95 | Resize(GetSize()); 96 | } 97 | 98 | // Optimization note: try to minimize the size of this function for force inline. 99 | // Expansion is run very infrequently, so it is moved to another (probably non-inline) function. 100 | template 101 | RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) { 102 | // Expand the stack if needed 103 | if (stackTop_ + sizeof(T) * count >= stackEnd_) 104 | Expand(count); 105 | 106 | T* ret = reinterpret_cast(stackTop_); 107 | stackTop_ += sizeof(T) * count; 108 | return ret; 109 | } 110 | 111 | template 112 | T* Pop(size_t count) { 113 | RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); 114 | stackTop_ -= count * sizeof(T); 115 | return reinterpret_cast(stackTop_); 116 | } 117 | 118 | template 119 | T* Top() { 120 | RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); 121 | return reinterpret_cast(stackTop_ - sizeof(T)); 122 | } 123 | 124 | template 125 | T* Bottom() { return (T*)stack_; } 126 | 127 | Allocator& GetAllocator() { return *allocator_; } 128 | bool Empty() const { return stackTop_ == stack_; } 129 | size_t GetSize() const { return static_cast(stackTop_ - stack_); } 130 | size_t GetCapacity() const { return static_cast(stackEnd_ - stack_); } 131 | 132 | private: 133 | template 134 | void Expand(size_t count) { 135 | // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity. 136 | size_t newCapacity; 137 | if (stack_ == 0) { 138 | if (!allocator_) 139 | ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); 140 | newCapacity = initialCapacity_; 141 | } else { 142 | newCapacity = GetCapacity(); 143 | newCapacity += (newCapacity + 1) / 2; 144 | } 145 | size_t newSize = GetSize() + sizeof(T) * count; 146 | if (newCapacity < newSize) 147 | newCapacity = newSize; 148 | 149 | Resize(newCapacity); 150 | } 151 | 152 | void Resize(size_t newCapacity) { 153 | const size_t size = GetSize(); // Backup the current size 154 | stack_ = (char*)allocator_->Realloc(stack_, GetCapacity(), newCapacity); 155 | stackTop_ = stack_ + size; 156 | stackEnd_ = stack_ + newCapacity; 157 | } 158 | 159 | void Destroy() { 160 | Allocator::Free(stack_); 161 | RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack 162 | } 163 | 164 | // Prohibit copy constructor & assignment operator. 165 | Stack(const Stack&); 166 | Stack& operator=(const Stack&); 167 | 168 | Allocator* allocator_; 169 | Allocator* ownAllocator_; 170 | char *stack_; 171 | char *stackTop_; 172 | char *stackEnd_; 173 | size_t initialCapacity_; 174 | }; 175 | 176 | } // namespace internal 177 | RAPIDJSON_NAMESPACE_END 178 | 179 | #endif // RAPIDJSON_STACK_H_ 180 | -------------------------------------------------------------------------------- /include/rapidjson/internal/strfunc.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_INTERNAL_STRFUNC_H_ 16 | #define RAPIDJSON_INTERNAL_STRFUNC_H_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | namespace internal { 22 | 23 | //! Custom strlen() which works on different character types. 24 | /*! \tparam Ch Character type (e.g. char, wchar_t, short) 25 | \param s Null-terminated input string. 26 | \return Number of characters in the string. 27 | \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints. 28 | */ 29 | template 30 | inline SizeType StrLen(const Ch* s) { 31 | const Ch* p = s; 32 | while (*p) ++p; 33 | return SizeType(p - s); 34 | } 35 | 36 | } // namespace internal 37 | RAPIDJSON_NAMESPACE_END 38 | 39 | #endif // RAPIDJSON_INTERNAL_STRFUNC_H_ 40 | -------------------------------------------------------------------------------- /include/rapidjson/memorybuffer.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_MEMORYBUFFER_H_ 16 | #define RAPIDJSON_MEMORYBUFFER_H_ 17 | 18 | #include "rapidjson.h" 19 | #include "internal/stack.h" 20 | 21 | RAPIDJSON_NAMESPACE_BEGIN 22 | 23 | //! Represents an in-memory output byte stream. 24 | /*! 25 | This class is mainly for being wrapped by EncodedOutputStream or AutoUTFOutputStream. 26 | 27 | It is similar to FileWriteBuffer but the destination is an in-memory buffer instead of a file. 28 | 29 | Differences between MemoryBuffer and StringBuffer: 30 | 1. StringBuffer has Encoding but MemoryBuffer is only a byte buffer. 31 | 2. StringBuffer::GetString() returns a null-terminated string. MemoryBuffer::GetBuffer() returns a buffer without terminator. 32 | 33 | \tparam Allocator type for allocating memory buffer. 34 | \note implements Stream concept 35 | */ 36 | template 37 | struct GenericMemoryBuffer { 38 | typedef char Ch; // byte 39 | 40 | GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} 41 | 42 | void Put(Ch c) { *stack_.template Push() = c; } 43 | void Flush() {} 44 | 45 | void Clear() { stack_.Clear(); } 46 | void ShrinkToFit() { stack_.ShrinkToFit(); } 47 | Ch* Push(size_t count) { return stack_.template Push(count); } 48 | void Pop(size_t count) { stack_.template Pop(count); } 49 | 50 | const Ch* GetBuffer() const { 51 | return stack_.template Bottom(); 52 | } 53 | 54 | size_t GetSize() const { return stack_.GetSize(); } 55 | 56 | static const size_t kDefaultCapacity = 256; 57 | mutable internal::Stack stack_; 58 | }; 59 | 60 | typedef GenericMemoryBuffer<> MemoryBuffer; 61 | 62 | //! Implement specialized version of PutN() with memset() for better performance. 63 | template<> 64 | inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) { 65 | std::memset(memoryBuffer.stack_.Push(n), c, n * sizeof(c)); 66 | } 67 | 68 | RAPIDJSON_NAMESPACE_END 69 | 70 | #endif // RAPIDJSON_MEMORYBUFFER_H_ 71 | -------------------------------------------------------------------------------- /include/rapidjson/memorystream.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_MEMORYSTREAM_H_ 16 | #define RAPIDJSON_MEMORYSTREAM_H_ 17 | 18 | #include "rapidjson.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | 22 | //! Represents an in-memory input byte stream. 23 | /*! 24 | This class is mainly for being wrapped by EncodedInputStream or AutoUTFInputStream. 25 | 26 | It is similar to FileReadBuffer but the source is an in-memory buffer instead of a file. 27 | 28 | Differences between MemoryStream and StringStream: 29 | 1. StringStream has encoding but MemoryStream is a byte stream. 30 | 2. MemoryStream needs size of the source buffer and the buffer don't need to be null terminated. StringStream assume null-terminated string as source. 31 | 3. MemoryStream supports Peek4() for encoding detection. StringStream is specified with an encoding so it should not have Peek4(). 32 | \note implements Stream concept 33 | */ 34 | struct MemoryStream { 35 | typedef char Ch; // byte 36 | 37 | MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {} 38 | 39 | Ch Peek() const { return (src_ == end_) ? '\0' : *src_; } 40 | Ch Take() { return (src_ == end_) ? '\0' : *src_++; } 41 | size_t Tell() const { return static_cast(src_ - begin_); } 42 | 43 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 44 | void Put(Ch) { RAPIDJSON_ASSERT(false); } 45 | void Flush() { RAPIDJSON_ASSERT(false); } 46 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } 47 | 48 | // For encoding detection only. 49 | const Ch* Peek4() const { 50 | return Tell() + 4 <= size_ ? src_ : 0; 51 | } 52 | 53 | const Ch* src_; //!< Current read position. 54 | const Ch* begin_; //!< Original head of the string. 55 | const Ch* end_; //!< End of stream. 56 | size_t size_; //!< Size of the stream. 57 | }; 58 | 59 | RAPIDJSON_NAMESPACE_END 60 | 61 | #endif // RAPIDJSON_MEMORYBUFFER_H_ 62 | -------------------------------------------------------------------------------- /include/rapidjson/stringbuffer.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_STRINGBUFFER_H_ 16 | #define RAPIDJSON_STRINGBUFFER_H_ 17 | 18 | #include "rapidjson.h" 19 | 20 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 21 | #include // std::move 22 | #endif 23 | 24 | #include "internal/stack.h" 25 | 26 | RAPIDJSON_NAMESPACE_BEGIN 27 | 28 | //! Represents an in-memory output stream. 29 | /*! 30 | \tparam Encoding Encoding of the stream. 31 | \tparam Allocator type for allocating memory buffer. 32 | \note implements Stream concept 33 | */ 34 | template 35 | class GenericStringBuffer { 36 | public: 37 | typedef typename Encoding::Ch Ch; 38 | 39 | GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} 40 | 41 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 42 | GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {} 43 | GenericStringBuffer& operator=(GenericStringBuffer&& rhs) { 44 | if (&rhs != this) 45 | stack_ = std::move(rhs.stack_); 46 | return *this; 47 | } 48 | #endif 49 | 50 | void Put(Ch c) { *stack_.template Push() = c; } 51 | void Flush() {} 52 | 53 | void Clear() { stack_.Clear(); } 54 | void ShrinkToFit() { 55 | // Push and pop a null terminator. This is safe. 56 | *stack_.template Push() = '\0'; 57 | stack_.ShrinkToFit(); 58 | stack_.template Pop(1); 59 | } 60 | Ch* Push(size_t count) { return stack_.template Push(count); } 61 | void Pop(size_t count) { stack_.template Pop(count); } 62 | 63 | const Ch* GetString() const { 64 | // Push and pop a null terminator. This is safe. 65 | *stack_.template Push() = '\0'; 66 | stack_.template Pop(1); 67 | 68 | return stack_.template Bottom(); 69 | } 70 | 71 | size_t GetSize() const { return stack_.GetSize(); } 72 | 73 | static const size_t kDefaultCapacity = 256; 74 | mutable internal::Stack stack_; 75 | 76 | private: 77 | // Prohibit copy constructor & assignment operator. 78 | GenericStringBuffer(const GenericStringBuffer&); 79 | GenericStringBuffer& operator=(const GenericStringBuffer&); 80 | }; 81 | 82 | //! String buffer with UTF8 encoding 83 | typedef GenericStringBuffer > StringBuffer; 84 | 85 | //! Implement specialized version of PutN() with memset() for better performance. 86 | template<> 87 | inline void PutN(GenericStringBuffer >& stream, char c, size_t n) { 88 | std::memset(stream.stack_.Push(n), c, n * sizeof(c)); 89 | } 90 | 91 | RAPIDJSON_NAMESPACE_END 92 | 93 | #endif // RAPIDJSON_STRINGBUFFER_H_ 94 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Tencent is pleased to support the open source community by making RapidJSON available. 2 | 3 | Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | 5 | If you have downloaded a copy of the RapidJSON binary from Tencent, please note that the RapidJSON binary is licensed under the MIT License. 6 | If you have downloaded a copy of the RapidJSON source code from Tencent, please note that RapidJSON source code is licensed under the MIT License, except for the third-party components listed below which are subject to different license terms. Your integration of RapidJSON into your own projects may require compliance with the MIT License, as well as the other licenses applicable to the third-party components included within RapidJSON. 7 | A copy of the MIT License is included in this file. 8 | 9 | Other dependencies and licenses: 10 | 11 | Open Source Software Licensed Under the BSD License: 12 | -------------------------------------------------------------------- 13 | 14 | The msinttypes r29 15 | Copyright (c) 2006-2013 Alexander Chemeris 16 | All rights reserved. 17 | 18 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 19 | 20 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 21 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 22 | * Neither the name of copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | 26 | Open Source Software Licensed Under the JSON License: 27 | -------------------------------------------------------------------- 28 | 29 | json.org 30 | Copyright (c) 2002 JSON.org 31 | All Rights Reserved. 32 | 33 | JSON_checker 34 | Copyright (c) 2002 JSON.org 35 | All Rights Reserved. 36 | 37 | 38 | Terms of the JSON License: 39 | --------------------------------------------------- 40 | 41 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 42 | 43 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 44 | 45 | The Software shall be used for Good, not Evil. 46 | 47 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 48 | 49 | 50 | Terms of the MIT License: 51 | -------------------------------------------------------------------- 52 | 53 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 54 | 55 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 56 | 57 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 58 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ![](doc/logo/rapidjson.png) 2 | 3 | ![](https://img.shields.io/badge/release-v1.0.1-blue.png) 4 | 5 | ## A fast JSON parser/generator for C++ with both SAX/DOM style API 6 | 7 | Tencent is pleased to support the open source community by making RapidJSON available. 8 | 9 | Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 10 | 11 | * [RapidJSON GitHub](https://github.com/miloyip/rapidjson/) 12 | * RapidJSON Documentation 13 | * [English](http://miloyip.github.io/rapidjson/) 14 | * [简体中文](http://miloyip.github.io/rapidjson/zh-cn/) 15 | * [GitBook](https://www.gitbook.com/book/miloyip/rapidjson/) with downloadable PDF/EPUB/MOBI, without API reference. 16 | 17 | ## Build status 18 | 19 | | [Linux][lin-link] | [Windows][win-link] | [Coveralls][cov-link] | 20 | | :---------------: | :-----------------: | :-------------------: | 21 | | ![lin-badge] | ![win-badge] | ![cov-badge] | 22 | 23 | [lin-badge]: https://travis-ci.org/miloyip/rapidjson.png?branch=master "Travis build status" 24 | [lin-link]: https://travis-ci.org/miloyip/rapidjson "Travis build status" 25 | [win-badge]: https://ci.appveyor.com/api/projects/status/u658dcuwxo14a8m9/branch/master "AppVeyor build status" 26 | [win-link]: https://ci.appveyor.com/project/miloyip/rapidjson/branch/master "AppVeyor build status" 27 | [cov-badge]: https://coveralls.io/repos/miloyip/rapidjson/badge.png?branch=master 28 | [cov-link]: https://coveralls.io/r/miloyip/rapidjson?branch=master 29 | 30 | ## Introduction 31 | 32 | RapidJSON is a JSON parser and generator for C++. It was inspired by [RapidXml](http://rapidxml.sourceforge.net/). 33 | 34 | * RapidJSON is small but complete. It supports both SAX and DOM style API. The SAX parser is only a half thousand lines of code. 35 | 36 | * RapidJSON is fast. Its performance can be comparable to `strlen()`. It also optionally supports SSE2/SSE4.2 for acceleration. 37 | 38 | * RapidJSON is self-contained. It does not depend on external libraries such as BOOST. It even does not depend on STL. 39 | 40 | * RapidJSON is memory friendly. Each JSON value occupies exactly 16/20 bytes for most 32/64-bit machines (excluding text string). By default it uses a fast memory allocator, and the parser allocates memory compactly during parsing. 41 | 42 | * RapidJSON is Unicode friendly. It supports UTF-8, UTF-16, UTF-32 (LE & BE), and their detection, validation and transcoding internally. For example, you can read a UTF-8 file and let RapidJSON transcode the JSON strings into UTF-16 in the DOM. It also supports surrogates and "\u0000" (null character). 43 | 44 | More features can be read [here](doc/features.md). 45 | 46 | JSON(JavaScript Object Notation) is a light-weight data exchange format. RapidJSON should be in fully compliance with RFC7159/ECMA-404. More information about JSON can be obtained at 47 | * [Introducing JSON](http://json.org/) 48 | * [RFC7159: The JavaScript Object Notation (JSON) Data Interchange Format](http://www.ietf.org/rfc/rfc7159.txt) 49 | * [Standard ECMA-404: The JSON Data Interchange Format](http://www.ecma-international.org/publications/standards/Ecma-404.htm) 50 | 51 | ## Compatibility 52 | 53 | RapidJSON is cross-platform. Some platform/compiler combinations which have been tested are shown as follows. 54 | * Visual C++ 2008/2010/2013 on Windows (32/64-bit) 55 | * GNU C++ 3.8.x on Cygwin 56 | * Clang 3.4 on Mac OS X (32/64-bit) and iOS 57 | * Clang 3.4 on Android NDK 58 | 59 | Users can build and run the unit tests on their platform/compiler. 60 | 61 | ## Installation 62 | 63 | RapidJSON is a header-only C++ library. Just copy the `include/rapidjson` folder to system or project's include path. 64 | 65 | RapidJSON uses following software as its dependencies: 66 | * [CMake](http://www.cmake.org) as a general build tool 67 | * (optional)[Doxygen](http://www.doxygen.org) to build documentation 68 | * (optional)[googletest](https://code.google.com/p/googletest/) for unit and performance testing 69 | 70 | To generate user documentation and run tests please proceed with the steps below: 71 | 72 | 1. Execute `git submodule update --init` to get the files of thirdparty submodules (google test). 73 | 2. Create directory called `build` in rapidjson source directory. 74 | 3. Change to `build` directory and run `cmake ..` command to configure your build. Windows users can do the same with cmake-gui application. 75 | 4. On Windows, build the solution found in the build directory. On Linux, run `make` from the build directory. 76 | 77 | On successfull build you will find compiled test and example binaries in `bin` 78 | directory. The generated documentation will be available in `doc/html` 79 | directory of the build tree. To run tests after finished build please run `make 80 | test` or `ctest` from your build tree. You can get detailed output using `ctest 81 | -V` command. 82 | 83 | It is possible to install library system-wide by running `make install` command 84 | from the build tree with administrative privileges. This will install all files 85 | according to system preferences. Once RapidJSON is installed, it is possible 86 | to use it from other CMake projects by adding `find_package(RapidJSON)` line to 87 | your CMakeLists.txt. 88 | 89 | ## Usage at a glance 90 | 91 | This simple example parses a JSON string into a document (DOM), make a simple modification of the DOM, and finally stringify the DOM to a JSON string. 92 | 93 | ~~~~~~~~~~cpp 94 | // rapidjson/example/simpledom/simpledom.cpp` 95 | #include "rapidjson/document.h" 96 | #include "rapidjson/writer.h" 97 | #include "rapidjson/stringbuffer.h" 98 | #include 99 | 100 | using namespace rapidjson; 101 | 102 | int main() { 103 | // 1. Parse a JSON string into DOM. 104 | const char* json = "{\"project\":\"rapidjson\",\"stars\":10}"; 105 | Document d; 106 | d.Parse(json); 107 | 108 | // 2. Modify it by DOM. 109 | Value& s = d["stars"]; 110 | s.SetInt(s.GetInt() + 1); 111 | 112 | // 3. Stringify the DOM 113 | StringBuffer buffer; 114 | Writer writer(buffer); 115 | d.Accept(writer); 116 | 117 | // Output {"project":"rapidjson","stars":11} 118 | std::cout << buffer.GetString() << std::endl; 119 | return 0; 120 | } 121 | ~~~~~~~~~~ 122 | 123 | Note that this example did not handle potential errors. 124 | 125 | The following diagram shows the process. 126 | 127 | ![simpledom](doc/diagram/simpledom.png) 128 | 129 | More [examples](https://github.com/miloyip/rapidjson/tree/master/example) are available. 130 | -------------------------------------------------------------------------------- /readme.zh-cn.md: -------------------------------------------------------------------------------- 1 | ![](doc/logo/rapidjson.png) 2 | 3 | ![](https://img.shields.io/badge/release-v1.0.1-blue.png) 4 | 5 | ## 高效的C++ JSON解析/生成器,提供SAX及DOM风格API 6 | 7 | Tencent is pleased to support the open source community by making RapidJSON available. 8 | 9 | Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 10 | 11 | * [RapidJSON GitHub](https://github.com/miloyip/rapidjson/) 12 | * RapidJSON 文档 13 | * [English](http://miloyip.github.io/rapidjson/) 14 | * [简体中文](http://miloyip.github.io/rapidjson/zh-cn/) 15 | * [GitBook](https://www.gitbook.com/book/miloyip/rapidjson/)可下载PDF/EPUB/MOBI,但不含API参考手册。 16 | 17 | ## Build 状态 18 | 19 | | [Linux][lin-link] | [Windows][win-link] | [Coveralls][cov-link] | 20 | | :---------------: | :-----------------: | :-------------------: | 21 | | ![lin-badge] | ![win-badge] | ![cov-badge] | 22 | 23 | [lin-badge]: https://travis-ci.org/miloyip/rapidjson.png?branch=master "Travis build status" 24 | [lin-link]: https://travis-ci.org/miloyip/rapidjson "Travis build status" 25 | [win-badge]: https://ci.appveyor.com/api/projects/status/u658dcuwxo14a8m9/branch/master "AppVeyor build status" 26 | [win-link]: https://ci.appveyor.com/project/miloyip/rapidjson/branch/master "AppVeyor build status" 27 | [cov-badge]: https://coveralls.io/repos/miloyip/rapidjson/badge.png?branch=master 28 | [cov-link]: https://coveralls.io/r/miloyip/rapidjson?branch=master 29 | 30 | ## 简介 31 | 32 | RapidJSON是一个C++的JSON解析器及生成器。它的灵感来自[RapidXml](http://rapidxml.sourceforge.net/)。 33 | 34 | * RapidJSON小而全。它同时支持SAX和DOM风格的API。SAX解析器只有约500行代码。 35 | 36 | * RapidJSON快。它的性能可与`strlen()`相比。可支持SSE2/SSE4.2加速。 37 | 38 | * RapidJSON独立。它不依赖于BOOST等外部库。它甚至不依赖于STL。 39 | 40 | * RapidJSON对内存友好。在大部分32/64位机器上,每个JSON值只占16或20字节(除字符串外)。它预设使用一个快速的内存分配器,令分析器可以紧凑地分配内存。 41 | 42 | * RapidJSON对Unicode友好。它支持UTF-8、UTF-16、UTF-32 (大端序/小端序),并内部支持这些编码的检测、校验及转码。例如,RapidJSON可以在分析一个UTF-8文件至DOM时,把当中的JSON字符串转码至UTF-16。它也支持代理对(surrogate pair)及`"\u0000"`(空字符)。 43 | 44 | 在[这里](doc/features.md)可读取更多特点。 45 | 46 | JSON(JavaScript Object Notation)是一个轻量的数据交换格式。RapidJSON应该完全遵从RFC7159/ECMA-404。 关于JSON的更多信息可参考: 47 | * [Introducing JSON](http://json.org/) 48 | * [RFC7159: The JavaScript Object Notation (JSON) Data Interchange Format](http://www.ietf.org/rfc/rfc7159.txt) 49 | * [Standard ECMA-404: The JSON Data Interchange Format](http://www.ecma-international.org/publications/standards/Ecma-404.htm) 50 | 51 | ## 兼容性 52 | 53 | RapidJSON是跨平台的。以下是一些曾测试的平台/编译器组合: 54 | * Visual C++ 2008/2010/2013 在 Windows (32/64-bit) 55 | * GNU C++ 3.8.x 在 Cygwin 56 | * Clang 3.4 在 Mac OS X (32/64-bit) 及 iOS 57 | * Clang 3.4 在 Android NDK 58 | 59 | 用户也可以在他们的平台上生成及执行单元测试。 60 | 61 | ## 安装 62 | 63 | RapidJSON是只有头文件的C++库。只需把`include/rapidjson`目录复制至系统或项目的include目录中。 64 | 65 | RapidJSON依赖于以下软件: 66 | * [CMake](http://www.cmake.org) 作为通用生成工具 67 | * (optional)[Doxygen](http://www.doxygen.org)用于生成文档 68 | * (optional)[googletest](https://code.google.com/p/googletest/)用于单元及性能测试 69 | 70 | 生成测试及例子的步骤: 71 | 72 | 1. 执行 `git submodule update --init` 去获取 thirdparty submodules (google test)。 73 | 2. 在rapidjson目渌下,建立一个`build`目录。 74 | 3. 在`build`目录下执行`cmake ..`命令以设置生成。Windows用户可使用cmake-gui应用程序。 75 | 4. 在Windows下,编译生成在build目录中的solution。在Linux下,于build目录运行`make`。 76 | 77 | 成功生成后,你会在`bin`的目录下找到编译后的测试及例子可执行文件。而生成的文档将位于build下的`doc/html`目录。要执行测试,请在build下执行`make test`或`ctest`。使用`ctest -V`命令可获取详细的输出。 78 | 79 | 我们也可以把程序库安装至全系统中,只要在具管理權限下从build目录执行`make install`命令。这样会按系统的偏好设置安装所有文件。当安装RapidJSON后,其他的CMake项目需要使用它时,可以通过在`CMakeLists.txt`加入一句`find_package(RapidJSON)`。 80 | 81 | ## 用法一览 82 | 83 | 此简单例子解析一个JSON字符串至一个document (DOM),对DOM作出简单修改,最终把DOM转换(stringify)至JSON字符串。 84 | 85 | ~~~~~~~~~~cpp 86 | // rapidjson/example/simpledom/simpledom.cpp` 87 | #include "rapidjson/document.h" 88 | #include "rapidjson/writer.h" 89 | #include "rapidjson/stringbuffer.h" 90 | #include 91 | 92 | using namespace rapidjson; 93 | 94 | int main() { 95 | // 1. 把JSON解析至DOM。 96 | const char* json = "{\"project\":\"rapidjson\",\"stars\":10}"; 97 | Document d; 98 | d.Parse(json); 99 | 100 | // 2. 利用DOM作出修改。 101 | Value& s = d["stars"]; 102 | s.SetInt(s.GetInt() + 1); 103 | 104 | // 3. 把DOM转换(stringify)成JSON。 105 | StringBuffer buffer; 106 | Writer writer(buffer); 107 | d.Accept(writer); 108 | 109 | // Output {"project":"rapidjson","stars":11} 110 | std::cout << buffer.GetString() << std::endl; 111 | return 0; 112 | } 113 | ~~~~~~~~~~ 114 | 115 | 注意此例子并没有处理潜在错误。 116 | 117 | 下图展示执行过程。 118 | 119 | ![simpledom](doc/diagram/simpledom.png) 120 | 121 | 还有许多[例子](https://github.com/miloyip/rapidjson/tree/master/example)可供参考。 122 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(GTestSrc) 2 | 3 | IF(GTESTSRC_FOUND) 4 | enable_testing() 5 | 6 | if (WIN32 AND (NOT CYGWIN) AND (NOT MINGW)) 7 | set(gtest_disable_pthreads ON) 8 | set(gtest_force_shared_crt ON) 9 | endif() 10 | 11 | add_subdirectory(${GTEST_SOURCE_DIR} ${CMAKE_BINARY_DIR}/googletest) 12 | include_directories(${GTEST_INCLUDE_DIR}) 13 | 14 | set(TEST_LIBRARIES gtest gtest_main) 15 | 16 | add_custom_target(tests ALL) 17 | add_subdirectory(perftest) 18 | add_subdirectory(unittest) 19 | 20 | ENDIF(GTESTSRC_FOUND) 21 | -------------------------------------------------------------------------------- /test/perftest/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(PERFTEST_SOURCES 2 | misctest.cpp 3 | perftest.cpp 4 | platformtest.cpp 5 | rapidjsontest.cpp) 6 | 7 | add_executable(perftest ${PERFTEST_SOURCES}) 8 | target_link_libraries(perftest ${TEST_LIBRARIES}) 9 | 10 | add_dependencies(tests perftest) 11 | 12 | IF(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug")) 13 | add_test(NAME perftest 14 | COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/perftest 15 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) 16 | ENDIF() 17 | -------------------------------------------------------------------------------- /test/perftest/perftest.cpp: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #include "perftest.h" 16 | 17 | int main(int argc, char **argv) { 18 | #if _MSC_VER 19 | _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); 20 | //void *testWhetherMemoryLeakDetectionWorks = malloc(1); 21 | #endif 22 | ::testing::InitGoogleTest(&argc, argv); 23 | return RUN_ALL_TESTS(); 24 | } 25 | -------------------------------------------------------------------------------- /test/perftest/perftest.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef PERFTEST_H_ 16 | #define PERFTEST_H_ 17 | 18 | #define TEST_RAPIDJSON 1 19 | #define TEST_PLATFORM 0 20 | #define TEST_MISC 0 21 | 22 | #define TEST_VERSION_CODE(x,y,z) \ 23 | (((x)*100000) + ((y)*100) + (z)) 24 | 25 | // __SSE2__ and __SSE4_2__ are recognized by gcc, clang, and the Intel compiler. 26 | // We use -march=native with gmake to enable -msse2 and -msse4.2, if supported. 27 | #if defined(__SSE4_2__) 28 | # define RAPIDJSON_SSE42 29 | #elif defined(__SSE2__) 30 | # define RAPIDJSON_SSE2 31 | #endif 32 | 33 | //////////////////////////////////////////////////////////////////////////////// 34 | // Google Test 35 | 36 | #ifdef __cplusplus 37 | 38 | // gtest indirectly included inttypes.h, without __STDC_CONSTANT_MACROS. 39 | #ifndef __STDC_CONSTANT_MACROS 40 | # define __STDC_CONSTANT_MACROS 1 // required by C++ standard 41 | #endif 42 | 43 | #if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) 44 | #if defined(__clang__) || (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) 45 | #pragma GCC diagnostic push 46 | #endif 47 | #pragma GCC diagnostic ignored "-Weffc++" 48 | #endif 49 | 50 | #include "gtest/gtest.h" 51 | 52 | #if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) 53 | #pragma GCC diagnostic pop 54 | #endif 55 | 56 | #ifdef _MSC_VER 57 | #define _CRTDBG_MAP_ALLOC 58 | #include 59 | #pragma warning(disable : 4996) // 'function': was declared deprecated 60 | #endif 61 | 62 | //! Base class for all performance tests 63 | class PerfTest : public ::testing::Test { 64 | public: 65 | PerfTest() : filename_(), json_(), length_(), whitespace_(), whitespace_length_() {} 66 | 67 | virtual void SetUp() { 68 | 69 | const char *paths[] = { 70 | "data/sample.json", 71 | "bin/data/sample.json", 72 | "../bin/data/sample.json", 73 | "../../bin/data/sample.json", 74 | "../../../bin/data/sample.json" 75 | }; 76 | FILE *fp = 0; 77 | for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) { 78 | fp = fopen(filename_ = paths[i], "rb"); 79 | if (fp) 80 | break; 81 | } 82 | ASSERT_TRUE(fp != 0); 83 | 84 | fseek(fp, 0, SEEK_END); 85 | length_ = (size_t)ftell(fp); 86 | fseek(fp, 0, SEEK_SET); 87 | json_ = (char*)malloc(length_ + 1); 88 | ASSERT_EQ(length_, fread(json_, 1, length_, fp)); 89 | json_[length_] = '\0'; 90 | fclose(fp); 91 | 92 | // whitespace test 93 | whitespace_length_ = 1024 * 1024; 94 | whitespace_ = (char *)malloc(whitespace_length_ + 4); 95 | char *p = whitespace_; 96 | for (size_t i = 0; i < whitespace_length_; i += 4) { 97 | *p++ = ' '; 98 | *p++ = '\n'; 99 | *p++ = '\r'; 100 | *p++ = '\t'; 101 | } 102 | *p++ = '['; 103 | *p++ = '0'; 104 | *p++ = ']'; 105 | *p++ = '\0'; 106 | } 107 | 108 | virtual void TearDown() { 109 | free(json_); 110 | free(whitespace_); 111 | json_ = 0; 112 | whitespace_ = 0; 113 | } 114 | 115 | private: 116 | PerfTest(const PerfTest&); 117 | PerfTest& operator=(const PerfTest&); 118 | 119 | protected: 120 | const char* filename_; 121 | char *json_; 122 | size_t length_; 123 | char *whitespace_; 124 | size_t whitespace_length_; 125 | 126 | static const size_t kTrialCount = 1000; 127 | }; 128 | 129 | #endif // __cplusplus 130 | 131 | #endif // PERFTEST_H_ 132 | -------------------------------------------------------------------------------- /test/perftest/platformtest.cpp: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #include "perftest.h" 16 | 17 | // This file is for giving the performance characteristics of the platform (compiler/OS/CPU). 18 | 19 | #if TEST_PLATFORM 20 | 21 | #include 22 | #include 23 | 24 | // Windows 25 | #ifdef _WIN32 26 | #include 27 | #endif 28 | 29 | // UNIX 30 | #if defined(unix) || defined(__unix__) || defined(__unix) 31 | #include 32 | #ifdef _POSIX_MAPPED_FILES 33 | #include 34 | #endif 35 | #endif 36 | 37 | class Platform : public PerfTest { 38 | public: 39 | virtual void SetUp() { 40 | PerfTest::SetUp(); 41 | 42 | // temp buffer for testing 43 | temp_ = (char *)malloc(length_ + 1); 44 | memcpy(temp_, json_, length_); 45 | checkSum_ = CheckSum(); 46 | } 47 | 48 | char CheckSum() { 49 | char c = 0; 50 | for (size_t i = 0; i < length_; ++i) 51 | c += temp_[i]; 52 | return c; 53 | } 54 | 55 | virtual void TearDown() { 56 | PerfTest::TearDown(); 57 | free(temp_); 58 | } 59 | 60 | protected: 61 | char *temp_; 62 | char checkSum_; 63 | }; 64 | 65 | TEST_F(Platform, CheckSum) { 66 | for (int i = 0; i < kTrialCount; i++) 67 | EXPECT_EQ(checkSum_, CheckSum()); 68 | } 69 | 70 | TEST_F(Platform, strlen) { 71 | for (int i = 0; i < kTrialCount; i++) { 72 | size_t l = strlen(json_); 73 | EXPECT_EQ(length_, l); 74 | } 75 | } 76 | 77 | TEST_F(Platform, memcmp) { 78 | for (int i = 0; i < kTrialCount; i++) { 79 | EXPECT_EQ(0, memcmp(temp_, json_, length_)); 80 | } 81 | } 82 | 83 | TEST_F(Platform, pow) { 84 | double sum = 0; 85 | for (int i = 0; i < kTrialCount * kTrialCount; i++) 86 | sum += pow(10.0, i & 255); 87 | EXPECT_GT(sum, 0.0); 88 | } 89 | 90 | TEST_F(Platform, Whitespace_strlen) { 91 | for (int i = 0; i < kTrialCount; i++) { 92 | size_t l = strlen(whitespace_); 93 | EXPECT_GT(l, whitespace_length_); 94 | } 95 | } 96 | 97 | TEST_F(Platform, Whitespace_strspn) { 98 | for (int i = 0; i < kTrialCount; i++) { 99 | size_t l = strspn(whitespace_, " \n\r\t"); 100 | EXPECT_EQ(whitespace_length_, l); 101 | } 102 | } 103 | 104 | TEST_F(Platform, fread) { 105 | for (int i = 0; i < kTrialCount; i++) { 106 | FILE *fp = fopen(filename_, "rb"); 107 | ASSERT_EQ(length_, fread(temp_, 1, length_, fp)); 108 | EXPECT_EQ(checkSum_, CheckSum()); 109 | fclose(fp); 110 | } 111 | } 112 | 113 | #ifdef _MSC_VER 114 | TEST_F(Platform, read) { 115 | for (int i = 0; i < kTrialCount; i++) { 116 | int fd = _open(filename_, _O_BINARY | _O_RDONLY); 117 | ASSERT_NE(-1, fd); 118 | ASSERT_EQ(length_, _read(fd, temp_, length_)); 119 | EXPECT_EQ(checkSum_, CheckSum()); 120 | _close(fd); 121 | } 122 | } 123 | #else 124 | TEST_F(Platform, read) { 125 | for (int i = 0; i < kTrialCount; i++) { 126 | int fd = open(filename_, O_RDONLY); 127 | ASSERT_NE(-1, fd); 128 | ASSERT_EQ(length_, read(fd, temp_, length_)); 129 | EXPECT_EQ(checkSum_, CheckSum()); 130 | close(fd); 131 | } 132 | } 133 | #endif 134 | 135 | #ifdef _WIN32 136 | TEST_F(Platform, MapViewOfFile) { 137 | for (int i = 0; i < kTrialCount; i++) { 138 | HANDLE file = CreateFile(filename_, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 139 | ASSERT_NE(INVALID_HANDLE_VALUE, file); 140 | HANDLE mapObject = CreateFileMapping(file, NULL, PAGE_READONLY, 0, length_, NULL); 141 | ASSERT_NE(INVALID_HANDLE_VALUE, mapObject); 142 | void *p = MapViewOfFile(mapObject, FILE_MAP_READ, 0, 0, length_); 143 | ASSERT_TRUE(p != NULL); 144 | EXPECT_EQ(checkSum_, CheckSum()); 145 | ASSERT_TRUE(UnmapViewOfFile(p) == TRUE); 146 | ASSERT_TRUE(CloseHandle(mapObject) == TRUE); 147 | ASSERT_TRUE(CloseHandle(file) == TRUE); 148 | } 149 | } 150 | #endif 151 | 152 | #ifdef _POSIX_MAPPED_FILES 153 | TEST_F(Platform, mmap) { 154 | for (int i = 0; i < kTrialCount; i++) { 155 | int fd = open(filename_, O_RDONLY); 156 | ASSERT_NE(-1, fd); 157 | void *p = mmap(NULL, length_, PROT_READ, MAP_PRIVATE, fd, 0); 158 | ASSERT_TRUE(p != NULL); 159 | EXPECT_EQ(checkSum_, CheckSum()); 160 | munmap(p, length_); 161 | close(fd); 162 | } 163 | } 164 | #endif 165 | 166 | #endif // TEST_PLATFORM 167 | -------------------------------------------------------------------------------- /test/unittest/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(UNITTEST_SOURCES 2 | allocatorstest.cpp 3 | bigintegertest.cpp 4 | documenttest.cpp 5 | encodedstreamtest.cpp 6 | encodingstest.cpp 7 | filestreamtest.cpp 8 | itoatest.cpp 9 | jsoncheckertest.cpp 10 | namespacetest.cpp 11 | prettywritertest.cpp 12 | readertest.cpp 13 | simdtest.cpp 14 | stringbuffertest.cpp 15 | strtodtest.cpp 16 | unittest.cpp 17 | valuetest.cpp 18 | writertest.cpp) 19 | 20 | if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") 21 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default -Wfloat-equal") 22 | elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") 23 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default -Wfloat-equal") 24 | elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") 25 | add_definitions(-D_CRT_SECURE_NO_WARNINGS=1) 26 | endif() 27 | 28 | add_library(namespacetest STATIC namespacetest.cpp) 29 | 30 | add_executable(unittest ${UNITTEST_SOURCES}) 31 | target_link_libraries(unittest ${TEST_LIBRARIES} namespacetest) 32 | 33 | add_dependencies(tests unittest) 34 | 35 | add_test(NAME unittest 36 | COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittest 37 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) 38 | 39 | if(NOT MSVC) 40 | # Not running SIMD.* unit test cases for Valgrind 41 | add_test(NAME valgrind_unittest 42 | COMMAND valgrind --leak-check=full --error-exitcode=1 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittest --gtest_filter=-SIMD.* 43 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) 44 | 45 | if(CMAKE_BUILD_TYPE STREQUAL "Debug") 46 | add_test(NAME symbol_check 47 | COMMAND sh -c "objdump -t -C libnamespacetest.a | grep rapidjson ; test $? -ne 0" 48 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) 49 | endif(CMAKE_BUILD_TYPE STREQUAL "Debug") 50 | 51 | endif(NOT MSVC) 52 | -------------------------------------------------------------------------------- /test/unittest/allocatorstest.cpp: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #include "unittest.h" 16 | 17 | #include "rapidjson/allocators.h" 18 | 19 | using namespace rapidjson; 20 | 21 | template 22 | void TestAllocator(Allocator& a) { 23 | EXPECT_TRUE(a.Malloc(0) == 0); 24 | 25 | uint8_t* p = (uint8_t*)a.Malloc(100); 26 | EXPECT_TRUE(p != 0); 27 | for (size_t i = 0; i < 100; i++) 28 | p[i] = (uint8_t)i; 29 | 30 | // Expand 31 | uint8_t* q = (uint8_t*)a.Realloc(p, 100, 200); 32 | EXPECT_TRUE(q != 0); 33 | for (size_t i = 0; i < 100; i++) 34 | EXPECT_EQ(i, q[i]); 35 | for (size_t i = 100; i < 200; i++) 36 | q[i] = (uint8_t)i; 37 | 38 | // Shrink 39 | uint8_t *r = (uint8_t*)a.Realloc(q, 200, 150); 40 | EXPECT_TRUE(r != 0); 41 | for (size_t i = 0; i < 150; i++) 42 | EXPECT_EQ(i, r[i]); 43 | 44 | Allocator::Free(r); 45 | } 46 | 47 | TEST(Allocator, CrtAllocator) { 48 | CrtAllocator a; 49 | TestAllocator(a); 50 | } 51 | 52 | TEST(Allocator, MemoryPoolAllocator) { 53 | MemoryPoolAllocator<> a; 54 | TestAllocator(a); 55 | 56 | for (int i = 1; i < 1000; i++) { 57 | EXPECT_TRUE(a.Malloc(i) != 0); 58 | EXPECT_LE(a.Size(), a.Capacity()); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /test/unittest/bigintegertest.cpp: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #include "unittest.h" 16 | 17 | #include "rapidjson/internal/biginteger.h" 18 | 19 | using namespace rapidjson::internal; 20 | 21 | #define BIGINTEGER_LITERAL(s) BigInteger(s, sizeof(s) - 1) 22 | 23 | static const BigInteger kZero(0); 24 | static const BigInteger kOne(1); 25 | static const BigInteger kUint64Max = BIGINTEGER_LITERAL("18446744073709551615"); 26 | static const BigInteger kTwo64 = BIGINTEGER_LITERAL("18446744073709551616"); 27 | 28 | TEST(BigInteger, Constructor) { 29 | EXPECT_TRUE(kZero.IsZero()); 30 | EXPECT_TRUE(kZero == kZero); 31 | EXPECT_TRUE(kZero == BIGINTEGER_LITERAL("0")); 32 | EXPECT_TRUE(kZero == BIGINTEGER_LITERAL("00")); 33 | 34 | const BigInteger a(123); 35 | EXPECT_TRUE(a == a); 36 | EXPECT_TRUE(a == BIGINTEGER_LITERAL("123")); 37 | EXPECT_TRUE(a == BIGINTEGER_LITERAL("0123")); 38 | 39 | EXPECT_EQ(2u, kTwo64.GetCount()); 40 | EXPECT_EQ(0u, kTwo64.GetDigit(0)); 41 | EXPECT_EQ(1u, kTwo64.GetDigit(1)); 42 | } 43 | 44 | TEST(BigInteger, AddUint64) { 45 | BigInteger a = kZero; 46 | a += 0u; 47 | EXPECT_TRUE(kZero == a); 48 | 49 | a += 1u; 50 | EXPECT_TRUE(kOne == a); 51 | 52 | a += 1u; 53 | EXPECT_TRUE(BigInteger(2) == a); 54 | 55 | EXPECT_TRUE(BigInteger(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFFF)) == kUint64Max); 56 | BigInteger b = kUint64Max; 57 | b += 1u; 58 | EXPECT_TRUE(kTwo64 == b); 59 | b += RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFFF); 60 | EXPECT_TRUE(BIGINTEGER_LITERAL("36893488147419103231") == b); 61 | } 62 | 63 | TEST(BigInteger, MultiplyUint64) { 64 | BigInteger a = kZero; 65 | a *= static_cast (0); 66 | EXPECT_TRUE(kZero == a); 67 | a *= static_cast (123); 68 | EXPECT_TRUE(kZero == a); 69 | 70 | BigInteger b = kOne; 71 | b *= static_cast(1); 72 | EXPECT_TRUE(kOne == b); 73 | b *= static_cast(0); 74 | EXPECT_TRUE(kZero == b); 75 | 76 | BigInteger c(123); 77 | c *= static_cast(456u); 78 | EXPECT_TRUE(BigInteger(123u * 456u) == c); 79 | c *= RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFFF); 80 | EXPECT_TRUE(BIGINTEGER_LITERAL("1034640981606221330982120") == c); 81 | c *= RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFFF); 82 | EXPECT_TRUE(BIGINTEGER_LITERAL("19085757395861596536664473018420572782123800") == c); 83 | } 84 | 85 | TEST(BigInteger, MultiplyUint32) { 86 | BigInteger a = kZero; 87 | a *= static_cast (0); 88 | EXPECT_TRUE(kZero == a); 89 | a *= static_cast (123); 90 | EXPECT_TRUE(kZero == a); 91 | 92 | BigInteger b = kOne; 93 | b *= static_cast(1); 94 | EXPECT_TRUE(kOne == b); 95 | b *= static_cast(0); 96 | EXPECT_TRUE(kZero == b); 97 | 98 | BigInteger c(123); 99 | c *= static_cast(456u); 100 | EXPECT_TRUE(BigInteger(123u * 456u) == c); 101 | c *= 0xFFFFFFFFu; 102 | EXPECT_TRUE(BIGINTEGER_LITERAL("240896125641960") == c); 103 | c *= 0xFFFFFFFFu; 104 | EXPECT_TRUE(BIGINTEGER_LITERAL("1034640981124429079698200") == c); 105 | } 106 | 107 | TEST(BigInteger, LeftShift) { 108 | BigInteger a = kZero; 109 | a <<= 1; 110 | EXPECT_TRUE(kZero == a); 111 | a <<= 64; 112 | EXPECT_TRUE(kZero == a); 113 | 114 | a = BigInteger(123); 115 | a <<= 0; 116 | EXPECT_TRUE(BigInteger(123) == a); 117 | a <<= 1; 118 | EXPECT_TRUE(BigInteger(246) == a); 119 | a <<= 64; 120 | EXPECT_TRUE(BIGINTEGER_LITERAL("4537899042132549697536") == a); 121 | a <<= 99; 122 | EXPECT_TRUE(BIGINTEGER_LITERAL("2876235222267216943024851750785644982682875244576768") == a); 123 | } 124 | 125 | TEST(BigInteger, Compare) { 126 | EXPECT_EQ(0, kZero.Compare(kZero)); 127 | EXPECT_EQ(1, kOne.Compare(kZero)); 128 | EXPECT_EQ(-1, kZero.Compare(kOne)); 129 | EXPECT_EQ(0, kUint64Max.Compare(kUint64Max)); 130 | EXPECT_EQ(0, kTwo64.Compare(kTwo64)); 131 | EXPECT_EQ(-1, kUint64Max.Compare(kTwo64)); 132 | EXPECT_EQ(1, kTwo64.Compare(kUint64Max)); 133 | } 134 | -------------------------------------------------------------------------------- /test/unittest/filestreamtest.cpp: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #include "unittest.h" 16 | #include "rapidjson/filereadstream.h" 17 | #include "rapidjson/filewritestream.h" 18 | #include "rapidjson/encodedstream.h" 19 | 20 | using namespace rapidjson; 21 | 22 | class FileStreamTest : public ::testing::Test { 23 | public: 24 | FileStreamTest() : filename_(), json_(), length_() {} 25 | 26 | virtual void SetUp() { 27 | const char *paths[] = { 28 | "data/sample.json", 29 | "bin/data/sample.json", 30 | "../bin/data/sample.json", 31 | "../../bin/data/sample.json", 32 | "../../../bin/data/sample.json" 33 | }; 34 | FILE* fp = 0; 35 | for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) { 36 | fp = fopen(paths[i], "rb"); 37 | if (fp) { 38 | filename_ = paths[i]; 39 | break; 40 | } 41 | } 42 | ASSERT_TRUE(fp != 0); 43 | 44 | fseek(fp, 0, SEEK_END); 45 | length_ = (size_t)ftell(fp); 46 | fseek(fp, 0, SEEK_SET); 47 | json_ = (char*)malloc(length_ + 1); 48 | size_t readLength = fread(json_, 1, length_, fp); 49 | json_[readLength] = '\0'; 50 | fclose(fp); 51 | } 52 | 53 | virtual void TearDown() { 54 | free(json_); 55 | json_ = 0; 56 | } 57 | 58 | private: 59 | FileStreamTest(const FileStreamTest&); 60 | FileStreamTest& operator=(const FileStreamTest&); 61 | 62 | protected: 63 | const char* filename_; 64 | char *json_; 65 | size_t length_; 66 | }; 67 | 68 | TEST_F(FileStreamTest, FileReadStream) { 69 | FILE *fp = fopen(filename_, "rb"); 70 | ASSERT_TRUE(fp != 0); 71 | char buffer[65536]; 72 | FileReadStream s(fp, buffer, sizeof(buffer)); 73 | 74 | for (size_t i = 0; i < length_; i++) { 75 | EXPECT_EQ(json_[i], s.Peek()); 76 | EXPECT_EQ(json_[i], s.Peek()); // 2nd time should be the same 77 | EXPECT_EQ(json_[i], s.Take()); 78 | } 79 | 80 | EXPECT_EQ(length_, s.Tell()); 81 | EXPECT_EQ('\0', s.Peek()); 82 | 83 | fclose(fp); 84 | } 85 | 86 | TEST_F(FileStreamTest, FileWriteStream) { 87 | char filename[L_tmpnam]; 88 | FILE* fp = TempFile(filename); 89 | 90 | char buffer[65536]; 91 | FileWriteStream os(fp, buffer, sizeof(buffer)); 92 | for (size_t i = 0; i < length_; i++) 93 | os.Put(json_[i]); 94 | os.Flush(); 95 | fclose(fp); 96 | 97 | // Read it back to verify 98 | fp = fopen(filename, "rb"); 99 | FileReadStream is(fp, buffer, sizeof(buffer)); 100 | 101 | for (size_t i = 0; i < length_; i++) 102 | EXPECT_EQ(json_[i], is.Take()); 103 | 104 | EXPECT_EQ(length_, is.Tell()); 105 | fclose(fp); 106 | 107 | //std::cout << filename << std::endl; 108 | remove(filename); 109 | } 110 | -------------------------------------------------------------------------------- /test/unittest/itoatest.cpp: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #include "unittest.h" 16 | #include "rapidjson/internal/itoa.h" 17 | 18 | #ifdef __GNUC__ 19 | RAPIDJSON_DIAG_PUSH 20 | RAPIDJSON_DIAG_OFF(type-limits) 21 | #endif 22 | 23 | using namespace rapidjson::internal; 24 | 25 | template 26 | struct Traits { 27 | }; 28 | 29 | template <> 30 | struct Traits { 31 | enum { kBufferSize = 11 }; 32 | enum { kMaxDigit = 10 }; 33 | static uint32_t Negate(uint32_t x) { return x; }; 34 | }; 35 | 36 | template <> 37 | struct Traits { 38 | enum { kBufferSize = 12 }; 39 | enum { kMaxDigit = 10 }; 40 | static int32_t Negate(int32_t x) { return -x; }; 41 | }; 42 | 43 | template <> 44 | struct Traits { 45 | enum { kBufferSize = 21 }; 46 | enum { kMaxDigit = 20 }; 47 | static uint64_t Negate(uint64_t x) { return x; }; 48 | }; 49 | 50 | template <> 51 | struct Traits { 52 | enum { kBufferSize = 22 }; 53 | enum { kMaxDigit = 20 }; 54 | static int64_t Negate(int64_t x) { return -x; }; 55 | }; 56 | 57 | template 58 | static void VerifyValue(T value, void(*f)(T, char*), char* (*g)(T, char*)) { 59 | char buffer1[Traits::kBufferSize]; 60 | char buffer2[Traits::kBufferSize]; 61 | 62 | f(value, buffer1); 63 | *g(value, buffer2) = '\0'; 64 | 65 | 66 | EXPECT_STREQ(buffer1, buffer2); 67 | } 68 | 69 | template 70 | static void Verify(void(*f)(T, char*), char* (*g)(T, char*)) { 71 | // Boundary cases 72 | VerifyValue(0, f, g); 73 | VerifyValue(std::numeric_limits::min(), f, g); 74 | VerifyValue(std::numeric_limits::max(), f, g); 75 | 76 | // 2^n - 1, 2^n, 10^n - 1, 10^n until overflow 77 | for (uint32_t power = 2; power <= 10; power += 8) { 78 | T i = 1, last; 79 | do { 80 | VerifyValue(i - 1, f, g); 81 | VerifyValue(i, f, g); 82 | if (std::numeric_limits::min() < 0) { 83 | VerifyValue(Traits::Negate(i), f, g); 84 | VerifyValue(Traits::Negate(i + 1), f, g); 85 | } 86 | last = i; 87 | i *= power; 88 | } while (last < i); 89 | } 90 | } 91 | 92 | static void u32toa_naive(uint32_t value, char* buffer) { 93 | char temp[10]; 94 | char *p = temp; 95 | do { 96 | *p++ = char(value % 10) + '0'; 97 | value /= 10; 98 | } while (value > 0); 99 | 100 | do { 101 | *buffer++ = *--p; 102 | } while (p != temp); 103 | 104 | *buffer = '\0'; 105 | } 106 | 107 | static void i32toa_naive(int32_t value, char* buffer) { 108 | uint32_t u = static_cast(value); 109 | if (value < 0) { 110 | *buffer++ = '-'; 111 | u = ~u + 1; 112 | } 113 | u32toa_naive(u, buffer); 114 | } 115 | 116 | static void u64toa_naive(uint64_t value, char* buffer) { 117 | char temp[20]; 118 | char *p = temp; 119 | do { 120 | *p++ = char(value % 10) + '0'; 121 | value /= 10; 122 | } while (value > 0); 123 | 124 | do { 125 | *buffer++ = *--p; 126 | } while (p != temp); 127 | 128 | *buffer = '\0'; 129 | } 130 | 131 | static void i64toa_naive(int64_t value, char* buffer) { 132 | uint64_t u = static_cast(value); 133 | if (value < 0) { 134 | *buffer++ = '-'; 135 | u = ~u + 1; 136 | } 137 | u64toa_naive(u, buffer); 138 | } 139 | 140 | TEST(itoa, u32toa) { 141 | Verify(u32toa_naive, u32toa); 142 | } 143 | 144 | TEST(itoa, i32toa) { 145 | Verify(i32toa_naive, i32toa); 146 | } 147 | 148 | TEST(itoa, u64toa) { 149 | Verify(u64toa_naive, u64toa); 150 | } 151 | 152 | TEST(itoa, i64toa) { 153 | Verify(i64toa_naive, i64toa); 154 | } 155 | 156 | #ifdef __GNUC__ 157 | RAPIDJSON_DIAG_POP 158 | #endif 159 | -------------------------------------------------------------------------------- /test/unittest/jsoncheckertest.cpp: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #include "unittest.h" 16 | 17 | #include "rapidjson/document.h" 18 | 19 | using namespace rapidjson; 20 | 21 | static char* ReadFile(const char* filename, size_t& length) { 22 | const char *paths[] = { 23 | "jsonchecker/%s", 24 | "bin/jsonchecker/%s", 25 | "../bin/jsonchecker/%s", 26 | "../../bin/jsonchecker/%s", 27 | "../../../bin/jsonchecker/%s" 28 | }; 29 | char buffer[1024]; 30 | FILE *fp = 0; 31 | for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) { 32 | sprintf(buffer, paths[i], filename); 33 | fp = fopen(buffer, "rb"); 34 | if (fp) 35 | break; 36 | } 37 | 38 | if (!fp) 39 | return 0; 40 | 41 | fseek(fp, 0, SEEK_END); 42 | length = (size_t)ftell(fp); 43 | fseek(fp, 0, SEEK_SET); 44 | char* json = (char*)malloc(length + 1); 45 | size_t readLength = fread(json, 1, length, fp); 46 | json[readLength] = '\0'; 47 | fclose(fp); 48 | return json; 49 | } 50 | 51 | TEST(JsonChecker, Reader) { 52 | char filename[256]; 53 | 54 | // jsonchecker/failXX.json 55 | for (int i = 1; i <= 33; i++) { 56 | if (i == 1) // fail1.json is valid in rapidjson, which has no limitation on type of root element (RFC 7159). 57 | continue; 58 | if (i == 18) // fail18.json is valid in rapidjson, which has no limitation on depth of nesting. 59 | continue; 60 | 61 | sprintf(filename, "fail%d.json", i); 62 | size_t length; 63 | char* json = ReadFile(filename, length); 64 | if (!json) { 65 | printf("jsonchecker file %s not found", filename); 66 | ADD_FAILURE(); 67 | continue; 68 | } 69 | 70 | GenericDocument, CrtAllocator> document; // Use Crt allocator to check exception-safety (no memory leak) 71 | document.Parse((const char*)json); 72 | EXPECT_TRUE(document.HasParseError()); 73 | 74 | document.Parse((const char*)json); 75 | EXPECT_TRUE(document.HasParseError()); 76 | 77 | free(json); 78 | } 79 | 80 | // passX.json 81 | for (int i = 1; i <= 3; i++) { 82 | sprintf(filename, "pass%d.json", i); 83 | size_t length; 84 | char* json = ReadFile(filename, length); 85 | if (!json) { 86 | printf("jsonchecker file %s not found", filename); 87 | continue; 88 | } 89 | 90 | GenericDocument, CrtAllocator> document; // Use Crt allocator to check exception-safety (no memory leak) 91 | document.Parse((const char*)json); 92 | EXPECT_FALSE(document.HasParseError()); 93 | 94 | document.Parse((const char*)json); 95 | EXPECT_FALSE(document.HasParseError()); 96 | 97 | free(json); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /test/unittest/namespacetest.cpp: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #include "unittest.h" 16 | 17 | // test another instantiation of RapidJSON in a different namespace 18 | 19 | #define RAPIDJSON_NAMESPACE my::rapid::json 20 | #define RAPIDJSON_NAMESPACE_BEGIN namespace my { namespace rapid { namespace json { 21 | #define RAPIDJSON_NAMESPACE_END } } } 22 | 23 | // include lots of RapidJSON files 24 | 25 | #include "rapidjson/document.h" 26 | #include "rapidjson/writer.h" 27 | #include "rapidjson/filereadstream.h" 28 | #include "rapidjson/filewritestream.h" 29 | #include "rapidjson/encodedstream.h" 30 | #include "rapidjson/stringbuffer.h" 31 | 32 | static const char json[] = "{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3,4]}"; 33 | 34 | TEST(NamespaceTest,Using) { 35 | using namespace RAPIDJSON_NAMESPACE; 36 | typedef GenericDocument, CrtAllocator> DocumentType; 37 | DocumentType doc; 38 | 39 | doc.Parse(json); 40 | EXPECT_TRUE(!doc.HasParseError()); 41 | } 42 | 43 | TEST(NamespaceTest,Direct) { 44 | typedef RAPIDJSON_NAMESPACE::Document Document; 45 | typedef RAPIDJSON_NAMESPACE::Reader Reader; 46 | typedef RAPIDJSON_NAMESPACE::StringStream StringStream; 47 | typedef RAPIDJSON_NAMESPACE::StringBuffer StringBuffer; 48 | typedef RAPIDJSON_NAMESPACE::Writer WriterType; 49 | 50 | StringStream s(json); 51 | StringBuffer buffer; 52 | WriterType writer(buffer); 53 | buffer.ShrinkToFit(); 54 | Reader reader; 55 | reader.Parse(s, writer); 56 | 57 | EXPECT_STREQ(json, buffer.GetString()); 58 | EXPECT_EQ(sizeof(json)-1, buffer.GetSize()); 59 | EXPECT_TRUE(writer.IsComplete()); 60 | 61 | Document doc; 62 | doc.Parse(buffer.GetString()); 63 | EXPECT_TRUE(!doc.HasParseError()); 64 | 65 | buffer.Clear(); 66 | writer.Reset(buffer); 67 | doc.Accept(writer); 68 | EXPECT_STREQ(json, buffer.GetString()); 69 | EXPECT_TRUE(writer.IsComplete()); 70 | } 71 | -------------------------------------------------------------------------------- /test/unittest/prettywritertest.cpp: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #include "unittest.h" 16 | #include "rapidjson/reader.h" 17 | #include "rapidjson/prettywriter.h" 18 | #include "rapidjson/stringbuffer.h" 19 | #include "rapidjson/filewritestream.h" 20 | 21 | using namespace rapidjson; 22 | 23 | static const char kJson[] = "{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3,-1],\"u64\":1234567890123456789,\"i64\":-1234567890123456789}"; 24 | static const char kPrettyJson[] = 25 | "{\n" 26 | " \"hello\": \"world\",\n" 27 | " \"t\": true,\n" 28 | " \"f\": false,\n" 29 | " \"n\": null,\n" 30 | " \"i\": 123,\n" 31 | " \"pi\": 3.1416,\n" 32 | " \"a\": [\n" 33 | " 1,\n" 34 | " 2,\n" 35 | " 3,\n" 36 | " -1\n" 37 | " ],\n" 38 | " \"u64\": 1234567890123456789,\n" 39 | " \"i64\": -1234567890123456789\n" 40 | "}"; 41 | 42 | TEST(PrettyWriter, Basic) { 43 | StringBuffer buffer; 44 | PrettyWriter writer(buffer); 45 | Reader reader; 46 | StringStream s(kJson); 47 | reader.Parse(s, writer); 48 | EXPECT_STREQ(kPrettyJson, buffer.GetString()); 49 | } 50 | 51 | TEST(PrettyWriter, SetIndent) { 52 | StringBuffer buffer; 53 | PrettyWriter writer(buffer); 54 | writer.SetIndent('\t', 1); 55 | Reader reader; 56 | StringStream s(kJson); 57 | reader.Parse(s, writer); 58 | EXPECT_STREQ( 59 | "{\n" 60 | "\t\"hello\": \"world\",\n" 61 | "\t\"t\": true,\n" 62 | "\t\"f\": false,\n" 63 | "\t\"n\": null,\n" 64 | "\t\"i\": 123,\n" 65 | "\t\"pi\": 3.1416,\n" 66 | "\t\"a\": [\n" 67 | "\t\t1,\n" 68 | "\t\t2,\n" 69 | "\t\t3,\n" 70 | "\t\t-1\n" 71 | "\t],\n" 72 | "\t\"u64\": 1234567890123456789,\n" 73 | "\t\"i64\": -1234567890123456789\n" 74 | "}", 75 | buffer.GetString()); 76 | } 77 | 78 | TEST(PrettyWriter, String) { 79 | StringBuffer buffer; 80 | PrettyWriter writer(buffer); 81 | EXPECT_TRUE(writer.StartArray()); 82 | EXPECT_TRUE(writer.String("Hello\n")); 83 | EXPECT_TRUE(writer.EndArray()); 84 | EXPECT_STREQ("[\n \"Hello\\n\"\n]", buffer.GetString()); 85 | } 86 | 87 | #if RAPIDJSON_HAS_STDSTRING 88 | TEST(PrettyWriter, String_STDSTRING) { 89 | StringBuffer buffer; 90 | PrettyWriter writer(buffer); 91 | EXPECT_TRUE(writer.StartArray()); 92 | EXPECT_TRUE(writer.String(std::string("Hello\n"))); 93 | EXPECT_TRUE(writer.EndArray()); 94 | EXPECT_STREQ("[\n \"Hello\\n\"\n]", buffer.GetString()); 95 | } 96 | #endif 97 | 98 | #include 99 | 100 | class OStreamWrapper { 101 | public: 102 | typedef char Ch; 103 | 104 | OStreamWrapper(std::ostream& os) : os_(os) {} 105 | 106 | Ch Peek() const { assert(false); return '\0'; } 107 | Ch Take() { assert(false); return '\0'; } 108 | size_t Tell() const { return 0; } 109 | 110 | Ch* PutBegin() { assert(false); return 0; } 111 | void Put(Ch c) { os_.put(c); } 112 | void Flush() { os_.flush(); } 113 | size_t PutEnd(Ch*) { assert(false); return 0; } 114 | 115 | private: 116 | OStreamWrapper(const OStreamWrapper&); 117 | OStreamWrapper& operator=(const OStreamWrapper&); 118 | 119 | std::ostream& os_; 120 | }; 121 | 122 | // For covering PutN() generic version 123 | TEST(PrettyWriter, OStreamWrapper) { 124 | StringStream s(kJson); 125 | 126 | std::stringstream ss; 127 | OStreamWrapper os(ss); 128 | 129 | PrettyWriter writer(os); 130 | 131 | Reader reader; 132 | reader.Parse(s, writer); 133 | 134 | std::string actual = ss.str(); 135 | EXPECT_STREQ(kPrettyJson, actual.c_str()); 136 | } 137 | 138 | // For covering FileWriteStream::PutN() 139 | TEST(PrettyWriter, FileWriteStream) { 140 | char filename[L_tmpnam]; 141 | FILE* fp = TempFile(filename); 142 | char buffer[16]; 143 | FileWriteStream os(fp, buffer, sizeof(buffer)); 144 | PrettyWriter writer(os); 145 | Reader reader; 146 | StringStream s(kJson); 147 | reader.Parse(s, writer); 148 | fclose(fp); 149 | 150 | fp = fopen(filename, "rb"); 151 | fseek(fp, 0, SEEK_END); 152 | size_t size = (size_t)ftell(fp); 153 | fseek(fp, 0, SEEK_SET); 154 | char* json = (char*)malloc(size + 1); 155 | size_t readLength = fread(json, 1, size, fp); 156 | json[readLength] = '\0'; 157 | fclose(fp); 158 | remove(filename); 159 | EXPECT_STREQ(kPrettyJson, json); 160 | free(json); 161 | } -------------------------------------------------------------------------------- /test/unittest/readertest.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TencentAPI/rapidjson_bk/1ef0f98f6a42212f11e461935cff1b8ea291cd88/test/unittest/readertest.cpp -------------------------------------------------------------------------------- /test/unittest/simdtest.cpp: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | // Since Travis CI installs old Valgrind 3.7.0, which fails with some SSE4.2 16 | // The unit tests prefix with SIMD should be skipped by Valgrind test 17 | 18 | // __SSE2__ and __SSE4_2__ are recognized by gcc, clang, and the Intel compiler. 19 | // We use -march=native with gmake to enable -msse2 and -msse4.2, if supported. 20 | #if defined(__SSE4_2__) 21 | # define RAPIDJSON_SSE42 22 | #elif defined(__SSE2__) 23 | # define RAPIDJSON_SSE2 24 | #endif 25 | 26 | #define RAPIDJSON_NAMESPACE rapidjson_simd 27 | 28 | #include "unittest.h" 29 | 30 | #include "rapidjson/reader.h" 31 | 32 | using namespace rapidjson_simd; 33 | 34 | #ifdef RAPIDJSON_SSE2 35 | #define SIMD_SUFFIX(name) name##_SSE2 36 | #elif defined(RAPIDJSON_SSE42) 37 | #define SIMD_SUFFIX(name) name##_SSE42 38 | #else 39 | #define SIMD_SUFFIX(name) name 40 | #endif 41 | 42 | template 43 | void TestSkipWhitespace() { 44 | for (int step = 1; step < 32; step++) { 45 | char buffer[1025]; 46 | for (size_t i = 0; i < 1024; i++) 47 | buffer[i] = " \t\r\n"[i % 4]; 48 | for (size_t i = 0; i < 1024; i += step) 49 | buffer[i] = 'X'; 50 | buffer[1024] = '\0'; 51 | 52 | StreamType s(buffer); 53 | size_t i = 0; 54 | for (;;) { 55 | SkipWhitespace(s); 56 | if (s.Peek() == '\0') 57 | break; 58 | EXPECT_EQ(i, s.Tell()); 59 | EXPECT_EQ('X', s.Take()); 60 | i += step; 61 | } 62 | } 63 | } 64 | 65 | TEST(SIMD, SIMD_SUFFIX(SkipWhitespace)) { 66 | TestSkipWhitespace(); 67 | TestSkipWhitespace(); 68 | } 69 | -------------------------------------------------------------------------------- /test/unittest/stringbuffertest.cpp: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #include "unittest.h" 16 | #include "rapidjson/stringbuffer.h" 17 | #include "rapidjson/writer.h" 18 | 19 | using namespace rapidjson; 20 | 21 | TEST(StringBuffer, InitialSize) { 22 | StringBuffer buffer; 23 | EXPECT_EQ(0u, buffer.GetSize()); 24 | EXPECT_STREQ("", buffer.GetString()); 25 | } 26 | 27 | TEST(StringBuffer, Put) { 28 | StringBuffer buffer; 29 | buffer.Put('A'); 30 | 31 | EXPECT_EQ(1u, buffer.GetSize()); 32 | EXPECT_STREQ("A", buffer.GetString()); 33 | } 34 | 35 | TEST(StringBuffer, Clear) { 36 | StringBuffer buffer; 37 | buffer.Put('A'); 38 | buffer.Put('B'); 39 | buffer.Put('C'); 40 | buffer.Clear(); 41 | 42 | EXPECT_EQ(0u, buffer.GetSize()); 43 | EXPECT_STREQ("", buffer.GetString()); 44 | } 45 | 46 | TEST(StringBuffer, Push) { 47 | StringBuffer buffer; 48 | buffer.Push(5); 49 | 50 | EXPECT_EQ(5u, buffer.GetSize()); 51 | 52 | // Causes sudden expansion to make the stack's capacity equal to size 53 | buffer.Push(65536u); 54 | EXPECT_EQ(5u + 65536u, buffer.GetSize()); 55 | } 56 | 57 | TEST(StringBuffer, Pop) { 58 | StringBuffer buffer; 59 | buffer.Put('A'); 60 | buffer.Put('B'); 61 | buffer.Put('C'); 62 | buffer.Put('D'); 63 | buffer.Put('E'); 64 | buffer.Pop(3); 65 | 66 | EXPECT_EQ(2u, buffer.GetSize()); 67 | EXPECT_STREQ("AB", buffer.GetString()); 68 | } 69 | 70 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 71 | 72 | #include 73 | 74 | TEST(StringBuffer, Traits) { 75 | static_assert( std::is_constructible::value, ""); 76 | static_assert( std::is_default_constructible::value, ""); 77 | #ifndef _MSC_VER 78 | static_assert(!std::is_copy_constructible::value, ""); 79 | #endif 80 | static_assert( std::is_move_constructible::value, ""); 81 | 82 | static_assert(!std::is_nothrow_constructible::value, ""); 83 | static_assert(!std::is_nothrow_default_constructible::value, ""); 84 | 85 | #if !defined(_MSC_VER) || _MSC_VER >= 1800 86 | static_assert(!std::is_nothrow_copy_constructible::value, ""); 87 | static_assert(!std::is_nothrow_move_constructible::value, ""); 88 | #endif 89 | 90 | static_assert( std::is_assignable::value, ""); 91 | #ifndef _MSC_VER 92 | static_assert(!std::is_copy_assignable::value, ""); 93 | #endif 94 | static_assert( std::is_move_assignable::value, ""); 95 | 96 | #if !defined(_MSC_VER) || _MSC_VER >= 1800 97 | static_assert(!std::is_nothrow_assignable::value, ""); 98 | #endif 99 | 100 | static_assert(!std::is_nothrow_copy_assignable::value, ""); 101 | static_assert(!std::is_nothrow_move_assignable::value, ""); 102 | 103 | static_assert( std::is_destructible::value, ""); 104 | #ifndef _MSC_VER 105 | static_assert(std::is_nothrow_destructible::value, ""); 106 | #endif 107 | } 108 | 109 | TEST(StringBuffer, MoveConstructor) { 110 | StringBuffer x; 111 | x.Put('A'); 112 | x.Put('B'); 113 | x.Put('C'); 114 | x.Put('D'); 115 | 116 | EXPECT_EQ(4u, x.GetSize()); 117 | EXPECT_STREQ("ABCD", x.GetString()); 118 | 119 | // StringBuffer y(x); // does not compile (!is_copy_constructible) 120 | StringBuffer y(std::move(x)); 121 | EXPECT_EQ(0u, x.GetSize()); 122 | EXPECT_EQ(4u, y.GetSize()); 123 | EXPECT_STREQ("ABCD", y.GetString()); 124 | 125 | // StringBuffer z = y; // does not compile (!is_copy_assignable) 126 | StringBuffer z = std::move(y); 127 | EXPECT_EQ(0u, y.GetSize()); 128 | EXPECT_EQ(4u, z.GetSize()); 129 | EXPECT_STREQ("ABCD", z.GetString()); 130 | } 131 | 132 | TEST(StringBuffer, MoveAssignment) { 133 | StringBuffer x; 134 | x.Put('A'); 135 | x.Put('B'); 136 | x.Put('C'); 137 | x.Put('D'); 138 | 139 | EXPECT_EQ(4u, x.GetSize()); 140 | EXPECT_STREQ("ABCD", x.GetString()); 141 | 142 | StringBuffer y; 143 | // y = x; // does not compile (!is_copy_assignable) 144 | y = std::move(x); 145 | EXPECT_EQ(0u, x.GetSize()); 146 | EXPECT_EQ(4u, y.GetSize()); 147 | EXPECT_STREQ("ABCD", y.GetString()); 148 | } 149 | 150 | #endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS 151 | -------------------------------------------------------------------------------- /test/unittest/strtodtest.cpp: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #include "unittest.h" 16 | 17 | #include "rapidjson/internal/strtod.h" 18 | 19 | #define BIGINTEGER_LITERAL(s) BigInteger(s, sizeof(s) - 1) 20 | 21 | using namespace rapidjson::internal; 22 | 23 | TEST(Strtod, CheckApproximationCase) { 24 | static const int kSignificandSize = 52; 25 | static const int kExponentBias = 0x3FF; 26 | static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); 27 | static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); 28 | static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); 29 | 30 | // http://www.exploringbinary.com/using-integers-to-check-a-floating-point-approximation/ 31 | // Let b = 0x1.465a72e467d88p-149 32 | // = 5741268244528520 x 2^-201 33 | union { 34 | double d; 35 | uint64_t u; 36 | }u; 37 | u.u = 0x465a72e467d88 | ((static_cast(-149 + kExponentBias)) << kSignificandSize); 38 | const double b = u.d; 39 | const uint64_t bInt = (u.u & kSignificandMask) | kHiddenBit; 40 | const int bExp = ((u.u & kExponentMask) >> kSignificandSize) - kExponentBias - kSignificandSize; 41 | EXPECT_DOUBLE_EQ(1.7864e-45, b); 42 | EXPECT_EQ(RAPIDJSON_UINT64_C2(0x001465a7, 0x2e467d88), bInt); 43 | EXPECT_EQ(-201, bExp); 44 | 45 | // Let d = 17864 x 10-49 46 | const char dInt[] = "17864"; 47 | const int dExp = -49; 48 | 49 | // Let h = 2^(bExp-1) 50 | const int hExp = bExp - 1; 51 | EXPECT_EQ(-202, hExp); 52 | 53 | int dS_Exp2 = 0; 54 | int dS_Exp5 = 0; 55 | int bS_Exp2 = 0; 56 | int bS_Exp5 = 0; 57 | int hS_Exp2 = 0; 58 | int hS_Exp5 = 0; 59 | 60 | // Adjust for decimal exponent 61 | if (dExp >= 0) { 62 | dS_Exp2 += dExp; 63 | dS_Exp5 += dExp; 64 | } 65 | else { 66 | bS_Exp2 -= dExp; 67 | bS_Exp5 -= dExp; 68 | hS_Exp2 -= dExp; 69 | hS_Exp5 -= dExp; 70 | } 71 | 72 | // Adjust for binary exponent 73 | if (bExp >= 0) 74 | bS_Exp2 += bExp; 75 | else { 76 | dS_Exp2 -= bExp; 77 | hS_Exp2 -= bExp; 78 | } 79 | 80 | // Adjust for half ulp exponent 81 | if (hExp >= 0) 82 | hS_Exp2 += hExp; 83 | else { 84 | dS_Exp2 -= hExp; 85 | bS_Exp2 -= hExp; 86 | } 87 | 88 | // Remove common power of two factor from all three scaled values 89 | int common_Exp2 = std::min(dS_Exp2, std::min(bS_Exp2, hS_Exp2)); 90 | dS_Exp2 -= common_Exp2; 91 | bS_Exp2 -= common_Exp2; 92 | hS_Exp2 -= common_Exp2; 93 | 94 | EXPECT_EQ(153, dS_Exp2); 95 | EXPECT_EQ(0, dS_Exp5); 96 | EXPECT_EQ(1, bS_Exp2); 97 | EXPECT_EQ(49, bS_Exp5); 98 | EXPECT_EQ(0, hS_Exp2); 99 | EXPECT_EQ(49, hS_Exp5); 100 | 101 | BigInteger dS = BIGINTEGER_LITERAL(dInt); 102 | dS.MultiplyPow5(dS_Exp5) <<= dS_Exp2; 103 | 104 | BigInteger bS(bInt); 105 | bS.MultiplyPow5(bS_Exp5) <<= bS_Exp2; 106 | 107 | BigInteger hS(1); 108 | hS.MultiplyPow5(hS_Exp5) <<= hS_Exp2; 109 | 110 | EXPECT_TRUE(BIGINTEGER_LITERAL("203970822259994138521801764465966248930731085529088") == dS); 111 | EXPECT_TRUE(BIGINTEGER_LITERAL("203970822259994122305215569213032722473144531250000") == bS); 112 | EXPECT_TRUE(BIGINTEGER_LITERAL("17763568394002504646778106689453125") == hS); 113 | 114 | EXPECT_EQ(1, dS.Compare(bS)); 115 | 116 | BigInteger delta(0); 117 | EXPECT_FALSE(dS.Difference(bS, &delta)); 118 | EXPECT_TRUE(BIGINTEGER_LITERAL("16216586195252933526457586554279088") == delta); 119 | EXPECT_TRUE(bS.Difference(dS, &delta)); 120 | EXPECT_TRUE(BIGINTEGER_LITERAL("16216586195252933526457586554279088") == delta); 121 | 122 | EXPECT_EQ(-1, delta.Compare(hS)); 123 | } 124 | -------------------------------------------------------------------------------- /test/unittest/unittest.cpp: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #include "unittest.h" 16 | #include "rapidjson/rapidjson.h" 17 | 18 | int main(int argc, char **argv) { 19 | ::testing::InitGoogleTest(&argc, argv); 20 | 21 | std::cout << "RapidJSON v" << RAPIDJSON_VERSION_STRING << std::endl; 22 | 23 | #if _MSC_VER 24 | _CrtMemState memoryState = { 0 }; 25 | _CrtMemCheckpoint(&memoryState); 26 | //_CrtSetBreakAlloc(X); 27 | //void *testWhetherMemoryLeakDetectionWorks = malloc(1); 28 | #endif 29 | 30 | int ret = RUN_ALL_TESTS(); 31 | 32 | #if _MSC_VER 33 | // Current gtest constantly leak 2 blocks at exit 34 | _CrtMemDumpAllObjectsSince(&memoryState); 35 | #endif 36 | return ret; 37 | } 38 | -------------------------------------------------------------------------------- /test/unittest/unittest.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef UNITTEST_H_ 16 | #define UNITTEST_H_ 17 | 18 | 19 | // gtest indirectly included inttypes.h, without __STDC_CONSTANT_MACROS. 20 | #ifndef __STDC_CONSTANT_MACROS 21 | # define __STDC_CONSTANT_MACROS 1 // required by C++ standard 22 | #endif 23 | 24 | #ifdef _MSC_VER 25 | #define _CRTDBG_MAP_ALLOC 26 | #include 27 | #pragma warning(disable : 4996) // 'function': was declared deprecated 28 | #endif 29 | 30 | #if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) 31 | #if defined(__clang__) || (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) 32 | #pragma GCC diagnostic push 33 | #endif 34 | #pragma GCC diagnostic ignored "-Weffc++" 35 | #endif 36 | 37 | #include "gtest/gtest.h" 38 | #include 39 | 40 | #if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) 41 | #pragma GCC diagnostic pop 42 | #endif 43 | 44 | template 45 | inline unsigned StrLen(const Ch* s) { 46 | const Ch* p = s; 47 | while (*p) p++; 48 | return unsigned(p - s); 49 | } 50 | 51 | template 52 | inline int StrCmp(const Ch* s1, const Ch* s2) { 53 | while(*s1 && (*s1 == *s2)) { s1++; s2++; } 54 | return (unsigned)*s1 < (unsigned)*s2 ? -1 : (unsigned)*s1 > (unsigned)*s2; 55 | } 56 | 57 | template 58 | inline Ch* StrDup(const Ch* str) { 59 | size_t bufferSize = sizeof(Ch) * (StrLen(str) + 1); 60 | Ch* buffer = (Ch*)malloc(bufferSize); 61 | memcpy(buffer, str, bufferSize); 62 | return buffer; 63 | } 64 | 65 | inline FILE* TempFile(char *filename) { 66 | #if _MSC_VER 67 | filename = tmpnam(filename); 68 | 69 | // For Visual Studio, tmpnam() adds a backslash in front. Remove it. 70 | if (filename[0] == '\\') 71 | for (int i = 0; filename[i] != '\0'; i++) 72 | filename[i] = filename[i + 1]; 73 | 74 | return fopen(filename, "wb"); 75 | #else 76 | strcpy(filename, "/tmp/fileXXXXXX"); 77 | int fd = mkstemp(filename); 78 | return fdopen(fd, "w"); 79 | #endif 80 | } 81 | 82 | // Use exception for catching assert 83 | #if _MSC_VER 84 | #pragma warning(disable : 4127) 85 | #endif 86 | 87 | class AssertException : public std::logic_error { 88 | public: 89 | AssertException(const char* w) : std::logic_error(w) {} 90 | }; 91 | 92 | #define RAPIDJSON_ASSERT(x) if (!(x)) throw AssertException(RAPIDJSON_STRINGIFY(x)) 93 | 94 | class Random { 95 | public: 96 | Random(unsigned seed = 0) : mSeed(seed) {} 97 | 98 | unsigned operator()() { 99 | mSeed = 214013 * mSeed + 2531011; 100 | return mSeed; 101 | } 102 | 103 | private: 104 | unsigned mSeed; 105 | }; 106 | 107 | #endif // UNITTEST_H_ 108 | -------------------------------------------------------------------------------- /travis-doxygen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Update Doxygen documentation after push to 'master'. 3 | # Author: @pah 4 | 5 | set -e 6 | 7 | DOXYGEN_VER=doxygen-1.8.7 8 | DOXYGEN_TAR=${DOXYGEN_VER}.linux.bin.tar.gz 9 | DOXYGEN_URL="http://ftp.stack.nl/pub/users/dimitri/${DOXYGEN_TAR}" 10 | DOXYGEN_BIN="/usr/local/bin/doxygen" 11 | 12 | : ${GITHUB_REPO:="miloyip/rapidjson"} 13 | GITHUB_HOST="github.com" 14 | GITHUB_CLONE="git://${GITHUB_HOST}/${GITHUB_REPO}" 15 | GITHUB_URL="https://${GITHUB_HOST}/${GITHUB_PUSH-${GITHUB_REPO}}" 16 | 17 | # if not set, ignore password 18 | #GIT_ASKPASS="${TRAVIS_BUILD_DIR}/gh_ignore_askpass.sh" 19 | 20 | skip() { 21 | echo "$@" 1>&2 22 | echo "Exiting..." 1>&2 23 | exit 0 24 | } 25 | 26 | abort() { 27 | echo "Error: $@" 1>&2 28 | echo "Exiting..." 1>&2 29 | exit 1 30 | } 31 | 32 | # TRAVIS_BUILD_DIR not set, exiting 33 | [ -d "${TRAVIS_BUILD_DIR-/nonexistent}" ] || \ 34 | abort '${TRAVIS_BUILD_DIR} not set or nonexistent.' 35 | 36 | # check for pull-requests 37 | [ "${TRAVIS_PULL_REQUEST}" = "false" ] || \ 38 | skip "Not running Doxygen for pull-requests." 39 | 40 | # check for branch name 41 | [ "${TRAVIS_BRANCH}" = "master" ] || \ 42 | skip "Running Doxygen only for updates on 'master' branch (current: ${TRAVIS_BRANCH})." 43 | 44 | # check for job number 45 | [ "${TRAVIS_JOB_NUMBER}" = "${TRAVIS_BUILD_NUMBER}.1" ] || \ 46 | skip "Running Doxygen only on first job of build ${TRAVIS_BUILD_NUMBER} (current: ${TRAVIS_JOB_NUMBER})." 47 | 48 | # install doxygen binary distribution 49 | doxygen_install() 50 | { 51 | wget -O - "${DOXYGEN_URL}" | \ 52 | tar xz -C ${TMPDIR-/tmp} ${DOXYGEN_VER}/bin/doxygen 53 | export PATH="${TMPDIR-/tmp}/${DOXYGEN_VER}/bin:$PATH" 54 | } 55 | 56 | doxygen_run() 57 | { 58 | cd "${TRAVIS_BUILD_DIR}"; 59 | doxygen ${TRAVIS_BUILD_DIR}/build/doc/Doxyfile; 60 | doxygen ${TRAVIS_BUILD_DIR}/build/doc/Doxyfile.zh-cn; 61 | } 62 | 63 | gh_pages_prepare() 64 | { 65 | cd "${TRAVIS_BUILD_DIR}/build/doc"; 66 | [ ! -d "html" ] || \ 67 | abort "Doxygen target directory already exists." 68 | git --version 69 | git clone --single-branch -b gh-pages "${GITHUB_CLONE}" html 70 | cd html 71 | # setup git config (with defaults) 72 | git config user.name "${GIT_NAME-travis}" 73 | git config user.email "${GIT_EMAIL-"travis@localhost"}" 74 | # clean working dir 75 | rm -f .git/index 76 | git clean -df 77 | } 78 | 79 | gh_pages_commit() { 80 | cd "${TRAVIS_BUILD_DIR}/build/doc/html"; 81 | git add --all; 82 | git diff-index --quiet HEAD || git commit -m "Automatic doxygen build"; 83 | } 84 | 85 | gh_setup_askpass() { 86 | cat > ${GIT_ASKPASS} < ${HOME}/.git-credentials ; \ 111 | chmod go-rw ${HOME}/.git-credentials ) ) 112 | # push to GitHub 113 | git push origin gh-pages 114 | } 115 | 116 | doxygen_install 117 | gh_pages_prepare 118 | doxygen_run 119 | gh_pages_commit 120 | gh_pages_push 121 | 122 | --------------------------------------------------------------------------------