mirror of
https://github.com/Tencent/rapidjson.git
synced 2025-03-05 20:49:05 +01:00
Merge branch 'master' into custom_malloc
This commit is contained in:
commit
004e8e61a0
73
.travis.yml
73
.travis.yml
@ -1,11 +1,18 @@
|
||||
sudo: required
|
||||
dist: trusty
|
||||
group: edge
|
||||
dist: xenial
|
||||
|
||||
language: cpp
|
||||
cache:
|
||||
- ccache
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- cmake
|
||||
- valgrind
|
||||
- clang-8
|
||||
env:
|
||||
global:
|
||||
- USE_CCACHE=1
|
||||
@ -14,41 +21,60 @@ 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
|
||||
- ARCH_FLAGS_aarch64='-march=armv8-a'
|
||||
- GITHUB_REPO='Tencent/rapidjson'
|
||||
- secure: "HrsaCb+N66EG1HR+LWH1u51SjaJyRwJEDzqJGYMB7LJ/bfqb9mWKF1fLvZGk46W5t7TVaXRDD5KHFx9DPWvKn4gRUVkwTHEy262ah5ORh8M6n/6VVVajeV/AYt2C0sswdkDBDO4Xq+xy5gdw3G8s1A4Inbm73pUh+6vx+7ltBbk="
|
||||
|
||||
before_install:
|
||||
- sudo apt-add-repository -y ppa:ubuntu-toolchain-r/test
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -y cmake valgrind g++-multilib libc6-dbg:i386
|
||||
|
||||
matrix:
|
||||
include:
|
||||
# gcc
|
||||
- env: CONF=release ARCH=x86 CXX11=ON
|
||||
compiler: gcc
|
||||
arch: amd64
|
||||
- env: CONF=release ARCH=x86_64 CXX11=ON
|
||||
compiler: gcc
|
||||
arch: amd64
|
||||
- env: CONF=debug ARCH=x86 CXX11=OFF
|
||||
compiler: gcc
|
||||
arch: amd64
|
||||
- env: CONF=debug ARCH=x86_64 CXX11=OFF
|
||||
compiler: gcc
|
||||
arch: amd64
|
||||
- env: CONF=release ARCH=aarch64 CXX11=ON
|
||||
compiler: gcc
|
||||
arch: arm64
|
||||
- env: CONF=debug ARCH=aarch64 CXX11=OFF
|
||||
compiler: gcc
|
||||
arch: arm64
|
||||
# clang
|
||||
- env: CONF=debug ARCH=x86 CXX11=ON CCACHE_CPP2=yes
|
||||
compiler: clang
|
||||
arch: amd64
|
||||
- env: CONF=debug ARCH=x86_64 CXX11=ON CCACHE_CPP2=yes
|
||||
compiler: clang
|
||||
arch: amd64
|
||||
- env: CONF=debug ARCH=x86 CXX11=OFF CCACHE_CPP2=yes
|
||||
compiler: clang
|
||||
arch: amd64
|
||||
- env: CONF=debug ARCH=x86_64 CXX11=OFF CCACHE_CPP2=yes
|
||||
compiler: clang
|
||||
arch: amd64
|
||||
- env: CONF=release ARCH=x86 CXX11=ON CCACHE_CPP2=yes
|
||||
compiler: clang
|
||||
arch: amd64
|
||||
- env: CONF=release ARCH=x86_64 CXX11=ON CCACHE_CPP2=yes
|
||||
compiler: clang
|
||||
arch: amd64
|
||||
- env: CONF=debug ARCH=aarch64 CXX11=ON CCACHE_CPP2=yes
|
||||
compiler: clang
|
||||
arch: arm64
|
||||
- env: CONF=debug ARCH=aarch64 CXX11=OFF CCACHE_CPP2=yes
|
||||
compiler: clang
|
||||
arch: arm64
|
||||
# coverage report
|
||||
- env: CONF=debug ARCH=x86 CXX11=ON GCOV_FLAGS='--coverage'
|
||||
compiler: gcc
|
||||
arch: amd64
|
||||
cache:
|
||||
- ccache
|
||||
- pip
|
||||
@ -57,6 +83,16 @@ matrix:
|
||||
- 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
|
||||
- env: CONF=debug ARCH=x86_64 GCOV_FLAGS='--coverage'
|
||||
compiler: gcc
|
||||
arch: amd64
|
||||
cache:
|
||||
- ccache
|
||||
- pip
|
||||
after_success:
|
||||
- pip install --user cpp-coveralls
|
||||
- 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
|
||||
- env: CONF=debug ARCH=aarch64 GCOV_FLAGS='--coverage'
|
||||
compiler: gcc
|
||||
arch: arm64
|
||||
cache:
|
||||
- ccache
|
||||
- pip
|
||||
@ -73,13 +109,24 @@ matrix:
|
||||
packages:
|
||||
- doxygen
|
||||
|
||||
before_install:
|
||||
- if [ "x86_64" = "$(arch)" ]; then sudo apt-get install -y g++-multilib libc6-dbg:i386 --allow-unauthenticated; fi
|
||||
|
||||
before_script:
|
||||
- ccache -s
|
||||
# hack to avoid Valgrind bug (https://bugs.kde.org/show_bug.cgi?id=326469),
|
||||
# exposed by merging PR#163 (using -march=native)
|
||||
# TODO: Since this bug is already fixed. Remove this when valgrind can be upgraded.
|
||||
- sed -i "s/-march=native//" CMakeLists.txt
|
||||
- mkdir build
|
||||
# travis provides clang-7 for amd64 and clang-3.8 for arm64
|
||||
# here use clang-8 to all architectures as clang-7 is not available for arm64
|
||||
- if [ -f /usr/bin/clang++-8 ]; then
|
||||
sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-8 1000;
|
||||
sudo update-alternatives --config clang++;
|
||||
export PATH=/usr/bin:$PATH;
|
||||
fi
|
||||
- if [ "$CXX" = "clang++" ]; then export CCACHE_CPP2=yes; fi
|
||||
- ccache -s
|
||||
# hack to avoid Valgrind bug (https://bugs.kde.org/show_bug.cgi?id=326469),
|
||||
# exposed by merging PR#163 (using -march=native)
|
||||
# TODO: Since this bug is already fixed. Remove this when valgrind can be upgraded.
|
||||
- sed -i "s/-march=native//" CMakeLists.txt
|
||||
- mkdir build
|
||||
|
||||
script:
|
||||
- if [ "$CXX" = "clang++" ]; then export CXXFLAGS="-stdlib=libc++ ${CXXFLAGS}"; fi
|
||||
|
@ -9,13 +9,18 @@ endif()
|
||||
|
||||
SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules)
|
||||
|
||||
PROJECT(RapidJSON CXX)
|
||||
|
||||
set(LIB_MAJOR_VERSION "1")
|
||||
set(LIB_MINOR_VERSION "1")
|
||||
set(LIB_PATCH_VERSION "0")
|
||||
set(LIB_VERSION_STRING "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_PATCH_VERSION}")
|
||||
|
||||
if (CMAKE_VERSION VERSION_LESS 3.0)
|
||||
PROJECT(RapidJSON CXX)
|
||||
else()
|
||||
cmake_policy(SET CMP0048 NEW)
|
||||
PROJECT(RapidJSON VERSION "${LIB_VERSION_STRING}" LANGUAGES CXX)
|
||||
endif()
|
||||
|
||||
# compile in release with debug info mode by default
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE)
|
||||
|
@ -1,3 +1,7 @@
|
||||
################################################################################
|
||||
# CMake minimum version required
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
################################################################################
|
||||
# RapidJSON source dir
|
||||
set( RapidJSON_SOURCE_DIR "@CONFIG_SOURCE_DIR@")
|
||||
@ -13,3 +17,9 @@ get_filename_component(RapidJSON_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
|
||||
set( RapidJSON_INCLUDE_DIR "@RapidJSON_INCLUDE_DIR@" )
|
||||
set( RapidJSON_INCLUDE_DIRS "@RapidJSON_INCLUDE_DIR@" )
|
||||
message(STATUS "RapidJSON found. Headers: ${RapidJSON_INCLUDE_DIRS}")
|
||||
|
||||
if(NOT TARGET rapidjson)
|
||||
add_library(rapidjson INTERFACE IMPORTED)
|
||||
set_property(TARGET rapidjson PROPERTY
|
||||
INTERFACE_INCLUDE_DIRECTORIES ${RapidJSON_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
@ -5,8 +5,8 @@
|
||||
<DisplayString Condition="(data_.f.flags & 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 & kTypeMask) == kStringType">{(const char*)((size_t)data_.s.str & 0x0000FFFFFFFFFFFF)}</DisplayString>
|
||||
<DisplayString Condition="data_.f.flags == kShortStringFlag">{(const Ch*)data_.ss.str,na}</DisplayString>
|
||||
<DisplayString Condition="(data_.f.flags & kTypeMask) == kStringType">{(const Ch*)((size_t)data_.s.str & 0x0000FFFFFFFFFFFF),na}</DisplayString>
|
||||
<DisplayString Condition="(data_.f.flags & kNumberIntFlag) == kNumberIntFlag">{data_.n.i.i}</DisplayString>
|
||||
<DisplayString Condition="(data_.f.flags & kNumberUintFlag) == kNumberUintFlag">{data_.n.u.u}</DisplayString>
|
||||
<DisplayString Condition="(data_.f.flags & kNumberInt64Flag) == kNumberInt64Flag">{data_.n.i64}</DisplayString>
|
||||
|
@ -119,6 +119,7 @@ Parse flags | Meaning
|
||||
`kParseNumbersAsStringsFlag` | Parse numerical type values as strings.
|
||||
`kParseTrailingCommasFlag` | Allow trailing commas at the end of objects and arrays (relaxed JSON syntax).
|
||||
`kParseNanAndInfFlag` | Allow parsing `NaN`, `Inf`, `Infinity`, `-Inf` and `-Infinity` as `double` values (relaxed JSON syntax).
|
||||
`kParseEscapedApostropheFlag` | Allow escaped apostrophe `\'` in strings (relaxed JSON syntax).
|
||||
|
||||
By using a non-type template parameter, instead of a function parameter, C++ compiler can generate code which is optimized for specified combinations, improving speed, and reducing code size (if only using a single specialization). The downside is the flags needed to be determined in compile-time.
|
||||
|
||||
|
@ -119,6 +119,7 @@ GenericDocument& GenericDocument::Parse(const Ch* str);
|
||||
`kParseNumbersAsStringsFlag` | 把数字类型解析成字符串。
|
||||
`kParseTrailingCommasFlag` | 容许在对象和数组结束前含有逗号(放宽的 JSON 语法)。
|
||||
`kParseNanAndInfFlag` | 容许 `NaN`、`Inf`、`Infinity`、`-Inf` 及 `-Infinity` 作为 `double` 值(放宽的 JSON 语法)。
|
||||
`kParseEscapedApostropheFlag` | 容许字符串中转义单引号 `\'` (放宽的 JSON 语法)。
|
||||
|
||||
由于使用了非类型模板参数,而不是函数参数,C++ 编译器能为个别组合生成代码,以改善性能及减少代码尺寸(当只用单种特化)。缺点是需要在编译期决定标志。
|
||||
|
||||
|
@ -64,11 +64,11 @@
|
||||
|
||||
JSON are commonly used in web applications for transferring structured data. It is also used as a file format for data persistence.
|
||||
|
||||
2. Does RapidJSON conform to the JSON standard?
|
||||
3. Does RapidJSON conform to the JSON standard?
|
||||
|
||||
Yes. RapidJSON is fully compliance with [RFC7159](http://www.ietf.org/rfc/rfc7159.txt) and [ECMA-404](http://www.ecma-international.org/publications/standards/Ecma-404.htm). It can handle corner cases, such as supporting null character and surrogate pairs in JSON strings.
|
||||
|
||||
3. Does RapidJSON support relaxed syntax?
|
||||
4. 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/Tencent/rapidjson/issues/36).
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
4. RapidJSON 是免费的么?
|
||||
|
||||
是的,它在 MIT 特許條款下免费。它可用于商业软件。详情请参看 [license.txt](https://github.com/Tencent/rapidjson/blob/master/license.txt)。
|
||||
是的,它在 MIT 协议下免费。它可用于商业软件。详情请参看 [license.txt](https://github.com/Tencent/rapidjson/blob/master/license.txt)。
|
||||
|
||||
5. RapidJSON 很小么?它有何依赖?
|
||||
|
||||
@ -64,13 +64,13 @@
|
||||
|
||||
JSON 常用于网页应用程序,以传送结构化数据。它也可作为文件格式用于数据持久化。
|
||||
|
||||
2. RapidJSON 是否符合 JSON 标准?
|
||||
3. RapidJSON 是否符合 JSON 标准?
|
||||
|
||||
是。RapidJSON 完全符合 [RFC7159](http://www.ietf.org/rfc/rfc7159.txt) 及 [ECMA-404](http://www.ecma-international.org/publications/standards/Ecma-404.htm)。它能处理一些特殊情况,例如支持 JSON 字符串中含有空字符及代理对(surrogate pair)。
|
||||
|
||||
3. RapidJSON 是否支持宽松的语法?
|
||||
4. RapidJSON 是否支持宽松的语法?
|
||||
|
||||
现时不支持。RapidJSON 只支持严格的标准格式。宽松语法现时在这 [issue](https://github.com/Tencent/rapidjson/issues/36) 中进行讨论。
|
||||
目前不支持。RapidJSON 只支持严格的标准格式。宽松语法可以在这个 [issue](https://github.com/Tencent/rapidjson/issues/36) 中进行讨论。
|
||||
|
||||
## DOM 与 SAX
|
||||
|
||||
@ -271,7 +271,7 @@
|
||||
|
||||
有些应用程序需要处理非常大的 JSON 文件。而有些后台应用程序需要处理大量的 JSON。达到高性能同时改善延时及吞吐量。更广义来说,这也可以节省能源。
|
||||
|
||||
## 八挂
|
||||
## 八卦
|
||||
|
||||
1. 谁是 RapidJSON 的开发者?
|
||||
|
||||
@ -279,11 +279,11 @@
|
||||
|
||||
2. 为何你要开发 RapidJSON?
|
||||
|
||||
在 2011 年开始这项目是,它仅一个兴趣项目。Milo Yip 是一个游戏程序员,他在那时候认识到 JSON 并希望在未来的项目中使用。由于 JSON 好像很简单,他希望写一个仅有头文件并且快速的程序库。
|
||||
在 2011 年开始这项目时,它只是一个兴趣项目。Milo Yip 是一个游戏程序员,他在那时候认识到 JSON 并希望在未来的项目中使用。由于 JSON 好像很简单,他希望写一个快速的仅有头文件的程序库。
|
||||
|
||||
3. 为什么开发中段有一段长期空档?
|
||||
|
||||
主要是个人因素,例如加入新家庭成员。另外,Milo Yip 也花了许多业馀时间去翻译 Jason Gregory 的《Game Engine Architecture》至中文版《游戏引擎架构》。
|
||||
主要是个人因素,例如加入新家庭成员。另外,Milo Yip 也花了许多业余时间去翻译 Jason Gregory 的《Game Engine Architecture》至中文版《游戏引擎架构》。
|
||||
|
||||
4. 为什么这个项目从 Google Code 搬到 GitHub?
|
||||
|
||||
|
@ -79,7 +79,7 @@ The following tables show the data layout of each type. The 32-bit/64-bit column
|
||||
| `unsigned u` | 32-bit unsigned integer |4 |4 |
|
||||
| (zero padding) | 0 |4 |4 |
|
||||
| (unused) | |4 |8 |
|
||||
| `unsigned flags_` | `kNumberType kNumberFlag kUIntFlag kUInt64Flag ...` |4 |4 |
|
||||
| `unsigned flags_` | `kNumberType kNumberFlag kUintFlag kUint64Flag ...` |4 |4 |
|
||||
|
||||
| Number (Int64) | |32-bit|64-bit|
|
||||
|---------------------|-------------------------------------|:----:|:----:|
|
||||
|
@ -79,7 +79,7 @@ SAX 和 DOM API 都依赖于3个额外的概念:`Allocator`、`Encoding` 和 `
|
||||
| `unsigned u` | 32位无符号整数 |4 |4 |
|
||||
| (零填充) | 0 |4 |4 |
|
||||
| (未使用) | |4 |8 |
|
||||
| `unsigned flags_` | `kNumberType kNumberFlag kUIntFlag kUInt64Flag ...` |4 |4 |
|
||||
| `unsigned flags_` | `kNumberType kNumberFlag kUintFlag kUint64Flag ...` |4 |4 |
|
||||
|
||||
| Number (Int64) | | 32位 | 64位 |
|
||||
|---------------------|-------------------------------------|:----:|:----:|
|
||||
@ -248,7 +248,7 @@ void SkipWhitespace(InputStream& is) {
|
||||
|
||||
## 整数到字符串的转换 {#itoa}
|
||||
|
||||
整数到字符串转换的朴素算法需要对每一个十进制位进行一次处罚。我们实现了若干版本并在 [itoa-benchmark](https://github.com/miloyip/itoa-benchmark) 中对它们进行了评估。
|
||||
整数到字符串转换的朴素算法需要对每一个十进制位进行一次除法。我们实现了若干版本并在 [itoa-benchmark](https://github.com/miloyip/itoa-benchmark) 中对它们进行了评估。
|
||||
|
||||
虽然 SSE2 版本是最快的,但它和第二快的 `branchlut` 差距不大。而且 `branchlut` 是纯C++实现,所以我们在 RapidJSON 中使用了 `branchlut`。
|
||||
|
||||
|
@ -181,7 +181,7 @@ private:
|
||||
|
||||
`Pointer` 在其建构函数里会解译源字符串。若有解析错误,`Pointer::IsValid()` 返回 `false`。你可使用 `Pointer::GetParseErrorCode()` 和 `GetParseErrorOffset()` 去获取错信息。
|
||||
|
||||
要注意的是,所有解析函数都假设 pointer 是合法的。对一个非法 pointer 解析会做成断言失败。
|
||||
要注意的是,所有解析函数都假设 pointer 是合法的。对一个非法 pointer 解析会造成断言失败。
|
||||
|
||||
# URI 片段表示方式 {#URIFragment}
|
||||
|
||||
|
@ -37,7 +37,7 @@ Bool(false)
|
||||
Key("n", 1, true)
|
||||
Null()
|
||||
Key("i")
|
||||
UInt(123)
|
||||
Uint(123)
|
||||
Key("pi")
|
||||
Double(3.1416)
|
||||
Key("a")
|
||||
|
@ -37,7 +37,7 @@ Bool(false)
|
||||
Key("n", 1, true)
|
||||
Null()
|
||||
Key("i")
|
||||
UInt(123)
|
||||
Uint(123)
|
||||
Key("pi")
|
||||
Double(3.1416)
|
||||
Key("a")
|
||||
@ -91,7 +91,7 @@ void main() {
|
||||
}
|
||||
~~~~~~~~~~
|
||||
|
||||
注意 RapidJSON 使用模板去静态挷定 `Reader` 类型及处理器的类形,而不是使用含虚函数的类。这个范式可以通过把函数内联而改善性能。
|
||||
注意 RapidJSON 使用模板去静态挷定 `Reader` 类型及处理器的类型,而不是使用含虚函数的类。这个范式可以通过把函数内联而改善性能。
|
||||
|
||||
## 处理器 {#Handler}
|
||||
|
||||
|
@ -127,7 +127,7 @@ Due to users' requests, RapidJSON provided official wrappers for `std::basic_ist
|
||||
|
||||
## IStreamWrapper {#IStreamWrapper}
|
||||
|
||||
`IStreamWrapper` wraps any class drived from `std::istream`, such as `std::istringstream`, `std::stringstream`, `std::ifstream`, `std::fstream`, into RapidJSON's input stream.
|
||||
`IStreamWrapper` wraps any class derived from `std::istream`, such as `std::istringstream`, `std::stringstream`, `std::ifstream`, `std::fstream`, into RapidJSON's input stream.
|
||||
|
||||
~~~cpp
|
||||
#include <rapidjson/document.h>
|
||||
|
@ -82,7 +82,7 @@ JSON number type represents all numeric values. However, C++ needs more specific
|
||||
~~~~~~~~~~cpp
|
||||
assert(document["i"].IsNumber());
|
||||
|
||||
// In this case, IsUint()/IsInt64()/IsUInt64() also return true.
|
||||
// In this case, IsUint()/IsInt64()/IsUint64() also return true.
|
||||
assert(document["i"].IsInt());
|
||||
printf("i = %d\n", document["i"].GetInt());
|
||||
// Alternative (int)document["i"]
|
||||
|
@ -82,7 +82,7 @@ JSON Number 类型表示所有数值。然而,C++ 需要使用更专门的类
|
||||
~~~~~~~~~~cpp
|
||||
assert(document["i"].IsNumber());
|
||||
|
||||
// 在此情况下,IsUint()/IsInt64()/IsUInt64() 也会返回 true
|
||||
// 在此情况下,IsUint()/IsInt64()/IsUint64() 也会返回 true
|
||||
assert(document["i"].IsInt());
|
||||
printf("i = %d\n", document["i"].GetInt());
|
||||
// 另一种用法: (int)document["i"]
|
||||
@ -250,7 +250,7 @@ string(const char* s, size_t count);
|
||||
|
||||
~~~~~~~~~~cpp
|
||||
if (document["hello"] == document["n"]) /*...*/; // 比较两个值
|
||||
if (document["hello"] == "world") /*...*/; // 与字符串家面量作比较
|
||||
if (document["hello"] == "world") /*...*/; // 与字符串字面量作比较
|
||||
if (document["i"] != 123) /*...*/; // 与整数作比较
|
||||
if (document["pi"] != 3.14) /*...*/; // 与 double 作比较
|
||||
~~~~~~~~~~
|
||||
@ -388,7 +388,7 @@ allocator 参数。对于字符串字面量(或字符数组常量),只需
|
||||
|
||||
~~~~~~~~~~cpp
|
||||
Value s;
|
||||
s.SetString("rapidjson"); // 可包含空字符,长度在编译萁推导
|
||||
s.SetString("rapidjson"); // 可包含空字符,长度在编译期推导
|
||||
s = "rapidjson"; // 上行的缩写
|
||||
~~~~~~~~~~
|
||||
|
||||
@ -447,7 +447,7 @@ contact.PushBack(val, document.GetAllocator());
|
||||
~~~~~~~~~~
|
||||
|
||||
## 修改 Object {#ModifyObject}
|
||||
Object 是键值对的集合。每个键必须为 String。要修改 Object,方法是增加或移除成员。以下的 API 用来增加城员:
|
||||
Object 是键值对的集合。每个键必须为 String。要修改 Object,方法是增加或移除成员。以下的 API 用来增加成员:
|
||||
|
||||
* `Value& AddMember(Value&, Value&, Allocator& allocator)`
|
||||
* `Value& AddMember(StringRefType, Value&, Allocator&)`
|
||||
|
@ -42,7 +42,12 @@ int main() {
|
||||
}
|
||||
*/
|
||||
|
||||
// C++11 supports std::move() of Value so it always have no problem for std::sort().
|
||||
// Some C++03 implementations of std::sort() requires copy constructor which causes compilation error.
|
||||
// Needs a sorting function only depends on std::swap() instead.
|
||||
#if __cplusplus >= 201103L || (!defined(__GLIBCXX__) && (!defined(_MSC_VER) || _MSC_VER >= 1900))
|
||||
std::sort(d.MemberBegin(), d.MemberEnd(), NameComparator());
|
||||
|
||||
printIt(d);
|
||||
|
||||
/*
|
||||
@ -53,4 +58,5 @@ int main() {
|
||||
"zeta": false
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ int main(int, char*[]) {
|
||||
printf("n = %s\n", document["n"].IsNull() ? "null" : "?");
|
||||
|
||||
assert(document["i"].IsNumber()); // Number is a JSON type, but C++ needs more specific type.
|
||||
assert(document["i"].IsInt()); // In this case, IsUint()/IsInt64()/IsUInt64() also return true.
|
||||
assert(document["i"].IsInt()); // In this case, IsUint()/IsInt64()/IsUint64() also return true.
|
||||
printf("i = %d\n", document["i"].GetInt()); // Alternative (int)document["i"]
|
||||
|
||||
assert(document["pi"].IsNumber());
|
||||
|
@ -53,7 +53,7 @@ concept Allocator {
|
||||
*/
|
||||
|
||||
|
||||
/*! \def RAPIDJSON_ALLOCATOR_DEFUALT_CHUNK_CAPACITY
|
||||
/*! \def RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY
|
||||
\ingroup RAPIDJSON_CONFIG
|
||||
\brief User-defined kDefaultChunkCapacity definition.
|
||||
|
||||
|
@ -24,6 +24,9 @@
|
||||
#include "encodedstream.h"
|
||||
#include <new> // placement new
|
||||
#include <limits>
|
||||
#ifdef __cpp_lib_three_way_comparison
|
||||
#include <compare>
|
||||
#endif
|
||||
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
#ifdef __clang__
|
||||
@ -56,6 +59,48 @@ class GenericValue;
|
||||
template <typename Encoding, typename Allocator, typename StackAllocator>
|
||||
class GenericDocument;
|
||||
|
||||
/*! \def RAPIDJSON_DEFAULT_ALLOCATOR
|
||||
\ingroup RAPIDJSON_CONFIG
|
||||
\brief Allows to choose default allocator.
|
||||
|
||||
User can define this to use CrtAllocator or MemoryPoolAllocator.
|
||||
*/
|
||||
#ifndef RAPIDJSON_DEFAULT_ALLOCATOR
|
||||
#define RAPIDJSON_DEFAULT_ALLOCATOR MemoryPoolAllocator<CrtAllocator>
|
||||
#endif
|
||||
|
||||
/*! \def RAPIDJSON_DEFAULT_STACK_ALLOCATOR
|
||||
\ingroup RAPIDJSON_CONFIG
|
||||
\brief Allows to choose default stack allocator for Document.
|
||||
|
||||
User can define this to use CrtAllocator or MemoryPoolAllocator.
|
||||
*/
|
||||
#ifndef RAPIDJSON_DEFAULT_STACK_ALLOCATOR
|
||||
#define RAPIDJSON_DEFAULT_STACK_ALLOCATOR CrtAllocator
|
||||
#endif
|
||||
|
||||
/*! \def RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY
|
||||
\ingroup RAPIDJSON_CONFIG
|
||||
\brief User defined kDefaultObjectCapacity value.
|
||||
|
||||
User can define this as any natural number.
|
||||
*/
|
||||
#ifndef RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY
|
||||
// number of objects that rapidjson::Value allocates memory for by default
|
||||
#define RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY 16
|
||||
#endif
|
||||
|
||||
/*! \def RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY
|
||||
\ingroup RAPIDJSON_CONFIG
|
||||
\brief User defined kDefaultArrayCapacity value.
|
||||
|
||||
User can define this as any natural number.
|
||||
*/
|
||||
#ifndef RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY
|
||||
// number of array elements that rapidjson::Value allocates memory for by default
|
||||
#define RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY 16
|
||||
#endif
|
||||
|
||||
//! Name-value pair in a JSON object value.
|
||||
/*!
|
||||
This class was internal to GenericValue. It used to be a inner struct.
|
||||
@ -63,15 +108,45 @@ class GenericDocument;
|
||||
https://code.google.com/p/rapidjson/issues/detail?id=64
|
||||
*/
|
||||
template <typename Encoding, typename Allocator>
|
||||
struct GenericMember {
|
||||
class GenericMember {
|
||||
public:
|
||||
GenericValue<Encoding, Allocator> name; //!< name of member (must be a string)
|
||||
GenericValue<Encoding, Allocator> value; //!< value of member.
|
||||
|
||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
//! Move constructor in C++11
|
||||
GenericMember(GenericMember&& rhs) RAPIDJSON_NOEXCEPT
|
||||
: name(std::move(rhs.name)),
|
||||
value(std::move(rhs.value))
|
||||
{
|
||||
}
|
||||
|
||||
//! Move assignment in C++11
|
||||
GenericMember& operator=(GenericMember&& rhs) RAPIDJSON_NOEXCEPT {
|
||||
return *this = static_cast<GenericMember&>(rhs);
|
||||
}
|
||||
#endif
|
||||
|
||||
//! Assignment with move semantics.
|
||||
/*! \param rhs Source of the assignment. Its name and value will become a null value after assignment.
|
||||
*/
|
||||
GenericMember& operator=(GenericMember& rhs) RAPIDJSON_NOEXCEPT {
|
||||
if (RAPIDJSON_LIKELY(this != &rhs)) {
|
||||
name = rhs.name;
|
||||
value = rhs.value;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// swap() for std::sort() and other potential use in STL.
|
||||
friend inline void swap(GenericMember& a, GenericMember& b) RAPIDJSON_NOEXCEPT {
|
||||
a.name.Swap(b.name);
|
||||
a.value.Swap(b.value);
|
||||
}
|
||||
|
||||
private:
|
||||
//! Copy constructor is not permitted.
|
||||
GenericMember(const GenericMember& rhs);
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -175,12 +250,16 @@ public:
|
||||
|
||||
//! @name relations
|
||||
//@{
|
||||
bool operator==(ConstIterator that) const { return ptr_ == that.ptr_; }
|
||||
bool operator!=(ConstIterator that) const { return ptr_ != that.ptr_; }
|
||||
bool operator<=(ConstIterator that) const { return ptr_ <= that.ptr_; }
|
||||
bool operator>=(ConstIterator that) const { return ptr_ >= that.ptr_; }
|
||||
bool operator< (ConstIterator that) const { return ptr_ < that.ptr_; }
|
||||
bool operator> (ConstIterator that) const { return ptr_ > that.ptr_; }
|
||||
template <bool Const_> bool operator==(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ == that.ptr_; }
|
||||
template <bool Const_> bool operator!=(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ != that.ptr_; }
|
||||
template <bool Const_> bool operator<=(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ <= that.ptr_; }
|
||||
template <bool Const_> bool operator>=(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ >= that.ptr_; }
|
||||
template <bool Const_> bool operator< (const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ < that.ptr_; }
|
||||
template <bool Const_> bool operator> (const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ > that.ptr_; }
|
||||
|
||||
#ifdef __cpp_lib_three_way_comparison
|
||||
template <bool Const_> std::strong_ordering operator<=>(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ <=> that.ptr_; }
|
||||
#endif
|
||||
//@}
|
||||
|
||||
//! @name dereference
|
||||
@ -205,17 +284,17 @@ private:
|
||||
// class-based member iterator implementation disabled, use plain pointers
|
||||
|
||||
template <bool Const, typename Encoding, typename Allocator>
|
||||
struct GenericMemberIterator;
|
||||
class GenericMemberIterator;
|
||||
|
||||
//! non-const GenericMemberIterator
|
||||
template <typename Encoding, typename Allocator>
|
||||
struct GenericMemberIterator<false,Encoding,Allocator> {
|
||||
class GenericMemberIterator<false,Encoding,Allocator> {
|
||||
//! use plain pointer as iterator type
|
||||
typedef GenericMember<Encoding,Allocator>* Iterator;
|
||||
};
|
||||
//! const GenericMemberIterator
|
||||
template <typename Encoding, typename Allocator>
|
||||
struct GenericMemberIterator<true,Encoding,Allocator> {
|
||||
class GenericMemberIterator<true,Encoding,Allocator> {
|
||||
//! use plain const pointer as iterator type
|
||||
typedef const GenericMember<Encoding,Allocator>* Iterator;
|
||||
};
|
||||
@ -574,7 +653,7 @@ template <bool, typename> class GenericObject;
|
||||
\tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document)
|
||||
\tparam Allocator Allocator type for allocating memory of object, array and string.
|
||||
*/
|
||||
template <typename Encoding, typename Allocator = MemoryPoolAllocator<> >
|
||||
template <typename Encoding, typename Allocator = RAPIDJSON_DEFAULT_ALLOCATOR >
|
||||
class GenericValue {
|
||||
public:
|
||||
//! Name-value pair in an object.
|
||||
@ -1939,8 +2018,8 @@ private:
|
||||
kTypeMask = 0x07
|
||||
};
|
||||
|
||||
static const SizeType kDefaultArrayCapacity = 16;
|
||||
static const SizeType kDefaultObjectCapacity = 16;
|
||||
static const SizeType kDefaultArrayCapacity = RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY;
|
||||
static const SizeType kDefaultObjectCapacity = RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY;
|
||||
|
||||
struct Flag {
|
||||
#if RAPIDJSON_48BITPOINTER_OPTIMIZATION
|
||||
@ -2120,7 +2199,7 @@ typedef GenericValue<UTF8<> > Value;
|
||||
\tparam StackAllocator Allocator for allocating memory for stack during parsing.
|
||||
\warning Although GenericDocument inherits from GenericValue, the API does \b not provide any virtual functions, especially no virtual destructor. To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a GenericValue.
|
||||
*/
|
||||
template <typename Encoding, typename Allocator = MemoryPoolAllocator<>, typename StackAllocator = CrtAllocator>
|
||||
template <typename Encoding, typename Allocator = RAPIDJSON_DEFAULT_ALLOCATOR, typename StackAllocator = RAPIDJSON_DEFAULT_STACK_ALLOCATOR >
|
||||
class GenericDocument : public GenericValue<Encoding, Allocator> {
|
||||
public:
|
||||
typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
|
||||
@ -2505,6 +2584,7 @@ private:
|
||||
//! GenericDocument with UTF8 encoding
|
||||
typedef GenericDocument<UTF8<> > Document;
|
||||
|
||||
|
||||
//! Helper class for accessing Value of array type.
|
||||
/*!
|
||||
Instance of this helper class is obtained by \c GenericValue::GetArray().
|
||||
|
@ -102,7 +102,7 @@ class PrettyWriter;
|
||||
// document.h
|
||||
|
||||
template <typename Encoding, typename Allocator>
|
||||
struct GenericMember;
|
||||
class GenericMember;
|
||||
|
||||
template <bool Const, typename Encoding, typename Allocator>
|
||||
class GenericMemberIterator;
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
#include "../rapidjson.h"
|
||||
|
||||
#if defined(_MSC_VER) && !__INTEL_COMPILER && defined(_M_AMD64)
|
||||
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && defined(_M_AMD64)
|
||||
#include <intrin.h> // for _umul128
|
||||
#pragma intrinsic(_umul128)
|
||||
#endif
|
||||
|
71
include/rapidjson/internal/clzll.h
Normal file
71
include/rapidjson/internal/clzll.h
Normal file
@ -0,0 +1,71 @@
|
||||
// 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_CLZLL_H_
|
||||
#define RAPIDJSON_CLZLL_H_
|
||||
|
||||
#include "../rapidjson.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <intrin.h>
|
||||
#if defined(_WIN64)
|
||||
#pragma intrinsic(_BitScanReverse64)
|
||||
#else
|
||||
#pragma intrinsic(_BitScanReverse)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
|
||||
inline uint32_t clzll(uint64_t x) {
|
||||
// Passing 0 to __builtin_clzll is UB in GCC and results in an
|
||||
// infinite loop in the software implementation.
|
||||
RAPIDJSON_ASSERT(x != 0);
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
unsigned long r = 0;
|
||||
#if defined(_WIN64)
|
||||
_BitScanReverse64(&r, x);
|
||||
#else
|
||||
// Scan the high 32 bits.
|
||||
if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32)))
|
||||
return 63 - (r + 32);
|
||||
|
||||
// Scan the low 32 bits.
|
||||
_BitScanReverse(&r, static_cast<uint32_t>(x & 0xFFFFFFFF));
|
||||
#endif // _WIN64
|
||||
|
||||
return 63 - r;
|
||||
#elif (defined(__GNUC__) && __GNUC__ >= 4) || RAPIDJSON_HAS_BUILTIN(__builtin_clzll)
|
||||
// __builtin_clzll wrapper
|
||||
return static_cast<uint32_t>(__builtin_clzll(x));
|
||||
#else
|
||||
// naive version
|
||||
uint32_t r;
|
||||
while (!(x & (static_cast<uint64_t>(1) << 63))) {
|
||||
x <<= 1;
|
||||
++r;
|
||||
}
|
||||
|
||||
return r;
|
||||
#endif // _MSC_VER
|
||||
}
|
||||
|
||||
#define RAPIDJSON_CLZLL RAPIDJSON_NAMESPACE::internal::clzll
|
||||
|
||||
} // namespace internal
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // RAPIDJSON_CLZLL_H_
|
@ -20,11 +20,11 @@
|
||||
#define RAPIDJSON_DIYFP_H_
|
||||
|
||||
#include "../rapidjson.h"
|
||||
#include "clzll.h"
|
||||
#include <limits>
|
||||
|
||||
#if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER)
|
||||
#include <intrin.h>
|
||||
#pragma intrinsic(_BitScanReverse64)
|
||||
#pragma intrinsic(_umul128)
|
||||
#endif
|
||||
|
||||
@ -100,22 +100,8 @@ struct DiyFp {
|
||||
}
|
||||
|
||||
DiyFp Normalize() const {
|
||||
RAPIDJSON_ASSERT(f != 0); // https://stackoverflow.com/a/26809183/291737
|
||||
#if defined(_MSC_VER) && defined(_M_AMD64)
|
||||
unsigned long index;
|
||||
_BitScanReverse64(&index, f);
|
||||
return DiyFp(f << (63 - index), e - (63 - index));
|
||||
#elif defined(__GNUC__) && __GNUC__ >= 4
|
||||
int s = __builtin_clzll(f);
|
||||
int s = static_cast<int>(clzll(f));
|
||||
return DiyFp(f << s, e - s);
|
||||
#else
|
||||
DiyFp res = *this;
|
||||
while (!(res.f & (static_cast<uint64_t>(1) << 63))) {
|
||||
res.f <<= 1;
|
||||
res.e--;
|
||||
}
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
DiyFp NormalizeBoundary() const {
|
||||
|
@ -23,7 +23,6 @@
|
||||
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
|
||||
@ -32,9 +31,6 @@ RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
|
||||
#ifdef __GNUC__
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(effc++)
|
||||
#if __GNUC__ >= 7
|
||||
RAPIDJSON_DIAG_OFF(implicit-fallthrough)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef RAPIDJSON_REGEX_VERBOSE
|
||||
@ -291,6 +287,7 @@ private:
|
||||
if (!CharacterEscape(ds, &codepoint))
|
||||
return; // Unsupported escape character
|
||||
// fall through to default
|
||||
RAPIDJSON_DELIBERATE_FALLTHROUGH;
|
||||
|
||||
default: // Pattern character
|
||||
PushOperand(operandStack, codepoint);
|
||||
@ -520,6 +517,7 @@ private:
|
||||
else if (!CharacterEscape(ds, &codepoint))
|
||||
return false;
|
||||
// fall through to default
|
||||
RAPIDJSON_DELIBERATE_FALLTHROUGH;
|
||||
|
||||
default:
|
||||
switch (step) {
|
||||
@ -529,6 +527,7 @@ private:
|
||||
break;
|
||||
}
|
||||
// fall through to step 0 for other characters
|
||||
RAPIDJSON_DELIBERATE_FALLTHROUGH;
|
||||
|
||||
case 0:
|
||||
{
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "../allocators.h"
|
||||
#include "swap.h"
|
||||
#include <cstddef>
|
||||
|
||||
#if defined(__clang__)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
@ -114,7 +115,7 @@ public:
|
||||
template<typename T>
|
||||
RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) {
|
||||
// Expand the stack if needed
|
||||
if (RAPIDJSON_UNLIKELY(stackTop_ + sizeof(T) * count > stackEnd_))
|
||||
if (RAPIDJSON_UNLIKELY(static_cast<std::ptrdiff_t>(sizeof(T) * count) > (stackEnd_ - stackTop_)))
|
||||
Expand<T>(count);
|
||||
}
|
||||
|
||||
@ -127,7 +128,7 @@ public:
|
||||
template<typename T>
|
||||
RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) {
|
||||
RAPIDJSON_ASSERT(stackTop_);
|
||||
RAPIDJSON_ASSERT(stackTop_ + sizeof(T) * count <= stackEnd_);
|
||||
RAPIDJSON_ASSERT(static_cast<std::ptrdiff_t>(sizeof(T) * count) <= (stackEnd_ - stackTop_));
|
||||
T* ret = reinterpret_cast<T*>(stackTop_);
|
||||
stackTop_ += sizeof(T) * count;
|
||||
return ret;
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "stream.h"
|
||||
#include <iosfwd>
|
||||
#include <ios>
|
||||
|
||||
#ifdef __clang__
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
|
@ -488,10 +488,11 @@ public:
|
||||
v = &((*v)[t->index]);
|
||||
}
|
||||
else {
|
||||
typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
|
||||
typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
|
||||
if (m == v->MemberEnd()) {
|
||||
v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator);
|
||||
v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end
|
||||
m = v->MemberEnd();
|
||||
v = &(--m)->value; // Assumes AddMember() appends at the end
|
||||
exist = false;
|
||||
}
|
||||
else
|
||||
@ -543,7 +544,7 @@ public:
|
||||
switch (v->GetType()) {
|
||||
case kObjectType:
|
||||
{
|
||||
typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
|
||||
typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
|
||||
if (m == v->MemberEnd())
|
||||
break;
|
||||
v = &m->value;
|
||||
@ -779,7 +780,7 @@ public:
|
||||
switch (v->GetType()) {
|
||||
case kObjectType:
|
||||
{
|
||||
typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
|
||||
typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
|
||||
if (m == v->MemberEnd())
|
||||
return false;
|
||||
v = &m->value;
|
||||
|
@ -60,7 +60,7 @@ public:
|
||||
|
||||
|
||||
explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
|
||||
Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {}
|
||||
Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
|
||||
|
||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
PrettyWriter(PrettyWriter&& rhs) :
|
||||
|
@ -490,6 +490,12 @@ RAPIDJSON_NAMESPACE_END
|
||||
#define RAPIDJSON_VERSION_CODE(x,y,z) \
|
||||
(((x)*100000) + ((y)*100) + (z))
|
||||
|
||||
#if defined(__has_builtin)
|
||||
#define RAPIDJSON_HAS_BUILTIN(x) __has_builtin(x)
|
||||
#else
|
||||
#define RAPIDJSON_HAS_BUILTIN(x) 0
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF
|
||||
|
||||
@ -591,6 +597,19 @@ RAPIDJSON_NAMESPACE_END
|
||||
#endif
|
||||
#endif // RAPIDJSON_HAS_CXX11_RANGE_FOR
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// C++17 features
|
||||
|
||||
#if defined(__has_cpp_attribute)
|
||||
# if __has_cpp_attribute(fallthrough)
|
||||
# define RAPIDJSON_DELIBERATE_FALLTHROUGH [[fallthrough]]
|
||||
# else
|
||||
# define RAPIDJSON_DELIBERATE_FALLTHROUGH
|
||||
# endif
|
||||
#else
|
||||
# define RAPIDJSON_DELIBERATE_FALLTHROUGH
|
||||
#endif
|
||||
|
||||
//!@endcond
|
||||
|
||||
//! Assertion (in non-throwing contexts).
|
||||
@ -607,15 +626,18 @@ RAPIDJSON_NAMESPACE_END
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// RAPIDJSON_NOEXCEPT_ASSERT
|
||||
|
||||
#ifndef RAPIDJSON_NOEXCEPT_ASSERT
|
||||
#ifdef RAPIDJSON_ASSERT_THROWS
|
||||
#if RAPIDJSON_HAS_CXX11_NOEXCEPT
|
||||
#define RAPIDJSON_NOEXCEPT_ASSERT(x)
|
||||
#else
|
||||
#define RAPIDJSON_NOEXCEPT_ASSERT(x) RAPIDJSON_ASSERT(x)
|
||||
#include <cassert>
|
||||
#define RAPIDJSON_NOEXCEPT_ASSERT(x) assert(x)
|
||||
#endif // RAPIDJSON_HAS_CXX11_NOEXCEPT
|
||||
#else
|
||||
#define RAPIDJSON_NOEXCEPT_ASSERT(x) RAPIDJSON_ASSERT(x)
|
||||
#endif // RAPIDJSON_ASSERT_THROWS
|
||||
#endif // RAPIDJSON_NOEXCEPT_ASSERT
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// malloc/realloc/free
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "allocators.h"
|
||||
#include "stream.h"
|
||||
#include "encodedstream.h"
|
||||
#include "internal/clzll.h"
|
||||
#include "internal/meta.h"
|
||||
#include "internal/stack.h"
|
||||
#include "internal/strtod.h"
|
||||
@ -153,6 +154,7 @@ enum ParseFlag {
|
||||
kParseNumbersAsStringsFlag = 64, //!< Parse all numbers (ints/doubles) as strings.
|
||||
kParseTrailingCommasFlag = 128, //!< Allow trailing commas at the end of objects and arrays.
|
||||
kParseNanAndInfFlag = 256, //!< Allow parsing NaN, Inf, Infinity, -Inf and -Infinity as doubles.
|
||||
kParseEscapedApostropheFlag = 512, //!< Allow escaped apostrophe in strings.
|
||||
kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS
|
||||
};
|
||||
|
||||
@ -443,16 +445,16 @@ inline const char *SkipWhitespace_SIMD(const char* p) {
|
||||
|
||||
x = vmvnq_u8(x); // Negate
|
||||
x = vrev64q_u8(x); // Rev in 64
|
||||
uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
|
||||
uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
|
||||
uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract
|
||||
uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract
|
||||
|
||||
if (low == 0) {
|
||||
if (high != 0) {
|
||||
int lz =__builtin_clzll(high);;
|
||||
uint32_t lz = internal::clzll(high);
|
||||
return p + 8 + (lz >> 3);
|
||||
}
|
||||
} else {
|
||||
int lz = __builtin_clzll(low);;
|
||||
uint32_t lz = internal::clzll(low);
|
||||
return p + (lz >> 3);
|
||||
}
|
||||
}
|
||||
@ -479,16 +481,16 @@ inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
|
||||
|
||||
x = vmvnq_u8(x); // Negate
|
||||
x = vrev64q_u8(x); // Rev in 64
|
||||
uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
|
||||
uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
|
||||
uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract
|
||||
uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract
|
||||
|
||||
if (low == 0) {
|
||||
if (high != 0) {
|
||||
int lz = __builtin_clzll(high);
|
||||
uint32_t lz = internal::clzll(high);
|
||||
return p + 8 + (lz >> 3);
|
||||
}
|
||||
} else {
|
||||
int lz = __builtin_clzll(low);
|
||||
uint32_t lz = internal::clzll(low);
|
||||
return p + (lz >> 3);
|
||||
}
|
||||
}
|
||||
@ -990,7 +992,7 @@ private:
|
||||
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
||||
#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
static const char escape[256] = {
|
||||
Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/',
|
||||
Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '/',
|
||||
Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
|
||||
0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0,
|
||||
0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
@ -1013,6 +1015,10 @@ private:
|
||||
is.Take();
|
||||
os.Put(static_cast<typename TEncoding::Ch>(escape[static_cast<unsigned char>(e)]));
|
||||
}
|
||||
else if ((parseFlags & kParseEscapedApostropheFlag) && RAPIDJSON_LIKELY(e == '\'')) { // Allow escaped apostrophe
|
||||
is.Take();
|
||||
os.Put('\'');
|
||||
}
|
||||
else if (RAPIDJSON_LIKELY(e == 'u')) { // Unicode
|
||||
is.Take();
|
||||
unsigned codepoint = ParseHex4(is, escapeOffset);
|
||||
@ -1244,19 +1250,19 @@ private:
|
||||
x = vorrq_u8(x, vcltq_u8(s, s3));
|
||||
|
||||
x = vrev64q_u8(x); // Rev in 64
|
||||
uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
|
||||
uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
|
||||
uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract
|
||||
uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract
|
||||
|
||||
SizeType length = 0;
|
||||
bool escaped = false;
|
||||
if (low == 0) {
|
||||
if (high != 0) {
|
||||
unsigned lz = (unsigned)__builtin_clzll(high);;
|
||||
uint32_t lz = internal::clzll(high);
|
||||
length = 8 + (lz >> 3);
|
||||
escaped = true;
|
||||
}
|
||||
} else {
|
||||
unsigned lz = (unsigned)__builtin_clzll(low);;
|
||||
uint32_t lz = internal::clzll(low);
|
||||
length = lz >> 3;
|
||||
escaped = true;
|
||||
}
|
||||
@ -1314,19 +1320,19 @@ private:
|
||||
x = vorrq_u8(x, vcltq_u8(s, s3));
|
||||
|
||||
x = vrev64q_u8(x); // Rev in 64
|
||||
uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
|
||||
uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
|
||||
uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract
|
||||
uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract
|
||||
|
||||
SizeType length = 0;
|
||||
bool escaped = false;
|
||||
if (low == 0) {
|
||||
if (high != 0) {
|
||||
unsigned lz = (unsigned)__builtin_clzll(high);
|
||||
uint32_t lz = internal::clzll(high);
|
||||
length = 8 + (lz >> 3);
|
||||
escaped = true;
|
||||
}
|
||||
} else {
|
||||
unsigned lz = (unsigned)__builtin_clzll(low);
|
||||
uint32_t lz = internal::clzll(low);
|
||||
length = lz >> 3;
|
||||
escaped = true;
|
||||
}
|
||||
@ -1370,17 +1376,17 @@ private:
|
||||
x = vorrq_u8(x, vcltq_u8(s, s3));
|
||||
|
||||
x = vrev64q_u8(x); // Rev in 64
|
||||
uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
|
||||
uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
|
||||
uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract
|
||||
uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract
|
||||
|
||||
if (low == 0) {
|
||||
if (high != 0) {
|
||||
int lz = __builtin_clzll(high);
|
||||
uint32_t lz = internal::clzll(high);
|
||||
p += 8 + (lz >> 3);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
int lz = __builtin_clzll(low);
|
||||
uint32_t lz = internal::clzll(low);
|
||||
p += lz >> 3;
|
||||
break;
|
||||
}
|
||||
@ -1403,7 +1409,7 @@ private:
|
||||
RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); }
|
||||
RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); }
|
||||
RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); }
|
||||
RAPIDJSON_FORCEINLINE void Push(char) {}
|
||||
RAPIDJSON_FORCEINLINE void Push(char) {}
|
||||
|
||||
size_t Tell() { return is.Tell(); }
|
||||
size_t Length() { return 0; }
|
||||
|
@ -443,7 +443,6 @@ public:
|
||||
exclusiveMaximum_(false),
|
||||
defaultValueLength_(0)
|
||||
{
|
||||
typedef typename SchemaDocumentType::ValueType ValueType;
|
||||
typedef typename ValueType::ConstValueIterator ConstValueIterator;
|
||||
typedef typename ValueType::ConstMemberIterator ConstMemberIterator;
|
||||
|
||||
@ -899,7 +898,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
SizeType index;
|
||||
SizeType index = 0;
|
||||
if (FindPropertyIndex(ValueType(str, len).Move(), &index)) {
|
||||
if (context.patternPropertiesSchemaCount > 0) {
|
||||
context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema;
|
||||
@ -1149,7 +1148,7 @@ private:
|
||||
#elif RAPIDJSON_SCHEMA_USE_STDREGEX
|
||||
template <typename ValueType>
|
||||
RegexType* CreatePattern(const ValueType& value) {
|
||||
if (value.IsString())
|
||||
if (value.IsString()) {
|
||||
RegexType *r = static_cast<RegexType*>(allocator_->Malloc(sizeof(RegexType)));
|
||||
try {
|
||||
return new (r) RegexType(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript);
|
||||
@ -1157,6 +1156,7 @@ private:
|
||||
catch (const std::regex_error&) {
|
||||
AllocatorType::Free(r);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#define RAPIDJSON_WRITER_H_
|
||||
|
||||
#include "stream.h"
|
||||
#include "internal/clzll.h"
|
||||
#include "internal/meta.h"
|
||||
#include "internal/stack.h"
|
||||
#include "internal/strfunc.h"
|
||||
@ -226,7 +227,7 @@ public:
|
||||
return Key(str.data(), SizeType(str.size()));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool EndObject(SizeType memberCount = 0) {
|
||||
(void)memberCount;
|
||||
RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); // not inside an Object
|
||||
@ -282,6 +283,8 @@ public:
|
||||
os_->Flush();
|
||||
}
|
||||
|
||||
static const size_t kDefaultLevelDepth = 32;
|
||||
|
||||
protected:
|
||||
//! Information for each nested level
|
||||
struct Level {
|
||||
@ -290,8 +293,6 @@ protected:
|
||||
bool inArray; //!< true if in array, otherwise in object
|
||||
};
|
||||
|
||||
static const size_t kDefaultLevelDepth = 32;
|
||||
|
||||
bool WriteNull() {
|
||||
PutReserve(*os_, 4);
|
||||
PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true;
|
||||
@ -668,19 +669,19 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz
|
||||
x = vorrq_u8(x, vcltq_u8(s, s3));
|
||||
|
||||
x = vrev64q_u8(x); // Rev in 64
|
||||
uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
|
||||
uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
|
||||
uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract
|
||||
uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract
|
||||
|
||||
SizeType len = 0;
|
||||
bool escaped = false;
|
||||
if (low == 0) {
|
||||
if (high != 0) {
|
||||
unsigned lz = (unsigned)__builtin_clzll(high);
|
||||
uint32_t lz = internal::clzll(high);
|
||||
len = 8 + (lz >> 3);
|
||||
escaped = true;
|
||||
}
|
||||
} else {
|
||||
unsigned lz = (unsigned)__builtin_clzll(low);
|
||||
uint32_t lz = internal::clzll(low);
|
||||
len = lz >> 3;
|
||||
escaped = true;
|
||||
}
|
||||
|
50
readme.md
50
readme.md
@ -72,6 +72,9 @@ Users can build and run the unit tests on their platform/compiler.
|
||||
|
||||
RapidJSON is a header-only C++ library. Just copy the `include/rapidjson` folder to system or project's include path.
|
||||
|
||||
Alternatively, if you are using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager you can download and install rapidjson with CMake integration in a single command:
|
||||
* vcpkg install rapidjson
|
||||
|
||||
RapidJSON uses following software as its dependencies:
|
||||
* [CMake](https://cmake.org/) as a general build tool
|
||||
* (optional) [Doxygen](http://www.doxygen.org) to build documentation
|
||||
@ -158,3 +161,50 @@ More [examples](https://github.com/Tencent/rapidjson/tree/master/example) are av
|
||||
* [parsebyparts](https://github.com/Tencent/rapidjson/blob/master/example/parsebyparts/parsebyparts.cpp): Implements an `AsyncDocumentParser` which can parse JSON in parts, using C++11 thread.
|
||||
* [filterkey](https://github.com/Tencent/rapidjson/blob/master/example/filterkey/filterkey.cpp): A command line tool to remove all values with user-specified key.
|
||||
* [filterkeydom](https://github.com/Tencent/rapidjson/blob/master/example/filterkeydom/filterkeydom.cpp): Same tool as above, but it demonstrates how to use a generator to populate a `Document`.
|
||||
|
||||
## Contributing
|
||||
|
||||
RapidJSON welcomes contributions. When contributing, please follow the code below.
|
||||
|
||||
### Issues
|
||||
|
||||
Feel free to submit issues and enhancement requests.
|
||||
|
||||
Please help us by providing **minimal reproducible examples**, because source code is easier to let other people understand what happens.
|
||||
For crash problems on certain platforms, please bring stack dump content with the detail of the OS, compiler, etc.
|
||||
|
||||
Please try breakpoint debugging first, tell us what you found, see if we can start exploring based on more information been prepared.
|
||||
|
||||
### Workflow
|
||||
|
||||
In general, we follow the "fork-and-pull" Git workflow.
|
||||
|
||||
1. **Fork** the repo on GitHub
|
||||
2. **Clone** the project to your own machine
|
||||
3. **Checkout** a new branch on your fork, start developing on the branch
|
||||
4. **Test** the change before commit, Make sure the changes pass all the tests, including `unittest` and `preftest`, please add test case for each new feature or bug-fix if needed.
|
||||
5. **Commit** changes to your own branch
|
||||
6. **Push** your work back up to your fork
|
||||
7. Submit a **Pull request** so that we can review your changes
|
||||
|
||||
NOTE: Be sure to merge the latest from "upstream" before making a pull request!
|
||||
|
||||
### Copyright and Licensing
|
||||
|
||||
You can copy and paste the license summary from below.
|
||||
|
||||
```
|
||||
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.
|
||||
```
|
@ -674,6 +674,9 @@ TEST(Pointer, Get) {
|
||||
EXPECT_EQ(2u, unresolvedTokenIndex);
|
||||
EXPECT_TRUE(Pointer("/foo/0/a").Get(d, &unresolvedTokenIndex) == 0); // "/foo/0" is an string, cannot further query
|
||||
EXPECT_EQ(2u, unresolvedTokenIndex);
|
||||
|
||||
Pointer::Token tokens[] = { { "foo ...", 3, kPointerInvalidIndex } };
|
||||
EXPECT_EQ(&d["foo"], Pointer(tokens, 1).Get(d));
|
||||
}
|
||||
|
||||
TEST(Pointer, GetWithDefault) {
|
||||
|
@ -2198,4 +2198,28 @@ TEST(Reader, ParseNanAndInfinity) {
|
||||
#undef TEST_NAN_INF
|
||||
}
|
||||
|
||||
TEST(Reader, EscapedApostrophe) {
|
||||
const char json[] = " { \"foo\": \"bar\\'buzz\" } ";
|
||||
|
||||
BaseReaderHandler<> h;
|
||||
|
||||
{
|
||||
StringStream s(json);
|
||||
Reader reader;
|
||||
ParseResult r = reader.Parse<kParseNoFlags>(s, h);
|
||||
EXPECT_TRUE(reader.HasParseError());
|
||||
EXPECT_EQ(kParseErrorStringEscapeInvalid, r.Code());
|
||||
EXPECT_EQ(14u, r.Offset());
|
||||
}
|
||||
|
||||
{
|
||||
StringStream s(json);
|
||||
Reader reader;
|
||||
ParseResult r = reader.Parse<kParseEscapedApostropheFlag>(s, h);
|
||||
EXPECT_FALSE(reader.HasParseError());
|
||||
EXPECT_EQ(kParseErrorNone, r.Code());
|
||||
EXPECT_EQ(0u, r.Offset());
|
||||
}
|
||||
}
|
||||
|
||||
RAPIDJSON_DIAG_POP
|
||||
|
@ -122,6 +122,9 @@ public:
|
||||
|
||||
#ifndef RAPIDJSON_ASSERT
|
||||
#define RAPIDJSON_ASSERT(x) (!(x) ? throw AssertException(RAPIDJSON_STRINGIFY(x)) : (void)0u)
|
||||
#ifndef RAPIDJSON_ASSERT_THROWS
|
||||
#define RAPIDJSON_ASSERT_THROWS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
class Random {
|
||||
|
@ -4,9 +4,8 @@
|
||||
|
||||
set -e
|
||||
|
||||
DOXYGEN_VER=doxygen-1.8.13
|
||||
DOXYGEN_TAR=${DOXYGEN_VER}.linux.bin.tar.gz
|
||||
DOXYGEN_URL="http://ftp.stack.nl/pub/users/dimitri/${DOXYGEN_TAR}"
|
||||
DOXYGEN_VER=1_8_16
|
||||
DOXYGEN_URL="https://codeload.github.com/doxygen/doxygen/tar.gz/Release_${DOXYGEN_VER}"
|
||||
|
||||
: ${GITHUB_REPO:="Tencent/rapidjson"}
|
||||
GITHUB_HOST="github.com"
|
||||
@ -47,9 +46,17 @@ abort() {
|
||||
# install doxygen binary distribution
|
||||
doxygen_install()
|
||||
{
|
||||
wget -O - "${DOXYGEN_URL}" | \
|
||||
tar xz -C ${TMPDIR-/tmp} ${DOXYGEN_VER}/bin/doxygen
|
||||
export PATH="${TMPDIR-/tmp}/${DOXYGEN_VER}/bin:$PATH"
|
||||
cd ${TMPDIR-/tmp}
|
||||
curl ${DOXYGEN_URL} -o doxygen.tar.gz
|
||||
tar zxvf doxygen.tar.gz
|
||||
mkdir doxygen_build
|
||||
cd doxygen_build
|
||||
cmake ../doxygen-Release_${DOXYGEN_VER}/
|
||||
make
|
||||
|
||||
export PATH="${TMPDIR-/tmp}/doxygen_build/bin:$PATH"
|
||||
|
||||
cd ../../
|
||||
}
|
||||
|
||||
doxygen_run()
|
||||
|
Loading…
x
Reference in New Issue
Block a user