From 678f8da95b47a7749afc7a9cb556d435a4be38df Mon Sep 17 00:00:00 2001 From: Sleepy Flower Girl Date: Mon, 28 May 2018 17:39:58 -0400 Subject: [PATCH] Moved Discord RPC library's source code to external --- Externals/discord-rpc/CMakeLists.txt | 56 + Externals/discord-rpc/LICENSE | 19 + Externals/discord-rpc/README.md | 91 + Externals/discord-rpc/bin/discord-rpc.dll | Bin 400392 -> 0 bytes Externals/discord-rpc/build.py | 304 ++ .../discord-rpc/include/discord_register.h | 20 +- Externals/discord-rpc/lib/discord-rpc.lib | Bin 3622 -> 0 bytes .../discord-rpc/lib/libdiscord-rpc.dylib | Bin 260256 -> 0 bytes Externals/discord-rpc/lib/libdiscord-rpc.so | Bin 661146 -> 0 bytes Externals/discord-rpc/src/CMakeLists.txt | 142 + Externals/discord-rpc/src/backoff.h | 40 + Externals/discord-rpc/src/connection.h | 19 + Externals/discord-rpc/src/connection_unix.cpp | 122 + Externals/discord-rpc/src/connection_win.cpp | 128 + Externals/discord-rpc/src/discord-rpc.vcxproj | 93 + .../src/discord_register_linux.cpp | 100 + .../discord-rpc/src/discord_register_osx.m | 80 + .../discord-rpc/src/discord_register_win.cpp | 185 ++ Externals/discord-rpc/src/discord_rpc.cpp | 499 ++++ Externals/discord-rpc/src/dllmain.cpp | 8 + Externals/discord-rpc/src/msg_queue.h | 36 + Externals/discord-rpc/src/rpc_connection.cpp | 141 + Externals/discord-rpc/src/rpc_connection.h | 59 + Externals/discord-rpc/src/serialization.cpp | 245 ++ Externals/discord-rpc/src/serialization.h | 215 ++ .../thirdparty/include/rapidjson/allocators.h | 271 ++ .../thirdparty/include/rapidjson/document.h | 2575 +++++++++++++++++ .../include/rapidjson/encodedstream.h | 299 ++ .../thirdparty/include/rapidjson/encodings.h | 716 +++++ .../thirdparty/include/rapidjson/error/en.h | 74 + .../include/rapidjson/error/error.h | 155 + .../include/rapidjson/filereadstream.h | 99 + .../include/rapidjson/filewritestream.h | 104 + .../thirdparty/include/rapidjson/fwd.h | 151 + .../include/rapidjson/internal/biginteger.h | 290 ++ .../include/rapidjson/internal/diyfp.h | 258 ++ .../include/rapidjson/internal/dtoa.h | 245 ++ .../include/rapidjson/internal/ieee754.h | 78 + .../include/rapidjson/internal/itoa.h | 304 ++ .../include/rapidjson/internal/meta.h | 181 ++ .../include/rapidjson/internal/pow10.h | 55 + .../include/rapidjson/internal/regex.h | 701 +++++ .../include/rapidjson/internal/stack.h | 230 ++ .../include/rapidjson/internal/strfunc.h | 55 + .../include/rapidjson/internal/strtod.h | 269 ++ .../include/rapidjson/internal/swap.h | 46 + .../include/rapidjson/istreamwrapper.h | 115 + .../include/rapidjson/memorybuffer.h | 70 + .../include/rapidjson/memorystream.h | 71 + .../include/rapidjson/msinttypes/inttypes.h | 316 ++ .../include/rapidjson/msinttypes/stdint.h | 300 ++ .../include/rapidjson/ostreamwrapper.h | 81 + .../thirdparty/include/rapidjson/pointer.h | 1358 +++++++++ .../include/rapidjson/prettywriter.h | 255 ++ .../thirdparty/include/rapidjson/rapidjson.h | 615 ++++ .../thirdparty/include/rapidjson/reader.h | 1879 ++++++++++++ .../thirdparty/include/rapidjson/schema.h | 2006 +++++++++++++ .../thirdparty/include/rapidjson/stream.h | 179 ++ .../include/rapidjson/stringbuffer.h | 117 + .../thirdparty/include/rapidjson/writer.h | 610 ++++ Source/Core/DolphinQt2/DolphinQt2.vcxproj | 2 +- Source/Core/DolphinWX/DolphinWX.vcxproj | 2 +- Source/Core/UICommon/CMakeLists.txt | 2 +- Source/Core/UICommon/UICommon.vcxproj | 13 +- Source/UnitTests/UnitTests.vcxproj | 2 +- Source/VSProps/Base.props | 1 + Source/dolphin-emu.sln | 7 + 67 files changed, 17735 insertions(+), 24 deletions(-) create mode 100644 Externals/discord-rpc/CMakeLists.txt create mode 100644 Externals/discord-rpc/LICENSE create mode 100644 Externals/discord-rpc/README.md delete mode 100644 Externals/discord-rpc/bin/discord-rpc.dll create mode 100644 Externals/discord-rpc/build.py delete mode 100644 Externals/discord-rpc/lib/discord-rpc.lib delete mode 100644 Externals/discord-rpc/lib/libdiscord-rpc.dylib delete mode 100644 Externals/discord-rpc/lib/libdiscord-rpc.so create mode 100644 Externals/discord-rpc/src/CMakeLists.txt create mode 100644 Externals/discord-rpc/src/backoff.h create mode 100644 Externals/discord-rpc/src/connection.h create mode 100644 Externals/discord-rpc/src/connection_unix.cpp create mode 100644 Externals/discord-rpc/src/connection_win.cpp create mode 100644 Externals/discord-rpc/src/discord-rpc.vcxproj create mode 100644 Externals/discord-rpc/src/discord_register_linux.cpp create mode 100644 Externals/discord-rpc/src/discord_register_osx.m create mode 100644 Externals/discord-rpc/src/discord_register_win.cpp create mode 100644 Externals/discord-rpc/src/discord_rpc.cpp create mode 100644 Externals/discord-rpc/src/dllmain.cpp create mode 100644 Externals/discord-rpc/src/msg_queue.h create mode 100644 Externals/discord-rpc/src/rpc_connection.cpp create mode 100644 Externals/discord-rpc/src/rpc_connection.h create mode 100644 Externals/discord-rpc/src/serialization.cpp create mode 100644 Externals/discord-rpc/src/serialization.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/allocators.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/document.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/encodedstream.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/encodings.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/error/en.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/error/error.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/filereadstream.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/filewritestream.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/fwd.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/internal/biginteger.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/internal/diyfp.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/internal/dtoa.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/internal/ieee754.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/internal/itoa.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/internal/meta.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/internal/pow10.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/internal/regex.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/internal/stack.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/internal/strfunc.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/internal/strtod.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/internal/swap.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/istreamwrapper.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/memorybuffer.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/memorystream.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/msinttypes/inttypes.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/msinttypes/stdint.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/ostreamwrapper.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/pointer.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/prettywriter.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/rapidjson.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/reader.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/schema.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/stream.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/stringbuffer.h create mode 100644 Externals/discord-rpc/thirdparty/include/rapidjson/writer.h diff --git a/Externals/discord-rpc/CMakeLists.txt b/Externals/discord-rpc/CMakeLists.txt new file mode 100644 index 0000000000..5dad9e9f6d --- /dev/null +++ b/Externals/discord-rpc/CMakeLists.txt @@ -0,0 +1,56 @@ +cmake_minimum_required (VERSION 3.2.0) +project (DiscordRPC) + +include(GNUInstallDirs) + +option(BUILD_EXAMPLES "Build example apps" ON) + +# format +file(GLOB_RECURSE ALL_SOURCE_FILES + examples/*.cpp examples/*.h examples/*.c + include/*.h + src/*.cpp src/*.h src/*.c +) + +# Set CLANG_FORMAT_SUFFIX if you are using custom clang-format, e.g. clang-format-5.0 +find_program(CLANG_FORMAT_CMD clang-format${CLANG_FORMAT_SUFFIX}) + +if (CLANG_FORMAT_CMD) + add_custom_target( + clangformat + COMMAND ${CLANG_FORMAT_CMD} + -i -style=file -fallback-style=none + ${ALL_SOURCE_FILES} + DEPENDS + ${ALL_SOURCE_FILES} + ) +endif(CLANG_FORMAT_CMD) + +# thirdparty stuff +execute_process( + COMMAND mkdir ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty + ERROR_QUIET +) + +find_file(RAPIDJSONTEST NAMES rapidjson rapidjson-1.1.0 PATHS ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty CMAKE_FIND_ROOT_PATH_BOTH) +if (NOT RAPIDJSONTEST) + message("no rapidjson, download") + set(RJ_TAR_FILE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/v1.1.0.tar.gz) + file(DOWNLOAD https://github.com/miloyip/rapidjson/archive/v1.1.0.tar.gz ${RJ_TAR_FILE}) + execute_process( + COMMAND ${CMAKE_COMMAND} -E tar xzf ${RJ_TAR_FILE} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty + ) + file(REMOVE ${RJ_TAR_FILE}) +endif(NOT RAPIDJSONTEST) + +find_file(RAPIDJSON NAMES rapidjson rapidjson-1.1.0 PATHS ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty CMAKE_FIND_ROOT_PATH_BOTH) + +add_library(rapidjson STATIC IMPORTED ${RAPIDJSON}) + +# add subdirs + +add_subdirectory(src) +if (BUILD_EXAMPLES) + add_subdirectory(examples/send-presence) +endif(BUILD_EXAMPLES) diff --git a/Externals/discord-rpc/LICENSE b/Externals/discord-rpc/LICENSE new file mode 100644 index 0000000000..17fca3d50f --- /dev/null +++ b/Externals/discord-rpc/LICENSE @@ -0,0 +1,19 @@ +Copyright 2017 Discord, Inc. + +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. diff --git a/Externals/discord-rpc/README.md b/Externals/discord-rpc/README.md new file mode 100644 index 0000000000..011c961755 --- /dev/null +++ b/Externals/discord-rpc/README.md @@ -0,0 +1,91 @@ +# Discord RPC + +This is a library for interfacing your game with a locally running Discord desktop client. It's known to work on Windows, macOS, and Linux. You can use the lib directly if you like, or use it as a guide to writing your own if it doesn't suit your game as is. PRs/feedback welcome if you have an improvement everyone might want, or can describe how this doesn't meet your needs. + +Included here are some quick demos that implement the very minimal subset to show current status, and +have callbacks for where a more complete game would do more things (joining, spectating, etc). + +## Documentation + +The most up to date documentation for Rich Presence can always be found on our [developer site](https://discordapp.com/developers/docs/rich-presence/how-to)! If you're interested in rolling your own native implementation of Rich Presence via IPC sockets instead of using our SDK—hey, you've got free time, right?—check out the ["Hard Mode" documentation](https://github.com/discordapp/discord-rpc/blob/master/documentation/hard-mode.md). + +## Basic Usage + +Zeroith, you should be set up to build things because you are a game developer, right? + +First, head on over to the [Discord developers site](https://discordapp.com/developers/applications/me) and make yourself an app. Keep track of `Client ID` -- you'll need it here to pass to the init function. + +### From package + +Download a release package for your platform(s) -- they have subdirs with various prebuilt options, select the one you need add `/include` to your compile includes, `/lib` to your linker paths, and link with `discord-rpc`. For the dynamically linked builds, you'll need to ship the associated file along with your game. + +### From repo + +First-eth, you'll want `CMake`. There's a few different ways to install it on your system, and you should refer to [their website](https://cmake.org/install/). Many package managers provide ways of installing CMake as well. + +To make sure it's installed correctly, type `cmake --version` into your flavor of terminal/cmd. If you get a response with a version number, you're good to go! + +There's a [CMake](https://cmake.org/download/) file that should be able to generate the lib for you; Sometimes I use it like this: +```sh + cd + mkdir build + cd build + cmake .. -DCMAKE_INSTALL_PREFIX= + cmake --build . --config Release --target install +``` +There is a wrapper build script `build.py` that runs `cmake` with a few different options. + +Usually, I run `build.py` to get things started, then use the generated project files as I work on things. It does depend on `click` library, so do a quick `pip install click` to make sure you have it if you want to run `build.py`. + +There are some CMake options you might care about: + +| flag | default | does | +|------|---------|------| +| `ENABLE_IO_THREAD` | `ON` | When enabled, we start up a thread to do io processing, if disabled you should call `Discord_UpdateConnection` yourself. +| `USE_STATIC_CRT` | `OFF` | (Windows) Enable to statically link the CRT, avoiding requiring users install the redistributable package. (The prebuilt binaries enable this option) +| [`BUILD_SHARED_LIBS`](https://cmake.org/cmake/help/v3.7/variable/BUILD_SHARED_LIBS.html) | `OFF` | Build library as a DLL +| `WARNINGS_AS_ERRORS` | `OFF` | When enabled, compiles with `-Werror` (on *nix platforms). | + +## Continuous Builds + +Why do we have three of these? Three times the fun! + +| CI | badge | +|----|-------| +| TravisCI | [![Build status](https://travis-ci.org/discordapp/discord-rpc.svg?branch=master)](https://travis-ci.org/discordapp/discord-rpc) +| AppVeyor | [![Build status](https://ci.appveyor.com/api/projects/status/qvkoc0w1c4f4b8tj?svg=true)](https://ci.appveyor.com/project/crmarsh/discord-rpc) +| Buildkite (internal) | [![Build status](https://badge.buildkite.com/e103d79d247f6776605a15246352a04b8fd83d69211b836111.svg)](https://buildkite.com/discord/discord-rpc) + +## Sample: send-presence + +This is a text adventure "game" that inits/deinits the connection to Discord, and sends a presence update on each command. + +## Sample: button-clicker + +This is a sample [Unity](https://unity3d.com/) project that wraps a DLL version of the library, and sends presence updates when you click on a button. Run `python build.py unity` in the root directory to build the correct library files and place them in their respective folders. + +## Sample: unrealstatus + +This is a sample [Unreal](https://www.unrealengine.com) project that wraps the DLL version of the library with an Unreal plugin, exposes a blueprint class for interacting with it, and uses that to make a very simple UI. Run `python build.py unreal` in the root directory to build the correct library files and place them in their respective folders. + +## Wrappers and Implementations + +Below is a table of unofficial, community-developed wrappers for and implementations of Rich Presence in various languages. If you would like to have yours added, please make a pull request adding your repository to the table. The repository should include: + +- The code +- A brief ReadMe of how to use it +- A working example + +###### Rich Presence Wrappers and Implementations + +| Name | Language | +|------|----------| +| [DerelictDiscordRPC](https://github.com/voidblaster/DerelictDiscordRPC) | [D](https://dlang.org/) | +| [discord-rpc.jar](https://github.com/Vatuu/discord-rpc "Discord-RPC.jar") | Java | +| [java-discord-rpc](https://github.com/MinnDevelopment/java-discord-rpc) | Java | +| [Discord-IPC](https://github.com/jagrosh/DiscordIPC) | Java | +| [Discord Rich Presence](https://npmjs.org/discord-rich-presence) | JavaScript | +| [drpc4k](https://github.com/Bluexin/drpc4k) | [Kotlin](https://kotlinlang.org/) | +| [lua-discordRPC](https://github.com/pfirsich/lua-discordRPC) | LuaJIT (FFI) | +| [pypresence](https://github.com/qwertyquerty/pypresence) | [Python](https://python.org/) | +| [SwordRPC](https://github.com/Azoy/SwordRPC) | [Swift](https://swift.org) | diff --git a/Externals/discord-rpc/bin/discord-rpc.dll b/Externals/discord-rpc/bin/discord-rpc.dll deleted file mode 100644 index 289d550306073492d7b88fac35e302b1bc1bfab2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 400392 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

7CBb)dE2ptDgtTECSZb^L$C#X6Ov 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 diff --git a/Externals/discord-rpc/build.py b/Externals/discord-rpc/build.py new file mode 100644 index 0000000000..215d3586b3 --- /dev/null +++ b/Externals/discord-rpc/build.py @@ -0,0 +1,304 @@ +#!/usr/bin/env python + +import os +import subprocess +import sys +import shutil +import zipfile +from contextlib import contextmanager +import click + + +def get_platform(): + """ a name for the platform """ + if sys.platform.startswith('win'): + return 'win' + elif sys.platform == 'darwin': + return 'osx' + elif sys.platform.startswith('linux'): + return 'linux' + raise Exception('Unsupported platform ' + sys.platform) + + +SCRIPT_PATH = os.path.dirname(os.path.abspath(__file__)) +# we use Buildkite which sets this env variable by default +IS_BUILD_MACHINE = os.environ.get('CI', '') == 'true' +PLATFORM = get_platform() +INSTALL_ROOT = os.path.join(SCRIPT_PATH, 'builds', 'install') + + +def get_signtool(): + """ get path to code signing tool """ + if PLATFORM == 'win': + sdk_dir = 'c:\\Program Files (x86)\\Windows Kits\\10' # os.environ['WindowsSdkDir'] + return os.path.join(sdk_dir, 'bin', 'x86', 'signtool.exe') + elif PLATFORM == 'osx': + return '/usr/bin/codesign' + + +@contextmanager +def cd(new_dir): + """ Temporarily change current directory """ + if new_dir: + old_dir = os.getcwd() + os.chdir(new_dir) + yield + if new_dir: + os.chdir(old_dir) + + +def mkdir_p(path): + """ mkdir -p """ + if not os.path.isdir(path): + click.secho('Making ' + path, fg='yellow') + os.makedirs(path) + + +@click.group(invoke_without_command=True) +@click.pass_context +@click.option('--clean', is_flag=True) +def cli(ctx, clean): + """ click wrapper for command line stuff """ + if ctx.invoked_subcommand is None: + ctx.invoke(libs, clean=clean) + if IS_BUILD_MACHINE: + ctx.invoke(sign) + ctx.invoke(archive) + + +@cli.command() +@click.pass_context +def unity(ctx): + """ build just dynamic libs for use in unity project """ + ctx.invoke(libs, clean=False, static=False, shared=True, skip_formatter=True, just_release=True) + BUILDS = [] + + click.echo('--- Copying libs and header into unity example') + UNITY_PROJECT_PATH = os.path.join(SCRIPT_PATH, 'examples', 'button-clicker', 'Assets', 'Plugins') + + if sys.platform.startswith('win'): + LIBRARY_NAME = 'discord-rpc.dll' + BUILD_64_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'win64-dynamic', 'src', 'Release') + UNITY_64_DLL_PATH = os.path.join(UNITY_PROJECT_PATH, 'x86_64') + BUILDS.append({BUILD_64_BASE_PATH: UNITY_64_DLL_PATH}) + + BUILD_32_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'win32-dynamic', 'src', 'Release') + UNITY_32_DLL_PATH = os.path.join(UNITY_PROJECT_PATH, 'x86') + BUILDS.append({BUILD_32_BASE_PATH: UNITY_32_DLL_PATH}) + + elif sys.platform == 'darwin': + LIBRARY_NAME = 'discord-rpc.bundle' + BUILD_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'osx-dynamic', 'src') + UNITY_DLL_PATH = UNITY_PROJECT_PATH + os.rename( + os.path.join(BUILD_BASE_PATH, 'libdiscord-rpc.dylib'), os.path.join(BUILD_BASE_PATH, 'discord-rpc.bundle')) + + BUILDS.append({BUILD_BASE_PATH: UNITY_DLL_PATH}) + + elif sys.platform.startswith('linux'): + LIBRARY_NAME = 'discord-rpc.so' + BUILD_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'linux-dynamic', 'src') + UNITY_DLL_PATH = os.path.join(UNITY_PROJECT_PATH, 'x86') + os.rename(os.path.join(BUILD_BASE_PATH, 'libdiscord-rpc.so'), os.path.join(BUILD_BASE_PATH, 'discord-rpc.so')) + + BUILDS.append({BUILD_BASE_PATH: UNITY_DLL_PATH}) + + else: + raise Exception('Unsupported platform ' + sys.platform) + + for build in BUILDS: + for i in build: + mkdir_p(build[i]) + shutil.copy(os.path.join(i, LIBRARY_NAME), build[i]) + + +@cli.command() +@click.pass_context +def unreal(ctx): + """ build libs and copy them into the unreal project """ + ctx.invoke(libs, clean=False, static=False, shared=True, skip_formatter=True, just_release=True) + BUILDS = [] + + click.echo('--- Copying libs and header into unreal example') + UNREAL_PROJECT_PATH = os.path.join(SCRIPT_PATH, 'examples', 'unrealstatus', 'Plugins', 'discordrpc') + UNREAL_INCLUDE_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'DiscordRpcLibrary', 'Include') + mkdir_p(UNREAL_INCLUDE_PATH) + shutil.copy(os.path.join(SCRIPT_PATH, 'include', 'discord_rpc.h'), UNREAL_INCLUDE_PATH) + + if sys.platform.startswith('win'): + LIBRARY_NAME = 'discord-rpc.lib' + BUILD_64_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'win64-dynamic', 'src', 'Release') + UNREAL_64_DLL_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'DiscordRpcLibrary', 'Win64') + BUILDS.append({BUILD_64_BASE_PATH: UNREAL_64_DLL_PATH}) + + BUILD_32_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'win32-dynamic', 'src', 'Release') + UNREAL_32_DLL_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'DiscordRpcLibrary', 'Win32') + BUILDS.append({BUILD_32_BASE_PATH: UNREAL_32_DLL_PATH}) + + elif sys.platform == 'darwin': + LIBRARY_NAME = 'libdiscord-rpc.dylib' + BUILD_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'osx-dynamic', 'src') + UNREAL_DLL_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'DiscordRpcLibrary', 'Mac') + + BUILDS.append({BUILD_BASE_PATH: UNREAL_DLL_PATH}) + + elif sys.platform.startswith('linux'): + LIBRARY_NAME = 'libdiscord-rpc.so' + BUILD_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'linux-dynamic', 'src') + UNREAL_DLL_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'DiscordRpcLibrary', 'Linux') + + BUILDS.append({BUILD_BASE_PATH: UNREAL_DLL_PATH}) + + else: + raise Exception('Unsupported platform ' + sys.platform) + + for build in BUILDS: + for i in build: + mkdir_p(build[i]) + shutil.copy(os.path.join(i, LIBRARY_NAME), build[i]) + + +def build_lib(build_name, generator, options, just_release): + """ Create a dir under builds, run build and install in it """ + build_path = os.path.join(SCRIPT_PATH, 'builds', build_name) + install_path = os.path.join(INSTALL_ROOT, build_name) + mkdir_p(build_path) + mkdir_p(install_path) + with cd(build_path): + initial_cmake = ['cmake', SCRIPT_PATH, '-DCMAKE_INSTALL_PREFIX=%s' % os.path.join('..', 'install', build_name)] + if generator: + initial_cmake.extend(['-G', generator]) + for key in options: + val = options[key] + if type(val) is bool: + val = 'ON' if val else 'OFF' + initial_cmake.append('-D%s=%s' % (key, val)) + click.echo('--- Building ' + build_name) + subprocess.check_call(initial_cmake) + if not just_release: + subprocess.check_call(['cmake', '--build', '.', '--config', 'Debug']) + subprocess.check_call(['cmake', '--build', '.', '--config', 'Release', '--target', 'install']) + + +@cli.command() +def archive(): + """ create zip of install dir """ + click.echo('--- Archiving') + archive_file_path = os.path.join(SCRIPT_PATH, 'builds', 'discord-rpc-%s.zip' % get_platform()) + archive_file = zipfile.ZipFile(archive_file_path, 'w', zipfile.ZIP_DEFLATED) + archive_src_base_path = INSTALL_ROOT + archive_dst_base_path = 'discord-rpc' + with cd(archive_src_base_path): + for path, _, filenames in os.walk('.'): + for fname in filenames: + fpath = os.path.join(path, fname) + dst_path = os.path.normpath(os.path.join(archive_dst_base_path, fpath)) + click.echo('Adding ' + dst_path) + archive_file.write(fpath, dst_path) + + +@cli.command() +def sign(): + """ Do code signing within install directory using our cert """ + tool = get_signtool() + signable_extensions = set() + if PLATFORM == 'win': + signable_extensions.add('.dll') + sign_command_base = [ + tool, + 'sign', + '/n', + 'Discord Inc.', + '/a', + '/tr', + 'http://timestamp.digicert.com/rfc3161', + '/as', + '/td', + 'sha256', + '/fd', + 'sha256', + ] + elif PLATFORM == 'osx': + signable_extensions.add('.dylib') + sign_command_base = [ + tool, + '--keychain', + os.path.expanduser('~/Library/Keychains/login.keychain'), + '-vvvv', + '--deep', + '--force', + '--sign', + 'Developer ID Application: Hammer & Chisel Inc. (53Q6R32WPB)', + ] + else: + click.secho('Not signing things on this platform yet', fg='red') + return + + click.echo('--- Signing') + for path, _, filenames in os.walk(INSTALL_ROOT): + for fname in filenames: + ext = os.path.splitext(fname)[1] + if ext not in signable_extensions: + continue + fpath = os.path.join(path, fname) + click.echo('Sign ' + fpath) + sign_command = sign_command_base + [fpath] + subprocess.check_call(sign_command) + + +@cli.command() +@click.option('--clean', is_flag=True) +@click.option('--static', is_flag=True) +@click.option('--shared', is_flag=True) +@click.option('--skip_formatter', is_flag=True) +@click.option('--just_release', is_flag=True) +def libs(clean, static, shared, skip_formatter, just_release): + """ Do all the builds for this platform """ + if clean: + shutil.rmtree('builds', ignore_errors=True) + + mkdir_p('builds') + + if not (static or shared): + static = True + shared = True + + static_options = {} + dynamic_options = { + 'BUILD_SHARED_LIBS': True, + 'USE_STATIC_CRT': True, + } + + if skip_formatter or IS_BUILD_MACHINE: + static_options['CLANG_FORMAT_SUFFIX'] = 'none' + dynamic_options['CLANG_FORMAT_SUFFIX'] = 'none' + + if IS_BUILD_MACHINE: + just_release = True + static_options['WARNINGS_AS_ERRORS'] = True + dynamic_options['WARNINGS_AS_ERRORS'] = True + + if PLATFORM == 'win': + generator32 = 'Visual Studio 14 2015' + generator64 = 'Visual Studio 14 2015 Win64' + if static: + build_lib('win32-static', generator32, static_options, just_release) + build_lib('win64-static', generator64, static_options, just_release) + if shared: + build_lib('win32-dynamic', generator32, dynamic_options, just_release) + build_lib('win64-dynamic', generator64, dynamic_options, just_release) + elif PLATFORM == 'osx': + if static: + build_lib('osx-static', None, static_options, just_release) + if shared: + build_lib('osx-dynamic', None, dynamic_options, just_release) + elif PLATFORM == 'linux': + if static: + build_lib('linux-static', None, static_options, just_release) + if shared: + build_lib('linux-dynamic', None, dynamic_options, just_release) + + +if __name__ == '__main__': + os.chdir(SCRIPT_PATH) + sys.exit(cli()) diff --git a/Externals/discord-rpc/include/discord_register.h b/Externals/discord-rpc/include/discord_register.h index 4c16b68a7f..16fb42f328 100644 --- a/Externals/discord-rpc/include/discord_register.h +++ b/Externals/discord-rpc/include/discord_register.h @@ -1,17 +1,17 @@ #pragma once #if defined(DISCORD_DYNAMIC_LIB) -# if defined(_WIN32) -# if defined(DISCORD_BUILDING_SDK) -# define DISCORD_EXPORT __declspec(dllexport) -# else -# define DISCORD_EXPORT __declspec(dllimport) -# endif -# else -# define DISCORD_EXPORT __attribute__((visibility("default"))) -# endif +#if defined(_WIN32) +#if defined(DISCORD_BUILDING_SDK) +#define DISCORD_EXPORT __declspec(dllexport) #else -# define DISCORD_EXPORT +#define DISCORD_EXPORT __declspec(dllimport) +#endif +#else +#define DISCORD_EXPORT __attribute__((visibility("default"))) +#endif +#else +#define DISCORD_EXPORT #endif #ifdef __cplusplus diff --git a/Externals/discord-rpc/lib/discord-rpc.lib b/Externals/discord-rpc/lib/discord-rpc.lib deleted file mode 100644 index fdf4abe6d03feb1c232a9fe2a9e7da100a6d4e4d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3622 zcmY$iNi0gvu;bEKKm~@TM#h!~h6a{qsNx1tt|?q1fs28GL6m`k)rf(CJ%@pTV;KVj zR~-cN9ARJpV?PE49zO;K-gOYn#lgS;!rb>57(kfUjDZ1!xjr#4fG~Fo0|R$Te7vV` zfPYX(yo+nFbC731h<{LgN@j6#eo=~UQ9&|8e7s+%j}N9IhI%Ab5H%qlp?==+E{-9N z3@#88;yv>+OEMF4GOJP<;^Q-O3*xazz=VP`N=s7m%k$7w!i8b#f=ct86LWHs5|guw z(bS?y!PJKqq$HN41{9?hr{*Q2y8}%UrpGxaHL(bX7F0Qyj-b@yg8aM`bO%92VX7e3 zc_ikg zhk=2?h?RjMhn<0883zMH9Tx+`5grBxKOP2#b-WA=99#?x_qZ7t%y=0XK5;QHq;P{1 zFarkz3j;R;4+AFy8v`o?7Xv#3BLfo_QD%4=!XDm8DGNOS;5spVj8F=REjS-JO~C{) zQXY;7f(Rp}7BX`bY7Rm5HmV$w=TRkKKE{z&5K)h=4H6t^qR4@QDg_T3RAER+;7#7} zV8UB|AeAk8DLFa%1WQT-OK6#yz?IU*%&_9ol_+6G1_llW2+&JOO)5=S35M_(7+e_` z7Kfnj=_kZ)#kQGRiLT8V;2 zkfwrWIfmstY8+JO$-jn`MCvpnJLrb7#aWnXJA0+0vQT& zBohPFOGXY13}9zxz(l~F1nFRgiI{-YfONvum?A_#;wm5lib19`FxWzQAc~10ih+TF zHWd#Sn%4=Y93xW`q?E%1PC0uS7#JYVW?;aUa#BFPK*C5V#~3CIN;xZG94HM+IUsXs zk|KzSV_9&x|+*qJ%?IVpxMHJ#wVB~ zOii)ds?5N^z{r5G6{!+Jvx0%-Txe>H-A+)DG9lRsuiq%P(aZ?DjauLW6yZyljfkof z-D)&G;qb*_vjPLCAV;I@7F>_|4EHBxA5FQ~N(YfeJ!g|~k&>;(YmQk3-o diff --git a/Externals/discord-rpc/lib/libdiscord-rpc.dylib b/Externals/discord-rpc/lib/libdiscord-rpc.dylib deleted file mode 100644 index b48f5616cdb89650f856aa74124ecfd4624d8620..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 260256 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 P^#v!?p8_vq87u?<)porO diff --git a/Externals/discord-rpc/lib/libdiscord-rpc.so b/Externals/discord-rpc/lib/libdiscord-rpc.so deleted file mode 100644 index 43f56c753ebe43c5c0f968e5a7d23821567741dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 661146 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Ξ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

4L(oY1yG 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�>VO7RKCv=EdjV<; zoJ$ z`PjnQm}ggWc(JlGKV|V^o?ZO}H1qqM#S1hu4sN)C-0lE6=mC@~vAR6~CVQEMk<}D5 z3ndGhN(Ln{4r^9+woi~i&;$+6z?6Pq040}Cps@vr|3I<_V6s0Lz?BxV{~o~PKuvL3 zE{~m5Gh{KeHDbb7Rdl5QCMC?JA@n0`ir>Bv{&E0hNm28uuD#VpOk$Ro;tL z;2QJh>J!XoS-e19GkItl2WgxD(|DN`6yDJO7bvV3z+}ELfJ%K18&*@cCWxP18913P zz@+anL2U#Lhl_ZzazYyrAVmU`q0Z`HW@Hrv4b_1Xtv8yHDtkR$XJ7|v)q{U$h)Po-(fusN_9YJnQ zfJyyj1Sbm6l&lx4Hn^{hh!RiEP; zC?v%rm^ow;^F0t;*_Oy(^EXc&Y8 zw1C2fRjPzlw*;Z+08CL6Gic2J6RQ}T4Xg4lR=qWdWcdN62AbkPV|ZSmW|g!TE6XQV z8zi4POoxWWe-#4o5TznqyNOlaSdVzNOA$Pq&C+lR$Wjx9z6U9lD+_w zp2iIF%O_SF&@`dfaDqGK)nQ7v!(`W zpvkd$v5J63BAdZIevS#OOiiqM973#2(Bum)sA1YL3Tlv{4KUenjEtc5oDwW zB)b46`+<>>)d@P3r2{QiK?)AQ6!bDOvZ{d^JA!OptSl2)^`I?FkRk@~QAP|5%qti{ z%M+VewPCYQpy(HX$!_HZ)lXkQ!~T#E1IZe|WcTxe;^Hf-5L*N*H#EJ142PVP#K6G( zofR_L1{!2whdL27yV?LV0o3?a;Nn=v%F6~?OLCIcIFeP5Z5OK`+f!C$wkGC<^&In9 zdD)mBFnEQqF)yhH&)Gj@@M7idXXTvF%9{%56M-x>mWAL_K5%%HmQGb_t=R(1}3R+dyqBLvi5E`X_d z#SAu2pH-gChE7whp@w4(^9N9qn~6z7h*h3#1;hZ*fQ7;Ws3q%I zK~>x*@FFA$FIIsFR!->57ib_X0H$m`*xhd@v2xC4Wo0rHWR+OV%E{Km#-uFF%F2+tLgu25Am*a>)Pd*0j)EtayjbD$V7no6Q6O>1 zT-0vxT+~rU8|K}Rxu|1cEr_|O7Er&0mCc5gkvhDA_UkTQvmn5qU(c);h; zC%_EDGLH`O@&TCqd~nz66B`FKfrHX7!(ymQq(DKsDFW)!05s}) z0jA*_Kd8FqxXQ}OX2WW?3pCc`)x;Xp#G35ITI|Idsp|7wQNjg zLZDg+JpCET#<7M~i>;rP^*UP`ByY&dSQ9B+SZ* zG{?~ZQ!-ruRR4Si`Ho{v8j~I!xSZ6Udv34?o=9|4C)tn*&C({R*t~cPph+V9@Y-y~P&}tOqQ-PIGV?iwo zPEg4RjRg}g*5D>q7cWpegOfft~EnYy8i(4NQXsAE@5B08>g*y^{o~cR&U-tbsbW89b&4UYZFVwFgOW zfJuYqLG-ye6j-&`Y*+}_)xPAtYjJMa!19hl=F-Nd+N3t=u)?5Q||1d|evPFZ3 z<@rGKunje!4l{ET3p6f3#wo0WI;MpYl!QLBau)&aj%Xod9F_CVK@u@B)fUXzmBe7QkfZfNS7gkR~w5pA%p*INc9ZfMZ7L0Ze`#xL^T= zrx&XlhYhO;+i`I5iaZl!uo3D*T=Px=Fa?vqeUm-lg^D64Sb4ozk(_f&#UjS3PkpzeP(o+t`T|<01zx5I>e4E}B(E|svKqj;&7gj<0Ze8JGibTWCverx z;>9Wj%|jqH2{1J?m_WlrpTKMJIJ{WJplvje4HIB$K;3Uyu210hxfWCb$dCgt1$Zp_ z08@j^- zwh1sbSUa`_Fj>&xjt0oppcR=c6IiXFgBYNG+y|HD3RjTI2QZbLjEt;$Twhs1bNCJ%O{{EbY?-V^%)Fn#+fanq zIJ{Z8QnOfDPO-8_va&H}LdO?CW;ASv1^}8%Kw~8fU~+RA8CfMjkpP;4R)MBhP~cvG zsaVAbDyY7(@_uGzXFCDf-2&Q=2bxRe1~s12AwdSxqOb#MAx3Q+>QPf z7HFr6BvboT4}HkF9aK%KBpr+a3#);QFYrEksvOBc6+`sFd+e!W6!M_ure?pABli`ngHl105 z1Mo8@z-Iv9Iw66BfuR`fgaoiNASWbnB2Gx)!f-I?91KPV2GH>nsi4CHSV7(^N=*cv zWx>Y4P>^44XrKo^@Bwm&0c8I@=v0B6%p?YGuxiLj0icsFpeF@zqxu`zyQ(@3U)q_Yd{>RVbD_zARdJtU%<)0kegbP2n&{?l6=q^ z8k}fn5AcBofdU}4qXerM=)eKyN)9hBFG%GH8i8y$0Fh?q1Z{<4mfyw7UCPQ++6>wy zE)1R?VbT|7fNl8Y@b*`BWtW|UTnKr8P2eR zM#?$ZN?2t_Ho=RBb>D z4?)}bL2Ko>*&$;uzi$_ZY41KQI#kChiRC2$h7JCZeu zl^?YGe+_eV8mkx^GiU_nDI3QL(5h;ERw3}VObNE@P?jLubnA!1#QN3^w7!`6K0^ts%yrNjA+}~#UJe6Rxyh`&Y$eRI>cP8Ko->rN8nMj-EiF|} zV-;;;6$BjsFr)qi=m3D1NP0Q+S$QY18iMx6v9+=>_t!HiGlC{!J~MEf0L>M#ih8kX zgT^dC3m2q0K$~;tgBNLlM!a{iJq2xq?5v*v>b8`?)bp~f1$B2oJBpb9GL*0i&1dyx zo5$+i1X?;N$Poc@@t!C)=D&6GK&!&q8B16tu7kScY|R|{tgOs|6IdCUjUreXnD^Fm z*nm#KC}riD&nm_?4>ULp=`SgL!r2(4l z#XF?|avEt<8X$+@nbH7z1U3&1WDL zcs8GbqzO&gg47T>WeZZua0uFHohk_4Ok}(zPSVtd)uoBm4s@;;q-O^*w*aQ{uK;MvEn1Tbq+$U~#VY~O3OEE8xZI$i|_|D#ek(YIU7e1JsLP(idVCYhvYP+s($I#|G*i z^yf1fF*1J?;F!S5$`-@M+?{`o`KthU6Rb9Pvc|ZHRf0)Lh`BExtOO(pQpGV3#DcWp zK~?I6BhcVj3SQ9!+M^ELdJK}?0F#Amar(^0e6@~4k9jp{VTd4GBr7LuCmTO#vB^=W zQJ{rdd7ug0IyNuXbT8IEMvgSrd5j!hPnf`KBtd~u08`v21lpVMi50Ze!T~yg2{LU0 zOu-Y#O4ADPnL|=+Us&}gftDh$U1y8nC^^AAsfGi*FQ5gq!kjsaLywhr0jReMl4tI( z0c{=r$jmW;jmbh7tbyYRD<|80R+T95$!xq{AaxuiCpez4nzJngcl{s+b39=cWkZr5v&4i%*`wjY|MYFIp%?ODYUS7F-e0~seoEj1t*~a16t3n$^|+} zDuPuOx~vQo%nM)&K+DQNtM6Rdyg(fp=TXIvF`8Fn_O$0Cn`cz^li=n<7=&I21u< zKvqYAEZqPzp18a8tX5o~Sk2kISnZ&m1}O-DDOk?}nr;EFVF3lN1hl6DQd0m^Gl>N> z{qYI1`2xBw3zUZ!z!ZR{QYE=S>mzL-)8QcP2VkN?`==pceOHwVlAK&lZV`$J|pI0n+l7OAnV44DC@cm8@)25CL6q7V7xrELh_a z6juviY8n~A$B*c-+OgTN2I#T+ffkA(Jb3}8uAK>Vl*?z(;tJ;PwN0!-Y|LFuUaW$? zpq*~apKDLB@-z1`>9O*pfzGy2vSI#QJAqXdETrzmst@5Cf%zt0tTr~R_7hkgy}+ti znR}T)i_A`f_rI{R9cN?yTnipU>Syv|WBypnp~u|M zz*K-{qcyp9vC6QeLB<9_u1J8%9)RT0Qa0v&RU9Xn53zz4)q!_4@v<#oW8PiG@rn5; zYXpdK0?OFMe3aD&bZpT{wkK>S*&-sCcUEykFdt{-n80x@;>3vv&`{lc(12G&1oJkK z)G34%^R_DRVA^R`YKB0*K7p2<~*8f)`47ei8X?G9Y_|!*u{K_)y9i?T@~m! z1?J1F5im!s0oi;7VKcZe<&6TlcO^*bIzozhCB#uTkR8=<8S1E8a7QfxS$hY~Q42wi zy3ZQHybvUd#@NMtALP1)5Z66m)q}ZiKFA3V5l%pI-5ikA6ND7=9Ej_lBD-$GRjBKh zvoW%oa)H((8h}pnVEfF<*}}$rrIJaTk$DXp#{}jpmEZtB3|bKhu6001BJr_(Vb${i zFC0?m5MuRZTMHh5<49+V;P}LRw(>dV&sZon*d2Z`zo3A8JQ2UaZF%x6av}5ukr-*A-0kTPzCjrjd^cn3G-n#FUVp_ zQ0is43HAIL@RnMRQa0vI)f^|7&#@q--Y7N>1&I0UsyQNt!r#{;PQ0>7sk?q8Z z2=LNNQ8wo5ETA*kyds!aR)dq$4HkH0Ee9EJ6UhKxw)w2$(X4`{Y#b2~I~IbJ+(#&3 zURVu2{PZD91o#j~UN4Aktj26n;Gl-sJ-a%BRgjJOISV}5&Hx$o0$~uVG1~%!238d| zcyj=30;+jzQLLgZ;8lvE5v;s6%-z)-;4@3VgQnI&`^&A_B0;Mn*>;0`&K3zeuL87< zJd%yW3*wI^koEtNtQTdQ56(0HL8-D4kt$geLD`%+1~iy$fRvXV?nC2d0zBKi17(a! z$k_%FH?Kg(PD3&lHEy0)f!#lw6&g2BAsJ~7A|pKp888>g0BGE(l){=#;BaD#Vl|$K z2uJ3dRp9luD_KF|?-jvn&ITG^heZ-EXrbVhD)6zxYgs|94=<2APQsJaMUbuQk!%%Y zn;#7-TF!zbHX|gM&sKrMX(8)8R#s+Nq=0I83=OC^9H1P`F`pHbfz8=Ca@d%A$~nMC z4}atEVijQH5Mo=)%Gb;))(To!?Zqm@w!Rd^=k;F82HM`v&vtz+E9YlcR_5o75p2v; zO0O}$;qqdhQp%wRs_NP}z1Wz4m3?AvQWiY8SGPiN2fy7R*YO*o6bApb# z`owB70kl6^kj-vB8}qla2v!N^E>17zZ)KmLG)D=P0WzSAGYxc3i6q-ewrk8^%TBP$ zvN88?>aj6@DdW&%?&0)e{!#`~*Tb3S#j4D9l2wr{0(>Z`tT(G@6su$;t2CPptJNA- z3yug@*9oi&Hmu@Jtg39btb)wt6PS7Cu`#~_yI~rq7xSyKPs|XSqXfzTnLQ2J4KE>X zm;rLb3y>RTaC$Mn0J~uZS#E$hfRl}RA!h_DFSB3-D4Nfefr_k6oE#IF&y__mZ{qY~ zvH%xd=gLknZ{jS8n8$psY#!*q=&hXdSb4o!1?SIaV?F`)$qr60<`ZR~m?1Pr36ufy z$qukjm`{|QV3lHH-pM(S?F94jvTL9~-Nm_!jrmyFC+1z8Ud+e9{@Dfck15+pR(WtT zP-lx|mGur~m5v3^=-I7dwc$u(^_;+}W&=9(LlRUTd9w;KS4?2$p2x<#7wnkBoL&qfoMVK#gdNHpr`vj#qN}vpo%Pw-JvGRgs!KbTT;%s931S!4Nf}`a! zC&vUPO>lIqEjz({85A9CPr;`QDt=;>=O|&-nE=`vAmhatzLZGe5N^H!F%04mQSUD2FUp5 zkQkT=NzyMkL8s1ofzEV}0(YF9*04Hoq_O%=VAZl=)$n4K1<8A}Dn12m2xrv=%_UAM z1MRnBe$E-es>#d^nv4V$7}9L9th~N#%x&O+{>ACV+*bC98A5ZEKp7wh`~n9ws~X!$ zP_4l#$(9b@-K+kIxupzr#w_z6P8(LE39KqMp!4O#p=V7!W#dp_)nvQQDmamixuFca zTd0Z4i;ekT=_giRHs)WPpkqwABG{P!ltzF8yNwGP*t~2vuY-c!i}@R<@KRvz;sQ;g zf*P9~`mCDsSxwmHfzEHR+66kvMwm%Qh*g>`l2yo;Rd6jR_THC*&kbgt%;m+#;RTwM z)n{XVQwln`fq5F&1UBYZrJtCmad|PnDg~7wUbCf_CAfx7RrLoF_WI^l0ndgE6<|C_Q z6su@3t6)4E^Mg`Q>B+o^3sifhG2bgqW0hfJUJMG{yQQB%4CcEauPx^CV!m4nGH@|o zx3Q(Oag?w<1r=$xN{y|uu9Blm19c-oroo($7;cr#cItK0h+=W<4|A~XFCOIlQOR= zf)of-!J+dS5u8&?PcXj*g$gSx+fz_2T>`D8ne-Sz zEXYU~sCm2KH?(E&oE1F$rpU(8#C8%q@yW{;xtEpI8=@98?!oW}s&br zDaf!3FcpyPy&QI+4PD}(=mTwVU}b~uxdkaT_zQI$Xi$X{bQ%fsfAFvlc)u2?z5;ET z2OV4v+W068YU?zE8s?DU0FVhAU?yx~1P{yDv+}YujthQXcSUuUiSlzu? zm7pU+AT<|YYL0h#45@L*+eYt#VX3?4c<>I z>;>M&2;MIbnh*^554G?jc;^-esJj-yHlLOAG#m5EdX9O_*BLk_u!^(AfKv(Q1h8)K zCPOST4H^t#_28&)ysFbF6wD8LjPX9JCyF$-|40S$wLVq1hQ3cSZrAc9qp&6W*xSkFoD zsJ8@20Cd1TXpkAy!1Q7jdBSQB-Vnwi#C8(WL1Np@>Hs>VFAY@1r?W~$vVmgaI#|+# zEfTiMMGjP{*@C)D%(E&%r7rVxHZL~jnUx&7n4h!Rcrnkc1UGtLvPG~lPp{;d$NZ8l zf_Zx7HRhLWHqcJhv`UT$=2xK3__Rt8BjN;Pn8cE8KKL+7eJ{}IZ<1^fYo=6!I^N80 z+4R_$Cxfhc3pZ#I$e?#1gC3P3P`An(G*xgK zq~liwM+9>lJI4g(Ulkw*)PKysD(10rvN2y}d&0`fYy#~>fznR^J2d@(R=Hb4j}LY5 zVpV{Sn}Skp0Zh#{Ax2hDE{+qdexR!yY*?LaSgoO_WrNghfT>#p*?4@CjrmgUHBb*~ zy-*3O5?d3iJ$MVGj}5CS=pq3QJ?4wKpu&iGBZ|DK4fFY2P|?G@NeDW04ob-h98jlr zvxCm@+yfb>1bLzWCNm3spdCj98}rjT4jbm#pveo{2v!RlR%;GDRtG&uxd<}s0Za>M zj9rL}qZG7_aSdo$od{bxELVuL*|Hi;1oH&h(m`XLpbG$G(?H9p1Z`NQ+0wzcCWx_t z&h7MKmA7G4N(1#2#E6n(i(-plZUA+68$cV$v33%>uAmW;U#@;FD?uK|?d%phUtd%61BT27>G-R<#MNoS@aI;%q0t z6(G3!1leA|2X*sX@Dacq`mCm)v#HZqS=T_0)dDHn08?}kyjK}?cx)Qv6k*WfmkTgi z(99Pfs13!-2C9JtPOhho3w1f7sE({ zmSckM;sCXKyuq~}FPrUTcq0>JVS@nF!UNzFT|g(YgRT|=ZMNr)V4K9s3O&yp6p9C6 zYPWzV;yBV+K^NyZ&0~#%Hb_B=7zCjP?hpb`ZR@kfgDxnsVO0esWl%$`iPfTs)zOR9 z&xTbSw0D?|BNEZPpyFnFP)n@=<{GkQA3-KC2tobR2cEzD%*Onoj-!Nm0;m92Ws79h z2ThH8LE4WX|0lrI&jKH!%rT#pH=WIkRgY~xD`?lTYXs=R5z!{_xoV(RwItg_aI;X= zi&Z-UwBeMK4Kzo3zW`icFXs1R)jr9p2|B+IbXc%HB6kZ2Lmk$|&&cY}#W8`^gAI0^ zGRPqTF!_Cu79Hp!ATL(Od8`pgu{8mv=l~>2^;zxMN?7%6KnLJ}vZ^Fo6RSBmw*0Zh zmVgM<4ZSFywPKsk>dofG8W_Rq;swePpi_~NJ*(oys)gj)HxSQG!|mAvFpE0)8ChdN zo(+S07F206h(aB*g#&b?4u=gmu*0Bjc904Mn2J3dpaTR!n@Me0C86yNkOBvo0s>t# zklF<>wc9x$$E90?j!TE0H40L20j2BW=l33R(&J|3}R3R@8tk3!k-6eGJv!S zz+`rEfX?;##A?cB!>Wy>)d8kp9|vgq5ULe)yjcKDMhUcO5;Rd=!W;uxNe@a*5v<&x z@orF`DFQSb%9{ofU}cMB6^jB7UGdt01bD!!{-GfQN=XM`#x4>9pYOW{d=Q|21gmQV zYcNt`Vi1S=X#qqXsL=9a^b|WUpqW+Z;TWKRGl0oR zf@&~Gz@?_KG0WJ1mbin?J`w;OfX5aA9$TEp$~l2KX&z|3g@PWd9#nJ}D<|lhsz^v> z4LT>_0L)ZrP^*wxWDOg00LL0;1C9xxZ3jGT%!Z&Wja2_CNJ1UBfEBb9f#U>g0H}u^ z!J62_S_VDw0TdwxFm>~SRtQipuas2~R1ZWjf3E@`%-Y2|k5!Mu8+Ow9Eq3@dhp1y1^<9J`Oq^lA%E=8(=EWfIA=G!7Hvf*>+Bd)~vb?xscF#D;b6D^>R}g70~!s)?lRill7sAI28HWRzW_1LiBF z>$j02bHF!#4(vWvz1dA$tK zZc*^ARHzYPHpF1a4ppdinRz83QP>VuP6mdY{N%(O(52QO6(yAgFeYS&DklR2`X%E$ z@Exk03=GISRM`+aRC$qhsDjLe?oj1K-vbQV*~A6D$2%T$g030!pg}uk8J^~07ogSB*$r1UXB~A65z#&pmWo| zunK}MJYdUUHRHGe9=sK_VYOi6CRg&Wd+XS|B zRyB@N@MxYKx|BL=3k(zCk5G<+rd{){;UJ9Hw1fuIr#~z*aB7!wh64-X`n@)+Fq=VHmojb ztP!BgNz)ry6*E}PIj)1Jv_wHme>gzP%9~gXU>9?8TnD%N6hIdWeugrcKh%N7#+fIA z>|O5;2_CrdganK> z+XPmV zXQV5#?E&3%$-J>Xf{pnCgBN&FB_mriD+BX22GBev=ypm(@{eZaafj>C7>zqv!LX=8RTxzB<%%=dq8{!4qwoPjuTmt z?Lf_9oE)d%w(Nu0au{k0_%KgKHs)gxTXunLIR>+3FT@rQpMhg9DYmSJ*m4bO%L=Gp zZbEEX4zlGY%$8LUTR?oMEhmxuV#vzLA;K!mQ3@W=0*!iea-3vkWEKRi9VukeU}R&S zS;uh#G;Qz-v?^*ED49rt?ohqP%DaG78eFQZVV+p`38dr$V+pGQXjl0>=Ds@6vP0(2 zP$zano%jtD-CcDYUd-P>*SE4US3O~4o&ZS-pFwiH5a)hlEa3pH^#vV>b3qH*;GO|F zgQpODs3j-ph)2+ZO;E&eda+$+W##Z;d%`3N(grFe3$&ryG(e}aaez;xWV2%x0FRkB zLq?H6>K4G%DS*0;9O>XC$n2m!_@5z)K&JpafGK(hUJcG+!|DdQehai(Sb5{SUF3Wch{$}F&|?n0Uzna4a%6!;I1n- z$m<+YkPZ*XkO|Z8fd-V7xj33wgW0ZuuEnySz=|Ar4`Awy zKo?AbE_<+H)p`Ot2NHbiEy$k=`XoEC0H%eK@O?lHLjnv)cKiaE7D^m1Uim3Ds z3g-lv7CX?18lS*J4H{2aWuWsMASDZ6N{CM_A7EN2@lApe)HmcB0?N-9V1~R0pK!=w z18!vLgU(D;V3miK6(EHQ#!%bVfE6++34xCBW=)*H8g9etca7B@n)yM6U;|9;Y(~() z;3sf140f+GNWlV_f`0G;knn9epx`_Jlf#vhK#CYlpsvBE$blF|4TKbdJbwVD2s8l0 z2R_P|%?os8qCyF1If=CwtFRZVFNY0l)f(1rM(DL|Adf1TLf!cba!{=$xQInMs8)y# za^(vv8}z_hkS@YI@Ij7BfSG*_awiPzP&!t!cGiRJC4LV&$PPT4=0VZ~_rrs1#J(RM zA=%z76HZN9{d7!IG%xplL9R$JGdmpHI!hC=k+`t5_U;|Z6;EgcMdullJn2&&D zK(pXjs z39?}UOb7mDWFVysmQcr#wTuj8LIcc%!Ly7E^pLDLVAISIihtn%Qyt0%C6?yd%Hk^1BA&zFg3@L&P*qB#= z*D_v%oVu06+RfLU047A6b)qrgxD`=bk zMWhj+nZQZ4;8lX}nY_TuKz-RDSEq9bF@LN9-Au|nf!T{y2DGfTgjI&^ zDXSM-39DcUXk2V9t2Ns^R#6+~w>6*}gqf!>gVxNIuqv>D7Hfj&-K_d-C9J+)tg1Gk z8=e)|KBEfovQ1)ReqIBb)@7c>>;+ncDadx3jrnoS1W@1i9a97w^Q77c&~5SanL)di zK!>@(78!#M;%0D!djB#5BP%1FNi_M!=kFA8&$cvQ|bl<>k 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 WLl>aAd0aE{$iuL791K9({tN(9(oSIj diff --git a/Externals/discord-rpc/src/CMakeLists.txt b/Externals/discord-rpc/src/CMakeLists.txt new file mode 100644 index 0000000000..f9ec2503d2 --- /dev/null +++ b/Externals/discord-rpc/src/CMakeLists.txt @@ -0,0 +1,142 @@ +include_directories(${PROJECT_SOURCE_DIR}/include) + +option(ENABLE_IO_THREAD "Start up a separate I/O thread, otherwise I'd need to call an update function" ON) +option(USE_STATIC_CRT "Use /MT[d] for dynamic library" OFF) +option(WARNINGS_AS_ERRORS "When enabled, compiles with `-Werror` (on *nix platforms)." OFF) + +set(CMAKE_CXX_STANDARD 14) + +set(BASE_RPC_SRC + ${PROJECT_SOURCE_DIR}/include/discord_rpc.h + discord_rpc.cpp + ${PROJECT_SOURCE_DIR}/include/discord_register.h + rpc_connection.h + rpc_connection.cpp + serialization.h + serialization.cpp + connection.h + backoff.h + msg_queue.h +) + +if (${BUILD_SHARED_LIBS}) + if(WIN32) + set(BASE_RPC_SRC ${BASE_RPC_SRC} dllmain.cpp) + endif(WIN32) +endif(${BUILD_SHARED_LIBS}) + +if(WIN32) + add_definitions(-DDISCORD_WINDOWS) + set(BASE_RPC_SRC ${BASE_RPC_SRC} connection_win.cpp discord_register_win.cpp) + add_library(discord-rpc ${BASE_RPC_SRC}) + if (MSVC) + if(USE_STATIC_CRT) + foreach(CompilerFlag + CMAKE_CXX_FLAGS + CMAKE_CXX_FLAGS_DEBUG + CMAKE_CXX_FLAGS_RELEASE + CMAKE_C_FLAGS + CMAKE_C_FLAGS_DEBUG + CMAKE_C_FLAGS_RELEASE) + string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}") + endforeach() + endif(USE_STATIC_CRT) + target_compile_options(discord-rpc PRIVATE /EHsc + /Wall + /wd4100 # unreferenced formal parameter + /wd4514 # unreferenced inline + /wd4625 # copy constructor deleted + /wd5026 # move constructor deleted + /wd4626 # move assignment operator deleted + /wd4668 # not defined preprocessor macro + /wd4710 # function not inlined + /wd4711 # function was inlined + /wd4820 # structure padding + /wd4946 # reinterpret_cast used between related classes + /wd5027 # move assignment operator was implicitly defined as deleted + ) + endif(MSVC) + target_link_libraries(discord-rpc PRIVATE psapi advapi32) +endif(WIN32) + +if(UNIX) + set(BASE_RPC_SRC ${BASE_RPC_SRC} connection_unix.cpp) + + if (APPLE) + add_definitions(-DDISCORD_OSX) + set(BASE_RPC_SRC ${BASE_RPC_SRC} discord_register_osx.m) + else (APPLE) + add_definitions(-DDISCORD_LINUX) + set(BASE_RPC_SRC ${BASE_RPC_SRC} discord_register_linux.cpp) + endif(APPLE) + + add_library(discord-rpc ${BASE_RPC_SRC}) + target_link_libraries(discord-rpc PUBLIC pthread) + target_compile_options(discord-rpc PRIVATE + -g + -Wall + -Wextra + -Wpedantic + ) + + if (${WARNINGS_AS_ERRORS}) + target_compile_options(discord-rpc PRIVATE -Werror) + endif (${WARNINGS_AS_ERRORS}) + + target_compile_options(discord-rpc PRIVATE + -Wno-unknown-pragmas # pragma push thing doesn't work on clang + -Wno-old-style-cast # it's fine + -Wno-c++98-compat # that was almost 2 decades ago + -Wno-c++98-compat-pedantic + -Wno-missing-noreturn + -Wno-padded # structure padding + -Wno-covered-switch-default + -Wno-exit-time-destructors # not sure about these + -Wno-global-constructors + ) + + if (${BUILD_SHARED_LIBS}) + target_compile_options(discord-rpc PRIVATE -fPIC) + endif (${BUILD_SHARED_LIBS}) + + if (APPLE) + target_link_libraries(discord-rpc PRIVATE "-framework AppKit") + endif (APPLE) +endif(UNIX) + +target_include_directories(discord-rpc PRIVATE ${RAPIDJSON}/include) + +if (NOT ${ENABLE_IO_THREAD}) + target_compile_definitions(discord-rpc PUBLIC -DDISCORD_DISABLE_IO_THREAD) +endif (NOT ${ENABLE_IO_THREAD}) + +if (${BUILD_SHARED_LIBS}) + target_compile_definitions(discord-rpc PUBLIC -DDISCORD_DYNAMIC_LIB) + target_compile_definitions(discord-rpc PRIVATE -DDISCORD_BUILDING_SDK) +endif(${BUILD_SHARED_LIBS}) + +if (CLANG_FORMAT_CMD) + add_dependencies(discord-rpc clangformat) +endif(CLANG_FORMAT_CMD) + +# install + +install( + TARGETS discord-rpc + EXPORT "discord-rpc" + RUNTIME + DESTINATION "${CMAKE_INSTALL_BINDIR}" + LIBRARY + DESTINATION "${CMAKE_INSTALL_LIBDIR}" + ARCHIVE + DESTINATION "${CMAKE_INSTALL_LIBDIR}" + INCLUDES + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" +) + +install( + FILES + "../include/discord_rpc.h" + "../include/discord_register.h" + DESTINATION "include" +) diff --git a/Externals/discord-rpc/src/backoff.h b/Externals/discord-rpc/src/backoff.h new file mode 100644 index 0000000000..a3e736fb7b --- /dev/null +++ b/Externals/discord-rpc/src/backoff.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include +#include +#include + +struct Backoff { + int64_t minAmount; + int64_t maxAmount; + int64_t current; + int fails; + std::mt19937_64 randGenerator; + std::uniform_real_distribution<> randDistribution; + + double rand01() { return randDistribution(randGenerator); } + + Backoff(int64_t min, int64_t max) + : minAmount(min) + , maxAmount(max) + , current(min) + , fails(0) + , randGenerator((uint64_t)time(0)) + { + } + + void reset() + { + fails = 0; + current = minAmount; + } + + int64_t nextDelay() + { + ++fails; + int64_t delay = (int64_t)((double)current * 2.0 * rand01()); + current = std::min(current + delay, maxAmount); + return current; + } +}; diff --git a/Externals/discord-rpc/src/connection.h b/Externals/discord-rpc/src/connection.h new file mode 100644 index 0000000000..a8f99b9f10 --- /dev/null +++ b/Externals/discord-rpc/src/connection.h @@ -0,0 +1,19 @@ +#pragma once + +// This is to wrap the platform specific kinds of connect/read/write. + +#include +#include + +// not really connectiony, but need per-platform +int GetProcessId(); + +struct BaseConnection { + static BaseConnection* Create(); + static void Destroy(BaseConnection*&); + bool isOpen{false}; + bool Open(); + bool Close(); + bool Write(const void* data, size_t length); + bool Read(void* data, size_t length); +}; diff --git a/Externals/discord-rpc/src/connection_unix.cpp b/Externals/discord-rpc/src/connection_unix.cpp new file mode 100644 index 0000000000..6fe359ea4f --- /dev/null +++ b/Externals/discord-rpc/src/connection_unix.cpp @@ -0,0 +1,122 @@ +#include "connection.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +int GetProcessId() +{ + return ::getpid(); +} + +struct BaseConnectionUnix : public BaseConnection { + int sock{-1}; +}; + +static BaseConnectionUnix Connection; +static sockaddr_un PipeAddr{}; +#ifdef MSG_NOSIGNAL +static int MsgFlags = MSG_NOSIGNAL; +#else +static int MsgFlags = 0; +#endif + +static const char* GetTempPath() +{ + const char* temp = getenv("XDG_RUNTIME_DIR"); + temp = temp ? temp : getenv("TMPDIR"); + temp = temp ? temp : getenv("TMP"); + temp = temp ? temp : getenv("TEMP"); + temp = temp ? temp : "/tmp"; + return temp; +} + +/*static*/ BaseConnection* BaseConnection::Create() +{ + PipeAddr.sun_family = AF_UNIX; + return &Connection; +} + +/*static*/ void BaseConnection::Destroy(BaseConnection*& c) +{ + auto self = reinterpret_cast(c); + self->Close(); + c = nullptr; +} + +bool BaseConnection::Open() +{ + const char* tempPath = GetTempPath(); + auto self = reinterpret_cast(this); + self->sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (self->sock == -1) { + return false; + } + fcntl(self->sock, F_SETFL, O_NONBLOCK); +#ifdef SO_NOSIGPIPE + int optval = 1; + setsockopt(self->sock, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)); +#endif + + for (int pipeNum = 0; pipeNum < 10; ++pipeNum) { + snprintf( + PipeAddr.sun_path, sizeof(PipeAddr.sun_path), "%s/discord-ipc-%d", tempPath, pipeNum); + int err = connect(self->sock, (const sockaddr*)&PipeAddr, sizeof(PipeAddr)); + if (err == 0) { + self->isOpen = true; + return true; + } + } + self->Close(); + return false; +} + +bool BaseConnection::Close() +{ + auto self = reinterpret_cast(this); + if (self->sock == -1) { + return false; + } + close(self->sock); + self->sock = -1; + self->isOpen = false; + return true; +} + +bool BaseConnection::Write(const void* data, size_t length) +{ + auto self = reinterpret_cast(this); + + if (self->sock == -1) { + return false; + } + + ssize_t sentBytes = send(self->sock, data, length, MsgFlags); + if (sentBytes < 0) { + Close(); + } + return sentBytes == (ssize_t)length; +} + +bool BaseConnection::Read(void* data, size_t length) +{ + auto self = reinterpret_cast(this); + + if (self->sock == -1) { + return false; + } + + int res = (int)recv(self->sock, data, length, MsgFlags); + if (res < 0) { + if (errno == EAGAIN) { + return false; + } + Close(); + } + return res == (int)length; +} diff --git a/Externals/discord-rpc/src/connection_win.cpp b/Externals/discord-rpc/src/connection_win.cpp new file mode 100644 index 0000000000..2dd2750c06 --- /dev/null +++ b/Externals/discord-rpc/src/connection_win.cpp @@ -0,0 +1,128 @@ +#include "connection.h" + +#define WIN32_LEAN_AND_MEAN +#define NOMCX +#define NOSERVICE +#define NOIME +#include +#include + +int GetProcessId() +{ + return (int)::GetCurrentProcessId(); +} + +struct BaseConnectionWin : public BaseConnection { + HANDLE pipe{INVALID_HANDLE_VALUE}; +}; + +static BaseConnectionWin Connection; + +/*static*/ BaseConnection* BaseConnection::Create() +{ + return &Connection; +} + +/*static*/ void BaseConnection::Destroy(BaseConnection*& c) +{ + auto self = reinterpret_cast(c); + self->Close(); + c = nullptr; +} + +bool BaseConnection::Open() +{ + wchar_t pipeName[]{L"\\\\?\\pipe\\discord-ipc-0"}; + const size_t pipeDigit = sizeof(pipeName) / sizeof(wchar_t) - 2; + pipeName[pipeDigit] = L'0'; + auto self = reinterpret_cast(this); + for (;;) { + self->pipe = ::CreateFileW( + pipeName, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr); + if (self->pipe != INVALID_HANDLE_VALUE) { + self->isOpen = true; + return true; + } + + auto lastError = GetLastError(); + if (lastError == ERROR_FILE_NOT_FOUND) { + if (pipeName[pipeDigit] < L'9') { + pipeName[pipeDigit]++; + continue; + } + } + else if (lastError == ERROR_PIPE_BUSY) { + if (!WaitNamedPipeW(pipeName, 10000)) { + return false; + } + continue; + } + return false; + } +} + +bool BaseConnection::Close() +{ + auto self = reinterpret_cast(this); + ::CloseHandle(self->pipe); + self->pipe = INVALID_HANDLE_VALUE; + self->isOpen = false; + return true; +} + +bool BaseConnection::Write(const void* data, size_t length) +{ + if (length == 0) { + return true; + } + auto self = reinterpret_cast(this); + assert(self); + if (!self) { + return false; + } + if (self->pipe == INVALID_HANDLE_VALUE) { + return false; + } + assert(data); + if (!data) { + return false; + } + const DWORD bytesLength = (DWORD)length; + DWORD bytesWritten = 0; + return ::WriteFile(self->pipe, data, bytesLength, &bytesWritten, nullptr) == TRUE && + bytesWritten == bytesLength; +} + +bool BaseConnection::Read(void* data, size_t length) +{ + assert(data); + if (!data) { + return false; + } + auto self = reinterpret_cast(this); + assert(self); + if (!self) { + return false; + } + if (self->pipe == INVALID_HANDLE_VALUE) { + return false; + } + DWORD bytesAvailable = 0; + if (::PeekNamedPipe(self->pipe, nullptr, 0, nullptr, &bytesAvailable, nullptr)) { + if (bytesAvailable >= length) { + DWORD bytesToRead = (DWORD)length; + DWORD bytesRead = 0; + if (::ReadFile(self->pipe, data, bytesToRead, &bytesRead, nullptr) == TRUE) { + assert(bytesToRead == bytesRead); + return true; + } + else { + Close(); + } + } + } + else { + Close(); + } + return false; +} diff --git a/Externals/discord-rpc/src/discord-rpc.vcxproj b/Externals/discord-rpc/src/discord-rpc.vcxproj new file mode 100644 index 0000000000..971b47ffc1 --- /dev/null +++ b/Externals/discord-rpc/src/discord-rpc.vcxproj @@ -0,0 +1,93 @@ + + + + + Debug + x64 + + + Release + x64 + + + + {4482FD2A-EC43-3FFB-AC20-2E5C54B05EAD} + 10.0.15063.0 + Win32Proj + x64 + discord-rpc + + + + StaticLibrary + v141 + Unicode + + + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + + + + ..\include;..\thirdparty\include;%(AdditionalIncludeDirectories) + + + WIN32;_WINDOWS;_DEBUG;DISCORD_WINDOWS;%(PreprocessorDefinitions) + ..\include;..\thirdparty\rapidjson-1.1.0\include;%(AdditionalIncludeDirectories) + + + ..\include;..\thirdparty\rapidjson-1.1.0\include;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + + ..\include;..\thirdparty\include;%(AdditionalIncludeDirectories) + + + + + WIN32;_WINDOWS;NDEBUG;DISCORD_WINDOWS;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) + ..\include;..\thirdparty\rapidjson-1.1.0\include;%(AdditionalIncludeDirectories) + + + ..\include;..\thirdparty\rapidjson-1.1.0\include;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Externals/discord-rpc/src/discord_register_linux.cpp b/Externals/discord-rpc/src/discord_register_linux.cpp new file mode 100644 index 0000000000..b10f96db66 --- /dev/null +++ b/Externals/discord-rpc/src/discord_register_linux.cpp @@ -0,0 +1,100 @@ +#include "discord_rpc.h" +#include "discord_register.h" +#include + +#include +#include +#include +#include +#include +#include + +static bool Mkdir(const char* path) +{ + int result = mkdir(path, 0755); + if (result == 0) { + return true; + } + if (errno == EEXIST) { + return true; + } + return false; +} + +// we want to register games so we can run them from Discord client as discord-:// +extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command) +{ + // Add a desktop file and update some mime handlers so that xdg-open does the right thing. + + const char* home = getenv("HOME"); + if (!home) { + return; + } + + char exePath[1024]; + if (!command || !command[0]) { + if (readlink("/proc/self/exe", exePath, sizeof(exePath)) <= 0) { + return; + } + command = exePath; + } + + const char* destopFileFormat = "[Desktop Entry]\n" + "Name=Game %s\n" + "Exec=%s %%u\n" // note: it really wants that %u in there + "Type=Application\n" + "NoDisplay=true\n" + "Categories=Discord;Games;\n" + "MimeType=x-scheme-handler/discord-%s;\n"; + char desktopFile[2048]; + int fileLen = snprintf( + desktopFile, sizeof(desktopFile), destopFileFormat, applicationId, command, applicationId); + if (fileLen <= 0) { + return; + } + + char desktopFilename[256]; + snprintf(desktopFilename, sizeof(desktopFilename), "/discord-%s.desktop", applicationId); + + char desktopFilePath[1024]; + snprintf(desktopFilePath, sizeof(desktopFilePath), "%s/.local", home); + if (!Mkdir(desktopFilePath)) { + return; + } + strcat(desktopFilePath, "/share"); + if (!Mkdir(desktopFilePath)) { + return; + } + strcat(desktopFilePath, "/applications"); + if (!Mkdir(desktopFilePath)) { + return; + } + strcat(desktopFilePath, desktopFilename); + + FILE* fp = fopen(desktopFilePath, "w"); + if (fp) { + fwrite(desktopFile, 1, fileLen, fp); + fclose(fp); + } + else { + return; + } + + char xdgMimeCommand[1024]; + snprintf(xdgMimeCommand, + sizeof(xdgMimeCommand), + "xdg-mime default discord-%s.desktop x-scheme-handler/discord-%s", + applicationId, + applicationId); + if (system(xdgMimeCommand) < 0) { + fprintf(stderr, "Failed to register mime handler\n"); + } +} + +extern "C" DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId, + const char* steamId) +{ + char command[256]; + sprintf(command, "xdg-open steam://rungameid/%s", steamId); + Discord_Register(applicationId, command); +} diff --git a/Externals/discord-rpc/src/discord_register_osx.m b/Externals/discord-rpc/src/discord_register_osx.m new file mode 100644 index 0000000000..d710102865 --- /dev/null +++ b/Externals/discord-rpc/src/discord_register_osx.m @@ -0,0 +1,80 @@ +#include +#include + +#import + +#include "discord_register.h" + +static void RegisterCommand(const char* applicationId, const char* command) +{ + // There does not appear to be a way to register arbitrary commands on OSX, so instead we'll save the command + // to a file in the Discord config path, and when it is needed, Discord can try to load the file there, open + // the command therein (will pass to js's window.open, so requires a url-like thing) + + // Note: will not work for sandboxed apps + NSString *home = NSHomeDirectory(); + if (!home) { + return; + } + + NSString *path = [[[[[[home stringByAppendingPathComponent:@"Library"] + stringByAppendingPathComponent:@"Application Support"] + stringByAppendingPathComponent:@"discord"] + stringByAppendingPathComponent:@"games"] + stringByAppendingPathComponent:[NSString stringWithUTF8String:applicationId]] + stringByAppendingPathExtension:@"json"]; + [[NSFileManager defaultManager] createDirectoryAtPath:[path stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:nil]; + + NSString *jsonBuffer = [NSString stringWithFormat:@"{\"command\": \"%s\"}", command]; + [jsonBuffer writeToFile:path atomically:NO encoding:NSUTF8StringEncoding error:nil]; +} + +static void RegisterURL(const char* applicationId) +{ + char url[256]; + snprintf(url, sizeof(url), "discord-%s", applicationId); + CFStringRef cfURL = CFStringCreateWithCString(NULL, url, kCFStringEncodingUTF8); + + NSString* myBundleId = [[NSBundle mainBundle] bundleIdentifier]; + if (!myBundleId) { + fprintf(stderr, "No bundle id found\n"); + return; + } + + NSURL* myURL = [[NSBundle mainBundle] bundleURL]; + if (!myURL) { + fprintf(stderr, "No bundle url found\n"); + return; + } + + OSStatus status = LSSetDefaultHandlerForURLScheme(cfURL, (__bridge CFStringRef)myBundleId); + if (status != noErr) { + fprintf(stderr, "Error in LSSetDefaultHandlerForURLScheme: %d\n", (int)status); + return; + } + + status = LSRegisterURL((__bridge CFURLRef)myURL, true); + if (status != noErr) { + fprintf(stderr, "Error in LSRegisterURL: %d\n", (int)status); + } +} + +void Discord_Register(const char* applicationId, const char* command) +{ + if (command) { + RegisterCommand(applicationId, command); + } + else { + // raii lite + @autoreleasepool { + RegisterURL(applicationId); + } + } +} + +void Discord_RegisterSteamGame(const char* applicationId, const char* steamId) +{ + char command[256]; + snprintf(command, 256, "steam://rungameid/%s", steamId); + Discord_Register(applicationId, command); +} diff --git a/Externals/discord-rpc/src/discord_register_win.cpp b/Externals/discord-rpc/src/discord_register_win.cpp new file mode 100644 index 0000000000..e441318dd5 --- /dev/null +++ b/Externals/discord-rpc/src/discord_register_win.cpp @@ -0,0 +1,185 @@ +#include "discord_rpc.h" +#include "discord_register.h" + +#define WIN32_LEAN_AND_MEAN +#define NOMCX +#define NOSERVICE +#define NOIME +#include +#include +#include +#include + +/** + * Updated fixes for MinGW and WinXP + * This block is written the way it does not involve changing the rest of the code + * Checked to be compiling + * 1) strsafe.h belongs to Windows SDK and cannot be added to MinGW + * #include guarded, functions redirected to substitutes + * 2) RegSetKeyValueW and LSTATUS are not declared in + * The entire function is rewritten + */ +#ifdef __MINGW32__ +/// strsafe.h fixes +static HRESULT StringCbPrintfW(LPWSTR pszDest, size_t cbDest, LPCWSTR pszFormat, ...) +{ + HRESULT ret; + va_list va; + va_start(va, pszFormat); + cbDest /= 2; // Size is divided by 2 to convert from bytes to wide characters - causes segfault + // othervise + ret = vsnwprintf(pszDest, cbDest, pszFormat, va); + pszDest[cbDest - 1] = 0; // Terminate the string in case a buffer overflow; -1 will be returned + va_end(va); + return ret; +} +#else +#include +#endif // __MINGW32__ + +/// winreg.h fixes +#ifndef LSTATUS +#define LSTATUS LONG +#endif +#ifdef RegSetKeyValueW +#undefine RegSetKeyValueW +#endif +#define RegSetKeyValueW regset +static LSTATUS regset(HKEY hkey, + LPCWSTR subkey, + LPCWSTR name, + DWORD type, + const void* data, + DWORD len) +{ + HKEY htkey = hkey, hsubkey = nullptr; + LSTATUS ret; + if (subkey && subkey[0]) { + if ((ret = RegCreateKeyExW(hkey, subkey, 0, 0, 0, KEY_ALL_ACCESS, 0, &hsubkey, 0)) != + ERROR_SUCCESS) + return ret; + htkey = hsubkey; + } + ret = RegSetValueExW(htkey, name, 0, type, (const BYTE*)data, len); + if (hsubkey && hsubkey != hkey) + RegCloseKey(hsubkey); + return ret; +} + +static void Discord_RegisterW(const wchar_t* applicationId, const wchar_t* command) +{ + // https://msdn.microsoft.com/en-us/library/aa767914(v=vs.85).aspx + // we want to register games so we can run them as discord-:// + // Update the HKEY_CURRENT_USER, because it doesn't seem to require special permissions. + + wchar_t exeFilePath[MAX_PATH]; + DWORD exeLen = GetModuleFileNameW(nullptr, exeFilePath, MAX_PATH); + wchar_t openCommand[1024]; + + if (command && command[0]) { + StringCbPrintfW(openCommand, sizeof(openCommand), L"%s", command); + } + else { + // StringCbCopyW(openCommand, sizeof(openCommand), exeFilePath); + StringCbPrintfW(openCommand, sizeof(openCommand), L"%s", exeFilePath); + } + + wchar_t protocolName[64]; + StringCbPrintfW(protocolName, sizeof(protocolName), L"discord-%s", applicationId); + wchar_t protocolDescription[128]; + StringCbPrintfW( + protocolDescription, sizeof(protocolDescription), L"URL:Run game %s protocol", applicationId); + wchar_t urlProtocol = 0; + + wchar_t keyName[256]; + StringCbPrintfW(keyName, sizeof(keyName), L"Software\\Classes\\%s", protocolName); + HKEY key; + auto status = + RegCreateKeyExW(HKEY_CURRENT_USER, keyName, 0, nullptr, 0, KEY_WRITE, nullptr, &key, nullptr); + if (status != ERROR_SUCCESS) { + fprintf(stderr, "Error creating key\n"); + return; + } + DWORD len; + LSTATUS result; + len = (DWORD)lstrlenW(protocolDescription) + 1; + result = + RegSetKeyValueW(key, nullptr, nullptr, REG_SZ, protocolDescription, len * sizeof(wchar_t)); + if (FAILED(result)) { + fprintf(stderr, "Error writing description\n"); + } + + len = (DWORD)lstrlenW(protocolDescription) + 1; + result = RegSetKeyValueW(key, nullptr, L"URL Protocol", REG_SZ, &urlProtocol, sizeof(wchar_t)); + if (FAILED(result)) { + fprintf(stderr, "Error writing description\n"); + } + + result = RegSetKeyValueW( + key, L"DefaultIcon", nullptr, REG_SZ, exeFilePath, (exeLen + 1) * sizeof(wchar_t)); + if (FAILED(result)) { + fprintf(stderr, "Error writing icon\n"); + } + + len = (DWORD)lstrlenW(openCommand) + 1; + result = RegSetKeyValueW( + key, L"shell\\open\\command", nullptr, REG_SZ, openCommand, len * sizeof(wchar_t)); + if (FAILED(result)) { + fprintf(stderr, "Error writing command\n"); + } + RegCloseKey(key); +} + +extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command) +{ + wchar_t appId[32]; + MultiByteToWideChar(CP_UTF8, 0, applicationId, -1, appId, 32); + + wchar_t openCommand[1024]; + const wchar_t* wcommand = nullptr; + if (command && command[0]) { + const auto commandBufferLen = sizeof(openCommand) / sizeof(*openCommand); + MultiByteToWideChar(CP_UTF8, 0, command, -1, openCommand, commandBufferLen); + wcommand = openCommand; + } + + Discord_RegisterW(appId, wcommand); +} + +extern "C" DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId, + const char* steamId) +{ + wchar_t appId[32]; + MultiByteToWideChar(CP_UTF8, 0, applicationId, -1, appId, 32); + + wchar_t wSteamId[32]; + MultiByteToWideChar(CP_UTF8, 0, steamId, -1, wSteamId, 32); + + HKEY key; + auto status = RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Valve\\Steam", 0, KEY_READ, &key); + if (status != ERROR_SUCCESS) { + fprintf(stderr, "Error opening Steam key\n"); + return; + } + + wchar_t steamPath[MAX_PATH]; + DWORD pathBytes = sizeof(steamPath); + status = RegQueryValueExW(key, L"SteamExe", nullptr, nullptr, (BYTE*)steamPath, &pathBytes); + RegCloseKey(key); + if (status != ERROR_SUCCESS || pathBytes < 1) { + fprintf(stderr, "Error reading SteamExe key\n"); + return; + } + + DWORD pathChars = pathBytes / sizeof(wchar_t); + for (DWORD i = 0; i < pathChars; ++i) { + if (steamPath[i] == L'/') { + steamPath[i] = L'\\'; + } + } + + wchar_t command[1024]; + StringCbPrintfW(command, sizeof(command), L"\"%s\" steam://rungameid/%s", steamPath, wSteamId); + + Discord_RegisterW(appId, command); +} diff --git a/Externals/discord-rpc/src/discord_rpc.cpp b/Externals/discord-rpc/src/discord_rpc.cpp new file mode 100644 index 0000000000..dedb3f1539 --- /dev/null +++ b/Externals/discord-rpc/src/discord_rpc.cpp @@ -0,0 +1,499 @@ +#include "discord_rpc.h" + +#include "backoff.h" +#include "discord_register.h" +#include "msg_queue.h" +#include "rpc_connection.h" +#include "serialization.h" + +#include +#include +#include + +#ifndef DISCORD_DISABLE_IO_THREAD +#include +#include +#endif + +constexpr size_t MaxMessageSize{16 * 1024}; +constexpr size_t MessageQueueSize{8}; +constexpr size_t JoinQueueSize{8}; + +struct QueuedMessage { + size_t length; + char buffer[MaxMessageSize]; + + void Copy(const QueuedMessage& other) + { + length = other.length; + if (length) { + memcpy(buffer, other.buffer, length); + } + } +}; + +struct User { + // snowflake (64bit int), turned into a ascii decimal string, at most 20 chars +1 null + // terminator = 21 + char userId[32]; + // 32 unicode glyphs is max name size => 4 bytes per glyph in the worst case, +1 for null + // terminator = 129 + char username[344]; + // 4 decimal digits + 1 null terminator = 5 + char discriminator[8]; + // optional 'a_' + md5 hex digest (32 bytes) + null terminator = 35 + char avatar[128]; + // Rounded way up because I'm paranoid about games breaking from future changes in these sizes +}; + +static RpcConnection* Connection{nullptr}; +static DiscordEventHandlers QueuedHandlers{}; +static DiscordEventHandlers Handlers{}; +static std::atomic_bool WasJustConnected{false}; +static std::atomic_bool WasJustDisconnected{false}; +static std::atomic_bool GotErrorMessage{false}; +static std::atomic_bool WasJoinGame{false}; +static std::atomic_bool WasSpectateGame{false}; +static char JoinGameSecret[256]; +static char SpectateGameSecret[256]; +static int LastErrorCode{0}; +static char LastErrorMessage[256]; +static int LastDisconnectErrorCode{0}; +static char LastDisconnectErrorMessage[256]; +static std::mutex PresenceMutex; +static std::mutex HandlerMutex; +static QueuedMessage QueuedPresence{}; +static MsgQueue SendQueue; +static MsgQueue JoinAskQueue; +static User connectedUser; + +// We want to auto connect, and retry on failure, but not as fast as possible. This does expoential +// backoff from 0.5 seconds to 1 minute +static Backoff ReconnectTimeMs(500, 60 * 1000); +static auto NextConnect = std::chrono::system_clock::now(); +static int Pid{0}; +static int Nonce{1}; + +#ifndef DISCORD_DISABLE_IO_THREAD +static void Discord_UpdateConnection(void); +class IoThreadHolder { +private: + std::atomic_bool keepRunning{true}; + std::mutex waitForIOMutex; + std::condition_variable waitForIOActivity; + std::thread ioThread; + +public: + void Start() + { + keepRunning.store(true); + ioThread = std::thread([&]() { + const std::chrono::duration maxWait{500LL}; + while (keepRunning.load()) { + Discord_UpdateConnection(); + std::unique_lock lock(waitForIOMutex); + waitForIOActivity.wait_for(lock, maxWait); + } + }); + } + + void Notify() { waitForIOActivity.notify_all(); } + + void Stop() + { + keepRunning.exchange(false); + Notify(); + if (ioThread.joinable()) { + ioThread.join(); + } + } + + ~IoThreadHolder() { Stop(); } +}; +#else +class IoThreadHolder { +public: + void Start() {} + void Stop() {} + void Notify() {} +}; +#endif // DISCORD_DISABLE_IO_THREAD +static IoThreadHolder* IoThread{nullptr}; + +static void UpdateReconnectTime() +{ + NextConnect = std::chrono::system_clock::now() + + std::chrono::duration{ReconnectTimeMs.nextDelay()}; +} + +#ifdef DISCORD_DISABLE_IO_THREAD +extern "C" DISCORD_EXPORT void Discord_UpdateConnection(void) +#else +static void Discord_UpdateConnection(void) +#endif +{ + if (!Connection) { + return; + } + + if (!Connection->IsOpen()) { + if (std::chrono::system_clock::now() >= NextConnect) { + UpdateReconnectTime(); + Connection->Open(); + } + } + else { + // reads + + for (;;) { + JsonDocument message; + + if (!Connection->Read(message)) { + break; + } + + const char* evtName = GetStrMember(&message, "evt"); + const char* nonce = GetStrMember(&message, "nonce"); + + if (nonce) { + // in responses only -- should use to match up response when needed. + + if (evtName && strcmp(evtName, "ERROR") == 0) { + auto data = GetObjMember(&message, "data"); + LastErrorCode = GetIntMember(data, "code"); + StringCopy(LastErrorMessage, GetStrMember(data, "message", "")); + GotErrorMessage.store(true); + } + } + else { + // should have evt == name of event, optional data + if (evtName == nullptr) { + continue; + } + + auto data = GetObjMember(&message, "data"); + + if (strcmp(evtName, "ACTIVITY_JOIN") == 0) { + auto secret = GetStrMember(data, "secret"); + if (secret) { + StringCopy(JoinGameSecret, secret); + WasJoinGame.store(true); + } + } + else if (strcmp(evtName, "ACTIVITY_SPECTATE") == 0) { + auto secret = GetStrMember(data, "secret"); + if (secret) { + StringCopy(SpectateGameSecret, secret); + WasSpectateGame.store(true); + } + } + else if (strcmp(evtName, "ACTIVITY_JOIN_REQUEST") == 0) { + auto user = GetObjMember(data, "user"); + auto userId = GetStrMember(user, "id"); + auto username = GetStrMember(user, "username"); + auto avatar = GetStrMember(user, "avatar"); + auto joinReq = JoinAskQueue.GetNextAddMessage(); + if (userId && username && joinReq) { + StringCopy(joinReq->userId, userId); + StringCopy(joinReq->username, username); + auto discriminator = GetStrMember(user, "discriminator"); + if (discriminator) { + StringCopy(joinReq->discriminator, discriminator); + } + if (avatar) { + StringCopy(joinReq->avatar, avatar); + } + else { + joinReq->avatar[0] = 0; + } + JoinAskQueue.CommitAdd(); + } + } + } + } + + // writes + if (QueuedPresence.length) { + QueuedMessage local; + { + std::lock_guard guard(PresenceMutex); + local.Copy(QueuedPresence); + QueuedPresence.length = 0; + } + if (!Connection->Write(local.buffer, local.length)) { + // if we fail to send, requeue + std::lock_guard guard(PresenceMutex); + QueuedPresence.Copy(local); + } + } + + while (SendQueue.HavePendingSends()) { + auto qmessage = SendQueue.GetNextSendMessage(); + Connection->Write(qmessage->buffer, qmessage->length); + SendQueue.CommitSend(); + } + } +} + +static void SignalIOActivity() +{ + if (IoThread != nullptr) { + IoThread->Notify(); + } +} + +static bool RegisterForEvent(const char* evtName) +{ + auto qmessage = SendQueue.GetNextAddMessage(); + if (qmessage) { + qmessage->length = + JsonWriteSubscribeCommand(qmessage->buffer, sizeof(qmessage->buffer), Nonce++, evtName); + SendQueue.CommitAdd(); + SignalIOActivity(); + return true; + } + return false; +} + +static bool DeregisterForEvent(const char* evtName) +{ + auto qmessage = SendQueue.GetNextAddMessage(); + if (qmessage) { + qmessage->length = + JsonWriteUnsubscribeCommand(qmessage->buffer, sizeof(qmessage->buffer), Nonce++, evtName); + SendQueue.CommitAdd(); + SignalIOActivity(); + return true; + } + return false; +} + +extern "C" DISCORD_EXPORT void Discord_Initialize(const char* applicationId, + DiscordEventHandlers* handlers, + int autoRegister, + const char* optionalSteamId) +{ + IoThread = new (std::nothrow) IoThreadHolder(); + if (IoThread == nullptr) { + return; + } + + if (autoRegister) { + if (optionalSteamId && optionalSteamId[0]) { + Discord_RegisterSteamGame(applicationId, optionalSteamId); + } + else { + Discord_Register(applicationId, nullptr); + } + } + + Pid = GetProcessId(); + + { + std::lock_guard guard(HandlerMutex); + + if (handlers) { + QueuedHandlers = *handlers; + } + else { + QueuedHandlers = {}; + } + + Handlers = {}; + } + + if (Connection) { + return; + } + + Connection = RpcConnection::Create(applicationId); + Connection->onConnect = [](JsonDocument& readyMessage) { + Discord_UpdateHandlers(&QueuedHandlers); + auto data = GetObjMember(&readyMessage, "data"); + auto user = GetObjMember(data, "user"); + auto userId = GetStrMember(user, "id"); + auto username = GetStrMember(user, "username"); + auto avatar = GetStrMember(user, "avatar"); + if (userId && username) { + StringCopy(connectedUser.userId, userId); + StringCopy(connectedUser.username, username); + auto discriminator = GetStrMember(user, "discriminator"); + if (discriminator) { + StringCopy(connectedUser.discriminator, discriminator); + } + if (avatar) { + StringCopy(connectedUser.avatar, avatar); + } + else { + connectedUser.avatar[0] = 0; + } + } + WasJustConnected.exchange(true); + ReconnectTimeMs.reset(); + }; + Connection->onDisconnect = [](int err, const char* message) { + LastDisconnectErrorCode = err; + StringCopy(LastDisconnectErrorMessage, message); + { + std::lock_guard guard(HandlerMutex); + Handlers = {}; + } + WasJustDisconnected.exchange(true); + UpdateReconnectTime(); + }; + + IoThread->Start(); +} + +extern "C" DISCORD_EXPORT void Discord_Shutdown(void) +{ + if (!Connection) { + return; + } + Connection->onConnect = nullptr; + Connection->onDisconnect = nullptr; + Handlers = {}; + if (IoThread != nullptr) { + IoThread->Stop(); + delete IoThread; + IoThread = nullptr; + } + + RpcConnection::Destroy(Connection); +} + +extern "C" DISCORD_EXPORT void Discord_UpdatePresence(const DiscordRichPresence* presence) +{ + { + std::lock_guard guard(PresenceMutex); + QueuedPresence.length = JsonWriteRichPresenceObj( + QueuedPresence.buffer, sizeof(QueuedPresence.buffer), Nonce++, Pid, presence); + } + SignalIOActivity(); +} + +extern "C" DISCORD_EXPORT void Discord_ClearPresence(void) +{ + Discord_UpdatePresence(nullptr); +} + +extern "C" DISCORD_EXPORT void Discord_Respond(const char* userId, /* DISCORD_REPLY_ */ int reply) +{ + // if we are not connected, let's not batch up stale messages for later + if (!Connection || !Connection->IsOpen()) { + return; + } + auto qmessage = SendQueue.GetNextAddMessage(); + if (qmessage) { + qmessage->length = + JsonWriteJoinReply(qmessage->buffer, sizeof(qmessage->buffer), userId, reply, Nonce++); + SendQueue.CommitAdd(); + SignalIOActivity(); + } +} + +extern "C" DISCORD_EXPORT void Discord_RunCallbacks(void) +{ + // Note on some weirdness: internally we might connect, get other signals, disconnect any number + // of times inbetween calls here. Externally, we want the sequence to seem sane, so any other + // signals are book-ended by calls to ready and disconnect. + + if (!Connection) { + return; + } + + bool wasDisconnected = WasJustDisconnected.exchange(false); + bool isConnected = Connection->IsOpen(); + + if (isConnected) { + // if we are connected, disconnect cb first + std::lock_guard guard(HandlerMutex); + if (wasDisconnected && Handlers.disconnected) { + Handlers.disconnected(LastDisconnectErrorCode, LastDisconnectErrorMessage); + } + } + + if (WasJustConnected.exchange(false)) { + std::lock_guard guard(HandlerMutex); + if (Handlers.ready) { + DiscordUser du{connectedUser.userId, + connectedUser.username, + connectedUser.discriminator, + connectedUser.avatar}; + Handlers.ready(&du); + } + } + + if (GotErrorMessage.exchange(false)) { + std::lock_guard guard(HandlerMutex); + if (Handlers.errored) { + Handlers.errored(LastErrorCode, LastErrorMessage); + } + } + + if (WasJoinGame.exchange(false)) { + std::lock_guard guard(HandlerMutex); + if (Handlers.joinGame) { + Handlers.joinGame(JoinGameSecret); + } + } + + if (WasSpectateGame.exchange(false)) { + std::lock_guard guard(HandlerMutex); + if (Handlers.spectateGame) { + Handlers.spectateGame(SpectateGameSecret); + } + } + + // Right now this batches up any requests and sends them all in a burst; I could imagine a world + // where the implementer would rather sequentially accept/reject each one before the next invite + // is sent. I left it this way because I could also imagine wanting to process these all and + // maybe show them in one common dialog and/or start fetching the avatars in parallel, and if + // not it should be trivial for the implementer to make a queue themselves. + while (JoinAskQueue.HavePendingSends()) { + auto req = JoinAskQueue.GetNextSendMessage(); + { + std::lock_guard guard(HandlerMutex); + if (Handlers.joinRequest) { + DiscordUser du{req->userId, req->username, req->discriminator, req->avatar}; + Handlers.joinRequest(&du); + } + } + JoinAskQueue.CommitSend(); + } + + if (!isConnected) { + // if we are not connected, disconnect message last + std::lock_guard guard(HandlerMutex); + if (wasDisconnected && Handlers.disconnected) { + Handlers.disconnected(LastDisconnectErrorCode, LastDisconnectErrorMessage); + } + } +} + +extern "C" DISCORD_EXPORT void Discord_UpdateHandlers(DiscordEventHandlers* newHandlers) +{ + if (newHandlers) { +#define HANDLE_EVENT_REGISTRATION(handler_name, event) \ + if (!Handlers.handler_name && newHandlers->handler_name) { \ + RegisterForEvent(event); \ + } \ + else if (Handlers.handler_name && !newHandlers->handler_name) { \ + DeregisterForEvent(event); \ + } + + std::lock_guard guard(HandlerMutex); + HANDLE_EVENT_REGISTRATION(joinGame, "ACTIVITY_JOIN") + HANDLE_EVENT_REGISTRATION(spectateGame, "ACTIVITY_SPECTATE") + HANDLE_EVENT_REGISTRATION(joinRequest, "ACTIVITY_JOIN_REQUEST") + +#undef HANDLE_EVENT_REGISTRATION + + Handlers = *newHandlers; + } + else { + std::lock_guard guard(HandlerMutex); + Handlers = {}; + } + return; +} diff --git a/Externals/discord-rpc/src/dllmain.cpp b/Externals/discord-rpc/src/dllmain.cpp new file mode 100644 index 0000000000..fbfc2950d7 --- /dev/null +++ b/Externals/discord-rpc/src/dllmain.cpp @@ -0,0 +1,8 @@ +#include + +// outsmart GCC's missing-declarations warning +BOOL WINAPI DllMain(HMODULE, DWORD, LPVOID); +BOOL WINAPI DllMain(HMODULE, DWORD, LPVOID) +{ + return TRUE; +} diff --git a/Externals/discord-rpc/src/msg_queue.h b/Externals/discord-rpc/src/msg_queue.h new file mode 100644 index 0000000000..77f380e705 --- /dev/null +++ b/Externals/discord-rpc/src/msg_queue.h @@ -0,0 +1,36 @@ +#pragma once + +#include + +// A simple queue. No locks, but only works with a single thread as producer and a single thread as +// a consumer. Mutex up as needed. + +template +class MsgQueue { + ElementType queue_[QueueSize]; + std::atomic_uint nextAdd_{0}; + std::atomic_uint nextSend_{0}; + std::atomic_uint pendingSends_{0}; + +public: + MsgQueue() {} + + ElementType* GetNextAddMessage() + { + // if we are falling behind, bail + if (pendingSends_.load() >= QueueSize) { + return nullptr; + } + auto index = (nextAdd_++) % QueueSize; + return &queue_[index]; + } + void CommitAdd() { ++pendingSends_; } + + bool HavePendingSends() const { return pendingSends_.load() != 0; } + ElementType* GetNextSendMessage() + { + auto index = (nextSend_++) % QueueSize; + return &queue_[index]; + } + void CommitSend() { --pendingSends_; } +}; diff --git a/Externals/discord-rpc/src/rpc_connection.cpp b/Externals/discord-rpc/src/rpc_connection.cpp new file mode 100644 index 0000000000..bf9e4cc7a4 --- /dev/null +++ b/Externals/discord-rpc/src/rpc_connection.cpp @@ -0,0 +1,141 @@ +#include "rpc_connection.h" +#include "serialization.h" + +#include + +static const int RpcVersion = 1; +static RpcConnection Instance; + +/*static*/ RpcConnection* RpcConnection::Create(const char* applicationId) +{ + Instance.connection = BaseConnection::Create(); + StringCopy(Instance.appId, applicationId); + return &Instance; +} + +/*static*/ void RpcConnection::Destroy(RpcConnection*& c) +{ + c->Close(); + BaseConnection::Destroy(c->connection); + c = nullptr; +} + +void RpcConnection::Open() +{ + if (state == State::Connected) { + return; + } + + if (state == State::Disconnected) { + if (connection->Open()) { + } + else { + return; + } + } + + if (state == State::SentHandshake) { + JsonDocument message; + if (Read(message)) { + auto cmd = GetStrMember(&message, "cmd"); + auto evt = GetStrMember(&message, "evt"); + if (cmd && evt && !strcmp(cmd, "DISPATCH") && !strcmp(evt, "READY")) { + state = State::Connected; + if (onConnect) { + onConnect(message); + } + } + } + } + else { + sendFrame.opcode = Opcode::Handshake; + sendFrame.length = (uint32_t)JsonWriteHandshakeObj( + sendFrame.message, sizeof(sendFrame.message), RpcVersion, appId); + + if (connection->Write(&sendFrame, sizeof(MessageFrameHeader) + sendFrame.length)) { + state = State::SentHandshake; + } + else { + Close(); + } + } +} + +void RpcConnection::Close() +{ + if (onDisconnect && (state == State::Connected || state == State::SentHandshake)) { + onDisconnect(lastErrorCode, lastErrorMessage); + } + connection->Close(); + state = State::Disconnected; +} + +bool RpcConnection::Write(const void* data, size_t length) +{ + sendFrame.opcode = Opcode::Frame; + memcpy(sendFrame.message, data, length); + sendFrame.length = (uint32_t)length; + if (!connection->Write(&sendFrame, sizeof(MessageFrameHeader) + length)) { + Close(); + return false; + } + return true; +} + +bool RpcConnection::Read(JsonDocument& message) +{ + if (state != State::Connected && state != State::SentHandshake) { + return false; + } + MessageFrame readFrame; + for (;;) { + bool didRead = connection->Read(&readFrame, sizeof(MessageFrameHeader)); + if (!didRead) { + if (!connection->isOpen) { + lastErrorCode = (int)ErrorCode::PipeClosed; + StringCopy(lastErrorMessage, "Pipe closed"); + Close(); + } + return false; + } + + if (readFrame.length > 0) { + didRead = connection->Read(readFrame.message, readFrame.length); + if (!didRead) { + lastErrorCode = (int)ErrorCode::ReadCorrupt; + StringCopy(lastErrorMessage, "Partial data in frame"); + Close(); + return false; + } + readFrame.message[readFrame.length] = 0; + } + + switch (readFrame.opcode) { + case Opcode::Close: { + message.ParseInsitu(readFrame.message); + lastErrorCode = GetIntMember(&message, "code"); + StringCopy(lastErrorMessage, GetStrMember(&message, "message", "")); + Close(); + return false; + } + case Opcode::Frame: + message.ParseInsitu(readFrame.message); + return true; + case Opcode::Ping: + readFrame.opcode = Opcode::Pong; + if (!connection->Write(&readFrame, sizeof(MessageFrameHeader) + readFrame.length)) { + Close(); + } + break; + case Opcode::Pong: + break; + case Opcode::Handshake: + default: + // something bad happened + lastErrorCode = (int)ErrorCode::ReadCorrupt; + StringCopy(lastErrorMessage, "Bad ipc frame"); + Close(); + return false; + } + } +} diff --git a/Externals/discord-rpc/src/rpc_connection.h b/Externals/discord-rpc/src/rpc_connection.h new file mode 100644 index 0000000000..bbdd05c792 --- /dev/null +++ b/Externals/discord-rpc/src/rpc_connection.h @@ -0,0 +1,59 @@ +#pragma once + +#include "connection.h" +#include "serialization.h" + +// I took this from the buffer size libuv uses for named pipes; I suspect ours would usually be much +// smaller. +constexpr size_t MaxRpcFrameSize = 64 * 1024; + +struct RpcConnection { + enum class ErrorCode : int { + Success = 0, + PipeClosed = 1, + ReadCorrupt = 2, + }; + + enum class Opcode : uint32_t { + Handshake = 0, + Frame = 1, + Close = 2, + Ping = 3, + Pong = 4, + }; + + struct MessageFrameHeader { + Opcode opcode; + uint32_t length; + }; + + struct MessageFrame : public MessageFrameHeader { + char message[MaxRpcFrameSize - sizeof(MessageFrameHeader)]; + }; + + enum class State : uint32_t { + Disconnected, + SentHandshake, + AwaitingResponse, + Connected, + }; + + BaseConnection* connection{nullptr}; + State state{State::Disconnected}; + void (*onConnect)(JsonDocument& message){nullptr}; + void (*onDisconnect)(int errorCode, const char* message){nullptr}; + char appId[64]{}; + int lastErrorCode{0}; + char lastErrorMessage[256]{}; + RpcConnection::MessageFrame sendFrame; + + static RpcConnection* Create(const char* applicationId); + static void Destroy(RpcConnection*&); + + inline bool IsOpen() const { return state == State::Connected; } + + void Open(); + void Close(); + bool Write(const void* data, size_t length); + bool Read(JsonDocument& message); +}; diff --git a/Externals/discord-rpc/src/serialization.cpp b/Externals/discord-rpc/src/serialization.cpp new file mode 100644 index 0000000000..6cc1e9013d --- /dev/null +++ b/Externals/discord-rpc/src/serialization.cpp @@ -0,0 +1,245 @@ +#include "serialization.h" +#include "connection.h" +#include "discord_rpc.h" + +template +void NumberToString(char* dest, T number) +{ + if (!number) { + *dest++ = '0'; + *dest++ = 0; + return; + } + if (number < 0) { + *dest++ = '-'; + number = -number; + } + char temp[32]; + int place = 0; + while (number) { + auto digit = number % 10; + number = number / 10; + temp[place++] = '0' + (char)digit; + } + for (--place; place >= 0; --place) { + *dest++ = temp[place]; + } + *dest = 0; +} + +// it's ever so slightly faster to not have to strlen the key +template +void WriteKey(JsonWriter& w, T& k) +{ + w.Key(k, sizeof(T) - 1); +} + +struct WriteObject { + JsonWriter& writer; + WriteObject(JsonWriter& w) + : writer(w) + { + writer.StartObject(); + } + template + WriteObject(JsonWriter& w, T& name) + : writer(w) + { + WriteKey(writer, name); + writer.StartObject(); + } + ~WriteObject() { writer.EndObject(); } +}; + +struct WriteArray { + JsonWriter& writer; + template + WriteArray(JsonWriter& w, T& name) + : writer(w) + { + WriteKey(writer, name); + writer.StartArray(); + } + ~WriteArray() { writer.EndArray(); } +}; + +template +void WriteOptionalString(JsonWriter& w, T& k, const char* value) +{ + if (value && value[0]) { + w.Key(k, sizeof(T) - 1); + w.String(value); + } +} + +static void JsonWriteNonce(JsonWriter& writer, int nonce) +{ + WriteKey(writer, "nonce"); + char nonceBuffer[32]; + NumberToString(nonceBuffer, nonce); + writer.String(nonceBuffer); +} + +size_t JsonWriteRichPresenceObj(char* dest, + size_t maxLen, + int nonce, + int pid, + const DiscordRichPresence* presence) +{ + JsonWriter writer(dest, maxLen); + + { + WriteObject top(writer); + + JsonWriteNonce(writer, nonce); + + WriteKey(writer, "cmd"); + writer.String("SET_ACTIVITY"); + + { + WriteObject args(writer, "args"); + + WriteKey(writer, "pid"); + writer.Int(pid); + + if (presence != nullptr) { + WriteObject activity(writer, "activity"); + + WriteOptionalString(writer, "state", presence->state); + WriteOptionalString(writer, "details", presence->details); + + if (presence->startTimestamp || presence->endTimestamp) { + WriteObject timestamps(writer, "timestamps"); + + if (presence->startTimestamp) { + WriteKey(writer, "start"); + writer.Int64(presence->startTimestamp); + } + + if (presence->endTimestamp) { + WriteKey(writer, "end"); + writer.Int64(presence->endTimestamp); + } + } + + if ((presence->largeImageKey && presence->largeImageKey[0]) || + (presence->largeImageText && presence->largeImageText[0]) || + (presence->smallImageKey && presence->smallImageKey[0]) || + (presence->smallImageText && presence->smallImageText[0])) { + WriteObject assets(writer, "assets"); + WriteOptionalString(writer, "large_image", presence->largeImageKey); + WriteOptionalString(writer, "large_text", presence->largeImageText); + WriteOptionalString(writer, "small_image", presence->smallImageKey); + WriteOptionalString(writer, "small_text", presence->smallImageText); + } + + if ((presence->partyId && presence->partyId[0]) || presence->partySize || + presence->partyMax) { + WriteObject party(writer, "party"); + WriteOptionalString(writer, "id", presence->partyId); + if (presence->partySize && presence->partyMax) { + WriteArray size(writer, "size"); + writer.Int(presence->partySize); + writer.Int(presence->partyMax); + } + } + + if ((presence->matchSecret && presence->matchSecret[0]) || + (presence->joinSecret && presence->joinSecret[0]) || + (presence->spectateSecret && presence->spectateSecret[0])) { + WriteObject secrets(writer, "secrets"); + WriteOptionalString(writer, "match", presence->matchSecret); + WriteOptionalString(writer, "join", presence->joinSecret); + WriteOptionalString(writer, "spectate", presence->spectateSecret); + } + + writer.Key("instance"); + writer.Bool(presence->instance != 0); + } + } + } + + return writer.Size(); +} + +size_t JsonWriteHandshakeObj(char* dest, size_t maxLen, int version, const char* applicationId) +{ + JsonWriter writer(dest, maxLen); + + { + WriteObject obj(writer); + WriteKey(writer, "v"); + writer.Int(version); + WriteKey(writer, "client_id"); + writer.String(applicationId); + } + + return writer.Size(); +} + +size_t JsonWriteSubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName) +{ + JsonWriter writer(dest, maxLen); + + { + WriteObject obj(writer); + + JsonWriteNonce(writer, nonce); + + WriteKey(writer, "cmd"); + writer.String("SUBSCRIBE"); + + WriteKey(writer, "evt"); + writer.String(evtName); + } + + return writer.Size(); +} + +size_t JsonWriteUnsubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName) +{ + JsonWriter writer(dest, maxLen); + + { + WriteObject obj(writer); + + JsonWriteNonce(writer, nonce); + + WriteKey(writer, "cmd"); + writer.String("UNSUBSCRIBE"); + + WriteKey(writer, "evt"); + writer.String(evtName); + } + + return writer.Size(); +} + +size_t JsonWriteJoinReply(char* dest, size_t maxLen, const char* userId, int reply, int nonce) +{ + JsonWriter writer(dest, maxLen); + + { + WriteObject obj(writer); + + WriteKey(writer, "cmd"); + if (reply == DISCORD_REPLY_YES) { + writer.String("SEND_ACTIVITY_JOIN_INVITE"); + } + else { + writer.String("CLOSE_ACTIVITY_JOIN_REQUEST"); + } + + WriteKey(writer, "args"); + { + WriteObject args(writer); + + WriteKey(writer, "user_id"); + writer.String(userId); + } + + JsonWriteNonce(writer, nonce); + } + + return writer.Size(); +} diff --git a/Externals/discord-rpc/src/serialization.h b/Externals/discord-rpc/src/serialization.h new file mode 100644 index 0000000000..9c462dc283 --- /dev/null +++ b/Externals/discord-rpc/src/serialization.h @@ -0,0 +1,215 @@ +#pragma once + +#include + +#ifndef __MINGW32__ +#pragma warning(push) + +#pragma warning(disable : 4061) // enum is not explicitly handled by a case label +#pragma warning(disable : 4365) // signed/unsigned mismatch +#pragma warning(disable : 4464) // relative include path contains +#pragma warning(disable : 4668) // is not defined as a preprocessor macro +#pragma warning(disable : 6313) // Incorrect operator +#endif // __MINGW32__ + +#include "rapidjson/document.h" +#include "rapidjson/stringbuffer.h" +#include "rapidjson/writer.h" + +#ifndef __MINGW32__ +#pragma warning(pop) +#endif // __MINGW32__ + +// if only there was a standard library function for this +template +inline size_t StringCopy(char (&dest)[Len], const char* src) +{ + if (!src || !Len) { + return 0; + } + size_t copied; + char* out = dest; + for (copied = 1; *src && copied < Len; ++copied) { + *out++ = *src++; + } + *out = 0; + return copied - 1; +} + +size_t JsonWriteHandshakeObj(char* dest, size_t maxLen, int version, const char* applicationId); + +// Commands +struct DiscordRichPresence; +size_t JsonWriteRichPresenceObj(char* dest, + size_t maxLen, + int nonce, + int pid, + const DiscordRichPresence* presence); +size_t JsonWriteSubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName); + +size_t JsonWriteUnsubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName); + +size_t JsonWriteJoinReply(char* dest, size_t maxLen, const char* userId, int reply, int nonce); + +// I want to use as few allocations as I can get away with, and to do that with RapidJson, you need +// to supply some of your own allocators for stuff rather than use the defaults + +class LinearAllocator { +public: + char* buffer_; + char* end_; + LinearAllocator() + { + assert(0); // needed for some default case in rapidjson, should not use + } + LinearAllocator(char* buffer, size_t size) + : buffer_(buffer) + , end_(buffer + size) + { + } + static const bool kNeedFree = false; + void* Malloc(size_t size) + { + char* res = buffer_; + buffer_ += size; + if (buffer_ > end_) { + buffer_ = res; + return nullptr; + } + return res; + } + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) + { + if (newSize == 0) { + return nullptr; + } + // allocate how much you need in the first place + assert(!originalPtr && !originalSize); + // unused parameter warning + (void)(originalPtr); + (void)(originalSize); + return Malloc(newSize); + } + static void Free(void* ptr) + { + /* shrug */ + (void)ptr; + } +}; + +template +class FixedLinearAllocator : public LinearAllocator { +public: + char fixedBuffer_[Size]; + FixedLinearAllocator() + : LinearAllocator(fixedBuffer_, Size) + { + } + static const bool kNeedFree = false; +}; + +// wonder why this isn't a thing already, maybe I missed it +class DirectStringBuffer { +public: + using Ch = char; + char* buffer_; + char* end_; + char* current_; + + DirectStringBuffer(char* buffer, size_t maxLen) + : buffer_(buffer) + , end_(buffer + maxLen) + , current_(buffer) + { + } + + void Put(char c) + { + if (current_ < end_) { + *current_++ = c; + } + } + void Flush() {} + size_t GetSize() const { return (size_t)(current_ - buffer_); } +}; + +using MallocAllocator = rapidjson::CrtAllocator; +using PoolAllocator = rapidjson::MemoryPoolAllocator; +using UTF8 = rapidjson::UTF8; +// Writer appears to need about 16 bytes per nested object level (with 64bit size_t) +using StackAllocator = FixedLinearAllocator<2048>; +constexpr size_t WriterNestingLevels = 2048 / (2 * sizeof(size_t)); +using JsonWriterBase = + rapidjson::Writer; +class JsonWriter : public JsonWriterBase { +public: + DirectStringBuffer stringBuffer_; + StackAllocator stackAlloc_; + + JsonWriter(char* dest, size_t maxLen) + : JsonWriterBase(stringBuffer_, &stackAlloc_, WriterNestingLevels) + , stringBuffer_(dest, maxLen) + , stackAlloc_() + { + } + + size_t Size() const { return stringBuffer_.GetSize(); } +}; + +using JsonDocumentBase = rapidjson::GenericDocument; +class JsonDocument : public JsonDocumentBase { +public: + static const int kDefaultChunkCapacity = 32 * 1024; + // json parser will use this buffer first, then allocate more if needed; I seriously doubt we + // send any messages that would use all of this, though. + char parseBuffer_[32 * 1024]; + MallocAllocator mallocAllocator_; + PoolAllocator poolAllocator_; + StackAllocator stackAllocator_; + JsonDocument() + : JsonDocumentBase(rapidjson::kObjectType, + &poolAllocator_, + sizeof(stackAllocator_.fixedBuffer_), + &stackAllocator_) + , poolAllocator_(parseBuffer_, sizeof(parseBuffer_), kDefaultChunkCapacity, &mallocAllocator_) + , stackAllocator_() + { + } +}; + +using JsonValue = rapidjson::GenericValue; + +inline JsonValue* GetObjMember(JsonValue* obj, const char* name) +{ + if (obj) { + auto member = obj->FindMember(name); + if (member != obj->MemberEnd() && member->value.IsObject()) { + return &member->value; + } + } + return nullptr; +} + +inline int GetIntMember(JsonValue* obj, const char* name, int notFoundDefault = 0) +{ + if (obj) { + auto member = obj->FindMember(name); + if (member != obj->MemberEnd() && member->value.IsInt()) { + return member->value.GetInt(); + } + } + return notFoundDefault; +} + +inline const char* GetStrMember(JsonValue* obj, + const char* name, + const char* notFoundDefault = nullptr) +{ + if (obj) { + auto member = obj->FindMember(name); + if (member != obj->MemberEnd() && member->value.IsString()) { + return member->value.GetString(); + } + } + return notFoundDefault; +} diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/allocators.h b/Externals/discord-rpc/thirdparty/include/rapidjson/allocators.h new file mode 100644 index 0000000000..98affe03fb --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/allocators.h @@ -0,0 +1,271 @@ +// 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_ALLOCATORS_H_ +#define RAPIDJSON_ALLOCATORS_H_ + +#include "rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Allocator + +/*! \class rapidjson::Allocator + \brief Concept for allocating, resizing and freeing memory block. + + Note that Malloc() and Realloc() are non-static but Free() is static. + + So if an allocator need to support Free(), it needs to put its pointer in + the header of memory block. + +\code +concept Allocator { + static const bool kNeedFree; //!< Whether this allocator needs to call Free(). + + // Allocate a memory block. + // \param size of the memory block in bytes. + // \returns pointer to the memory block. + void* Malloc(size_t size); + + // Resize a memory block. + // \param originalPtr The pointer to current memory block. Null pointer is permitted. + // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.) + // \param newSize the new size in bytes. + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize); + + // Free a memory block. + // \param pointer to the memory block. Null pointer is permitted. + static void Free(void *ptr); +}; +\endcode +*/ + +/////////////////////////////////////////////////////////////////////////////// +// CrtAllocator + +//! C-runtime library allocator. +/*! This class is just wrapper for standard C library memory routines. + \note implements Allocator concept +*/ +class CrtAllocator { +public: + static const bool kNeedFree = true; + void* Malloc(size_t size) { + if (size) // behavior of malloc(0) is implementation defined. + return std::malloc(size); + else + return NULL; // standardize to returning NULL. + } + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { + (void)originalSize; + if (newSize == 0) { + std::free(originalPtr); + return NULL; + } + return std::realloc(originalPtr, newSize); + } + static void Free(void *ptr) { std::free(ptr); } +}; + +/////////////////////////////////////////////////////////////////////////////// +// MemoryPoolAllocator + +//! Default memory allocator used by the parser and DOM. +/*! This allocator allocate memory blocks from pre-allocated memory chunks. + + It does not free memory blocks. And Realloc() only allocate new memory. + + The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default. + + User may also supply a buffer as the first chunk. + + If the user-buffer is full then additional chunks are allocated by BaseAllocator. + + The user-buffer is not deallocated by this allocator. + + \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator. + \note implements Allocator concept +*/ +template +class MemoryPoolAllocator { +public: + static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator) + + //! Constructor with chunkSize. + /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. + \param baseAllocator The allocator for allocating memory chunks. + */ + MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : + chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0) + { + } + + //! Constructor with user-supplied buffer. + /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size. + + The user buffer will not be deallocated when this allocator is destructed. + + \param buffer User supplied buffer. + \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader). + \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. + \param baseAllocator The allocator for allocating memory chunks. + */ + MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : + chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0) + { + RAPIDJSON_ASSERT(buffer != 0); + RAPIDJSON_ASSERT(size > sizeof(ChunkHeader)); + chunkHead_ = reinterpret_cast(buffer); + chunkHead_->capacity = size - sizeof(ChunkHeader); + chunkHead_->size = 0; + chunkHead_->next = 0; + } + + //! Destructor. + /*! This deallocates all memory chunks, excluding the user-supplied buffer. + */ + ~MemoryPoolAllocator() { + Clear(); + RAPIDJSON_DELETE(ownBaseAllocator_); + } + + //! Deallocates all memory chunks, excluding the user-supplied buffer. + void Clear() { + while (chunkHead_ && chunkHead_ != userBuffer_) { + ChunkHeader* next = chunkHead_->next; + baseAllocator_->Free(chunkHead_); + chunkHead_ = next; + } + if (chunkHead_ && chunkHead_ == userBuffer_) + chunkHead_->size = 0; // Clear user buffer + } + + //! Computes the total capacity of allocated memory chunks. + /*! \return total capacity in bytes. + */ + size_t Capacity() const { + size_t capacity = 0; + for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) + capacity += c->capacity; + return capacity; + } + + //! Computes the memory blocks allocated. + /*! \return total used bytes. + */ + size_t Size() const { + size_t size = 0; + for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) + size += c->size; + return size; + } + + //! Allocates a memory block. (concept Allocator) + void* Malloc(size_t size) { + if (!size) + return NULL; + + size = RAPIDJSON_ALIGN(size); + if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity) + if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size)) + return NULL; + + void *buffer = reinterpret_cast(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size; + chunkHead_->size += size; + return buffer; + } + + //! Resizes a memory block (concept Allocator) + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { + if (originalPtr == 0) + return Malloc(newSize); + + if (newSize == 0) + return NULL; + + originalSize = RAPIDJSON_ALIGN(originalSize); + newSize = RAPIDJSON_ALIGN(newSize); + + // Do not shrink if new size is smaller than original + if (originalSize >= newSize) + return originalPtr; + + // Simply expand it if it is the last allocation and there is sufficient space + if (originalPtr == reinterpret_cast(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) { + size_t increment = static_cast(newSize - originalSize); + if (chunkHead_->size + increment <= chunkHead_->capacity) { + chunkHead_->size += increment; + return originalPtr; + } + } + + // Realloc process: allocate and copy memory, do not free original buffer. + if (void* newBuffer = Malloc(newSize)) { + if (originalSize) + std::memcpy(newBuffer, originalPtr, originalSize); + return newBuffer; + } + else + return NULL; + } + + //! Frees a memory block (concept Allocator) + static void Free(void *ptr) { (void)ptr; } // Do nothing + +private: + //! Copy constructor is not permitted. + MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */; + //! Copy assignment operator is not permitted. + MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */; + + //! Creates a new chunk. + /*! \param capacity Capacity of the chunk in bytes. + \return true if success. + */ + bool AddChunk(size_t capacity) { + if (!baseAllocator_) + ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator()); + if (ChunkHeader* chunk = reinterpret_cast(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity))) { + chunk->capacity = capacity; + chunk->size = 0; + chunk->next = chunkHead_; + chunkHead_ = chunk; + return true; + } + else + return false; + } + + static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity. + + //! Chunk header for perpending to each chunk. + /*! Chunks are stored as a singly linked list. + */ + struct ChunkHeader { + size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself). + size_t size; //!< Current size of allocated memory in bytes. + ChunkHeader *next; //!< Next chunk in the linked list. + }; + + ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation. + size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated. + void *userBuffer_; //!< User supplied buffer. + BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks. + BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object. +}; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_ENCODINGS_H_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/document.h b/Externals/discord-rpc/thirdparty/include/rapidjson/document.h new file mode 100644 index 0000000000..e3e20dfbdc --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/document.h @@ -0,0 +1,2575 @@ +// 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_DOCUMENT_H_ +#define RAPIDJSON_DOCUMENT_H_ + +/*! \file document.h */ + +#include "reader.h" +#include "internal/meta.h" +#include "internal/strfunc.h" +#include "memorystream.h" +#include "encodedstream.h" +#include // placement new +#include + +RAPIDJSON_DIAG_PUSH +#ifdef _MSC_VER +RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(switch-enum) +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_OFF(effc++) +#if __GNUC__ >= 6 +RAPIDJSON_DIAG_OFF(terminate) // ignore throwing RAPIDJSON_ASSERT in RAPIDJSON_NOEXCEPT functions +#endif +#endif // __GNUC__ + +#ifndef RAPIDJSON_NOMEMBERITERATORCLASS +#include // std::iterator, std::random_access_iterator_tag +#endif + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS +#include // std::move +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +// Forward declaration. +template +class GenericValue; + +template +class GenericDocument; + +//! Name-value pair in a JSON object value. +/*! + This class was internal to GenericValue. It used to be a inner struct. + But a compiler (IBM XL C/C++ for AIX) have reported to have problem with that so it moved as a namespace scope struct. + https://code.google.com/p/rapidjson/issues/detail?id=64 +*/ +template +struct GenericMember { + GenericValue name; //!< name of member (must be a string) + GenericValue value; //!< value of member. +}; + +/////////////////////////////////////////////////////////////////////////////// +// GenericMemberIterator + +#ifndef RAPIDJSON_NOMEMBERITERATORCLASS + +//! (Constant) member iterator for a JSON object value +/*! + \tparam Const Is this a constant iterator? + \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. + + This class implements a Random Access Iterator for GenericMember elements + of a GenericValue, see ISO/IEC 14882:2003(E) C++ standard, 24.1 [lib.iterator.requirements]. + + \note This iterator implementation is mainly intended to avoid implicit + conversions from iterator values to \c NULL, + e.g. from GenericValue::FindMember. + + \note Define \c RAPIDJSON_NOMEMBERITERATORCLASS to fall back to a + pointer-based implementation, if your platform doesn't provide + the C++ header. + + \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator + */ +template +class GenericMemberIterator + : public std::iterator >::Type> { + + friend class GenericValue; + template friend class GenericMemberIterator; + + typedef GenericMember PlainType; + typedef typename internal::MaybeAddConst::Type ValueType; + typedef std::iterator BaseType; + +public: + //! Iterator type itself + typedef GenericMemberIterator Iterator; + //! Constant iterator type + typedef GenericMemberIterator ConstIterator; + //! Non-constant iterator type + typedef GenericMemberIterator NonConstIterator; + + //! Pointer to (const) GenericMember + typedef typename BaseType::pointer Pointer; + //! Reference to (const) GenericMember + typedef typename BaseType::reference Reference; + //! Signed integer type (e.g. \c ptrdiff_t) + typedef typename BaseType::difference_type DifferenceType; + + //! Default constructor (singular value) + /*! Creates an iterator pointing to no element. + \note All operations, except for comparisons, are undefined on such values. + */ + GenericMemberIterator() : ptr_() {} + + //! Iterator conversions to more const + /*! + \param it (Non-const) iterator to copy from + + Allows the creation of an iterator from another GenericMemberIterator + that is "less const". Especially, creating a non-constant iterator + from a constant iterator are disabled: + \li const -> non-const (not ok) + \li const -> const (ok) + \li non-const -> const (ok) + \li non-const -> non-const (ok) + + \note If the \c Const template parameter is already \c false, this + constructor effectively defines a regular copy-constructor. + Otherwise, the copy constructor is implicitly defined. + */ + GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {} + Iterator& operator=(const NonConstIterator & it) { ptr_ = it.ptr_; return *this; } + + //! @name stepping + //@{ + Iterator& operator++(){ ++ptr_; return *this; } + Iterator& operator--(){ --ptr_; return *this; } + Iterator operator++(int){ Iterator old(*this); ++ptr_; return old; } + Iterator operator--(int){ Iterator old(*this); --ptr_; return old; } + //@} + + //! @name increment/decrement + //@{ + Iterator operator+(DifferenceType n) const { return Iterator(ptr_+n); } + Iterator operator-(DifferenceType n) const { return Iterator(ptr_-n); } + + Iterator& operator+=(DifferenceType n) { ptr_+=n; return *this; } + Iterator& operator-=(DifferenceType n) { ptr_-=n; return *this; } + //@} + + //! @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_; } + //@} + + //! @name dereference + //@{ + Reference operator*() const { return *ptr_; } + Pointer operator->() const { return ptr_; } + Reference operator[](DifferenceType n) const { return ptr_[n]; } + //@} + + //! Distance + DifferenceType operator-(ConstIterator that) const { return ptr_-that.ptr_; } + +private: + //! Internal constructor from plain pointer + explicit GenericMemberIterator(Pointer p) : ptr_(p) {} + + Pointer ptr_; //!< raw pointer +}; + +#else // RAPIDJSON_NOMEMBERITERATORCLASS + +// class-based member iterator implementation disabled, use plain pointers + +template +struct GenericMemberIterator; + +//! non-const GenericMemberIterator +template +struct GenericMemberIterator { + //! use plain pointer as iterator type + typedef GenericMember* Iterator; +}; +//! const GenericMemberIterator +template +struct GenericMemberIterator { + //! use plain const pointer as iterator type + typedef const GenericMember* Iterator; +}; + +#endif // RAPIDJSON_NOMEMBERITERATORCLASS + +/////////////////////////////////////////////////////////////////////////////// +// GenericStringRef + +//! Reference to a constant string (not taking a copy) +/*! + \tparam CharType character type of the string + + This helper class is used to automatically infer constant string + references for string literals, especially from \c const \b (!) + character arrays. + + The main use is for creating JSON string values without copying the + source string via an \ref Allocator. This requires that the referenced + string pointers have a sufficient lifetime, which exceeds the lifetime + of the associated GenericValue. + + \b Example + \code + Value v("foo"); // ok, no need to copy & calculate length + const char foo[] = "foo"; + v.SetString(foo); // ok + + const char* bar = foo; + // Value x(bar); // not ok, can't rely on bar's lifetime + Value x(StringRef(bar)); // lifetime explicitly guaranteed by user + Value y(StringRef(bar, 3)); // ok, explicitly pass length + \endcode + + \see StringRef, GenericValue::SetString +*/ +template +struct GenericStringRef { + typedef CharType Ch; //!< character type of the string + + //! Create string reference from \c const character array +#ifndef __clang__ // -Wdocumentation + /*! + This constructor implicitly creates a constant string reference from + a \c const character array. It has better performance than + \ref StringRef(const CharType*) by inferring the string \ref length + from the array length, and also supports strings containing null + characters. + + \tparam N length of the string, automatically inferred + + \param str Constant character array, lifetime assumed to be longer + than the use of the string in e.g. a GenericValue + + \post \ref s == str + + \note Constant complexity. + \note There is a hidden, private overload to disallow references to + non-const character arrays to be created via this constructor. + By this, e.g. function-scope arrays used to be filled via + \c snprintf are excluded from consideration. + In such cases, the referenced string should be \b copied to the + GenericValue instead. + */ +#endif + template + GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT + : s(str), length(N-1) {} + + //! Explicitly create string reference from \c const character pointer +#ifndef __clang__ // -Wdocumentation + /*! + This constructor can be used to \b explicitly create a reference to + a constant string pointer. + + \see StringRef(const CharType*) + + \param str Constant character pointer, lifetime assumed to be longer + than the use of the string in e.g. a GenericValue + + \post \ref s == str + + \note There is a hidden, private overload to disallow references to + non-const character arrays to be created via this constructor. + By this, e.g. function-scope arrays used to be filled via + \c snprintf are excluded from consideration. + In such cases, the referenced string should be \b copied to the + GenericValue instead. + */ +#endif + explicit GenericStringRef(const CharType* str) + : s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != 0); } + + //! Create constant string reference from pointer and length +#ifndef __clang__ // -Wdocumentation + /*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \param len length of the string, excluding the trailing NULL terminator + + \post \ref s == str && \ref length == len + \note Constant complexity. + */ +#endif + GenericStringRef(const CharType* str, SizeType len) + : s(str), length(len) { RAPIDJSON_ASSERT(s != 0); } + + GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length) {} + + GenericStringRef& operator=(const GenericStringRef& rhs) { s = rhs.s; length = rhs.length; } + + //! implicit conversion to plain CharType pointer + operator const Ch *() const { return s; } + + const Ch* const s; //!< plain CharType pointer + const SizeType length; //!< length of the string (excluding the trailing NULL terminator) + +private: + //! Disallow construction from non-const array + template + GenericStringRef(CharType (&str)[N]) /* = delete */; +}; + +//! Mark a character pointer as constant string +/*! Mark a plain character pointer as a "string literal". This function + can be used to avoid copying a character string to be referenced as a + value in a JSON GenericValue object, if the string's lifetime is known + to be valid long enough. + \tparam CharType Character type of the string + \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \return GenericStringRef string reference object + \relatesalso GenericStringRef + + \see GenericValue::GenericValue(StringRefType), GenericValue::operator=(StringRefType), GenericValue::SetString(StringRefType), GenericValue::PushBack(StringRefType, Allocator&), GenericValue::AddMember +*/ +template +inline GenericStringRef StringRef(const CharType* str) { + return GenericStringRef(str, internal::StrLen(str)); +} + +//! Mark a character pointer as constant string +/*! Mark a plain character pointer as a "string literal". This function + can be used to avoid copying a character string to be referenced as a + value in a JSON GenericValue object, if the string's lifetime is known + to be valid long enough. + + This version has better performance with supplied length, and also + supports string containing null characters. + + \tparam CharType character type of the string + \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \param length The length of source string. + \return GenericStringRef string reference object + \relatesalso GenericStringRef +*/ +template +inline GenericStringRef StringRef(const CharType* str, size_t length) { + return GenericStringRef(str, SizeType(length)); +} + +#if RAPIDJSON_HAS_STDSTRING +//! Mark a string object as constant string +/*! Mark a string object (e.g. \c std::string) as a "string literal". + This function can be used to avoid copying a string to be referenced as a + value in a JSON GenericValue object, if the string's lifetime is known + to be valid long enough. + + \tparam CharType character type of the string + \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \return GenericStringRef string reference object + \relatesalso GenericStringRef + \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. +*/ +template +inline GenericStringRef StringRef(const std::basic_string& str) { + return GenericStringRef(str.data(), SizeType(str.size())); +} +#endif + +/////////////////////////////////////////////////////////////////////////////// +// GenericValue type traits +namespace internal { + +template +struct IsGenericValueImpl : FalseType {}; + +// select candidates according to nested encoding and allocator types +template struct IsGenericValueImpl::Type, typename Void::Type> + : IsBaseOf, T>::Type {}; + +// helper to match arbitrary GenericValue instantiations, including derived classes +template struct IsGenericValue : IsGenericValueImpl::Type {}; + +} // namespace internal + +/////////////////////////////////////////////////////////////////////////////// +// TypeHelper + +namespace internal { + +template +struct TypeHelper {}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsBool(); } + static bool Get(const ValueType& v) { return v.GetBool(); } + static ValueType& Set(ValueType& v, bool data) { return v.SetBool(data); } + static ValueType& Set(ValueType& v, bool data, typename ValueType::AllocatorType&) { return v.SetBool(data); } +}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsInt(); } + static int Get(const ValueType& v) { return v.GetInt(); } + static ValueType& Set(ValueType& v, int data) { return v.SetInt(data); } + static ValueType& Set(ValueType& v, int data, typename ValueType::AllocatorType&) { return v.SetInt(data); } +}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsUint(); } + static unsigned Get(const ValueType& v) { return v.GetUint(); } + static ValueType& Set(ValueType& v, unsigned data) { return v.SetUint(data); } + static ValueType& Set(ValueType& v, unsigned data, typename ValueType::AllocatorType&) { return v.SetUint(data); } +}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsInt64(); } + static int64_t Get(const ValueType& v) { return v.GetInt64(); } + static ValueType& Set(ValueType& v, int64_t data) { return v.SetInt64(data); } + static ValueType& Set(ValueType& v, int64_t data, typename ValueType::AllocatorType&) { return v.SetInt64(data); } +}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsUint64(); } + static uint64_t Get(const ValueType& v) { return v.GetUint64(); } + static ValueType& Set(ValueType& v, uint64_t data) { return v.SetUint64(data); } + static ValueType& Set(ValueType& v, uint64_t data, typename ValueType::AllocatorType&) { return v.SetUint64(data); } +}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsDouble(); } + static double Get(const ValueType& v) { return v.GetDouble(); } + static ValueType& Set(ValueType& v, double data) { return v.SetDouble(data); } + static ValueType& Set(ValueType& v, double data, typename ValueType::AllocatorType&) { return v.SetDouble(data); } +}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsFloat(); } + static float Get(const ValueType& v) { return v.GetFloat(); } + static ValueType& Set(ValueType& v, float data) { return v.SetFloat(data); } + static ValueType& Set(ValueType& v, float data, typename ValueType::AllocatorType&) { return v.SetFloat(data); } +}; + +template +struct TypeHelper { + typedef const typename ValueType::Ch* StringType; + static bool Is(const ValueType& v) { return v.IsString(); } + static StringType Get(const ValueType& v) { return v.GetString(); } + static ValueType& Set(ValueType& v, const StringType data) { return v.SetString(typename ValueType::StringRefType(data)); } + static ValueType& Set(ValueType& v, const StringType data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); } +}; + +#if RAPIDJSON_HAS_STDSTRING +template +struct TypeHelper > { + typedef std::basic_string StringType; + static bool Is(const ValueType& v) { return v.IsString(); } + static StringType Get(const ValueType& v) { return StringType(v.GetString(), v.GetStringLength()); } + static ValueType& Set(ValueType& v, const StringType& data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); } +}; +#endif + +template +struct TypeHelper { + typedef typename ValueType::Array ArrayType; + static bool Is(const ValueType& v) { return v.IsArray(); } + static ArrayType Get(ValueType& v) { return v.GetArray(); } + static ValueType& Set(ValueType& v, ArrayType data) { return v = data; } + static ValueType& Set(ValueType& v, ArrayType data, typename ValueType::AllocatorType&) { return v = data; } +}; + +template +struct TypeHelper { + typedef typename ValueType::ConstArray ArrayType; + static bool Is(const ValueType& v) { return v.IsArray(); } + static ArrayType Get(const ValueType& v) { return v.GetArray(); } +}; + +template +struct TypeHelper { + typedef typename ValueType::Object ObjectType; + static bool Is(const ValueType& v) { return v.IsObject(); } + static ObjectType Get(ValueType& v) { return v.GetObject(); } + static ValueType& Set(ValueType& v, ObjectType data) { return v = data; } + static ValueType& Set(ValueType& v, ObjectType data, typename ValueType::AllocatorType&) { v = data; } +}; + +template +struct TypeHelper { + typedef typename ValueType::ConstObject ObjectType; + static bool Is(const ValueType& v) { return v.IsObject(); } + static ObjectType Get(const ValueType& v) { return v.GetObject(); } +}; + +} // namespace internal + +// Forward declarations +template class GenericArray; +template class GenericObject; + +/////////////////////////////////////////////////////////////////////////////// +// GenericValue + +//! Represents a JSON value. Use Value for UTF8 encoding and default allocator. +/*! + A JSON value can be one of 7 types. This class is a variant type supporting + these types. + + Use the Value if UTF8 and default allocator + + \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 > +class GenericValue { +public: + //! Name-value pair in an object. + typedef GenericMember Member; + typedef Encoding EncodingType; //!< Encoding type from template parameter. + typedef Allocator AllocatorType; //!< Allocator type from template parameter. + typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. + typedef GenericStringRef StringRefType; //!< Reference to a constant string + typedef typename GenericMemberIterator::Iterator MemberIterator; //!< Member iterator for iterating in object. + typedef typename GenericMemberIterator::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object. + typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array. + typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array. + typedef GenericValue ValueType; //!< Value type of itself. + typedef GenericArray Array; + typedef GenericArray ConstArray; + typedef GenericObject Object; + typedef GenericObject ConstObject; + + //!@name Constructors and destructor. + //@{ + + //! Default constructor creates a null value. + GenericValue() RAPIDJSON_NOEXCEPT : data_() { data_.f.flags = kNullFlag; } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move constructor in C++11 + GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_) { + rhs.data_.f.flags = kNullFlag; // give up contents + } +#endif + +private: + //! Copy constructor is not permitted. + GenericValue(const GenericValue& rhs); + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Moving from a GenericDocument is not permitted. + template + GenericValue(GenericDocument&& rhs); + + //! Move assignment from a GenericDocument is not permitted. + template + GenericValue& operator=(GenericDocument&& rhs); +#endif + +public: + + //! Constructor with JSON value type. + /*! This creates a Value of specified type with default content. + \param type Type of the value. + \note Default content for number is zero. + */ + explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_() { + static const uint16_t defaultFlags[7] = { + kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag, + kNumberAnyFlag + }; + RAPIDJSON_ASSERT(type <= kNumberType); + data_.f.flags = defaultFlags[type]; + + // Use ShortString to store empty string. + if (type == kStringType) + data_.ss.SetLength(0); + } + + //! Explicit copy constructor (with allocator) + /*! Creates a copy of a Value by using the given Allocator + \tparam SourceAllocator allocator of \c rhs + \param rhs Value to copy from (read-only) + \param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator(). + \see CopyFrom() + */ + template< typename SourceAllocator > + GenericValue(const GenericValue& rhs, Allocator & allocator); + + //! Constructor for boolean value. + /*! \param b Boolean value + \note This constructor is limited to \em real boolean values and rejects + implicitly converted types like arbitrary pointers. Use an explicit cast + to \c bool, if you want to construct a boolean JSON value in such cases. + */ +#ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen + template + explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame))) RAPIDJSON_NOEXCEPT // See #472 +#else + explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT +#endif + : data_() { + // safe-guard against failing SFINAE + RAPIDJSON_STATIC_ASSERT((internal::IsSame::Value)); + data_.f.flags = b ? kTrueFlag : kFalseFlag; + } + + //! Constructor for int value. + explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_() { + data_.n.i64 = i; + data_.f.flags = (i >= 0) ? (kNumberIntFlag | kUintFlag | kUint64Flag) : kNumberIntFlag; + } + + //! Constructor for unsigned value. + explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_() { + data_.n.u64 = u; + data_.f.flags = (u & 0x80000000) ? kNumberUintFlag : (kNumberUintFlag | kIntFlag | kInt64Flag); + } + + //! Constructor for int64_t value. + explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_() { + data_.n.i64 = i64; + data_.f.flags = kNumberInt64Flag; + if (i64 >= 0) { + data_.f.flags |= kNumberUint64Flag; + if (!(static_cast(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) + data_.f.flags |= kUintFlag; + if (!(static_cast(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + data_.f.flags |= kIntFlag; + } + else if (i64 >= static_cast(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + data_.f.flags |= kIntFlag; + } + + //! Constructor for uint64_t value. + explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_() { + data_.n.u64 = u64; + data_.f.flags = kNumberUint64Flag; + if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000))) + data_.f.flags |= kInt64Flag; + if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) + data_.f.flags |= kUintFlag; + if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + data_.f.flags |= kIntFlag; + } + + //! Constructor for double value. + explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = d; data_.f.flags = kNumberDoubleFlag; } + + //! Constructor for constant string (i.e. do not make a copy of string) + GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(StringRef(s, length)); } + + //! Constructor for constant string (i.e. do not make a copy of string) + explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(s); } + + //! Constructor for copy-string (i.e. do make a copy of string) + GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_() { SetStringRaw(StringRef(s, length), allocator); } + + //! Constructor for copy-string (i.e. do make a copy of string) + GenericValue(const Ch*s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); } + +#if RAPIDJSON_HAS_STDSTRING + //! Constructor for copy-string from a string object (i.e. do make a copy of string) + /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + GenericValue(const std::basic_string& s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); } +#endif + + //! Constructor for Array. + /*! + \param a An array obtained by \c GetArray(). + \note \c Array is always pass-by-value. + \note the source array is moved into this value and the sourec array becomes empty. + */ + GenericValue(Array a) RAPIDJSON_NOEXCEPT : data_(a.value_.data_) { + a.value_.data_ = Data(); + a.value_.data_.f.flags = kArrayFlag; + } + + //! Constructor for Object. + /*! + \param o An object obtained by \c GetObject(). + \note \c Object is always pass-by-value. + \note the source object is moved into this value and the sourec object becomes empty. + */ + GenericValue(Object o) RAPIDJSON_NOEXCEPT : data_(o.value_.data_) { + o.value_.data_ = Data(); + o.value_.data_.f.flags = kObjectFlag; + } + + //! Destructor. + /*! Need to destruct elements of array, members of object, or copy-string. + */ + ~GenericValue() { + if (Allocator::kNeedFree) { // Shortcut by Allocator's trait + switch(data_.f.flags) { + case kArrayFlag: + { + GenericValue* e = GetElementsPointer(); + for (GenericValue* v = e; v != e + data_.a.size; ++v) + v->~GenericValue(); + Allocator::Free(e); + } + break; + + case kObjectFlag: + for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) + m->~Member(); + Allocator::Free(GetMembersPointer()); + break; + + case kCopyStringFlag: + Allocator::Free(const_cast(GetStringPointer())); + break; + + default: + break; // Do nothing for other types. + } + } + } + + //@} + + //!@name Assignment operators + //@{ + + //! Assignment with move semantics. + /*! \param rhs Source of the assignment. It will become a null value after assignment. + */ + GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT { + RAPIDJSON_ASSERT(this != &rhs); + this->~GenericValue(); + RawAssign(rhs); + return *this; + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move assignment in C++11 + GenericValue& operator=(GenericValue&& rhs) RAPIDJSON_NOEXCEPT { + return *this = rhs.Move(); + } +#endif + + //! Assignment of constant string reference (no copy) + /*! \param str Constant string reference to be assigned + \note This overload is needed to avoid clashes with the generic primitive type assignment overload below. + \see GenericStringRef, operator=(T) + */ + GenericValue& operator=(StringRefType str) RAPIDJSON_NOEXCEPT { + GenericValue s(str); + return *this = s; + } + + //! Assignment with primitive types. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param value The value to be assigned. + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref SetString(const Ch*, Allocator&) (for copying) or + \ref StringRef() (to explicitly mark the pointer as constant) instead. + All other pointer types would implicitly convert to \c bool, + use \ref SetBool() instead. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer), (GenericValue&)) + operator=(T value) { + GenericValue v(value); + return *this = v; + } + + //! Deep-copy assignment from Value + /*! Assigns a \b copy of the Value to the current Value object + \tparam SourceAllocator Allocator type of \c rhs + \param rhs Value to copy from (read-only) + \param allocator Allocator to use for copying + */ + template + GenericValue& CopyFrom(const GenericValue& rhs, Allocator& allocator) { + RAPIDJSON_ASSERT(static_cast(this) != static_cast(&rhs)); + this->~GenericValue(); + new (this) GenericValue(rhs, allocator); + return *this; + } + + //! Exchange the contents of this value with those of other. + /*! + \param other Another value. + \note Constant complexity. + */ + GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT { + GenericValue temp; + temp.RawAssign(*this); + RawAssign(other); + other.RawAssign(temp); + return *this; + } + + //! free-standing swap function helper + /*! + Helper function to enable support for common swap implementation pattern based on \c std::swap: + \code + void swap(MyClass& a, MyClass& b) { + using std::swap; + swap(a.value, b.value); + // ... + } + \endcode + \see Swap() + */ + friend inline void swap(GenericValue& a, GenericValue& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } + + //! Prepare Value for move semantics + /*! \return *this */ + GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; } + //@} + + //!@name Equal-to and not-equal-to operators + //@{ + //! Equal-to operator + /*! + \note If an object contains duplicated named member, comparing equality with any object is always \c false. + \note Linear time complexity (number of all values in the subtree and total lengths of all strings). + */ + template + bool operator==(const GenericValue& rhs) const { + typedef GenericValue RhsType; + if (GetType() != rhs.GetType()) + return false; + + switch (GetType()) { + case kObjectType: // Warning: O(n^2) inner-loop + if (data_.o.size != rhs.data_.o.size) + return false; + for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) { + typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name); + if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value) + return false; + } + return true; + + case kArrayType: + if (data_.a.size != rhs.data_.a.size) + return false; + for (SizeType i = 0; i < data_.a.size; i++) + if ((*this)[i] != rhs[i]) + return false; + return true; + + case kStringType: + return StringEqual(rhs); + + case kNumberType: + if (IsDouble() || rhs.IsDouble()) { + double a = GetDouble(); // May convert from integer to double. + double b = rhs.GetDouble(); // Ditto + return a >= b && a <= b; // Prevent -Wfloat-equal + } + else + return data_.n.u64 == rhs.data_.n.u64; + + default: + return true; + } + } + + //! Equal-to operator with const C-string pointer + bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRef(rhs)); } + +#if RAPIDJSON_HAS_STDSTRING + //! Equal-to operator with string object + /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + bool operator==(const std::basic_string& rhs) const { return *this == GenericValue(StringRef(rhs)); } +#endif + + //! Equal-to operator with primitive types + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false + */ + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr,internal::IsGenericValue >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); } + + //! Not-equal-to operator + /*! \return !(*this == rhs) + */ + template + bool operator!=(const GenericValue& rhs) const { return !(*this == rhs); } + + //! Not-equal-to operator with const C-string pointer + bool operator!=(const Ch* rhs) const { return !(*this == rhs); } + + //! Not-equal-to operator with arbitrary types + /*! \return !(*this == rhs) + */ + template RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); } + + //! Equal-to operator with arbitrary types (symmetric version) + /*! \return (rhs == lhs) + */ + template friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; } + + //! Not-Equal-to operator with arbitrary types (symmetric version) + /*! \return !(rhs == lhs) + */ + template friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); } + //@} + + //!@name Type + //@{ + + Type GetType() const { return static_cast(data_.f.flags & kTypeMask); } + bool IsNull() const { return data_.f.flags == kNullFlag; } + bool IsFalse() const { return data_.f.flags == kFalseFlag; } + bool IsTrue() const { return data_.f.flags == kTrueFlag; } + bool IsBool() const { return (data_.f.flags & kBoolFlag) != 0; } + bool IsObject() const { return data_.f.flags == kObjectFlag; } + bool IsArray() const { return data_.f.flags == kArrayFlag; } + bool IsNumber() const { return (data_.f.flags & kNumberFlag) != 0; } + bool IsInt() const { return (data_.f.flags & kIntFlag) != 0; } + bool IsUint() const { return (data_.f.flags & kUintFlag) != 0; } + bool IsInt64() const { return (data_.f.flags & kInt64Flag) != 0; } + bool IsUint64() const { return (data_.f.flags & kUint64Flag) != 0; } + bool IsDouble() const { return (data_.f.flags & kDoubleFlag) != 0; } + bool IsString() const { return (data_.f.flags & kStringFlag) != 0; } + + // Checks whether a number can be losslessly converted to a double. + bool IsLosslessDouble() const { + if (!IsNumber()) return false; + if (IsUint64()) { + uint64_t u = GetUint64(); + volatile double d = static_cast(u); + return (d >= 0.0) + && (d < static_cast(std::numeric_limits::max())) + && (u == static_cast(d)); + } + if (IsInt64()) { + int64_t i = GetInt64(); + volatile double d = static_cast(i); + return (d >= static_cast(std::numeric_limits::min())) + && (d < static_cast(std::numeric_limits::max())) + && (i == static_cast(d)); + } + return true; // double, int, uint are always lossless + } + + // Checks whether a number is a float (possible lossy). + bool IsFloat() const { + if ((data_.f.flags & kDoubleFlag) == 0) + return false; + double d = GetDouble(); + return d >= -3.4028234e38 && d <= 3.4028234e38; + } + // Checks whether a number can be losslessly converted to a float. + bool IsLosslessFloat() const { + if (!IsNumber()) return false; + double a = GetDouble(); + if (a < static_cast(-std::numeric_limits::max()) + || a > static_cast(std::numeric_limits::max())) + return false; + double b = static_cast(static_cast(a)); + return a >= b && a <= b; // Prevent -Wfloat-equal + } + + //@} + + //!@name Null + //@{ + + GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; } + + //@} + + //!@name Bool + //@{ + + bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return data_.f.flags == kTrueFlag; } + //!< Set boolean value + /*! \post IsBool() == true */ + GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; } + + //@} + + //!@name Object + //@{ + + //! Set this value as an empty object. + /*! \post IsObject() == true */ + GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; } + + //! Get the number of members in the object. + SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; } + + //! Check whether the object is empty. + bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; } + + //! Get a value from an object associated with the name. + /*! \pre IsObject() == true + \tparam T Either \c Ch or \c const \c Ch (template used for disambiguation with \ref operator[](SizeType)) + \note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7. + Since 0.2, if the name is not correct, it will assert. + If user is unsure whether a member exists, user should use HasMember() first. + A better approach is to use FindMember(). + \note Linear time complexity. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >),(GenericValue&)) operator[](T* name) { + GenericValue n(StringRef(name)); + return (*this)[n]; + } + template + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast(*this)[name]; } + + //! Get a value from an object associated with the name. + /*! \pre IsObject() == true + \tparam SourceAllocator Allocator of the \c name value + + \note Compared to \ref operator[](T*), this version is faster because it does not need a StrLen(). + And it can also handle strings with embedded null characters. + + \note Linear time complexity. + */ + template + GenericValue& operator[](const GenericValue& name) { + MemberIterator member = FindMember(name); + if (member != MemberEnd()) + return member->value; + else { + RAPIDJSON_ASSERT(false); // see above note + + // This will generate -Wexit-time-destructors in clang + // static GenericValue NullValue; + // return NullValue; + + // Use static buffer and placement-new to prevent destruction + static char buffer[sizeof(GenericValue)]; + return *new (buffer) GenericValue(); + } + } + template + const GenericValue& operator[](const GenericValue& name) const { return const_cast(*this)[name]; } + +#if RAPIDJSON_HAS_STDSTRING + //! Get a value from an object associated with name (string object). + GenericValue& operator[](const std::basic_string& name) { return (*this)[GenericValue(StringRef(name))]; } + const GenericValue& operator[](const std::basic_string& name) const { return (*this)[GenericValue(StringRef(name))]; } +#endif + + //! Const member iterator + /*! \pre IsObject() == true */ + ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer()); } + //! Const \em past-the-end member iterator + /*! \pre IsObject() == true */ + ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer() + data_.o.size); } + //! Member iterator + /*! \pre IsObject() == true */ + MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer()); } + //! \em Past-the-end member iterator + /*! \pre IsObject() == true */ + MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer() + data_.o.size); } + + //! Check whether a member exists in the object. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); } + +#if RAPIDJSON_HAS_STDSTRING + //! Check whether a member exists in the object with string object. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + bool HasMember(const std::basic_string& name) const { return FindMember(name) != MemberEnd(); } +#endif + + //! Check whether a member exists in the object with GenericValue name. + /*! + This version is faster because it does not need a StrLen(). It can also handle string with null character. + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + template + bool HasMember(const GenericValue& name) const { return FindMember(name) != MemberEnd(); } + + //! Find member by name. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + + \note Earlier versions of Rapidjson returned a \c NULL pointer, in case + the requested member doesn't exist. For consistency with e.g. + \c std::map, this has been changed to MemberEnd() now. + \note Linear time complexity. + */ + MemberIterator FindMember(const Ch* name) { + GenericValue n(StringRef(name)); + return FindMember(n); + } + + ConstMemberIterator FindMember(const Ch* name) const { return const_cast(*this).FindMember(name); } + + //! Find member by name. + /*! + This version is faster because it does not need a StrLen(). It can also handle string with null character. + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + + \note Earlier versions of Rapidjson returned a \c NULL pointer, in case + the requested member doesn't exist. For consistency with e.g. + \c std::map, this has been changed to MemberEnd() now. + \note Linear time complexity. + */ + template + MemberIterator FindMember(const GenericValue& name) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(name.IsString()); + MemberIterator member = MemberBegin(); + for ( ; member != MemberEnd(); ++member) + if (name.StringEqual(member->name)) + break; + return member; + } + template ConstMemberIterator FindMember(const GenericValue& name) const { return const_cast(*this).FindMember(name); } + +#if RAPIDJSON_HAS_STDSTRING + //! Find member by string object name. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + */ + MemberIterator FindMember(const std::basic_string& name) { return FindMember(GenericValue(StringRef(name))); } + ConstMemberIterator FindMember(const std::basic_string& name) const { return FindMember(GenericValue(StringRef(name))); } +#endif + + //! Add a member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value Value of any type. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note The ownership of \c name and \c value will be transferred to this object on success. + \pre IsObject() && name.IsString() + \post name.IsNull() && value.IsNull() + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(name.IsString()); + + ObjectData& o = data_.o; + if (o.size >= o.capacity) { + if (o.capacity == 0) { + o.capacity = kDefaultObjectCapacity; + SetMembersPointer(reinterpret_cast(allocator.Malloc(o.capacity * sizeof(Member)))); + } + else { + SizeType oldCapacity = o.capacity; + o.capacity += (oldCapacity + 1) / 2; // grow by factor 1.5 + SetMembersPointer(reinterpret_cast(allocator.Realloc(GetMembersPointer(), oldCapacity * sizeof(Member), o.capacity * sizeof(Member)))); + } + } + Member* members = GetMembersPointer(); + members[o.size].name.RawAssign(name); + members[o.size].value.RawAssign(value); + o.size++; + return *this; + } + + //! Add a constant string value as member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(GenericValue& name, StringRefType value, Allocator& allocator) { + GenericValue v(value); + return AddMember(name, v, allocator); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Add a string object as member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(GenericValue& name, std::basic_string& value, Allocator& allocator) { + GenericValue v(value, allocator); + return AddMember(name, v, allocator); + } +#endif + + //! Add any primitive value as member (name-value pair) to the object. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param name A string value as name of member. + \param value Value of primitive type \c T as value of member + \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref + AddMember(StringRefType, StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized Constant time complexity. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (GenericValue&)) + AddMember(GenericValue& name, T value, Allocator& allocator) { + GenericValue v(value); + return AddMember(name, v, allocator); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(GenericValue&& name, GenericValue& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(GenericValue& name, GenericValue&& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(StringRefType name, GenericValue&& value, Allocator& allocator) { + GenericValue n(name); + return AddMember(n, value, allocator); + } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + + + //! Add a member (name-value pair) to the object. + /*! \param name A constant string reference as name of member. + \param value Value of any type. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note The ownership of \c value will be transferred to this object on success. + \pre IsObject() + \post value.IsNull() + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(StringRefType name, GenericValue& value, Allocator& allocator) { + GenericValue n(name); + return AddMember(n, value, allocator); + } + + //! Add a constant string value as member (name-value pair) to the object. + /*! \param name A constant string reference as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(StringRefType,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(StringRefType name, StringRefType value, Allocator& allocator) { + GenericValue v(value); + return AddMember(name, v, allocator); + } + + //! Add any primitive value as member (name-value pair) to the object. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param name A constant string reference as name of member. + \param value Value of primitive type \c T as value of member + \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref + AddMember(StringRefType, StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized Constant time complexity. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (GenericValue&)) + AddMember(StringRefType name, T value, Allocator& allocator) { + GenericValue n(name); + return AddMember(n, value, allocator); + } + + //! Remove all members in the object. + /*! This function do not deallocate memory in the object, i.e. the capacity is unchanged. + \note Linear time complexity. + */ + void RemoveAllMembers() { + RAPIDJSON_ASSERT(IsObject()); + for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) + m->~Member(); + data_.o.size = 0; + } + + //! Remove a member in object by its name. + /*! \param name Name of member to be removed. + \return Whether the member existed. + \note This function may reorder the object members. Use \ref + EraseMember(ConstMemberIterator) if you need to preserve the + relative order of the remaining members. + \note Linear time complexity. + */ + bool RemoveMember(const Ch* name) { + GenericValue n(StringRef(name)); + return RemoveMember(n); + } + +#if RAPIDJSON_HAS_STDSTRING + bool RemoveMember(const std::basic_string& name) { return RemoveMember(GenericValue(StringRef(name))); } +#endif + + template + bool RemoveMember(const GenericValue& name) { + MemberIterator m = FindMember(name); + if (m != MemberEnd()) { + RemoveMember(m); + return true; + } + else + return false; + } + + //! Remove a member in object by iterator. + /*! \param m member iterator (obtained by FindMember() or MemberBegin()). + \return the new iterator after removal. + \note This function may reorder the object members. Use \ref + EraseMember(ConstMemberIterator) if you need to preserve the + relative order of the remaining members. + \note Constant time complexity. + */ + MemberIterator RemoveMember(MemberIterator m) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(data_.o.size > 0); + RAPIDJSON_ASSERT(GetMembersPointer() != 0); + RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd()); + + MemberIterator last(GetMembersPointer() + (data_.o.size - 1)); + if (data_.o.size > 1 && m != last) + *m = *last; // Move the last one to this place + else + m->~Member(); // Only one left, just destroy + --data_.o.size; + return m; + } + + //! Remove a member from an object by iterator. + /*! \param pos iterator to the member to remove + \pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd() + \return Iterator following the removed element. + If the iterator \c pos refers to the last element, the \ref MemberEnd() iterator is returned. + \note This function preserves the relative order of the remaining object + members. If you do not need this, use the more efficient \ref RemoveMember(MemberIterator). + \note Linear time complexity. + */ + MemberIterator EraseMember(ConstMemberIterator pos) { + return EraseMember(pos, pos +1); + } + + //! Remove members in the range [first, last) from an object. + /*! \param first iterator to the first member to remove + \param last iterator following the last member to remove + \pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd() + \return Iterator following the last removed element. + \note This function preserves the relative order of the remaining object + members. + \note Linear time complexity. + */ + MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(data_.o.size > 0); + RAPIDJSON_ASSERT(GetMembersPointer() != 0); + RAPIDJSON_ASSERT(first >= MemberBegin()); + RAPIDJSON_ASSERT(first <= last); + RAPIDJSON_ASSERT(last <= MemberEnd()); + + MemberIterator pos = MemberBegin() + (first - MemberBegin()); + for (MemberIterator itr = pos; itr != last; ++itr) + itr->~Member(); + std::memmove(&*pos, &*last, static_cast(MemberEnd() - last) * sizeof(Member)); + data_.o.size -= static_cast(last - first); + return pos; + } + + //! Erase a member in object by its name. + /*! \param name Name of member to be removed. + \return Whether the member existed. + \note Linear time complexity. + */ + bool EraseMember(const Ch* name) { + GenericValue n(StringRef(name)); + return EraseMember(n); + } + +#if RAPIDJSON_HAS_STDSTRING + bool EraseMember(const std::basic_string& name) { return EraseMember(GenericValue(StringRef(name))); } +#endif + + template + bool EraseMember(const GenericValue& name) { + MemberIterator m = FindMember(name); + if (m != MemberEnd()) { + EraseMember(m); + return true; + } + else + return false; + } + + Object GetObject() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); } + ConstObject GetObject() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); } + + //@} + + //!@name Array + //@{ + + //! Set this value as an empty array. + /*! \post IsArray == true */ + GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; } + + //! Get the number of elements in array. + SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; } + + //! Get the capacity of array. + SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; } + + //! Check whether the array is empty. + bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; } + + //! Remove all elements in the array. + /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged. + \note Linear time complexity. + */ + void Clear() { + RAPIDJSON_ASSERT(IsArray()); + GenericValue* e = GetElementsPointer(); + for (GenericValue* v = e; v != e + data_.a.size; ++v) + v->~GenericValue(); + data_.a.size = 0; + } + + //! Get an element from array by index. + /*! \pre IsArray() == true + \param index Zero-based index of element. + \see operator[](T*) + */ + GenericValue& operator[](SizeType index) { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(index < data_.a.size); + return GetElementsPointer()[index]; + } + const GenericValue& operator[](SizeType index) const { return const_cast(*this)[index]; } + + //! Element iterator + /*! \pre IsArray() == true */ + ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer(); } + //! \em Past-the-end element iterator + /*! \pre IsArray() == true */ + ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer() + data_.a.size; } + //! Constant element iterator + /*! \pre IsArray() == true */ + ConstValueIterator Begin() const { return const_cast(*this).Begin(); } + //! Constant \em past-the-end element iterator + /*! \pre IsArray() == true */ + ConstValueIterator End() const { return const_cast(*this).End(); } + + //! Request the array to have enough capacity to store elements. + /*! \param newCapacity The capacity that the array at least need to have. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note Linear time complexity. + */ + GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) { + RAPIDJSON_ASSERT(IsArray()); + if (newCapacity > data_.a.capacity) { + SetElementsPointer(reinterpret_cast(allocator.Realloc(GetElementsPointer(), data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue)))); + data_.a.capacity = newCapacity; + } + return *this; + } + + //! Append a GenericValue at the end of the array. + /*! \param value Value to be appended. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \post value.IsNull() == true + \return The value itself for fluent API. + \note The ownership of \c value will be transferred to this array on success. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + \note Amortized constant time complexity. + */ + GenericValue& PushBack(GenericValue& value, Allocator& allocator) { + RAPIDJSON_ASSERT(IsArray()); + if (data_.a.size >= data_.a.capacity) + Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.capacity + (data_.a.capacity + 1) / 2), allocator); + GetElementsPointer()[data_.a.size++].RawAssign(value); + return *this; + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericValue& PushBack(GenericValue&& value, Allocator& allocator) { + return PushBack(value, allocator); + } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + + //! Append a constant string reference at the end of the array. + /*! \param value Constant string reference to be appended. + \param allocator Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \return The value itself for fluent API. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + \note Amortized constant time complexity. + \see GenericStringRef + */ + GenericValue& PushBack(StringRefType value, Allocator& allocator) { + return (*this).template PushBack(value, allocator); + } + + //! Append a primitive value at the end of the array. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param value Value of primitive type T to be appended. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \return The value itself for fluent API. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref PushBack(GenericValue&, Allocator&) or \ref + PushBack(StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized constant time complexity. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (GenericValue&)) + PushBack(T value, Allocator& allocator) { + GenericValue v(value); + return PushBack(v, allocator); + } + + //! Remove the last element in the array. + /*! + \note Constant time complexity. + */ + GenericValue& PopBack() { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(!Empty()); + GetElementsPointer()[--data_.a.size].~GenericValue(); + return *this; + } + + //! Remove an element of array by iterator. + /*! + \param pos iterator to the element to remove + \pre IsArray() == true && \ref Begin() <= \c pos < \ref End() + \return Iterator following the removed element. If the iterator pos refers to the last element, the End() iterator is returned. + \note Linear time complexity. + */ + ValueIterator Erase(ConstValueIterator pos) { + return Erase(pos, pos + 1); + } + + //! Remove elements in the range [first, last) of the array. + /*! + \param first iterator to the first element to remove + \param last iterator following the last element to remove + \pre IsArray() == true && \ref Begin() <= \c first <= \c last <= \ref End() + \return Iterator following the last removed element. + \note Linear time complexity. + */ + ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(data_.a.size > 0); + RAPIDJSON_ASSERT(GetElementsPointer() != 0); + RAPIDJSON_ASSERT(first >= Begin()); + RAPIDJSON_ASSERT(first <= last); + RAPIDJSON_ASSERT(last <= End()); + ValueIterator pos = Begin() + (first - Begin()); + for (ValueIterator itr = pos; itr != last; ++itr) + itr->~GenericValue(); + std::memmove(pos, last, static_cast(End() - last) * sizeof(GenericValue)); + data_.a.size -= static_cast(last - first); + return pos; + } + + Array GetArray() { RAPIDJSON_ASSERT(IsArray()); return Array(*this); } + ConstArray GetArray() const { RAPIDJSON_ASSERT(IsArray()); return ConstArray(*this); } + + //@} + + //!@name Number + //@{ + + int GetInt() const { RAPIDJSON_ASSERT(data_.f.flags & kIntFlag); return data_.n.i.i; } + unsigned GetUint() const { RAPIDJSON_ASSERT(data_.f.flags & kUintFlag); return data_.n.u.u; } + int64_t GetInt64() const { RAPIDJSON_ASSERT(data_.f.flags & kInt64Flag); return data_.n.i64; } + uint64_t GetUint64() const { RAPIDJSON_ASSERT(data_.f.flags & kUint64Flag); return data_.n.u64; } + + //! Get the value as double type. + /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessDouble() to check whether the converison is lossless. + */ + double GetDouble() const { + RAPIDJSON_ASSERT(IsNumber()); + if ((data_.f.flags & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion. + if ((data_.f.flags & kIntFlag) != 0) return data_.n.i.i; // int -> double + if ((data_.f.flags & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double + if ((data_.f.flags & kInt64Flag) != 0) return static_cast(data_.n.i64); // int64_t -> double (may lose precision) + RAPIDJSON_ASSERT((data_.f.flags & kUint64Flag) != 0); return static_cast(data_.n.u64); // uint64_t -> double (may lose precision) + } + + //! Get the value as float type. + /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessFloat() to check whether the converison is lossless. + */ + float GetFloat() const { + return static_cast(GetDouble()); + } + + GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; } + GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; } + GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; } + GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; } + GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; } + GenericValue& SetFloat(float f) { this->~GenericValue(); new (this) GenericValue(f); return *this; } + + //@} + + //!@name String + //@{ + + const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return (data_.f.flags & kInlineStrFlag) ? data_.ss.str : GetStringPointer(); } + + //! Get the length of string. + /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength(). + */ + SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((data_.f.flags & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); } + + //! Set this value as a string without copying source string. + /*! This version has better performance with supplied length, and also support string containing null character. + \param s source string pointer. + \param length The length of source string, excluding the trailing null terminator. + \return The value itself for fluent API. + \post IsString() == true && GetString() == s && GetStringLength() == length + \see SetString(StringRefType) + */ + GenericValue& SetString(const Ch* s, SizeType length) { return SetString(StringRef(s, length)); } + + //! Set this value as a string without copying source string. + /*! \param s source string reference + \return The value itself for fluent API. + \post IsString() == true && GetString() == s && GetStringLength() == s.length + */ + GenericValue& SetString(StringRefType s) { this->~GenericValue(); SetStringRaw(s); return *this; } + + //! Set this value as a string by copying from source string. + /*! This version has better performance with supplied length, and also support string containing null character. + \param s source string. + \param length The length of source string, excluding the trailing null terminator. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length + */ + GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(StringRef(s, length), allocator); return *this; } + + //! Set this value as a string by copying from source string. + /*! \param s source string. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length + */ + GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(s, internal::StrLen(s), allocator); } + +#if RAPIDJSON_HAS_STDSTRING + //! Set this value as a string by copying from source string. + /*! \param s source string. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size() + \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + GenericValue& SetString(const std::basic_string& s, Allocator& allocator) { return SetString(s.data(), SizeType(s.size()), allocator); } +#endif + + //@} + + //!@name Array + //@{ + + //! Templated version for checking whether this value is type T. + /*! + \tparam T Either \c bool, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c float, \c const \c char*, \c std::basic_string + */ + template + bool Is() const { return internal::TypeHelper::Is(*this); } + + template + T Get() const { return internal::TypeHelper::Get(*this); } + + template + T Get() { return internal::TypeHelper::Get(*this); } + + template + ValueType& Set(const T& data) { return internal::TypeHelper::Set(*this, data); } + + template + ValueType& Set(const T& data, AllocatorType& allocator) { return internal::TypeHelper::Set(*this, data, allocator); } + + //@} + + //! Generate events of this value to a Handler. + /*! This function adopts the GoF visitor pattern. + Typical usage is to output this JSON value as JSON text via Writer, which is a Handler. + It can also be used to deep clone this value via GenericDocument, which is also a Handler. + \tparam Handler type of handler. + \param handler An object implementing concept Handler. + */ + template + bool Accept(Handler& handler) const { + switch(GetType()) { + case kNullType: return handler.Null(); + case kFalseType: return handler.Bool(false); + case kTrueType: return handler.Bool(true); + + case kObjectType: + if (RAPIDJSON_UNLIKELY(!handler.StartObject())) + return false; + for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) { + RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator. + if (RAPIDJSON_UNLIKELY(!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.data_.f.flags & kCopyFlag) != 0))) + return false; + if (RAPIDJSON_UNLIKELY(!m->value.Accept(handler))) + return false; + } + return handler.EndObject(data_.o.size); + + case kArrayType: + if (RAPIDJSON_UNLIKELY(!handler.StartArray())) + return false; + for (const GenericValue* v = Begin(); v != End(); ++v) + if (RAPIDJSON_UNLIKELY(!v->Accept(handler))) + return false; + return handler.EndArray(data_.a.size); + + case kStringType: + return handler.String(GetString(), GetStringLength(), (data_.f.flags & kCopyFlag) != 0); + + default: + RAPIDJSON_ASSERT(GetType() == kNumberType); + if (IsDouble()) return handler.Double(data_.n.d); + else if (IsInt()) return handler.Int(data_.n.i.i); + else if (IsUint()) return handler.Uint(data_.n.u.u); + else if (IsInt64()) return handler.Int64(data_.n.i64); + else return handler.Uint64(data_.n.u64); + } + } + +private: + template friend class GenericValue; + template friend class GenericDocument; + + enum { + kBoolFlag = 0x0008, + kNumberFlag = 0x0010, + kIntFlag = 0x0020, + kUintFlag = 0x0040, + kInt64Flag = 0x0080, + kUint64Flag = 0x0100, + kDoubleFlag = 0x0200, + kStringFlag = 0x0400, + kCopyFlag = 0x0800, + kInlineStrFlag = 0x1000, + + // Initial flags of different types. + kNullFlag = kNullType, + kTrueFlag = kTrueType | kBoolFlag, + kFalseFlag = kFalseType | kBoolFlag, + kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag, + kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag, + kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag, + kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag, + kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag, + kNumberAnyFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag, + kConstStringFlag = kStringType | kStringFlag, + kCopyStringFlag = kStringType | kStringFlag | kCopyFlag, + kShortStringFlag = kStringType | kStringFlag | kCopyFlag | kInlineStrFlag, + kObjectFlag = kObjectType, + kArrayFlag = kArrayType, + + kTypeMask = 0x07 + }; + + static const SizeType kDefaultArrayCapacity = 16; + static const SizeType kDefaultObjectCapacity = 16; + + struct Flag { +#if RAPIDJSON_48BITPOINTER_OPTIMIZATION + char payload[sizeof(SizeType) * 2 + 6]; // 2 x SizeType + lower 48-bit pointer +#elif RAPIDJSON_64BIT + char payload[sizeof(SizeType) * 2 + sizeof(void*) + 6]; // 6 padding bytes +#else + char payload[sizeof(SizeType) * 2 + sizeof(void*) + 2]; // 2 padding bytes +#endif + uint16_t flags; + }; + + struct String { + SizeType length; + SizeType hashcode; //!< reserved + const Ch* str; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + // implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars + // (excluding the terminating zero) and store a value to determine the length of the contained + // string in the last character str[LenPos] by storing "MaxSize - length" there. If the string + // to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as + // the string terminator as well. For getting the string length back from that value just use + // "MaxSize - str[LenPos]". + // This allows to store 13-chars strings in 32-bit mode, 21-chars strings in 64-bit mode, + // 13-chars strings for RAPIDJSON_48BITPOINTER_OPTIMIZATION=1 inline (for `UTF8`-encoded strings). + struct ShortString { + enum { MaxChars = sizeof(static_cast(0)->payload) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize }; + Ch str[MaxChars]; + + inline static bool Usable(SizeType len) { return (MaxSize >= len); } + inline void SetLength(SizeType len) { str[LenPos] = static_cast(MaxSize - len); } + inline SizeType GetLength() const { return static_cast(MaxSize - str[LenPos]); } + }; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + // By using proper binary layout, retrieval of different integer types do not need conversions. + union Number { +#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN + struct I { + int i; + char padding[4]; + }i; + struct U { + unsigned u; + char padding2[4]; + }u; +#else + struct I { + char padding[4]; + int i; + }i; + struct U { + char padding2[4]; + unsigned u; + }u; +#endif + int64_t i64; + uint64_t u64; + double d; + }; // 8 bytes + + struct ObjectData { + SizeType size; + SizeType capacity; + Member* members; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + struct ArrayData { + SizeType size; + SizeType capacity; + GenericValue* elements; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + union Data { + String s; + ShortString ss; + Number n; + ObjectData o; + ArrayData a; + Flag f; + }; // 16 bytes in 32-bit mode, 24 bytes in 64-bit mode, 16 bytes in 64-bit with RAPIDJSON_48BITPOINTER_OPTIMIZATION + + RAPIDJSON_FORCEINLINE const Ch* GetStringPointer() const { return RAPIDJSON_GETPOINTER(Ch, data_.s.str); } + RAPIDJSON_FORCEINLINE const Ch* SetStringPointer(const Ch* str) { return RAPIDJSON_SETPOINTER(Ch, data_.s.str, str); } + RAPIDJSON_FORCEINLINE GenericValue* GetElementsPointer() const { return RAPIDJSON_GETPOINTER(GenericValue, data_.a.elements); } + RAPIDJSON_FORCEINLINE GenericValue* SetElementsPointer(GenericValue* elements) { return RAPIDJSON_SETPOINTER(GenericValue, data_.a.elements, elements); } + RAPIDJSON_FORCEINLINE Member* GetMembersPointer() const { return RAPIDJSON_GETPOINTER(Member, data_.o.members); } + RAPIDJSON_FORCEINLINE Member* SetMembersPointer(Member* members) { return RAPIDJSON_SETPOINTER(Member, data_.o.members, members); } + + // Initialize this value as array with initial data, without calling destructor. + void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) { + data_.f.flags = kArrayFlag; + if (count) { + GenericValue* e = static_cast(allocator.Malloc(count * sizeof(GenericValue))); + SetElementsPointer(e); + std::memcpy(e, values, count * sizeof(GenericValue)); + } + else + SetElementsPointer(0); + data_.a.size = data_.a.capacity = count; + } + + //! Initialize this value as object with initial data, without calling destructor. + void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) { + data_.f.flags = kObjectFlag; + if (count) { + Member* m = static_cast(allocator.Malloc(count * sizeof(Member))); + SetMembersPointer(m); + std::memcpy(m, members, count * sizeof(Member)); + } + else + SetMembersPointer(0); + data_.o.size = data_.o.capacity = count; + } + + //! Initialize this value as constant string, without calling destructor. + void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT { + data_.f.flags = kConstStringFlag; + SetStringPointer(s); + data_.s.length = s.length; + } + + //! Initialize this value as copy string with initial data, without calling destructor. + void SetStringRaw(StringRefType s, Allocator& allocator) { + Ch* str = 0; + if (ShortString::Usable(s.length)) { + data_.f.flags = kShortStringFlag; + data_.ss.SetLength(s.length); + str = data_.ss.str; + } else { + data_.f.flags = kCopyStringFlag; + data_.s.length = s.length; + str = static_cast(allocator.Malloc((s.length + 1) * sizeof(Ch))); + SetStringPointer(str); + } + std::memcpy(str, s, s.length * sizeof(Ch)); + str[s.length] = '\0'; + } + + //! Assignment without calling destructor + void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT { + data_ = rhs.data_; + // data_.f.flags = rhs.data_.f.flags; + rhs.data_.f.flags = kNullFlag; + } + + template + bool StringEqual(const GenericValue& rhs) const { + RAPIDJSON_ASSERT(IsString()); + RAPIDJSON_ASSERT(rhs.IsString()); + + const SizeType len1 = GetStringLength(); + const SizeType len2 = rhs.GetStringLength(); + if(len1 != len2) { return false; } + + const Ch* const str1 = GetString(); + const Ch* const str2 = rhs.GetString(); + if(str1 == str2) { return true; } // fast path for constant string + + return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0); + } + + Data data_; +}; + +//! GenericValue with UTF8 encoding +typedef GenericValue > Value; + +/////////////////////////////////////////////////////////////////////////////// +// GenericDocument + +//! A document for parsing JSON text as DOM. +/*! + \note implements Handler concept + \tparam Encoding Encoding for both parsing and string storage. + \tparam Allocator Allocator for allocating memory for the DOM + \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 StackAllocator = CrtAllocator> +class GenericDocument : public GenericValue { +public: + typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. + typedef GenericValue ValueType; //!< Value type of the document. + typedef Allocator AllocatorType; //!< Allocator type from template parameter. + + //! Constructor + /*! Creates an empty document of specified type. + \param type Mandatory type of object to create. + \param allocator Optional allocator for allocating memory. + \param stackCapacity Optional initial capacity of stack in bytes. + \param stackAllocator Optional allocator for allocating memory for stack. + */ + explicit GenericDocument(Type type, Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : + GenericValue(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() + { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + } + + //! Constructor + /*! Creates an empty document which type is Null. + \param allocator Optional allocator for allocating memory. + \param stackCapacity Optional initial capacity of stack in bytes. + \param stackAllocator Optional allocator for allocating memory for stack. + */ + GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : + allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() + { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move constructor in C++11 + GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT + : ValueType(std::forward(rhs)), // explicit cast to avoid prohibited move from Document + allocator_(rhs.allocator_), + ownAllocator_(rhs.ownAllocator_), + stack_(std::move(rhs.stack_)), + parseResult_(rhs.parseResult_) + { + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.parseResult_ = ParseResult(); + } +#endif + + ~GenericDocument() { + Destroy(); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move assignment in C++11 + GenericDocument& operator=(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT + { + // The cast to ValueType is necessary here, because otherwise it would + // attempt to call GenericValue's templated assignment operator. + ValueType::operator=(std::forward(rhs)); + + // Calling the destructor here would prematurely call stack_'s destructor + Destroy(); + + allocator_ = rhs.allocator_; + ownAllocator_ = rhs.ownAllocator_; + stack_ = std::move(rhs.stack_); + parseResult_ = rhs.parseResult_; + + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.parseResult_ = ParseResult(); + + return *this; + } +#endif + + //! Exchange the contents of this document with those of another. + /*! + \param rhs Another document. + \note Constant complexity. + \see GenericValue::Swap + */ + GenericDocument& Swap(GenericDocument& rhs) RAPIDJSON_NOEXCEPT { + ValueType::Swap(rhs); + stack_.Swap(rhs.stack_); + internal::Swap(allocator_, rhs.allocator_); + internal::Swap(ownAllocator_, rhs.ownAllocator_); + internal::Swap(parseResult_, rhs.parseResult_); + return *this; + } + + //! free-standing swap function helper + /*! + Helper function to enable support for common swap implementation pattern based on \c std::swap: + \code + void swap(MyClass& a, MyClass& b) { + using std::swap; + swap(a.doc, b.doc); + // ... + } + \endcode + \see Swap() + */ + friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } + + //! Populate this document by a generator which produces SAX events. + /*! \tparam Generator A functor with bool f(Handler) prototype. + \param g Generator functor which sends SAX events to the parameter. + \return The document itself for fluent API. + */ + template + GenericDocument& Populate(Generator& g) { + ClearStackOnExit scope(*this); + if (g(*this)) { + RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object + ValueType::operator=(*stack_.template Pop(1));// Move value from stack to document + } + return *this; + } + + //!@name Parse from stream + //!@{ + + //! Parse JSON text from an input stream (with Encoding conversion) + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam SourceEncoding Encoding of input stream + \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseStream(InputStream& is) { + GenericReader reader( + stack_.HasAllocator() ? &stack_.GetAllocator() : 0); + ClearStackOnExit scope(*this); + parseResult_ = reader.template Parse(is, *this); + if (parseResult_) { + RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object + ValueType::operator=(*stack_.template Pop(1));// Move value from stack to document + } + return *this; + } + + //! Parse JSON text from an input stream + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseStream(InputStream& is) { + return ParseStream(is); + } + + //! Parse JSON text from an input stream (with \ref kParseDefaultFlags) + /*! \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseStream(InputStream& is) { + return ParseStream(is); + } + //!@} + + //!@name Parse in-place from mutable string + //!@{ + + //! Parse JSON text from a mutable string + /*! \tparam parseFlags Combination of \ref ParseFlag. + \param str Mutable zero-terminated string to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseInsitu(Ch* str) { + GenericInsituStringStream s(str); + return ParseStream(s); + } + + //! Parse JSON text from a mutable string (with \ref kParseDefaultFlags) + /*! \param str Mutable zero-terminated string to be parsed. + \return The document itself for fluent API. + */ + GenericDocument& ParseInsitu(Ch* str) { + return ParseInsitu(str); + } + //!@} + + //!@name Parse from read-only string + //!@{ + + //! Parse JSON text from a read-only string (with Encoding conversion) + /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). + \tparam SourceEncoding Transcoding from input Encoding + \param str Read-only zero-terminated string to be parsed. + */ + template + GenericDocument& Parse(const typename SourceEncoding::Ch* str) { + RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); + GenericStringStream s(str); + return ParseStream(s); + } + + //! Parse JSON text from a read-only string + /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). + \param str Read-only zero-terminated string to be parsed. + */ + template + GenericDocument& Parse(const Ch* str) { + return Parse(str); + } + + //! Parse JSON text from a read-only string (with \ref kParseDefaultFlags) + /*! \param str Read-only zero-terminated string to be parsed. + */ + GenericDocument& Parse(const Ch* str) { + return Parse(str); + } + + template + GenericDocument& Parse(const typename SourceEncoding::Ch* str, size_t length) { + RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); + MemoryStream ms(static_cast(str), length * sizeof(typename SourceEncoding::Ch)); + EncodedInputStream is(ms); + ParseStream(is); + return *this; + } + + template + GenericDocument& Parse(const Ch* str, size_t length) { + return Parse(str, length); + } + + GenericDocument& Parse(const Ch* str, size_t length) { + return Parse(str, length); + } + +#if RAPIDJSON_HAS_STDSTRING + template + GenericDocument& Parse(const std::basic_string& str) { + // c_str() is constant complexity according to standard. Should be faster than Parse(const char*, size_t) + return Parse(str.c_str()); + } + + template + GenericDocument& Parse(const std::basic_string& str) { + return Parse(str.c_str()); + } + + GenericDocument& Parse(const std::basic_string& str) { + return Parse(str); + } +#endif // RAPIDJSON_HAS_STDSTRING + + //!@} + + //!@name Handling parse errors + //!@{ + + //! Whether a parse error has occured in the last parsing. + bool HasParseError() const { return parseResult_.IsError(); } + + //! Get the \ref ParseErrorCode of last parsing. + ParseErrorCode GetParseError() const { return parseResult_.Code(); } + + //! Get the position of last parsing error in input, 0 otherwise. + size_t GetErrorOffset() const { return parseResult_.Offset(); } + + //! Implicit conversion to get the last parse result +#ifndef __clang // -Wdocumentation + /*! \return \ref ParseResult of the last parse operation + + \code + Document doc; + ParseResult ok = doc.Parse(json); + if (!ok) + printf( "JSON parse error: %s (%u)\n", GetParseError_En(ok.Code()), ok.Offset()); + \endcode + */ +#endif + operator ParseResult() const { return parseResult_; } + //!@} + + //! Get the allocator of this document. + Allocator& GetAllocator() { + RAPIDJSON_ASSERT(allocator_); + return *allocator_; + } + + //! Get the capacity of stack in bytes. + size_t GetStackCapacity() const { return stack_.GetCapacity(); } + +private: + // clear stack on any exit from ParseStream, e.g. due to exception + struct ClearStackOnExit { + explicit ClearStackOnExit(GenericDocument& d) : d_(d) {} + ~ClearStackOnExit() { d_.ClearStack(); } + private: + ClearStackOnExit(const ClearStackOnExit&); + ClearStackOnExit& operator=(const ClearStackOnExit&); + GenericDocument& d_; + }; + + // callers of the following private Handler functions + // template friend class GenericReader; // for parsing + template friend class GenericValue; // for deep copying + +public: + // Implementation of Handler + bool Null() { new (stack_.template Push()) ValueType(); return true; } + bool Bool(bool b) { new (stack_.template Push()) ValueType(b); return true; } + bool Int(int i) { new (stack_.template Push()) ValueType(i); return true; } + bool Uint(unsigned i) { new (stack_.template Push()) ValueType(i); return true; } + bool Int64(int64_t i) { new (stack_.template Push()) ValueType(i); return true; } + bool Uint64(uint64_t i) { new (stack_.template Push()) ValueType(i); return true; } + bool Double(double d) { new (stack_.template Push()) ValueType(d); return true; } + + bool RawNumber(const Ch* str, SizeType length, bool copy) { + if (copy) + new (stack_.template Push()) ValueType(str, length, GetAllocator()); + else + new (stack_.template Push()) ValueType(str, length); + return true; + } + + bool String(const Ch* str, SizeType length, bool copy) { + if (copy) + new (stack_.template Push()) ValueType(str, length, GetAllocator()); + else + new (stack_.template Push()) ValueType(str, length); + return true; + } + + bool StartObject() { new (stack_.template Push()) ValueType(kObjectType); return true; } + + bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); } + + bool EndObject(SizeType memberCount) { + typename ValueType::Member* members = stack_.template Pop(memberCount); + stack_.template Top()->SetObjectRaw(members, memberCount, GetAllocator()); + return true; + } + + bool StartArray() { new (stack_.template Push()) ValueType(kArrayType); return true; } + + bool EndArray(SizeType elementCount) { + ValueType* elements = stack_.template Pop(elementCount); + stack_.template Top()->SetArrayRaw(elements, elementCount, GetAllocator()); + return true; + } + +private: + //! Prohibit copying + GenericDocument(const GenericDocument&); + //! Prohibit assignment + GenericDocument& operator=(const GenericDocument&); + + void ClearStack() { + if (Allocator::kNeedFree) + while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects) + (stack_.template Pop(1))->~ValueType(); + else + stack_.Clear(); + stack_.ShrinkToFit(); + } + + void Destroy() { + RAPIDJSON_DELETE(ownAllocator_); + } + + static const size_t kDefaultStackCapacity = 1024; + Allocator* allocator_; + Allocator* ownAllocator_; + internal::Stack stack_; + ParseResult parseResult_; +}; + +//! GenericDocument with UTF8 encoding +typedef GenericDocument > Document; + +// defined here due to the dependency on GenericDocument +template +template +inline +GenericValue::GenericValue(const GenericValue& rhs, Allocator& allocator) +{ + switch (rhs.GetType()) { + case kObjectType: + case kArrayType: { // perform deep copy via SAX Handler + GenericDocument d(&allocator); + rhs.Accept(d); + RawAssign(*d.stack_.template Pop(1)); + } + break; + case kStringType: + if (rhs.data_.f.flags == kConstStringFlag) { + data_.f.flags = rhs.data_.f.flags; + data_ = *reinterpret_cast(&rhs.data_); + } else { + SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator); + } + break; + default: + data_.f.flags = rhs.data_.f.flags; + data_ = *reinterpret_cast(&rhs.data_); + break; + } +} + +//! Helper class for accessing Value of array type. +/*! + Instance of this helper class is obtained by \c GenericValue::GetArray(). + In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1. +*/ +template +class GenericArray { +public: + typedef GenericArray ConstArray; + typedef GenericArray Array; + typedef ValueT PlainType; + typedef typename internal::MaybeAddConst::Type ValueType; + typedef ValueType* ValueIterator; // This may be const or non-const iterator + typedef const ValueT* ConstValueIterator; + typedef typename ValueType::AllocatorType AllocatorType; + typedef typename ValueType::StringRefType StringRefType; + + template + friend class GenericValue; + + GenericArray(const GenericArray& rhs) : value_(rhs.value_) {} + GenericArray& operator=(const GenericArray& rhs) { value_ = rhs.value_; return *this; } + ~GenericArray() {} + + SizeType Size() const { return value_.Size(); } + SizeType Capacity() const { return value_.Capacity(); } + bool Empty() const { return value_.Empty(); } + void Clear() const { value_.Clear(); } + ValueType& operator[](SizeType index) const { return value_[index]; } + ValueIterator Begin() const { return value_.Begin(); } + ValueIterator End() const { return value_.End(); } + GenericArray Reserve(SizeType newCapacity, AllocatorType &allocator) const { value_.Reserve(newCapacity, allocator); return *this; } + GenericArray PushBack(ValueType& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericArray PushBack(ValueType&& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericArray PushBack(StringRefType value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (const GenericArray&)) PushBack(T value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } + GenericArray PopBack() const { value_.PopBack(); return *this; } + ValueIterator Erase(ConstValueIterator pos) const { return value_.Erase(pos); } + ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) const { return value_.Erase(first, last); } + +#if RAPIDJSON_HAS_CXX11_RANGE_FOR + ValueIterator begin() const { return value_.Begin(); } + ValueIterator end() const { return value_.End(); } +#endif + +private: + GenericArray(); + GenericArray(ValueType& value) : value_(value) {} + ValueType& value_; +}; + +//! Helper class for accessing Value of object type. +/*! + Instance of this helper class is obtained by \c GenericValue::GetObject(). + In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1. +*/ +template +class GenericObject { +public: + typedef GenericObject ConstObject; + typedef GenericObject Object; + typedef ValueT PlainType; + typedef typename internal::MaybeAddConst::Type ValueType; + typedef GenericMemberIterator MemberIterator; // This may be const or non-const iterator + typedef GenericMemberIterator ConstMemberIterator; + typedef typename ValueType::AllocatorType AllocatorType; + typedef typename ValueType::StringRefType StringRefType; + typedef typename ValueType::EncodingType EncodingType; + typedef typename ValueType::Ch Ch; + + template + friend class GenericValue; + + GenericObject(const GenericObject& rhs) : value_(rhs.value_) {} + GenericObject& operator=(const GenericObject& rhs) { value_ = rhs.value_; return *this; } + ~GenericObject() {} + + SizeType MemberCount() const { return value_.MemberCount(); } + bool ObjectEmpty() const { return value_.ObjectEmpty(); } + template ValueType& operator[](T* name) const { return value_[name]; } + template ValueType& operator[](const GenericValue& name) const { return value_[name]; } +#if RAPIDJSON_HAS_STDSTRING + ValueType& operator[](const std::basic_string& name) const { return value_[name]; } +#endif + MemberIterator MemberBegin() const { return value_.MemberBegin(); } + MemberIterator MemberEnd() const { return value_.MemberEnd(); } + bool HasMember(const Ch* name) const { return value_.HasMember(name); } +#if RAPIDJSON_HAS_STDSTRING + bool HasMember(const std::basic_string& name) const { return value_.HasMember(name); } +#endif + template bool HasMember(const GenericValue& name) const { return value_.HasMember(name); } + MemberIterator FindMember(const Ch* name) const { return value_.FindMember(name); } + template MemberIterator FindMember(const GenericValue& name) const { return value_.FindMember(name); } +#if RAPIDJSON_HAS_STDSTRING + MemberIterator FindMember(const std::basic_string& name) const { return value_.FindMember(name); } +#endif + GenericObject AddMember(ValueType& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(ValueType& name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#if RAPIDJSON_HAS_STDSTRING + GenericObject AddMember(ValueType& name, std::basic_string& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#endif + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) AddMember(ValueType& name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericObject AddMember(ValueType&& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(ValueType&& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(ValueType& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(StringRefType name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericObject AddMember(StringRefType name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(StringRefType name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (GenericObject)) AddMember(StringRefType name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + void RemoveAllMembers() { return value_.RemoveAllMembers(); } + bool RemoveMember(const Ch* name) const { return value_.RemoveMember(name); } +#if RAPIDJSON_HAS_STDSTRING + bool RemoveMember(const std::basic_string& name) const { return value_.RemoveMember(name); } +#endif + template bool RemoveMember(const GenericValue& name) const { return value_.RemoveMember(name); } + MemberIterator RemoveMember(MemberIterator m) const { return value_.RemoveMember(m); } + MemberIterator EraseMember(ConstMemberIterator pos) const { return value_.EraseMember(pos); } + MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) const { return value_.EraseMember(first, last); } + bool EraseMember(const Ch* name) const { return value_.EraseMember(name); } +#if RAPIDJSON_HAS_STDSTRING + bool EraseMember(const std::basic_string& name) const { return EraseMember(ValueType(StringRef(name))); } +#endif + template bool EraseMember(const GenericValue& name) const { return value_.EraseMember(name); } + +#if RAPIDJSON_HAS_CXX11_RANGE_FOR + MemberIterator begin() const { return value_.MemberBegin(); } + MemberIterator end() const { return value_.MemberEnd(); } +#endif + +private: + GenericObject(); + GenericObject(ValueType& value) : value_(value) {} + ValueType& value_; +}; + +RAPIDJSON_NAMESPACE_END +RAPIDJSON_DIAG_POP + +#endif // RAPIDJSON_DOCUMENT_H_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/encodedstream.h b/Externals/discord-rpc/thirdparty/include/rapidjson/encodedstream.h new file mode 100644 index 0000000000..145068386a --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/encodedstream.h @@ -0,0 +1,299 @@ +// 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_ENCODEDSTREAM_H_ +#define RAPIDJSON_ENCODEDSTREAM_H_ + +#include "stream.h" +#include "memorystream.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Input byte stream wrapper with a statically bound encoding. +/*! + \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE. + \tparam InputByteStream Type of input byte stream. For example, FileReadStream. +*/ +template +class EncodedInputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); +public: + typedef typename Encoding::Ch Ch; + + EncodedInputStream(InputByteStream& is) : is_(is) { + current_ = Encoding::TakeBOM(is_); + } + + Ch Peek() const { return current_; } + Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; } + size_t Tell() const { return is_.Tell(); } + + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + EncodedInputStream(const EncodedInputStream&); + EncodedInputStream& operator=(const EncodedInputStream&); + + InputByteStream& is_; + Ch current_; +}; + +//! Specialized for UTF8 MemoryStream. +template <> +class EncodedInputStream, MemoryStream> { +public: + typedef UTF8<>::Ch Ch; + + EncodedInputStream(MemoryStream& is) : is_(is) { + if (static_cast(is_.Peek()) == 0xEFu) is_.Take(); + if (static_cast(is_.Peek()) == 0xBBu) is_.Take(); + if (static_cast(is_.Peek()) == 0xBFu) is_.Take(); + } + Ch Peek() const { return is_.Peek(); } + Ch Take() { return is_.Take(); } + size_t Tell() const { return is_.Tell(); } + + // Not implemented + void Put(Ch) {} + void Flush() {} + Ch* PutBegin() { return 0; } + size_t PutEnd(Ch*) { return 0; } + + MemoryStream& is_; + +private: + EncodedInputStream(const EncodedInputStream&); + EncodedInputStream& operator=(const EncodedInputStream&); +}; + +//! Output byte stream wrapper with statically bound encoding. +/*! + \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE. + \tparam OutputByteStream Type of input byte stream. For example, FileWriteStream. +*/ +template +class EncodedOutputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); +public: + typedef typename Encoding::Ch Ch; + + EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) { + if (putBOM) + Encoding::PutBOM(os_); + } + + void Put(Ch c) { Encoding::Put(os_, c); } + void Flush() { os_.Flush(); } + + // Not implemented + Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;} + Ch Take() { RAPIDJSON_ASSERT(false); return 0;} + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + EncodedOutputStream(const EncodedOutputStream&); + EncodedOutputStream& operator=(const EncodedOutputStream&); + + OutputByteStream& os_; +}; + +#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8::x, UTF16LE::x, UTF16BE::x, UTF32LE::x, UTF32BE::x + +//! Input stream wrapper with dynamically bound encoding and automatic encoding detection. +/*! + \tparam CharType Type of character for reading. + \tparam InputByteStream type of input byte stream to be wrapped. +*/ +template +class AutoUTFInputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); +public: + typedef CharType Ch; + + //! Constructor. + /*! + \param is input stream to be wrapped. + \param type UTF encoding type if it is not detected from the stream. + */ + AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) { + RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE); + DetectType(); + static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) }; + takeFunc_ = f[type_]; + current_ = takeFunc_(*is_); + } + + UTFType GetType() const { return type_; } + bool HasBOM() const { return hasBOM_; } + + Ch Peek() const { return current_; } + Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; } + size_t Tell() const { return is_->Tell(); } + + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + AutoUTFInputStream(const AutoUTFInputStream&); + AutoUTFInputStream& operator=(const AutoUTFInputStream&); + + // Detect encoding type with BOM or RFC 4627 + void DetectType() { + // BOM (Byte Order Mark): + // 00 00 FE FF UTF-32BE + // FF FE 00 00 UTF-32LE + // FE FF UTF-16BE + // FF FE UTF-16LE + // EF BB BF UTF-8 + + const unsigned char* c = reinterpret_cast(is_->Peek4()); + if (!c) + return; + + unsigned bom = static_cast(c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24)); + hasBOM_ = false; + if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } + else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } + else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); } + else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); } + else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); } + + // RFC 4627: Section 3 + // "Since the first two characters of a JSON text will always be ASCII + // characters [RFC0020], it is possible to determine whether an octet + // stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking + // at the pattern of nulls in the first four octets." + // 00 00 00 xx UTF-32BE + // 00 xx 00 xx UTF-16BE + // xx 00 00 00 UTF-32LE + // xx 00 xx 00 UTF-16LE + // xx xx xx xx UTF-8 + + if (!hasBOM_) { + unsigned pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0); + switch (pattern) { + case 0x08: type_ = kUTF32BE; break; + case 0x0A: type_ = kUTF16BE; break; + case 0x01: type_ = kUTF32LE; break; + case 0x05: type_ = kUTF16LE; break; + case 0x0F: type_ = kUTF8; break; + default: break; // Use type defined by user. + } + } + + // Runtime check whether the size of character type is sufficient. It only perform checks with assertion. + if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2); + if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4); + } + + typedef Ch (*TakeFunc)(InputByteStream& is); + InputByteStream* is_; + UTFType type_; + Ch current_; + TakeFunc takeFunc_; + bool hasBOM_; +}; + +//! Output stream wrapper with dynamically bound encoding and automatic encoding detection. +/*! + \tparam CharType Type of character for writing. + \tparam OutputByteStream type of output byte stream to be wrapped. +*/ +template +class AutoUTFOutputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); +public: + typedef CharType Ch; + + //! Constructor. + /*! + \param os output stream to be wrapped. + \param type UTF encoding type. + \param putBOM Whether to write BOM at the beginning of the stream. + */ + AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) { + RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE); + + // Runtime check whether the size of character type is sufficient. It only perform checks with assertion. + if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2); + if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4); + + static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) }; + putFunc_ = f[type_]; + + if (putBOM) + PutBOM(); + } + + UTFType GetType() const { return type_; } + + void Put(Ch c) { putFunc_(*os_, c); } + void Flush() { os_->Flush(); } + + // Not implemented + Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;} + Ch Take() { RAPIDJSON_ASSERT(false); return 0;} + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + AutoUTFOutputStream(const AutoUTFOutputStream&); + AutoUTFOutputStream& operator=(const AutoUTFOutputStream&); + + void PutBOM() { + typedef void (*PutBOMFunc)(OutputByteStream&); + static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) }; + f[type_](*os_); + } + + typedef void (*PutFunc)(OutputByteStream&, Ch); + + OutputByteStream* os_; + UTFType type_; + PutFunc putFunc_; +}; + +#undef RAPIDJSON_ENCODINGS_FUNC + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_FILESTREAM_H_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/encodings.h b/Externals/discord-rpc/thirdparty/include/rapidjson/encodings.h new file mode 100644 index 0000000000..baa7c2b17f --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/encodings.h @@ -0,0 +1,716 @@ +// 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_ENCODINGS_H_ +#define RAPIDJSON_ENCODINGS_H_ + +#include "rapidjson.h" + +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data +RAPIDJSON_DIAG_OFF(4702) // unreachable code +#elif defined(__GNUC__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +RAPIDJSON_DIAG_OFF(overflow) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Encoding + +/*! \class rapidjson::Encoding + \brief Concept for encoding of Unicode characters. + +\code +concept Encoding { + typename Ch; //! Type of character. A "character" is actually a code unit in unicode's definition. + + enum { supportUnicode = 1 }; // or 0 if not supporting unicode + + //! \brief Encode a Unicode codepoint to an output stream. + //! \param os Output stream. + //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively. + template + static void Encode(OutputStream& os, unsigned codepoint); + + //! \brief Decode a Unicode codepoint from an input stream. + //! \param is Input stream. + //! \param codepoint Output of the unicode codepoint. + //! \return true if a valid codepoint can be decoded from the stream. + template + static bool Decode(InputStream& is, unsigned* codepoint); + + //! \brief Validate one Unicode codepoint from an encoded stream. + //! \param is Input stream to obtain codepoint. + //! \param os Output for copying one codepoint. + //! \return true if it is valid. + //! \note This function just validating and copying the codepoint without actually decode it. + template + static bool Validate(InputStream& is, OutputStream& os); + + // The following functions are deal with byte streams. + + //! Take a character from input byte stream, skip BOM if exist. + template + static CharType TakeBOM(InputByteStream& is); + + //! Take a character from input byte stream. + template + static Ch Take(InputByteStream& is); + + //! Put BOM to output byte stream. + template + static void PutBOM(OutputByteStream& os); + + //! Put a character to output byte stream. + template + static void Put(OutputByteStream& os, Ch c); +}; +\endcode +*/ + +/////////////////////////////////////////////////////////////////////////////// +// UTF8 + +//! UTF-8 encoding. +/*! http://en.wikipedia.org/wiki/UTF-8 + http://tools.ietf.org/html/rfc3629 + \tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char. + \note implements Encoding concept +*/ +template +struct UTF8 { + typedef CharType Ch; + + enum { supportUnicode = 1 }; + + template + static void Encode(OutputStream& os, unsigned codepoint) { + if (codepoint <= 0x7F) + os.Put(static_cast(codepoint & 0xFF)); + else if (codepoint <= 0x7FF) { + os.Put(static_cast(0xC0 | ((codepoint >> 6) & 0xFF))); + os.Put(static_cast(0x80 | ((codepoint & 0x3F)))); + } + else if (codepoint <= 0xFFFF) { + os.Put(static_cast(0xE0 | ((codepoint >> 12) & 0xFF))); + os.Put(static_cast(0x80 | ((codepoint >> 6) & 0x3F))); + os.Put(static_cast(0x80 | (codepoint & 0x3F))); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + os.Put(static_cast(0xF0 | ((codepoint >> 18) & 0xFF))); + os.Put(static_cast(0x80 | ((codepoint >> 12) & 0x3F))); + os.Put(static_cast(0x80 | ((codepoint >> 6) & 0x3F))); + os.Put(static_cast(0x80 | (codepoint & 0x3F))); + } + } + + template + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + if (codepoint <= 0x7F) + PutUnsafe(os, static_cast(codepoint & 0xFF)); + else if (codepoint <= 0x7FF) { + PutUnsafe(os, static_cast(0xC0 | ((codepoint >> 6) & 0xFF))); + PutUnsafe(os, static_cast(0x80 | ((codepoint & 0x3F)))); + } + else if (codepoint <= 0xFFFF) { + PutUnsafe(os, static_cast(0xE0 | ((codepoint >> 12) & 0xFF))); + PutUnsafe(os, static_cast(0x80 | ((codepoint >> 6) & 0x3F))); + PutUnsafe(os, static_cast(0x80 | (codepoint & 0x3F))); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + PutUnsafe(os, static_cast(0xF0 | ((codepoint >> 18) & 0xFF))); + PutUnsafe(os, static_cast(0x80 | ((codepoint >> 12) & 0x3F))); + PutUnsafe(os, static_cast(0x80 | ((codepoint >> 6) & 0x3F))); + PutUnsafe(os, static_cast(0x80 | (codepoint & 0x3F))); + } + } + + template + static bool Decode(InputStream& is, unsigned* codepoint) { +#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast(c) & 0x3Fu) +#define TRANS(mask) result &= ((GetRange(static_cast(c)) & mask) != 0) +#define TAIL() COPY(); TRANS(0x70) + typename InputStream::Ch c = is.Take(); + if (!(c & 0x80)) { + *codepoint = static_cast(c); + return true; + } + + unsigned char type = GetRange(static_cast(c)); + if (type >= 32) { + *codepoint = 0; + } else { + *codepoint = (0xFF >> type) & static_cast(c); + } + bool result = true; + switch (type) { + case 2: TAIL(); return result; + case 3: TAIL(); TAIL(); return result; + case 4: COPY(); TRANS(0x50); TAIL(); return result; + case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result; + case 6: TAIL(); TAIL(); TAIL(); return result; + case 10: COPY(); TRANS(0x20); TAIL(); return result; + case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result; + default: return false; + } +#undef COPY +#undef TRANS +#undef TAIL + } + + template + static bool Validate(InputStream& is, OutputStream& os) { +#define COPY() os.Put(c = is.Take()) +#define TRANS(mask) result &= ((GetRange(static_cast(c)) & mask) != 0) +#define TAIL() COPY(); TRANS(0x70) + Ch c; + COPY(); + if (!(c & 0x80)) + return true; + + bool result = true; + switch (GetRange(static_cast(c))) { + case 2: TAIL(); return result; + case 3: TAIL(); TAIL(); return result; + case 4: COPY(); TRANS(0x50); TAIL(); return result; + case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result; + case 6: TAIL(); TAIL(); TAIL(); return result; + case 10: COPY(); TRANS(0x20); TAIL(); return result; + case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result; + default: return false; + } +#undef COPY +#undef TRANS +#undef TAIL + } + + static unsigned char GetRange(unsigned char c) { + // Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ + // With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types. + static const unsigned char type[] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, + }; + return type[c]; + } + + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + typename InputByteStream::Ch c = Take(is); + if (static_cast(c) != 0xEFu) return c; + c = is.Take(); + if (static_cast(c) != 0xBBu) return c; + c = is.Take(); + if (static_cast(c) != 0xBFu) return c; + c = is.Take(); + return c; + } + + template + static Ch Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + return static_cast(is.Take()); + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(0xEFu)); + os.Put(static_cast(0xBBu)); + os.Put(static_cast(0xBFu)); + } + + template + static void Put(OutputByteStream& os, Ch c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(c)); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// UTF16 + +//! UTF-16 encoding. +/*! http://en.wikipedia.org/wiki/UTF-16 + http://tools.ietf.org/html/rfc2781 + \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead. + \note implements Encoding concept + + \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness. + For streaming, use UTF16LE and UTF16BE, which handle endianness. +*/ +template +struct UTF16 { + typedef CharType Ch; + RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2); + + enum { supportUnicode = 1 }; + + template + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); + if (codepoint <= 0xFFFF) { + RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair + os.Put(static_cast(codepoint)); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + unsigned v = codepoint - 0x10000; + os.Put(static_cast((v >> 10) | 0xD800)); + os.Put((v & 0x3FF) | 0xDC00); + } + } + + + template + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); + if (codepoint <= 0xFFFF) { + RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair + PutUnsafe(os, static_cast(codepoint)); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + unsigned v = codepoint - 0x10000; + PutUnsafe(os, static_cast((v >> 10) | 0xD800)); + PutUnsafe(os, (v & 0x3FF) | 0xDC00); + } + } + + template + static bool Decode(InputStream& is, unsigned* codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2); + typename InputStream::Ch c = is.Take(); + if (c < 0xD800 || c > 0xDFFF) { + *codepoint = static_cast(c); + return true; + } + else if (c <= 0xDBFF) { + *codepoint = (static_cast(c) & 0x3FF) << 10; + c = is.Take(); + *codepoint |= (static_cast(c) & 0x3FF); + *codepoint += 0x10000; + return c >= 0xDC00 && c <= 0xDFFF; + } + return false; + } + + template + static bool Validate(InputStream& is, OutputStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2); + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); + typename InputStream::Ch c; + os.Put(static_cast(c = is.Take())); + if (c < 0xD800 || c > 0xDFFF) + return true; + else if (c <= 0xDBFF) { + os.Put(c = is.Take()); + return c >= 0xDC00 && c <= 0xDFFF; + } + return false; + } +}; + +//! UTF-16 little endian encoding. +template +struct UTF16LE : UTF16 { + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast(c) == 0xFEFFu ? Take(is) : c; + } + + template + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast(is.Take()); + c |= static_cast(static_cast(is.Take())) << 8; + return static_cast(c); + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(0xFFu)); + os.Put(static_cast(0xFEu)); + } + + template + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(static_cast(c) & 0xFFu)); + os.Put(static_cast((static_cast(c) >> 8) & 0xFFu)); + } +}; + +//! UTF-16 big endian encoding. +template +struct UTF16BE : UTF16 { + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast(c) == 0xFEFFu ? Take(is) : c; + } + + template + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast(static_cast(is.Take())) << 8; + c |= static_cast(is.Take()); + return static_cast(c); + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(0xFEu)); + os.Put(static_cast(0xFFu)); + } + + template + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast((static_cast(c) >> 8) & 0xFFu)); + os.Put(static_cast(static_cast(c) & 0xFFu)); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// UTF32 + +//! UTF-32 encoding. +/*! http://en.wikipedia.org/wiki/UTF-32 + \tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead. + \note implements Encoding concept + + \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness. + For streaming, use UTF32LE and UTF32BE, which handle endianness. +*/ +template +struct UTF32 { + typedef CharType Ch; + RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4); + + enum { supportUnicode = 1 }; + + template + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + os.Put(codepoint); + } + + template + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + PutUnsafe(os, codepoint); + } + + template + static bool Decode(InputStream& is, unsigned* codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4); + Ch c = is.Take(); + *codepoint = c; + return c <= 0x10FFFF; + } + + template + static bool Validate(InputStream& is, OutputStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4); + Ch c; + os.Put(c = is.Take()); + return c <= 0x10FFFF; + } +}; + +//! UTF-32 little endian enocoding. +template +struct UTF32LE : UTF32 { + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast(c) == 0x0000FEFFu ? Take(is) : c; + } + + template + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast(is.Take()); + c |= static_cast(static_cast(is.Take())) << 8; + c |= static_cast(static_cast(is.Take())) << 16; + c |= static_cast(static_cast(is.Take())) << 24; + return static_cast(c); + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(0xFFu)); + os.Put(static_cast(0xFEu)); + os.Put(static_cast(0x00u)); + os.Put(static_cast(0x00u)); + } + + template + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(c & 0xFFu)); + os.Put(static_cast((c >> 8) & 0xFFu)); + os.Put(static_cast((c >> 16) & 0xFFu)); + os.Put(static_cast((c >> 24) & 0xFFu)); + } +}; + +//! UTF-32 big endian encoding. +template +struct UTF32BE : UTF32 { + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast(c) == 0x0000FEFFu ? Take(is) : c; + } + + template + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast(static_cast(is.Take())) << 24; + c |= static_cast(static_cast(is.Take())) << 16; + c |= static_cast(static_cast(is.Take())) << 8; + c |= static_cast(static_cast(is.Take())); + return static_cast(c); + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(0x00u)); + os.Put(static_cast(0x00u)); + os.Put(static_cast(0xFEu)); + os.Put(static_cast(0xFFu)); + } + + template + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast((c >> 24) & 0xFFu)); + os.Put(static_cast((c >> 16) & 0xFFu)); + os.Put(static_cast((c >> 8) & 0xFFu)); + os.Put(static_cast(c & 0xFFu)); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// ASCII + +//! ASCII encoding. +/*! http://en.wikipedia.org/wiki/ASCII + \tparam CharType Code unit for storing 7-bit ASCII data. Default is char. + \note implements Encoding concept +*/ +template +struct ASCII { + typedef CharType Ch; + + enum { supportUnicode = 0 }; + + template + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_ASSERT(codepoint <= 0x7F); + os.Put(static_cast(codepoint & 0xFF)); + } + + template + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + RAPIDJSON_ASSERT(codepoint <= 0x7F); + PutUnsafe(os, static_cast(codepoint & 0xFF)); + } + + template + static bool Decode(InputStream& is, unsigned* codepoint) { + uint8_t c = static_cast(is.Take()); + *codepoint = c; + return c <= 0X7F; + } + + template + static bool Validate(InputStream& is, OutputStream& os) { + uint8_t c = static_cast(is.Take()); + os.Put(static_cast(c)); + return c <= 0x7F; + } + + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + uint8_t c = static_cast(Take(is)); + return static_cast(c); + } + + template + static Ch Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + return static_cast(is.Take()); + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + (void)os; + } + + template + static void Put(OutputByteStream& os, Ch c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(c)); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// AutoUTF + +//! Runtime-specified UTF encoding type of a stream. +enum UTFType { + kUTF8 = 0, //!< UTF-8. + kUTF16LE = 1, //!< UTF-16 little endian. + kUTF16BE = 2, //!< UTF-16 big endian. + kUTF32LE = 3, //!< UTF-32 little endian. + kUTF32BE = 4 //!< UTF-32 big endian. +}; + +//! Dynamically select encoding according to stream's runtime-specified UTF encoding type. +/*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType(). +*/ +template +struct AutoUTF { + typedef CharType Ch; + + enum { supportUnicode = 1 }; + +#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8::x, UTF16LE::x, UTF16BE::x, UTF32LE::x, UTF32BE::x + + template + RAPIDJSON_FORCEINLINE static 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 + RAPIDJSON_FORCEINLINE static 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 + RAPIDJSON_FORCEINLINE static 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 + RAPIDJSON_FORCEINLINE static 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); + } + +#undef RAPIDJSON_ENCODINGS_FUNC +}; + +/////////////////////////////////////////////////////////////////////////////// +// Transcoder + +//! Encoding conversion. +template +struct Transcoder { + //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream. + template + RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) { + unsigned codepoint; + if (!SourceEncoding::Decode(is, &codepoint)) + return false; + TargetEncoding::Encode(os, codepoint); + return true; + } + + template + RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) { + unsigned codepoint; + if (!SourceEncoding::Decode(is, &codepoint)) + return false; + TargetEncoding::EncodeUnsafe(os, codepoint); + return true; + } + + //! Validate one Unicode codepoint from an encoded stream. + template + RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { + return Transcode(is, os); // Since source/target encoding is different, must transcode. + } +}; + +// Forward declaration. +template +inline void PutUnsafe(Stream& stream, typename Stream::Ch c); + +//! Specialization of Transcoder with same source and target encoding. +template +struct Transcoder { + template + RAPIDJSON_FORCEINLINE static 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 + RAPIDJSON_FORCEINLINE static 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 + RAPIDJSON_FORCEINLINE static 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) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_ENCODINGS_H_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/error/en.h b/Externals/discord-rpc/thirdparty/include/rapidjson/error/en.h new file mode 100644 index 0000000000..2db838bff2 --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/error/en.h @@ -0,0 +1,74 @@ +// 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_ERROR_EN_H_ +#define RAPIDJSON_ERROR_EN_H_ + +#include "error.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(switch-enum) +RAPIDJSON_DIAG_OFF(covered-switch-default) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Maps error code of parsing into error message. +/*! + \ingroup RAPIDJSON_ERRORS + \param parseErrorCode Error code obtained in parsing. + \return the error message. + \note User can make a copy of this function for localization. + Using switch-case is safer for future modification of error codes. +*/ +inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) { + switch (parseErrorCode) { + case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error."); + + case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty."); + case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values."); + + case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value."); + + case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member."); + case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member."); + case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member."); + + case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element."); + + case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string."); + case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid."); + case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string."); + case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string."); + case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string."); + + case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double."); + case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number."); + case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number."); + + case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error."); + case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error."); + + default: return RAPIDJSON_ERROR_STRING("Unknown error."); + } +} + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_ERROR_EN_H_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/error/error.h b/Externals/discord-rpc/thirdparty/include/rapidjson/error/error.h new file mode 100644 index 0000000000..95cb31a72f --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/error/error.h @@ -0,0 +1,155 @@ +// 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_ERROR_ERROR_H_ +#define RAPIDJSON_ERROR_ERROR_H_ + +#include "../rapidjson.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + +/*! \file error.h */ + +/*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */ + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ERROR_CHARTYPE + +//! Character type of error messages. +/*! \ingroup RAPIDJSON_ERRORS + The default character type is \c char. + On Windows, user can define this macro as \c TCHAR for supporting both + unicode/non-unicode settings. +*/ +#ifndef RAPIDJSON_ERROR_CHARTYPE +#define RAPIDJSON_ERROR_CHARTYPE char +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ERROR_STRING + +//! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[]. +/*! \ingroup RAPIDJSON_ERRORS + By default this conversion macro does nothing. + On Windows, user can define this macro as \c _T(x) for supporting both + unicode/non-unicode settings. +*/ +#ifndef RAPIDJSON_ERROR_STRING +#define RAPIDJSON_ERROR_STRING(x) x +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// ParseErrorCode + +//! Error code of parsing. +/*! \ingroup RAPIDJSON_ERRORS + \see GenericReader::Parse, GenericReader::GetParseErrorCode +*/ +enum ParseErrorCode { + kParseErrorNone = 0, //!< No error. + + kParseErrorDocumentEmpty, //!< The document is empty. + kParseErrorDocumentRootNotSingular, //!< The document root must not follow by other values. + + kParseErrorValueInvalid, //!< Invalid value. + + kParseErrorObjectMissName, //!< Missing a name for object member. + kParseErrorObjectMissColon, //!< Missing a colon after a name of object member. + kParseErrorObjectMissCommaOrCurlyBracket, //!< Missing a comma or '}' after an object member. + + kParseErrorArrayMissCommaOrSquareBracket, //!< Missing a comma or ']' after an array element. + + kParseErrorStringUnicodeEscapeInvalidHex, //!< Incorrect hex digit after \\u escape in string. + kParseErrorStringUnicodeSurrogateInvalid, //!< The surrogate pair in string is invalid. + kParseErrorStringEscapeInvalid, //!< Invalid escape character in string. + kParseErrorStringMissQuotationMark, //!< Missing a closing quotation mark in string. + kParseErrorStringInvalidEncoding, //!< Invalid encoding in string. + + kParseErrorNumberTooBig, //!< Number too big to be stored in double. + kParseErrorNumberMissFraction, //!< Miss fraction part in number. + kParseErrorNumberMissExponent, //!< Miss exponent in number. + + kParseErrorTermination, //!< Parsing was terminated. + kParseErrorUnspecificSyntaxError //!< Unspecific syntax error. +}; + +//! Result of parsing (wraps ParseErrorCode) +/*! + \ingroup RAPIDJSON_ERRORS + \code + Document doc; + ParseResult ok = doc.Parse("[42]"); + if (!ok) { + fprintf(stderr, "JSON parse error: %s (%u)", + GetParseError_En(ok.Code()), ok.Offset()); + exit(EXIT_FAILURE); + } + \endcode + \see GenericReader::Parse, GenericDocument::Parse +*/ +struct ParseResult { +public: + //! Default constructor, no error. + ParseResult() : code_(kParseErrorNone), offset_(0) {} + //! Constructor to set an error. + ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {} + + //! Get the error code. + ParseErrorCode Code() const { return code_; } + //! 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(); } + //! Whether the result is an error. + bool IsError() const { return code_ != kParseErrorNone; } + + bool operator==(const ParseResult& that) const { return code_ == that.code_; } + bool operator==(ParseErrorCode code) const { return code_ == code; } + friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; } + + //! Reset error code. + void Clear() { Set(kParseErrorNone); } + //! Update error code and offset. + void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; } + +private: + ParseErrorCode code_; + size_t offset_; +}; + +//! Function pointer type of GetParseError(). +/*! \ingroup RAPIDJSON_ERRORS + + This is the prototype for \c GetParseError_X(), where \c X is a locale. + User can dynamically change locale in runtime, e.g.: +\code + GetParseErrorFunc GetParseError = GetParseError_En; // or whatever + const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode()); +\endcode +*/ +typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode); + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_ERROR_ERROR_H_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/filereadstream.h b/Externals/discord-rpc/thirdparty/include/rapidjson/filereadstream.h new file mode 100644 index 0000000000..b56ea13b34 --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/filereadstream.h @@ -0,0 +1,99 @@ +// 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_FILEREADSTREAM_H_ +#define RAPIDJSON_FILEREADSTREAM_H_ + +#include "stream.h" +#include + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(unreachable-code) +RAPIDJSON_DIAG_OFF(missing-noreturn) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! File byte stream for input using fread(). +/*! + \note implements Stream concept +*/ +class FileReadStream { +public: + typedef char Ch; //!< Character type (byte). + + //! Constructor. + /*! + \param fp File pointer opened for read. + \param buffer user-supplied buffer. + \param bufferSize size of buffer in bytes. Must >=4 bytes. + */ + FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { + RAPIDJSON_ASSERT(fp_ != 0); + RAPIDJSON_ASSERT(bufferSize >= 4); + Read(); + } + + Ch Peek() const { return *current_; } + Ch Take() { Ch c = *current_; Read(); return c; } + size_t Tell() const { return count_ + static_cast(current_ - buffer_); } + + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + // For encoding detection only. + const Ch* Peek4() const { + return (current_ + 4 <= bufferLast_) ? current_ : 0; + } + +private: + void Read() { + if (current_ < bufferLast_) + ++current_; + else if (!eof_) { + count_ += readCount_; + readCount_ = fread(buffer_, 1, bufferSize_, fp_); + bufferLast_ = buffer_ + readCount_ - 1; + current_ = buffer_; + + if (readCount_ < bufferSize_) { + buffer_[readCount_] = '\0'; + ++bufferLast_; + eof_ = true; + } + } + } + + std::FILE* fp_; + Ch *buffer_; + size_t bufferSize_; + Ch *bufferLast_; + Ch *current_; + size_t readCount_; + size_t count_; //!< Number of characters read + bool eof_; +}; + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_FILESTREAM_H_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/filewritestream.h b/Externals/discord-rpc/thirdparty/include/rapidjson/filewritestream.h new file mode 100644 index 0000000000..6378dd60ed --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/filewritestream.h @@ -0,0 +1,104 @@ +// 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_FILEWRITESTREAM_H_ +#define RAPIDJSON_FILEWRITESTREAM_H_ + +#include "stream.h" +#include + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(unreachable-code) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Wrapper of C file stream for input using fread(). +/*! + \note implements Stream concept +*/ +class FileWriteStream { +public: + typedef char Ch; //!< Character type. Only support char. + + FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) { + RAPIDJSON_ASSERT(fp_ != 0); + } + + void Put(char c) { + if (current_ >= bufferEnd_) + Flush(); + + *current_++ = c; + } + + void PutN(char c, size_t n) { + size_t avail = static_cast(bufferEnd_ - current_); + while (n > avail) { + std::memset(current_, c, avail); + current_ += avail; + Flush(); + n -= avail; + avail = static_cast(bufferEnd_ - current_); + } + + if (n > 0) { + std::memset(current_, c, n); + current_ += n; + } + } + + void Flush() { + if (current_ != buffer_) { + size_t result = fwrite(buffer_, 1, static_cast(current_ - buffer_), fp_); + if (result < static_cast(current_ - buffer_)) { + // failure deliberately ignored at this time + // added to avoid warn_unused_result build errors + } + current_ = buffer_; + } + } + + // Not implemented + char Peek() const { RAPIDJSON_ASSERT(false); return 0; } + char Take() { RAPIDJSON_ASSERT(false); return 0; } + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + // Prohibit copy constructor & assignment operator. + FileWriteStream(const FileWriteStream&); + FileWriteStream& operator=(const FileWriteStream&); + + std::FILE* fp_; + char *buffer_; + char *bufferEnd_; + char *current_; +}; + +//! Implement specialized version of PutN() with memset() for better performance. +template<> +inline void PutN(FileWriteStream& stream, char c, size_t n) { + stream.PutN(c, n); +} + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_FILESTREAM_H_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/fwd.h b/Externals/discord-rpc/thirdparty/include/rapidjson/fwd.h new file mode 100644 index 0000000000..e8104e841b --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/fwd.h @@ -0,0 +1,151 @@ +// 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_FWD_H_ +#define RAPIDJSON_FWD_H_ + +#include "rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN + +// encodings.h + +template struct UTF8; +template struct UTF16; +template struct UTF16BE; +template struct UTF16LE; +template struct UTF32; +template struct UTF32BE; +template struct UTF32LE; +template struct ASCII; +template struct AutoUTF; + +template +struct Transcoder; + +// allocators.h + +class CrtAllocator; + +template +class MemoryPoolAllocator; + +// stream.h + +template +struct GenericStringStream; + +typedef GenericStringStream > StringStream; + +template +struct GenericInsituStringStream; + +typedef GenericInsituStringStream > InsituStringStream; + +// stringbuffer.h + +template +class GenericStringBuffer; + +typedef GenericStringBuffer, CrtAllocator> StringBuffer; + +// filereadstream.h + +class FileReadStream; + +// filewritestream.h + +class FileWriteStream; + +// memorybuffer.h + +template +struct GenericMemoryBuffer; + +typedef GenericMemoryBuffer MemoryBuffer; + +// memorystream.h + +struct MemoryStream; + +// reader.h + +template +struct BaseReaderHandler; + +template +class GenericReader; + +typedef GenericReader, UTF8, CrtAllocator> Reader; + +// writer.h + +template +class Writer; + +// prettywriter.h + +template +class PrettyWriter; + +// document.h + +template +struct GenericMember; + +template +class GenericMemberIterator; + +template +struct GenericStringRef; + +template +class GenericValue; + +typedef GenericValue, MemoryPoolAllocator > Value; + +template +class GenericDocument; + +typedef GenericDocument, MemoryPoolAllocator, CrtAllocator> Document; + +// pointer.h + +template +class GenericPointer; + +typedef GenericPointer Pointer; + +// schema.h + +template +class IGenericRemoteSchemaDocumentProvider; + +template +class GenericSchemaDocument; + +typedef GenericSchemaDocument SchemaDocument; +typedef IGenericRemoteSchemaDocumentProvider IRemoteSchemaDocumentProvider; + +template < + typename SchemaDocumentType, + typename OutputHandler, + typename StateAllocator> +class GenericSchemaValidator; + +typedef GenericSchemaValidator, void>, CrtAllocator> SchemaValidator; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_RAPIDJSONFWD_H_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/internal/biginteger.h b/Externals/discord-rpc/thirdparty/include/rapidjson/internal/biginteger.h new file mode 100644 index 0000000000..9d3e88c998 --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/internal/biginteger.h @@ -0,0 +1,290 @@ +// 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_BIGINTEGER_H_ +#define RAPIDJSON_BIGINTEGER_H_ + +#include "../rapidjson.h" + +#if defined(_MSC_VER) && defined(_M_AMD64) +#include // for _umul128 +#pragma intrinsic(_umul128) +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +class BigInteger { +public: + typedef uint64_t Type; + + BigInteger(const BigInteger& rhs) : count_(rhs.count_) { + std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type)); + } + + explicit BigInteger(uint64_t u) : count_(1) { + digits_[0] = u; + } + + BigInteger(const char* decimals, size_t length) : count_(1) { + RAPIDJSON_ASSERT(length > 0); + digits_[0] = 0; + size_t i = 0; + const size_t kMaxDigitPerIteration = 19; // 2^64 = 18446744073709551616 > 10^19 + while (length >= kMaxDigitPerIteration) { + AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration); + length -= kMaxDigitPerIteration; + i += kMaxDigitPerIteration; + } + + if (length > 0) + AppendDecimal64(decimals + i, decimals + i + length); + } + + BigInteger& operator=(const BigInteger &rhs) + { + if (this != &rhs) { + count_ = rhs.count_; + std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type)); + } + return *this; + } + + BigInteger& operator=(uint64_t u) { + digits_[0] = u; + count_ = 1; + return *this; + } + + BigInteger& operator+=(uint64_t u) { + Type backup = digits_[0]; + digits_[0] += u; + for (size_t i = 0; i < count_ - 1; i++) { + if (digits_[i] >= backup) + return *this; // no carry + backup = digits_[i + 1]; + digits_[i + 1] += 1; + } + + // Last carry + if (digits_[count_ - 1] < backup) + PushBack(1); + + return *this; + } + + BigInteger& operator*=(uint64_t u) { + if (u == 0) return *this = 0; + if (u == 1) return *this; + if (*this == 1) return *this = u; + + uint64_t k = 0; + for (size_t i = 0; i < count_; i++) { + uint64_t hi; + digits_[i] = MulAdd64(digits_[i], u, k, &hi); + k = hi; + } + + if (k > 0) + PushBack(k); + + return *this; + } + + BigInteger& operator*=(uint32_t u) { + if (u == 0) return *this = 0; + if (u == 1) return *this; + if (*this == 1) return *this = u; + + uint64_t k = 0; + for (size_t i = 0; i < count_; i++) { + const uint64_t c = digits_[i] >> 32; + const uint64_t d = digits_[i] & 0xFFFFFFFF; + const uint64_t uc = u * c; + const uint64_t ud = u * d; + const uint64_t p0 = ud + k; + const uint64_t p1 = uc + (p0 >> 32); + digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32); + k = p1 >> 32; + } + + if (k > 0) + PushBack(k); + + return *this; + } + + BigInteger& operator<<=(size_t shift) { + if (IsZero() || shift == 0) return *this; + + size_t offset = shift / kTypeBit; + size_t interShift = shift % kTypeBit; + RAPIDJSON_ASSERT(count_ + offset <= kCapacity); + + if (interShift == 0) { + std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type)); + count_ += offset; + } + else { + digits_[count_] = 0; + for (size_t i = count_; i > 0; i--) + digits_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift)); + digits_[offset] = digits_[0] << interShift; + count_ += offset; + if (digits_[count_]) + count_++; + } + + std::memset(digits_, 0, offset * sizeof(Type)); + + return *this; + } + + bool operator==(const BigInteger& rhs) const { + return count_ == rhs.count_ && std::memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0; + } + + bool operator==(const Type rhs) const { + return count_ == 1 && digits_[0] == rhs; + } + + BigInteger& MultiplyPow5(unsigned exp) { + static const uint32_t kPow5[12] = { + 5, + 5 * 5, + 5 * 5 * 5, + 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 + }; + if (exp == 0) return *this; + for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27 + for (; exp >= 13; exp -= 13) *this *= static_cast(1220703125u); // 5^13 + if (exp > 0) *this *= kPow5[exp - 1]; + return *this; + } + + // Compute absolute difference of this and rhs. + // Assume this != rhs + bool Difference(const BigInteger& rhs, BigInteger* out) const { + int cmp = Compare(rhs); + RAPIDJSON_ASSERT(cmp != 0); + const BigInteger *a, *b; // Makes a > b + bool ret; + if (cmp < 0) { a = &rhs; b = this; ret = true; } + else { a = this; b = &rhs; ret = false; } + + Type borrow = 0; + for (size_t i = 0; i < a->count_; i++) { + Type d = a->digits_[i] - borrow; + if (i < b->count_) + d -= b->digits_[i]; + borrow = (d > a->digits_[i]) ? 1 : 0; + out->digits_[i] = d; + if (d != 0) + out->count_ = i + 1; + } + + return ret; + } + + int Compare(const BigInteger& rhs) const { + if (count_ != rhs.count_) + return count_ < rhs.count_ ? -1 : 1; + + for (size_t i = count_; i-- > 0;) + if (digits_[i] != rhs.digits_[i]) + return digits_[i] < rhs.digits_[i] ? -1 : 1; + + return 0; + } + + size_t GetCount() const { return count_; } + Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; } + bool IsZero() const { return count_ == 1 && digits_[0] == 0; } + +private: + void AppendDecimal64(const char* begin, const char* end) { + uint64_t u = ParseUint64(begin, end); + if (IsZero()) + *this = u; + else { + unsigned exp = static_cast(end - begin); + (MultiplyPow5(exp) <<= exp) += u; // *this = *this * 10^exp + u + } + } + + void PushBack(Type digit) { + RAPIDJSON_ASSERT(count_ < kCapacity); + digits_[count_++] = digit; + } + + static uint64_t ParseUint64(const char* begin, const char* end) { + uint64_t r = 0; + for (const char* p = begin; p != end; ++p) { + RAPIDJSON_ASSERT(*p >= '0' && *p <= '9'); + r = r * 10u + static_cast(*p - '0'); + } + return r; + } + + // Assume a * b + k < 2^128 + static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh) { +#if defined(_MSC_VER) && defined(_M_AMD64) + uint64_t low = _umul128(a, b, outHigh) + k; + if (low < k) + (*outHigh)++; + return low; +#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) + __extension__ typedef unsigned __int128 uint128; + uint128 p = static_cast(a) * static_cast(b); + p += k; + *outHigh = static_cast(p >> 64); + return static_cast(p); +#else + const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF, b1 = b >> 32; + uint64_t x0 = a0 * b0, x1 = a0 * b1, x2 = a1 * b0, x3 = a1 * b1; + x1 += (x0 >> 32); // can't give carry + x1 += x2; + if (x1 < x2) + x3 += (static_cast(1) << 32); + uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF); + uint64_t hi = x3 + (x1 >> 32); + + lo += k; + if (lo < k) + hi++; + *outHigh = hi; + return lo; +#endif + } + + static const size_t kBitCount = 3328; // 64bit * 54 > 10^1000 + static const size_t kCapacity = kBitCount / sizeof(Type); + static const size_t kTypeBit = sizeof(Type) * 8; + + Type digits_[kCapacity]; + size_t count_; +}; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_BIGINTEGER_H_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/internal/diyfp.h b/Externals/discord-rpc/thirdparty/include/rapidjson/internal/diyfp.h new file mode 100644 index 0000000000..c9fefdc613 --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/internal/diyfp.h @@ -0,0 +1,258 @@ +// 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. + +// This is a C++ header-only implementation of Grisu2 algorithm from the publication: +// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with +// integers." ACM Sigplan Notices 45.6 (2010): 233-243. + +#ifndef RAPIDJSON_DIYFP_H_ +#define RAPIDJSON_DIYFP_H_ + +#include "../rapidjson.h" + +#if defined(_MSC_VER) && defined(_M_AMD64) +#include +#pragma intrinsic(_BitScanReverse64) +#pragma intrinsic(_umul128) +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + +struct DiyFp { + DiyFp() : f(), e() {} + + DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {} + + explicit DiyFp(double d) { + union { + double d; + uint64_t u64; + } u = { d }; + + int biased_e = static_cast((u.u64 & kDpExponentMask) >> kDpSignificandSize); + uint64_t significand = (u.u64 & kDpSignificandMask); + if (biased_e != 0) { + f = significand + kDpHiddenBit; + e = biased_e - kDpExponentBias; + } + else { + f = significand; + e = kDpMinExponent + 1; + } + } + + DiyFp operator-(const DiyFp& rhs) const { + return DiyFp(f - rhs.f, e); + } + + DiyFp operator*(const DiyFp& rhs) const { +#if defined(_MSC_VER) && defined(_M_AMD64) + uint64_t h; + uint64_t l = _umul128(f, rhs.f, &h); + if (l & (uint64_t(1) << 63)) // rounding + h++; + return DiyFp(h, e + rhs.e + 64); +#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) + __extension__ typedef unsigned __int128 uint128; + uint128 p = static_cast(f) * static_cast(rhs.f); + uint64_t h = static_cast(p >> 64); + uint64_t l = static_cast(p); + if (l & (uint64_t(1) << 63)) // rounding + h++; + return DiyFp(h, e + rhs.e + 64); +#else + const uint64_t M32 = 0xFFFFFFFF; + const uint64_t a = f >> 32; + const uint64_t b = f & M32; + const uint64_t c = rhs.f >> 32; + const uint64_t d = rhs.f & M32; + const uint64_t ac = a * c; + const uint64_t bc = b * c; + const uint64_t ad = a * d; + const uint64_t bd = b * d; + uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32); + tmp += 1U << 31; /// mult_round + return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64); +#endif + } + + DiyFp Normalize() const { +#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); + return DiyFp(f << s, e - s); +#else + DiyFp res = *this; + while (!(res.f & (static_cast(1) << 63))) { + res.f <<= 1; + res.e--; + } + return res; +#endif + } + + DiyFp NormalizeBoundary() const { + DiyFp res = *this; + while (!(res.f & (kDpHiddenBit << 1))) { + res.f <<= 1; + res.e--; + } + res.f <<= (kDiySignificandSize - kDpSignificandSize - 2); + res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2); + return res; + } + + void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const { + DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary(); + DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1); + mi.f <<= mi.e - pl.e; + mi.e = pl.e; + *plus = pl; + *minus = mi; + } + + double ToDouble() const { + union { + double d; + uint64_t u64; + }u; + const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 : + static_cast(e + kDpExponentBias); + u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize); + return u.d; + } + + static const int kDiySignificandSize = 64; + static const int kDpSignificandSize = 52; + static const int kDpExponentBias = 0x3FF + kDpSignificandSize; + static const int kDpMaxExponent = 0x7FF - kDpExponentBias; + static const int kDpMinExponent = -kDpExponentBias; + static const int kDpDenormalExponent = -kDpExponentBias + 1; + static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); + static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); + static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); + + uint64_t f; + int e; +}; + +inline DiyFp GetCachedPowerByIndex(size_t index) { + // 10^-348, 10^-340, ..., 10^340 + static const uint64_t kCachedPowers_F[] = { + RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76), + RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea), + RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df), + RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f), + RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c), + RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5), + RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d), + RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637), + RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7), + RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5), + RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b), + RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996), + RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6), + RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8), + RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053), + RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd), + RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94), + RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b), + RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac), + RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3), + RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb), + RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c), + RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000), + RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984), + RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70), + RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245), + RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8), + RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a), + RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea), + RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85), + RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2), + RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3), + RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25), + RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece), + RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5), + RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a), + RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c), + RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a), + RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129), + RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429), + RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d), + RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841), + RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9), + RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b) + }; + static const int16_t kCachedPowers_E[] = { + -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, + -954, -927, -901, -874, -847, -821, -794, -768, -741, -715, + -688, -661, -635, -608, -582, -555, -529, -502, -475, -449, + -422, -396, -369, -343, -316, -289, -263, -236, -210, -183, + -157, -130, -103, -77, -50, -24, 3, 30, 56, 83, + 109, 136, 162, 189, 216, 242, 269, 295, 322, 348, + 375, 402, 428, 455, 481, 508, 534, 561, 588, 614, + 641, 667, 694, 720, 747, 774, 800, 827, 853, 880, + 907, 933, 960, 986, 1013, 1039, 1066 + }; + return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]); +} + +inline DiyFp GetCachedPower(int e, int* K) { + + //int k = static_cast(ceil((-61 - e) * 0.30102999566398114)) + 374; + double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive + int k = static_cast(dk); + if (dk - k > 0.0) + k++; + + unsigned index = static_cast((k >> 3) + 1); + *K = -(-348 + static_cast(index << 3)); // decimal exponent no need lookup table + + return GetCachedPowerByIndex(index); +} + +inline DiyFp GetCachedPower10(int exp, int *outExp) { + unsigned index = (static_cast(exp) + 348u) / 8u; + *outExp = -348 + static_cast(index) * 8; + return GetCachedPowerByIndex(index); + } + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +RAPIDJSON_DIAG_OFF(padded) +#endif + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_DIYFP_H_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/internal/dtoa.h b/Externals/discord-rpc/thirdparty/include/rapidjson/internal/dtoa.h new file mode 100644 index 0000000000..8d6350e626 --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/internal/dtoa.h @@ -0,0 +1,245 @@ +// 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. + +// This is a C++ header-only implementation of Grisu2 algorithm from the publication: +// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with +// integers." ACM Sigplan Notices 45.6 (2010): 233-243. + +#ifndef RAPIDJSON_DTOA_ +#define RAPIDJSON_DTOA_ + +#include "itoa.h" // GetDigitsLut() +#include "diyfp.h" +#include "ieee754.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +RAPIDJSON_DIAG_OFF(array-bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124 +#endif + +inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) { + while (rest < wp_w && delta - rest >= ten_kappa && + (rest + ten_kappa < wp_w || /// closer + wp_w - rest > rest + ten_kappa - wp_w)) { + buffer[len - 1]--; + rest += ten_kappa; + } +} + +inline unsigned CountDecimalDigit32(uint32_t n) { + // Simple pure C++ implementation was faster than __builtin_clz version in this situation. + if (n < 10) return 1; + if (n < 100) return 2; + if (n < 1000) return 3; + if (n < 10000) return 4; + if (n < 100000) return 5; + if (n < 1000000) return 6; + if (n < 10000000) return 7; + if (n < 100000000) return 8; + // Will not reach 10 digits in DigitGen() + //if (n < 1000000000) return 9; + //return 10; + return 9; +} + +inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) { + static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; + const DiyFp one(uint64_t(1) << -Mp.e, Mp.e); + const DiyFp wp_w = Mp - W; + uint32_t p1 = static_cast(Mp.f >> -one.e); + uint64_t p2 = Mp.f & (one.f - 1); + unsigned kappa = CountDecimalDigit32(p1); // kappa in [0, 9] + *len = 0; + + while (kappa > 0) { + uint32_t d = 0; + switch (kappa) { + case 9: d = p1 / 100000000; p1 %= 100000000; break; + case 8: d = p1 / 10000000; p1 %= 10000000; break; + case 7: d = p1 / 1000000; p1 %= 1000000; break; + case 6: d = p1 / 100000; p1 %= 100000; break; + case 5: d = p1 / 10000; p1 %= 10000; break; + case 4: d = p1 / 1000; p1 %= 1000; break; + case 3: d = p1 / 100; p1 %= 100; break; + case 2: d = p1 / 10; p1 %= 10; break; + case 1: d = p1; p1 = 0; break; + default:; + } + if (d || *len) + buffer[(*len)++] = static_cast('0' + static_cast(d)); + kappa--; + uint64_t tmp = (static_cast(p1) << -one.e) + p2; + if (tmp <= delta) { + *K += kappa; + GrisuRound(buffer, *len, delta, tmp, static_cast(kPow10[kappa]) << -one.e, wp_w.f); + return; + } + } + + // kappa = 0 + for (;;) { + p2 *= 10; + delta *= 10; + char d = static_cast(p2 >> -one.e); + if (d || *len) + buffer[(*len)++] = static_cast('0' + d); + p2 &= one.f - 1; + kappa--; + if (p2 < delta) { + *K += kappa; + int index = -static_cast(kappa); + GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[-static_cast(kappa)] : 0)); + return; + } + } +} + +inline void Grisu2(double value, char* buffer, int* length, int* K) { + const DiyFp v(value); + DiyFp w_m, w_p; + v.NormalizedBoundaries(&w_m, &w_p); + + const DiyFp c_mk = GetCachedPower(w_p.e, K); + const DiyFp W = v.Normalize() * c_mk; + DiyFp Wp = w_p * c_mk; + DiyFp Wm = w_m * c_mk; + Wm.f++; + Wp.f--; + DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K); +} + +inline char* WriteExponent(int K, char* buffer) { + if (K < 0) { + *buffer++ = '-'; + K = -K; + } + + if (K >= 100) { + *buffer++ = static_cast('0' + static_cast(K / 100)); + K %= 100; + const char* d = GetDigitsLut() + K * 2; + *buffer++ = d[0]; + *buffer++ = d[1]; + } + else if (K >= 10) { + const char* d = GetDigitsLut() + K * 2; + *buffer++ = d[0]; + *buffer++ = d[1]; + } + else + *buffer++ = static_cast('0' + static_cast(K)); + + return buffer; +} + +inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) { + const int kk = length + k; // 10^(kk-1) <= v < 10^kk + + if (0 <= k && kk <= 21) { + // 1234e7 -> 12340000000 + for (int i = length; i < kk; i++) + buffer[i] = '0'; + buffer[kk] = '.'; + buffer[kk + 1] = '0'; + return &buffer[kk + 2]; + } + else if (0 < kk && kk <= 21) { + // 1234e-2 -> 12.34 + std::memmove(&buffer[kk + 1], &buffer[kk], static_cast(length - kk)); + buffer[kk] = '.'; + if (0 > k + maxDecimalPlaces) { + // When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1 + // Remove extra trailing zeros (at least one) after truncation. + for (int i = kk + maxDecimalPlaces; i > kk + 1; i--) + if (buffer[i] != '0') + return &buffer[i + 1]; + return &buffer[kk + 2]; // Reserve one zero + } + else + return &buffer[length + 1]; + } + else if (-6 < kk && kk <= 0) { + // 1234e-6 -> 0.001234 + const int offset = 2 - kk; + std::memmove(&buffer[offset], &buffer[0], static_cast(length)); + buffer[0] = '0'; + buffer[1] = '.'; + for (int i = 2; i < offset; i++) + buffer[i] = '0'; + if (length - kk > maxDecimalPlaces) { + // When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1 + // Remove extra trailing zeros (at least one) after truncation. + for (int i = maxDecimalPlaces + 1; i > 2; i--) + if (buffer[i] != '0') + return &buffer[i + 1]; + return &buffer[3]; // Reserve one zero + } + else + return &buffer[length + offset]; + } + else if (kk < -maxDecimalPlaces) { + // Truncate to zero + buffer[0] = '0'; + buffer[1] = '.'; + buffer[2] = '0'; + return &buffer[3]; + } + else if (length == 1) { + // 1e30 + buffer[1] = 'e'; + return WriteExponent(kk - 1, &buffer[2]); + } + else { + // 1234e30 -> 1.234e33 + std::memmove(&buffer[2], &buffer[1], static_cast(length - 1)); + buffer[1] = '.'; + buffer[length + 1] = 'e'; + return WriteExponent(kk - 1, &buffer[0 + length + 2]); + } +} + +inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) { + RAPIDJSON_ASSERT(maxDecimalPlaces >= 1); + Double d(value); + if (d.IsZero()) { + if (d.Sign()) + *buffer++ = '-'; // -0.0, Issue #289 + buffer[0] = '0'; + buffer[1] = '.'; + buffer[2] = '0'; + return &buffer[3]; + } + else { + if (value < 0) { + *buffer++ = '-'; + value = -value; + } + int length, K; + Grisu2(value, buffer, &length, &K); + return Prettify(buffer, length, K, maxDecimalPlaces); + } +} + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_DTOA_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/internal/ieee754.h b/Externals/discord-rpc/thirdparty/include/rapidjson/internal/ieee754.h new file mode 100644 index 0000000000..82bb0b99e5 --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/internal/ieee754.h @@ -0,0 +1,78 @@ +// 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_IEEE754_ +#define RAPIDJSON_IEEE754_ + +#include "../rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +class Double { +public: + Double() {} + Double(double d) : d_(d) {} + Double(uint64_t u) : u_(u) {} + + double Value() const { return d_; } + uint64_t Uint64Value() const { return u_; } + + double NextPositiveDouble() const { + RAPIDJSON_ASSERT(!Sign()); + return Double(u_ + 1).Value(); + } + + bool Sign() const { return (u_ & kSignMask) != 0; } + uint64_t Significand() const { return u_ & kSignificandMask; } + int Exponent() const { return static_cast(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); } + + bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; } + bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; } + bool IsNanOrInf() const { return (u_ & kExponentMask) == kExponentMask; } + bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; } + bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; } + + uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); } + int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; } + uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; } + + static unsigned EffectiveSignificandSize(int order) { + if (order >= -1021) + return 53; + else if (order <= -1074) + return 0; + else + return static_cast(order) + 1074; + } + +private: + static const int kSignificandSize = 52; + static const int kExponentBias = 0x3FF; + static const int kDenormalExponent = 1 - kExponentBias; + static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000); + static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); + static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); + static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); + + union { + double d_; + uint64_t u_; + }; +}; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_IEEE754_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/internal/itoa.h b/Externals/discord-rpc/thirdparty/include/rapidjson/internal/itoa.h new file mode 100644 index 0000000000..01a4e7e72d --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/internal/itoa.h @@ -0,0 +1,304 @@ +// 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_ITOA_ +#define RAPIDJSON_ITOA_ + +#include "../rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +inline const char* GetDigitsLut() { + static const char cDigitsLut[200] = { + '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9', + '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9', + '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9', + '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9', + '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9', + '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9', + '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9', + '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9', + '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9', + '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9' + }; + return cDigitsLut; +} + +inline char* u32toa(uint32_t value, char* buffer) { + 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) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= 10) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + } + else if (value < 100000000) { + // 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) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= 100000) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + } + 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]; + *buffer++ = cDigitsLut[i + 1]; + } + else + *buffer++ = static_cast('0' + static_cast(a)); + + 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]; + *buffer++ = cDigitsLut[d2 + 1]; + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + } + return buffer; +} + +inline char* i32toa(int32_t value, char* buffer) { + uint32_t u = static_cast(value); + if (value < 0) { + *buffer++ = '-'; + u = ~u + 1; + } + + return u32toa(u, buffer); +} + +inline char* u64toa(uint64_t value, char* buffer) { + const char* cDigitsLut = GetDigitsLut(); + const uint64_t kTen8 = 100000000; + const uint64_t kTen9 = kTen8 * 10; + const uint64_t kTen10 = kTen8 * 100; + const uint64_t kTen11 = kTen8 * 1000; + const uint64_t kTen12 = kTen8 * 10000; + const uint64_t kTen13 = kTen8 * 100000; + 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(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) + *buffer++ = cDigitsLut[d1 + 1]; + if (v >= 10) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + } + else { + // 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) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= 100000) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + } + } + else if (value < kTen16) { + const uint32_t v0 = static_cast(value / kTen8); + const uint32_t v1 = static_cast(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; + + if (value >= kTen15) + *buffer++ = cDigitsLut[d1]; + if (value >= kTen14) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= kTen13) + *buffer++ = cDigitsLut[d2]; + if (value >= kTen12) + *buffer++ = cDigitsLut[d2 + 1]; + if (value >= kTen11) + *buffer++ = cDigitsLut[d3]; + if (value >= kTen10) + *buffer++ = cDigitsLut[d3 + 1]; + if (value >= kTen9) + *buffer++ = cDigitsLut[d4]; + if (value >= kTen8) + *buffer++ = cDigitsLut[d4 + 1]; + + *buffer++ = cDigitsLut[d5]; + *buffer++ = cDigitsLut[d5 + 1]; + *buffer++ = cDigitsLut[d6]; + *buffer++ = cDigitsLut[d6 + 1]; + *buffer++ = cDigitsLut[d7]; + *buffer++ = cDigitsLut[d7 + 1]; + *buffer++ = cDigitsLut[d8]; + *buffer++ = cDigitsLut[d8 + 1]; + } + else { + const uint32_t a = static_cast(value / kTen16); // 1 to 1844 + value %= kTen16; + + if (a < 10) + *buffer++ = static_cast('0' + static_cast(a)); + else if (a < 100) { + const uint32_t i = a << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + } + else if (a < 1000) { + *buffer++ = static_cast('0' + static_cast(a / 100)); + + const uint32_t i = (a % 100) << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + } + else { + const uint32_t i = (a / 100) << 1; + const uint32_t j = (a % 100) << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + *buffer++ = cDigitsLut[j]; + *buffer++ = cDigitsLut[j + 1]; + } + + const uint32_t v0 = static_cast(value / kTen8); + const uint32_t v1 = static_cast(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]; + *buffer++ = cDigitsLut[d2 + 1]; + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + *buffer++ = cDigitsLut[d5]; + *buffer++ = cDigitsLut[d5 + 1]; + *buffer++ = cDigitsLut[d6]; + *buffer++ = cDigitsLut[d6 + 1]; + *buffer++ = cDigitsLut[d7]; + *buffer++ = cDigitsLut[d7 + 1]; + *buffer++ = cDigitsLut[d8]; + *buffer++ = cDigitsLut[d8 + 1]; + } + + return buffer; +} + +inline char* i64toa(int64_t value, char* buffer) { + uint64_t u = static_cast(value); + if (value < 0) { + *buffer++ = '-'; + u = ~u + 1; + } + + return u64toa(u, buffer); +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_ITOA_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/internal/meta.h b/Externals/discord-rpc/thirdparty/include/rapidjson/internal/meta.h new file mode 100644 index 0000000000..5a9aaa4286 --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/internal/meta.h @@ -0,0 +1,181 @@ +// 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_INTERNAL_META_H_ +#define RAPIDJSON_INTERNAL_META_H_ + +#include "../rapidjson.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif +#if defined(_MSC_VER) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(6334) +#endif + +#if RAPIDJSON_HAS_CXX11_TYPETRAITS +#include +#endif + +//@cond RAPIDJSON_INTERNAL +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching +template struct Void { typedef void Type; }; + +/////////////////////////////////////////////////////////////////////////////// +// BoolType, TrueType, FalseType +// +template struct BoolType { + static const bool Value = Cond; + typedef BoolType Type; +}; +typedef BoolType TrueType; +typedef BoolType FalseType; + + +/////////////////////////////////////////////////////////////////////////////// +// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr +// + +template struct SelectIfImpl { template struct Apply { typedef T1 Type; }; }; +template <> struct SelectIfImpl { template struct Apply { typedef T2 Type; }; }; +template struct SelectIfCond : SelectIfImpl::template Apply {}; +template struct SelectIf : SelectIfCond {}; + +template struct AndExprCond : FalseType {}; +template <> struct AndExprCond : TrueType {}; +template struct OrExprCond : TrueType {}; +template <> struct OrExprCond : FalseType {}; + +template struct BoolExpr : SelectIf::Type {}; +template struct NotExpr : SelectIf::Type {}; +template struct AndExpr : AndExprCond::Type {}; +template struct OrExpr : OrExprCond::Type {}; + + +/////////////////////////////////////////////////////////////////////////////// +// AddConst, MaybeAddConst, RemoveConst +template struct AddConst { typedef const T Type; }; +template struct MaybeAddConst : SelectIfCond {}; +template struct RemoveConst { typedef T Type; }; +template struct RemoveConst { typedef T Type; }; + + +/////////////////////////////////////////////////////////////////////////////// +// IsSame, IsConst, IsMoreConst, IsPointer +// +template struct IsSame : FalseType {}; +template struct IsSame : TrueType {}; + +template struct IsConst : FalseType {}; +template struct IsConst : TrueType {}; + +template +struct IsMoreConst + : AndExpr::Type, typename RemoveConst::Type>, + BoolType::Value >= IsConst::Value> >::Type {}; + +template struct IsPointer : FalseType {}; +template struct IsPointer : TrueType {}; + +/////////////////////////////////////////////////////////////////////////////// +// IsBaseOf +// +#if RAPIDJSON_HAS_CXX11_TYPETRAITS + +template struct IsBaseOf + : BoolType< ::std::is_base_of::value> {}; + +#else // simplified version adopted from Boost + +template struct IsBaseOfImpl { + RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0); + RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0); + + typedef char (&Yes)[1]; + typedef char (&No) [2]; + + template + static Yes Check(const D*, T); + static No Check(const B*, int); + + struct Host { + operator const B*() const; + operator const D*(); + }; + + enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) }; +}; + +template struct IsBaseOf + : OrExpr, BoolExpr > >::Type {}; + +#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS + + +////////////////////////////////////////////////////////////////////////// +// EnableIf / DisableIf +// +template struct EnableIfCond { typedef T Type; }; +template struct EnableIfCond { /* empty */ }; + +template struct DisableIfCond { typedef T Type; }; +template struct DisableIfCond { /* empty */ }; + +template +struct EnableIf : EnableIfCond {}; + +template +struct DisableIf : DisableIfCond {}; + +// SFINAE helpers +struct SfinaeTag {}; +template struct RemoveSfinaeTag; +template struct RemoveSfinaeTag { typedef T Type; }; + +#define RAPIDJSON_REMOVEFPTR_(type) \ + typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \ + < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type + +#define RAPIDJSON_ENABLEIF(cond) \ + typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ + ::Type * = NULL + +#define RAPIDJSON_DISABLEIF(cond) \ + typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ + ::Type * = NULL + +#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \ + typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ + ::Type + +#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \ + typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ + ::Type + +} // namespace internal +RAPIDJSON_NAMESPACE_END +//@endcond + +#if defined(__GNUC__) || defined(_MSC_VER) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_INTERNAL_META_H_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/internal/pow10.h b/Externals/discord-rpc/thirdparty/include/rapidjson/internal/pow10.h new file mode 100644 index 0000000000..02f475d705 --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/internal/pow10.h @@ -0,0 +1,55 @@ +// 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_POW10_ +#define RAPIDJSON_POW10_ + +#include "../rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +//! Computes integer powers of 10 in double (10.0^n). +/*! This function uses lookup table for fast and accurate results. + \param n non-negative exponent. Must <= 308. + \return 10.0^n +*/ +inline double Pow10(int n) { + static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes + 1e+0, + 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, + 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40, + 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60, + 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80, + 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100, + 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120, + 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140, + 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160, + 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180, + 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200, + 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220, + 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240, + 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260, + 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280, + 1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300, + 1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308 + }; + RAPIDJSON_ASSERT(n >= 0 && n <= 308); + return e[n]; +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_POW10_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/internal/regex.h b/Externals/discord-rpc/thirdparty/include/rapidjson/internal/regex.h new file mode 100644 index 0000000000..422a5240bf --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/internal/regex.h @@ -0,0 +1,701 @@ +// 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_INTERNAL_REGEX_H_ +#define RAPIDJSON_INTERNAL_REGEX_H_ + +#include "../allocators.h" +#include "../stream.h" +#include "stack.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(switch-enum) +RAPIDJSON_DIAG_OFF(implicit-fallthrough) +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated +#endif + +#ifndef RAPIDJSON_REGEX_VERBOSE +#define RAPIDJSON_REGEX_VERBOSE 0 +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +/////////////////////////////////////////////////////////////////////////////// +// GenericRegex + +static const SizeType kRegexInvalidState = ~SizeType(0); //!< Represents an invalid index in GenericRegex::State::out, out1 +static const SizeType kRegexInvalidRange = ~SizeType(0); + +//! Regular expression engine with subset of ECMAscript grammar. +/*! + Supported regular expression syntax: + - \c ab Concatenation + - \c a|b Alternation + - \c a? Zero or one + - \c a* Zero or more + - \c a+ One or more + - \c a{3} Exactly 3 times + - \c a{3,} At least 3 times + - \c a{3,5} 3 to 5 times + - \c (ab) Grouping + - \c ^a At the beginning + - \c a$ At the end + - \c . Any character + - \c [abc] Character classes + - \c [a-c] Character class range + - \c [a-z0-9_] Character class combination + - \c [^abc] Negated character classes + - \c [^a-c] Negated character class range + - \c [\b] Backspace (U+0008) + - \c \\| \\\\ ... Escape characters + - \c \\f Form feed (U+000C) + - \c \\n Line feed (U+000A) + - \c \\r Carriage return (U+000D) + - \c \\t Tab (U+0009) + - \c \\v Vertical tab (U+000B) + + \note This is a Thompson NFA engine, implemented with reference to + Cox, Russ. "Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby,...).", + https://swtch.com/~rsc/regexp/regexp1.html +*/ +template +class GenericRegex { +public: + typedef typename Encoding::Ch Ch; + + GenericRegex(const Ch* source, Allocator* allocator = 0) : + states_(allocator, 256), ranges_(allocator, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(), + stateSet_(), state0_(allocator, 0), state1_(allocator, 0), anchorBegin_(), anchorEnd_() + { + GenericStringStream ss(source); + DecodedStream > ds(ss); + Parse(ds); + } + + ~GenericRegex() { + Allocator::Free(stateSet_); + } + + bool IsValid() const { + return root_ != kRegexInvalidState; + } + + template + bool Match(InputStream& is) const { + return SearchWithAnchoring(is, true, true); + } + + bool Match(const Ch* s) const { + GenericStringStream is(s); + return Match(is); + } + + template + bool Search(InputStream& is) const { + return SearchWithAnchoring(is, anchorBegin_, anchorEnd_); + } + + bool Search(const Ch* s) const { + GenericStringStream is(s); + return Search(is); + } + +private: + enum Operator { + kZeroOrOne, + kZeroOrMore, + kOneOrMore, + kConcatenation, + kAlternation, + kLeftParenthesis + }; + + static const unsigned kAnyCharacterClass = 0xFFFFFFFF; //!< For '.' + static const unsigned kRangeCharacterClass = 0xFFFFFFFE; + static const unsigned kRangeNegationFlag = 0x80000000; + + struct Range { + unsigned start; // + unsigned end; + SizeType next; + }; + + struct State { + SizeType out; //!< Equals to kInvalid for matching state + SizeType out1; //!< Equals to non-kInvalid for split + SizeType rangeStart; + unsigned codepoint; + }; + + struct Frag { + Frag(SizeType s, SizeType o, SizeType m) : start(s), out(o), minIndex(m) {} + SizeType start; + SizeType out; //!< link-list of all output states + SizeType minIndex; + }; + + template + class DecodedStream { + public: + DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); } + unsigned Peek() { return codepoint_; } + unsigned Take() { + unsigned c = codepoint_; + if (c) // No further decoding when '\0' + Decode(); + return c; + } + + private: + void Decode() { + if (!Encoding::Decode(ss_, &codepoint_)) + codepoint_ = 0; + } + + SourceStream& ss_; + unsigned codepoint_; + }; + + State& GetState(SizeType index) { + RAPIDJSON_ASSERT(index < stateCount_); + return states_.template Bottom()[index]; + } + + const State& GetState(SizeType index) const { + RAPIDJSON_ASSERT(index < stateCount_); + return states_.template Bottom()[index]; + } + + Range& GetRange(SizeType index) { + RAPIDJSON_ASSERT(index < rangeCount_); + return ranges_.template Bottom()[index]; + } + + const Range& GetRange(SizeType index) const { + RAPIDJSON_ASSERT(index < rangeCount_); + return ranges_.template Bottom()[index]; + } + + template + void Parse(DecodedStream& ds) { + Allocator allocator; + Stack operandStack(&allocator, 256); // Frag + Stack operatorStack(&allocator, 256); // Operator + Stack atomCountStack(&allocator, 256); // unsigned (Atom per parenthesis) + + *atomCountStack.template Push() = 0; + + unsigned codepoint; + while (ds.Peek() != 0) { + switch (codepoint = ds.Take()) { + case '^': + anchorBegin_ = true; + break; + + case '$': + anchorEnd_ = true; + break; + + case '|': + while (!operatorStack.Empty() && *operatorStack.template Top() < kAlternation) + if (!Eval(operandStack, *operatorStack.template Pop(1))) + return; + *operatorStack.template Push() = kAlternation; + *atomCountStack.template Top() = 0; + break; + + case '(': + *operatorStack.template Push() = kLeftParenthesis; + *atomCountStack.template Push() = 0; + break; + + case ')': + while (!operatorStack.Empty() && *operatorStack.template Top() != kLeftParenthesis) + if (!Eval(operandStack, *operatorStack.template Pop(1))) + return; + if (operatorStack.Empty()) + return; + operatorStack.template Pop(1); + atomCountStack.template Pop(1); + ImplicitConcatenation(atomCountStack, operatorStack); + break; + + case '?': + if (!Eval(operandStack, kZeroOrOne)) + return; + break; + + case '*': + if (!Eval(operandStack, kZeroOrMore)) + return; + break; + + case '+': + if (!Eval(operandStack, kOneOrMore)) + return; + break; + + case '{': + { + unsigned n, m; + if (!ParseUnsigned(ds, &n)) + return; + + if (ds.Peek() == ',') { + ds.Take(); + if (ds.Peek() == '}') + m = kInfinityQuantifier; + else if (!ParseUnsigned(ds, &m) || m < n) + return; + } + else + m = n; + + if (!EvalQuantifier(operandStack, n, m) || ds.Peek() != '}') + return; + ds.Take(); + } + break; + + case '.': + PushOperand(operandStack, kAnyCharacterClass); + ImplicitConcatenation(atomCountStack, operatorStack); + break; + + case '[': + { + SizeType range; + if (!ParseRange(ds, &range)) + return; + SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, kRangeCharacterClass); + GetState(s).rangeStart = range; + *operandStack.template Push() = Frag(s, s, s); + } + ImplicitConcatenation(atomCountStack, operatorStack); + break; + + case '\\': // Escape character + if (!CharacterEscape(ds, &codepoint)) + return; // Unsupported escape character + // fall through to default + + default: // Pattern character + PushOperand(operandStack, codepoint); + ImplicitConcatenation(atomCountStack, operatorStack); + } + } + + while (!operatorStack.Empty()) + if (!Eval(operandStack, *operatorStack.template Pop(1))) + return; + + // Link the operand to matching state. + if (operandStack.GetSize() == sizeof(Frag)) { + Frag* e = operandStack.template Pop(1); + Patch(e->out, NewState(kRegexInvalidState, kRegexInvalidState, 0)); + root_ = e->start; + +#if RAPIDJSON_REGEX_VERBOSE + printf("root: %d\n", root_); + for (SizeType i = 0; i < stateCount_ ; i++) { + State& s = GetState(i); + printf("[%2d] out: %2d out1: %2d c: '%c'\n", i, s.out, s.out1, (char)s.codepoint); + } + printf("\n"); +#endif + } + + // Preallocate buffer for SearchWithAnchoring() + RAPIDJSON_ASSERT(stateSet_ == 0); + if (stateCount_ > 0) { + stateSet_ = static_cast(states_.GetAllocator().Malloc(GetStateSetSize())); + state0_.template Reserve(stateCount_); + state1_.template Reserve(stateCount_); + } + } + + SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) { + State* s = states_.template Push(); + s->out = out; + s->out1 = out1; + s->codepoint = codepoint; + s->rangeStart = kRegexInvalidRange; + return stateCount_++; + } + + void PushOperand(Stack& operandStack, unsigned codepoint) { + SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, codepoint); + *operandStack.template Push() = Frag(s, s, s); + } + + void ImplicitConcatenation(Stack& atomCountStack, Stack& operatorStack) { + if (*atomCountStack.template Top()) + *operatorStack.template Push() = kConcatenation; + (*atomCountStack.template Top())++; + } + + SizeType Append(SizeType l1, SizeType l2) { + SizeType old = l1; + while (GetState(l1).out != kRegexInvalidState) + l1 = GetState(l1).out; + GetState(l1).out = l2; + return old; + } + + void Patch(SizeType l, SizeType s) { + for (SizeType next; l != kRegexInvalidState; l = next) { + next = GetState(l).out; + GetState(l).out = s; + } + } + + bool Eval(Stack& operandStack, Operator op) { + switch (op) { + case kConcatenation: + RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag) * 2); + { + Frag e2 = *operandStack.template Pop(1); + Frag e1 = *operandStack.template Pop(1); + Patch(e1.out, e2.start); + *operandStack.template Push() = Frag(e1.start, e2.out, Min(e1.minIndex, e2.minIndex)); + } + return true; + + case kAlternation: + if (operandStack.GetSize() >= sizeof(Frag) * 2) { + Frag e2 = *operandStack.template Pop(1); + Frag e1 = *operandStack.template Pop(1); + SizeType s = NewState(e1.start, e2.start, 0); + *operandStack.template Push() = Frag(s, Append(e1.out, e2.out), Min(e1.minIndex, e2.minIndex)); + return true; + } + return false; + + case kZeroOrOne: + if (operandStack.GetSize() >= sizeof(Frag)) { + Frag e = *operandStack.template Pop(1); + SizeType s = NewState(kRegexInvalidState, e.start, 0); + *operandStack.template Push() = Frag(s, Append(e.out, s), e.minIndex); + return true; + } + return false; + + case kZeroOrMore: + if (operandStack.GetSize() >= sizeof(Frag)) { + Frag e = *operandStack.template Pop(1); + SizeType s = NewState(kRegexInvalidState, e.start, 0); + Patch(e.out, s); + *operandStack.template Push() = Frag(s, s, e.minIndex); + return true; + } + return false; + + default: + RAPIDJSON_ASSERT(op == kOneOrMore); + if (operandStack.GetSize() >= sizeof(Frag)) { + Frag e = *operandStack.template Pop(1); + SizeType s = NewState(kRegexInvalidState, e.start, 0); + Patch(e.out, s); + *operandStack.template Push() = Frag(e.start, s, e.minIndex); + return true; + } + return false; + } + } + + bool EvalQuantifier(Stack& operandStack, unsigned n, unsigned m) { + RAPIDJSON_ASSERT(n <= m); + RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag)); + + if (n == 0) { + if (m == 0) // a{0} not support + return false; + else if (m == kInfinityQuantifier) + Eval(operandStack, kZeroOrMore); // a{0,} -> a* + else { + Eval(operandStack, kZeroOrOne); // a{0,5} -> a? + for (unsigned i = 0; i < m - 1; i++) + CloneTopOperand(operandStack); // a{0,5} -> a? a? a? a? a? + for (unsigned i = 0; i < m - 1; i++) + Eval(operandStack, kConcatenation); // a{0,5} -> a?a?a?a?a? + } + return true; + } + + for (unsigned i = 0; i < n - 1; i++) // a{3} -> a a a + CloneTopOperand(operandStack); + + if (m == kInfinityQuantifier) + Eval(operandStack, kOneOrMore); // a{3,} -> a a a+ + else if (m > n) { + CloneTopOperand(operandStack); // a{3,5} -> a a a a + Eval(operandStack, kZeroOrOne); // a{3,5} -> a a a a? + for (unsigned i = n; i < m - 1; i++) + CloneTopOperand(operandStack); // a{3,5} -> a a a a? a? + for (unsigned i = n; i < m; i++) + Eval(operandStack, kConcatenation); // a{3,5} -> a a aa?a? + } + + for (unsigned i = 0; i < n - 1; i++) + Eval(operandStack, kConcatenation); // a{3} -> aaa, a{3,} -> aaa+, a{3.5} -> aaaa?a? + + return true; + } + + static SizeType Min(SizeType a, SizeType b) { return a < b ? a : b; } + + void CloneTopOperand(Stack& operandStack) { + const Frag src = *operandStack.template Top(); // Copy constructor to prevent invalidation + SizeType count = stateCount_ - src.minIndex; // Assumes top operand contains states in [src->minIndex, stateCount_) + State* s = states_.template Push(count); + memcpy(s, &GetState(src.minIndex), count * sizeof(State)); + for (SizeType j = 0; j < count; j++) { + if (s[j].out != kRegexInvalidState) + s[j].out += count; + if (s[j].out1 != kRegexInvalidState) + s[j].out1 += count; + } + *operandStack.template Push() = Frag(src.start + count, src.out + count, src.minIndex + count); + stateCount_ += count; + } + + template + bool ParseUnsigned(DecodedStream& ds, unsigned* u) { + unsigned r = 0; + if (ds.Peek() < '0' || ds.Peek() > '9') + return false; + while (ds.Peek() >= '0' && ds.Peek() <= '9') { + if (r >= 429496729 && ds.Peek() > '5') // 2^32 - 1 = 4294967295 + return false; // overflow + r = r * 10 + (ds.Take() - '0'); + } + *u = r; + return true; + } + + template + bool ParseRange(DecodedStream& ds, SizeType* range) { + bool isBegin = true; + bool negate = false; + int step = 0; + SizeType start = kRegexInvalidRange; + SizeType current = kRegexInvalidRange; + unsigned codepoint; + while ((codepoint = ds.Take()) != 0) { + if (isBegin) { + isBegin = false; + if (codepoint == '^') { + negate = true; + continue; + } + } + + switch (codepoint) { + case ']': + if (start == kRegexInvalidRange) + return false; // Error: nothing inside [] + if (step == 2) { // Add trailing '-' + SizeType r = NewRange('-'); + RAPIDJSON_ASSERT(current != kRegexInvalidRange); + GetRange(current).next = r; + } + if (negate) + GetRange(start).start |= kRangeNegationFlag; + *range = start; + return true; + + case '\\': + if (ds.Peek() == 'b') { + ds.Take(); + codepoint = 0x0008; // Escape backspace character + } + else if (!CharacterEscape(ds, &codepoint)) + return false; + // fall through to default + + default: + switch (step) { + case 1: + if (codepoint == '-') { + step++; + break; + } + // fall through to step 0 for other characters + + case 0: + { + SizeType r = NewRange(codepoint); + if (current != kRegexInvalidRange) + GetRange(current).next = r; + if (start == kRegexInvalidRange) + start = r; + current = r; + } + step = 1; + break; + + default: + RAPIDJSON_ASSERT(step == 2); + GetRange(current).end = codepoint; + step = 0; + } + } + } + return false; + } + + SizeType NewRange(unsigned codepoint) { + Range* r = ranges_.template Push(); + r->start = r->end = codepoint; + r->next = kRegexInvalidRange; + return rangeCount_++; + } + + template + bool CharacterEscape(DecodedStream& ds, unsigned* escapedCodepoint) { + unsigned codepoint; + switch (codepoint = ds.Take()) { + case '^': + case '$': + case '|': + case '(': + case ')': + case '?': + case '*': + case '+': + case '.': + case '[': + case ']': + case '{': + case '}': + case '\\': + *escapedCodepoint = codepoint; return true; + case 'f': *escapedCodepoint = 0x000C; return true; + case 'n': *escapedCodepoint = 0x000A; return true; + case 'r': *escapedCodepoint = 0x000D; return true; + case 't': *escapedCodepoint = 0x0009; return true; + case 'v': *escapedCodepoint = 0x000B; return true; + default: + return false; // Unsupported escape character + } + } + + template + bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) const { + RAPIDJSON_ASSERT(IsValid()); + DecodedStream ds(is); + + state0_.Clear(); + Stack *current = &state0_, *next = &state1_; + const size_t stateSetSize = GetStateSetSize(); + std::memset(stateSet_, 0, stateSetSize); + + bool matched = AddState(*current, root_); + unsigned codepoint; + while (!current->Empty() && (codepoint = ds.Take()) != 0) { + std::memset(stateSet_, 0, stateSetSize); + next->Clear(); + matched = false; + for (const SizeType* s = current->template Bottom(); s != current->template End(); ++s) { + const State& sr = GetState(*s); + if (sr.codepoint == codepoint || + sr.codepoint == kAnyCharacterClass || + (sr.codepoint == kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint))) + { + matched = AddState(*next, sr.out) || matched; + if (!anchorEnd && matched) + return true; + } + if (!anchorBegin) + AddState(*next, root_); + } + internal::Swap(current, next); + } + + return matched; + } + + size_t GetStateSetSize() const { + return (stateCount_ + 31) / 32 * 4; + } + + // Return whether the added states is a match state + bool AddState(Stack& l, SizeType index) const { + RAPIDJSON_ASSERT(index != kRegexInvalidState); + + const State& s = GetState(index); + if (s.out1 != kRegexInvalidState) { // Split + bool matched = AddState(l, s.out); + return AddState(l, s.out1) || matched; + } + else if (!(stateSet_[index >> 5] & (1 << (index & 31)))) { + stateSet_[index >> 5] |= (1 << (index & 31)); + *l.template PushUnsafe() = index; + } + return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation. + } + + bool MatchRange(SizeType rangeIndex, unsigned codepoint) const { + bool yes = (GetRange(rangeIndex).start & kRangeNegationFlag) == 0; + while (rangeIndex != kRegexInvalidRange) { + const Range& r = GetRange(rangeIndex); + if (codepoint >= (r.start & ~kRangeNegationFlag) && codepoint <= r.end) + return yes; + rangeIndex = r.next; + } + return !yes; + } + + Stack states_; + Stack ranges_; + SizeType root_; + SizeType stateCount_; + SizeType rangeCount_; + + static const unsigned kInfinityQuantifier = ~0u; + + // For SearchWithAnchoring() + uint32_t* stateSet_; // allocated by states_.GetAllocator() + mutable Stack state0_; + mutable Stack state1_; + bool anchorBegin_; + bool anchorEnd_; +}; + +typedef GenericRegex > Regex; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_INTERNAL_REGEX_H_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/internal/stack.h b/Externals/discord-rpc/thirdparty/include/rapidjson/internal/stack.h new file mode 100644 index 0000000000..022c9aab41 --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/internal/stack.h @@ -0,0 +1,230 @@ +// 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_INTERNAL_STACK_H_ +#define RAPIDJSON_INTERNAL_STACK_H_ + +#include "../allocators.h" +#include "swap.h" + +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +/////////////////////////////////////////////////////////////////////////////// +// Stack + +//! A type-unsafe stack for storing different types of data. +/*! \tparam Allocator Allocator for allocating stack memory. +*/ +template +class Stack { +public: + // Optimization note: Do not allocate memory for stack_ in constructor. + // Do it lazily when first Push() -> Expand() -> Resize(). + Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) { + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + Stack(Stack&& rhs) + : allocator_(rhs.allocator_), + ownAllocator_(rhs.ownAllocator_), + stack_(rhs.stack_), + stackTop_(rhs.stackTop_), + stackEnd_(rhs.stackEnd_), + initialCapacity_(rhs.initialCapacity_) + { + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.stack_ = 0; + rhs.stackTop_ = 0; + rhs.stackEnd_ = 0; + rhs.initialCapacity_ = 0; + } +#endif + + ~Stack() { + Destroy(); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + Stack& operator=(Stack&& rhs) { + if (&rhs != this) + { + Destroy(); + + allocator_ = rhs.allocator_; + ownAllocator_ = rhs.ownAllocator_; + stack_ = rhs.stack_; + stackTop_ = rhs.stackTop_; + stackEnd_ = rhs.stackEnd_; + initialCapacity_ = rhs.initialCapacity_; + + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.stack_ = 0; + rhs.stackTop_ = 0; + rhs.stackEnd_ = 0; + rhs.initialCapacity_ = 0; + } + return *this; + } +#endif + + void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT { + internal::Swap(allocator_, rhs.allocator_); + internal::Swap(ownAllocator_, rhs.ownAllocator_); + internal::Swap(stack_, rhs.stack_); + internal::Swap(stackTop_, rhs.stackTop_); + internal::Swap(stackEnd_, rhs.stackEnd_); + internal::Swap(initialCapacity_, rhs.initialCapacity_); + } + + void Clear() { stackTop_ = stack_; } + + void ShrinkToFit() { + if (Empty()) { + // If the stack is empty, completely deallocate the memory. + Allocator::Free(stack_); + stack_ = 0; + stackTop_ = 0; + stackEnd_ = 0; + } + else + Resize(GetSize()); + } + + // Optimization note: try to minimize the size of this function for force inline. + // Expansion is run very infrequently, so it is moved to another (probably non-inline) function. + template + RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) { + // Expand the stack if needed + if (RAPIDJSON_UNLIKELY(stackTop_ + sizeof(T) * count > stackEnd_)) + Expand(count); + } + + template + RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) { + Reserve(count); + return PushUnsafe(count); + } + + template + RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) { + RAPIDJSON_ASSERT(stackTop_ + sizeof(T) * count <= stackEnd_); + T* ret = reinterpret_cast(stackTop_); + stackTop_ += sizeof(T) * count; + return ret; + } + + template + T* Pop(size_t count) { + RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); + stackTop_ -= count * sizeof(T); + return reinterpret_cast(stackTop_); + } + + template + T* Top() { + RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); + return reinterpret_cast(stackTop_ - sizeof(T)); + } + + template + const T* Top() const { + RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); + return reinterpret_cast(stackTop_ - sizeof(T)); + } + + template + T* End() { return reinterpret_cast(stackTop_); } + + template + const T* End() const { return reinterpret_cast(stackTop_); } + + template + T* Bottom() { return reinterpret_cast(stack_); } + + template + const T* Bottom() const { return reinterpret_cast(stack_); } + + bool HasAllocator() const { + return allocator_ != 0; + } + + Allocator& GetAllocator() { + RAPIDJSON_ASSERT(allocator_); + return *allocator_; + } + + bool Empty() const { return stackTop_ == stack_; } + size_t GetSize() const { return static_cast(stackTop_ - stack_); } + size_t GetCapacity() const { return static_cast(stackEnd_ - stack_); } + +private: + template + void Expand(size_t count) { + // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity. + size_t newCapacity; + if (stack_ == 0) { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + newCapacity = initialCapacity_; + } else { + newCapacity = GetCapacity(); + newCapacity += (newCapacity + 1) / 2; + } + size_t newSize = GetSize() + sizeof(T) * count; + if (newCapacity < newSize) + newCapacity = newSize; + + Resize(newCapacity); + } + + void Resize(size_t newCapacity) { + const size_t size = GetSize(); // Backup the current size + stack_ = static_cast(allocator_->Realloc(stack_, GetCapacity(), newCapacity)); + stackTop_ = stack_ + size; + stackEnd_ = stack_ + newCapacity; + } + + void Destroy() { + Allocator::Free(stack_); + RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack + } + + // Prohibit copy constructor & assignment operator. + Stack(const Stack&); + Stack& operator=(const Stack&); + + Allocator* allocator_; + Allocator* ownAllocator_; + char *stack_; + char *stackTop_; + char *stackEnd_; + size_t initialCapacity_; +}; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_STACK_H_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/internal/strfunc.h b/Externals/discord-rpc/thirdparty/include/rapidjson/internal/strfunc.h new file mode 100644 index 0000000000..2edfae5267 --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/internal/strfunc.h @@ -0,0 +1,55 @@ +// 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_INTERNAL_STRFUNC_H_ +#define RAPIDJSON_INTERNAL_STRFUNC_H_ + +#include "../stream.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +//! Custom strlen() which works on different character types. +/*! \tparam Ch Character type (e.g. char, wchar_t, short) + \param s Null-terminated input string. + \return Number of characters in the string. + \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints. +*/ +template +inline SizeType StrLen(const Ch* s) { + const Ch* p = s; + while (*p) ++p; + return SizeType(p - s); +} + +//! Returns number of code points in a encoded string. +template +bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) { + GenericStringStream is(s); + const typename Encoding::Ch* end = s + length; + SizeType count = 0; + while (is.src_ < end) { + unsigned codepoint; + if (!Encoding::Decode(is, &codepoint)) + return false; + count++; + } + *outCount = count; + return true; +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_INTERNAL_STRFUNC_H_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/internal/strtod.h b/Externals/discord-rpc/thirdparty/include/rapidjson/internal/strtod.h new file mode 100644 index 0000000000..289c413b07 --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/internal/strtod.h @@ -0,0 +1,269 @@ +// 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_STRTOD_ +#define RAPIDJSON_STRTOD_ + +#include "ieee754.h" +#include "biginteger.h" +#include "diyfp.h" +#include "pow10.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +inline double FastPath(double significand, int exp) { + if (exp < -308) + return 0.0; + else if (exp >= 0) + return significand * internal::Pow10(exp); + else + return significand / internal::Pow10(-exp); +} + +inline double StrtodNormalPrecision(double d, int p) { + if (p < -308) { + // Prevent expSum < -308, making Pow10(p) = 0 + d = FastPath(d, -308); + d = FastPath(d, p + 308); + } + else + d = FastPath(d, p); + return d; +} + +template +inline T Min3(T a, T b, T c) { + T m = a; + if (m > b) m = b; + if (m > c) m = c; + return m; +} + +inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) { + const Double db(b); + const uint64_t bInt = db.IntegerSignificand(); + const int bExp = db.IntegerExponent(); + const int hExp = bExp - 1; + + int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0; + + // Adjust for decimal exponent + if (dExp >= 0) { + dS_Exp2 += dExp; + dS_Exp5 += dExp; + } + else { + bS_Exp2 -= dExp; + bS_Exp5 -= dExp; + hS_Exp2 -= dExp; + hS_Exp5 -= dExp; + } + + // Adjust for binary exponent + if (bExp >= 0) + bS_Exp2 += bExp; + else { + dS_Exp2 -= bExp; + hS_Exp2 -= bExp; + } + + // Adjust for half ulp exponent + if (hExp >= 0) + hS_Exp2 += hExp; + else { + dS_Exp2 -= hExp; + bS_Exp2 -= hExp; + } + + // Remove common power of two factor from all three scaled values + int common_Exp2 = Min3(dS_Exp2, bS_Exp2, hS_Exp2); + dS_Exp2 -= common_Exp2; + bS_Exp2 -= common_Exp2; + hS_Exp2 -= common_Exp2; + + BigInteger dS = d; + dS.MultiplyPow5(static_cast(dS_Exp5)) <<= static_cast(dS_Exp2); + + BigInteger bS(bInt); + bS.MultiplyPow5(static_cast(bS_Exp5)) <<= static_cast(bS_Exp2); + + BigInteger hS(1); + hS.MultiplyPow5(static_cast(hS_Exp5)) <<= static_cast(hS_Exp2); + + BigInteger delta(0); + dS.Difference(bS, &delta); + + return delta.Compare(hS); +} + +inline bool StrtodFast(double d, int p, double* result) { + // Use fast path for string-to-double conversion if possible + // see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/ + if (p > 22 && p < 22 + 16) { + // Fast Path Cases In Disguise + d *= internal::Pow10(p - 22); + p = 22; + } + + if (p >= -22 && p <= 22 && d <= 9007199254740991.0) { // 2^53 - 1 + *result = FastPath(d, p); + return true; + } + else + return false; +} + +// Compute an approximation and see if it is within 1/2 ULP +inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosition, int exp, double* result) { + uint64_t significand = 0; + size_t i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999 + for (; i < length; i++) { + if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || + (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5')) + break; + significand = significand * 10u + static_cast(decimals[i] - '0'); + } + + if (i < length && decimals[i] >= '5') // Rounding + significand++; + + size_t remaining = length - i; + const unsigned kUlpShift = 3; + const unsigned kUlp = 1 << kUlpShift; + int64_t error = (remaining == 0) ? 0 : kUlp / 2; + + DiyFp v(significand, 0); + v = v.Normalize(); + error <<= -v.e; + + const int dExp = static_cast(decimalPosition) - static_cast(i) + exp; + + int actualExp; + DiyFp cachedPower = GetCachedPower10(dExp, &actualExp); + if (actualExp != dExp) { + static const DiyFp kPow10[] = { + DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 00000000), -60), // 10^1 + DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57), // 10^2 + DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54), // 10^3 + DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 00000000), -50), // 10^4 + DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 00000000), -47), // 10^5 + DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44), // 10^6 + DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40) // 10^7 + }; + int adjustment = dExp - actualExp - 1; + RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7); + v = v * kPow10[adjustment]; + if (length + static_cast(adjustment)> 19u) // has more digits than decimal digits in 64-bit + error += kUlp / 2; + } + + v = v * cachedPower; + + error += kUlp + (error == 0 ? 0 : 1); + + const int oldExp = v.e; + v = v.Normalize(); + error <<= oldExp - v.e; + + const unsigned effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e); + unsigned precisionSize = 64 - effectiveSignificandSize; + if (precisionSize + kUlpShift >= 64) { + unsigned scaleExp = (precisionSize + kUlpShift) - 63; + v.f >>= scaleExp; + v.e += scaleExp; + error = (error >> scaleExp) + 1 + static_cast(kUlp); + precisionSize -= scaleExp; + } + + DiyFp rounded(v.f >> precisionSize, v.e + static_cast(precisionSize)); + const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp; + const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp; + if (precisionBits >= halfWay + static_cast(error)) { + rounded.f++; + if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340) + rounded.f >>= 1; + rounded.e++; + } + } + + *result = rounded.ToDouble(); + + return halfWay - static_cast(error) >= precisionBits || precisionBits >= halfWay + static_cast(error); +} + +inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) { + const BigInteger dInt(decimals, length); + const int dExp = static_cast(decimalPosition) - static_cast(length) + exp; + Double a(approx); + int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp); + if (cmp < 0) + return a.Value(); // within half ULP + else if (cmp == 0) { + // Round towards even + if (a.Significand() & 1) + return a.NextPositiveDouble(); + else + return a.Value(); + } + else // adjustment + return a.NextPositiveDouble(); +} + +inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) { + RAPIDJSON_ASSERT(d >= 0.0); + RAPIDJSON_ASSERT(length >= 1); + + double result; + if (StrtodFast(d, p, &result)) + return result; + + // Trim leading zeros + while (*decimals == '0' && length > 1) { + length--; + decimals++; + decimalPosition--; + } + + // Trim trailing zeros + while (decimals[length - 1] == '0' && length > 1) { + length--; + decimalPosition--; + exp++; + } + + // Trim right-most digits + const int kMaxDecimalDigit = 780; + if (static_cast(length) > kMaxDecimalDigit) { + int delta = (static_cast(length) - kMaxDecimalDigit); + exp += delta; + decimalPosition -= static_cast(delta); + length = kMaxDecimalDigit; + } + + // If too small, underflow to zero + if (int(length) + exp < -324) + return 0.0; + + if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result)) + return result; + + // Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison + return StrtodBigInteger(result, decimals, length, decimalPosition, exp); +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_STRTOD_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/internal/swap.h b/Externals/discord-rpc/thirdparty/include/rapidjson/internal/swap.h new file mode 100644 index 0000000000..666e49f97b --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/internal/swap.h @@ -0,0 +1,46 @@ +// 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_INTERNAL_SWAP_H_ +#define RAPIDJSON_INTERNAL_SWAP_H_ + +#include "../rapidjson.h" + +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +//! Custom swap() to avoid dependency on C++ header +/*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only. + \note This has the same semantics as std::swap(). +*/ +template +inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT { + T tmp = a; + a = b; + b = tmp; +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_INTERNAL_SWAP_H_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/istreamwrapper.h b/Externals/discord-rpc/thirdparty/include/rapidjson/istreamwrapper.h new file mode 100644 index 0000000000..f5fe28977e --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/istreamwrapper.h @@ -0,0 +1,115 @@ +// 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_ISTREAMWRAPPER_H_ +#define RAPIDJSON_ISTREAMWRAPPER_H_ + +#include "stream.h" +#include + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Wrapper of \c std::basic_istream into RapidJSON's Stream concept. +/*! + The classes can be wrapped including but not limited to: + + - \c std::istringstream + - \c std::stringstream + - \c std::wistringstream + - \c std::wstringstream + - \c std::ifstream + - \c std::fstream + - \c std::wifstream + - \c std::wfstream + + \tparam StreamType Class derived from \c std::basic_istream. +*/ + +template +class BasicIStreamWrapper { +public: + typedef typename StreamType::char_type Ch; + BasicIStreamWrapper(StreamType& stream) : stream_(stream), count_(), peekBuffer_() {} + + Ch Peek() const { + typename StreamType::int_type c = stream_.peek(); + return RAPIDJSON_LIKELY(c != StreamType::traits_type::eof()) ? static_cast(c) : '\0'; + } + + Ch Take() { + typename StreamType::int_type c = stream_.get(); + if (RAPIDJSON_LIKELY(c != StreamType::traits_type::eof())) { + count_++; + return static_cast(c); + } + else + return '\0'; + } + + // tellg() may return -1 when failed. So we count by ourself. + size_t Tell() const { return count_; } + + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + // For encoding detection only. + const Ch* Peek4() const { + RAPIDJSON_ASSERT(sizeof(Ch) == 1); // Only usable for byte stream. + int i; + bool hasError = false; + for (i = 0; i < 4; ++i) { + typename StreamType::int_type c = stream_.get(); + if (c == StreamType::traits_type::eof()) { + hasError = true; + stream_.clear(); + break; + } + peekBuffer_[i] = static_cast(c); + } + for (--i; i >= 0; --i) + stream_.putback(peekBuffer_[i]); + return !hasError ? peekBuffer_ : 0; + } + +private: + BasicIStreamWrapper(const BasicIStreamWrapper&); + BasicIStreamWrapper& operator=(const BasicIStreamWrapper&); + + StreamType& stream_; + size_t count_; //!< Number of characters read. Note: + mutable Ch peekBuffer_[4]; +}; + +typedef BasicIStreamWrapper IStreamWrapper; +typedef BasicIStreamWrapper WIStreamWrapper; + +#if defined(__clang__) || defined(_MSC_VER) +RAPIDJSON_DIAG_POP +#endif + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_ISTREAMWRAPPER_H_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/memorybuffer.h b/Externals/discord-rpc/thirdparty/include/rapidjson/memorybuffer.h new file mode 100644 index 0000000000..39bee1dec1 --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/memorybuffer.h @@ -0,0 +1,70 @@ +// 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_MEMORYBUFFER_H_ +#define RAPIDJSON_MEMORYBUFFER_H_ + +#include "stream.h" +#include "internal/stack.h" + +RAPIDJSON_NAMESPACE_BEGIN + +//! Represents an in-memory output byte stream. +/*! + This class is mainly for being wrapped by EncodedOutputStream or AutoUTFOutputStream. + + It is similar to FileWriteBuffer but the destination is an in-memory buffer instead of a file. + + Differences between MemoryBuffer and StringBuffer: + 1. StringBuffer has Encoding but MemoryBuffer is only a byte buffer. + 2. StringBuffer::GetString() returns a null-terminated string. MemoryBuffer::GetBuffer() returns a buffer without terminator. + + \tparam Allocator type for allocating memory buffer. + \note implements Stream concept +*/ +template +struct GenericMemoryBuffer { + typedef char Ch; // byte + + GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} + + void Put(Ch c) { *stack_.template Push() = c; } + void Flush() {} + + void Clear() { stack_.Clear(); } + void ShrinkToFit() { stack_.ShrinkToFit(); } + Ch* Push(size_t count) { return stack_.template Push(count); } + void Pop(size_t count) { stack_.template Pop(count); } + + const Ch* GetBuffer() const { + return stack_.template Bottom(); + } + + size_t GetSize() const { return stack_.GetSize(); } + + static const size_t kDefaultCapacity = 256; + mutable internal::Stack stack_; +}; + +typedef GenericMemoryBuffer<> MemoryBuffer; + +//! Implement specialized version of PutN() with memset() for better performance. +template<> +inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) { + std::memset(memoryBuffer.stack_.Push(n), c, n * sizeof(c)); +} + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_MEMORYBUFFER_H_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/memorystream.h b/Externals/discord-rpc/thirdparty/include/rapidjson/memorystream.h new file mode 100644 index 0000000000..1d71d8a4f0 --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/memorystream.h @@ -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_MEMORYSTREAM_H_ +#define RAPIDJSON_MEMORYSTREAM_H_ + +#include "stream.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(unreachable-code) +RAPIDJSON_DIAG_OFF(missing-noreturn) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Represents an in-memory input byte stream. +/*! + This class is mainly for being wrapped by EncodedInputStream or AutoUTFInputStream. + + It is similar to FileReadBuffer but the source is an in-memory buffer instead of a file. + + Differences between MemoryStream and StringStream: + 1. StringStream has encoding but MemoryStream is a byte stream. + 2. MemoryStream needs size of the source buffer and the buffer don't need to be null terminated. StringStream assume null-terminated string as source. + 3. MemoryStream supports Peek4() for encoding detection. StringStream is specified with an encoding so it should not have Peek4(). + \note implements Stream concept +*/ +struct MemoryStream { + typedef char Ch; // byte + + MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {} + + Ch Peek() const { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_; } + Ch Take() { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_++; } + size_t Tell() const { return static_cast(src_ - begin_); } + + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + // For encoding detection only. + const Ch* Peek4() const { + return Tell() + 4 <= size_ ? src_ : 0; + } + + const Ch* src_; //!< Current read position. + const Ch* begin_; //!< Original head of the string. + const Ch* end_; //!< End of stream. + size_t size_; //!< Size of the stream. +}; + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_MEMORYBUFFER_H_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/msinttypes/inttypes.h b/Externals/discord-rpc/thirdparty/include/rapidjson/msinttypes/inttypes.h new file mode 100644 index 0000000000..18111286bf --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/msinttypes/inttypes.h @@ -0,0 +1,316 @@ +// ISO C9x compliant inttypes.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2013 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the product nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +// The above software in this distribution may have been modified by +// THL A29 Limited ("Tencent Modifications"). +// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited. + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_INTTYPES_H_ // [ +#define _MSC_INTTYPES_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include "stdint.h" + +// miloyip: VC supports inttypes.h since VC2013 +#if _MSC_VER >= 1800 +#include +#else + +// 7.8 Format conversion of integer types + +typedef struct { + intmax_t quot; + intmax_t rem; +} imaxdiv_t; + +// 7.8.1 Macros for format specifiers + +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 + +// The fprintf macros for signed integers are: +#define PRId8 "d" +#define PRIi8 "i" +#define PRIdLEAST8 "d" +#define PRIiLEAST8 "i" +#define PRIdFAST8 "d" +#define PRIiFAST8 "i" + +#define PRId16 "hd" +#define PRIi16 "hi" +#define PRIdLEAST16 "hd" +#define PRIiLEAST16 "hi" +#define PRIdFAST16 "hd" +#define PRIiFAST16 "hi" + +#define PRId32 "I32d" +#define PRIi32 "I32i" +#define PRIdLEAST32 "I32d" +#define PRIiLEAST32 "I32i" +#define PRIdFAST32 "I32d" +#define PRIiFAST32 "I32i" + +#define PRId64 "I64d" +#define PRIi64 "I64i" +#define PRIdLEAST64 "I64d" +#define PRIiLEAST64 "I64i" +#define PRIdFAST64 "I64d" +#define PRIiFAST64 "I64i" + +#define PRIdMAX "I64d" +#define PRIiMAX "I64i" + +#define PRIdPTR "Id" +#define PRIiPTR "Ii" + +// The fprintf macros for unsigned integers are: +#define PRIo8 "o" +#define PRIu8 "u" +#define PRIx8 "x" +#define PRIX8 "X" +#define PRIoLEAST8 "o" +#define PRIuLEAST8 "u" +#define PRIxLEAST8 "x" +#define PRIXLEAST8 "X" +#define PRIoFAST8 "o" +#define PRIuFAST8 "u" +#define PRIxFAST8 "x" +#define PRIXFAST8 "X" + +#define PRIo16 "ho" +#define PRIu16 "hu" +#define PRIx16 "hx" +#define PRIX16 "hX" +#define PRIoLEAST16 "ho" +#define PRIuLEAST16 "hu" +#define PRIxLEAST16 "hx" +#define PRIXLEAST16 "hX" +#define PRIoFAST16 "ho" +#define PRIuFAST16 "hu" +#define PRIxFAST16 "hx" +#define PRIXFAST16 "hX" + +#define PRIo32 "I32o" +#define PRIu32 "I32u" +#define PRIx32 "I32x" +#define PRIX32 "I32X" +#define PRIoLEAST32 "I32o" +#define PRIuLEAST32 "I32u" +#define PRIxLEAST32 "I32x" +#define PRIXLEAST32 "I32X" +#define PRIoFAST32 "I32o" +#define PRIuFAST32 "I32u" +#define PRIxFAST32 "I32x" +#define PRIXFAST32 "I32X" + +#define PRIo64 "I64o" +#define PRIu64 "I64u" +#define PRIx64 "I64x" +#define PRIX64 "I64X" +#define PRIoLEAST64 "I64o" +#define PRIuLEAST64 "I64u" +#define PRIxLEAST64 "I64x" +#define PRIXLEAST64 "I64X" +#define PRIoFAST64 "I64o" +#define PRIuFAST64 "I64u" +#define PRIxFAST64 "I64x" +#define PRIXFAST64 "I64X" + +#define PRIoMAX "I64o" +#define PRIuMAX "I64u" +#define PRIxMAX "I64x" +#define PRIXMAX "I64X" + +#define PRIoPTR "Io" +#define PRIuPTR "Iu" +#define PRIxPTR "Ix" +#define PRIXPTR "IX" + +// The fscanf macros for signed integers are: +#define SCNd8 "d" +#define SCNi8 "i" +#define SCNdLEAST8 "d" +#define SCNiLEAST8 "i" +#define SCNdFAST8 "d" +#define SCNiFAST8 "i" + +#define SCNd16 "hd" +#define SCNi16 "hi" +#define SCNdLEAST16 "hd" +#define SCNiLEAST16 "hi" +#define SCNdFAST16 "hd" +#define SCNiFAST16 "hi" + +#define SCNd32 "ld" +#define SCNi32 "li" +#define SCNdLEAST32 "ld" +#define SCNiLEAST32 "li" +#define SCNdFAST32 "ld" +#define SCNiFAST32 "li" + +#define SCNd64 "I64d" +#define SCNi64 "I64i" +#define SCNdLEAST64 "I64d" +#define SCNiLEAST64 "I64i" +#define SCNdFAST64 "I64d" +#define SCNiFAST64 "I64i" + +#define SCNdMAX "I64d" +#define SCNiMAX "I64i" + +#ifdef _WIN64 // [ +# define SCNdPTR "I64d" +# define SCNiPTR "I64i" +#else // _WIN64 ][ +# define SCNdPTR "ld" +# define SCNiPTR "li" +#endif // _WIN64 ] + +// The fscanf macros for unsigned integers are: +#define SCNo8 "o" +#define SCNu8 "u" +#define SCNx8 "x" +#define SCNX8 "X" +#define SCNoLEAST8 "o" +#define SCNuLEAST8 "u" +#define SCNxLEAST8 "x" +#define SCNXLEAST8 "X" +#define SCNoFAST8 "o" +#define SCNuFAST8 "u" +#define SCNxFAST8 "x" +#define SCNXFAST8 "X" + +#define SCNo16 "ho" +#define SCNu16 "hu" +#define SCNx16 "hx" +#define SCNX16 "hX" +#define SCNoLEAST16 "ho" +#define SCNuLEAST16 "hu" +#define SCNxLEAST16 "hx" +#define SCNXLEAST16 "hX" +#define SCNoFAST16 "ho" +#define SCNuFAST16 "hu" +#define SCNxFAST16 "hx" +#define SCNXFAST16 "hX" + +#define SCNo32 "lo" +#define SCNu32 "lu" +#define SCNx32 "lx" +#define SCNX32 "lX" +#define SCNoLEAST32 "lo" +#define SCNuLEAST32 "lu" +#define SCNxLEAST32 "lx" +#define SCNXLEAST32 "lX" +#define SCNoFAST32 "lo" +#define SCNuFAST32 "lu" +#define SCNxFAST32 "lx" +#define SCNXFAST32 "lX" + +#define SCNo64 "I64o" +#define SCNu64 "I64u" +#define SCNx64 "I64x" +#define SCNX64 "I64X" +#define SCNoLEAST64 "I64o" +#define SCNuLEAST64 "I64u" +#define SCNxLEAST64 "I64x" +#define SCNXLEAST64 "I64X" +#define SCNoFAST64 "I64o" +#define SCNuFAST64 "I64u" +#define SCNxFAST64 "I64x" +#define SCNXFAST64 "I64X" + +#define SCNoMAX "I64o" +#define SCNuMAX "I64u" +#define SCNxMAX "I64x" +#define SCNXMAX "I64X" + +#ifdef _WIN64 // [ +# define SCNoPTR "I64o" +# define SCNuPTR "I64u" +# define SCNxPTR "I64x" +# define SCNXPTR "I64X" +#else // _WIN64 ][ +# define SCNoPTR "lo" +# define SCNuPTR "lu" +# define SCNxPTR "lx" +# define SCNXPTR "lX" +#endif // _WIN64 ] + +#endif // __STDC_FORMAT_MACROS ] + +// 7.8.2 Functions for greatest-width integer types + +// 7.8.2.1 The imaxabs function +#define imaxabs _abs64 + +// 7.8.2.2 The imaxdiv function + +// This is modified version of div() function from Microsoft's div.c found +// in %MSVC.NET%\crt\src\div.c +#ifdef STATIC_IMAXDIV // [ +static +#else // STATIC_IMAXDIV ][ +_inline +#endif // STATIC_IMAXDIV ] +imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) +{ + imaxdiv_t result; + + result.quot = numer / denom; + result.rem = numer % denom; + + if (numer < 0 && result.rem > 0) { + // did division wrong; must fix up + ++result.quot; + result.rem -= denom; + } + + return result; +} + +// 7.8.2.3 The strtoimax and strtoumax functions +#define strtoimax _strtoi64 +#define strtoumax _strtoui64 + +// 7.8.2.4 The wcstoimax and wcstoumax functions +#define wcstoimax _wcstoi64 +#define wcstoumax _wcstoui64 + +#endif // _MSC_VER >= 1800 + +#endif // _MSC_INTTYPES_H_ ] diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/msinttypes/stdint.h b/Externals/discord-rpc/thirdparty/include/rapidjson/msinttypes/stdint.h new file mode 100644 index 0000000000..3d4477b9a0 --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/msinttypes/stdint.h @@ -0,0 +1,300 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2013 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the product nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +// The above software in this distribution may have been modified by +// THL A29 Limited ("Tencent Modifications"). +// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited. + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_STDINT_H_ // [ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +// miloyip: Originally Visual Studio 2010 uses its own stdint.h. However it generates warning with INT64_C(), so change to use this file for vs2010. +#if _MSC_VER >= 1600 // [ +#include + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +#undef INT8_C +#undef INT16_C +#undef INT32_C +#undef INT64_C +#undef UINT8_C +#undef UINT16_C +#undef UINT32_C +#undef UINT64_C + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +// These #ifndef's are needed to prevent collisions with . +// Check out Issue 9 for the details. +#ifndef INTMAX_C // [ +# define INTMAX_C INT64_C +#endif // INTMAX_C ] +#ifndef UINTMAX_C // [ +# define UINTMAX_C UINT64_C +#endif // UINTMAX_C ] + +#endif // __STDC_CONSTANT_MACROS ] + +#else // ] _MSC_VER >= 1700 [ + +#include + +// For Visual Studio 6 in C++ mode and for many Visual Studio versions when +// compiling for ARM we have to wrap include with 'extern "C++" {}' +// or compiler would give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +#if defined(__cplusplus) && !defined(_M_ARM) +extern "C" { +#endif +# include +#if defined(__cplusplus) && !defined(_M_ARM) +} +#endif + +// Define _W64 macros to mark types changing their size, like intptr_t. +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types + +// Visual Studio 6 and Embedded Visual C++ 4 doesn't +// realize that, e.g. char has the same size as __int8 +// so we give up on __intX for them. +#if (_MSC_VER < 1300) + typedef signed char int8_t; + typedef signed short int16_t; + typedef signed int int32_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; +#else + typedef signed __int8 int8_t; + typedef signed __int16 int16_t; + typedef signed __int32 int32_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; +#endif +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; + + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef signed __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef _W64 signed int intptr_t; + typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +// These #ifndef's are needed to prevent collisions with . +// Check out Issue 9 for the details. +#ifndef INTMAX_C // [ +# define INTMAX_C INT64_C +#endif // INTMAX_C ] +#ifndef UINTMAX_C // [ +# define UINTMAX_C UINT64_C +#endif // UINTMAX_C ] + +#endif // __STDC_CONSTANT_MACROS ] + +#endif // _MSC_VER >= 1600 ] + +#endif // _MSC_STDINT_H_ ] diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/ostreamwrapper.h b/Externals/discord-rpc/thirdparty/include/rapidjson/ostreamwrapper.h new file mode 100644 index 0000000000..6f4667c08a --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/ostreamwrapper.h @@ -0,0 +1,81 @@ +// 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_OSTREAMWRAPPER_H_ +#define RAPIDJSON_OSTREAMWRAPPER_H_ + +#include "stream.h" +#include + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Wrapper of \c std::basic_ostream into RapidJSON's Stream concept. +/*! + The classes can be wrapped including but not limited to: + + - \c std::ostringstream + - \c std::stringstream + - \c std::wpstringstream + - \c std::wstringstream + - \c std::ifstream + - \c std::fstream + - \c std::wofstream + - \c std::wfstream + + \tparam StreamType Class derived from \c std::basic_ostream. +*/ + +template +class BasicOStreamWrapper { +public: + typedef typename StreamType::char_type Ch; + BasicOStreamWrapper(StreamType& stream) : stream_(stream) {} + + void Put(Ch c) { + stream_.put(c); + } + + void Flush() { + stream_.flush(); + } + + // Not implemented + char Peek() const { RAPIDJSON_ASSERT(false); return 0; } + char Take() { RAPIDJSON_ASSERT(false); return 0; } + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + BasicOStreamWrapper(const BasicOStreamWrapper&); + BasicOStreamWrapper& operator=(const BasicOStreamWrapper&); + + StreamType& stream_; +}; + +typedef BasicOStreamWrapper OStreamWrapper; +typedef BasicOStreamWrapper WOStreamWrapper; + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_OSTREAMWRAPPER_H_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/pointer.h b/Externals/discord-rpc/thirdparty/include/rapidjson/pointer.h new file mode 100644 index 0000000000..0206ac1c8b --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/pointer.h @@ -0,0 +1,1358 @@ +// 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_POINTER_H_ +#define RAPIDJSON_POINTER_H_ + +#include "document.h" +#include "internal/itoa.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(switch-enum) +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +static const SizeType kPointerInvalidIndex = ~SizeType(0); //!< Represents an invalid index in GenericPointer::Token + +//! Error code of parsing. +/*! \ingroup RAPIDJSON_ERRORS + \see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode +*/ +enum PointerParseErrorCode { + kPointerParseErrorNone = 0, //!< The parse is successful + + kPointerParseErrorTokenMustBeginWithSolidus, //!< A token must begin with a '/' + kPointerParseErrorInvalidEscape, //!< Invalid escape + kPointerParseErrorInvalidPercentEncoding, //!< Invalid percent encoding in URI fragment + kPointerParseErrorCharacterMustPercentEncode //!< A character must percent encoded in URI fragment +}; + +/////////////////////////////////////////////////////////////////////////////// +// GenericPointer + +//! Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator. +/*! + This class implements RFC 6901 "JavaScript Object Notation (JSON) Pointer" + (https://tools.ietf.org/html/rfc6901). + + A JSON pointer is for identifying a specific value in a JSON document + (GenericDocument). It can simplify coding of DOM tree manipulation, because it + can access multiple-level depth of DOM tree with single API call. + + After it parses a string representation (e.g. "/foo/0" or URI fragment + representation (e.g. "#/foo/0") into its internal representation (tokens), + it can be used to resolve a specific value in multiple documents, or sub-tree + of documents. + + Contrary to GenericValue, Pointer can be copy constructed and copy assigned. + Apart from assignment, a Pointer cannot be modified after construction. + + Although Pointer is very convenient, please aware that constructing Pointer + involves parsing and dynamic memory allocation. A special constructor with user- + supplied tokens eliminates these. + + GenericPointer depends on GenericDocument and GenericValue. + + \tparam ValueType The value type of the DOM tree. E.g. GenericValue > + \tparam Allocator The allocator type for allocating memory for internal representation. + + \note GenericPointer uses same encoding of ValueType. + However, Allocator of GenericPointer is independent of Allocator of Value. +*/ +template +class GenericPointer { +public: + typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value + typedef typename ValueType::Ch Ch; //!< Character type from Value + + //! A token is the basic units of internal representation. + /*! + A JSON pointer string representation "/foo/123" is parsed to two tokens: + "foo" and 123. 123 will be represented in both numeric form and string form. + They are resolved according to the actual value type (object or array). + + For token that are not numbers, or the numeric value is out of bound + (greater than limits of SizeType), they are only treated as string form + (i.e. the token's index will be equal to kPointerInvalidIndex). + + This struct is public so that user can create a Pointer without parsing and + allocation, using a special constructor. + */ + struct Token { + const Ch* name; //!< Name of the token. It has null character at the end but it can contain null character. + SizeType length; //!< Length of the name. + SizeType index; //!< A valid array index, if it is not equal to kPointerInvalidIndex. + }; + + //!@name Constructors and destructor. + //@{ + + //! Default constructor. + GenericPointer(Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} + + //! Constructor that parses a string or URI fragment representation. + /*! + \param source A null-terminated, string or URI fragment representation of JSON pointer. + \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. + */ + explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + Parse(source, internal::StrLen(source)); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Constructor that parses a string or URI fragment representation. + /*! + \param source A string or URI fragment representation of JSON pointer. + \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. + \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + explicit GenericPointer(const std::basic_string& source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + Parse(source.c_str(), source.size()); + } +#endif + + //! Constructor that parses a string or URI fragment representation, with length of the source string. + /*! + \param source A string or URI fragment representation of JSON pointer. + \param length Length of source. + \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. + \note Slightly faster than the overload without length. + */ + GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + Parse(source, length); + } + + //! Constructor with user-supplied tokens. + /*! + This constructor let user supplies const array of tokens. + This prevents the parsing process and eliminates allocation. + This is preferred for memory constrained environments. + + \param tokens An constant array of tokens representing the JSON pointer. + \param tokenCount Number of tokens. + + \b Example + \code + #define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex } + #define INDEX(i) { #i, sizeof(#i) - 1, i } + + static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(123) }; + static const Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0])); + // Equivalent to static const Pointer p("/foo/123"); + + #undef NAME + #undef INDEX + \endcode + */ + GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} + + //! Copy constructor. + GenericPointer(const GenericPointer& rhs, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + *this = rhs; + } + + //! Destructor. + ~GenericPointer() { + if (nameBuffer_) // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated. + Allocator::Free(tokens_); + RAPIDJSON_DELETE(ownAllocator_); + } + + //! Assignment operator. + GenericPointer& operator=(const GenericPointer& rhs) { + if (this != &rhs) { + // Do not delete ownAllcator + if (nameBuffer_) + Allocator::Free(tokens_); + + tokenCount_ = rhs.tokenCount_; + parseErrorOffset_ = rhs.parseErrorOffset_; + parseErrorCode_ = rhs.parseErrorCode_; + + if (rhs.nameBuffer_) + CopyFromRaw(rhs); // Normally parsed tokens. + else { + tokens_ = rhs.tokens_; // User supplied const tokens. + nameBuffer_ = 0; + } + } + return *this; + } + + //@} + + //!@name Append token + //@{ + + //! Append a token and return a new Pointer + /*! + \param token Token to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const Token& token, Allocator* allocator = 0) const { + GenericPointer r; + r.allocator_ = allocator; + Ch *p = r.CopyFromRaw(*this, 1, token.length + 1); + std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch)); + r.tokens_[tokenCount_].name = p; + r.tokens_[tokenCount_].length = token.length; + r.tokens_[tokenCount_].index = token.index; + return r; + } + + //! Append a name token with length, and return a new Pointer + /*! + \param name Name to be appended. + \param length Length of name. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const Ch* name, SizeType length, Allocator* allocator = 0) const { + Token token = { name, length, kPointerInvalidIndex }; + return Append(token, allocator); + } + + //! Append a name token without length, and return a new Pointer + /*! + \param name Name (const Ch*) to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >), (GenericPointer)) + Append(T* name, Allocator* allocator = 0) const { + return Append(name, StrLen(name), allocator); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Append a name token, and return a new Pointer + /*! + \param name Name to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const std::basic_string& name, Allocator* allocator = 0) const { + return Append(name.c_str(), static_cast(name.size()), allocator); + } +#endif + + //! Append a index token, and return a new Pointer + /*! + \param index Index to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(SizeType index, Allocator* allocator = 0) const { + char buffer[21]; + char* end = sizeof(SizeType) == 4 ? internal::u32toa(index, buffer) : internal::u64toa(index, buffer); + SizeType length = static_cast(end - buffer); + buffer[length] = '\0'; + + if (sizeof(Ch) == 1) { + Token token = { reinterpret_cast(buffer), length, index }; + return Append(token, allocator); + } + else { + Ch name[21]; + for (size_t i = 0; i <= length; i++) + name[i] = buffer[i]; + Token token = { name, length, index }; + return Append(token, allocator); + } + } + + //! Append a token by value, and return a new Pointer + /*! + \param token token to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const ValueType& token, Allocator* allocator = 0) const { + if (token.IsString()) + return Append(token.GetString(), token.GetStringLength(), allocator); + else { + RAPIDJSON_ASSERT(token.IsUint64()); + RAPIDJSON_ASSERT(token.GetUint64() <= SizeType(~0)); + return Append(static_cast(token.GetUint64()), allocator); + } + } + + //!@name Handling Parse Error + //@{ + + //! Check whether this is a valid pointer. + bool IsValid() const { return parseErrorCode_ == kPointerParseErrorNone; } + + //! Get the parsing error offset in code unit. + size_t GetParseErrorOffset() const { return parseErrorOffset_; } + + //! Get the parsing error code. + PointerParseErrorCode GetParseErrorCode() const { return parseErrorCode_; } + + //@} + + //! Get the allocator of this pointer. + Allocator& GetAllocator() { return *allocator_; } + + //!@name Tokens + //@{ + + //! Get the token array (const version only). + const Token* GetTokens() const { return tokens_; } + + //! Get the number of tokens. + size_t GetTokenCount() const { return tokenCount_; } + + //@} + + //!@name Equality/inequality operators + //@{ + + //! Equality operator. + /*! + \note When any pointers are invalid, always returns false. + */ + bool operator==(const GenericPointer& rhs) const { + if (!IsValid() || !rhs.IsValid() || tokenCount_ != rhs.tokenCount_) + return false; + + for (size_t i = 0; i < tokenCount_; i++) { + if (tokens_[i].index != rhs.tokens_[i].index || + tokens_[i].length != rhs.tokens_[i].length || + (tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0)) + { + return false; + } + } + + return true; + } + + //! Inequality operator. + /*! + \note When any pointers are invalid, always returns true. + */ + bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); } + + //@} + + //!@name Stringify + //@{ + + //! Stringify the pointer into string representation. + /*! + \tparam OutputStream Type of output stream. + \param os The output stream. + */ + template + bool Stringify(OutputStream& os) const { + return Stringify(os); + } + + //! Stringify the pointer into URI fragment representation. + /*! + \tparam OutputStream Type of output stream. + \param os The output stream. + */ + template + bool StringifyUriFragment(OutputStream& os) const { + return Stringify(os); + } + + //@} + + //!@name Create value + //@{ + + //! Create a value in a subtree. + /*! + If the value is not exist, it creates all parent values and a JSON Null value. + So it always succeed and return the newly created or existing value. + + Remind that it may change types of parents according to tokens, so it + potentially removes previously stored values. For example, if a document + was an array, and "/foo" is used to create a value, then the document + will be changed to an object, and all existing array elements are lost. + + \param root Root value of a DOM subtree to be resolved. It can be any value other than document root. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \param alreadyExist If non-null, it stores whether the resolved value is already exist. + \return The resolved newly created (a JSON Null value), or already exists value. + */ + ValueType& Create(ValueType& root, typename ValueType::AllocatorType& allocator, bool* alreadyExist = 0) const { + RAPIDJSON_ASSERT(IsValid()); + ValueType* v = &root; + bool exist = true; + for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + if (v->IsArray() && t->name[0] == '-' && t->length == 1) { + v->PushBack(ValueType().Move(), allocator); + v = &((*v)[v->Size() - 1]); + exist = false; + } + else { + if (t->index == kPointerInvalidIndex) { // must be object name + if (!v->IsObject()) + v->SetObject(); // Change to Object + } + else { // object name or array index + if (!v->IsArray() && !v->IsObject()) + v->SetArray(); // Change to Array + } + + if (v->IsArray()) { + if (t->index >= v->Size()) { + v->Reserve(t->index + 1, allocator); + while (t->index >= v->Size()) + v->PushBack(ValueType().Move(), allocator); + exist = false; + } + v = &((*v)[t->index]); + } + else { + typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(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 + exist = false; + } + else + v = &m->value; + } + } + } + + if (alreadyExist) + *alreadyExist = exist; + + return *v; + } + + //! Creates a value in a document. + /*! + \param document A document to be resolved. + \param alreadyExist If non-null, it stores whether the resolved value is already exist. + \return The resolved newly created, or already exists value. + */ + template + ValueType& Create(GenericDocument& document, bool* alreadyExist = 0) const { + return Create(document, document.GetAllocator(), alreadyExist); + } + + //@} + + //!@name Query value + //@{ + + //! Query a value in a subtree. + /*! + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token. + \return Pointer to the value if it can be resolved. Otherwise null. + + \note + There are only 3 situations when a value cannot be resolved: + 1. A value in the path is not an array nor object. + 2. An object value does not contain the token. + 3. A token is out of range of an array value. + + Use unresolvedTokenIndex to retrieve the token index. + */ + ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const { + RAPIDJSON_ASSERT(IsValid()); + ValueType* v = &root; + for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + switch (v->GetType()) { + case kObjectType: + { + typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); + if (m == v->MemberEnd()) + break; + v = &m->value; + } + continue; + case kArrayType: + if (t->index == kPointerInvalidIndex || t->index >= v->Size()) + break; + v = &((*v)[t->index]); + continue; + default: + break; + } + + // Error: unresolved token + if (unresolvedTokenIndex) + *unresolvedTokenIndex = static_cast(t - tokens_); + return 0; + } + return v; + } + + //! Query a const value in a const subtree. + /*! + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \return Pointer to the value if it can be resolved. Otherwise null. + */ + const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const { + return Get(const_cast(root), unresolvedTokenIndex); + } + + //@} + + //!@name Query a value with default + //@{ + + //! Query a value in a subtree with default value. + /*! + Similar to Get(), but if the specified value do not exists, it creates all parents and clone the default value. + So that this function always succeed. + + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param defaultValue Default value to be cloned if the value was not exists. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \see Create() + */ + ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const { + bool alreadyExist; + Value& 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); + return alreadyExist ? v : v.SetString(defaultValue, allocator); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Query a value in a subtree with default std::basic_string. + ValueType& GetWithDefault(ValueType& root, const std::basic_string& defaultValue, typename ValueType::AllocatorType& allocator) const { + bool alreadyExist; + Value& v = Create(root, allocator, &alreadyExist); + return alreadyExist ? v : v.SetString(defaultValue, allocator); + } +#endif + + //! Query a value in a subtree with default primitive value. + /*! + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) + GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const { + return GetWithDefault(root, ValueType(defaultValue).Move(), allocator); + } + + //! Query a value in a document with default value. + template + ValueType& GetWithDefault(GenericDocument& document, const ValueType& defaultValue) const { + return GetWithDefault(document, defaultValue, document.GetAllocator()); + } + + //! Query a value in a document with default null-terminated string. + template + ValueType& GetWithDefault(GenericDocument& document, const Ch* defaultValue) const { + return GetWithDefault(document, defaultValue, document.GetAllocator()); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Query a value in a document with default std::basic_string. + template + ValueType& GetWithDefault(GenericDocument& document, const std::basic_string& defaultValue) const { + return GetWithDefault(document, defaultValue, document.GetAllocator()); + } +#endif + + //! Query a value in a document with default primitive value. + /*! + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) + GetWithDefault(GenericDocument& document, T defaultValue) const { + return GetWithDefault(document, defaultValue, document.GetAllocator()); + } + + //@} + + //!@name Set a value + //@{ + + //! Set a value in a subtree, with move semantics. + /*! + It creates all parents if they are not exist or types are different to the tokens. + So this function always succeeds but potentially remove existing values. + + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param value Value to be set. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \see Create() + */ + ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator) = value; + } + + //! Set a value in a subtree, with copy semantics. + ValueType& Set(ValueType& root, const ValueType& value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator).CopyFrom(value, allocator); + } + + //! Set a null-terminated string in a subtree. + ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator) = ValueType(value, allocator).Move(); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Set a std::basic_string in a subtree. + ValueType& Set(ValueType& root, const std::basic_string& value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator) = ValueType(value, allocator).Move(); + } +#endif + + //! Set a primitive value in a subtree. + /*! + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) + Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator) = ValueType(value).Move(); + } + + //! Set a value in a document, with move semantics. + template + ValueType& Set(GenericDocument& document, ValueType& value) const { + return Create(document) = value; + } + + //! Set a value in a document, with copy semantics. + template + ValueType& Set(GenericDocument& document, const ValueType& value) const { + return Create(document).CopyFrom(value, document.GetAllocator()); + } + + //! Set a null-terminated string in a document. + template + ValueType& Set(GenericDocument& document, const Ch* value) const { + return Create(document) = ValueType(value, document.GetAllocator()).Move(); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Sets a std::basic_string in a document. + template + ValueType& Set(GenericDocument& document, const std::basic_string& value) const { + return Create(document) = ValueType(value, document.GetAllocator()).Move(); + } +#endif + + //! Set a primitive value in a document. + /*! + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) + Set(GenericDocument& document, T value) const { + return Create(document) = value; + } + + //@} + + //!@name Swap a value + //@{ + + //! Swap a value with a value in a subtree. + /*! + It creates all parents if they are not exist or types are different to the tokens. + So this function always succeeds but potentially remove existing values. + + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param value Value to be swapped. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \see Create() + */ + ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator).Swap(value); + } + + //! Swap a value with a value in a document. + template + ValueType& Swap(GenericDocument& document, ValueType& value) const { + return Create(document).Swap(value); + } + + //@} + + //! Erase a value in a subtree. + /*! + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \return Whether the resolved value is found and erased. + + \note Erasing with an empty pointer \c Pointer(""), i.e. the root, always fail and return false. + */ + bool Erase(ValueType& root) const { + RAPIDJSON_ASSERT(IsValid()); + if (tokenCount_ == 0) // Cannot erase the root + return false; + + ValueType* v = &root; + const Token* last = tokens_ + (tokenCount_ - 1); + for (const Token *t = tokens_; t != last; ++t) { + switch (v->GetType()) { + case kObjectType: + { + typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); + if (m == v->MemberEnd()) + return false; + v = &m->value; + } + break; + case kArrayType: + if (t->index == kPointerInvalidIndex || t->index >= v->Size()) + return false; + v = &((*v)[t->index]); + break; + default: + return false; + } + } + + switch (v->GetType()) { + case kObjectType: + return v->EraseMember(GenericStringRef(last->name, last->length)); + case kArrayType: + if (last->index == kPointerInvalidIndex || last->index >= v->Size()) + return false; + v->Erase(v->Begin() + last->index); + return true; + default: + return false; + } + } + +private: + //! Clone the content from rhs to this. + /*! + \param rhs Source pointer. + \param extraToken Extra tokens to be allocated. + \param extraNameBufferSize Extra name buffer size (in number of Ch) to be allocated. + \return Start of non-occupied name buffer, for storing extra names. + */ + Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) { + if (!allocator_) // allocator is independently owned. + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + + size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens + for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t) + nameBufferSize += t->length; + + tokenCount_ = rhs.tokenCount_ + extraToken; + tokens_ = static_cast(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch))); + nameBuffer_ = reinterpret_cast(tokens_ + tokenCount_); + if (rhs.tokenCount_ > 0) { + std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token)); + } + if (nameBufferSize > 0) { + std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch)); + } + + // Adjust pointers to name buffer + std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_; + for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t) + t->name += diff; + + return nameBuffer_ + nameBufferSize; + } + + //! Check whether a character should be percent-encoded. + /*! + According to RFC 3986 2.3 Unreserved Characters. + \param c The character (code unit) to be tested. + */ + bool NeedPercentEncode(Ch c) const { + return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~'); + } + + //! Parse a JSON String or its URI fragment representation into tokens. +#ifndef __clang__ // -Wdocumentation + /*! + \param source Either a JSON Pointer string, or its URI fragment representation. Not need to be null terminated. + \param length Length of the source string. + \note Source cannot be JSON String Representation of JSON Pointer, e.g. In "/\u0000", \u0000 will not be unescaped. + */ +#endif + void Parse(const Ch* source, size_t length) { + RAPIDJSON_ASSERT(source != NULL); + RAPIDJSON_ASSERT(nameBuffer_ == 0); + RAPIDJSON_ASSERT(tokens_ == 0); + + // Create own allocator if user did not supply. + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + + // Count number of '/' as tokenCount + tokenCount_ = 0; + for (const Ch* s = source; s != source + length; s++) + if (*s == '/') + tokenCount_++; + + Token* token = tokens_ = static_cast(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch))); + Ch* name = nameBuffer_ = reinterpret_cast(tokens_ + tokenCount_); + size_t i = 0; + + // Detect if it is a URI fragment + bool uriFragment = false; + if (source[i] == '#') { + uriFragment = true; + i++; + } + + if (i != length && source[i] != '/') { + parseErrorCode_ = kPointerParseErrorTokenMustBeginWithSolidus; + goto error; + } + + while (i < length) { + RAPIDJSON_ASSERT(source[i] == '/'); + i++; // consumes '/' + + token->name = name; + bool isNumber = true; + + while (i < length && source[i] != '/') { + Ch c = source[i]; + if (uriFragment) { + // Decoding percent-encoding for URI fragment + if (c == '%') { + PercentDecodeStream is(&source[i], source + length); + GenericInsituStringStream os(name); + Ch* begin = os.PutBegin(); + if (!Transcoder, EncodingType>().Validate(is, os) || !is.IsValid()) { + parseErrorCode_ = kPointerParseErrorInvalidPercentEncoding; + goto error; + } + size_t len = os.PutEnd(begin); + i += is.Tell() - 1; + if (len == 1) + c = *name; + else { + name += len; + isNumber = false; + i++; + continue; + } + } + else if (NeedPercentEncode(c)) { + parseErrorCode_ = kPointerParseErrorCharacterMustPercentEncode; + goto error; + } + } + + i++; + + // Escaping "~0" -> '~', "~1" -> '/' + if (c == '~') { + if (i < length) { + c = source[i]; + if (c == '0') c = '~'; + else if (c == '1') c = '/'; + else { + parseErrorCode_ = kPointerParseErrorInvalidEscape; + goto error; + } + i++; + } + else { + parseErrorCode_ = kPointerParseErrorInvalidEscape; + goto error; + } + } + + // First check for index: all of characters are digit + if (c < '0' || c > '9') + isNumber = false; + + *name++ = c; + } + token->length = static_cast(name - token->name); + if (token->length == 0) + isNumber = false; + *name++ = '\0'; // Null terminator + + // Second check for index: more than one digit cannot have leading zero + if (isNumber && token->length > 1 && token->name[0] == '0') + isNumber = false; + + // String to SizeType conversion + SizeType n = 0; + if (isNumber) { + for (size_t j = 0; j < token->length; j++) { + SizeType m = n * 10 + static_cast(token->name[j] - '0'); + if (m < n) { // overflow detection + isNumber = false; + break; + } + n = m; + } + } + + token->index = isNumber ? n : kPointerInvalidIndex; + token++; + } + + RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer + parseErrorCode_ = kPointerParseErrorNone; + return; + + error: + Allocator::Free(tokens_); + nameBuffer_ = 0; + tokens_ = 0; + tokenCount_ = 0; + parseErrorOffset_ = i; + return; + } + + //! Stringify to string or URI fragment representation. + /*! + \tparam uriFragment True for stringifying to URI fragment representation. False for string representation. + \tparam OutputStream type of output stream. + \param os The output stream. + */ + template + bool Stringify(OutputStream& os) const { + RAPIDJSON_ASSERT(IsValid()); + + if (uriFragment) + os.Put('#'); + + for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + os.Put('/'); + for (size_t j = 0; j < t->length; j++) { + Ch c = t->name[j]; + if (c == '~') { + os.Put('~'); + os.Put('0'); + } + else if (c == '/') { + os.Put('~'); + os.Put('1'); + } + else if (uriFragment && NeedPercentEncode(c)) { + // Transcode to UTF8 sequence + GenericStringStream source(&t->name[j]); + PercentEncodeStream target(os); + if (!Transcoder >().Validate(source, target)) + return false; + j += source.Tell() - 1; + } + else + os.Put(c); + } + } + return true; + } + + //! A helper stream for decoding a percent-encoded sequence into code unit. + /*! + This stream decodes %XY triplet into code unit (0-255). + If it encounters invalid characters, it sets output code unit as 0 and + mark invalid, and to be checked by IsValid(). + */ + class PercentDecodeStream { + public: + typedef typename ValueType::Ch Ch; + + //! Constructor + /*! + \param source Start of the stream + \param end Past-the-end of the stream. + */ + PercentDecodeStream(const Ch* source, const Ch* end) : src_(source), head_(source), end_(end), valid_(true) {} + + Ch Take() { + if (*src_ != '%' || src_ + 3 > end_) { // %XY triplet + valid_ = false; + return 0; + } + src_++; + Ch c = 0; + for (int j = 0; j < 2; j++) { + c = static_cast(c << 4); + Ch h = *src_; + if (h >= '0' && h <= '9') c = static_cast(c + h - '0'); + else if (h >= 'A' && h <= 'F') c = static_cast(c + h - 'A' + 10); + else if (h >= 'a' && h <= 'f') c = static_cast(c + h - 'a' + 10); + else { + valid_ = false; + return 0; + } + src_++; + } + return c; + } + + size_t Tell() const { return static_cast(src_ - head_); } + bool IsValid() const { return valid_; } + + private: + const Ch* src_; //!< Current read position. + const Ch* head_; //!< Original head of the string. + const Ch* end_; //!< Past-the-end position. + bool valid_; //!< Whether the parsing is valid. + }; + + //! A helper stream to encode character (UTF-8 code unit) into percent-encoded sequence. + template + class PercentEncodeStream { + public: + PercentEncodeStream(OutputStream& os) : os_(os) {} + void Put(char c) { // UTF-8 must be byte + unsigned char u = static_cast(c); + static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + os_.Put('%'); + os_.Put(hexDigits[u >> 4]); + os_.Put(hexDigits[u & 15]); + } + private: + OutputStream& os_; + }; + + Allocator* allocator_; //!< The current allocator. It is either user-supplied or equal to ownAllocator_. + Allocator* ownAllocator_; //!< Allocator owned by this Pointer. + Ch* nameBuffer_; //!< A buffer containing all names in tokens. + Token* tokens_; //!< A list of tokens. + size_t tokenCount_; //!< Number of tokens in tokens_. + size_t parseErrorOffset_; //!< Offset in code unit when parsing fail. + PointerParseErrorCode parseErrorCode_; //!< Parsing error code. +}; + +//! GenericPointer for Value (UTF-8, default allocator). +typedef GenericPointer Pointer; + +//!@name Helper functions for GenericPointer +//@{ + +////////////////////////////////////////////////////////////////////////////// + +template +typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer& pointer, typename T::AllocatorType& a) { + return pointer.Create(root, a); +} + +template +typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Create(root, a); +} + +// No allocator parameter + +template +typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const GenericPointer& pointer) { + return pointer.Create(document); +} + +template +typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) { + return GenericPointer(source, N - 1).Create(document); +} + +////////////////////////////////////////////////////////////////////////////// + +template +typename T::ValueType* GetValueByPointer(T& root, const GenericPointer& pointer, size_t* unresolvedTokenIndex = 0) { + return pointer.Get(root, unresolvedTokenIndex); +} + +template +const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer& pointer, size_t* unresolvedTokenIndex = 0) { + return pointer.Get(root, unresolvedTokenIndex); +} + +template +typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) { + return GenericPointer(source, N - 1).Get(root, unresolvedTokenIndex); +} + +template +const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) { + return GenericPointer(source, N - 1).Get(root, unresolvedTokenIndex); +} + +////////////////////////////////////////////////////////////////////////////// + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const typename T::Ch* defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const std::basic_string& defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, T2 defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string& defaultValue, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); +} + +// No allocator parameter + +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::ValueType& defaultValue) { + return pointer.GetWithDefault(document, defaultValue); +} + +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::Ch* defaultValue) { + return pointer.GetWithDefault(document, defaultValue); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, const std::basic_string& defaultValue) { + return pointer.GetWithDefault(document, defaultValue); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) +GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, T2 defaultValue) { + return pointer.GetWithDefault(document, defaultValue); +} + +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) { + return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); +} + +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) { + return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string& defaultValue) { + return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) +GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) { + return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); +} + +////////////////////////////////////////////////////////////////////////////// + +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const typename T::ValueType& value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const typename T::Ch* value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const std::basic_string& value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +SetValueByPointer(T& root, const GenericPointer& pointer, T2 value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Set(root, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Set(root, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Set(root, value, a); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string& value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Set(root, value, a); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Set(root, value, a); +} + +// No allocator parameter + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, typename DocumentType::ValueType& value) { + return pointer.Set(document, value); +} + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::ValueType& value) { + return pointer.Set(document, value); +} + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::Ch* value) { + return pointer.Set(document, value); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, const std::basic_string& value) { + return pointer.Set(document, value); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) +SetValueByPointer(DocumentType& document, const GenericPointer& pointer, T2 value) { + return pointer.Set(document, value); +} + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) { + return GenericPointer(source, N - 1).Set(document, value); +} + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& value) { + return GenericPointer(source, N - 1).Set(document, value); +} + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* value) { + return GenericPointer(source, N - 1).Set(document, value); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string& value) { + return GenericPointer(source, N - 1).Set(document, value); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) +SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) { + return GenericPointer(source, N - 1).Set(document, value); +} + +////////////////////////////////////////////////////////////////////////////// + +template +typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { + return pointer.Swap(root, value, a); +} + +template +typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Swap(root, value, a); +} + +template +typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const GenericPointer& pointer, typename DocumentType::ValueType& value) { + return pointer.Swap(document, value); +} + +template +typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) { + return GenericPointer(source, N - 1).Swap(document, value); +} + +////////////////////////////////////////////////////////////////////////////// + +template +bool EraseValueByPointer(T& root, const GenericPointer& pointer) { + return pointer.Erase(root); +} + +template +bool EraseValueByPointer(T& root, const CharType(&source)[N]) { + return GenericPointer(source, N - 1).Erase(root); +} + +//@} + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_POINTER_H_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/prettywriter.h b/Externals/discord-rpc/thirdparty/include/rapidjson/prettywriter.h new file mode 100644 index 0000000000..0dcb0fee92 --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/prettywriter.h @@ -0,0 +1,255 @@ +// 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_PRETTYWRITER_H_ +#define RAPIDJSON_PRETTYWRITER_H_ + +#include "writer.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Combination of PrettyWriter format flags. +/*! \see PrettyWriter::SetFormatOptions + */ +enum PrettyFormatOptions { + kFormatDefault = 0, //!< Default pretty formatting. + kFormatSingleLineArray = 1 //!< Format arrays on a single line. +}; + +//! Writer with indentation and spacing. +/*! + \tparam OutputStream Type of ouptut os. + \tparam SourceEncoding Encoding of source string. + \tparam TargetEncoding Encoding of output stream. + \tparam StackAllocator Type of allocator for allocating memory of stack. +*/ +template, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags> +class PrettyWriter : public Writer { +public: + typedef Writer Base; + typedef typename Base::Ch Ch; + + //! Constructor + /*! \param os Output stream. + \param allocator User supplied allocator. If it is null, it will create a private one. + \param levelDepth Initial capacity of stack. + */ + explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : + Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {} + + + explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : + Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {} + + //! Set custom indentation. + /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r'). + \param indentCharCount Number of indent characters for each indentation level. + \note The default indentation is 4 spaces. + */ + PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) { + RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r'); + indentChar_ = indentChar; + indentCharCount_ = indentCharCount; + return *this; + } + + //! Set pretty writer formatting options. + /*! \param options Formatting options. + */ + PrettyWriter& SetFormatOptions(PrettyFormatOptions options) { + formatOptions_ = options; + return *this; + } + + /*! @name Implementation of Handler + \see Handler + */ + //@{ + + bool Null() { PrettyPrefix(kNullType); return Base::WriteNull(); } + bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); } + bool Int(int i) { PrettyPrefix(kNumberType); return Base::WriteInt(i); } + bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::WriteUint(u); } + bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); } + bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); } + bool Double(double d) { PrettyPrefix(kNumberType); return Base::WriteDouble(d); } + + bool RawNumber(const Ch* str, SizeType length, bool copy = false) { + (void)copy; + PrettyPrefix(kNumberType); + return Base::WriteString(str, length); + } + + bool String(const Ch* str, SizeType length, bool copy = false) { + (void)copy; + PrettyPrefix(kStringType); + return Base::WriteString(str, length); + } + +#if RAPIDJSON_HAS_STDSTRING + bool String(const std::basic_string& str) { + return String(str.data(), SizeType(str.size())); + } +#endif + + bool StartObject() { + PrettyPrefix(kObjectType); + new (Base::level_stack_.template Push()) typename Base::Level(false); + return Base::WriteStartObject(); + } + + bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } + +#if RAPIDJSON_HAS_STDSTRING + bool Key(const std::basic_string& str) { + return Key(str.data(), SizeType(str.size())); + } +#endif + + bool EndObject(SizeType memberCount = 0) { + (void)memberCount; + RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); + RAPIDJSON_ASSERT(!Base::level_stack_.template Top()->inArray); + bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; + + if (!empty) { + Base::os_->Put('\n'); + WriteIndent(); + } + bool ret = Base::WriteEndObject(); + (void)ret; + RAPIDJSON_ASSERT(ret == true); + if (Base::level_stack_.Empty()) // end of json text + Base::os_->Flush(); + return true; + } + + bool StartArray() { + PrettyPrefix(kArrayType); + new (Base::level_stack_.template Push()) typename Base::Level(true); + return Base::WriteStartArray(); + } + + bool EndArray(SizeType memberCount = 0) { + (void)memberCount; + RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); + RAPIDJSON_ASSERT(Base::level_stack_.template Top()->inArray); + bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; + + if (!empty && !(formatOptions_ & kFormatSingleLineArray)) { + Base::os_->Put('\n'); + WriteIndent(); + } + bool ret = Base::WriteEndArray(); + (void)ret; + RAPIDJSON_ASSERT(ret == true); + if (Base::level_stack_.Empty()) // end of json text + Base::os_->Flush(); + return true; + } + + //@} + + /*! @name Convenience extensions */ + //@{ + + //! Simpler but slower overload. + bool String(const Ch* str) { return String(str, internal::StrLen(str)); } + bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } + + //@} + + //! Write a raw JSON value. + /*! + For user to write a stringified JSON as a value. + + \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range. + \param length Length of the json. + \param type Type of the root of json. + \note When using PrettyWriter::RawValue(), the result json may not be indented correctly. + */ + bool RawValue(const Ch* json, size_t length, Type type) { PrettyPrefix(type); return Base::WriteRawValue(json, length); } + +protected: + void PrettyPrefix(Type type) { + (void)type; + if (Base::level_stack_.GetSize() != 0) { // this value is not at root + typename Base::Level* level = Base::level_stack_.template Top(); + + if (level->inArray) { + if (level->valueCount > 0) { + Base::os_->Put(','); // add comma if it is not the first element in array + if (formatOptions_ & kFormatSingleLineArray) + Base::os_->Put(' '); + } + + if (!(formatOptions_ & kFormatSingleLineArray)) { + Base::os_->Put('\n'); + WriteIndent(); + } + } + else { // in object + if (level->valueCount > 0) { + if (level->valueCount % 2 == 0) { + Base::os_->Put(','); + Base::os_->Put('\n'); + } + else { + Base::os_->Put(':'); + Base::os_->Put(' '); + } + } + else + Base::os_->Put('\n'); + + if (level->valueCount % 2 == 0) + WriteIndent(); + } + if (!level->inArray && level->valueCount % 2 == 0) + RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name + level->valueCount++; + } + else { + RAPIDJSON_ASSERT(!Base::hasRoot_); // Should only has one and only one root. + Base::hasRoot_ = true; + } + } + + void WriteIndent() { + size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_; + PutN(*Base::os_, static_cast(indentChar_), count); + } + + Ch indentChar_; + unsigned indentCharCount_; + PrettyFormatOptions formatOptions_; + +private: + // Prohibit copy constructor & assignment operator. + PrettyWriter(const PrettyWriter&); + PrettyWriter& operator=(const PrettyWriter&); +}; + +RAPIDJSON_NAMESPACE_END + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/rapidjson.h b/Externals/discord-rpc/thirdparty/include/rapidjson/rapidjson.h new file mode 100644 index 0000000000..053b2ce43f --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/rapidjson.h @@ -0,0 +1,615 @@ +// 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_RAPIDJSON_H_ +#define RAPIDJSON_RAPIDJSON_H_ + +/*!\file rapidjson.h + \brief common definitions and configuration + + \see RAPIDJSON_CONFIG + */ + +/*! \defgroup RAPIDJSON_CONFIG RapidJSON configuration + \brief Configuration macros for library features + + 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 + preprocessor macros at compile-time. + + Some additional customization is available in the \ref RAPIDJSON_ERRORS APIs. + + \note These macros should be given on the compiler command-line + (where applicable) to avoid inconsistent values when compiling + different translation units of a single application. + */ + +#include // malloc(), realloc(), free(), size_t +#include // memset(), memcpy(), memmove(), memcmp() + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_VERSION_STRING +// +// ALWAYS synchronize the following 3 macros with corresponding variables in /CMakeLists.txt. +// + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +// token stringification +#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x) +#define RAPIDJSON_DO_STRINGIFY(x) #x +//!@endcond + +/*! \def RAPIDJSON_MAJOR_VERSION + \ingroup RAPIDJSON_CONFIG + \brief Major version of RapidJSON in integer. +*/ +/*! \def RAPIDJSON_MINOR_VERSION + \ingroup RAPIDJSON_CONFIG + \brief Minor version of RapidJSON in integer. +*/ +/*! \def RAPIDJSON_PATCH_VERSION + \ingroup RAPIDJSON_CONFIG + \brief Patch version of RapidJSON in integer. +*/ +/*! \def RAPIDJSON_VERSION_STRING + \ingroup RAPIDJSON_CONFIG + \brief Version of RapidJSON in ".." string format. +*/ +#define RAPIDJSON_MAJOR_VERSION 1 +#define RAPIDJSON_MINOR_VERSION 1 +#define RAPIDJSON_PATCH_VERSION 0 +#define RAPIDJSON_VERSION_STRING \ + RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION) + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NAMESPACE_(BEGIN|END) +/*! \def RAPIDJSON_NAMESPACE + \ingroup RAPIDJSON_CONFIG + \brief provide custom rapidjson namespace + + In order to avoid symbol clashes and/or "One Definition Rule" errors + between multiple inclusions of (different versions of) RapidJSON in + a single binary, users can customize the name of the main RapidJSON + namespace. + + In case of a single nesting level, defining \c RAPIDJSON_NAMESPACE + to a custom name (e.g. \c MyRapidJSON) is sufficient. If multiple + levels are needed, both \ref RAPIDJSON_NAMESPACE_BEGIN and \ref + RAPIDJSON_NAMESPACE_END need to be defined as well: + + \code + // in some .cpp file + #define RAPIDJSON_NAMESPACE my::rapidjson + #define RAPIDJSON_NAMESPACE_BEGIN namespace my { namespace rapidjson { + #define RAPIDJSON_NAMESPACE_END } } + #include "rapidjson/..." + \endcode + + \see rapidjson + */ +/*! \def RAPIDJSON_NAMESPACE_BEGIN + \ingroup RAPIDJSON_CONFIG + \brief provide custom rapidjson namespace (opening expression) + \see RAPIDJSON_NAMESPACE +*/ +/*! \def RAPIDJSON_NAMESPACE_END + \ingroup RAPIDJSON_CONFIG + \brief provide custom rapidjson namespace (closing expression) + \see RAPIDJSON_NAMESPACE +*/ +#ifndef RAPIDJSON_NAMESPACE +#define RAPIDJSON_NAMESPACE rapidjson +#endif +#ifndef RAPIDJSON_NAMESPACE_BEGIN +#define RAPIDJSON_NAMESPACE_BEGIN namespace RAPIDJSON_NAMESPACE { +#endif +#ifndef RAPIDJSON_NAMESPACE_END +#define RAPIDJSON_NAMESPACE_END } +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_HAS_STDSTRING + +#ifndef RAPIDJSON_HAS_STDSTRING +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation +#else +#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default +#endif +/*! \def RAPIDJSON_HAS_STDSTRING + \ingroup RAPIDJSON_CONFIG + \brief Enable RapidJSON support for \c std::string + + By defining this preprocessor symbol to \c 1, several convenience functions for using + \ref rapidjson::GenericValue with \c std::string are enabled, especially + for construction and comparison. + + \hideinitializer +*/ +#endif // !defined(RAPIDJSON_HAS_STDSTRING) + +#if RAPIDJSON_HAS_STDSTRING +#include +#endif // RAPIDJSON_HAS_STDSTRING + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NO_INT64DEFINE + +/*! \def RAPIDJSON_NO_INT64DEFINE + \ingroup RAPIDJSON_CONFIG + \brief Use external 64-bit integer types. + + RapidJSON requires the 64-bit integer types \c int64_t and \c uint64_t types + to be available at global scope. + + If users have their own definition, define RAPIDJSON_NO_INT64DEFINE to + prevent RapidJSON from defining its own types. +*/ +#ifndef RAPIDJSON_NO_INT64DEFINE +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#if defined(_MSC_VER) && (_MSC_VER < 1800) // Visual Studio 2013 +#include "msinttypes/stdint.h" +#include "msinttypes/inttypes.h" +#else +// Other compilers should have this. +#include +#include +#endif +//!@endcond +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_NO_INT64DEFINE +#endif +#endif // RAPIDJSON_NO_INT64TYPEDEF + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_FORCEINLINE + +#ifndef RAPIDJSON_FORCEINLINE +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#if defined(_MSC_VER) && defined(NDEBUG) +#define RAPIDJSON_FORCEINLINE __forceinline +#elif defined(__GNUC__) && __GNUC__ >= 4 && defined(NDEBUG) +#define RAPIDJSON_FORCEINLINE __attribute__((always_inline)) +#else +#define RAPIDJSON_FORCEINLINE +#endif +//!@endcond +#endif // RAPIDJSON_FORCEINLINE + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ENDIAN +#define RAPIDJSON_LITTLEENDIAN 0 //!< Little endian machine +#define RAPIDJSON_BIGENDIAN 1 //!< Big endian machine + +//! Endianness of the machine. +/*! + \def RAPIDJSON_ENDIAN + \ingroup RAPIDJSON_CONFIG + + GCC 4.6 provided macro for detecting endianness of the target machine. But other + compilers may not have this. User can define RAPIDJSON_ENDIAN to either + \ref RAPIDJSON_LITTLEENDIAN or \ref RAPIDJSON_BIGENDIAN. + + Default detection implemented with reference to + \li https://gcc.gnu.org/onlinedocs/gcc-4.6.0/cpp/Common-Predefined-Macros.html + \li http://www.boost.org/doc/libs/1_42_0/boost/detail/endian.hpp +*/ +#ifndef RAPIDJSON_ENDIAN +// Detect with GCC 4.6's macro +# ifdef __BYTE_ORDER__ +# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +# else +# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN. +# endif // __BYTE_ORDER__ +// Detect with GLIBC's endian.h +# elif defined(__GLIBC__) +# include +# if (__BYTE_ORDER == __LITTLE_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif (__BYTE_ORDER == __BIG_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +# else +# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN. +# endif // __GLIBC__ +// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro +# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +// Detect with architecture macros +# elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__) +# 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) +# 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. +# endif +#endif // RAPIDJSON_ENDIAN + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_64BIT + +//! Whether using 64-bit architecture +#ifndef RAPIDJSON_64BIT +#if defined(__LP64__) || (defined(__x86_64__) && defined(__ILP32__)) || defined(_WIN64) || defined(__EMSCRIPTEN__) +#define RAPIDJSON_64BIT 1 +#else +#define RAPIDJSON_64BIT 0 +#endif +#endif // RAPIDJSON_64BIT + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ALIGN + +//! Data alignment of the machine. +/*! \ingroup RAPIDJSON_CONFIG + \param x pointer to align + + Some machines require strict data alignment. Currently the default uses 4 bytes + alignment on 32-bit platforms and 8 bytes alignment for 64-bit platforms. + User can customize by defining the RAPIDJSON_ALIGN function macro. +*/ +#ifndef RAPIDJSON_ALIGN +#if RAPIDJSON_64BIT == 1 +#define RAPIDJSON_ALIGN(x) (((x) + static_cast(7u)) & ~static_cast(7u)) +#else +#define RAPIDJSON_ALIGN(x) (((x) + 3u) & ~3u) +#endif +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_UINT64_C2 + +//! Construct a 64-bit literal by a pair of 32-bit integer. +/*! + 64-bit literal with or without ULL suffix is prone to compiler warnings. + UINT64_C() is C macro which cause compilation problems. + Use this macro to define 64-bit constants by a pair of 32-bit integer. +*/ +#ifndef RAPIDJSON_UINT64_C2 +#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast(high32) << 32) | static_cast(low32)) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_48BITPOINTER_OPTIMIZATION + +//! Use only lower 48-bit address for some pointers. +/*! + \ingroup RAPIDJSON_CONFIG + + This optimization uses the fact that current X86-64 architecture only implement lower 48-bit virtual address. + The higher 16-bit can be used for storing other data. + \c GenericValue uses this optimization to reduce its size form 24 bytes to 16 bytes in 64-bit architecture. +*/ +#ifndef RAPIDJSON_48BITPOINTER_OPTIMIZATION +#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64) +#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 1 +#else +#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 0 +#endif +#endif // RAPIDJSON_48BITPOINTER_OPTIMIZATION + +#if RAPIDJSON_48BITPOINTER_OPTIMIZATION == 1 +#if RAPIDJSON_64BIT != 1 +#error RAPIDJSON_48BITPOINTER_OPTIMIZATION can only be set to 1 when RAPIDJSON_64BIT=1 +#endif +#define RAPIDJSON_SETPOINTER(type, p, x) (p = reinterpret_cast((reinterpret_cast(p) & static_cast(RAPIDJSON_UINT64_C2(0xFFFF0000, 0x00000000))) | reinterpret_cast(reinterpret_cast(x)))) +#define RAPIDJSON_GETPOINTER(type, p) (reinterpret_cast(reinterpret_cast(p) & static_cast(RAPIDJSON_UINT64_C2(0x0000FFFF, 0xFFFFFFFF)))) +#else +#define RAPIDJSON_SETPOINTER(type, p, x) (p = (x)) +#define RAPIDJSON_GETPOINTER(type, p) (p) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD + +/*! \def RAPIDJSON_SIMD + \ingroup RAPIDJSON_CONFIG + \brief Enable SSE2/SSE4.2 optimization. + + RapidJSON supports optimized implementations for some parsing operations + based on the SSE2 or SSE4.2 SIMD extensions on modern Intel-compatible + processors. + + To enable these optimizations, two different symbols can be defined; + \code + // Enable SSE2 optimization. + #define RAPIDJSON_SSE2 + + // Enable SSE4.2 optimization. + #define RAPIDJSON_SSE42 + \endcode + + \c RAPIDJSON_SSE42 takes precedence, 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) +#define RAPIDJSON_SIMD +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NO_SIZETYPEDEFINE + +#ifndef RAPIDJSON_NO_SIZETYPEDEFINE +/*! \def RAPIDJSON_NO_SIZETYPEDEFINE + \ingroup RAPIDJSON_CONFIG + \brief User-provided \c SizeType definition. + + In order to avoid using 32-bit size types for indexing strings and arrays, + define this preprocessor symbol and provide the type rapidjson::SizeType + before including RapidJSON: + \code + #define RAPIDJSON_NO_SIZETYPEDEFINE + namespace rapidjson { typedef ::std::size_t SizeType; } + #include "rapidjson/..." + \endcode + + \see rapidjson::SizeType +*/ +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_NO_SIZETYPEDEFINE +#endif +RAPIDJSON_NAMESPACE_BEGIN +//! Size type (for string lengths, array sizes, etc.) +/*! RapidJSON uses 32-bit array/string indices even on 64-bit platforms, + instead of using \c size_t. Users may override the SizeType by defining + \ref RAPIDJSON_NO_SIZETYPEDEFINE. +*/ +typedef unsigned SizeType; +RAPIDJSON_NAMESPACE_END +#endif + +// always import std::size_t to rapidjson namespace +RAPIDJSON_NAMESPACE_BEGIN +using std::size_t; +RAPIDJSON_NAMESPACE_END + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ASSERT + +//! Assertion. +/*! \ingroup RAPIDJSON_CONFIG + By default, rapidjson uses C \c assert() for internal assertions. + User can override it by defining RAPIDJSON_ASSERT(x) macro. + + \note Parsing errors are handled and can be customized by the + \ref RAPIDJSON_ERRORS APIs. +*/ +#ifndef RAPIDJSON_ASSERT +#include +#define RAPIDJSON_ASSERT(x) assert(x) +#endif // RAPIDJSON_ASSERT + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_STATIC_ASSERT + +// Adopt from boost +#ifndef RAPIDJSON_STATIC_ASSERT +#ifndef __clang__ +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#endif +RAPIDJSON_NAMESPACE_BEGIN +template struct STATIC_ASSERTION_FAILURE; +template <> struct STATIC_ASSERTION_FAILURE { enum { value = 1 }; }; +template 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__) +#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused)) +#else +#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE +#endif +#ifndef __clang__ +//!@endcond +#endif + +/*! \def RAPIDJSON_STATIC_ASSERT + \brief (Internal) macro to check for conditions at compile-time + \param x compile-time condition + \hideinitializer + */ +#define RAPIDJSON_STATIC_ASSERT(x) \ + typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \ + sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE)> \ + RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_LIKELY, RAPIDJSON_UNLIKELY + +//! Compiler branching hint for expression with high probability to be true. +/*! + \ingroup RAPIDJSON_CONFIG + \param x Boolean expression likely to be true. +*/ +#ifndef RAPIDJSON_LIKELY +#if defined(__GNUC__) || defined(__clang__) +#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1) +#else +#define RAPIDJSON_LIKELY(x) (x) +#endif +#endif + +//! Compiler branching hint for expression with low probability to be true. +/*! + \ingroup RAPIDJSON_CONFIG + \param x Boolean expression unlikely to be true. +*/ +#ifndef RAPIDJSON_UNLIKELY +#if defined(__GNUC__) || defined(__clang__) +#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0) +#else +#define RAPIDJSON_UNLIKELY(x) (x) +#endif +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Helpers + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN + +#define RAPIDJSON_MULTILINEMACRO_BEGIN do { +#define RAPIDJSON_MULTILINEMACRO_END \ +} while((void)0, 0) + +// adopted from Boost +#define RAPIDJSON_VERSION_CODE(x,y,z) \ + (((x)*100000) + ((y)*100) + (z)) + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF + +#if defined(__GNUC__) +#define RAPIDJSON_GNUC \ + RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__) +#endif + +#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,2,0)) + +#define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x)) +#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x) +#define RAPIDJSON_DIAG_OFF(x) \ + RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W,x))) + +// push/pop support in Clang and GCC>=4.6 +#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) +#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push) +#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop) +#else // GCC >= 4.2, < 4.6 +#define RAPIDJSON_DIAG_PUSH /* ignored */ +#define RAPIDJSON_DIAG_POP /* ignored */ +#endif + +#elif defined(_MSC_VER) + +// pragma (MSVC specific) +#define RAPIDJSON_PRAGMA(x) __pragma(x) +#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(warning(x)) + +#define RAPIDJSON_DIAG_OFF(x) RAPIDJSON_DIAG_PRAGMA(disable: x) +#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push) +#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop) + +#else + +#define RAPIDJSON_DIAG_OFF(x) /* ignored */ +#define RAPIDJSON_DIAG_PUSH /* ignored */ +#define RAPIDJSON_DIAG_POP /* ignored */ + +#endif // RAPIDJSON_DIAG_* + +/////////////////////////////////////////////////////////////////////////////// +// C++11 features + +#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS +#if defined(__clang__) +#if __has_feature(cxx_rvalue_references) && \ + (defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306) +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 +#else +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0 +#endif +#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ + (defined(_MSC_VER) && _MSC_VER >= 1600) + +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 +#else +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0 +#endif +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + +#ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT +#if defined(__clang__) +#define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept) +#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) +// (defined(_MSC_VER) && _MSC_VER >= ????) // not yet supported +#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1 +#else +#define RAPIDJSON_HAS_CXX11_NOEXCEPT 0 +#endif +#endif +#if RAPIDJSON_HAS_CXX11_NOEXCEPT +#define RAPIDJSON_NOEXCEPT noexcept +#else +#define RAPIDJSON_NOEXCEPT /* noexcept */ +#endif // RAPIDJSON_HAS_CXX11_NOEXCEPT + +// no automatic detection, yet +#ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS +#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0 +#endif + +#ifndef RAPIDJSON_HAS_CXX11_RANGE_FOR +#if defined(__clang__) +#define RAPIDJSON_HAS_CXX11_RANGE_FOR __has_feature(cxx_range_for) +#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ + (defined(_MSC_VER) && _MSC_VER >= 1700) +#define RAPIDJSON_HAS_CXX11_RANGE_FOR 1 +#else +#define RAPIDJSON_HAS_CXX11_RANGE_FOR 0 +#endif +#endif // RAPIDJSON_HAS_CXX11_RANGE_FOR + +//!@endcond + +/////////////////////////////////////////////////////////////////////////////// +// new/delete + +#ifndef RAPIDJSON_NEW +///! customization point for global \c new +#define RAPIDJSON_NEW(x) new x +#endif +#ifndef RAPIDJSON_DELETE +///! customization point for global \c delete +#define RAPIDJSON_DELETE(x) delete x +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Type + +/*! \namespace rapidjson + \brief main RapidJSON namespace + \see RAPIDJSON_NAMESPACE +*/ +RAPIDJSON_NAMESPACE_BEGIN + +//! Type of JSON value +enum Type { + kNullType = 0, //!< null + kFalseType = 1, //!< false + kTrueType = 2, //!< true + kObjectType = 3, //!< object + kArrayType = 4, //!< array + kStringType = 5, //!< string + kNumberType = 6 //!< number +}; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/reader.h b/Externals/discord-rpc/thirdparty/include/rapidjson/reader.h new file mode 100644 index 0000000000..19f8849b14 --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/reader.h @@ -0,0 +1,1879 @@ +// 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_READER_H_ +#define RAPIDJSON_READER_H_ + +/*! \file reader.h */ + +#include "allocators.h" +#include "stream.h" +#include "encodedstream.h" +#include "internal/meta.h" +#include "internal/stack.h" +#include "internal/strtod.h" +#include + +#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER) +#include +#pragma intrinsic(_BitScanForward) +#endif +#ifdef RAPIDJSON_SSE42 +#include +#elif defined(RAPIDJSON_SSE2) +#include +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +RAPIDJSON_DIAG_OFF(4702) // unreachable code +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(old-style-cast) +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(switch-enum) +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#define RAPIDJSON_NOTHING /* deliberately empty */ +#ifndef RAPIDJSON_PARSE_ERROR_EARLY_RETURN +#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN(value) \ + RAPIDJSON_MULTILINEMACRO_BEGIN \ + if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \ + RAPIDJSON_MULTILINEMACRO_END +#endif +#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID \ + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING) +//!@endcond + +/*! \def RAPIDJSON_PARSE_ERROR_NORETURN + \ingroup RAPIDJSON_ERRORS + \brief Macro to indicate a parse error. + \param parseErrorCode \ref rapidjson::ParseErrorCode of the error + \param offset position of the error in JSON input (\c size_t) + + This macros can be used as a customization point for the internal + error handling mechanism of RapidJSON. + + A common usage model is to throw an exception instead of requiring the + caller to explicitly check the \ref rapidjson::GenericReader::Parse's + return value: + + \code + #define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode,offset) \ + throw ParseException(parseErrorCode, #parseErrorCode, offset) + + #include // std::runtime_error + #include "rapidjson/error/error.h" // rapidjson::ParseResult + + struct ParseException : std::runtime_error, rapidjson::ParseResult { + ParseException(rapidjson::ParseErrorCode code, const char* msg, size_t offset) + : std::runtime_error(msg), ParseResult(code, offset) {} + }; + + #include "rapidjson/reader.h" + \endcode + + \see RAPIDJSON_PARSE_ERROR, rapidjson::GenericReader::Parse + */ +#ifndef RAPIDJSON_PARSE_ERROR_NORETURN +#define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset) \ + RAPIDJSON_MULTILINEMACRO_BEGIN \ + RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \ + SetParseError(parseErrorCode, offset); \ + RAPIDJSON_MULTILINEMACRO_END +#endif + +/*! \def RAPIDJSON_PARSE_ERROR + \ingroup RAPIDJSON_ERRORS + \brief (Internal) macro to indicate and handle a parse error. + \param parseErrorCode \ref rapidjson::ParseErrorCode of the error + \param offset position of the error in JSON input (\c size_t) + + Invokes RAPIDJSON_PARSE_ERROR_NORETURN and stops the parsing. + + \see RAPIDJSON_PARSE_ERROR_NORETURN + \hideinitializer + */ +#ifndef RAPIDJSON_PARSE_ERROR +#define RAPIDJSON_PARSE_ERROR(parseErrorCode, offset) \ + RAPIDJSON_MULTILINEMACRO_BEGIN \ + RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \ + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \ + RAPIDJSON_MULTILINEMACRO_END +#endif + +#include "error/error.h" // ParseErrorCode, ParseResult + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// ParseFlag + +/*! \def RAPIDJSON_PARSE_DEFAULT_FLAGS + \ingroup RAPIDJSON_CONFIG + \brief User-defined kParseDefaultFlags definition. + + User can define this as any \c ParseFlag combinations. +*/ +#ifndef RAPIDJSON_PARSE_DEFAULT_FLAGS +#define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseNoFlags +#endif + +//! Combination of parseFlags +/*! \see Reader::Parse, Document::Parse, Document::ParseInsitu, Document::ParseStream + */ +enum ParseFlag { + kParseNoFlags = 0, //!< No flags are set. + kParseInsituFlag = 1, //!< In-situ(destructive) parsing. + kParseValidateEncodingFlag = 2, //!< Validate encoding of JSON strings. + kParseIterativeFlag = 4, //!< Iterative(constant complexity in terms of function call stack size) parsing. + kParseStopWhenDoneFlag = 8, //!< After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error. + kParseFullPrecisionFlag = 16, //!< Parse number in full precision (but slower). + kParseCommentsFlag = 32, //!< Allow one-line (//) and multi-line (/**/) comments. + 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. + kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS +}; + +/////////////////////////////////////////////////////////////////////////////// +// Handler + +/*! \class rapidjson::Handler + \brief Concept for receiving events from GenericReader upon parsing. + The functions return true if no error occurs. If they return false, + the event publisher should terminate the process. +\code +concept Handler { + typename Ch; + + bool Null(); + bool Bool(bool b); + bool Int(int i); + bool Uint(unsigned i); + bool Int64(int64_t i); + bool Uint64(uint64_t i); + bool Double(double d); + /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length) + bool RawNumber(const Ch* str, SizeType length, bool copy); + bool String(const Ch* str, SizeType length, bool copy); + bool StartObject(); + bool Key(const Ch* str, SizeType length, bool copy); + bool EndObject(SizeType memberCount); + bool StartArray(); + bool EndArray(SizeType elementCount); +}; +\endcode +*/ +/////////////////////////////////////////////////////////////////////////////// +// BaseReaderHandler + +//! Default implementation of Handler. +/*! This can be used as base class of any reader handler. + \note implements Handler concept +*/ +template, typename Derived = void> +struct BaseReaderHandler { + typedef typename Encoding::Ch Ch; + + typedef typename internal::SelectIf, BaseReaderHandler, Derived>::Type Override; + + bool Default() { return true; } + bool Null() { return static_cast(*this).Default(); } + bool Bool(bool) { return static_cast(*this).Default(); } + bool Int(int) { return static_cast(*this).Default(); } + bool Uint(unsigned) { return static_cast(*this).Default(); } + bool Int64(int64_t) { return static_cast(*this).Default(); } + bool Uint64(uint64_t) { return static_cast(*this).Default(); } + bool Double(double) { return static_cast(*this).Default(); } + /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length) + bool RawNumber(const Ch* str, SizeType len, bool copy) { return static_cast(*this).String(str, len, copy); } + bool String(const Ch*, SizeType, bool) { return static_cast(*this).Default(); } + bool StartObject() { return static_cast(*this).Default(); } + bool Key(const Ch* str, SizeType len, bool copy) { return static_cast(*this).String(str, len, copy); } + bool EndObject(SizeType) { return static_cast(*this).Default(); } + bool StartArray() { return static_cast(*this).Default(); } + bool EndArray(SizeType) { return static_cast(*this).Default(); } +}; + +/////////////////////////////////////////////////////////////////////////////// +// StreamLocalCopy + +namespace internal { + +template::copyOptimization> +class StreamLocalCopy; + +//! Do copy optimization. +template +class StreamLocalCopy { +public: + StreamLocalCopy(Stream& original) : s(original), original_(original) {} + ~StreamLocalCopy() { original_ = s; } + + Stream s; + +private: + StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */; + + Stream& original_; +}; + +//! Keep reference. +template +class StreamLocalCopy { +public: + StreamLocalCopy(Stream& original) : s(original) {} + + Stream& s; + +private: + StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */; +}; + +} // namespace internal + +/////////////////////////////////////////////////////////////////////////////// +// SkipWhitespace + +//! Skip the JSON white spaces in a stream. +/*! \param is A input stream for skipping white spaces. + \note This function has SSE2/SSE4.2 specialization. +*/ +template +void SkipWhitespace(InputStream& is) { + internal::StreamLocalCopy copy(is); + InputStream& s(copy.s); + + typename InputStream::Ch c; + while ((c = s.Peek()) == ' ' || c == '\n' || c == '\r' || c == '\t') + s.Take(); +} + +inline const char* SkipWhitespace(const char* p, const char* end) { + while (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + ++p; + return p; +} + +#ifdef RAPIDJSON_SSE42 +//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once. +inline const char *SkipWhitespace_SIMD(const char* p) { + // Fast return for single non-whitespace + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // 16-byte align to the next boundary + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // The rest of string using SIMD + static const char whitespace[16] = " \n\r\t"; + const __m128i w = _mm_loadu_si128(reinterpret_cast(&whitespace[0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const int r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY)); + if (r != 0) { // some of characters is non-whitespace +#ifdef _MSC_VER // Find the index of first non-whitespace + unsigned long offset; + _BitScanForward(&offset, r); + return p + offset; +#else + return p + __builtin_ffs(r) - 1; +#endif + } + } +} + +inline const char *SkipWhitespace_SIMD(const char* p, const char* end) { + // Fast return for single non-whitespace + if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + ++p; + else + return p; + + // The middle of string using SIMD + static const char whitespace[16] = " \n\r\t"; + const __m128i w = _mm_loadu_si128(reinterpret_cast(&whitespace[0])); + + for (; p <= end - 16; p += 16) { + const __m128i s = _mm_loadu_si128(reinterpret_cast(p)); + const int r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY)); + if (r != 0) { // some of characters is non-whitespace +#ifdef _MSC_VER // Find the index of first non-whitespace + unsigned long offset; + _BitScanForward(&offset, r); + return p + offset; +#else + return p + __builtin_ffs(r) - 1; +#endif + } + } + + return SkipWhitespace(p, end); +} + +#elif defined(RAPIDJSON_SSE2) + +//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once. +inline const char *SkipWhitespace_SIMD(const char* p) { + // Fast return for single non-whitespace + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // 16-byte align to the next boundary + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // The rest of string + #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c } + static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') }; + #undef C16 + + const __m128i w0 = _mm_loadu_si128(reinterpret_cast(&whitespaces[0][0])); + const __m128i w1 = _mm_loadu_si128(reinterpret_cast(&whitespaces[1][0])); + const __m128i w2 = _mm_loadu_si128(reinterpret_cast(&whitespaces[2][0])); + const __m128i w3 = _mm_loadu_si128(reinterpret_cast(&whitespaces[3][0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + __m128i x = _mm_cmpeq_epi8(s, w0); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); + unsigned short r = static_cast(~_mm_movemask_epi8(x)); + if (r != 0) { // some of characters may be non-whitespace +#ifdef _MSC_VER // Find the index of first non-whitespace + unsigned long offset; + _BitScanForward(&offset, r); + return p + offset; +#else + return p + __builtin_ffs(r) - 1; +#endif + } + } +} + +inline const char *SkipWhitespace_SIMD(const char* p, const char* end) { + // Fast return for single non-whitespace + if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + ++p; + else + return p; + + // The rest of string + #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c } + static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') }; + #undef C16 + + const __m128i w0 = _mm_loadu_si128(reinterpret_cast(&whitespaces[0][0])); + const __m128i w1 = _mm_loadu_si128(reinterpret_cast(&whitespaces[1][0])); + const __m128i w2 = _mm_loadu_si128(reinterpret_cast(&whitespaces[2][0])); + const __m128i w3 = _mm_loadu_si128(reinterpret_cast(&whitespaces[3][0])); + + for (; p <= end - 16; p += 16) { + const __m128i s = _mm_loadu_si128(reinterpret_cast(p)); + __m128i x = _mm_cmpeq_epi8(s, w0); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); + unsigned short r = static_cast(~_mm_movemask_epi8(x)); + if (r != 0) { // some of characters may be non-whitespace +#ifdef _MSC_VER // Find the index of first non-whitespace + unsigned long offset; + _BitScanForward(&offset, r); + return p + offset; +#else + return p + __builtin_ffs(r) - 1; +#endif + } + } + + return SkipWhitespace(p, end); +} + +#endif // RAPIDJSON_SSE2 + +#ifdef RAPIDJSON_SIMD +//! Template function specialization for InsituStringStream +template<> inline void SkipWhitespace(InsituStringStream& is) { + is.src_ = const_cast(SkipWhitespace_SIMD(is.src_)); +} + +//! Template function specialization for StringStream +template<> inline void SkipWhitespace(StringStream& is) { + is.src_ = SkipWhitespace_SIMD(is.src_); +} + +template<> inline void SkipWhitespace(EncodedInputStream, MemoryStream>& is) { + is.is_.src_ = SkipWhitespace_SIMD(is.is_.src_, is.is_.end_); +} +#endif // RAPIDJSON_SIMD + +/////////////////////////////////////////////////////////////////////////////// +// GenericReader + +//! SAX-style JSON parser. Use \ref Reader for UTF8 encoding and default allocator. +/*! GenericReader parses JSON text from a stream, and send events synchronously to an + object implementing Handler concept. + + It needs to allocate a stack for storing a single decoded string during + non-destructive parsing. + + For in-situ parsing, the decoded string is directly written to the source + text string, no temporary buffer is required. + + A GenericReader object can be reused for parsing multiple JSON text. + + \tparam SourceEncoding Encoding of the input stream. + \tparam TargetEncoding Encoding of the parse output. + \tparam StackAllocator Allocator type for stack. +*/ +template +class GenericReader { +public: + typedef typename SourceEncoding::Ch Ch; //!< SourceEncoding character type + + //! Constructor. + /*! \param stackAllocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing) + \param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing) + */ + GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(stackAllocator, stackCapacity), parseResult_() {} + + //! Parse JSON text. + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam InputStream Type of input stream, implementing Stream concept. + \tparam Handler Type of handler, implementing Handler concept. + \param is Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. + */ + template + ParseResult Parse(InputStream& is, Handler& handler) { + if (parseFlags & kParseIterativeFlag) + return IterativeParse(is, handler); + + parseResult_.Clear(); + + ClearStackOnExit scope(*this); + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + + if (RAPIDJSON_UNLIKELY(is.Peek() == '\0')) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell()); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } + else { + ParseValue(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + + if (!(parseFlags & kParseStopWhenDoneFlag)) { + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + + if (RAPIDJSON_UNLIKELY(is.Peek() != '\0')) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell()); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } + } + } + + return parseResult_; + } + + //! Parse JSON text (with \ref kParseDefaultFlags) + /*! \tparam InputStream Type of input stream, implementing Stream concept + \tparam Handler Type of handler, implementing Handler concept. + \param is Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. + */ + template + ParseResult Parse(InputStream& is, Handler& handler) { + return Parse(is, handler); + } + + //! Whether a parse error has occured in the last parsing. + bool HasParseError() const { return parseResult_.IsError(); } + + //! Get the \ref ParseErrorCode of last parsing. + ParseErrorCode GetParseErrorCode() const { return parseResult_.Code(); } + + //! Get the position of last parsing error in input, 0 otherwise. + size_t GetErrorOffset() const { return parseResult_.Offset(); } + +protected: + void SetParseError(ParseErrorCode code, size_t offset) { parseResult_.Set(code, offset); } + +private: + // Prohibit copy constructor & assignment operator. + GenericReader(const GenericReader&); + GenericReader& operator=(const GenericReader&); + + void ClearStack() { stack_.Clear(); } + + // clear stack on any exit from ParseStream, e.g. due to exception + struct ClearStackOnExit { + explicit ClearStackOnExit(GenericReader& r) : r_(r) {} + ~ClearStackOnExit() { r_.ClearStack(); } + private: + GenericReader& r_; + ClearStackOnExit(const ClearStackOnExit&); + ClearStackOnExit& operator=(const ClearStackOnExit&); + }; + + template + void SkipWhitespaceAndComments(InputStream& is) { + SkipWhitespace(is); + + if (parseFlags & kParseCommentsFlag) { + while (RAPIDJSON_UNLIKELY(Consume(is, '/'))) { + if (Consume(is, '*')) { + while (true) { + if (RAPIDJSON_UNLIKELY(is.Peek() == '\0')) + RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); + else if (Consume(is, '*')) { + if (Consume(is, '/')) + break; + } + else + is.Take(); + } + } + else if (RAPIDJSON_LIKELY(Consume(is, '/'))) + while (is.Peek() != '\0' && is.Take() != '\n'); + else + RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); + + SkipWhitespace(is); + } + } + } + + // Parse object: { string : value, ... } + template + void ParseObject(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == '{'); + is.Take(); // Skip '{' + + if (RAPIDJSON_UNLIKELY(!handler.StartObject())) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (Consume(is, '}')) { + if (RAPIDJSON_UNLIKELY(!handler.EndObject(0))) // empty object + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + } + + for (SizeType memberCount = 0;;) { + if (RAPIDJSON_UNLIKELY(is.Peek() != '"')) + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); + + ParseString(is, handler, true); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (RAPIDJSON_UNLIKELY(!Consume(is, ':'))) + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + ParseValue(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + ++memberCount; + + switch (is.Peek()) { + case ',': + is.Take(); + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + break; + case '}': + is.Take(); + if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + default: + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); break; // This useless break is only for making warning and coverage happy + } + + if (parseFlags & kParseTrailingCommasFlag) { + if (is.Peek() == '}') { + if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + is.Take(); + return; + } + } + } + } + + // Parse array: [ value, ... ] + template + void ParseArray(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == '['); + is.Take(); // Skip '[' + + if (RAPIDJSON_UNLIKELY(!handler.StartArray())) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (Consume(is, ']')) { + if (RAPIDJSON_UNLIKELY(!handler.EndArray(0))) // empty array + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + } + + for (SizeType elementCount = 0;;) { + ParseValue(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + ++elementCount; + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (Consume(is, ',')) { + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + } + else if (Consume(is, ']')) { + if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); + + if (parseFlags & kParseTrailingCommasFlag) { + if (is.Peek() == ']') { + if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + is.Take(); + return; + } + } + } + } + + template + void ParseNull(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == 'n'); + is.Take(); + + if (RAPIDJSON_LIKELY(Consume(is, 'u') && Consume(is, 'l') && Consume(is, 'l'))) { + if (RAPIDJSON_UNLIKELY(!handler.Null())) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); + } + + template + void ParseTrue(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == 't'); + is.Take(); + + if (RAPIDJSON_LIKELY(Consume(is, 'r') && Consume(is, 'u') && Consume(is, 'e'))) { + if (RAPIDJSON_UNLIKELY(!handler.Bool(true))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); + } + + template + void ParseFalse(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == 'f'); + is.Take(); + + if (RAPIDJSON_LIKELY(Consume(is, 'a') && Consume(is, 'l') && Consume(is, 's') && Consume(is, 'e'))) { + if (RAPIDJSON_UNLIKELY(!handler.Bool(false))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); + } + + template + RAPIDJSON_FORCEINLINE static bool Consume(InputStream& is, typename InputStream::Ch expect) { + if (RAPIDJSON_LIKELY(is.Peek() == expect)) { + is.Take(); + return true; + } + else + return false; + } + + // Helper function to parse four hexidecimal digits in \uXXXX in ParseString(). + template + unsigned ParseHex4(InputStream& is, size_t escapeOffset) { + unsigned codepoint = 0; + for (int i = 0; i < 4; i++) { + Ch c = is.Peek(); + codepoint <<= 4; + codepoint += static_cast(c); + if (c >= '0' && c <= '9') + codepoint -= '0'; + else if (c >= 'A' && c <= 'F') + codepoint -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + codepoint -= 'a' - 10; + else { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorStringUnicodeEscapeInvalidHex, escapeOffset); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0); + } + is.Take(); + } + return codepoint; + } + + template + class StackStream { + public: + typedef CharType Ch; + + StackStream(internal::Stack& stack) : stack_(stack), length_(0) {} + RAPIDJSON_FORCEINLINE void Put(Ch c) { + *stack_.template Push() = c; + ++length_; + } + + RAPIDJSON_FORCEINLINE void* Push(SizeType count) { + length_ += count; + return stack_.template Push(count); + } + + size_t Length() const { return length_; } + + Ch* Pop() { + return stack_.template Pop(length_); + } + + private: + StackStream(const StackStream&); + StackStream& operator=(const StackStream&); + + internal::Stack& stack_; + SizeType length_; + }; + + // Parse string and generate String event. Different code paths for kParseInsituFlag. + template + void ParseString(InputStream& is, Handler& handler, bool isKey = false) { + internal::StreamLocalCopy copy(is); + InputStream& s(copy.s); + + RAPIDJSON_ASSERT(s.Peek() == '\"'); + s.Take(); // Skip '\"' + + bool success = false; + if (parseFlags & kParseInsituFlag) { + typename InputStream::Ch *head = s.PutBegin(); + ParseStringToStream(s, s); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + size_t length = s.PutEnd(head) - 1; + RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); + const typename TargetEncoding::Ch* const str = reinterpret_cast(head); + success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false)); + } + else { + StackStream stackStream(stack_); + ParseStringToStream(s, stackStream); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + SizeType length = static_cast(stackStream.Length()) - 1; + const typename TargetEncoding::Ch* const str = stackStream.Pop(); + success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true)); + } + if (RAPIDJSON_UNLIKELY(!success)) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell()); + } + + // Parse string to an output is + // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation. + template + RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) { +//!@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, 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, + Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 + }; +#undef Z16 +//!@endcond + + for (;;) { + // Scan and copy string before "\\\"" or < 0x20. This is an optional optimzation. + if (!(parseFlags & kParseValidateEncodingFlag)) + ScanCopyUnescapedString(is, os); + + Ch c = is.Peek(); + if (RAPIDJSON_UNLIKELY(c == '\\')) { // Escape + size_t escapeOffset = is.Tell(); // For invalid escaping, report the inital '\\' as error offset + is.Take(); + Ch e = is.Peek(); + if ((sizeof(Ch) == 1 || unsigned(e) < 256) && RAPIDJSON_LIKELY(escape[static_cast(e)])) { + is.Take(); + os.Put(static_cast(escape[static_cast(e)])); + } + else if (RAPIDJSON_LIKELY(e == 'u')) { // Unicode + is.Take(); + unsigned codepoint = ParseHex4(is, escapeOffset); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + if (RAPIDJSON_UNLIKELY(codepoint >= 0xD800 && codepoint <= 0xDBFF)) { + // Handle UTF-16 surrogate pair + if (RAPIDJSON_UNLIKELY(!Consume(is, '\\') || !Consume(is, 'u'))) + RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset); + unsigned codepoint2 = ParseHex4(is, escapeOffset); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + if (RAPIDJSON_UNLIKELY(codepoint2 < 0xDC00 || codepoint2 > 0xDFFF)) + RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset); + codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000; + } + TEncoding::Encode(os, codepoint); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, escapeOffset); + } + else if (RAPIDJSON_UNLIKELY(c == '"')) { // Closing double quote + is.Take(); + os.Put('\0'); // null-terminate the string + return; + } + else if (RAPIDJSON_UNLIKELY(static_cast(c) < 0x20)) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF + if (c == '\0') + RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell()); + else + RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell()); + } + else { + size_t offset = is.Tell(); + if (RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ? + !Transcoder::Validate(is, os) : + !Transcoder::Transcode(is, os)))) + RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, offset); + } + } + } + + template + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream&, OutputStream&) { + // Do nothing for generic version + } + +#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) + // StringStream -> StackStream + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream& os) { + const char* p = is.src_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { + is.src_ = p; + return; + } + else + os.Put(*p++); + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19 + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped + SizeType length; + #ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + length = offset; + #else + length = static_cast(__builtin_ffs(r) - 1); + #endif + char* q = reinterpret_cast(os.Push(length)); + for (size_t i = 0; i < length; i++) + q[i] = p[i]; + + p += length; + break; + } + _mm_storeu_si128(reinterpret_cast<__m128i *>(os.Push(16)), s); + } + + is.src_ = p; + } + + // InsituStringStream -> InsituStringStream + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) { + RAPIDJSON_ASSERT(&is == &os); + (void)os; + + if (is.src_ == is.dst_) { + SkipUnescapedString(is); + return; + } + + char* p = is.src_; + char *q = is.dst_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { + is.src_ = p; + is.dst_ = q; + return; + } + else + *q++ = *p++; + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); + + for (;; p += 16, q += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19 + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped + size_t length; +#ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + length = offset; +#else + length = static_cast(__builtin_ffs(r) - 1); +#endif + for (const char* pend = p + length; p != pend; ) + *q++ = *p++; + break; + } + _mm_storeu_si128(reinterpret_cast<__m128i *>(q), s); + } + + is.src_ = p; + is.dst_ = q; + } + + // When read/write pointers are the same for insitu stream, just skip unescaped characters + static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) { + RAPIDJSON_ASSERT(is.src_ == is.dst_); + char* p = is.src_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + for (; p != nextAligned; p++) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { + is.src_ = is.dst_ = p; + return; + } + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19 + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped + size_t length; +#ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + length = offset; +#else + length = static_cast(__builtin_ffs(r) - 1); +#endif + p += length; + break; + } + } + + is.src_ = is.dst_ = p; + } +#endif + + template + class NumberStream; + + template + class NumberStream { + public: + typedef typename InputStream::Ch Ch; + + NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader; } + ~NumberStream() {} + + 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) {} + + size_t Tell() { return is.Tell(); } + size_t Length() { return 0; } + const char* Pop() { return 0; } + + protected: + NumberStream& operator=(const NumberStream&); + + InputStream& is; + }; + + template + class NumberStream : public NumberStream { + typedef NumberStream Base; + public: + NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is), stackStream(reader.stack_) {} + ~NumberStream() {} + + RAPIDJSON_FORCEINLINE Ch TakePush() { + stackStream.Put(static_cast(Base::is.Peek())); + return Base::is.Take(); + } + + RAPIDJSON_FORCEINLINE void Push(char c) { + stackStream.Put(c); + } + + size_t Length() { return stackStream.Length(); } + + const char* Pop() { + stackStream.Put('\0'); + return stackStream.Pop(); + } + + private: + StackStream stackStream; + }; + + template + class NumberStream : public NumberStream { + typedef NumberStream Base; + public: + NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {} + ~NumberStream() {} + + RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); } + }; + + template + void ParseNumber(InputStream& is, Handler& handler) { + internal::StreamLocalCopy copy(is); + NumberStream s(*this, copy.s); + + size_t startOffset = s.Tell(); + double d = 0.0; + bool useNanOrInf = false; + + // Parse minus + bool minus = Consume(s, '-'); + + // Parse int: zero / ( digit1-9 *DIGIT ) + unsigned i = 0; + uint64_t i64 = 0; + bool use64bit = false; + int significandDigit = 0; + if (RAPIDJSON_UNLIKELY(s.Peek() == '0')) { + i = 0; + s.TakePush(); + } + else if (RAPIDJSON_LIKELY(s.Peek() >= '1' && s.Peek() <= '9')) { + i = static_cast(s.TakePush() - '0'); + + if (minus) + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(i >= 214748364)) { // 2^31 = 2147483648 + if (RAPIDJSON_LIKELY(i != 214748364 || s.Peek() > '8')) { + i64 = i; + use64bit = true; + break; + } + } + i = i * 10 + static_cast(s.TakePush() - '0'); + significandDigit++; + } + else + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(i >= 429496729)) { // 2^32 - 1 = 4294967295 + if (RAPIDJSON_LIKELY(i != 429496729 || s.Peek() > '5')) { + i64 = i; + use64bit = true; + break; + } + } + i = i * 10 + static_cast(s.TakePush() - '0'); + significandDigit++; + } + } + // Parse NaN or Infinity here + else if ((parseFlags & kParseNanAndInfFlag) && RAPIDJSON_LIKELY((s.Peek() == 'I' || s.Peek() == 'N'))) { + useNanOrInf = true; + if (RAPIDJSON_LIKELY(Consume(s, 'N') && Consume(s, 'a') && Consume(s, 'N'))) { + d = std::numeric_limits::quiet_NaN(); + } + else if (RAPIDJSON_LIKELY(Consume(s, 'I') && Consume(s, 'n') && Consume(s, 'f'))) { + d = (minus ? -std::numeric_limits::infinity() : std::numeric_limits::infinity()); + if (RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n') + && Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y')))) + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); + + // Parse 64bit int + bool useDouble = false; + if (use64bit) { + if (minus) + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC))) // 2^63 = 9223372036854775808 + if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8')) { + d = static_cast(i64); + useDouble = true; + break; + } + i64 = i64 * 10 + static_cast(s.TakePush() - '0'); + significandDigit++; + } + else + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999))) // 2^64 - 1 = 18446744073709551615 + if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5')) { + d = static_cast(i64); + useDouble = true; + break; + } + i64 = i64 * 10 + static_cast(s.TakePush() - '0'); + significandDigit++; + } + } + + // Force double for big integer + if (useDouble) { + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(d >= 1.7976931348623157e307)) // DBL_MAX / 10.0 + RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset); + d = d * 10 + (s.TakePush() - '0'); + } + } + + // Parse frac = decimal-point 1*DIGIT + int expFrac = 0; + size_t decimalPosition; + if (Consume(s, '.')) { + decimalPosition = s.Length(); + + if (RAPIDJSON_UNLIKELY(!(s.Peek() >= '0' && s.Peek() <= '9'))) + RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell()); + + if (!useDouble) { +#if RAPIDJSON_64BIT + // Use i64 to store significand in 64-bit architecture + if (!use64bit) + i64 = i; + + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path + break; + else { + i64 = i64 * 10 + static_cast(s.TakePush() - '0'); + --expFrac; + if (i64 != 0) + significandDigit++; + } + } + + d = static_cast(i64); +#else + // Use double to store significand in 32-bit architecture + d = static_cast(use64bit ? i64 : i); +#endif + useDouble = true; + } + + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (significandDigit < 17) { + d = d * 10.0 + (s.TakePush() - '0'); + --expFrac; + if (RAPIDJSON_LIKELY(d > 0.0)) + significandDigit++; + } + else + s.TakePush(); + } + } + else + decimalPosition = s.Length(); // decimal position at the end of integer. + + // Parse exp = e [ minus / plus ] 1*DIGIT + int exp = 0; + if (Consume(s, 'e') || Consume(s, 'E')) { + if (!useDouble) { + d = static_cast(use64bit ? i64 : i); + useDouble = true; + } + + bool expMinus = false; + if (Consume(s, '+')) + ; + else if (Consume(s, '-')) + expMinus = true; + + if (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + exp = static_cast(s.Take() - '0'); + if (expMinus) { + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + exp = exp * 10 + static_cast(s.Take() - '0'); + if (exp >= 214748364) { // Issue #313: prevent overflow exponent + while (RAPIDJSON_UNLIKELY(s.Peek() >= '0' && s.Peek() <= '9')) // Consume the rest of exponent + s.Take(); + } + } + } + else { // positive exp + int maxExp = 308 - expFrac; + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + exp = exp * 10 + static_cast(s.Take() - '0'); + if (RAPIDJSON_UNLIKELY(exp > maxExp)) + RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset); + } + } + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissExponent, s.Tell()); + + if (expMinus) + exp = -exp; + } + + // Finish parsing, call event according to the type of number. + bool cont = true; + + if (parseFlags & kParseNumbersAsStringsFlag) { + if (parseFlags & kParseInsituFlag) { + s.Pop(); // Pop stack no matter if it will be used or not. + typename InputStream::Ch* head = is.PutBegin(); + const size_t length = s.Tell() - startOffset; + RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); + // unable to insert the \0 character here, it will erase the comma after this number + const typename TargetEncoding::Ch* const str = reinterpret_cast(head); + cont = handler.RawNumber(str, SizeType(length), false); + } + else { + SizeType numCharsToCopy = static_cast(s.Length()); + StringStream srcStream(s.Pop()); + StackStream dstStream(stack_); + while (numCharsToCopy--) { + Transcoder, TargetEncoding>::Transcode(srcStream, dstStream); + } + dstStream.Put('\0'); + const typename TargetEncoding::Ch* str = dstStream.Pop(); + const SizeType length = static_cast(dstStream.Length()) - 1; + cont = handler.RawNumber(str, SizeType(length), true); + } + } + else { + size_t length = s.Length(); + const char* decimal = s.Pop(); // Pop stack no matter if it will be used or not. + + if (useDouble) { + int p = exp + expFrac; + if (parseFlags & kParseFullPrecisionFlag) + d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp); + else + d = internal::StrtodNormalPrecision(d, p); + + cont = handler.Double(minus ? -d : d); + } + else if (useNanOrInf) { + cont = handler.Double(d); + } + else { + if (use64bit) { + if (minus) + cont = handler.Int64(static_cast(~i64 + 1)); + else + cont = handler.Uint64(i64); + } + else { + if (minus) + cont = handler.Int(static_cast(~i + 1)); + else + cont = handler.Uint(i); + } + } + } + if (RAPIDJSON_UNLIKELY(!cont)) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, startOffset); + } + + // Parse any JSON value + template + void ParseValue(InputStream& is, Handler& handler) { + switch (is.Peek()) { + case 'n': ParseNull (is, handler); break; + case 't': ParseTrue (is, handler); break; + case 'f': ParseFalse (is, handler); break; + case '"': ParseString(is, handler); break; + case '{': ParseObject(is, handler); break; + case '[': ParseArray (is, handler); break; + default : + ParseNumber(is, handler); + break; + + } + } + + // Iterative Parsing + + // States + enum IterativeParsingState { + IterativeParsingStartState = 0, + IterativeParsingFinishState, + IterativeParsingErrorState, + + // Object states + IterativeParsingObjectInitialState, + IterativeParsingMemberKeyState, + IterativeParsingKeyValueDelimiterState, + IterativeParsingMemberValueState, + IterativeParsingMemberDelimiterState, + IterativeParsingObjectFinishState, + + // Array states + IterativeParsingArrayInitialState, + IterativeParsingElementState, + IterativeParsingElementDelimiterState, + IterativeParsingArrayFinishState, + + // Single value state + IterativeParsingValueState + }; + + enum { cIterativeParsingStateCount = IterativeParsingValueState + 1 }; + + // Tokens + enum Token { + LeftBracketToken = 0, + RightBracketToken, + + LeftCurlyBracketToken, + RightCurlyBracketToken, + + CommaToken, + ColonToken, + + StringToken, + FalseToken, + TrueToken, + NullToken, + NumberToken, + + kTokenCount + }; + + RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) { + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#define N NumberToken +#define N16 N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N + // Maps from ASCII to Token + static const unsigned char tokenMap[256] = { + N16, // 00~0F + N16, // 10~1F + N, N, StringToken, N, N, N, N, N, N, N, N, N, CommaToken, N, N, N, // 20~2F + N, N, N, N, N, N, N, N, N, N, ColonToken, N, N, N, N, N, // 30~3F + N16, // 40~4F + N, N, N, N, N, N, N, N, N, N, N, LeftBracketToken, N, RightBracketToken, N, N, // 50~5F + N, N, N, N, N, N, FalseToken, N, N, N, N, N, N, N, NullToken, N, // 60~6F + N, N, N, N, TrueToken, N, N, N, N, N, N, LeftCurlyBracketToken, N, RightCurlyBracketToken, N, N, // 70~7F + N16, N16, N16, N16, N16, N16, N16, N16 // 80~FF + }; +#undef N +#undef N16 +//!@endcond + + if (sizeof(Ch) == 1 || static_cast(c) < 256) + return static_cast(tokenMap[static_cast(c)]); + else + return NumberToken; + } + + RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) { + // current state x one lookahead token -> new state + static const char G[cIterativeParsingStateCount][kTokenCount] = { + // Start + { + IterativeParsingArrayInitialState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingValueState, // String + IterativeParsingValueState, // False + IterativeParsingValueState, // True + IterativeParsingValueState, // Null + IterativeParsingValueState // Number + }, + // Finish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // Error(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // ObjectInitial + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingObjectFinishState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberKeyState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // MemberKey + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingKeyValueDelimiterState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // KeyValueDelimiter + { + IterativeParsingArrayInitialState, // Left bracket(push MemberValue state) + IterativeParsingErrorState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push MemberValue state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberValueState, // String + IterativeParsingMemberValueState, // False + IterativeParsingMemberValueState, // True + IterativeParsingMemberValueState, // Null + IterativeParsingMemberValueState // Number + }, + // MemberValue + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingObjectFinishState, // Right curly bracket + IterativeParsingMemberDelimiterState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // MemberDelimiter + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingObjectFinishState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberKeyState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // ObjectFinish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // ArrayInitial + { + IterativeParsingArrayInitialState, // Left bracket(push Element state) + IterativeParsingArrayFinishState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push Element state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingElementState, // String + IterativeParsingElementState, // False + IterativeParsingElementState, // True + IterativeParsingElementState, // Null + IterativeParsingElementState // Number + }, + // Element + { + IterativeParsingErrorState, // Left bracket + IterativeParsingArrayFinishState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingElementDelimiterState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // ElementDelimiter + { + IterativeParsingArrayInitialState, // Left bracket(push Element state) + IterativeParsingArrayFinishState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push Element state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingElementState, // String + IterativeParsingElementState, // False + IterativeParsingElementState, // True + IterativeParsingElementState, // Null + IterativeParsingElementState // Number + }, + // ArrayFinish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // Single Value (sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + } + }; // End of G + + return static_cast(G[state][token]); + } + + // Make an advance in the token stream and state based on the candidate destination state which was returned by Transit(). + // May return a new state on state pop. + template + RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) { + (void)token; + + switch (dst) { + case IterativeParsingErrorState: + return dst; + + case IterativeParsingObjectInitialState: + case IterativeParsingArrayInitialState: + { + // Push the state(Element or MemeberValue) if we are nested in another array or value of member. + // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop. + IterativeParsingState n = src; + if (src == IterativeParsingArrayInitialState || src == IterativeParsingElementDelimiterState) + n = IterativeParsingElementState; + else if (src == IterativeParsingKeyValueDelimiterState) + n = IterativeParsingMemberValueState; + // Push current state. + *stack_.template Push(1) = n; + // Initialize and push the member/element count. + *stack_.template Push(1) = 0; + // Call handler + bool hr = (dst == IterativeParsingObjectInitialState) ? handler.StartObject() : handler.StartArray(); + // On handler short circuits the parsing. + if (!hr) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else { + is.Take(); + return dst; + } + } + + case IterativeParsingMemberKeyState: + ParseString(is, handler, true); + if (HasParseError()) + return IterativeParsingErrorState; + else + return dst; + + case IterativeParsingKeyValueDelimiterState: + RAPIDJSON_ASSERT(token == ColonToken); + is.Take(); + return dst; + + case IterativeParsingMemberValueState: + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return dst; + + case IterativeParsingElementState: + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return dst; + + case IterativeParsingMemberDelimiterState: + case IterativeParsingElementDelimiterState: + is.Take(); + // Update member/element count. + *stack_.template Top() = *stack_.template Top() + 1; + return dst; + + case IterativeParsingObjectFinishState: + { + // Transit from delimiter is only allowed when trailing commas are enabled + if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingMemberDelimiterState) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorObjectMissName, is.Tell()); + return IterativeParsingErrorState; + } + // Get member count. + SizeType c = *stack_.template Pop(1); + // If the object is not empty, count the last member. + if (src == IterativeParsingMemberValueState) + ++c; + // Restore the state. + IterativeParsingState n = static_cast(*stack_.template Pop(1)); + // Transit to Finish state if this is the topmost scope. + if (n == IterativeParsingStartState) + n = IterativeParsingFinishState; + // Call handler + bool hr = handler.EndObject(c); + // On handler short circuits the parsing. + if (!hr) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else { + is.Take(); + return n; + } + } + + case IterativeParsingArrayFinishState: + { + // Transit from delimiter is only allowed when trailing commas are enabled + if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingElementDelimiterState) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorValueInvalid, is.Tell()); + return IterativeParsingErrorState; + } + // Get element count. + SizeType c = *stack_.template Pop(1); + // If the array is not empty, count the last element. + if (src == IterativeParsingElementState) + ++c; + // Restore the state. + IterativeParsingState n = static_cast(*stack_.template Pop(1)); + // Transit to Finish state if this is the topmost scope. + if (n == IterativeParsingStartState) + n = IterativeParsingFinishState; + // Call handler + bool hr = handler.EndArray(c); + // On handler short circuits the parsing. + if (!hr) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else { + is.Take(); + return n; + } + } + + default: + // This branch is for IterativeParsingValueState actually. + // Use `default:` rather than + // `case IterativeParsingValueState:` is for code coverage. + + // The IterativeParsingStartState is not enumerated in this switch-case. + // It is impossible for that case. And it can be caught by following assertion. + + // The IterativeParsingFinishState is not enumerated in this switch-case either. + // It is a "derivative" state which cannot triggered from Predict() directly. + // Therefore it cannot happen here. And it can be caught by following assertion. + RAPIDJSON_ASSERT(dst == IterativeParsingValueState); + + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return IterativeParsingFinishState; + } + } + + template + void HandleError(IterativeParsingState src, InputStream& is) { + if (HasParseError()) { + // Error flag has been set. + return; + } + + switch (src) { + case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); return; + case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); return; + case IterativeParsingObjectInitialState: + case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); return; + case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return; + case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return; + case IterativeParsingKeyValueDelimiterState: + case IterativeParsingArrayInitialState: + case IterativeParsingElementDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); return; + default: RAPIDJSON_ASSERT(src == IterativeParsingElementState); RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return; + } + } + + template + ParseResult IterativeParse(InputStream& is, Handler& handler) { + parseResult_.Clear(); + ClearStackOnExit scope(*this); + IterativeParsingState state = IterativeParsingStartState; + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + while (is.Peek() != '\0') { + Token t = Tokenize(is.Peek()); + IterativeParsingState n = Predict(state, t); + IterativeParsingState d = Transit(state, t, n, is, handler); + + if (d == IterativeParsingErrorState) { + HandleError(state, is); + break; + } + + state = d; + + // Do not further consume streams if a root JSON has been parsed. + if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState) + break; + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } + + // Handle the end of file. + if (state != IterativeParsingFinishState) + HandleError(state, is); + + return parseResult_; + } + + static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string. + internal::Stack stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing. + ParseResult parseResult_; +}; // class GenericReader + +//! Reader with UTF8 encoding and default allocator. +typedef GenericReader, UTF8<> > Reader; + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_READER_H_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/schema.h b/Externals/discord-rpc/thirdparty/include/rapidjson/schema.h new file mode 100644 index 0000000000..b182aa27f0 --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/schema.h @@ -0,0 +1,2006 @@ +// 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_SCHEMA_H_ +#define RAPIDJSON_SCHEMA_H_ + +#include "document.h" +#include "pointer.h" +#include // abs, floor + +#if !defined(RAPIDJSON_SCHEMA_USE_INTERNALREGEX) +#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 1 +#else +#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 0 +#endif + +#if !RAPIDJSON_SCHEMA_USE_INTERNALREGEX && !defined(RAPIDJSON_SCHEMA_USE_STDREGEX) && (__cplusplus >=201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)) +#define RAPIDJSON_SCHEMA_USE_STDREGEX 1 +#else +#define RAPIDJSON_SCHEMA_USE_STDREGEX 0 +#endif + +#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX +#include "internal/regex.h" +#elif RAPIDJSON_SCHEMA_USE_STDREGEX +#include +#endif + +#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX || RAPIDJSON_SCHEMA_USE_STDREGEX +#define RAPIDJSON_SCHEMA_HAS_REGEX 1 +#else +#define RAPIDJSON_SCHEMA_HAS_REGEX 0 +#endif + +#ifndef RAPIDJSON_SCHEMA_VERBOSE +#define RAPIDJSON_SCHEMA_VERBOSE 0 +#endif + +#if RAPIDJSON_SCHEMA_VERBOSE +#include "stringbuffer.h" +#endif + +RAPIDJSON_DIAG_PUSH + +#if defined(__GNUC__) +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_OFF(weak-vtables) +RAPIDJSON_DIAG_OFF(exit-time-destructors) +RAPIDJSON_DIAG_OFF(c++98-compat-pedantic) +RAPIDJSON_DIAG_OFF(variadic-macros) +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Verbose Utilities + +#if RAPIDJSON_SCHEMA_VERBOSE + +namespace internal { + +inline void PrintInvalidKeyword(const char* keyword) { + printf("Fail keyword: %s\n", keyword); +} + +inline void PrintInvalidKeyword(const wchar_t* keyword) { + wprintf(L"Fail keyword: %ls\n", keyword); +} + +inline void PrintInvalidDocument(const char* document) { + printf("Fail document: %s\n\n", document); +} + +inline void PrintInvalidDocument(const wchar_t* document) { + wprintf(L"Fail document: %ls\n\n", document); +} + +inline void PrintValidatorPointers(unsigned depth, const char* s, const char* d) { + printf("S: %*s%s\nD: %*s%s\n\n", depth * 4, " ", s, depth * 4, " ", d); +} + +inline void PrintValidatorPointers(unsigned depth, const wchar_t* s, const wchar_t* d) { + wprintf(L"S: %*ls%ls\nD: %*ls%ls\n\n", depth * 4, L" ", s, depth * 4, L" ", d); +} + +} // namespace internal + +#endif // RAPIDJSON_SCHEMA_VERBOSE + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_INVALID_KEYWORD_RETURN + +#if RAPIDJSON_SCHEMA_VERBOSE +#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword) internal::PrintInvalidKeyword(keyword) +#else +#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword) +#endif + +#define RAPIDJSON_INVALID_KEYWORD_RETURN(keyword)\ +RAPIDJSON_MULTILINEMACRO_BEGIN\ + context.invalidKeyword = keyword.GetString();\ + RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword.GetString());\ + return false;\ +RAPIDJSON_MULTILINEMACRO_END + +/////////////////////////////////////////////////////////////////////////////// +// Forward declarations + +template +class GenericSchemaDocument; + +namespace internal { + +template +class Schema; + +/////////////////////////////////////////////////////////////////////////////// +// ISchemaValidator + +class ISchemaValidator { +public: + virtual ~ISchemaValidator() {} + virtual bool IsValid() const = 0; +}; + +/////////////////////////////////////////////////////////////////////////////// +// ISchemaStateFactory + +template +class ISchemaStateFactory { +public: + virtual ~ISchemaStateFactory() {} + virtual ISchemaValidator* CreateSchemaValidator(const SchemaType&) = 0; + virtual void DestroySchemaValidator(ISchemaValidator* validator) = 0; + virtual void* CreateHasher() = 0; + virtual uint64_t GetHashCode(void* hasher) = 0; + virtual void DestroryHasher(void* hasher) = 0; + virtual void* MallocState(size_t size) = 0; + virtual void FreeState(void* p) = 0; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Hasher + +// For comparison of compound value +template +class Hasher { +public: + typedef typename Encoding::Ch Ch; + + Hasher(Allocator* allocator = 0, size_t stackCapacity = kDefaultSize) : stack_(allocator, stackCapacity) {} + + bool Null() { return WriteType(kNullType); } + bool Bool(bool b) { return WriteType(b ? kTrueType : kFalseType); } + bool Int(int i) { Number n; n.u.i = i; n.d = static_cast(i); return WriteNumber(n); } + bool Uint(unsigned u) { Number n; n.u.u = u; n.d = static_cast(u); return WriteNumber(n); } + bool Int64(int64_t i) { Number n; n.u.i = i; n.d = static_cast(i); return WriteNumber(n); } + bool Uint64(uint64_t u) { Number n; n.u.u = u; n.d = static_cast(u); return WriteNumber(n); } + bool Double(double d) { + Number n; + if (d < 0) n.u.i = static_cast(d); + else n.u.u = static_cast(d); + n.d = d; + return WriteNumber(n); + } + + bool RawNumber(const Ch* str, SizeType len, bool) { + WriteBuffer(kNumberType, str, len * sizeof(Ch)); + return true; + } + + bool String(const Ch* str, SizeType len, bool) { + WriteBuffer(kStringType, str, len * sizeof(Ch)); + return true; + } + + bool StartObject() { return true; } + bool Key(const Ch* str, SizeType len, bool copy) { return String(str, len, copy); } + bool EndObject(SizeType memberCount) { + uint64_t h = Hash(0, kObjectType); + uint64_t* kv = stack_.template Pop(memberCount * 2); + for (SizeType i = 0; i < memberCount; i++) + h ^= Hash(kv[i * 2], kv[i * 2 + 1]); // Use xor to achieve member order insensitive + *stack_.template Push() = h; + return true; + } + + bool StartArray() { return true; } + bool EndArray(SizeType elementCount) { + uint64_t h = Hash(0, kArrayType); + uint64_t* e = stack_.template Pop(elementCount); + for (SizeType i = 0; i < elementCount; i++) + h = Hash(h, e[i]); // Use hash to achieve element order sensitive + *stack_.template Push() = h; + return true; + } + + bool IsValid() const { return stack_.GetSize() == sizeof(uint64_t); } + + uint64_t GetHashCode() const { + RAPIDJSON_ASSERT(IsValid()); + return *stack_.template Top(); + } + +private: + static const size_t kDefaultSize = 256; + struct Number { + union U { + uint64_t u; + int64_t i; + }u; + double d; + }; + + bool WriteType(Type type) { return WriteBuffer(type, 0, 0); } + + bool WriteNumber(const Number& n) { return WriteBuffer(kNumberType, &n, sizeof(n)); } + + bool WriteBuffer(Type type, const void* data, size_t len) { + // FNV-1a from http://isthe.com/chongo/tech/comp/fnv/ + uint64_t h = Hash(RAPIDJSON_UINT64_C2(0x84222325, 0xcbf29ce4), type); + const unsigned char* d = static_cast(data); + for (size_t i = 0; i < len; i++) + h = Hash(h, d[i]); + *stack_.template Push() = h; + return true; + } + + static uint64_t Hash(uint64_t h, uint64_t d) { + static const uint64_t kPrime = RAPIDJSON_UINT64_C2(0x00000100, 0x000001b3); + h ^= d; + h *= kPrime; + return h; + } + + Stack stack_; +}; + +/////////////////////////////////////////////////////////////////////////////// +// SchemaValidationContext + +template +struct SchemaValidationContext { + typedef Schema SchemaType; + typedef ISchemaStateFactory SchemaValidatorFactoryType; + typedef typename SchemaType::ValueType ValueType; + typedef typename ValueType::Ch Ch; + + enum PatternValidatorType { + kPatternValidatorOnly, + kPatternValidatorWithProperty, + kPatternValidatorWithAdditionalProperty + }; + + SchemaValidationContext(SchemaValidatorFactoryType& f, const SchemaType* s) : + factory(f), + schema(s), + valueSchema(), + invalidKeyword(), + hasher(), + arrayElementHashCodes(), + validators(), + validatorCount(), + patternPropertiesValidators(), + patternPropertiesValidatorCount(), + patternPropertiesSchemas(), + patternPropertiesSchemaCount(), + valuePatternValidatorType(kPatternValidatorOnly), + propertyExist(), + inArray(false), + valueUniqueness(false), + arrayUniqueness(false) + { + } + + ~SchemaValidationContext() { + if (hasher) + factory.DestroryHasher(hasher); + if (validators) { + for (SizeType i = 0; i < validatorCount; i++) + factory.DestroySchemaValidator(validators[i]); + factory.FreeState(validators); + } + if (patternPropertiesValidators) { + for (SizeType i = 0; i < patternPropertiesValidatorCount; i++) + factory.DestroySchemaValidator(patternPropertiesValidators[i]); + factory.FreeState(patternPropertiesValidators); + } + if (patternPropertiesSchemas) + factory.FreeState(patternPropertiesSchemas); + if (propertyExist) + factory.FreeState(propertyExist); + } + + SchemaValidatorFactoryType& factory; + const SchemaType* schema; + const SchemaType* valueSchema; + const Ch* invalidKeyword; + void* hasher; // Only validator access + void* arrayElementHashCodes; // Only validator access this + ISchemaValidator** validators; + SizeType validatorCount; + ISchemaValidator** patternPropertiesValidators; + SizeType patternPropertiesValidatorCount; + const SchemaType** patternPropertiesSchemas; + SizeType patternPropertiesSchemaCount; + PatternValidatorType valuePatternValidatorType; + PatternValidatorType objectPatternValidatorType; + SizeType arrayElementIndex; + bool* propertyExist; + bool inArray; + bool valueUniqueness; + bool arrayUniqueness; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Schema + +template +class Schema { +public: + typedef typename SchemaDocumentType::ValueType ValueType; + typedef typename SchemaDocumentType::AllocatorType AllocatorType; + typedef typename SchemaDocumentType::PointerType PointerType; + typedef typename ValueType::EncodingType EncodingType; + typedef typename EncodingType::Ch Ch; + typedef SchemaValidationContext Context; + typedef Schema SchemaType; + typedef GenericValue SValue; + friend class GenericSchemaDocument; + + Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator) : + allocator_(allocator), + enum_(), + enumCount_(), + not_(), + type_((1 << kTotalSchemaType) - 1), // typeless + validatorCount_(), + properties_(), + additionalPropertiesSchema_(), + patternProperties_(), + patternPropertyCount_(), + propertyCount_(), + minProperties_(), + maxProperties_(SizeType(~0)), + additionalProperties_(true), + hasDependencies_(), + hasRequired_(), + hasSchemaDependencies_(), + additionalItemsSchema_(), + itemsList_(), + itemsTuple_(), + itemsTupleCount_(), + minItems_(), + maxItems_(SizeType(~0)), + additionalItems_(true), + uniqueItems_(false), + pattern_(), + minLength_(0), + maxLength_(~SizeType(0)), + exclusiveMinimum_(false), + exclusiveMaximum_(false) + { + typedef typename SchemaDocumentType::ValueType ValueType; + typedef typename ValueType::ConstValueIterator ConstValueIterator; + typedef typename ValueType::ConstMemberIterator ConstMemberIterator; + + if (!value.IsObject()) + return; + + if (const ValueType* v = GetMember(value, GetTypeString())) { + type_ = 0; + if (v->IsString()) + AddType(*v); + else if (v->IsArray()) + for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) + AddType(*itr); + } + + if (const ValueType* v = GetMember(value, GetEnumString())) + if (v->IsArray() && v->Size() > 0) { + enum_ = static_cast(allocator_->Malloc(sizeof(uint64_t) * v->Size())); + for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) { + typedef Hasher > EnumHasherType; + char buffer[256 + 24]; + MemoryPoolAllocator<> hasherAllocator(buffer, sizeof(buffer)); + EnumHasherType h(&hasherAllocator, 256); + itr->Accept(h); + enum_[enumCount_++] = h.GetHashCode(); + } + } + + if (schemaDocument) { + AssignIfExist(allOf_, *schemaDocument, p, value, GetAllOfString(), document); + AssignIfExist(anyOf_, *schemaDocument, p, value, GetAnyOfString(), document); + AssignIfExist(oneOf_, *schemaDocument, p, value, GetOneOfString(), document); + } + + if (const ValueType* v = GetMember(value, GetNotString())) { + schemaDocument->CreateSchema(¬_, p.Append(GetNotString(), allocator_), *v, document); + notValidatorIndex_ = validatorCount_; + validatorCount_++; + } + + // Object + + const ValueType* properties = GetMember(value, GetPropertiesString()); + const ValueType* required = GetMember(value, GetRequiredString()); + const ValueType* dependencies = GetMember(value, GetDependenciesString()); + { + // Gather properties from properties/required/dependencies + SValue allProperties(kArrayType); + + if (properties && properties->IsObject()) + for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) + AddUniqueElement(allProperties, itr->name); + + if (required && required->IsArray()) + for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr) + if (itr->IsString()) + AddUniqueElement(allProperties, *itr); + + if (dependencies && dependencies->IsObject()) + for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) { + AddUniqueElement(allProperties, itr->name); + if (itr->value.IsArray()) + for (ConstValueIterator i = itr->value.Begin(); i != itr->value.End(); ++i) + if (i->IsString()) + AddUniqueElement(allProperties, *i); + } + + if (allProperties.Size() > 0) { + propertyCount_ = allProperties.Size(); + properties_ = static_cast(allocator_->Malloc(sizeof(Property) * propertyCount_)); + for (SizeType i = 0; i < propertyCount_; i++) { + new (&properties_[i]) Property(); + properties_[i].name = allProperties[i]; + properties_[i].schema = GetTypeless(); + } + } + } + + if (properties && properties->IsObject()) { + PointerType q = p.Append(GetPropertiesString(), allocator_); + for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) { + SizeType index; + if (FindPropertyIndex(itr->name, &index)) + schemaDocument->CreateSchema(&properties_[index].schema, q.Append(itr->name, allocator_), itr->value, document); + } + } + + if (const ValueType* v = GetMember(value, GetPatternPropertiesString())) { + PointerType q = p.Append(GetPatternPropertiesString(), allocator_); + patternProperties_ = static_cast(allocator_->Malloc(sizeof(PatternProperty) * v->MemberCount())); + patternPropertyCount_ = 0; + + for (ConstMemberIterator itr = v->MemberBegin(); itr != v->MemberEnd(); ++itr) { + new (&patternProperties_[patternPropertyCount_]) PatternProperty(); + patternProperties_[patternPropertyCount_].pattern = CreatePattern(itr->name); + schemaDocument->CreateSchema(&patternProperties_[patternPropertyCount_].schema, q.Append(itr->name, allocator_), itr->value, document); + patternPropertyCount_++; + } + } + + if (required && required->IsArray()) + for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr) + if (itr->IsString()) { + SizeType index; + if (FindPropertyIndex(*itr, &index)) { + properties_[index].required = true; + hasRequired_ = true; + } + } + + if (dependencies && dependencies->IsObject()) { + PointerType q = p.Append(GetDependenciesString(), allocator_); + hasDependencies_ = true; + for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) { + SizeType sourceIndex; + if (FindPropertyIndex(itr->name, &sourceIndex)) { + if (itr->value.IsArray()) { + properties_[sourceIndex].dependencies = static_cast(allocator_->Malloc(sizeof(bool) * propertyCount_)); + std::memset(properties_[sourceIndex].dependencies, 0, sizeof(bool)* propertyCount_); + for (ConstValueIterator targetItr = itr->value.Begin(); targetItr != itr->value.End(); ++targetItr) { + SizeType targetIndex; + if (FindPropertyIndex(*targetItr, &targetIndex)) + properties_[sourceIndex].dependencies[targetIndex] = true; + } + } + else if (itr->value.IsObject()) { + hasSchemaDependencies_ = true; + schemaDocument->CreateSchema(&properties_[sourceIndex].dependenciesSchema, q.Append(itr->name, allocator_), itr->value, document); + properties_[sourceIndex].dependenciesValidatorIndex = validatorCount_; + validatorCount_++; + } + } + } + } + + if (const ValueType* v = GetMember(value, GetAdditionalPropertiesString())) { + if (v->IsBool()) + additionalProperties_ = v->GetBool(); + else if (v->IsObject()) + schemaDocument->CreateSchema(&additionalPropertiesSchema_, p.Append(GetAdditionalPropertiesString(), allocator_), *v, document); + } + + AssignIfExist(minProperties_, value, GetMinPropertiesString()); + AssignIfExist(maxProperties_, value, GetMaxPropertiesString()); + + // Array + if (const ValueType* v = GetMember(value, GetItemsString())) { + PointerType q = p.Append(GetItemsString(), allocator_); + if (v->IsObject()) // List validation + schemaDocument->CreateSchema(&itemsList_, q, *v, document); + else if (v->IsArray()) { // Tuple validation + itemsTuple_ = static_cast(allocator_->Malloc(sizeof(const Schema*) * v->Size())); + SizeType index = 0; + for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr, index++) + schemaDocument->CreateSchema(&itemsTuple_[itemsTupleCount_++], q.Append(index, allocator_), *itr, document); + } + } + + AssignIfExist(minItems_, value, GetMinItemsString()); + AssignIfExist(maxItems_, value, GetMaxItemsString()); + + if (const ValueType* v = GetMember(value, GetAdditionalItemsString())) { + if (v->IsBool()) + additionalItems_ = v->GetBool(); + else if (v->IsObject()) + schemaDocument->CreateSchema(&additionalItemsSchema_, p.Append(GetAdditionalItemsString(), allocator_), *v, document); + } + + AssignIfExist(uniqueItems_, value, GetUniqueItemsString()); + + // String + AssignIfExist(minLength_, value, GetMinLengthString()); + AssignIfExist(maxLength_, value, GetMaxLengthString()); + + if (const ValueType* v = GetMember(value, GetPatternString())) + pattern_ = CreatePattern(*v); + + // Number + if (const ValueType* v = GetMember(value, GetMinimumString())) + if (v->IsNumber()) + minimum_.CopyFrom(*v, *allocator_); + + if (const ValueType* v = GetMember(value, GetMaximumString())) + if (v->IsNumber()) + maximum_.CopyFrom(*v, *allocator_); + + AssignIfExist(exclusiveMinimum_, value, GetExclusiveMinimumString()); + AssignIfExist(exclusiveMaximum_, value, GetExclusiveMaximumString()); + + if (const ValueType* v = GetMember(value, GetMultipleOfString())) + if (v->IsNumber() && v->GetDouble() > 0.0) + multipleOf_.CopyFrom(*v, *allocator_); + } + + ~Schema() { + if (allocator_) { + allocator_->Free(enum_); + } + if (properties_) { + for (SizeType i = 0; i < propertyCount_; i++) + properties_[i].~Property(); + AllocatorType::Free(properties_); + } + if (patternProperties_) { + for (SizeType i = 0; i < patternPropertyCount_; i++) + patternProperties_[i].~PatternProperty(); + AllocatorType::Free(patternProperties_); + } + AllocatorType::Free(itemsTuple_); +#if RAPIDJSON_SCHEMA_HAS_REGEX + if (pattern_) { + pattern_->~RegexType(); + allocator_->Free(pattern_); + } +#endif + } + + bool BeginValue(Context& context) const { + if (context.inArray) { + if (uniqueItems_) + context.valueUniqueness = true; + + if (itemsList_) + context.valueSchema = itemsList_; + else if (itemsTuple_) { + if (context.arrayElementIndex < itemsTupleCount_) + context.valueSchema = itemsTuple_[context.arrayElementIndex]; + else if (additionalItemsSchema_) + context.valueSchema = additionalItemsSchema_; + else if (additionalItems_) + context.valueSchema = GetTypeless(); + else + RAPIDJSON_INVALID_KEYWORD_RETURN(GetItemsString()); + } + else + context.valueSchema = GetTypeless(); + + context.arrayElementIndex++; + } + return true; + } + + RAPIDJSON_FORCEINLINE bool EndValue(Context& context) const { + if (context.patternPropertiesValidatorCount > 0) { + bool otherValid = false; + SizeType count = context.patternPropertiesValidatorCount; + if (context.objectPatternValidatorType != Context::kPatternValidatorOnly) + otherValid = context.patternPropertiesValidators[--count]->IsValid(); + + bool patternValid = true; + for (SizeType i = 0; i < count; i++) + if (!context.patternPropertiesValidators[i]->IsValid()) { + patternValid = false; + break; + } + + if (context.objectPatternValidatorType == Context::kPatternValidatorOnly) { + if (!patternValid) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString()); + } + else if (context.objectPatternValidatorType == Context::kPatternValidatorWithProperty) { + if (!patternValid || !otherValid) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString()); + } + else if (!patternValid && !otherValid) // kPatternValidatorWithAdditionalProperty) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString()); + } + + if (enum_) { + const uint64_t h = context.factory.GetHashCode(context.hasher); + for (SizeType i = 0; i < enumCount_; i++) + if (enum_[i] == h) + goto foundEnum; + RAPIDJSON_INVALID_KEYWORD_RETURN(GetEnumString()); + foundEnum:; + } + + if (allOf_.schemas) + for (SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++) + if (!context.validators[i]->IsValid()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetAllOfString()); + + if (anyOf_.schemas) { + for (SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++) + if (context.validators[i]->IsValid()) + goto foundAny; + RAPIDJSON_INVALID_KEYWORD_RETURN(GetAnyOfString()); + foundAny:; + } + + if (oneOf_.schemas) { + bool oneValid = false; + for (SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++) + if (context.validators[i]->IsValid()) { + if (oneValid) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString()); + else + oneValid = true; + } + if (!oneValid) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString()); + } + + if (not_ && context.validators[notValidatorIndex_]->IsValid()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetNotString()); + + return true; + } + + bool Null(Context& context) const { + if (!(type_ & (1 << kNullSchemaType))) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + return CreateParallelValidator(context); + } + + bool Bool(Context& context, bool) const { + if (!(type_ & (1 << kBooleanSchemaType))) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + return CreateParallelValidator(context); + } + + bool Int(Context& context, int i) const { + if (!CheckInt(context, i)) + return false; + return CreateParallelValidator(context); + } + + bool Uint(Context& context, unsigned u) const { + if (!CheckUint(context, u)) + return false; + return CreateParallelValidator(context); + } + + bool Int64(Context& context, int64_t i) const { + if (!CheckInt(context, i)) + return false; + return CreateParallelValidator(context); + } + + bool Uint64(Context& context, uint64_t u) const { + if (!CheckUint(context, u)) + return false; + return CreateParallelValidator(context); + } + + bool Double(Context& context, double d) const { + if (!(type_ & (1 << kNumberSchemaType))) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + + if (!minimum_.IsNull() && !CheckDoubleMinimum(context, d)) + return false; + + if (!maximum_.IsNull() && !CheckDoubleMaximum(context, d)) + return false; + + if (!multipleOf_.IsNull() && !CheckDoubleMultipleOf(context, d)) + return false; + + return CreateParallelValidator(context); + } + + bool String(Context& context, const Ch* str, SizeType length, bool) const { + if (!(type_ & (1 << kStringSchemaType))) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + + if (minLength_ != 0 || maxLength_ != SizeType(~0)) { + SizeType count; + if (internal::CountStringCodePoint(str, length, &count)) { + if (count < minLength_) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinLengthString()); + if (count > maxLength_) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxLengthString()); + } + } + + if (pattern_ && !IsPatternMatch(pattern_, str, length)) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternString()); + + return CreateParallelValidator(context); + } + + bool StartObject(Context& context) const { + if (!(type_ & (1 << kObjectSchemaType))) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + + if (hasDependencies_ || hasRequired_) { + context.propertyExist = static_cast(context.factory.MallocState(sizeof(bool) * propertyCount_)); + std::memset(context.propertyExist, 0, sizeof(bool) * propertyCount_); + } + + if (patternProperties_) { // pre-allocate schema array + SizeType count = patternPropertyCount_ + 1; // extra for valuePatternValidatorType + context.patternPropertiesSchemas = static_cast(context.factory.MallocState(sizeof(const SchemaType*) * count)); + context.patternPropertiesSchemaCount = 0; + std::memset(context.patternPropertiesSchemas, 0, sizeof(SchemaType*) * count); + } + + return CreateParallelValidator(context); + } + + bool Key(Context& context, const Ch* str, SizeType len, bool) const { + if (patternProperties_) { + context.patternPropertiesSchemaCount = 0; + for (SizeType i = 0; i < patternPropertyCount_; i++) + if (patternProperties_[i].pattern && IsPatternMatch(patternProperties_[i].pattern, str, len)) + context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = patternProperties_[i].schema; + } + + SizeType index; + if (FindPropertyIndex(ValueType(str, len).Move(), &index)) { + if (context.patternPropertiesSchemaCount > 0) { + context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema; + context.valueSchema = GetTypeless(); + context.valuePatternValidatorType = Context::kPatternValidatorWithProperty; + } + else + context.valueSchema = properties_[index].schema; + + if (context.propertyExist) + context.propertyExist[index] = true; + + return true; + } + + if (additionalPropertiesSchema_) { + if (additionalPropertiesSchema_ && context.patternPropertiesSchemaCount > 0) { + context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_; + context.valueSchema = GetTypeless(); + context.valuePatternValidatorType = Context::kPatternValidatorWithAdditionalProperty; + } + else + context.valueSchema = additionalPropertiesSchema_; + return true; + } + else if (additionalProperties_) { + context.valueSchema = GetTypeless(); + return true; + } + + if (context.patternPropertiesSchemaCount == 0) // patternProperties are not additional properties + RAPIDJSON_INVALID_KEYWORD_RETURN(GetAdditionalPropertiesString()); + + return true; + } + + bool EndObject(Context& context, SizeType memberCount) const { + if (hasRequired_) + for (SizeType index = 0; index < propertyCount_; index++) + if (properties_[index].required) + if (!context.propertyExist[index]) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetRequiredString()); + + if (memberCount < minProperties_) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinPropertiesString()); + + if (memberCount > maxProperties_) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxPropertiesString()); + + if (hasDependencies_) { + for (SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++) + if (context.propertyExist[sourceIndex]) { + if (properties_[sourceIndex].dependencies) { + for (SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++) + if (properties_[sourceIndex].dependencies[targetIndex] && !context.propertyExist[targetIndex]) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString()); + } + else if (properties_[sourceIndex].dependenciesSchema) + if (!context.validators[properties_[sourceIndex].dependenciesValidatorIndex]->IsValid()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString()); + } + } + + return true; + } + + bool StartArray(Context& context) const { + if (!(type_ & (1 << kArraySchemaType))) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + + context.arrayElementIndex = 0; + context.inArray = true; + + return CreateParallelValidator(context); + } + + bool EndArray(Context& context, SizeType elementCount) const { + context.inArray = false; + + if (elementCount < minItems_) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinItemsString()); + + if (elementCount > maxItems_) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxItemsString()); + + return true; + } + + // Generate functions for string literal according to Ch +#define RAPIDJSON_STRING_(name, ...) \ + static const ValueType& Get##name##String() {\ + static const Ch s[] = { __VA_ARGS__, '\0' };\ + static const ValueType v(s, sizeof(s) / sizeof(Ch) - 1);\ + return v;\ + } + + RAPIDJSON_STRING_(Null, 'n', 'u', 'l', 'l') + RAPIDJSON_STRING_(Boolean, 'b', 'o', 'o', 'l', 'e', 'a', 'n') + RAPIDJSON_STRING_(Object, 'o', 'b', 'j', 'e', 'c', 't') + RAPIDJSON_STRING_(Array, 'a', 'r', 'r', 'a', 'y') + RAPIDJSON_STRING_(String, 's', 't', 'r', 'i', 'n', 'g') + RAPIDJSON_STRING_(Number, 'n', 'u', 'm', 'b', 'e', 'r') + RAPIDJSON_STRING_(Integer, 'i', 'n', 't', 'e', 'g', 'e', 'r') + RAPIDJSON_STRING_(Type, 't', 'y', 'p', 'e') + RAPIDJSON_STRING_(Enum, 'e', 'n', 'u', 'm') + RAPIDJSON_STRING_(AllOf, 'a', 'l', 'l', 'O', 'f') + RAPIDJSON_STRING_(AnyOf, 'a', 'n', 'y', 'O', 'f') + RAPIDJSON_STRING_(OneOf, 'o', 'n', 'e', 'O', 'f') + RAPIDJSON_STRING_(Not, 'n', 'o', 't') + RAPIDJSON_STRING_(Properties, 'p', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(Required, 'r', 'e', 'q', 'u', 'i', 'r', 'e', 'd') + RAPIDJSON_STRING_(Dependencies, 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'i', 'e', 's') + RAPIDJSON_STRING_(PatternProperties, 'p', 'a', 't', 't', 'e', 'r', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(AdditionalProperties, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(MinProperties, 'm', 'i', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(MaxProperties, 'm', 'a', 'x', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(Items, 'i', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(MinItems, 'm', 'i', 'n', 'I', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(MaxItems, 'm', 'a', 'x', 'I', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(AdditionalItems, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'I', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(UniqueItems, 'u', 'n', 'i', 'q', 'u', 'e', 'I', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(MinLength, 'm', 'i', 'n', 'L', 'e', 'n', 'g', 't', 'h') + RAPIDJSON_STRING_(MaxLength, 'm', 'a', 'x', 'L', 'e', 'n', 'g', 't', 'h') + RAPIDJSON_STRING_(Pattern, 'p', 'a', 't', 't', 'e', 'r', 'n') + RAPIDJSON_STRING_(Minimum, 'm', 'i', 'n', 'i', 'm', 'u', 'm') + RAPIDJSON_STRING_(Maximum, 'm', 'a', 'x', 'i', 'm', 'u', 'm') + RAPIDJSON_STRING_(ExclusiveMinimum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'i', 'n', 'i', 'm', 'u', 'm') + RAPIDJSON_STRING_(ExclusiveMaximum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'a', 'x', 'i', 'm', 'u', 'm') + RAPIDJSON_STRING_(MultipleOf, 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', 'O', 'f') + +#undef RAPIDJSON_STRING_ + +private: + enum SchemaValueType { + kNullSchemaType, + kBooleanSchemaType, + kObjectSchemaType, + kArraySchemaType, + kStringSchemaType, + kNumberSchemaType, + kIntegerSchemaType, + kTotalSchemaType + }; + +#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX + typedef internal::GenericRegex RegexType; +#elif RAPIDJSON_SCHEMA_USE_STDREGEX + typedef std::basic_regex RegexType; +#else + typedef char RegexType; +#endif + + struct SchemaArray { + SchemaArray() : schemas(), count() {} + ~SchemaArray() { AllocatorType::Free(schemas); } + const SchemaType** schemas; + SizeType begin; // begin index of context.validators + SizeType count; + }; + + static const SchemaType* GetTypeless() { + static SchemaType typeless(0, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), 0); + return &typeless; + } + + template + void AddUniqueElement(V1& a, const V2& v) { + for (typename V1::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr) + if (*itr == v) + return; + V1 c(v, *allocator_); + a.PushBack(c, *allocator_); + } + + static const ValueType* GetMember(const ValueType& value, const ValueType& name) { + typename ValueType::ConstMemberIterator itr = value.FindMember(name); + return itr != value.MemberEnd() ? &(itr->value) : 0; + } + + static void AssignIfExist(bool& out, const ValueType& value, const ValueType& name) { + if (const ValueType* v = GetMember(value, name)) + if (v->IsBool()) + out = v->GetBool(); + } + + static void AssignIfExist(SizeType& out, const ValueType& value, const ValueType& name) { + if (const ValueType* v = GetMember(value, name)) + if (v->IsUint64() && v->GetUint64() <= SizeType(~0)) + out = static_cast(v->GetUint64()); + } + + void AssignIfExist(SchemaArray& out, SchemaDocumentType& schemaDocument, const PointerType& p, const ValueType& value, const ValueType& name, const ValueType& document) { + if (const ValueType* v = GetMember(value, name)) { + if (v->IsArray() && v->Size() > 0) { + PointerType q = p.Append(name, allocator_); + out.count = v->Size(); + out.schemas = static_cast(allocator_->Malloc(out.count * sizeof(const Schema*))); + memset(out.schemas, 0, sizeof(Schema*)* out.count); + for (SizeType i = 0; i < out.count; i++) + schemaDocument.CreateSchema(&out.schemas[i], q.Append(i, allocator_), (*v)[i], document); + out.begin = validatorCount_; + validatorCount_ += out.count; + } + } + } + +#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX + template + RegexType* CreatePattern(const ValueType& value) { + if (value.IsString()) { + RegexType* r = new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString()); + if (!r->IsValid()) { + r->~RegexType(); + AllocatorType::Free(r); + r = 0; + } + return r; + } + return 0; + } + + static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType) { + return pattern->Search(str); + } +#elif RAPIDJSON_SCHEMA_USE_STDREGEX + template + RegexType* CreatePattern(const ValueType& value) { + if (value.IsString()) + try { + return new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript); + } + catch (const std::regex_error&) { + } + return 0; + } + + static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType length) { + std::match_results r; + return std::regex_search(str, str + length, r, *pattern); + } +#else + template + RegexType* CreatePattern(const ValueType&) { return 0; } + + static bool IsPatternMatch(const RegexType*, const Ch *, SizeType) { return true; } +#endif // RAPIDJSON_SCHEMA_USE_STDREGEX + + void AddType(const ValueType& type) { + if (type == GetNullString() ) type_ |= 1 << kNullSchemaType; + else if (type == GetBooleanString()) type_ |= 1 << kBooleanSchemaType; + else if (type == GetObjectString() ) type_ |= 1 << kObjectSchemaType; + else if (type == GetArrayString() ) type_ |= 1 << kArraySchemaType; + else if (type == GetStringString() ) type_ |= 1 << kStringSchemaType; + else if (type == GetIntegerString()) type_ |= 1 << kIntegerSchemaType; + else if (type == GetNumberString() ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType); + } + + bool CreateParallelValidator(Context& context) const { + if (enum_ || context.arrayUniqueness) + context.hasher = context.factory.CreateHasher(); + + if (validatorCount_) { + RAPIDJSON_ASSERT(context.validators == 0); + context.validators = static_cast(context.factory.MallocState(sizeof(ISchemaValidator*) * validatorCount_)); + context.validatorCount = validatorCount_; + + if (allOf_.schemas) + CreateSchemaValidators(context, allOf_); + + if (anyOf_.schemas) + CreateSchemaValidators(context, anyOf_); + + if (oneOf_.schemas) + CreateSchemaValidators(context, oneOf_); + + if (not_) + context.validators[notValidatorIndex_] = context.factory.CreateSchemaValidator(*not_); + + if (hasSchemaDependencies_) { + for (SizeType i = 0; i < propertyCount_; i++) + if (properties_[i].dependenciesSchema) + context.validators[properties_[i].dependenciesValidatorIndex] = context.factory.CreateSchemaValidator(*properties_[i].dependenciesSchema); + } + } + + return true; + } + + void CreateSchemaValidators(Context& context, const SchemaArray& schemas) const { + for (SizeType i = 0; i < schemas.count; i++) + context.validators[schemas.begin + i] = context.factory.CreateSchemaValidator(*schemas.schemas[i]); + } + + // O(n) + bool FindPropertyIndex(const ValueType& name, SizeType* outIndex) const { + SizeType len = name.GetStringLength(); + const Ch* str = name.GetString(); + for (SizeType index = 0; index < propertyCount_; index++) + if (properties_[index].name.GetStringLength() == len && + (std::memcmp(properties_[index].name.GetString(), str, sizeof(Ch) * len) == 0)) + { + *outIndex = index; + return true; + } + return false; + } + + bool CheckInt(Context& context, int64_t i) const { + if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + + if (!minimum_.IsNull()) { + if (minimum_.IsInt64()) { + if (exclusiveMinimum_ ? i <= minimum_.GetInt64() : i < minimum_.GetInt64()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); + } + else if (minimum_.IsUint64()) { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); // i <= max(int64_t) < minimum.GetUint64() + } + else if (!CheckDoubleMinimum(context, static_cast(i))) + return false; + } + + if (!maximum_.IsNull()) { + if (maximum_.IsInt64()) { + if (exclusiveMaximum_ ? i >= maximum_.GetInt64() : i > maximum_.GetInt64()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); + } + else if (maximum_.IsUint64()) + /* do nothing */; // i <= max(int64_t) < maximum_.GetUint64() + else if (!CheckDoubleMaximum(context, static_cast(i))) + return false; + } + + if (!multipleOf_.IsNull()) { + if (multipleOf_.IsUint64()) { + if (static_cast(i >= 0 ? i : -i) % multipleOf_.GetUint64() != 0) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString()); + } + else if (!CheckDoubleMultipleOf(context, static_cast(i))) + return false; + } + + return true; + } + + bool CheckUint(Context& context, uint64_t i) const { + if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + + if (!minimum_.IsNull()) { + if (minimum_.IsUint64()) { + if (exclusiveMinimum_ ? i <= minimum_.GetUint64() : i < minimum_.GetUint64()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); + } + else if (minimum_.IsInt64()) + /* do nothing */; // i >= 0 > minimum.Getint64() + else if (!CheckDoubleMinimum(context, static_cast(i))) + return false; + } + + if (!maximum_.IsNull()) { + if (maximum_.IsUint64()) { + if (exclusiveMaximum_ ? i >= maximum_.GetUint64() : i > maximum_.GetUint64()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); + } + else if (maximum_.IsInt64()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); // i >= 0 > maximum_ + else if (!CheckDoubleMaximum(context, static_cast(i))) + return false; + } + + if (!multipleOf_.IsNull()) { + if (multipleOf_.IsUint64()) { + if (i % multipleOf_.GetUint64() != 0) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString()); + } + else if (!CheckDoubleMultipleOf(context, static_cast(i))) + return false; + } + + return true; + } + + bool CheckDoubleMinimum(Context& context, double d) const { + if (exclusiveMinimum_ ? d <= minimum_.GetDouble() : d < minimum_.GetDouble()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); + return true; + } + + bool CheckDoubleMaximum(Context& context, double d) const { + if (exclusiveMaximum_ ? d >= maximum_.GetDouble() : d > maximum_.GetDouble()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); + return true; + } + + bool CheckDoubleMultipleOf(Context& context, double d) const { + double a = std::abs(d), b = std::abs(multipleOf_.GetDouble()); + double q = std::floor(a / b); + double r = a - q * b; + if (r > 0.0) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString()); + return true; + } + + struct Property { + Property() : schema(), dependenciesSchema(), dependenciesValidatorIndex(), dependencies(), required(false) {} + ~Property() { AllocatorType::Free(dependencies); } + SValue name; + const SchemaType* schema; + const SchemaType* dependenciesSchema; + SizeType dependenciesValidatorIndex; + bool* dependencies; + bool required; + }; + + struct PatternProperty { + PatternProperty() : schema(), pattern() {} + ~PatternProperty() { + if (pattern) { + pattern->~RegexType(); + AllocatorType::Free(pattern); + } + } + const SchemaType* schema; + RegexType* pattern; + }; + + AllocatorType* allocator_; + uint64_t* enum_; + SizeType enumCount_; + SchemaArray allOf_; + SchemaArray anyOf_; + SchemaArray oneOf_; + const SchemaType* not_; + unsigned type_; // bitmask of kSchemaType + SizeType validatorCount_; + SizeType notValidatorIndex_; + + Property* properties_; + const SchemaType* additionalPropertiesSchema_; + PatternProperty* patternProperties_; + SizeType patternPropertyCount_; + SizeType propertyCount_; + SizeType minProperties_; + SizeType maxProperties_; + bool additionalProperties_; + bool hasDependencies_; + bool hasRequired_; + bool hasSchemaDependencies_; + + const SchemaType* additionalItemsSchema_; + const SchemaType* itemsList_; + const SchemaType** itemsTuple_; + SizeType itemsTupleCount_; + SizeType minItems_; + SizeType maxItems_; + bool additionalItems_; + bool uniqueItems_; + + RegexType* pattern_; + SizeType minLength_; + SizeType maxLength_; + + SValue minimum_; + SValue maximum_; + SValue multipleOf_; + bool exclusiveMinimum_; + bool exclusiveMaximum_; +}; + +template +struct TokenHelper { + RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) { + *documentStack.template Push() = '/'; + char buffer[21]; + size_t length = static_cast((sizeof(SizeType) == 4 ? u32toa(index, buffer) : u64toa(index, buffer)) - buffer); + for (size_t i = 0; i < length; i++) + *documentStack.template Push() = buffer[i]; + } +}; + +// Partial specialized version for char to prevent buffer copying. +template +struct TokenHelper { + RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) { + if (sizeof(SizeType) == 4) { + char *buffer = documentStack.template Push(1 + 10); // '/' + uint + *buffer++ = '/'; + const char* end = internal::u32toa(index, buffer); + documentStack.template Pop(static_cast(10 - (end - buffer))); + } + else { + char *buffer = documentStack.template Push(1 + 20); // '/' + uint64 + *buffer++ = '/'; + const char* end = internal::u64toa(index, buffer); + documentStack.template Pop(static_cast(20 - (end - buffer))); + } + } +}; + +} // namespace internal + +/////////////////////////////////////////////////////////////////////////////// +// IGenericRemoteSchemaDocumentProvider + +template +class IGenericRemoteSchemaDocumentProvider { +public: + typedef typename SchemaDocumentType::Ch Ch; + + virtual ~IGenericRemoteSchemaDocumentProvider() {} + virtual const SchemaDocumentType* GetRemoteDocument(const Ch* uri, SizeType length) = 0; +}; + +/////////////////////////////////////////////////////////////////////////////// +// GenericSchemaDocument + +//! JSON schema document. +/*! + A JSON schema document is a compiled version of a JSON schema. + It is basically a tree of internal::Schema. + + \note This is an immutable class (i.e. its instance cannot be modified after construction). + \tparam ValueT Type of JSON value (e.g. \c Value ), which also determine the encoding. + \tparam Allocator Allocator type for allocating memory of this document. +*/ +template +class GenericSchemaDocument { +public: + typedef ValueT ValueType; + typedef IGenericRemoteSchemaDocumentProvider IRemoteSchemaDocumentProviderType; + typedef Allocator AllocatorType; + typedef typename ValueType::EncodingType EncodingType; + typedef typename EncodingType::Ch Ch; + typedef internal::Schema SchemaType; + typedef GenericPointer PointerType; + friend class internal::Schema; + template + friend class GenericSchemaValidator; + + //! Constructor. + /*! + Compile a JSON document into schema document. + + \param document A JSON document as source. + \param remoteProvider An optional remote schema document provider for resolving remote reference. Can be null. + \param allocator An optional allocator instance for allocating memory. Can be null. + */ + explicit GenericSchemaDocument(const ValueType& document, IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0) : + remoteProvider_(remoteProvider), + allocator_(allocator), + ownAllocator_(), + root_(), + schemaMap_(allocator, kInitialSchemaMapSize), + schemaRef_(allocator, kInitialSchemaRefSize) + { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + + // Generate root schema, it will call CreateSchema() to create sub-schemas, + // And call AddRefSchema() if there are $ref. + CreateSchemaRecursive(&root_, PointerType(), document, document); + + // Resolve $ref + while (!schemaRef_.Empty()) { + SchemaRefEntry* refEntry = schemaRef_.template Pop(1); + if (const SchemaType* s = GetSchema(refEntry->target)) { + if (refEntry->schema) + *refEntry->schema = s; + + // Create entry in map if not exist + if (!GetSchema(refEntry->source)) { + new (schemaMap_.template Push()) SchemaEntry(refEntry->source, const_cast(s), false, allocator_); + } + } + refEntry->~SchemaRefEntry(); + } + + RAPIDJSON_ASSERT(root_ != 0); + + schemaRef_.ShrinkToFit(); // Deallocate all memory for ref + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move constructor in C++11 + GenericSchemaDocument(GenericSchemaDocument&& rhs) RAPIDJSON_NOEXCEPT : + remoteProvider_(rhs.remoteProvider_), + allocator_(rhs.allocator_), + ownAllocator_(rhs.ownAllocator_), + root_(rhs.root_), + schemaMap_(std::move(rhs.schemaMap_)), + schemaRef_(std::move(rhs.schemaRef_)) + { + rhs.remoteProvider_ = 0; + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + } +#endif + + //! Destructor + ~GenericSchemaDocument() { + while (!schemaMap_.Empty()) + schemaMap_.template Pop(1)->~SchemaEntry(); + + RAPIDJSON_DELETE(ownAllocator_); + } + + //! Get the root schema. + const SchemaType& GetRoot() const { return *root_; } + +private: + //! Prohibit copying + GenericSchemaDocument(const GenericSchemaDocument&); + //! Prohibit assignment + GenericSchemaDocument& operator=(const GenericSchemaDocument&); + + struct SchemaRefEntry { + SchemaRefEntry(const PointerType& s, const PointerType& t, const SchemaType** outSchema, Allocator *allocator) : source(s, allocator), target(t, allocator), schema(outSchema) {} + PointerType source; + PointerType target; + const SchemaType** schema; + }; + + struct SchemaEntry { + SchemaEntry(const PointerType& p, SchemaType* s, bool o, Allocator* allocator) : pointer(p, allocator), schema(s), owned(o) {} + ~SchemaEntry() { + if (owned) { + schema->~SchemaType(); + Allocator::Free(schema); + } + } + PointerType pointer; + SchemaType* schema; + bool owned; + }; + + void CreateSchemaRecursive(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) { + if (schema) + *schema = SchemaType::GetTypeless(); + + if (v.GetType() == kObjectType) { + const SchemaType* s = GetSchema(pointer); + if (!s) + CreateSchema(schema, pointer, v, document); + + for (typename ValueType::ConstMemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); ++itr) + CreateSchemaRecursive(0, pointer.Append(itr->name, allocator_), itr->value, document); + } + else if (v.GetType() == kArrayType) + for (SizeType i = 0; i < v.Size(); i++) + CreateSchemaRecursive(0, pointer.Append(i, allocator_), v[i], document); + } + + void CreateSchema(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) { + RAPIDJSON_ASSERT(pointer.IsValid()); + if (v.IsObject()) { + if (!HandleRefSchema(pointer, schema, v, document)) { + SchemaType* s = new (allocator_->Malloc(sizeof(SchemaType))) SchemaType(this, pointer, v, document, allocator_); + new (schemaMap_.template Push()) SchemaEntry(pointer, s, true, allocator_); + if (schema) + *schema = s; + } + } + } + + bool HandleRefSchema(const PointerType& source, const SchemaType** schema, const ValueType& v, const ValueType& document) { + static const Ch kRefString[] = { '$', 'r', 'e', 'f', '\0' }; + static const ValueType kRefValue(kRefString, 4); + + typename ValueType::ConstMemberIterator itr = v.FindMember(kRefValue); + if (itr == v.MemberEnd()) + return false; + + if (itr->value.IsString()) { + SizeType len = itr->value.GetStringLength(); + if (len > 0) { + const Ch* s = itr->value.GetString(); + SizeType i = 0; + while (i < len && s[i] != '#') // Find the first # + i++; + + if (i > 0) { // Remote reference, resolve immediately + if (remoteProvider_) { + if (const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(s, i - 1)) { + PointerType pointer(&s[i], len - i, allocator_); + if (pointer.IsValid()) { + if (const SchemaType* sc = remoteDocument->GetSchema(pointer)) { + if (schema) + *schema = sc; + return true; + } + } + } + } + } + else if (s[i] == '#') { // Local reference, defer resolution + PointerType pointer(&s[i], len - i, allocator_); + if (pointer.IsValid()) { + if (const ValueType* nv = pointer.Get(document)) + if (HandleRefSchema(source, schema, *nv, document)) + return true; + + new (schemaRef_.template Push()) SchemaRefEntry(source, pointer, schema, allocator_); + return true; + } + } + } + } + return false; + } + + const SchemaType* GetSchema(const PointerType& pointer) const { + for (const SchemaEntry* target = schemaMap_.template Bottom(); target != schemaMap_.template End(); ++target) + if (pointer == target->pointer) + return target->schema; + return 0; + } + + PointerType GetPointer(const SchemaType* schema) const { + for (const SchemaEntry* target = schemaMap_.template Bottom(); target != schemaMap_.template End(); ++target) + if (schema == target->schema) + return target->pointer; + return PointerType(); + } + + static const size_t kInitialSchemaMapSize = 64; + static const size_t kInitialSchemaRefSize = 64; + + IRemoteSchemaDocumentProviderType* remoteProvider_; + Allocator *allocator_; + Allocator *ownAllocator_; + const SchemaType* root_; //!< Root schema. + internal::Stack schemaMap_; // Stores created Pointer -> Schemas + internal::Stack schemaRef_; // Stores Pointer from $ref and schema which holds the $ref +}; + +//! GenericSchemaDocument using Value type. +typedef GenericSchemaDocument SchemaDocument; +//! IGenericRemoteSchemaDocumentProvider using SchemaDocument. +typedef IGenericRemoteSchemaDocumentProvider IRemoteSchemaDocumentProvider; + +/////////////////////////////////////////////////////////////////////////////// +// GenericSchemaValidator + +//! JSON Schema Validator. +/*! + A SAX style JSON schema validator. + It uses a \c GenericSchemaDocument to validate SAX events. + It delegates the incoming SAX events to an output handler. + The default output handler does nothing. + It can be reused multiple times by calling \c Reset(). + + \tparam SchemaDocumentType Type of schema document. + \tparam OutputHandler Type of output handler. Default handler does nothing. + \tparam StateAllocator Allocator for storing the internal validation states. +*/ +template < + typename SchemaDocumentType, + typename OutputHandler = BaseReaderHandler, + typename StateAllocator = CrtAllocator> +class GenericSchemaValidator : + public internal::ISchemaStateFactory, + public internal::ISchemaValidator +{ +public: + typedef typename SchemaDocumentType::SchemaType SchemaType; + typedef typename SchemaDocumentType::PointerType PointerType; + typedef typename SchemaType::EncodingType EncodingType; + typedef typename EncodingType::Ch Ch; + + //! Constructor without output handler. + /*! + \param schemaDocument The schema document to conform to. + \param allocator Optional allocator for storing internal validation states. + \param schemaStackCapacity Optional initial capacity of schema path stack. + \param documentStackCapacity Optional initial capacity of document path stack. + */ + GenericSchemaValidator( + const SchemaDocumentType& schemaDocument, + StateAllocator* allocator = 0, + size_t schemaStackCapacity = kDefaultSchemaStackCapacity, + size_t documentStackCapacity = kDefaultDocumentStackCapacity) + : + schemaDocument_(&schemaDocument), + root_(schemaDocument.GetRoot()), + outputHandler_(GetNullHandler()), + stateAllocator_(allocator), + ownStateAllocator_(0), + schemaStack_(allocator, schemaStackCapacity), + documentStack_(allocator, documentStackCapacity), + valid_(true) +#if RAPIDJSON_SCHEMA_VERBOSE + , depth_(0) +#endif + { + } + + //! Constructor with output handler. + /*! + \param schemaDocument The schema document to conform to. + \param allocator Optional allocator for storing internal validation states. + \param schemaStackCapacity Optional initial capacity of schema path stack. + \param documentStackCapacity Optional initial capacity of document path stack. + */ + GenericSchemaValidator( + const SchemaDocumentType& schemaDocument, + OutputHandler& outputHandler, + StateAllocator* allocator = 0, + size_t schemaStackCapacity = kDefaultSchemaStackCapacity, + size_t documentStackCapacity = kDefaultDocumentStackCapacity) + : + schemaDocument_(&schemaDocument), + root_(schemaDocument.GetRoot()), + outputHandler_(outputHandler), + stateAllocator_(allocator), + ownStateAllocator_(0), + schemaStack_(allocator, schemaStackCapacity), + documentStack_(allocator, documentStackCapacity), + valid_(true) +#if RAPIDJSON_SCHEMA_VERBOSE + , depth_(0) +#endif + { + } + + //! Destructor. + ~GenericSchemaValidator() { + Reset(); + RAPIDJSON_DELETE(ownStateAllocator_); + } + + //! Reset the internal states. + void Reset() { + while (!schemaStack_.Empty()) + PopSchema(); + documentStack_.Clear(); + valid_ = true; + } + + //! Checks whether the current state is valid. + // Implementation of ISchemaValidator + virtual bool IsValid() const { return valid_; } + + //! Gets the JSON pointer pointed to the invalid schema. + PointerType GetInvalidSchemaPointer() const { + return schemaStack_.Empty() ? PointerType() : schemaDocument_->GetPointer(&CurrentSchema()); + } + + //! Gets the keyword of invalid schema. + const Ch* GetInvalidSchemaKeyword() const { + return schemaStack_.Empty() ? 0 : CurrentContext().invalidKeyword; + } + + //! Gets the JSON pointer pointed to the invalid value. + PointerType GetInvalidDocumentPointer() const { + return documentStack_.Empty() ? PointerType() : PointerType(documentStack_.template Bottom(), documentStack_.GetSize() / sizeof(Ch)); + } + +#if RAPIDJSON_SCHEMA_VERBOSE +#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() \ +RAPIDJSON_MULTILINEMACRO_BEGIN\ + *documentStack_.template Push() = '\0';\ + documentStack_.template Pop(1);\ + internal::PrintInvalidDocument(documentStack_.template Bottom());\ +RAPIDJSON_MULTILINEMACRO_END +#else +#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() +#endif + +#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1)\ + if (!valid_) return false; \ + if (!BeginValue() || !CurrentSchema().method arg1) {\ + RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_();\ + return valid_ = false;\ + } + +#define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\ + for (Context* context = schemaStack_.template Bottom(); context != schemaStack_.template End(); context++) {\ + if (context->hasher)\ + static_cast(context->hasher)->method arg2;\ + if (context->validators)\ + for (SizeType i_ = 0; i_ < context->validatorCount; i_++)\ + static_cast(context->validators[i_])->method arg2;\ + if (context->patternPropertiesValidators)\ + for (SizeType i_ = 0; i_ < context->patternPropertiesValidatorCount; i_++)\ + static_cast(context->patternPropertiesValidators[i_])->method arg2;\ + } + +#define RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)\ + return valid_ = EndValue() && outputHandler_.method arg2 + +#define RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2) \ + RAPIDJSON_SCHEMA_HANDLE_BEGIN_ (method, arg1);\ + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2);\ + RAPIDJSON_SCHEMA_HANDLE_END_ (method, arg2) + + bool Null() { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Null, (CurrentContext() ), ( )); } + bool Bool(bool b) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Bool, (CurrentContext(), b), (b)); } + bool Int(int i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int, (CurrentContext(), i), (i)); } + bool Uint(unsigned u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint, (CurrentContext(), u), (u)); } + bool Int64(int64_t i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int64, (CurrentContext(), i), (i)); } + bool Uint64(uint64_t u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint64, (CurrentContext(), u), (u)); } + bool Double(double d) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Double, (CurrentContext(), d), (d)); } + bool RawNumber(const Ch* str, SizeType length, bool copy) + { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); } + bool String(const Ch* str, SizeType length, bool copy) + { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); } + + bool StartObject() { + RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartObject, (CurrentContext())); + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartObject, ()); + return valid_ = outputHandler_.StartObject(); + } + + bool Key(const Ch* str, SizeType len, bool copy) { + if (!valid_) return false; + AppendToken(str, len); + if (!CurrentSchema().Key(CurrentContext(), str, len, copy)) return valid_ = false; + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(Key, (str, len, copy)); + return valid_ = outputHandler_.Key(str, len, copy); + } + + bool EndObject(SizeType memberCount) { + if (!valid_) return false; + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndObject, (memberCount)); + if (!CurrentSchema().EndObject(CurrentContext(), memberCount)) return valid_ = false; + RAPIDJSON_SCHEMA_HANDLE_END_(EndObject, (memberCount)); + } + + bool StartArray() { + RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartArray, (CurrentContext())); + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartArray, ()); + return valid_ = outputHandler_.StartArray(); + } + + bool EndArray(SizeType elementCount) { + if (!valid_) return false; + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndArray, (elementCount)); + if (!CurrentSchema().EndArray(CurrentContext(), elementCount)) return valid_ = false; + RAPIDJSON_SCHEMA_HANDLE_END_(EndArray, (elementCount)); + } + +#undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_ +#undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_ +#undef RAPIDJSON_SCHEMA_HANDLE_PARALLEL_ +#undef RAPIDJSON_SCHEMA_HANDLE_VALUE_ + + // Implementation of ISchemaStateFactory + virtual ISchemaValidator* CreateSchemaValidator(const SchemaType& root) { + return new (GetStateAllocator().Malloc(sizeof(GenericSchemaValidator))) GenericSchemaValidator(*schemaDocument_, root, +#if RAPIDJSON_SCHEMA_VERBOSE + depth_ + 1, +#endif + &GetStateAllocator()); + } + + virtual void DestroySchemaValidator(ISchemaValidator* validator) { + GenericSchemaValidator* v = static_cast(validator); + v->~GenericSchemaValidator(); + StateAllocator::Free(v); + } + + virtual void* CreateHasher() { + return new (GetStateAllocator().Malloc(sizeof(HasherType))) HasherType(&GetStateAllocator()); + } + + virtual uint64_t GetHashCode(void* hasher) { + return static_cast(hasher)->GetHashCode(); + } + + virtual void DestroryHasher(void* hasher) { + HasherType* h = static_cast(hasher); + h->~HasherType(); + StateAllocator::Free(h); + } + + virtual void* MallocState(size_t size) { + return GetStateAllocator().Malloc(size); + } + + virtual void FreeState(void* p) { + return StateAllocator::Free(p); + } + +private: + typedef typename SchemaType::Context Context; + typedef GenericValue, StateAllocator> HashCodeArray; + typedef internal::Hasher HasherType; + + GenericSchemaValidator( + const SchemaDocumentType& schemaDocument, + const SchemaType& root, +#if RAPIDJSON_SCHEMA_VERBOSE + unsigned depth, +#endif + StateAllocator* allocator = 0, + size_t schemaStackCapacity = kDefaultSchemaStackCapacity, + size_t documentStackCapacity = kDefaultDocumentStackCapacity) + : + schemaDocument_(&schemaDocument), + root_(root), + outputHandler_(GetNullHandler()), + stateAllocator_(allocator), + ownStateAllocator_(0), + schemaStack_(allocator, schemaStackCapacity), + documentStack_(allocator, documentStackCapacity), + valid_(true) +#if RAPIDJSON_SCHEMA_VERBOSE + , depth_(depth) +#endif + { + } + + StateAllocator& GetStateAllocator() { + if (!stateAllocator_) + stateAllocator_ = ownStateAllocator_ = RAPIDJSON_NEW(StateAllocator()); + return *stateAllocator_; + } + + bool BeginValue() { + if (schemaStack_.Empty()) + PushSchema(root_); + else { + if (CurrentContext().inArray) + internal::TokenHelper, Ch>::AppendIndexToken(documentStack_, CurrentContext().arrayElementIndex); + + if (!CurrentSchema().BeginValue(CurrentContext())) + return false; + + SizeType count = CurrentContext().patternPropertiesSchemaCount; + const SchemaType** sa = CurrentContext().patternPropertiesSchemas; + typename Context::PatternValidatorType patternValidatorType = CurrentContext().valuePatternValidatorType; + bool valueUniqueness = CurrentContext().valueUniqueness; + if (CurrentContext().valueSchema) + PushSchema(*CurrentContext().valueSchema); + + if (count > 0) { + CurrentContext().objectPatternValidatorType = patternValidatorType; + ISchemaValidator**& va = CurrentContext().patternPropertiesValidators; + SizeType& validatorCount = CurrentContext().patternPropertiesValidatorCount; + va = static_cast(MallocState(sizeof(ISchemaValidator*) * count)); + for (SizeType i = 0; i < count; i++) + va[validatorCount++] = CreateSchemaValidator(*sa[i]); + } + + CurrentContext().arrayUniqueness = valueUniqueness; + } + return true; + } + + bool EndValue() { + if (!CurrentSchema().EndValue(CurrentContext())) + return false; + +#if RAPIDJSON_SCHEMA_VERBOSE + GenericStringBuffer sb; + schemaDocument_->GetPointer(&CurrentSchema()).Stringify(sb); + + *documentStack_.template Push() = '\0'; + documentStack_.template Pop(1); + internal::PrintValidatorPointers(depth_, sb.GetString(), documentStack_.template Bottom()); +#endif + + uint64_t h = CurrentContext().arrayUniqueness ? static_cast(CurrentContext().hasher)->GetHashCode() : 0; + + PopSchema(); + + if (!schemaStack_.Empty()) { + Context& context = CurrentContext(); + if (context.valueUniqueness) { + HashCodeArray* a = static_cast(context.arrayElementHashCodes); + if (!a) + CurrentContext().arrayElementHashCodes = a = new (GetStateAllocator().Malloc(sizeof(HashCodeArray))) HashCodeArray(kArrayType); + for (typename HashCodeArray::ConstValueIterator itr = a->Begin(); itr != a->End(); ++itr) + if (itr->GetUint64() == h) + RAPIDJSON_INVALID_KEYWORD_RETURN(SchemaType::GetUniqueItemsString()); + a->PushBack(h, GetStateAllocator()); + } + } + + // Remove the last token of document pointer + while (!documentStack_.Empty() && *documentStack_.template Pop(1) != '/') + ; + + return true; + } + + void AppendToken(const Ch* str, SizeType len) { + documentStack_.template Reserve(1 + len * 2); // worst case all characters are escaped as two characters + *documentStack_.template PushUnsafe() = '/'; + for (SizeType i = 0; i < len; i++) { + if (str[i] == '~') { + *documentStack_.template PushUnsafe() = '~'; + *documentStack_.template PushUnsafe() = '0'; + } + else if (str[i] == '/') { + *documentStack_.template PushUnsafe() = '~'; + *documentStack_.template PushUnsafe() = '1'; + } + else + *documentStack_.template PushUnsafe() = str[i]; + } + } + + RAPIDJSON_FORCEINLINE void PushSchema(const SchemaType& schema) { new (schemaStack_.template Push()) Context(*this, &schema); } + + RAPIDJSON_FORCEINLINE void PopSchema() { + Context* c = schemaStack_.template Pop(1); + if (HashCodeArray* a = static_cast(c->arrayElementHashCodes)) { + a->~HashCodeArray(); + StateAllocator::Free(a); + } + c->~Context(); + } + + const SchemaType& CurrentSchema() const { return *schemaStack_.template Top()->schema; } + Context& CurrentContext() { return *schemaStack_.template Top(); } + const Context& CurrentContext() const { return *schemaStack_.template Top(); } + + static OutputHandler& GetNullHandler() { + static OutputHandler nullHandler; + return nullHandler; + } + + static const size_t kDefaultSchemaStackCapacity = 1024; + static const size_t kDefaultDocumentStackCapacity = 256; + const SchemaDocumentType* schemaDocument_; + const SchemaType& root_; + OutputHandler& outputHandler_; + StateAllocator* stateAllocator_; + StateAllocator* ownStateAllocator_; + internal::Stack schemaStack_; //!< stack to store the current path of schema (BaseSchemaType *) + internal::Stack documentStack_; //!< stack to store the current path of validating document (Ch) + bool valid_; +#if RAPIDJSON_SCHEMA_VERBOSE + unsigned depth_; +#endif +}; + +typedef GenericSchemaValidator SchemaValidator; + +/////////////////////////////////////////////////////////////////////////////// +// SchemaValidatingReader + +//! A helper class for parsing with validation. +/*! + This helper class is a functor, designed as a parameter of \ref GenericDocument::Populate(). + + \tparam parseFlags Combination of \ref ParseFlag. + \tparam InputStream Type of input stream, implementing Stream concept. + \tparam SourceEncoding Encoding of the input stream. + \tparam SchemaDocumentType Type of schema document. + \tparam StackAllocator Allocator type for stack. +*/ +template < + unsigned parseFlags, + typename InputStream, + typename SourceEncoding, + typename SchemaDocumentType = SchemaDocument, + typename StackAllocator = CrtAllocator> +class SchemaValidatingReader { +public: + typedef typename SchemaDocumentType::PointerType PointerType; + typedef typename InputStream::Ch Ch; + + //! Constructor + /*! + \param is Input stream. + \param sd Schema document. + */ + SchemaValidatingReader(InputStream& is, const SchemaDocumentType& sd) : is_(is), sd_(sd), invalidSchemaKeyword_(), isValid_(true) {} + + template + bool operator()(Handler& handler) { + GenericReader reader; + GenericSchemaValidator validator(sd_, handler); + parseResult_ = reader.template Parse(is_, validator); + + isValid_ = validator.IsValid(); + if (isValid_) { + invalidSchemaPointer_ = PointerType(); + invalidSchemaKeyword_ = 0; + invalidDocumentPointer_ = PointerType(); + } + else { + invalidSchemaPointer_ = validator.GetInvalidSchemaPointer(); + invalidSchemaKeyword_ = validator.GetInvalidSchemaKeyword(); + invalidDocumentPointer_ = validator.GetInvalidDocumentPointer(); + } + + return parseResult_; + } + + const ParseResult& GetParseResult() const { return parseResult_; } + bool IsValid() const { return isValid_; } + const PointerType& GetInvalidSchemaPointer() const { return invalidSchemaPointer_; } + const Ch* GetInvalidSchemaKeyword() const { return invalidSchemaKeyword_; } + const PointerType& GetInvalidDocumentPointer() const { return invalidDocumentPointer_; } + +private: + InputStream& is_; + const SchemaDocumentType& sd_; + + ParseResult parseResult_; + PointerType invalidSchemaPointer_; + const Ch* invalidSchemaKeyword_; + PointerType invalidDocumentPointer_; + bool isValid_; +}; + +RAPIDJSON_NAMESPACE_END +RAPIDJSON_DIAG_POP + +#endif // RAPIDJSON_SCHEMA_H_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/stream.h b/Externals/discord-rpc/thirdparty/include/rapidjson/stream.h new file mode 100644 index 0000000000..fef82c252f --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/stream.h @@ -0,0 +1,179 @@ +// 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. + +#include "rapidjson.h" + +#ifndef RAPIDJSON_STREAM_H_ +#define RAPIDJSON_STREAM_H_ + +#include "encodings.h" + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Stream + +/*! \class rapidjson::Stream + \brief Concept for reading and writing characters. + + For read-only stream, no need to implement PutBegin(), Put(), Flush() and PutEnd(). + + For write-only stream, only need to implement Put() and Flush(). + +\code +concept Stream { + typename Ch; //!< Character type of the stream. + + //! Read the current character from stream without moving the read cursor. + Ch Peek() const; + + //! Read the current character from stream and moving the read cursor to next character. + Ch Take(); + + //! Get the current read cursor. + //! \return Number of characters read from start. + size_t Tell(); + + //! Begin writing operation at the current read pointer. + //! \return The begin writer pointer. + Ch* PutBegin(); + + //! Write a character. + void Put(Ch c); + + //! Flush the buffer. + void Flush(); + + //! End the writing operation. + //! \param begin The begin write pointer returned by PutBegin(). + //! \return Number of characters written. + size_t PutEnd(Ch* begin); +} +\endcode +*/ + +//! Provides additional information for stream. +/*! + By using traits pattern, this type provides a default configuration for stream. + For custom stream, this type can be specialized for other configuration. + See TEST(Reader, CustomStringStream) in readertest.cpp for example. +*/ +template +struct StreamTraits { + //! Whether to make local copy of stream for optimization during parsing. + /*! + By default, for safety, streams do not use local copy optimization. + Stream that can be copied fast should specialize this, like StreamTraits. + */ + enum { copyOptimization = 0 }; +}; + +//! Reserve n characters for writing to a stream. +template +inline void PutReserve(Stream& stream, size_t count) { + (void)stream; + (void)count; +} + +//! Write character to a stream, presuming buffer is reserved. +template +inline void PutUnsafe(Stream& stream, typename Stream::Ch c) { + stream.Put(c); +} + +//! Put N copies of a character to a stream. +template +inline void PutN(Stream& stream, Ch c, size_t n) { + PutReserve(stream, n); + for (size_t i = 0; i < n; i++) + PutUnsafe(stream, c); +} + +/////////////////////////////////////////////////////////////////////////////// +// StringStream + +//! Read-only string stream. +/*! \note implements Stream concept +*/ +template +struct GenericStringStream { + typedef typename Encoding::Ch Ch; + + GenericStringStream(const Ch *src) : src_(src), head_(src) {} + + Ch Peek() const { return *src_; } + Ch Take() { return *src_++; } + size_t Tell() const { return static_cast(src_ - head_); } + + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + const Ch* src_; //!< Current read position. + const Ch* head_; //!< Original head of the string. +}; + +template +struct StreamTraits > { + enum { copyOptimization = 1 }; +}; + +//! String stream with UTF8 encoding. +typedef GenericStringStream > StringStream; + +/////////////////////////////////////////////////////////////////////////////// +// InsituStringStream + +//! A read-write string stream. +/*! This string stream is particularly designed for in-situ parsing. + \note implements Stream concept +*/ +template +struct GenericInsituStringStream { + typedef typename Encoding::Ch Ch; + + GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {} + + // Read + Ch Peek() { return *src_; } + Ch Take() { return *src_++; } + size_t Tell() { return static_cast(src_ - head_); } + + // Write + void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; } + + Ch* PutBegin() { return dst_ = src_; } + size_t PutEnd(Ch* begin) { return static_cast(dst_ - begin); } + void Flush() {} + + Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; } + void Pop(size_t count) { dst_ -= count; } + + Ch* src_; + Ch* dst_; + Ch* head_; +}; + +template +struct StreamTraits > { + enum { copyOptimization = 1 }; +}; + +//! Insitu string stream with UTF8 encoding. +typedef GenericInsituStringStream > InsituStringStream; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_STREAM_H_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/stringbuffer.h b/Externals/discord-rpc/thirdparty/include/rapidjson/stringbuffer.h new file mode 100644 index 0000000000..78f34d2098 --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/stringbuffer.h @@ -0,0 +1,117 @@ +// 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_STRINGBUFFER_H_ +#define RAPIDJSON_STRINGBUFFER_H_ + +#include "stream.h" +#include "internal/stack.h" + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS +#include // std::move +#endif + +#include "internal/stack.h" + +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Represents an in-memory output stream. +/*! + \tparam Encoding Encoding of the stream. + \tparam Allocator type for allocating memory buffer. + \note implements Stream concept +*/ +template +class GenericStringBuffer { +public: + typedef typename Encoding::Ch Ch; + + GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {} + GenericStringBuffer& operator=(GenericStringBuffer&& rhs) { + if (&rhs != this) + stack_ = std::move(rhs.stack_); + return *this; + } +#endif + + void Put(Ch c) { *stack_.template Push() = c; } + void PutUnsafe(Ch c) { *stack_.template PushUnsafe() = c; } + void Flush() {} + + void Clear() { stack_.Clear(); } + void ShrinkToFit() { + // Push and pop a null terminator. This is safe. + *stack_.template Push() = '\0'; + stack_.ShrinkToFit(); + stack_.template Pop(1); + } + + void Reserve(size_t count) { stack_.template Reserve(count); } + Ch* Push(size_t count) { return stack_.template Push(count); } + Ch* PushUnsafe(size_t count) { return stack_.template PushUnsafe(count); } + void Pop(size_t count) { stack_.template Pop(count); } + + const Ch* GetString() const { + // Push and pop a null terminator. This is safe. + *stack_.template Push() = '\0'; + stack_.template Pop(1); + + return stack_.template Bottom(); + } + + size_t GetSize() const { return stack_.GetSize(); } + + static const size_t kDefaultCapacity = 256; + mutable internal::Stack stack_; + +private: + // Prohibit copy constructor & assignment operator. + GenericStringBuffer(const GenericStringBuffer&); + GenericStringBuffer& operator=(const GenericStringBuffer&); +}; + +//! String buffer with UTF8 encoding +typedef GenericStringBuffer > StringBuffer; + +template +inline void PutReserve(GenericStringBuffer& stream, size_t count) { + stream.Reserve(count); +} + +template +inline void PutUnsafe(GenericStringBuffer& stream, typename Encoding::Ch c) { + stream.PutUnsafe(c); +} + +//! Implement specialized version of PutN() with memset() for better performance. +template<> +inline void PutN(GenericStringBuffer >& stream, char c, size_t n) { + std::memset(stream.stack_.Push(n), c, n * sizeof(c)); +} + +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_STRINGBUFFER_H_ diff --git a/Externals/discord-rpc/thirdparty/include/rapidjson/writer.h b/Externals/discord-rpc/thirdparty/include/rapidjson/writer.h new file mode 100644 index 0000000000..94f22dd5fc --- /dev/null +++ b/Externals/discord-rpc/thirdparty/include/rapidjson/writer.h @@ -0,0 +1,610 @@ +// 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_WRITER_H_ +#define RAPIDJSON_WRITER_H_ + +#include "stream.h" +#include "internal/stack.h" +#include "internal/strfunc.h" +#include "internal/dtoa.h" +#include "internal/itoa.h" +#include "stringbuffer.h" +#include // placement new + +#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER) +#include +#pragma intrinsic(_BitScanForward) +#endif +#ifdef RAPIDJSON_SSE42 +#include +#elif defined(RAPIDJSON_SSE2) +#include +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(unreachable-code) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// WriteFlag + +/*! \def RAPIDJSON_WRITE_DEFAULT_FLAGS + \ingroup RAPIDJSON_CONFIG + \brief User-defined kWriteDefaultFlags definition. + + User can define this as any \c WriteFlag combinations. +*/ +#ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS +#define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags +#endif + +//! Combination of writeFlags +enum WriteFlag { + kWriteNoFlags = 0, //!< No flags are set. + kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings. + kWriteNanAndInfFlag = 2, //!< Allow writing of Infinity, -Infinity and NaN. + kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS +}; + +//! JSON writer +/*! Writer implements the concept Handler. + It generates JSON text by events to an output os. + + User may programmatically calls the functions of a writer to generate JSON text. + + On the other side, a writer can also be passed to objects that generates events, + + for example Reader::Parse() and Document::Accept(). + + \tparam OutputStream Type of output stream. + \tparam SourceEncoding Encoding of source string. + \tparam TargetEncoding Encoding of output stream. + \tparam StackAllocator Type of allocator for allocating memory of stack. + \note implements Handler concept +*/ +template, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags> +class Writer { +public: + typedef typename SourceEncoding::Ch Ch; + + static const int kDefaultMaxDecimalPlaces = 324; + + //! Constructor + /*! \param os Output stream. + \param stackAllocator User supplied allocator. If it is null, it will create a private one. + \param levelDepth Initial capacity of stack. + */ + explicit + Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) : + os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {} + + explicit + Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : + os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {} + + //! Reset the writer with a new stream. + /*! + This function reset the writer with a new stream and default settings, + in order to make a Writer object reusable for output multiple JSONs. + + \param os New output stream. + \code + Writer writer(os1); + writer.StartObject(); + // ... + writer.EndObject(); + + writer.Reset(os2); + writer.StartObject(); + // ... + writer.EndObject(); + \endcode + */ + void Reset(OutputStream& os) { + os_ = &os; + hasRoot_ = false; + level_stack_.Clear(); + } + + //! Checks whether the output is a complete JSON. + /*! + A complete JSON has a complete root object or array. + */ + bool IsComplete() const { + return hasRoot_ && level_stack_.Empty(); + } + + int GetMaxDecimalPlaces() const { + return maxDecimalPlaces_; + } + + //! Sets the maximum number of decimal places for double output. + /*! + This setting truncates the output with specified number of decimal places. + + For example, + + \code + writer.SetMaxDecimalPlaces(3); + writer.StartArray(); + writer.Double(0.12345); // "0.123" + writer.Double(0.0001); // "0.0" + writer.Double(1.234567890123456e30); // "1.234567890123456e30" (do not truncate significand for positive exponent) + writer.Double(1.23e-4); // "0.0" (do truncate significand for negative exponent) + writer.EndArray(); + \endcode + + The default setting does not truncate any decimal places. You can restore to this setting by calling + \code + writer.SetMaxDecimalPlaces(Writer::kDefaultMaxDecimalPlaces); + \endcode + */ + void SetMaxDecimalPlaces(int maxDecimalPlaces) { + maxDecimalPlaces_ = maxDecimalPlaces; + } + + /*!@name Implementation of Handler + \see Handler + */ + //@{ + + bool Null() { Prefix(kNullType); return EndValue(WriteNull()); } + bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); } + bool Int(int i) { Prefix(kNumberType); return EndValue(WriteInt(i)); } + bool Uint(unsigned u) { Prefix(kNumberType); return EndValue(WriteUint(u)); } + bool Int64(int64_t i64) { Prefix(kNumberType); return EndValue(WriteInt64(i64)); } + bool Uint64(uint64_t u64) { Prefix(kNumberType); return EndValue(WriteUint64(u64)); } + + //! Writes the given \c double value to the stream + /*! + \param d The value to be written. + \return Whether it is succeed. + */ + bool Double(double d) { Prefix(kNumberType); return EndValue(WriteDouble(d)); } + + bool RawNumber(const Ch* str, SizeType length, bool copy = false) { + (void)copy; + Prefix(kNumberType); + return EndValue(WriteString(str, length)); + } + + bool String(const Ch* str, SizeType length, bool copy = false) { + (void)copy; + Prefix(kStringType); + return EndValue(WriteString(str, length)); + } + +#if RAPIDJSON_HAS_STDSTRING + bool String(const std::basic_string& str) { + return String(str.data(), SizeType(str.size())); + } +#endif + + bool StartObject() { + Prefix(kObjectType); + new (level_stack_.template Push()) Level(false); + return WriteStartObject(); + } + + bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } + + bool EndObject(SizeType memberCount = 0) { + (void)memberCount; + RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); + RAPIDJSON_ASSERT(!level_stack_.template Top()->inArray); + level_stack_.template Pop(1); + return EndValue(WriteEndObject()); + } + + bool StartArray() { + Prefix(kArrayType); + new (level_stack_.template Push()) Level(true); + return WriteStartArray(); + } + + bool EndArray(SizeType elementCount = 0) { + (void)elementCount; + RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); + RAPIDJSON_ASSERT(level_stack_.template Top()->inArray); + level_stack_.template Pop(1); + return EndValue(WriteEndArray()); + } + //@} + + /*! @name Convenience extensions */ + //@{ + + //! Simpler but slower overload. + bool String(const Ch* str) { return String(str, internal::StrLen(str)); } + bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } + + //@} + + //! Write a raw JSON value. + /*! + For user to write a stringified JSON as a value. + + \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range. + \param length Length of the json. + \param type Type of the root of json. + */ + bool RawValue(const Ch* json, size_t length, Type type) { Prefix(type); return EndValue(WriteRawValue(json, length)); } + +protected: + //! Information for each nested level + struct Level { + Level(bool inArray_) : valueCount(0), inArray(inArray_) {} + size_t valueCount; //!< number of values in this level + 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; + } + + bool WriteBool(bool b) { + if (b) { + PutReserve(*os_, 4); + PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e'); + } + else { + PutReserve(*os_, 5); + PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e'); + } + return true; + } + + bool WriteInt(int i) { + char buffer[11]; + const char* end = internal::i32toa(i, buffer); + PutReserve(*os_, static_cast(end - buffer)); + for (const char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast(*p)); + return true; + } + + bool WriteUint(unsigned u) { + char buffer[10]; + const char* end = internal::u32toa(u, buffer); + PutReserve(*os_, static_cast(end - buffer)); + for (const char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast(*p)); + return true; + } + + bool WriteInt64(int64_t i64) { + char buffer[21]; + const char* end = internal::i64toa(i64, buffer); + PutReserve(*os_, static_cast(end - buffer)); + for (const char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast(*p)); + return true; + } + + bool WriteUint64(uint64_t u64) { + char buffer[20]; + char* end = internal::u64toa(u64, buffer); + PutReserve(*os_, static_cast(end - buffer)); + for (char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast(*p)); + return true; + } + + bool WriteDouble(double d) { + if (internal::Double(d).IsNanOrInf()) { + if (!(writeFlags & kWriteNanAndInfFlag)) + return false; + if (internal::Double(d).IsNan()) { + PutReserve(*os_, 3); + PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N'); + return true; + } + if (internal::Double(d).Sign()) { + PutReserve(*os_, 9); + PutUnsafe(*os_, '-'); + } + else + PutReserve(*os_, 8); + PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f'); + PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y'); + return true; + } + + char buffer[25]; + char* end = internal::dtoa(d, buffer, maxDecimalPlaces_); + PutReserve(*os_, static_cast(end - buffer)); + for (char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast(*p)); + return true; + } + + bool WriteString(const Ch* str, SizeType length) { + static const typename TargetEncoding::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + static const char escape[256] = { +#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + //0 1 2 3 4 5 6 7 8 9 A B C D E F + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00 + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10 + 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20 + Z16, Z16, // 30~4F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50 + Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF +#undef Z16 + }; + + if (TargetEncoding::supportUnicode) + PutReserve(*os_, 2 + length * 6); // "\uxxxx..." + else + PutReserve(*os_, 2 + length * 12); // "\uxxxx\uyyyy..." + + PutUnsafe(*os_, '\"'); + GenericStringStream is(str); + while (ScanWriteUnescapedString(is, length)) { + const Ch c = is.Peek(); + if (!TargetEncoding::supportUnicode && static_cast(c) >= 0x80) { + // Unicode escaping + unsigned codepoint; + if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint))) + return false; + PutUnsafe(*os_, '\\'); + PutUnsafe(*os_, 'u'); + if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) { + PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]); + PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]); + PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]); + PutUnsafe(*os_, hexDigits[(codepoint ) & 15]); + } + else { + RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF); + // Surrogate pair + unsigned s = codepoint - 0x010000; + unsigned lead = (s >> 10) + 0xD800; + unsigned trail = (s & 0x3FF) + 0xDC00; + PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]); + PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]); + PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]); + PutUnsafe(*os_, hexDigits[(lead ) & 15]); + PutUnsafe(*os_, '\\'); + PutUnsafe(*os_, 'u'); + PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]); + PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]); + PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]); + PutUnsafe(*os_, hexDigits[(trail ) & 15]); + } + } + else if ((sizeof(Ch) == 1 || static_cast(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast(c)])) { + is.Take(); + PutUnsafe(*os_, '\\'); + PutUnsafe(*os_, static_cast(escape[static_cast(c)])); + if (escape[static_cast(c)] == 'u') { + PutUnsafe(*os_, '0'); + PutUnsafe(*os_, '0'); + PutUnsafe(*os_, hexDigits[static_cast(c) >> 4]); + PutUnsafe(*os_, hexDigits[static_cast(c) & 0xF]); + } + } + else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? + Transcoder::Validate(is, *os_) : + Transcoder::TranscodeUnsafe(is, *os_)))) + return false; + } + PutUnsafe(*os_, '\"'); + return true; + } + + bool ScanWriteUnescapedString(GenericStringStream& is, size_t length) { + return RAPIDJSON_LIKELY(is.Tell() < length); + } + + bool WriteStartObject() { os_->Put('{'); return true; } + bool WriteEndObject() { os_->Put('}'); return true; } + bool WriteStartArray() { os_->Put('['); return true; } + bool WriteEndArray() { os_->Put(']'); return true; } + + bool WriteRawValue(const Ch* json, size_t length) { + PutReserve(*os_, length); + for (size_t i = 0; i < length; i++) { + RAPIDJSON_ASSERT(json[i] != '\0'); + PutUnsafe(*os_, json[i]); + } + return true; + } + + void Prefix(Type type) { + (void)type; + if (RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root + Level* level = level_stack_.template Top(); + if (level->valueCount > 0) { + if (level->inArray) + os_->Put(','); // add comma if it is not the first element in array + else // in object + os_->Put((level->valueCount % 2 == 0) ? ',' : ':'); + } + if (!level->inArray && level->valueCount % 2 == 0) + RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name + level->valueCount++; + } + else { + RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root. + hasRoot_ = true; + } + } + + // Flush the value if it is the top level one. + bool EndValue(bool ret) { + if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text + os_->Flush(); + return ret; + } + + OutputStream* os_; + internal::Stack level_stack_; + int maxDecimalPlaces_; + bool hasRoot_; + +private: + // Prohibit copy constructor & assignment operator. + Writer(const Writer&); + Writer& operator=(const Writer&); +}; + +// Full specialization for StringStream to prevent memory copying + +template<> +inline bool Writer::WriteInt(int i) { + char *buffer = os_->Push(11); + const char* end = internal::i32toa(i, buffer); + os_->Pop(static_cast(11 - (end - buffer))); + return true; +} + +template<> +inline bool Writer::WriteUint(unsigned u) { + char *buffer = os_->Push(10); + const char* end = internal::u32toa(u, buffer); + os_->Pop(static_cast(10 - (end - buffer))); + return true; +} + +template<> +inline bool Writer::WriteInt64(int64_t i64) { + char *buffer = os_->Push(21); + const char* end = internal::i64toa(i64, buffer); + os_->Pop(static_cast(21 - (end - buffer))); + return true; +} + +template<> +inline bool Writer::WriteUint64(uint64_t u) { + char *buffer = os_->Push(20); + const char* end = internal::u64toa(u, buffer); + os_->Pop(static_cast(20 - (end - buffer))); + return true; +} + +template<> +inline bool Writer::WriteDouble(double d) { + if (internal::Double(d).IsNanOrInf()) { + // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag). + if (!(kWriteDefaultFlags & kWriteNanAndInfFlag)) + return false; + if (internal::Double(d).IsNan()) { + PutReserve(*os_, 3); + PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N'); + return true; + } + if (internal::Double(d).Sign()) { + PutReserve(*os_, 9); + PutUnsafe(*os_, '-'); + } + else + PutReserve(*os_, 8); + PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f'); + PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y'); + return true; + } + + char *buffer = os_->Push(25); + char* end = internal::dtoa(d, buffer, maxDecimalPlaces_); + os_->Pop(static_cast(25 - (end - buffer))); + return true; +} + +#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) +template<> +inline bool Writer::ScanWriteUnescapedString(StringStream& is, size_t length) { + if (length < 16) + return RAPIDJSON_LIKELY(is.Tell() < length); + + if (!RAPIDJSON_LIKELY(is.Tell() < length)) + return false; + + const char* p = is.src_; + const char* end = is.head_ + length; + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + const char* endAligned = reinterpret_cast(reinterpret_cast(end) & static_cast(~15)); + if (nextAligned > end) + return true; + + while (p != nextAligned) + if (*p < 0x20 || *p == '\"' || *p == '\\') { + is.src_ = p; + return RAPIDJSON_LIKELY(is.Tell() < length); + } + else + os_->PutUnsafe(*p++); + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); + + for (; p != endAligned; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19 + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped + SizeType len; +#ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + len = offset; +#else + len = static_cast(__builtin_ffs(r) - 1); +#endif + char* q = reinterpret_cast(os_->PushUnsafe(len)); + for (size_t i = 0; i < len; i++) + q[i] = p[i]; + + p += len; + break; + } + _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s); + } + + is.src_ = p; + return RAPIDJSON_LIKELY(is.Tell() < length); +} +#endif // defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) + +RAPIDJSON_NAMESPACE_END + +#ifdef _MSC_VER +RAPIDJSON_DIAG_POP +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/Source/Core/DolphinQt2/DolphinQt2.vcxproj b/Source/Core/DolphinQt2/DolphinQt2.vcxproj index 2b0698682a..ea0978648b 100644 --- a/Source/Core/DolphinQt2/DolphinQt2.vcxproj +++ b/Source/Core/DolphinQt2/DolphinQt2.vcxproj @@ -40,7 +40,7 @@ - $(ExternalsDir)ffmpeg\lib;$(ExternalsDir)discord-rpc\lib;%(AdditionalLibraryDirectories) + $(ExternalsDir)ffmpeg\lib;$(IntDir)..\discord-rpc\bin;%(AdditionalLibraryDirectories) avrt.lib;iphlpapi.lib;winmm.lib;setupapi.lib;opengl32.lib;glu32.lib;rpcrt4.lib;comctl32.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;Shlwapi.lib;discord-rpc.lib;%(AdditionalDependencies) diff --git a/Source/Core/DolphinWX/DolphinWX.vcxproj b/Source/Core/DolphinWX/DolphinWX.vcxproj index 1aabf572a2..1038bea539 100644 --- a/Source/Core/DolphinWX/DolphinWX.vcxproj +++ b/Source/Core/DolphinWX/DolphinWX.vcxproj @@ -38,7 +38,7 @@ - $(ExternalsDir)ffmpeg\lib;$(ExternalsDir)discord-rpc\lib;%(AdditionalLibraryDirectories) + $(ExternalsDir)ffmpeg\lib;$(IntDir)..\discord-rpc\bin;%(AdditionalLibraryDirectories) avrt.lib;iphlpapi.lib;winmm.lib;setupapi.lib;opengl32.lib;glu32.lib;rpcrt4.lib;comctl32.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;Shlwapi.lib;discord-rpc.lib;%(AdditionalDependencies) diff --git a/Source/Core/UICommon/CMakeLists.txt b/Source/Core/UICommon/CMakeLists.txt index 8b3976fb0c..eafc3e1022 100644 --- a/Source/Core/UICommon/CMakeLists.txt +++ b/Source/Core/UICommon/CMakeLists.txt @@ -2,7 +2,7 @@ add_library(uicommon AutoUpdate.cpp CommandLineParse.cpp Disassembler.cpp - DiscordPresence.cpp + DiscordPresence.cpp GameFile.cpp GameFileCache.cpp UICommon.cpp diff --git a/Source/Core/UICommon/UICommon.vcxproj b/Source/Core/UICommon/UICommon.vcxproj index 1a650b3a0c..4c5459be03 100644 --- a/Source/Core/UICommon/UICommon.vcxproj +++ b/Source/Core/UICommon/UICommon.vcxproj @@ -35,16 +35,6 @@ - - - USE_DISCORD_PRESENCE;%(PreprocessorDefinitions) - - - - - USE_DISCORD_PRESENCE;%(PreprocessorDefinitions) - - @@ -54,6 +44,9 @@ {2c0d058e-de35-4471-ad99-e68a2caf9e18} + + + {4482FD2A-EC43-3FFB-AC20-2E5C54B05EAD} diff --git a/Source/UnitTests/UnitTests.vcxproj b/Source/UnitTests/UnitTests.vcxproj index cb5c37b863..24e814d773 100644 --- a/Source/UnitTests/UnitTests.vcxproj +++ b/Source/UnitTests/UnitTests.vcxproj @@ -45,7 +45,7 @@ The following libs are needed since we pull in pretty much the entire dolphin codebase. --> - $(ExternalsDir)ffmpeg\lib;$(ExternalsDir)discord-rpc\lib;%(AdditionalLibraryDirectories) + $(ExternalsDir)ffmpeg\lib;$(IntDir)..\discord-rpc\bin;%(AdditionalLibraryDirectories) avrt.lib;iphlpapi.lib;winmm.lib;setupapi.lib;opengl32.lib;glu32.lib;rpcrt4.lib;comctl32.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;Shlwapi.lib;discord-rpc.lib;%(AdditionalDependencies) Console diff --git a/Source/VSProps/Base.props b/Source/VSProps/Base.props index 6449222367..5b421cf5df 100644 --- a/Source/VSProps/Base.props +++ b/Source/VSProps/Base.props @@ -59,6 +59,7 @@ _M_X86=1;%(PreprocessorDefinitions) SFML_STATIC;%(PreprocessorDefinitions) USE_ANALYTICS=1;%(PreprocessorDefinitions) + USE_DISCORD_PRESENCE;%(PreprocessorDefinitions) CURL_STATICLIB;%(PreprocessorDefinitions) _ARCH_64=1;_M_X86_64=1;%(PreprocessorDefinitions)