Unverified Commit 532cba14 authored by John Stiles's avatar John Stiles Committed by GitHub

Merge pull request #4 from Tencent/master

Merge
parents 1391e425 a0910358
......@@ -23,3 +23,6 @@ Doxyfile
Doxyfile.zh-cn
DartConfiguration.tcl
*.nupkg
# Files created by OS
*.DS_Store
sudo: required
dist: precise
dist: trusty
group: edge
language: cpp
cache:
......@@ -13,7 +14,7 @@ env:
- CCACHE_MAXSIZE=100M
- ARCH_FLAGS_x86='-m32' # #266: don't use SSE on 32-bit
- ARCH_FLAGS_x86_64='-msse4.2' # use SSE4.2 on 64-bit
- GITHUB_REPO='miloyip/rapidjson'
- GITHUB_REPO='Tencent/rapidjson'
- secure: "HrsaCb+N66EG1HR+LWH1u51SjaJyRwJEDzqJGYMB7LJ/bfqb9mWKF1fLvZGk46W5t7TVaXRDD5KHFx9DPWvKn4gRUVkwTHEy262ah5ORh8M6n/6VVVajeV/AYt2C0sswdkDBDO4Xq+xy5gdw3G8s1A4Inbm73pUh+6vx+7ltBbk="
before_install:
......
......@@ -109,7 +109,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## [1.0.0] - 2015-04-22
### Added
* 100% [Coverall](https://coveralls.io/r/miloyip/rapidjson?branch=master) coverage.
* 100% [Coverall](https://coveralls.io/r/Tencent/rapidjson?branch=master) coverage.
* Version macros (#311)
### Fixed
......@@ -140,7 +140,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
* Redo all documentation (English, Simplified Chinese)
### Changed
* Copyright ownership transfered to THL A29 Limited (a Tencent company).
* Copyright ownership transferred to THL A29 Limited (a Tencent company).
* Migrating from Premake to CMAKE (#192)
* Resolve all warning reports
......@@ -151,8 +151,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## 0.1 - 2011-11-18
[Unreleased]: https://github.com/miloyip/rapidjson/compare/v1.1.0...HEAD
[1.1.0]: https://github.com/miloyip/rapidjson/compare/v1.0.2...v1.1.0
[1.0.2]: https://github.com/miloyip/rapidjson/compare/v1.0.1...v1.0.2
[1.0.1]: https://github.com/miloyip/rapidjson/compare/v1.0.0...v1.0.1
[1.0.0]: https://github.com/miloyip/rapidjson/compare/v1.0-beta...v1.0.0
[Unreleased]: https://github.com/Tencent/rapidjson/compare/v1.1.0...HEAD
[1.1.0]: https://github.com/Tencent/rapidjson/compare/v1.0.2...v1.1.0
[1.0.2]: https://github.com/Tencent/rapidjson/compare/v1.0.1...v1.0.2
[1.0.1]: https://github.com/Tencent/rapidjson/compare/v1.0.0...v1.0.1
[1.0.0]: https://github.com/Tencent/rapidjson/compare/v1.0-beta...v1.0.0
......@@ -31,10 +31,16 @@ option(RAPIDJSON_BUILD_THIRDPARTY_GTEST
"Use gtest installation in `thirdparty/gtest` by default if available" OFF)
option(RAPIDJSON_BUILD_CXX11 "Build rapidjson with C++11 (gcc/clang)" ON)
if(RAPIDJSON_BUILD_CXX11)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
endif()
option(RAPIDJSON_BUILD_ASAN "Build rapidjson with address sanitizer (gcc/clang)" OFF)
option(RAPIDJSON_BUILD_UBSAN "Build rapidjson with undefined behavior sanitizer (gcc/clang)" OFF)
option(RAPIDJSON_ENABLE_INSTRUMENTATION_OPT "Build rapidjson with -march or -mcpu options" ON)
option(RAPIDJSON_HAS_STDSTRING "" OFF)
if(RAPIDJSON_HAS_STDSTRING)
add_definitions(-DRAPIDJSON_HAS_STDSTRING)
......@@ -49,16 +55,18 @@ if(CCACHE_FOUND)
endif()
endif(CCACHE_FOUND)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "powerpc" OR ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "ppc64" OR ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "ppc64le")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcpu=native")
else()
#FIXME: x86 is -march=native, but doesn't mean every arch is this option. To keep original project's compatibility, I leave this except POWER.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if(RAPIDJSON_ENABLE_INSTRUMENTATION_OPT AND NOT CMAKE_CROSSCOMPILING)
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "powerpc" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc64le")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcpu=native")
else()
#FIXME: x86 is -march=native, but doesn't mean every arch is this option. To keep original project's compatibility, I leave this except POWER.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
endif()
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror")
set(EXTRA_CXX_FLAGS -Weffc++ -Wswitch-default -Wfloat-equal -Wconversion -Wsign-conversion)
if (RAPIDJSON_BUILD_CXX11)
if (RAPIDJSON_BUILD_CXX11 AND CMAKE_VERSION VERSION_LESS 3.1)
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.7.0")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
......@@ -80,15 +88,17 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
endif()
endif()
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "powerpc" OR ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "ppc64" OR ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "ppc64le")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcpu=native")
else()
#FIXME: x86 is -march=native, but doesn't mean every arch is this option. To keep original project's compatibility, I leave this except POWER.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
if(NOT CMAKE_CROSSCOMPILING)
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "powerpc" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc64le")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcpu=native")
else()
#FIXME: x86 is -march=native, but doesn't mean every arch is this option. To keep original project's compatibility, I leave this except POWER.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
endif()
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror -Wno-missing-field-initializers")
set(EXTRA_CXX_FLAGS -Weffc++ -Wswitch-default -Wfloat-equal -Wconversion -Wimplicit-fallthrough -Weverything)
if (RAPIDJSON_BUILD_CXX11)
set(EXTRA_CXX_FLAGS -Weffc++ -Wswitch-default -Wfloat-equal -Wconversion -Wimplicit-fallthrough)
if (RAPIDJSON_BUILD_CXX11 AND CMAKE_VERSION VERSION_LESS 3.1)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
endif()
if (RAPIDJSON_BUILD_ASAN)
......@@ -101,7 +111,7 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined")
endif()
endif()
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
add_definitions(-D_CRT_SECURE_NO_WARNINGS=1)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc")
elseif (CMAKE_CXX_COMPILER_ID MATCHES "XL")
......@@ -118,7 +128,7 @@ IF(UNIX OR CYGWIN)
ELSEIF(WIN32)
SET(_CMAKE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/cmake")
ENDIF()
SET(CMAKE_INSTALL_DIR "${_CMAKE_INSTALL_DIR}" CACHE PATH "The directory cmake fiels are installed in")
SET(CMAKE_INSTALL_DIR "${_CMAKE_INSTALL_DIR}" CACHE PATH "The directory cmake files are installed in")
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
......@@ -181,6 +191,8 @@ EXPORT( PACKAGE ${PROJECT_NAME} )
# ... for the build tree
SET( CONFIG_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
SET( CONFIG_DIR ${CMAKE_CURRENT_BINARY_DIR})
SET( ${PROJECT_NAME}_INCLUDE_DIR "\${${PROJECT_NAME}_SOURCE_DIR}/include" )
CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}Config.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake @ONLY )
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}ConfigVersion.cmake.in
......
......@@ -3,5 +3,5 @@ includedir=@INCLUDE_INSTALL_DIR@
Name: @PROJECT_NAME@
Description: A fast JSON parser/generator for C++ with both SAX/DOM style API
Version: @LIB_VERSION_STRING@
URL: https://github.com/miloyip/rapidjson
URL: https://github.com/Tencent/rapidjson
Cflags: -I${includedir}
The MIT License (MIT)
Copyright (c) 2017 Bart Muzzin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Derived from:
The MIT License (MIT)
Copyright (c) 2015 mojmir svoboda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# rapidjson.natvis
This file can be used as a [Visual Studio Visualizer](https://docs.microsoft.com/en-gb/visualstudio/debugger/create-custom-views-of-native-objects) to aid in visualizing rapidjson structures within the Visual Studio debugger. Natvis visualizers are supported in Visual Studio 2012 and later. To install, copy the file into this directory:
`%USERPROFILE%\Documents\Visual Studio 2012\Visualizers`
Each version of Visual Studio has a similar directory, it must be copied into each directory to be used with that particular version. In Visual Studio 2015 and later, this can be done without restarting Visual Studio (a new debugging session must be started).
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<!-- rapidjson::GenericValue - basic support -->
<Type Name="rapidjson::GenericValue&lt;*,*&gt;">
<DisplayString Condition="(data_.f.flags &amp; kTypeMask) == kNullType">null</DisplayString>
<DisplayString Condition="data_.f.flags == kTrueFlag">true</DisplayString>
<DisplayString Condition="data_.f.flags == kFalseFlag">false</DisplayString>
<DisplayString Condition="data_.f.flags == kShortStringFlag">{data_.ss.str}</DisplayString>
<DisplayString Condition="(data_.f.flags &amp; kTypeMask) == kStringType">{(const char*)((size_t)data_.s.str &amp; 0x0000FFFFFFFFFFFF)}</DisplayString>
<DisplayString Condition="(data_.f.flags &amp; kNumberIntFlag) == kNumberIntFlag">{data_.n.i.i}</DisplayString>
<DisplayString Condition="(data_.f.flags &amp; kNumberUintFlag) == kNumberUintFlag">{data_.n.u.u}</DisplayString>
<DisplayString Condition="(data_.f.flags &amp; kNumberInt64Flag) == kNumberInt64Flag">{data_.n.i64}</DisplayString>
<DisplayString Condition="(data_.f.flags &amp; kNumberUint64Flag) == kNumberUint64Flag">{data_.n.u64}</DisplayString>
<DisplayString Condition="(data_.f.flags &amp; kNumberDoubleFlag) == kNumberDoubleFlag">{data_.n.d}</DisplayString>
<DisplayString Condition="data_.f.flags == kObjectType">Object members={data_.o.size}</DisplayString>
<DisplayString Condition="data_.f.flags == kArrayType">Array members={data_.a.size}</DisplayString>
<Expand>
<Item Condition="data_.f.flags == kObjectType" Name="[size]">data_.o.size</Item>
<Item Condition="data_.f.flags == kObjectType" Name="[capacity]">data_.o.capacity</Item>
<ArrayItems Condition="data_.f.flags == kObjectType">
<Size>data_.o.size</Size>
<!-- NOTE: Rapidjson stores some extra data in the high bits of pointers, which is why the mask -->
<ValuePointer>(rapidjson::GenericMember&lt;$T1,$T2&gt;*)(((size_t)data_.o.members) &amp; 0x0000FFFFFFFFFFFF)</ValuePointer>
</ArrayItems>
<Item Condition="data_.f.flags == kArrayType" Name="[size]">data_.a.size</Item>
<Item Condition="data_.f.flags == kArrayType" Name="[capacity]">data_.a.capacity</Item>
<ArrayItems Condition="data_.f.flags == kArrayType">
<Size>data_.a.size</Size>
<!-- NOTE: Rapidjson stores some extra data in the high bits of pointers, which is why the mask -->
<ValuePointer>(rapidjson::GenericValue&lt;$T1,$T2&gt;*)(((size_t)data_.a.elements) &amp; 0x0000FFFFFFFFFFFF)</ValuePointer>
</ArrayItems>
</Expand>
</Type>
</AutoVisualizer>
......@@ -10,11 +10,13 @@ ELSE()
CONFIGURE_FILE(Doxyfile.in Doxyfile @ONLY)
CONFIGURE_FILE(Doxyfile.zh-cn.in Doxyfile.zh-cn @ONLY)
file(GLOB DOXYFILES ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile*)
add_custom_command(OUTPUT html
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile.zh-cn
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/html
DEPENDS ${MARKDOWN_DOC} ${SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile*
DEPENDS ${MARKDOWN_DOC} ${SOURCES} ${DOXYFILES}
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/../
)
......
......@@ -1126,7 +1126,7 @@ HTML_STYLESHEET =
# defined cascading style sheet that is included after the standard style sheets
# created by doxygen. Using this option one can overrule certain style aspects.
# This is preferred over using HTML_STYLESHEET since it does not replace the
# standard style sheet and is therefor more robust against future updates.
# standard style sheet and is therefore more robust against future updates.
# Doxygen will copy the style sheet file to the output directory. For an example
# see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
......
......@@ -1126,7 +1126,7 @@ HTML_STYLESHEET =
# defined cascading style sheet that is included after the standard style sheets
# created by doxygen. Using this option one can overrule certain style aspects.
# This is preferred over using HTML_STYLESHEET since it does not replace the
# standard style sheet and is therefor more robust against future updates.
# standard style sheet and is therefore more robust against future updates.
# Doxygen will copy the style sheet file to the output directory. For an example
# see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
......
......@@ -18,7 +18,7 @@ digraph {
node [shape=Mrecord, style=filled, colorscheme=spectral7]
c1 [label="{contact:array|}", fillcolor=4]
c1 [label="{contacts:array|}", fillcolor=4]
c11 [label="{|}"]
c12 [label="{|}"]
c13 [shape="none", label="...", style="solid"]
......@@ -41,13 +41,13 @@ digraph {
node [shape=Mrecord, style=filled, colorscheme=spectral7]
c2 [label="{contact:array|}", fillcolor=4]
c2 [label="{contacts:array|}", fillcolor=4]
c3 [label="{array|}", fillcolor=4]
c21 [label="{|}"]
c22 [label="{|}"]
c23 [shape=none, label="...", style="solid"]
o2 [label="{o:object|}", fillcolor=3]
cs [label="{string|\"contact\"}", fillcolor=5]
cs [label="{string|\"contacts\"}", fillcolor=5]
c31 [label="{|}"]
c32 [label="{|}"]
c33 [shape="none", label="...", style="solid"]
......@@ -59,4 +59,4 @@ digraph {
c3 -> { c31; c32; c33 }
}
ghost -> o2 [style=invis]
}
\ No newline at end of file
}
......@@ -19,7 +19,7 @@ digraph {
node [shape=Mrecord, style=filled, colorscheme=spectral7]
c1 [label="{contact:array|}", fillcolor=4]
c1 [label="{contacts:array|}", fillcolor=4]
c11 [label="{|}"]
c12 [label="{|}"]
c13 [shape=none, label="...", style="solid"]
......@@ -42,13 +42,13 @@ digraph {
node [shape=Mrecord, style=filled, colorscheme=spectral7]
c2 [label="{contact:null|}", fillcolor=1]
c2 [label="{contacts:null|}", fillcolor=1]
c3 [label="{array|}", fillcolor=4]
c21 [label="{|}"]
c22 [label="{|}"]
c23 [shape="none", label="...", style="solid"]
o2 [label="{o:object|}", fillcolor=3]
cs [label="{string|\"contact\"}", fillcolor=5]
cs [label="{string|\"contacts\"}", fillcolor=5]
c2 -> o2 [style="dashed", constraint=false, label="AddMember", style=invis]
edge [arrowhead=vee]
......@@ -57,4 +57,4 @@ digraph {
cs -> c3 [arrowhead=none]
}
ghost -> o2 [style=invis]
}
\ No newline at end of file
}
......@@ -128,7 +128,7 @@ And the `InputStream` is type of input stream.
## Parse Error {#ParseError}
When the parse processing succeeded, the `Document` contains the parse results. When there is an error, the original DOM is *unchanged*. And the error state of parsing can be obtained by `bool HasParseError()`, `ParseErrorCode GetParseError()` and `size_t GetParseOffset()`.
When the parse processing succeeded, the `Document` contains the parse results. When there is an error, the original DOM is *unchanged*. And the error state of parsing can be obtained by `bool HasParseError()`, `ParseErrorCode GetParseError()` and `size_t GetErrorOffset()`.
Parse Error Code | Description
--------------------------------------------|---------------------------------------------------
......@@ -241,7 +241,7 @@ Some techniques about using DOM API is discussed here.
## DOM as SAX Event Publisher
In RapidJSON, stringifying a DOM with `Writer` may be look a little bit weired.
In RapidJSON, stringifying a DOM with `Writer` may be look a little bit weird.
~~~~~~~~~~cpp
// ...
......
......@@ -128,7 +128,7 @@ GenericDocument& GenericDocument::Parse(const Ch* str);
## 解析错误 {#ParseError}
当解析过程顺利完成,`Document` 便会含有解析结果。当过程出现错误,原来的 DOM 会*维持不变*。可使用 `bool HasParseError()``ParseErrorCode GetParseError()``size_t GetParseOffset()` 获取解析的错误状态。
当解析过程顺利完成,`Document` 便会含有解析结果。当过程出现错误,原来的 DOM 会*维持不变*。可使用 `bool HasParseError()``ParseErrorCode GetParseError()``size_t GetErrorOffset()` 获取解析的错误状态。
解析错误代号 | 描述
--------------------------------------------|---------------------------------------------------
......
......@@ -10,7 +10,7 @@ The earlier [RFC4627](http://www.ietf.org/rfc/rfc4627.txt) stated that,
> (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.
RapidJSON supports various encodings. It can also validate the encodings of JSON, and transconding JSON among encodings. All these features are implemented internally, without the need for external libraries (e.g. [ICU](http://site.icu-project.org/)).
RapidJSON supports various encodings. It can also validate the encodings of JSON, and transcoding JSON among encodings. All these features are implemented internally, without the need for external libraries (e.g. [ICU](http://site.icu-project.org/)).
[TOC]
......
......@@ -18,7 +18,7 @@
4. Is RapidJSON free?
Yes, it is free under MIT license. It can be used in commercial applications. Please check the details in [license.txt](https://github.com/miloyip/rapidjson/blob/master/license.txt).
Yes, it is free under MIT license. It can be used in commercial applications. Please check the details in [license.txt](https://github.com/Tencent/rapidjson/blob/master/license.txt).
5. Is RapidJSON small? What are its dependencies?
......@@ -44,7 +44,7 @@
10. How RapidJSON is tested?
RapidJSON contains a unit test suite for automatic testing. [Travis](https://travis-ci.org/miloyip/rapidjson/)(for Linux) and [AppVeyor](https://ci.appveyor.com/project/miloyip/rapidjson/)(for Windows) will compile and run the unit test suite for all modifications. The test process also uses Valgrind (in Linux) to detect memory leaks.
RapidJSON contains a unit test suite for automatic testing. [Travis](https://travis-ci.org/Tencent/rapidjson/)(for Linux) and [AppVeyor](https://ci.appveyor.com/project/Tencent/rapidjson/)(for Windows) will compile and run the unit test suite for all modifications. The test process also uses Valgrind (in Linux) to detect memory leaks.
11. Is RapidJSON well documented?
......@@ -70,7 +70,7 @@
3. Does RapidJSON support relaxed syntax?
Currently no. RapidJSON only support the strict standardized format. Support on related syntax is under discussion in this [issue](https://github.com/miloyip/rapidjson/issues/36).
Currently no. RapidJSON only support the strict standardized format. Support on related syntax is under discussion in this [issue](https://github.com/Tencent/rapidjson/issues/36).
## DOM and SAX
......@@ -116,7 +116,7 @@
~~~~~~~~~~cpp
Value(kObjectType).Swap(d);
~~~~~~~~~~
or equivalent, but sightly longer to type:
or equivalent, but slightly longer to type:
~~~~~~~~~~cpp
d.Swap(Value(kObjectType).Move());
~~~~~~~~~~
......@@ -140,11 +140,11 @@
}
~~~~~~~~~~
The most important requirement to take care of document and value life-cycle as well as consistent memory managent using the right allocator during the value transfer.
The most important requirement to take care of document and value life-cycle as well as consistent memory management using the right allocator during the value transfer.
Simple yet most efficient way to achieve that is to modify the `address` definition above to initialize it with allocator of the `person` document, then we just add the root member of the value:
~~~~~~~~~~cpp
Documnet address(person.GetAllocator());
Document address(person.GetAllocator());
...
person["person"].AddMember("address", address["address"], person.GetAllocator());
~~~~~~~~~~
......@@ -174,7 +174,7 @@ Alternatively, if we don't want to explicitly refer to the root value of `addres
3. Why do I need to provide the length of string?
Since C string is null-terminated, the length of string needs to be computed via `strlen()`, with linear runtime complexity. This incurs an unncessary overhead of many operations, if the user already knows the length of string.
Since C string is null-terminated, the length of string needs to be computed via `strlen()`, with linear runtime complexity. This incurs an unnecessary overhead of many operations, if the user already knows the length of string.
Also, RapidJSON can handle `\u0000` (null character) within a string. If a string contains null characters, `strlen()` cannot return the true length of it. In such case user must provide the length of string explicitly.
......@@ -204,7 +204,7 @@ Alternatively, if we don't want to explicitly refer to the root value of `addres
2. Can it validate the encoding?
Yes, just pass `kParseValidateEncodingFlag` to `Parse()`. If there is invalid encoding in the stream, it wil generate `kParseErrorStringInvalidEncoding` error.
Yes, just pass `kParseValidateEncodingFlag` to `Parse()`. If there is invalid encoding in the stream, it will generate `kParseErrorStringInvalidEncoding` error.
3. What is surrogate pair? Does RapidJSON support it?
......@@ -236,7 +236,7 @@ Alternatively, if we don't want to explicitly refer to the root value of `addres
4. What is BOM? How RapidJSON handle it?
[Byte order mark (BOM)](http://en.wikipedia.org/wiki/Byte_order_mark) sometimes reside at the beginning of file/stream to indiciate the UTF encoding type of it.
[Byte order mark (BOM)](http://en.wikipedia.org/wiki/Byte_order_mark) sometimes reside at the beginning of file/stream to indicate the UTF encoding type of it.
RapidJSON's `EncodedInputStream` can detect/consume BOM. `EncodedOutputStream` can optionally write a BOM. See [Encoded Streams](doc/stream.md) for example.
......@@ -248,7 +248,7 @@ Alternatively, if we don't want to explicitly refer to the root value of `addres
1. Is RapidJSON really fast?
Yes. It may be the fastest open source JSON library. There is a [benchmark](https://github.com/miloyip/nativejson-benchmark) for evaluating performance of C/C++ JSON libaries.
Yes. It may be the fastest open source JSON library. There is a [benchmark](https://github.com/miloyip/nativejson-benchmark) for evaluating performance of C/C++ JSON libraries.
2. Why is it fast?
......@@ -256,19 +256,19 @@ Alternatively, if we don't want to explicitly refer to the root value of `addres
3. What is SIMD? How it is applied in RapidJSON?
[SIMD](http://en.wikipedia.org/wiki/SIMD) instructions can perform parallel computation in modern CPUs. RapidJSON support Intel's SSE2/SSE4.2 to accelerate whitespace skipping. This improves performance of parsing indent formatted JSON. Define `RAPIDJSON_SSE2` or `RAPIDJSON_SSE42` macro to enable this feature. However, running the executable on a machine without such instruction set support will make it crash.
[SIMD](http://en.wikipedia.org/wiki/SIMD) instructions can perform parallel computation in modern CPUs. RapidJSON support Intel's SSE2/SSE4.2 and ARM's Neon to accelerate whitespace/tabspace/carriage-return/line-feed skipping. This improves performance of parsing indent formatted JSON. Define `RAPIDJSON_SSE2`, `RAPIDJSON_SSE42` or `RAPIDJSON_NEON` macro to enable this feature. However, running the executable on a machine without such instruction set support will make it crash.
4. Does it consume a lot of memory?
The design of RapidJSON aims at reducing memory footprint.
In the SAX API, `Reader` consumes memory portional to maximum depth of JSON tree, plus maximum length of JSON string.
In the SAX API, `Reader` consumes memory proportional to maximum depth of JSON tree, plus maximum length of JSON string.
In the DOM API, each `Value` consumes exactly 16/24 bytes for 32/64-bit architecture respectively. RapidJSON also uses a special memory allocator to minimize overhead of allocations.
5. What is the purpose of being high performance?
Some applications need to process very large JSON files. Some server-side applications need to process huge amount of JSONs. Being high performance can improve both latency and throuput. In a broad sense, it will also save energy.
Some applications need to process very large JSON files. Some server-side applications need to process huge amount of JSONs. Being high performance can improve both latency and throughput. In a broad sense, it will also save energy.
## Gossip
......
......@@ -18,7 +18,7 @@
4. RapidJSON 是免费的么?
是的,它在 MIT 特許條款下免费。它可用于商业软件。详情请参看 [license.txt](https://github.com/miloyip/rapidjson/blob/master/license.txt)
是的,它在 MIT 特許條款下免费。它可用于商业软件。详情请参看 [license.txt](https://github.com/Tencent/rapidjson/blob/master/license.txt)
5. RapidJSON 很小么?它有何依赖?
......@@ -44,7 +44,7 @@
10. RapidJSON 是如何被测试的?
RapidJSON 包含一组单元测试去执行自动测试。[Travis](https://travis-ci.org/miloyip/rapidjson/)(供 Linux 平台)及 [AppVeyor](https://ci.appveyor.com/project/miloyip/rapidjson/)(供 Windows 平台)会对所有修改进行编译及执行单元测试。在 Linux 下还会使用 Valgrind 去检测内存泄漏。
RapidJSON 包含一组单元测试去执行自动测试。[Travis](https://travis-ci.org/Tencent/rapidjson/)(供 Linux 平台)及 [AppVeyor](https://ci.appveyor.com/project/Tencent/rapidjson/)(供 Windows 平台)会对所有修改进行编译及执行单元测试。在 Linux 下还会使用 Valgrind 去检测内存泄漏。
11. RapidJSON 是否有完整的文档?
......@@ -70,7 +70,7 @@
3. RapidJSON 是否支持宽松的语法?
现时不支持。RapidJSON 只支持严格的标准格式。宽松语法现时在这 [issue](https://github.com/miloyip/rapidjson/issues/36) 中进行讨论。
现时不支持。RapidJSON 只支持严格的标准格式。宽松语法现时在这 [issue](https://github.com/Tencent/rapidjson/issues/36) 中进行讨论。
## DOM 与 SAX
......@@ -257,7 +257,7 @@
3. 什是是 SIMD?它如何用于 RapidJSON?
[SIMD](http://en.wikipedia.org/wiki/SIMD) 指令可以在现代 CPU 中执行并行运算。RapidJSON 支持了 Intel 的 SSE2/SSE4.2 去加速跳过空白字符。在解析含缩进的 JSON 时,这能提升性能。只要定义名为 `RAPIDJSON_SSE2``RAPIDJSON_SSE42` 的宏,就能启动这个功能。然而,若在不支持这些指令集的机器上执行这些可执行文件,会导致崩溃。
[SIMD](http://en.wikipedia.org/wiki/SIMD) 指令可以在现代 CPU 中执行并行运算。RapidJSON 支持使用 Intel 的 SSE2/SSE4.2 和 ARM 的 Neon 来加速对空白符、制表符、回车符和换行符的过滤处理。在解析含缩进的 JSON 时,这能提升性能。只要定义名为 `RAPIDJSON_SSE2``RAPIDJSON_SSE42``RAPIDJSON_NEON` 的宏,就能启动这个功能。然而,若在不支持这些指令集的机器上执行这些可执行文件,会导致崩溃。
4. 它会消耗许多内存么?
......
......@@ -29,7 +29,7 @@
* Single line (`// ...`) and multiple line (`/* ... */`) comments (`kParseCommentsFlag`).
* Trailing commas at the end of objects and arrays (`kParseTrailingCommasFlag`).
* `NaN`, `Inf`, `Infinity`, `-Inf` and `-Infinity` as `double` values (`kParseNanAndInfFlag`)
* [NPM compliant](http://github.com/miloyip/rapidjson/blob/master/doc/npm.md).
* [NPM compliant](http://github.com/Tencent/rapidjson/blob/master/doc/npm.md).
## Unicode
......
......@@ -29,7 +29,7 @@
* 单行(`// ...`)及多行(`/* ... */`) 注释 (`kParseCommentsFlag`)。
* 在对象和数组结束前含逗号 (`kParseTrailingCommasFlag`)。
* `NaN``Inf``Infinity``-Inf``-Infinity` 作为 `double` 值 (`kParseNanAndInfFlag`)
* [NPM 兼容](https://github.com/miloyip/rapidjson/blob/master/doc/npm.md).
* [NPM 兼容](https://github.com/Tencent/rapidjson/blob/master/doc/npm.md).
## Unicode
......
......@@ -28,7 +28,7 @@ Both SAX and DOM APIs depends on 3 additional concepts: `Allocator`, `Encoding`
## Data Layout {#DataLayout}
`Value` is a [variant type](http://en.wikipedia.org/wiki/Variant_type). In RapidJSON's context, an instance of `Value` can contain 1 of 6 JSON value types. This is possible by using `union`. Each `Value` contains two members: `union Data data_` and a`unsigned flags_`. The `flags_` indiciates the JSON type, and also additional information.
`Value` is a [variant type](http://en.wikipedia.org/wiki/Variant_type). In RapidJSON's context, an instance of `Value` can contain 1 of 6 JSON value types. This is possible by using `union`. Each `Value` contains two members: `union Data data_` and a`unsigned flags_`. The `flags_` indicates the JSON type, and also additional information.
The following tables show the data layout of each type. The 32-bit/64-bit columns indicates the size of the field in bytes.
......@@ -101,7 +101,7 @@ The following tables show the data layout of each type. The 32-bit/64-bit column
Here are some notes:
* To reduce memory consumption for 64-bit architecture, `SizeType` is typedef as `unsigned` instead of `size_t`.
* Zero padding for 32-bit number may be placed after or before the actual type, according to the endianess. This makes possible for interpreting a 32-bit integer as a 64-bit integer, without any conversion.
* Zero padding for 32-bit number may be placed after or before the actual type, according to the endianness. This makes possible for interpreting a 32-bit integer as a 64-bit integer, without any conversion.
* An `Int` is always an `Int64`, but the converse is not always true.
## Flags {#Flags}
......@@ -183,17 +183,20 @@ void SkipWhitespace(InputStream& s) {
However, this requires 4 comparisons and a few branching for each character. This was found to be a hot spot.
To accelerate this process, SIMD was applied to compare 16 characters with 4 white spaces for each iteration. Currently RapidJSON only supports SSE2 and SSE4.2 instructions for this. And it is only activated for UTF-8 memory streams, including string stream or *in situ* parsing.
To accelerate this process, SIMD was applied to compare 16 characters with 4 white spaces for each iteration. Currently RapidJSON supports SSE2, SSE4.2 and ARM Neon instructions for this. And it is only activated for UTF-8 memory streams, including string stream or *in situ* parsing.
To enable this optimization, need to define `RAPIDJSON_SSE2` or `RAPIDJSON_SSE42` before including `rapidjson.h`. Some compilers can detect the setting, as in `perftest.h`:
To enable this optimization, need to define `RAPIDJSON_SSE2`, `RAPIDJSON_SSE42` or `RAPIDJSON_NEON` before including `rapidjson.h`. Some compilers can detect the setting, as in `perftest.h`:
~~~cpp
// __SSE2__ and __SSE4_2__ are recognized by gcc, clang, and the Intel compiler.
// We use -march=native with gmake to enable -msse2 and -msse4.2, if supported.
// Likewise, __ARM_NEON is used to detect Neon.
#if defined(__SSE4_2__)
# define RAPIDJSON_SSE42
#elif defined(__SSE2__)
# define RAPIDJSON_SSE2
#elif defined(__ARM_NEON)
# define RAPIDJSON_NEON
#endif
~~~
......@@ -211,7 +214,7 @@ In [Intel® 64 and IA-32 Architectures Optimization Reference Manual
This is not feasible as RapidJSON should not enforce such requirement.
To fix this issue, currently the routine process bytes up to the next aligned address. After tha, use aligned read to perform SIMD processing. Also see [#85](https://github.com/miloyip/rapidjson/issues/85).
To fix this issue, currently the routine process bytes up to the next aligned address. After tha, use aligned read to perform SIMD processing. Also see [#85](https://github.com/Tencent/rapidjson/issues/85).
## Local Stream Copy {#LocalStreamCopy}
......
......@@ -183,17 +183,20 @@ void SkipWhitespace(InputStream& s) {
但是,这需要对每个字符进行4次比较以及一些分支。这被发现是一个热点。
为了加速这一处理,RapidJSON 使用 SIMD 来在一次迭代中比较16个字符和4个空格。目前 RapidJSON 只支持 SSE2 和 SSE4.2 指令。同时它也只会对 UTF-8 内存流启用,包括字符串流或 *原位* 解析。
为了加速这一处理,RapidJSON 使用 SIMD 来在一次迭代中比较16个字符和4个空格。目前 RapidJSON 支持 SSE2 , SSE4.2 和 ARM Neon 指令。同时它也只会对 UTF-8 内存流启用,包括字符串流或 *原位* 解析。
你可以通过在包含 `rapidjson.h` 之前定义 `RAPIDJSON_SSE2` `RAPIDJSON_SSE42` 来启用这个优化。一些编译器可以检测这个设置,如 `perftest.h`
你可以通过在包含 `rapidjson.h` 之前定义 `RAPIDJSON_SSE2` `RAPIDJSON_SSE42``RAPIDJSON_NEON` 来启用这个优化。一些编译器可以检测这个设置,如 `perftest.h`
~~~cpp
// __SSE2__ 和 __SSE4_2__ 可被 gcc、clang 和 Intel 编译器识别:
// 如果支持的话,我们在 gmake 中使用了 -march=native 来启用 -msse2 和 -msse4.2
// 同样的, __ARM_NEON 被用于识别Neon
#if defined(__SSE4_2__)
# define RAPIDJSON_SSE42
#elif defined(__SSE2__)
# define RAPIDJSON_SSE2
#elif defined(__ARM_NEON)
# define RAPIDJSON_NEON
#endif
~~~
......@@ -211,7 +214,7 @@ void SkipWhitespace(InputStream& s) {
对于 RapidJSON 来说,这显然是不可行的,因为 RapidJSON 不应当强迫用户进行内存对齐。
为了修复这个问题,当前的代码会先按字节处理直到下一个对齐的地址。在这之后,使用对齐读取来进行 SIMD 处理。见 [#85](https://github.com/miloyip/rapidjson/issues/85)
为了修复这个问题,当前的代码会先按字节处理直到下一个对齐的地址。在这之后,使用对齐读取来进行 SIMD 处理。见 [#85](https://github.com/Tencent/rapidjson/issues/85)
## 局部流拷贝 {#LocalStreamCopy}
......
......@@ -18,7 +18,7 @@ $extrastylesheet
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="topbanner"><a href="https://github.com/miloyip/rapidjson" title="RapidJSON GitHub"><i class="githublogo"></i></a></div>
<div id="topbanner"><a href="https://github.com/Tencent/rapidjson" title="RapidJSON GitHub"><i class="githublogo"></i></a></div>
$searchbox
<!--END TITLEAREA-->
<!-- end header part -->
......@@ -7,7 +7,7 @@
...
"dependencies": {
...
"rapidjson": "git@github.com:miloyip/rapidjson.git"
"rapidjson": "git@github.com:Tencent/rapidjson.git"
},
...
"gypfile": true
......
# Performance
There is a [native JSON benchmark collection] [1] which evaluates speed, memory usage and code size of various operations among 37 JSON libaries.
There is a [native JSON benchmark collection] [1] which evaluates speed, memory usage and code size of various operations among 37 JSON libraries.
[1]: https://github.com/miloyip/nativejson-benchmark
......@@ -15,12 +15,12 @@ Additionally, you may refer to the following third-party benchmarks.
* [json_spirit](https://github.com/cierelabs/json_spirit)
* [jsoncpp](http://jsoncpp.sourceforge.net/)
* [libjson](http://sourceforge.net/projects/libjson/)
* [rapidjson](https://github.com/miloyip/rapidjson/)
* [rapidjson](https://github.com/Tencent/rapidjson/)
* [QJsonDocument](http://qt-project.org/doc/qt-5.0/qtcore/qjsondocument.html)
* [JSON Parser Benchmarking](http://chadaustin.me/2013/01/json-parser-benchmarking/) by Chad Austin (Jan 2013)
* [sajson](https://github.com/chadaustin/sajson)
* [rapidjson](https://github.com/miloyip/rapidjson/)
* [rapidjson](https://github.com/Tencent/rapidjson/)
* [vjson](https://code.google.com/p/vjson/)
* [YAJL](http://lloyd.github.com/yajl/)
* [Jansson](http://www.digip.org/jansson/)
......@@ -15,12 +15,12 @@ RapidJSON 0.1 版本的性能测试文章位于 [这里](https://code.google.com
* [json_spirit](https://github.com/cierelabs/json_spirit)
* [jsoncpp](http://jsoncpp.sourceforge.net/)
* [libjson](http://sourceforge.net/projects/libjson/)
* [rapidjson](https://github.com/miloyip/rapidjson/)
* [rapidjson](https://github.com/Tencent/rapidjson/)
* [QJsonDocument](http://qt-project.org/doc/qt-5.0/qtcore/qjsondocument.html)
* [JSON Parser Benchmarking](http://chadaustin.me/2013/01/json-parser-benchmarking/) by Chad Austin (Jan 2013)
* [sajson](https://github.com/chadaustin/sajson)
* [rapidjson](https://github.com/miloyip/rapidjson/)
* [rapidjson](https://github.com/Tencent/rapidjson/)
* [vjson](https://code.google.com/p/vjson/)
* [YAJL](http://lloyd.github.com/yajl/)
* [Jansson](http://www.digip.org/jansson/)
......@@ -211,7 +211,7 @@ p.Stringify(sb);
std::cout << sb.GetString() << std::endl;
~~~
It can also stringify to URI fragment reprsentation by `StringifyUriFragment()`.
It can also stringify to URI fragment representation by `StringifyUriFragment()`.
# User-Supplied Tokens {#UserSuppliedTokens}
......
......@@ -126,7 +126,7 @@ When the `Reader` encounters a JSON number, it chooses a suitable C++ type mappi
When the `Reader` encounters the beginning of an object, it calls `StartObject()`. An object in JSON is a set of name-value pairs. If the object contains members it first calls `Key()` for the name of member, and then calls functions depending on the type of the value. These calls of name-value pairs repeat until calling `EndObject(SizeType memberCount)`. Note that the `memberCount` parameter is just an aid for the handler; users who do not need this parameter may ignore it.
Arrays are similar to objects, but simpler. At the beginning of an array, the `Reader` calls `BeginArary()`. If there is elements, it calls functions according to the types of element. Similarly, in the last call `EndArray(SizeType elementCount)`, the parameter `elementCount` is just an aid for the handler.
Arrays are similar to objects, but simpler. At the beginning of an array, the `Reader` calls `BeginArray()`. If there is elements, it calls functions according to the types of element. Similarly, in the last call `EndArray(SizeType elementCount)`, the parameter `elementCount` is just an aid for the handler.
Every handler function returns a `bool`. Normally it should return `true`. If the handler encounters an error, it can return `false` to notify the event publisher to stop further processing.
......
This diff is collapsed.
......@@ -8,7 +8,7 @@ RapidJSON 实现了一个 [JSON Schema Draft v4](http://json-schema.org/document
[TOC]
## 基本用法
# 基本用法 {#BasicUsage}
首先,你要把 JSON Schema 解析成 `Document`,再把它编译成一个 `SchemaDocument`
......@@ -20,7 +20,7 @@ RapidJSON 实现了一个 [JSON Schema Draft v4](http://json-schema.org/document
// ...
Document sd;
if (!sd.Parse(schemaJson).HasParseError()) {
if (sd.Parse(schemaJson).HasParseError()) {
// 此 schema 不是合法的 JSON
// ...
}
......@@ -28,7 +28,7 @@ SchemaDocument schema(sd); // 把一个 Document 编译至 SchemaDocument
// 之后不再需要 sd
Document d;
if (!d.Parse(inputJson).HasParseError()) {
if (d.Parse(inputJson).HasParseError()) {
// 输入不是一个合法的 JSON
// ...
}
......@@ -52,11 +52,11 @@ if (!d.Accept(validator)) {
* 一个 `SchemaDocment` 能被多个 `SchemaValidator` 引用。它不会被 `SchemaValidator` 修改。
* 可以重复使用一个 `SchemaValidator` 来校验多个文件。在校验其他文件前,须先调用 `validator.Reset()`
## 在解析/生成时进行校验
# 在解析/生成时进行校验 {#ParsingSerialization}
与大部分 JSON Schema 校验器有所不同,RapidJSON 提供了一个基于 SAX 的 schema 校验器实现。因此,你可以在输入流解析 JSON 的同时进行校验。若校验器遇到一个与 schema 不符的值,就会立即终止解析。这设计对于解析大型 JSON 文件时特别有用。
### DOM 解析
## DOM 解析 {#DomParsing}
在使用 DOM 进行解析时,`Document` 除了接收 SAX 事件外,还需做一些准备及结束工作,因此,为了连接 `Reader``SchemaValidator``Document` 要做多一点事情。`SchemaValidatingReader` 是一个辅助类去做那些工作。
......@@ -97,7 +97,7 @@ if (!reader.GetParseResult()) {
}
~~~
### SAX 解析
## SAX 解析 {#SaxParsing}
使用 SAX 解析时,情况就简单得多。若只需要校验 JSON 而无需进一步处理,那么仅需要:
......@@ -126,7 +126,7 @@ if (!reader.Parse(ss, validator)) {
}
~~~
### 生成
## 生成 {#Serialization}
我们也可以在生成(serialization)的时候进行校验。这能确保输出的 JSON 符合一个 JSON Schema。
......@@ -144,7 +144,7 @@ if (!d.Accept(validator)) {
当然,如果你的应用仅需要 SAX 风格的生成,那么只需要把 SAX 事件由原来发送到 `Writer`,改为发送到 `SchemaValidator`
## 远程 Schema
# 远程 Schema {#RemoteSchema}
JSON Schema 支持 [`$ref` 关键字](http://spacetelescope.github.io/understanding-json-schema/structuring.html),它是一个 [JSON pointer](doc/pointer.zh-cn.md) 引用至一个本地(local)或远程(remote) schema。本地指针的首字符是 `#`,而远程指针是一个相对或绝对 URI。例如:
......@@ -168,7 +168,7 @@ MyRemoteSchemaDocumentProvider provider;
SchemaDocument schema(sd, &provider);
~~~
## 标准的符合程度
# 标准的符合程度 {#Conformance}
RapidJSON 通过了 [JSON Schema Test Suite](https://github.com/json-schema/JSON-Schema-Test-Suite) (Json Schema draft 4) 中 263 个测试的 262 个。
......@@ -176,7 +176,7 @@ RapidJSON 通过了 [JSON Schema Test Suite](https://github.com/json-schema/JSON
除此以外,关于字符串类型的 `format` schema 关键字也会被忽略,因为标准中并没需求必须实现。
### 正则表达式
## 正则表达式 {#RegEx}
`pattern``patternProperties` 这两个 schema 关键字使用了正则表达式去匹配所需的模式。
......@@ -211,7 +211,7 @@ RapidJSON 实现了一个简单的 NFA 正则表达式引擎,并预设使用
对于使用 C++11 编译器的使用者,也可使用 `std::regex`,只需定义 `RAPIDJSON_SCHEMA_USE_INTERNALREGEX=0``RAPIDJSON_SCHEMA_USE_STDREGEX=1`。若你的 schema 无需使用 `pattern``patternProperties`,可以把两个宏都设为零,以禁用此功能,这样做可节省一些代码体积。
## 性能
# 性能 {#Performance}
大部分 C++ JSON 库都未支持 JSON Schema。因此我们尝试按照 [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) 去评估 RapidJSON 的 JSON Schema 校验器。该评测测试了 11 个运行在 node.js 上的 JavaScript 库。
......
......@@ -42,6 +42,7 @@ Note that, `StringStream` is a typedef of `GenericStringStream<UTF8<> >`, user m
~~~~~~~~~~cpp
#include "rapidjson/stringbuffer.h"
#include <rapidjson/writer.h>
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
......@@ -98,6 +99,7 @@ Apart from reading file, user can also use `FileReadStream` to read `stdin`.
~~~~~~~~~~cpp
#include "rapidjson/filewritestream.h"
#include <rapidjson/writer.h>
#include <cstdio>
using namespace rapidjson;
......@@ -215,6 +217,7 @@ fclose(fp);
~~~~~~~~~~cpp
#include "rapidjson/filewritestream.h" // FileWriteStream
#include "rapidjson/encodedstream.h" // EncodedOutputStream
#include <rapidjson/writer.h>
#include <cstdio>
Document d; // Document is GenericDocument<UTF8<> >
......
......@@ -42,6 +42,7 @@ d.Parse(json);
~~~~~~~~~~cpp
#include "rapidjson/stringbuffer.h"
#include <rapidjson/writer.h>
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
......@@ -98,6 +99,7 @@ fclose(fp);
~~~~~~~~~~cpp
#include "rapidjson/filewritestream.h"
#include <rapidjson/writer.h>
#include <cstdio>
using namespace rapidjson;
......@@ -215,6 +217,7 @@ fclose(fp);
~~~~~~~~~~cpp
#include "rapidjson/filewritestream.h" // FileWriteStream
#include "rapidjson/encodedstream.h" // EncodedOutputStream
#include <rapidjson/writer.h>
#include <cstdio>
Document d; // Document 为 GenericDocument<UTF8<> >
......
This diff is collapsed.
......@@ -343,7 +343,7 @@ Value o(kObjectType);
![转移语义不需复制。](diagram/move3.png)
在 C++11 中这称为转移赋值操作(move assignment operator)。由于 RapidJSON 支持 C++03,它在赋值操作采用转移语义,其它修改函数如 `AddMember()`, `PushBack()` 也采用转移语义。
在 C++11 中这称为转移赋值操作(move assignment operator)。由于 RapidJSON 支持 C++03,它在赋值操作采用转移语义,其它修改函数如 `AddMember()`, `PushBack()` 也采用转移语义。
### 转移语义及临时值 {#TemporaryValues}
......
......@@ -32,6 +32,8 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
endif()
add_executable(archivertest archiver/archiver.cpp archiver/archivertest.cpp)
foreach (example ${EXAMPLES})
add_executable(${example} ${example}/${example}.cpp)
endforeach()
......
#include "archiver.h"
#include <cassert>
#include <stack>
#include "rapidjson/document.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/stringbuffer.h"
using namespace rapidjson;
struct JsonReaderStackItem {
enum State {
BeforeStart, //!< An object/array is in the stack but it is not yet called by StartObject()/StartArray().
Started, //!< An object/array is called by StartObject()/StartArray().
Closed //!< An array is closed after read all element, but before EndArray().
};
JsonReaderStackItem(const Value* value, State state) : value(value), state(state), index() {}
const Value* value;
State state;
SizeType index; // For array iteration
};
typedef std::stack<JsonReaderStackItem> JsonReaderStack;
#define DOCUMENT reinterpret_cast<Document*>(mDocument)
#define STACK (reinterpret_cast<JsonReaderStack*>(mStack))
#define TOP (STACK->top())
#define CURRENT (*TOP.value)
JsonReader::JsonReader(const char* json) : mDocument(), mStack(), mError(false) {
mDocument = new Document;
DOCUMENT->Parse(json);
if (DOCUMENT->HasParseError())
mError = true;
else {
mStack = new JsonReaderStack;
STACK->push(JsonReaderStackItem(DOCUMENT, JsonReaderStackItem::BeforeStart));
}
}
JsonReader::~JsonReader() {
delete DOCUMENT;
delete STACK;
}
// Archive concept
JsonReader& JsonReader::StartObject() {
if (!mError) {
if (CURRENT.IsObject() && TOP.state == JsonReaderStackItem::BeforeStart)
TOP.state = JsonReaderStackItem::Started;
else
mError = true;
}
return *this;
}
JsonReader& JsonReader::EndObject() {
if (!mError) {
if (CURRENT.IsObject() && TOP.state == JsonReaderStackItem::Started)
Next();
else
mError = true;
}
return *this;
}
JsonReader& JsonReader::Member(const char* name) {
if (!mError) {
if (CURRENT.IsObject() && TOP.state == JsonReaderStackItem::Started) {
Value::ConstMemberIterator memberItr = CURRENT.FindMember(name);
if (memberItr != CURRENT.MemberEnd())
STACK->push(JsonReaderStackItem(&memberItr->value, JsonReaderStackItem::BeforeStart));
else
mError = true;
}
else
mError = true;
}
return *this;
}
bool JsonReader::HasMember(const char* name) const {
if (!mError && CURRENT.IsObject() && TOP.state == JsonReaderStackItem::Started)
return CURRENT.HasMember(name);
return false;
}
JsonReader& JsonReader::StartArray(size_t* size) {
if (!mError) {
if (CURRENT.IsArray() && TOP.state == JsonReaderStackItem::BeforeStart) {
TOP.state = JsonReaderStackItem::Started;
if (size)
*size = CURRENT.Size();
if (!CURRENT.Empty()) {
const Value* value = &CURRENT[TOP.index];
STACK->push(JsonReaderStackItem(value, JsonReaderStackItem::BeforeStart));
}
else
TOP.state = JsonReaderStackItem::Closed;
}
else
mError = true;
}
return *this;
}
JsonReader& JsonReader::EndArray() {
if (!mError) {
if (CURRENT.IsArray() && TOP.state == JsonReaderStackItem::Closed)
Next();
else
mError = true;
}
return *this;
}
JsonReader& JsonReader::operator&(bool& b) {
if (!mError) {
if (CURRENT.IsBool()) {
b = CURRENT.GetBool();
Next();
}
else
mError = true;
}
return *this;
}
JsonReader& JsonReader::operator&(unsigned& u) {
if (!mError) {
if (CURRENT.IsUint()) {
u = CURRENT.GetUint();
Next();
}
else
mError = true;
}
return *this;
}
JsonReader& JsonReader::operator&(int& i) {
if (!mError) {
if (CURRENT.IsInt()) {
i = CURRENT.GetInt();
Next();
}
else
mError = true;
}
return *this;
}
JsonReader& JsonReader::operator&(double& d) {
if (!mError) {
if (CURRENT.IsNumber()) {
d = CURRENT.GetDouble();
Next();
}
else
mError = true;
}
return *this;
}
JsonReader& JsonReader::operator&(std::string& s) {
if (!mError) {
if (CURRENT.IsString()) {
s = CURRENT.GetString();
Next();
}
else
mError = true;
}
return *this;
}
JsonReader& JsonReader::SetNull() {
// This function is for JsonWriter only.
mError = true;
return *this;
}
void JsonReader::Next() {
if (!mError) {
assert(!STACK->empty());
STACK->pop();
if (!STACK->empty() && CURRENT.IsArray()) {
if (TOP.state == JsonReaderStackItem::Started) { // Otherwise means reading array item pass end
if (TOP.index < CURRENT.Size() - 1) {
const Value* value = &CURRENT[++TOP.index];
STACK->push(JsonReaderStackItem(value, JsonReaderStackItem::BeforeStart));
}
else
TOP.state = JsonReaderStackItem::Closed;
}
else
mError = true;
}
}
}
#undef DOCUMENT
#undef STACK
#undef TOP
#undef CURRENT
////////////////////////////////////////////////////////////////////////////////
// JsonWriter
#define WRITER reinterpret_cast<PrettyWriter<StringBuffer>*>(mWriter)
#define STREAM reinterpret_cast<StringBuffer*>(mStream)
JsonWriter::JsonWriter() : mWriter(), mStream() {
mStream = new StringBuffer;
mWriter = new PrettyWriter<StringBuffer>(*STREAM);
}
JsonWriter::~JsonWriter() {
delete WRITER;
delete STREAM;
}
const char* JsonWriter::GetString() const {
return STREAM->GetString();
}
JsonWriter& JsonWriter::StartObject() {
WRITER->StartObject();
return *this;
}
JsonWriter& JsonWriter::EndObject() {
WRITER->EndObject();
return *this;
}
JsonWriter& JsonWriter::Member(const char* name) {
WRITER->String(name, static_cast<SizeType>(strlen(name)));
return *this;
}
bool JsonWriter::HasMember(const char*) const {
// This function is for JsonReader only.
assert(false);
return false;
}
JsonWriter& JsonWriter::StartArray(size_t*) {
WRITER->StartArray();
return *this;
}
JsonWriter& JsonWriter::EndArray() {
WRITER->EndArray();
return *this;
}
JsonWriter& JsonWriter::operator&(bool& b) {
WRITER->Bool(b);
return *this;
}
JsonWriter& JsonWriter::operator&(unsigned& u) {
WRITER->Uint(u);
return *this;
}
JsonWriter& JsonWriter::operator&(int& i) {
WRITER->Int(i);
return *this;
}
JsonWriter& JsonWriter::operator&(double& d) {
WRITER->Double(d);
return *this;
}
JsonWriter& JsonWriter::operator&(std::string& s) {
WRITER->String(s.c_str(), static_cast<SizeType>(s.size()));
return *this;
}
JsonWriter& JsonWriter::SetNull() {
WRITER->Null();
return *this;
}
#undef STREAM
#undef WRITER
#ifndef ARCHIVER_H_
#define ARCHIVER_H_
#include <cstddef>
#include <string>
/**
\class Archiver
\brief Archiver concept
Archiver can be a reader or writer for serialization or deserialization respectively.
class Archiver {
public:
/// \returns true if the archiver is in normal state. false if it has errors.
operator bool() const;
/// Starts an object
Archiver& StartObject();
/// After calling StartObject(), assign a member with a name
Archiver& Member(const char* name);
/// After calling StartObject(), check if a member presents
bool HasMember(const char* name) const;
/// Ends an object
Archiver& EndObject();
/// Starts an array
/// \param size If Archiver::IsReader is true, the size of array is written.
Archiver& StartArray(size_t* size = 0);
/// Ends an array
Archiver& EndArray();
/// Read/Write primitive types.
Archiver& operator&(bool& b);
Archiver& operator&(unsigned& u);
Archiver& operator&(int& i);
Archiver& operator&(double& d);
Archiver& operator&(std::string& s);
/// Write primitive types.
Archiver& SetNull();
//! Whether it is a reader.
static const bool IsReader;
//! Whether it is a writer.
static const bool IsWriter;
};
*/
/// Represents a JSON reader which implements Archiver concept.
class JsonReader {
public:
/// Constructor.
/**
\param json A non-const source json string for in-situ parsing.
\note in-situ means the source JSON string will be modified after parsing.
*/
JsonReader(const char* json);
/// Destructor.
~JsonReader();
// Archive concept
operator bool() const { return !mError; }
JsonReader& StartObject();
JsonReader& Member(const char* name);
bool HasMember(const char* name) const;
JsonReader& EndObject();
JsonReader& StartArray(size_t* size = 0);
JsonReader& EndArray();
JsonReader& operator&(bool& b);
JsonReader& operator&(unsigned& u);
JsonReader& operator&(int& i);
JsonReader& operator&(double& d);
JsonReader& operator&(std::string& s);
JsonReader& SetNull();
static const bool IsReader = true;
static const bool IsWriter = !IsReader;
private:
JsonReader(const JsonReader&);
JsonReader& operator=(const JsonReader&);
void Next();
// PIMPL
void* mDocument; ///< DOM result of parsing.
void* mStack; ///< Stack for iterating the DOM
bool mError; ///< Whether an error has occurred.
};
class JsonWriter {
public:
/// Constructor.
JsonWriter();
/// Destructor.
~JsonWriter();
/// Obtains the serialized JSON string.
const char* GetString() const;
// Archive concept
operator bool() const { return true; }
JsonWriter& StartObject();
JsonWriter& Member(const char* name);
bool HasMember(const char* name) const;
JsonWriter& EndObject();
JsonWriter& StartArray(size_t* size = 0);
JsonWriter& EndArray();
JsonWriter& operator&(bool& b);
JsonWriter& operator&(unsigned& u);
JsonWriter& operator&(int& i);
JsonWriter& operator&(double& d);
JsonWriter& operator&(std::string& s);
JsonWriter& SetNull();
static const bool IsReader = false;
static const bool IsWriter = !IsReader;
private:
JsonWriter(const JsonWriter&);
JsonWriter& operator=(const JsonWriter&);
// PIMPL idiom
void* mWriter; ///< JSON writer.
void* mStream; ///< Stream buffer.
};
#endif // ARCHIVER_H__
#include "archiver.h"
#include <iostream>
#include <vector>
//////////////////////////////////////////////////////////////////////////////
// Test1: simple object
struct Student {
Student() : name(), age(), height(), canSwim() {}
Student(const std::string name, unsigned age, double height, bool canSwim) :
name(name), age(age), height(height), canSwim(canSwim)
{}
std::string name;
unsigned age;
double height;
bool canSwim;
};
template <typename Archiver>
Archiver& operator&(Archiver& ar, Student& s) {
ar.StartObject();
ar.Member("name") & s.name;
ar.Member("age") & s.age;
ar.Member("height") & s.height;
ar.Member("canSwim") & s.canSwim;
return ar.EndObject();
}
std::ostream& operator<<(std::ostream& os, const Student& s) {
return os << s.name << " " << s.age << " " << s.height << " " << s.canSwim;
}
void test1() {
std::string json;
// Serialize
{
Student s("Lua", 9, 150.5, true);
JsonWriter writer;
writer & s;
json = writer.GetString();
std::cout << json << std::endl;
}
// Deserialize
{
Student s;
JsonReader reader(json.c_str());
reader & s;
std::cout << s << std::endl;
}
}
//////////////////////////////////////////////////////////////////////////////
// Test2: std::vector <=> JSON array
//
// You can map a JSON array to other data structures as well
struct Group {
Group() : groupName(), students() {}
std::string groupName;
std::vector<Student> students;
};
template <typename Archiver>
Archiver& operator&(Archiver& ar, Group& g) {
ar.StartObject();
ar.Member("groupName");
ar & g.groupName;
ar.Member("students");
size_t studentCount = g.students.size();
ar.StartArray(&studentCount);
if (ar.IsReader)
g.students.resize(studentCount);
for (size_t i = 0; i < studentCount; i++)
ar & g.students[i];
ar.EndArray();
return ar.EndObject();
}
std::ostream& operator<<(std::ostream& os, const Group& g) {
os << g.groupName << std::endl;
for (std::vector<Student>::const_iterator itr = g.students.begin(); itr != g.students.end(); ++itr)
os << *itr << std::endl;
return os;
}
void test2() {
std::string json;
// Serialize
{
Group g;
g.groupName = "Rainbow";
Student s1("Lua", 9, 150.5, true);
Student s2("Mio", 7, 120.0, false);
g.students.push_back(s1);
g.students.push_back(s2);
JsonWriter writer;
writer & g;
json = writer.GetString();
std::cout << json << std::endl;
}
// Deserialize
{
Group g;
JsonReader reader(json.c_str());
reader & g;
std::cout << g << std::endl;
}
}
//////////////////////////////////////////////////////////////////////////////
// Test3: polymorphism & friend
//
// Note that friendship is not necessary but make things simpler.
class Shape {
public:
virtual ~Shape() {}
virtual const char* GetType() const = 0;
virtual void Print(std::ostream& os) const = 0;
protected:
Shape() : x_(), y_() {}
Shape(double x, double y) : x_(x), y_(y) {}
template <typename Archiver>
friend Archiver& operator&(Archiver& ar, Shape& s);
double x_, y_;
};
template <typename Archiver>
Archiver& operator&(Archiver& ar, Shape& s) {
ar.Member("x") & s.x_;
ar.Member("y") & s.y_;
return ar;
}
class Circle : public Shape {
public:
Circle() : radius_() {}
Circle(double x, double y, double radius) : Shape(x, y), radius_(radius) {}
~Circle() {}
const char* GetType() const { return "Circle"; }
void Print(std::ostream& os) const {
os << "Circle (" << x_ << ", " << y_ << ")" << " radius = " << radius_;
}
private:
template <typename Archiver>
friend Archiver& operator&(Archiver& ar, Circle& c);
double radius_;
};
template <typename Archiver>
Archiver& operator&(Archiver& ar, Circle& c) {
ar & static_cast<Shape&>(c);
ar.Member("radius") & c.radius_;
return ar;
}
class Box : public Shape {
public:
Box() : width_(), height_() {}
Box(double x, double y, double width, double height) : Shape(x, y), width_(width), height_(height) {}
~Box() {}
const char* GetType() const { return "Box"; }
void Print(std::ostream& os) const {
os << "Box (" << x_ << ", " << y_ << ")" << " width = " << width_ << " height = " << height_;
}
private:
template <typename Archiver>
friend Archiver& operator&(Archiver& ar, Box& b);
double width_, height_;
};
template <typename Archiver>
Archiver& operator&(Archiver& ar, Box& b) {
ar & static_cast<Shape&>(b);
ar.Member("width") & b.width_;
ar.Member("height") & b.height_;
return ar;
}
class Canvas {
public:
Canvas() : shapes_() {}
~Canvas() { Clear(); }
void Clear() {
for (std::vector<Shape*>::iterator itr = shapes_.begin(); itr != shapes_.end(); ++itr)
delete *itr;
}
void AddShape(Shape* shape) { shapes_.push_back(shape); }
void Print(std::ostream& os) {
for (std::vector<Shape*>::iterator itr = shapes_.begin(); itr != shapes_.end(); ++itr) {
(*itr)->Print(os);
std::cout << std::endl;
}
}
private:
template <typename Archiver>
friend Archiver& operator&(Archiver& ar, Canvas& c);
std::vector<Shape*> shapes_;
};
template <typename Archiver>
Archiver& operator&(Archiver& ar, Shape*& shape) {
std::string type = ar.IsReader ? "" : shape->GetType();
ar.StartObject();
ar.Member("type") & type;
if (type == "Circle") {
if (ar.IsReader) shape = new Circle;
ar & static_cast<Circle&>(*shape);
}
else if (type == "Box") {
if (ar.IsReader) shape = new Box;
ar & static_cast<Box&>(*shape);
}
return ar.EndObject();
}
template <typename Archiver>
Archiver& operator&(Archiver& ar, Canvas& c) {
size_t shapeCount = c.shapes_.size();
ar.StartArray(&shapeCount);
if (ar.IsReader) {
c.Clear();
c.shapes_.resize(shapeCount);
}
for (size_t i = 0; i < shapeCount; i++)
ar & c.shapes_[i];
return ar.EndArray();
}
void test3() {
std::string json;
// Serialize
{
Canvas c;
c.AddShape(new Circle(1.0, 2.0, 3.0));
c.AddShape(new Box(4.0, 5.0, 6.0, 7.0));
JsonWriter writer;
writer & c;
json = writer.GetString();
std::cout << json << std::endl;
}
// Deserialize
{
Canvas c;
JsonReader reader(json.c_str());
reader & c;
c.Print(std::cout);
}
}
//////////////////////////////////////////////////////////////////////////////
int main() {
test1();
test2();
test3();
}
// JSON to JSONx conversion exmaple, using SAX API.
// JSON to JSONx conversion example, using SAX API.
// JSONx is an IBM standard format to represent JSON as XML.
// https://www-01.ibm.com/support/knowledgecenter/SS9H2Y_7.1.0/com.ibm.dp.doc/json_jsonx.html
// This example parses JSON text from stdin with validation,
......
......@@ -2,6 +2,11 @@
#include "rapidjson/document.h"
#include <iostream>
RAPIDJSON_DIAG_PUSH
#ifdef __GNUC__
RAPIDJSON_DIAG_OFF(effc++)
#endif
// This example demonstrates JSON token-by-token parsing with an API that is
// more direct; you don't need to design your logic around a handler object and
// callbacks. Instead, you retrieve values from the JSON stream by calling
......@@ -341,3 +346,5 @@ int main() {
return 0;
}
RAPIDJSON_DIAG_POP
......@@ -143,7 +143,7 @@ int main() {
AsyncDocumentParser<> parser(d);
const char json1[] = " { \"hello\" : \"world\", \"t\" : tr";
//const char json1[] = " { \"hello\" : \"world\", \"t\" : trX"; // Fot test parsing error
//const char json1[] = " { \"hello\" : \"world\", \"t\" : trX"; // For test parsing error
const char json2[] = "ue, \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.14";
const char json3[] = "16, \"a\":[1, 2, 3, 4] } ";
......
......@@ -6,6 +6,7 @@
#include "rapidjson/filereadstream.h"
#include "rapidjson/schema.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/prettywriter.h"
using namespace rapidjson;
......@@ -67,6 +68,11 @@ int main(int argc, char *argv[]) {
sb.Clear();
validator.GetInvalidDocumentPointer().StringifyUriFragment(sb);
fprintf(stderr, "Invalid document: %s\n", sb.GetString());
// Detailed violation report is available as a JSON value
sb.Clear();
PrettyWriter<StringBuffer> w(sb);
validator.GetError().Accept(w);
fprintf(stderr, "Error report:\n%s\n", sb.GetString());
return EXIT_FAILURE;
}
}
......@@ -52,6 +52,19 @@ concept Allocator {
\endcode
*/
/*! \def RAPIDJSON_ALLOCATOR_DEFUALT_CHUNK_CAPACITY
\ingroup RAPIDJSON_CONFIG
\brief User-defined kDefaultChunkCapacity definition.
User can define this as any \c size that is a power of 2.
*/
#ifndef RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY
#define RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY (64 * 1024)
#endif
///////////////////////////////////////////////////////////////////////////////
// CrtAllocator
......@@ -248,7 +261,7 @@ private:
return false;
}
static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.
static const int kDefaultChunkCapacity = RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY; //!< Default chunk capacity.
//! Chunk header for perpending to each chunk.
/*! Chunks are stored as a singly linked list.
......
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_CURSORSTREAMWRAPPER_H_
#define RAPIDJSON_CURSORSTREAMWRAPPER_H_
#include "stream.h"
#if defined(__GNUC__)
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
#endif
#if defined(_MSC_VER) && _MSC_VER <= 1800
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(4702) // unreachable code
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
#endif
RAPIDJSON_NAMESPACE_BEGIN
//! Cursor stream wrapper for counting line and column number if error exists.
/*!
\tparam InputStream Any stream that implements Stream Concept
*/
template <typename InputStream, typename Encoding = UTF8<> >
class CursorStreamWrapper : public GenericStreamWrapper<InputStream, Encoding> {
public:
typedef typename Encoding::Ch Ch;
CursorStreamWrapper(InputStream& is):
GenericStreamWrapper<InputStream, Encoding>(is), line_(1), col_(0) {}
// counting line and column number
Ch Take() {
Ch ch = this->is_.Take();
if(ch == '\n') {
line_ ++;
col_ = 0;
} else {
col_ ++;
}
return ch;
}
//! Get the error line number, if error exists.
size_t GetLine() const { return line_; }
//! Get the error column number, if error exists.
size_t GetColumn() const { return col_; }
private:
size_t line_; //!< Current Line
size_t col_; //!< Current Column
};
#if defined(_MSC_VER) && _MSC_VER <= 1800
RAPIDJSON_DIAG_POP
#endif
#if defined(__GNUC__)
RAPIDJSON_DIAG_POP
#endif
RAPIDJSON_NAMESPACE_END
#endif // RAPIDJSON_CURSORSTREAMWRAPPER_H_
This diff is collapsed.
......@@ -17,7 +17,7 @@
#include "rapidjson.h"
#ifdef _MSC_VER
#if defined(_MSC_VER) && !defined(__clang__)
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data
RAPIDJSON_DIAG_OFF(4702) // unreachable code
......@@ -384,7 +384,7 @@ struct UTF16BE : UTF16<CharType> {
static CharType Take(InputByteStream& is) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
c |= static_cast<uint8_t>(is.Take());
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take()));
return static_cast<CharType>(c);
}
......@@ -620,28 +620,28 @@ struct AutoUTF {
#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
template<typename OutputStream>
RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) {
static RAPIDJSON_FORCEINLINE void Encode(OutputStream& os, unsigned codepoint) {
typedef void (*EncodeFunc)(OutputStream&, unsigned);
static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) };
(*f[os.GetType()])(os, codepoint);
}
template<typename OutputStream>
RAPIDJSON_FORCEINLINE static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
static RAPIDJSON_FORCEINLINE void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
typedef void (*EncodeFunc)(OutputStream&, unsigned);
static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) };
(*f[os.GetType()])(os, codepoint);
}
template <typename InputStream>
RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) {
static RAPIDJSON_FORCEINLINE bool Decode(InputStream& is, unsigned* codepoint) {
typedef bool (*DecodeFunc)(InputStream&, unsigned*);
static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) };
return (*f[is.GetType()])(is, codepoint);
}
template <typename InputStream, typename OutputStream>
RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
typedef bool (*ValidateFunc)(InputStream&, OutputStream&);
static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) };
return (*f[is.GetType()])(is, os);
......@@ -658,7 +658,7 @@ template<typename SourceEncoding, typename TargetEncoding>
struct Transcoder {
//! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream.
template<typename InputStream, typename OutputStream>
RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) {
unsigned codepoint;
if (!SourceEncoding::Decode(is, &codepoint))
return false;
......@@ -667,7 +667,7 @@ struct Transcoder {
}
template<typename InputStream, typename OutputStream>
RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
unsigned codepoint;
if (!SourceEncoding::Decode(is, &codepoint))
return false;
......@@ -677,7 +677,7 @@ struct Transcoder {
//! Validate one Unicode codepoint from an encoded stream.
template<typename InputStream, typename OutputStream>
RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
return Transcode(is, os); // Since source/target encoding is different, must transcode.
}
};
......@@ -690,26 +690,26 @@ inline void PutUnsafe(Stream& stream, typename Stream::Ch c);
template<typename Encoding>
struct Transcoder<Encoding, Encoding> {
template<typename InputStream, typename OutputStream>
RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) {
os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class.
return true;
}
template<typename InputStream, typename OutputStream>
RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class.
return true;
}
template<typename InputStream, typename OutputStream>
RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
return Encoding::Validate(is, os); // source/target encoding are the same
}
};
RAPIDJSON_NAMESPACE_END
#if defined(__GNUC__) || defined(_MSC_VER)
#if defined(__GNUC__) || (defined(_MSC_VER) && !defined(__clang__))
RAPIDJSON_DIAG_POP
#endif
......
......@@ -104,6 +104,8 @@ enum ParseErrorCode {
\see GenericReader::Parse, GenericDocument::Parse
*/
struct ParseResult {
//!! Unspecified boolean type
typedef bool (ParseResult::*BooleanType)() const;
public:
//! Default constructor, no error.
ParseResult() : code_(kParseErrorNone), offset_(0) {}
......@@ -115,8 +117,8 @@ public:
//! Get the error offset, if \ref IsError(), 0 otherwise.
size_t Offset() const { return offset_; }
//! Conversion to \c bool, returns \c true, iff !\ref IsError().
operator bool() const { return !IsError(); }
//! Explicit conversion to \c bool, returns \c true, iff !\ref IsError().
operator BooleanType() const { return !IsError() ? &ParseResult::IsError : NULL; }
//! Whether the result is an error.
bool IsError() const { return code_ != kParseErrorNone; }
......@@ -124,6 +126,10 @@ public:
bool operator==(ParseErrorCode code) const { return code_ == code; }
friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; }
bool operator!=(const ParseResult& that) const { return !(*this == that); }
bool operator!=(ParseErrorCode code) const { return !(*this == code); }
friend bool operator!=(ParseErrorCode code, const ParseResult & err) { return err != code; }
//! Reset error code.
void Clear() { Set(kParseErrorNone); }
//! Update error code and offset.
......
......@@ -68,7 +68,7 @@ private:
++current_;
else if (!eof_) {
count_ += readCount_;
readCount_ = fread(buffer_, 1, bufferSize_, fp_);
readCount_ = std::fread(buffer_, 1, bufferSize_, fp_);
bufferLast_ = buffer_ + readCount_ - 1;
current_ = buffer_;
......
......@@ -25,7 +25,7 @@ RAPIDJSON_DIAG_OFF(unreachable-code)
RAPIDJSON_NAMESPACE_BEGIN
//! Wrapper of C file stream for input using fread().
//! Wrapper of C file stream for output using fwrite().
/*!
\note implements Stream concept
*/
......@@ -62,7 +62,7 @@ public:
void Flush() {
if (current_ != buffer_) {
size_t result = fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
size_t result = std::fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
if (result < static_cast<size_t>(current_ - buffer_)) {
// failure deliberately ignored at this time
// added to avoid warn_unused_result build errors
......
......@@ -17,7 +17,7 @@
#include "../rapidjson.h"
#if defined(_MSC_VER) && defined(_M_AMD64)
#if defined(_MSC_VER) && !__INTEL_COMPILER && defined(_M_AMD64)
#include <intrin.h> // for _umul128
#pragma intrinsic(_umul128)
#endif
......
......@@ -21,7 +21,7 @@
#include "../rapidjson.h"
#if defined(_MSC_VER) && defined(_M_AMD64)
#if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER)
#include <intrin.h>
#pragma intrinsic(_BitScanReverse64)
#pragma intrinsic(_umul128)
......
// Tencent is pleased to support the open source community by making RapidJSON available.
//
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
......@@ -7,9 +7,9 @@
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_ITOA_
......@@ -37,12 +37,14 @@ inline const char* GetDigitsLut() {
}
inline char* u32toa(uint32_t value, char* buffer) {
RAPIDJSON_ASSERT(buffer != 0);
const char* cDigitsLut = GetDigitsLut();
if (value < 10000) {
const uint32_t d1 = (value / 100) << 1;
const uint32_t d2 = (value % 100) << 1;
if (value >= 1000)
*buffer++ = cDigitsLut[d1];
if (value >= 100)
......@@ -55,13 +57,13 @@ inline char* u32toa(uint32_t value, char* buffer) {
// value = bbbbcccc
const uint32_t b = value / 10000;
const uint32_t c = value % 10000;
const uint32_t d1 = (b / 100) << 1;
const uint32_t d2 = (b % 100) << 1;
const uint32_t d3 = (c / 100) << 1;
const uint32_t d4 = (c % 100) << 1;
if (value >= 10000000)
*buffer++ = cDigitsLut[d1];
if (value >= 1000000)
......@@ -69,7 +71,7 @@ inline char* u32toa(uint32_t value, char* buffer) {
if (value >= 100000)
*buffer++ = cDigitsLut[d2];
*buffer++ = cDigitsLut[d2 + 1];
*buffer++ = cDigitsLut[d3];
*buffer++ = cDigitsLut[d3 + 1];
*buffer++ = cDigitsLut[d4];
......@@ -77,10 +79,10 @@ inline char* u32toa(uint32_t value, char* buffer) {
}
else {
// value = aabbbbcccc in decimal
const uint32_t a = value / 100000000; // 1 to 42
value %= 100000000;
if (a >= 10) {
const unsigned i = a << 1;
*buffer++ = cDigitsLut[i];
......@@ -91,13 +93,13 @@ inline char* u32toa(uint32_t value, char* buffer) {
const uint32_t b = value / 10000; // 0 to 9999
const uint32_t c = value % 10000; // 0 to 9999
const uint32_t d1 = (b / 100) << 1;
const uint32_t d2 = (b % 100) << 1;
const uint32_t d3 = (c / 100) << 1;
const uint32_t d4 = (c % 100) << 1;
*buffer++ = cDigitsLut[d1];
*buffer++ = cDigitsLut[d1 + 1];
*buffer++ = cDigitsLut[d2];
......@@ -111,6 +113,7 @@ inline char* u32toa(uint32_t value, char* buffer) {
}
inline char* i32toa(int32_t value, char* buffer) {
RAPIDJSON_ASSERT(buffer != 0);
uint32_t u = static_cast<uint32_t>(value);
if (value < 0) {
*buffer++ = '-';
......@@ -121,6 +124,7 @@ inline char* i32toa(int32_t value, char* buffer) {
}
inline char* u64toa(uint64_t value, char* buffer) {
RAPIDJSON_ASSERT(buffer != 0);
const char* cDigitsLut = GetDigitsLut();
const uint64_t kTen8 = 100000000;
const uint64_t kTen9 = kTen8 * 10;
......@@ -131,13 +135,13 @@ inline char* u64toa(uint64_t value, char* buffer) {
const uint64_t kTen14 = kTen8 * 1000000;
const uint64_t kTen15 = kTen8 * 10000000;
const uint64_t kTen16 = kTen8 * kTen8;
if (value < kTen8) {
uint32_t v = static_cast<uint32_t>(value);
if (v < 10000) {
const uint32_t d1 = (v / 100) << 1;
const uint32_t d2 = (v % 100) << 1;
if (v >= 1000)
*buffer++ = cDigitsLut[d1];
if (v >= 100)
......@@ -150,13 +154,13 @@ inline char* u64toa(uint64_t value, char* buffer) {
// value = bbbbcccc
const uint32_t b = v / 10000;
const uint32_t c = v % 10000;
const uint32_t d1 = (b / 100) << 1;
const uint32_t d2 = (b % 100) << 1;
const uint32_t d3 = (c / 100) << 1;
const uint32_t d4 = (c % 100) << 1;
if (value >= 10000000)
*buffer++ = cDigitsLut[d1];
if (value >= 1000000)
......@@ -164,7 +168,7 @@ inline char* u64toa(uint64_t value, char* buffer) {
if (value >= 100000)
*buffer++ = cDigitsLut[d2];
*buffer++ = cDigitsLut[d2 + 1];
*buffer++ = cDigitsLut[d3];
*buffer++ = cDigitsLut[d3 + 1];
*buffer++ = cDigitsLut[d4];
......@@ -174,22 +178,22 @@ inline char* u64toa(uint64_t value, char* buffer) {
else if (value < kTen16) {
const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
const uint32_t b0 = v0 / 10000;
const uint32_t c0 = v0 % 10000;
const uint32_t d1 = (b0 / 100) << 1;
const uint32_t d2 = (b0 % 100) << 1;
const uint32_t d3 = (c0 / 100) << 1;
const uint32_t d4 = (c0 % 100) << 1;
const uint32_t b1 = v1 / 10000;
const uint32_t c1 = v1 % 10000;
const uint32_t d5 = (b1 / 100) << 1;
const uint32_t d6 = (b1 % 100) << 1;
const uint32_t d7 = (c1 / 100) << 1;
const uint32_t d8 = (c1 % 100) << 1;
......@@ -209,7 +213,7 @@ inline char* u64toa(uint64_t value, char* buffer) {
*buffer++ = cDigitsLut[d4];
if (value >= kTen8)
*buffer++ = cDigitsLut[d4 + 1];
*buffer++ = cDigitsLut[d5];
*buffer++ = cDigitsLut[d5 + 1];
*buffer++ = cDigitsLut[d6];
......@@ -222,7 +226,7 @@ inline char* u64toa(uint64_t value, char* buffer) {
else {
const uint32_t a = static_cast<uint32_t>(value / kTen16); // 1 to 1844
value %= kTen16;
if (a < 10)
*buffer++ = static_cast<char>('0' + static_cast<char>(a));
else if (a < 100) {
......@@ -232,7 +236,7 @@ inline char* u64toa(uint64_t value, char* buffer) {
}
else if (a < 1000) {
*buffer++ = static_cast<char>('0' + static_cast<char>(a / 100));
const uint32_t i = (a % 100) << 1;
*buffer++ = cDigitsLut[i];
*buffer++ = cDigitsLut[i + 1];
......@@ -245,28 +249,28 @@ inline char* u64toa(uint64_t value, char* buffer) {
*buffer++ = cDigitsLut[j];
*buffer++ = cDigitsLut[j + 1];
}
const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
const uint32_t b0 = v0 / 10000;
const uint32_t c0 = v0 % 10000;
const uint32_t d1 = (b0 / 100) << 1;
const uint32_t d2 = (b0 % 100) << 1;
const uint32_t d3 = (c0 / 100) << 1;
const uint32_t d4 = (c0 % 100) << 1;
const uint32_t b1 = v1 / 10000;
const uint32_t c1 = v1 % 10000;
const uint32_t d5 = (b1 / 100) << 1;
const uint32_t d6 = (b1 % 100) << 1;
const uint32_t d7 = (c1 / 100) << 1;
const uint32_t d8 = (c1 % 100) << 1;
*buffer++ = cDigitsLut[d1];
*buffer++ = cDigitsLut[d1 + 1];
*buffer++ = cDigitsLut[d2];
......@@ -284,11 +288,12 @@ inline char* u64toa(uint64_t value, char* buffer) {
*buffer++ = cDigitsLut[d8];
*buffer++ = cDigitsLut[d8 + 1];
}
return buffer;
}
inline char* i64toa(int64_t value, char* buffer) {
RAPIDJSON_ASSERT(buffer != 0);
uint64_t u = static_cast<uint64_t>(value);
if (value < 0) {
*buffer++ = '-';
......
......@@ -21,7 +21,8 @@
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
#endif
#if defined(_MSC_VER)
#if defined(_MSC_VER) && !defined(__clang__)
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(6334)
#endif
......@@ -174,7 +175,11 @@ template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type;
RAPIDJSON_NAMESPACE_END
//@endcond
#if defined(__GNUC__) || defined(_MSC_VER)
#if defined(_MSC_VER) && !defined(__clang__)
RAPIDJSON_DIAG_POP
#endif
#ifdef __GNUC__
RAPIDJSON_DIAG_POP
#endif
......
......@@ -24,16 +24,17 @@ RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(padded)
RAPIDJSON_DIAG_OFF(switch-enum)
RAPIDJSON_DIAG_OFF(implicit-fallthrough)
#elif defined(_MSC_VER)
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
#endif
#ifdef __GNUC__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
#if __GNUC__ >= 7
RAPIDJSON_DIAG_OFF(implicit-fallthrough)
#endif
#ifdef _MSC_VER
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
#endif
#ifndef RAPIDJSON_REGEX_VERBOSE
......@@ -720,11 +721,11 @@ typedef GenericRegexSearch<Regex> RegexSearch;
} // namespace internal
RAPIDJSON_NAMESPACE_END
#ifdef __clang__
#ifdef __GNUC__
RAPIDJSON_DIAG_POP
#endif
#ifdef _MSC_VER
#if defined(__clang__) || defined(_MSC_VER)
RAPIDJSON_DIAG_POP
#endif
......
......@@ -100,7 +100,7 @@ public:
void ShrinkToFit() {
if (Empty()) {
// If the stack is empty, completely deallocate the memory.
Allocator::Free(stack_);
Allocator::Free(stack_); // NOLINT (+clang-analyzer-unix.Malloc)
stack_ = 0;
stackTop_ = 0;
stackEnd_ = 0;
......
......@@ -21,9 +21,7 @@
#ifdef __clang__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(padded)
#endif
#ifdef _MSC_VER
#elif defined(_MSC_VER)
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized
#endif
......
......@@ -21,9 +21,7 @@
#ifdef __clang__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(switch-enum)
#endif
#ifdef _MSC_VER
#elif defined(_MSC_VER)
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
#endif
......@@ -165,7 +163,12 @@ public:
GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
//! Copy constructor.
GenericPointer(const GenericPointer& rhs, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
GenericPointer(const GenericPointer& rhs) : allocator_(rhs.allocator_), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
*this = rhs;
}
//! Copy constructor.
GenericPointer(const GenericPointer& rhs, Allocator* allocator) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
*this = rhs;
}
......@@ -532,14 +535,14 @@ public:
*/
ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const {
bool alreadyExist;
Value& v = Create(root, allocator, &alreadyExist);
ValueType& v = Create(root, allocator, &alreadyExist);
return alreadyExist ? v : v.CopyFrom(defaultValue, allocator);
}
//! Query a value in a subtree with default null-terminated string.
ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const {
bool alreadyExist;
Value& v = Create(root, allocator, &alreadyExist);
ValueType& v = Create(root, allocator, &alreadyExist);
return alreadyExist ? v : v.SetString(defaultValue, allocator);
}
......@@ -547,7 +550,7 @@ public:
//! Query a value in a subtree with default std::basic_string.
ValueType& GetWithDefault(ValueType& root, const std::basic_string<Ch>& defaultValue, typename ValueType::AllocatorType& allocator) const {
bool alreadyExist;
Value& v = Create(root, allocator, &alreadyExist);
ValueType& v = Create(root, allocator, &alreadyExist);
return alreadyExist ? v : v.SetString(defaultValue, allocator);
}
#endif
......@@ -1347,11 +1350,7 @@ bool EraseValueByPointer(T& root, const CharType(&source)[N]) {
RAPIDJSON_NAMESPACE_END
#ifdef __clang__
RAPIDJSON_DIAG_POP
#endif
#ifdef _MSC_VER
#if defined(__clang__) || defined(_MSC_VER)
RAPIDJSON_DIAG_POP
#endif
......
......@@ -39,7 +39,7 @@ enum PrettyFormatOptions {
//! Writer with indentation and spacing.
/*!
\tparam OutputStream Type of ouptut os.
\tparam OutputStream Type of output os.
\tparam SourceEncoding Encoding of source string.
\tparam TargetEncoding Encoding of output stream.
\tparam StackAllocator Type of allocator for allocating memory of stack.
......@@ -47,7 +47,7 @@ enum PrettyFormatOptions {
template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> {
public:
typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> Base;
typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> Base;
typedef typename Base::Ch Ch;
//! Constructor
......
......@@ -26,7 +26,7 @@
Some RapidJSON features are configurable to adapt the library to a wide
variety of platforms, environments and usage scenarios. Most of the
features can be configured in terms of overriden or predefined
features can be configured in terms of overridden or predefined
preprocessor macros at compile-time.
Some additional customization is available in the \ref RAPIDJSON_ERRORS APIs.
......@@ -49,6 +49,11 @@
// token stringification
#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x)
#define RAPIDJSON_DO_STRINGIFY(x) #x
// token concatenation
#define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y)
#define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y)
#define RAPIDJSON_DO_JOIN2(X, Y) X##Y
//!@endcond
/*! \def RAPIDJSON_MAJOR_VERSION
......@@ -214,7 +219,7 @@
# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
# else
# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.
# error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.
# endif // __BYTE_ORDER__
// Detect with GLIBC's endian.h
# elif defined(__GLIBC__)
......@@ -224,7 +229,7 @@
# elif (__BYTE_ORDER == __BIG_ENDIAN)
# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
# else
# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.
# error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.
# endif // __GLIBC__
// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro
# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
......@@ -236,12 +241,12 @@
# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
# elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__)
# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
# elif defined(_MSC_VER) && defined(_M_ARM)
# elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64))
# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
# elif defined(RAPIDJSON_DOXYGEN_RUNNING)
# define RAPIDJSON_ENDIAN
# else
# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.
# error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.
# endif
#endif // RAPIDJSON_ENDIAN
......@@ -320,17 +325,17 @@
#endif
///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD
// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_NEON/RAPIDJSON_SIMD
/*! \def RAPIDJSON_SIMD
\ingroup RAPIDJSON_CONFIG
\brief Enable SSE2/SSE4.2 optimization.
\brief Enable SSE2/SSE4.2/Neon optimization.
RapidJSON supports optimized implementations for some parsing operations
based on the SSE2 or SSE4.2 SIMD extensions on modern Intel-compatible
processors.
based on the SSE2, SSE4.2 or NEon SIMD extensions on modern Intel
or ARM compatible processors.
To enable these optimizations, two different symbols can be defined;
To enable these optimizations, three different symbols can be defined;
\code
// Enable SSE2 optimization.
#define RAPIDJSON_SSE2
......@@ -339,13 +344,17 @@
#define RAPIDJSON_SSE42
\endcode
\c RAPIDJSON_SSE42 takes precedence, if both are defined.
// Enable ARM Neon optimization.
#define RAPIDJSON_NEON
\endcode
\c RAPIDJSON_SSE42 takes precedence over SSE2, if both are defined.
If any of these symbols is defined, RapidJSON defines the macro
\c RAPIDJSON_SIMD to indicate the availability of the optimized code.
*/
#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) \
|| defined(RAPIDJSON_DOXYGEN_RUNNING)
|| defined(RAPIDJSON_NEON) || defined(RAPIDJSON_DOXYGEN_RUNNING)
#define RAPIDJSON_SIMD
#endif
......@@ -405,7 +414,15 @@ RAPIDJSON_NAMESPACE_END
///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_STATIC_ASSERT
// Adopt from boost
// Prefer C++11 static_assert, if available
#ifndef RAPIDJSON_STATIC_ASSERT
#if __cplusplus >= 201103L || ( defined(_MSC_VER) && _MSC_VER >= 1800 )
#define RAPIDJSON_STATIC_ASSERT(x) \
static_assert(x, RAPIDJSON_STRINGIFY(x))
#endif // C++11
#endif // RAPIDJSON_STATIC_ASSERT
// Adopt C++03 implementation from boost
#ifndef RAPIDJSON_STATIC_ASSERT
#ifndef __clang__
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
......@@ -413,14 +430,10 @@ RAPIDJSON_NAMESPACE_END
RAPIDJSON_NAMESPACE_BEGIN
template <bool x> struct STATIC_ASSERTION_FAILURE;
template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
template<int x> struct StaticAssertTest {};
template <size_t x> struct StaticAssertTest {};
RAPIDJSON_NAMESPACE_END
#define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y)
#define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y)
#define RAPIDJSON_DO_JOIN2(X, Y) X##Y
#if defined(__GNUC__)
#if defined(__GNUC__) || defined(__clang__)
#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused))
#else
#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
......@@ -438,7 +451,7 @@ RAPIDJSON_NAMESPACE_END
typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \
sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE<bool(x) >)> \
RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
#endif
#endif // RAPIDJSON_STATIC_ASSERT
///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_LIKELY, RAPIDJSON_UNLIKELY
......@@ -530,7 +543,7 @@ RAPIDJSON_NAMESPACE_END
#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS
#if defined(__clang__)
#if __has_feature(cxx_rvalue_references) && \
(defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306)
(defined(_MSC_VER) || defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306)
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
#else
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
......
This diff is collapsed.
This diff is collapsed.
// Tencent is pleased to support the open source community by making RapidJSON available.
//
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
......@@ -7,9 +7,9 @@
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "rapidjson.h"
......@@ -100,6 +100,50 @@ inline void PutN(Stream& stream, Ch c, size_t n) {
PutUnsafe(stream, c);
}
///////////////////////////////////////////////////////////////////////////////
// GenericStreamWrapper
//! A Stream Wrapper
/*! \tThis string stream is a wrapper for any stream by just forwarding any
\treceived message to the origin stream.
\note implements Stream concept
*/
#if defined(_MSC_VER) && _MSC_VER <= 1800
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(4702) // unreachable code
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
#endif
template <typename InputStream, typename Encoding = UTF8<> >
class GenericStreamWrapper {
public:
typedef typename Encoding::Ch Ch;
GenericStreamWrapper(InputStream& is): is_(is) {}
Ch Peek() const { return is_.Peek(); }
Ch Take() { return is_.Take(); }
size_t Tell() { return is_.Tell(); }
Ch* PutBegin() { return is_.PutBegin(); }
void Put(Ch ch) { is_.Put(ch); }
void Flush() { is_.Flush(); }
size_t PutEnd(Ch* ch) { return is_.PutEnd(ch); }
// wrapper for MemoryStream
const Ch* Peek4() const { return is_.Peek4(); }
// wrapper for AutoUTFInputStream
UTFType GetType() const { return is_.GetType(); }
bool HasBOM() const { return is_.HasBOM(); }
protected:
InputStream& is_;
};
#if defined(_MSC_VER) && _MSC_VER <= 1800
RAPIDJSON_DIAG_POP
#endif
///////////////////////////////////////////////////////////////////////////////
// StringStream
......
This diff is collapsed.
......@@ -10,6 +10,6 @@
"repository":
{
"type": "git",
"url": "https://github.com/miloyip/rapidjson"
"url": "https://github.com/Tencent/rapidjson"
}
}
......@@ -13,12 +13,12 @@
},
"repository": {
"type": "git",
"url": "git+https://github.com/miloyip/rapidjson.git"
"url": "git+https://github.com/Tencent/rapidjson.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/miloyip/rapidjson/issues"
"url": "https://github.com/Tencent/rapidjson/issues"
},
"homepage": "https://github.com/miloyip/rapidjson#readme"
"homepage": "https://github.com/Tencent/rapidjson#readme"
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -28,6 +28,8 @@
#define SIMD_SUFFIX(name) name##_SSE2
#elif defined(RAPIDJSON_SSE42)
#define SIMD_SUFFIX(name) name##_SSE42
#elif defined(RAPIDJSON_NEON)
#define SIMD_SUFFIX(name) name##_NEON
#else
#define SIMD_SUFFIX(name) name
#endif
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment