diff --git a/.gitignore b/.gitignore index 8fc8285e16..5e02e1759b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,14 @@ +### +WIN32/CMakeFiles/ +WIN32/Debug/ +WIN32/Release/ +WIN32/.vs/ +.vscode/ +JSON/JSON/Release/ +simple_web/Release/ +HTTP_CLIENT_GET_PICTURE/Release/ +HTTP_SIMPLE_CLIENT/Release/ +HTTP_SIMPLE_SERVER/Release/ # Visual Studio files *.o *.d diff --git a/Build_android/configure.sh b/Build_android/configure.sh deleted file mode 100755 index 0d218a46b4..0000000000 --- a/Build_android/configure.sh +++ /dev/null @@ -1,205 +0,0 @@ -#!/bin/bash -# Copyright (C) Microsoft. All rights reserved. -# Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. -# =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -# -# configure.sh -# -# Build script for casablanca on android -# -# For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk -# -# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - -set -e - -# The Android NDK r10e or later may work, but we test with r18b. To download, see the following link: -# https://developer.android.com/ndk/downloads/index.html - -# ----------------- -# Parse args -# ----------------- - -DO_BOOST=1 -DO_OPENSSL=1 -DO_CMAKE=1 -DO_CPPRESTSDK=1 - -BOOSTVER=1.69.0 -OPENSSLVER=1.1.0j -CMAKEVER=3.14.0 - -API=15 -STL=c++_shared - -function usage { - echo "Usage: $0 [--skip-boost] [--skip-openssl] [--skip-cpprestsdk] [-h] [--ndk ]" - echo "" - echo " --skip-boost Skip fetching and compiling boost" - echo " --skip-openssl Skip fetching and compiling openssl" - echo " --skip-cpprestsdk Skip compiling cpprestsdk" - echo " --boost Override the Boost version to build (default is ${BOOSTVER})" - echo " --openssl Override the OpenSSL version to build (default is ${OPENSSLVER})" - echo " --ndk If specified, overrides the ANDROID_NDK environment variable" - echo " -h,--help,-? Display this information" -} - -while [[ $# > 0 ]] -do - case $1 in - "--skip-boost") - DO_BOOST=0 - ;; - "--skip-openssl") - DO_OPENSSL=0 - ;; - "--skip-cmake") - DO_CMAKE=0 - ;; - "--skip-cpprestsdk") - DO_CPPRESTSDK=0 - ;; - "--boost") - shift - DO_BOOST=1 - BOOSTVER=$1 - ;; - "--cmake") - shift - DO_CMAKE=1 - CMAKEVER=$1 - ;; - "--openssl") - shift - DO_OPENSSL=1 - OPENSSLVER=$1 - ;; - "--ndk") - shift - export ANDROID_NDK=$1 - ;; - "-?"|"-h"|"--help") - usage - exit - ;; - *) - usage - exit 1 - ;; - esac - shift -done - -# Variables setup - -if [ ! -e "${ANDROID_NDK}/ndk-build" ] -then - echo "ANDROID_NDK does not point to a valid NDK." - echo "(current setting: '${ANDROID_NDK}')" - exit 1 -fi -NDK_DIR=`cd "${ANDROID_NDK}" && pwd` -SRC_DIR=`pwd` - -if [ -z "$NCPU" ]; then - NCPU=4 - if uname -s | grep -i "linux" > /dev/null ; then - NCPU=`cat /proc/cpuinfo | grep -c -i processor` - fi -fi - -# ----------------------- -# Identify the script dir -# ----------------------- - -# source: -# http://stackoverflow.com/questions/59895/can-a-bash-script-tell-what-directory-its-stored-in - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -if [ "$SRC_DIR" == "$DIR" ] -then - echo "You must use a separate directory for building." - echo "(try 'mkdir build; cd build; ../configure.sh')" - exit 1 -fi - -# ------- -# Openssl -# ------- - -# This steps are based on the official openssl build instructions -# http://wiki.openssl.org/index.php/Android -if [ "${DO_OPENSSL}" == "1" ]; then ( - if [ ! -d "openssl" ]; then mkdir openssl; fi - cd openssl - cp -af "${DIR}/openssl/." . - make all ANDROID_NDK="${NDK_DIR}" ANDROID_TOOLCHAIN=clang ANDROID_ABI=armeabi-v7a OPENSSL_PREFIX=armeabi-v7a OPENSSL_VERSION=$OPENSSLVER -j $NCPU - make all ANDROID_NDK="${NDK_DIR}" ANDROID_TOOLCHAIN=clang ANDROID_ABI=x86 OPENSSL_PREFIX=x86 OPENSSL_VERSION=$OPENSSLVER -j $NCPU -) fi - -# ----- -# Boost -# ----- -# Uses the build script from Moritz Wundke (formerly MysticTreeGames) -# https://github.com/moritz-wundke/Boost-for-Android - -if [ "${DO_BOOST}" == "1" ]; then ( - if [ ! -d 'Boost-for-Android' ]; then git clone https://github.com/moritz-wundke/Boost-for-Android; fi - cd Boost-for-Android - git checkout 1356b87fed389b4abf1ff671adec0b899877174b - PATH="$PATH:$NDK_DIR" \ - CXXFLAGS="-std=gnu++11" \ - ./build-android.sh \ - --boost=$BOOSTVER \ - --arch=armeabi-v7a,x86 \ - --with-libraries=atomic,random,date_time,filesystem,system,thread,chrono \ - "${NDK_DIR}" || exit 1 -) fi - -# ------ -# CMake -# ------ -# We update CMake because the version included with Ubuntu is too old to handle Boost 1.69. - -if [ "${DO_CMAKE}" == "1" ]; then ( - if [ ! -d "cmake-${CMAKEVER}" ]; then wget https://github.com/Kitware/CMake/releases/download/v${CMAKEVER}/cmake-${CMAKEVER}-Linux-x86_64.sh; fi - chmod +x cmake-${CMAKEVER}-Linux-x86_64.sh - rm -rf cmake-${CMAKEVER} - mkdir cmake-${CMAKEVER} - cd cmake-${CMAKEVER} - ../cmake-${CMAKEVER}-Linux-x86_64.sh --skip-license -) fi - -# ---------- -# casablanca -# ---------- - -if [ "${DO_CPPRESTSDK}" == "1" ]; then - # Use the builtin CMake toolchain configuration that comes with the NDK - function build_cpprestsdk { ( - rm -rf $1 - ./cmake-${CMAKEVER}/bin/cmake \ - -DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK}/build/cmake/android.toolchain.cmake" \ - -DANDROID_NDK="${ANDROID_NDK}" \ - -DANDROID_TOOLCHAIN=clang \ - -DANDROID_ABI=$2 \ - -DBOOST_VERSION="${BOOSTVER}" \ - -DCMAKE_BUILD_TYPE=$3 \ - -S "${DIR}/.." \ - -B $1 - make -j $NCPU -C $1 - ) } - - # Build the cpprestsdk for each target configuration - build_cpprestsdk build.armv7.debug armeabi-v7a Debug - build_cpprestsdk build.armv7.release armeabi-v7a Release - build_cpprestsdk build.x86.debug x86 Debug - build_cpprestsdk build.x86.release x86 Release -fi diff --git a/Build_android/openssl/Makefile b/Build_android/openssl/Makefile deleted file mode 100644 index 2da8fa48c9..0000000000 --- a/Build_android/openssl/Makefile +++ /dev/null @@ -1,176 +0,0 @@ -# Configuration parameters -ANDROID_API = 18 -ANDROID_ABI = armeabi-v7a -ANDROID_HOST = linux-x86_64 -ANDROID_TOOLCHAIN = gcc -ANDROID_GCC_VERSION = 4.8 -OPENSSL_VERSION = 1.0.2k -OPENSSL_PACKAGE = openssl-$(OPENSSL_VERSION) -OPENSSL_PATCH = $(OPENSSL_PACKAGE).patch -OPENSSL_TARBALL = $(OPENSSL_PACKAGE).tar.gz -OPENSSL_URL = https://www.openssl.org/source/$(OPENSSL_TARBALL) -OPENSSL_OPTIONS = -no-ssl2 -no-ssl3 -no-comp -no-hw -no-engine -OPENSSL_PREFIX = android-$(ANDROID_API)-$(ANDROID_ABI)-$(ANDROID_TOOLCHAIN) -OPENSSL_SOURCE = $(OPENSSL_PACKAGE)-$(ANDROID_ABI) - -# Setup target parameters from ABI -ifneq ($(findstring armeabi,$(ANDROID_ABI)),) -ANDROID_ARCH := arm -ANDROID_TRIPLE := arm-linux-androideabi -ANDROID_TOOLARCH := $(ANDROID_TRIPLE) -OPENSSL_MACHINE := armv7 -OPENSSL_SYSTEM := android -OPENSSL_TARGET := android-armeabi -endif - -ifneq ($(findstring aarch64,$(ANDROID_ABI)),) -ANDROID_ARCH := arm64 -ANDROID_TRIPLE := aarch64-linux-android -ANDROID_TOOLARCH := $(ANDROID_TRIPLE) -OPENSSL_MACHINE := aarch64 -OPENSSL_SYSTEM := android64 -OPENSSL_TARGET := android64-aarch64 -endif - -ifneq ($(findstring x86,$(ANDROID_ABI)),) -ANDROID_ARCH := x86 -ANDROID_TRIPLE := i686-linux-android -ANDROID_TOOLARCH := $(ANDROID_ARCH) -OPENSSL_MACHINE := i686 -OPENSSL_SYSTEM := android -OPENSSL_TARGET := android-x86 -endif - -# Validate Android NDK directory paths and use fallback directories where applicable -define direxists = -$(if $(wildcard $(1)),$(strip $(1)),"") -endef - -define findfirstdir = -$(call direxists,$(firstword $(filter-out "",$(foreach val,$(3),$(call direxists,$(subst $(2),$(strip $(val)),$(1))))))) -endef - -ifeq ($(call direxists,$(ANDROID_NDK)),"") -$(error invalid Android NDK root directory) -endif - -ANDROID_LINK_SYSROOT := $(ANDROID_NDK)/platforms/android-$(ANDROID_API)/arch-$(ANDROID_ARCH) -ifeq ($(call direxists,$(ANDROID_LINK_SYSROOT)),"") -$(error invalid Android ABI or API level, could not locate Android NDK sysroot directory) -endif - -ANDROID_SYSROOT := $(ANDROID_NDK)/sysroot -ifeq ($(call direxists,$(ANDROID_SYSROOT)),"") -ANDROID_SYSROOT := $(ANDROID_LINK_SYSROOT) -endif - -ANDROID_GCC_VERSIONS := $(ANDROID_GCC_VERSION) 4.9 4.8 -ANDROID_GCC_PREBUILT_template := $(ANDROID_NDK)/toolchains/$(ANDROID_TOOLARCH)-<>/prebuilt -ANDROID_GCC_PREBUILT := $(call findfirstdir,$(ANDROID_GCC_PREBUILT_template),<>,$(ANDROID_GCC_VERSIONS)) -ifeq ($(ANDROID_GCC_PREBUILT),"") -$(error could not determine Android NDK GCC toolchain prebuilt directory) -endif - -ANDROID_HOSTS := $(ANDROID_HOST) linux-x86_64 linux-x86 darwin-x86_64 darwin-x86 -ANDROID_GCC_TOOLCHAIN_template := $(ANDROID_GCC_PREBUILT)/<> -ANDROID_GCC_TOOLCHAIN := $(call findfirstdir,$(ANDROID_GCC_TOOLCHAIN_template),<>,$(ANDROID_HOSTS)) -ifeq ($(ANDROID_GCC_TOOLCHAIN),"") -$(error could not determine Android NDK GCC toolchain host directory) -endif - -ANDROID_LLVM_VERSIONS := llvm llvm-3.6 llvm-3.5 llvm-3.4 -ANDROID_LLVM_TOOLCHAIN_template := $(ANDROID_NDK)/toolchains/<>/prebuilt/$(notdir $(ANDROID_GCC_TOOLCHAIN)) -ANDROID_LLVM_TOOLCHAIN := $(call findfirstdir,$(ANDROID_LLVM_TOOLCHAIN_template),<>,$(ANDROID_LLVM_VERSIONS)) -ifeq ($(ANDROID_LLVM_TOOLCHAIN),"") -$(error could not determine Android NDK LLVM toolchain directory) -endif - -# Configure toolchain -OPENSSL_CROSS_COMPILE := -OPENSSL_CC := -OPENSSL_RANLIB := $(ANDROID_GCC_TOOLCHAIN)/bin/$(ANDROID_TRIPLE)-ranlib - -ifneq ($(findstring clang,$(ANDROID_TOOLCHAIN)),) -OPENSSL_TARGET := $(OPENSSL_TARGET)-clang -OPENSSL_CC := $(ANDROID_LLVM_TOOLCHAIN)/bin/clang -endif - -ifneq ($(findstring gcc,$(ANDROID_TOOLCHAIN)),) -OPENSSL_CROSS_COMPILE := $(ANDROID_TRIPLE)- -OPENSSL_CC := $(ANDROID_GCC_TOOLCHAIN)/bin/$(ANDROID_TRIPLE)-gcc -endif - -ifeq ($(OPENSSL_CC),) -$(error invalid toolchain specified for ANDROID_TOOLCHAIN) -endif - -all: info $(OPENSSL_PREFIX)/lib/libssl.a - -$(OPENSSL_TARBALL): - @echo "Downloading OpenSSL tarball" - wget $(OPENSSL_URL) - -$(OPENSSL_PREFIX)/lib/libssl.a: $(OPENSSL_TARBALL) - @echo "Decompressing OpenSSL package" && \ - ( \ - set -e; \ - rm -rf $(OPENSSL_SOURCE); \ - rm -rf $(OPENSSL_PACKAGE); \ - tar xzf $(OPENSSL_TARBALL); \ - ) && \ - mv $(OPENSSL_PACKAGE) $(OPENSSL_SOURCE) - @if test -f $(OPENSSL_PATCH); then \ - echo "Patching OpenSSL source tree"; \ - ( cd $(OPENSSL_SOURCE) && patch -p1 < ../$(OPENSSL_PATCH) ); \ - fi - @echo "Building OpenSSL" && \ - export ANDROID_NDK="$(ANDROID_NDK)" && \ - export ANDROID_API="$(ANDROID_API)" && \ - export ANDROID_ARCH="$(ANDROID_ARCH)" && \ - export ANDROID_TRIPLE="$(ANDROID_TRIPLE)" && \ - export ANDROID_SYSROOT="$(ANDROID_SYSROOT)" && \ - export ANDROID_LINK_SYSROOT="$(ANDROID_LINK_SYSROOT)" && \ - export ANDROID_GCC_TOOLCHAIN="$(ANDROID_GCC_TOOLCHAIN)" && \ - export CROSS_SYSROOT="$(ANDROID_SYSROOT)" && \ - export SYSROOT="$(ANDROID_SYSROOT)" && \ - export ARCH="$(ANDROID_ARCH)" && \ - export MACHINE="$(OPENSSL_MACHINE)" && \ - export SYSTEM="$(OPENSSL_SYSTEM)" && \ - export CROSS_COMPILE="$(OPENSSL_CROSS_COMPILE)" && \ - export HOSTCC="$(ANDROID_TOOLCHAIN)" && \ - export PATH="$(ANDROID_GCC_TOOLCHAIN)/bin:$(ANDROID_LLVM_TOOLCHAIN)/bin:$(PATH)" && \ - ( \ - cd $(OPENSSL_SOURCE); \ - perl Configure $(OPENSSL_TARGET) shared $(OPENSSL_OPTIONS) --prefix="`pwd`/../$(OPENSSL_PREFIX)" $(OPENSSL_CFLAGS) && \ - make depend && \ - make all && \ - make install CC=$(OPENSSL_CC) RANLIB=$(OPENSSL_RANLIB); \ - ) - -clean: - @echo "Cleaning" - rm -rf $(OPENSSL_SOURCE) - rm -rf $(OPENSSL_PACKAGE) - rm -rf $(OPENSSL_PREFIX) - -info: - @echo "OpenSSL build options" - @echo "ANDROID_NDK = $(ANDROID_NDK)" - @echo "ANDROID_API = $(ANDROID_API)" - @echo "ANDROID_ABI = $(ANDROID_ABI)" - @echo "ANDROID_HOST = $(ANDROID_HOST)" - @echo "ANDROID_TOOLCHAIN = $(ANDROID_TOOLCHAIN)" - @echo "ANDROID_TRIPLE = $(ANDROID_TRIPLE)" - @echo "ANDROID_SYSROOT = $(ANDROID_SYSROOT)" - @echo "ANDROID_LINK_SYSROOT = $(ANDROID_LINK_SYSROOT)" - @echo "ANDROID_GCC_TOOLCHAIN = $(ANDROID_GCC_TOOLCHAIN)" - @echo "ANDROID_LLVM_TOOLCHAIN = $(ANDROID_LLVM_TOOLCHAIN)" - @echo "OPENSSL_VERSION = $(OPENSSL_VERSION)" - @echo "OPENSSL_URL = $(OPENSSL_URL)" - @echo "OPENSSL_OPTIONS = $(OPENSSL_OPTIONS)" - @echo "OPENSSL_PREFIX = $(OPENSSL_PREFIX)" - @echo "OPENSSL_CFLAGS = $(OPENSSL_CFLAGS)" - @echo "OPENSSL_CC = $(OPENSSL_CC)" - @echo "OPENSSL_RANLIB = $(OPENSSL_RANLIB)" - -.PHONY: all clean info diff --git a/Build_android/openssl/openssl-1.0.2k.patch b/Build_android/openssl/openssl-1.0.2k.patch deleted file mode 100644 index 992a27e9f9..0000000000 --- a/Build_android/openssl/openssl-1.0.2k.patch +++ /dev/null @@ -1,108 +0,0 @@ -This patch applies several changes that enable OpenSSL 1.0.2k to be built -for Android using either Clang or GCC toolchains. - -An alias for the android-armv7 target, named android-armeabi, is added for -compatability with the OpenSSL 1.1.0 configuration target names. Support for -the AArch64 archicture is also added, as well as targets using the Clang -compiler. - -Clang does not recognize some of the ARM assembly nmenonics that are used in -OpenSSL. In particular, the 'adrl' pseudo instruction is not supported. To -further complicate matters, Clang doesn't support immediate fixup values so -the alternative adr/sub sequence used for the Thumb2 code path cannot be -used either. Instead it is replaced with a sequence of instructions that -computes the offset at runtime. It utilizes register r4 for computing the -intermediate result, which is first saved to and later restored from the -stack. The upstream bug in LLVM can be found here: -https://llvm.org/bugs/show_bug.cgi?id=24350 - -diff -Naur org/Configure mod/Configure ---- org/Configure 2017-01-26 05:22:03.000000000 -0800 -+++ mod/Configure 2018-01-17 14:25:44.712943600 -0800 -@@ -471,10 +471,17 @@ - "linux-alpha+bwx-ccc","ccc:-fast -readonly_strings -DL_ENDIAN::-D_REENTRANT:::SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_PTR DES_RISC1 DES_UNROLL:${alpha_asm}", - - # Android: linux-* but without pointers to headers and libs. --"android","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", --"android-x86","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:".eval{my $asm=${x86_elf_asm};$asm=~s/:elf/:android/;$asm}.":dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", --"android-armv7","gcc:-march=armv7-a -mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", --"android-mips","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android","gcc:-mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-x86","gcc:-mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:".eval{my $asm=${x86_elf_asm};$asm=~s/:elf/:android/;$asm}.":dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-armv7","gcc:-march=armv7-a -mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-armeabi","gcc:-march=armv7-a -mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android64-aarch64","gcc:-march=armv8-a -mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${aarch64_asm}:linux64:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-mips","gcc:-mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-x86-clang","clang:-target i686-none-linux-android --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:".eval{my $asm=${x86_elf_asm};$asm=~s/:elf/:android/;$asm}.":dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-armv7-clang","clang:-target armv7-none-linux-androideabi --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-armeabi-clang","clang:-target armv7-none-linux-androideabi --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android64-aarch64-clang","clang:-target aarch64-none-linux-android --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${aarch64_asm}:linux64:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-mips-clang","clang:-target mipsel-none-linux-android --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", - - #### *BSD [do see comment about ${BSDthreads} above!] - "BSD-generic32","gcc:-O3 -fomit-frame-pointer -Wall::${BSDthreads}:::BN_LLONG RC2_CHAR RC4_INDEX DES_INT DES_UNROLL:${no_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -diff -Naur org/crypto/bn/asm/armv4-gf2m.pl mod/crypto/bn/asm/armv4-gf2m.pl ---- org/crypto/bn/asm/armv4-gf2m.pl 2017-01-26 05:22:03.000000000 -0800 -+++ mod/crypto/bn/asm/armv4-gf2m.pl 2018-01-17 11:38:57.297482700 -0800 -@@ -213,8 +213,8 @@ - .align 5 - .LNEON: - ldr r12, [sp] @ 5th argument -- vmov.32 $a, r2, r1 -- vmov.32 $b, r12, r3 -+ vmov $a, r2, r1 -+ vmov $b, r12, r3 - vmov.i64 $k48, #0x0000ffffffffffff - vmov.i64 $k32, #0x00000000ffffffff - vmov.i64 $k16, #0x000000000000ffff -diff -Naur org/crypto/sha/asm/sha256-armv4.pl mod/crypto/sha/asm/sha256-armv4.pl ---- org/crypto/sha/asm/sha256-armv4.pl 2017-01-26 05:22:03.000000000 -0800 -+++ mod/crypto/sha/asm/sha256-armv4.pl 2018-01-17 11:38:57.306342000 -0800 -@@ -576,6 +576,7 @@ - my @MSG=map("q$_",(8..11)); - my ($W0,$W1,$ABCD_SAVE,$EFGH_SAVE)=map("q$_",(12..15)); - my $Ktbl="r3"; -+my $Temp="r4"; - - $code.=<<___; - #if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) -@@ -591,7 +592,13 @@ - sha256_block_data_order_armv8: - .LARMv8: - vld1.32 {$ABCD,$EFGH},[$ctx] --# ifdef __thumb2__ -+# if defined(__clang__) -+ stmdb sp!,{r4,lr} -+ adr $Ktbl,.LARMv8 -+ ldr $Temp,=K256 -+ sub $Temp,$Ktbl,$Temp -+ sub $Ktbl,$Ktbl,$Temp -+# elif defined(__thumb2__) - adr $Ktbl,.LARMv8 - sub $Ktbl,$Ktbl,#.LARMv8-K256 - # else -@@ -655,7 +662,12 @@ - - vst1.32 {$ABCD,$EFGH},[$ctx] - -+# ifdef __clang__ -+ ldmia sp!,{r4,pc} -+# else - ret @ bx lr -+# endif -+ - .size sha256_block_data_order_armv8,.-sha256_block_data_order_armv8 - #endif - ___ -diff -Naur org/Makefile.org mod/Makefile.org ---- org/Makefile.org 2017-01-26 05:22:03.000000000 -0800 -+++ mod/Makefile.org 2018-01-17 14:26:20.623418300 -0800 -@@ -532,7 +532,7 @@ - @$(MAKE) SDIRS='$(SDIRS)' clean - @$(MAKE) TAR='$(TAR)' TARFLAGS='$(TARFLAGS)' $(DISTTARVARS) tar - --install: all install_docs install_sw -+install: install_docs install_sw - - install_sw: - @$(PERL) $(TOP)/util/mkdir-p.pl $(INSTALL_PREFIX)$(INSTALLTOP)/bin \ diff --git a/Build_android/openssl/openssl-1.0.2l.patch b/Build_android/openssl/openssl-1.0.2l.patch deleted file mode 100644 index 03acbee7c0..0000000000 --- a/Build_android/openssl/openssl-1.0.2l.patch +++ /dev/null @@ -1,108 +0,0 @@ -This patch applies several changes that enable OpenSSL 1.0.2l to be built -for Android using either Clang or GCC toolchains. - -An alias for the android-armv7 target, named android-armeabi, is added for -compatability with the OpenSSL 1.1.0 configuration target names. Support for -the AArch64 archicture is also added, as well as targets using the Clang -compiler. - -Clang does not recognize some of the ARM assembly nmenonics that are used in -OpenSSL. In particular, the 'adrl' pseudo instruction is not supported. To -further complicate matters, Clang doesn't support immediate fixup values so -the alternative adr/sub sequence used for the Thumb2 code path cannot be -used either. Instead it is replaced with a sequence of instructions that -computes the offset at runtime. It utilizes register r4 for computing the -intermediate result, which is first saved to and later restored from the -stack. The upstream bug in LLVM can be found here: -https://llvm.org/bugs/show_bug.cgi?id=24350 - -diff -Naur org/Configure mod/Configure ---- org/Configure 2017-05-25 05:54:38.000000000 -0700 -+++ mod/Configure 2018-01-17 20:36:12.497485400 -0800 -@@ -471,10 +471,17 @@ - "linux-alpha+bwx-ccc","ccc:-fast -readonly_strings -DL_ENDIAN::-D_REENTRANT:::SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_PTR DES_RISC1 DES_UNROLL:${alpha_asm}", - - # Android: linux-* but without pointers to headers and libs. --"android","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", --"android-x86","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:".eval{my $asm=${x86_elf_asm};$asm=~s/:elf/:android/;$asm}.":dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", --"android-armv7","gcc:-march=armv7-a -mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", --"android-mips","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android","gcc:-mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-x86","gcc:-mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:".eval{my $asm=${x86_elf_asm};$asm=~s/:elf/:android/;$asm}.":dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-armv7","gcc:-march=armv7-a -mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-armeabi","gcc:-march=armv7-a -mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android64-aarch64","gcc:-march=armv8-a -mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${aarch64_asm}:linux64:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-mips","gcc:-mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-x86-clang","clang:-target i686-none-linux-android --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:".eval{my $asm=${x86_elf_asm};$asm=~s/:elf/:android/;$asm}.":dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-armv7-clang","clang:-target armv7-none-linux-androideabi --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-armeabi-clang","clang:-target armv7-none-linux-androideabi --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android64-aarch64-clang","clang:-target aarch64-none-linux-android --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${aarch64_asm}:linux64:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-mips-clang","clang:-target mipsel-none-linux-android --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", - - #### *BSD [do see comment about ${BSDthreads} above!] - "BSD-generic32","gcc:-O3 -fomit-frame-pointer -Wall::${BSDthreads}:::BN_LLONG RC2_CHAR RC4_INDEX DES_INT DES_UNROLL:${no_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -diff -Naur org/crypto/bn/asm/armv4-gf2m.pl mod/crypto/bn/asm/armv4-gf2m.pl ---- org/crypto/bn/asm/armv4-gf2m.pl 2017-05-25 05:54:34.000000000 -0700 -+++ mod/crypto/bn/asm/armv4-gf2m.pl 2018-01-17 20:36:12.508421200 -0800 -@@ -213,8 +213,8 @@ - .align 5 - .LNEON: - ldr r12, [sp] @ 5th argument -- vmov.32 $a, r2, r1 -- vmov.32 $b, r12, r3 -+ vmov $a, r2, r1 -+ vmov $b, r12, r3 - vmov.i64 $k48, #0x0000ffffffffffff - vmov.i64 $k32, #0x00000000ffffffff - vmov.i64 $k16, #0x000000000000ffff -diff -Naur org/crypto/sha/asm/sha256-armv4.pl mod/crypto/sha/asm/sha256-armv4.pl ---- org/crypto/sha/asm/sha256-armv4.pl 2017-05-25 05:54:34.000000000 -0700 -+++ mod/crypto/sha/asm/sha256-armv4.pl 2018-01-17 20:36:12.518242800 -0800 -@@ -576,6 +576,7 @@ - my @MSG=map("q$_",(8..11)); - my ($W0,$W1,$ABCD_SAVE,$EFGH_SAVE)=map("q$_",(12..15)); - my $Ktbl="r3"; -+my $Temp="r4"; - - $code.=<<___; - #if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) -@@ -591,7 +592,13 @@ - sha256_block_data_order_armv8: - .LARMv8: - vld1.32 {$ABCD,$EFGH},[$ctx] --# ifdef __thumb2__ -+# if defined(__clang__) -+ stmdb sp!,{r4,lr} -+ adr $Ktbl,.LARMv8 -+ ldr $Temp,=K256 -+ sub $Temp,$Ktbl,$Temp -+ sub $Ktbl,$Ktbl,$Temp -+# elif defined(__thumb2__) - adr $Ktbl,.LARMv8 - sub $Ktbl,$Ktbl,#.LARMv8-K256 - # else -@@ -655,7 +662,12 @@ - - vst1.32 {$ABCD,$EFGH},[$ctx] - -+# ifdef __clang__ -+ ldmia sp!,{r4,pc} -+# else - ret @ bx lr -+# endif -+ - .size sha256_block_data_order_armv8,.-sha256_block_data_order_armv8 - #endif - ___ -diff -Naur org/Makefile.org mod/Makefile.org ---- org/Makefile.org 2017-05-25 05:54:38.000000000 -0700 -+++ mod/Makefile.org 2018-01-17 20:36:12.532553700 -0800 -@@ -540,7 +540,7 @@ - @$(MAKE) SDIRS='$(SDIRS)' clean - @$(MAKE) TAR='$(TAR)' TARFLAGS='$(TARFLAGS)' $(DISTTARVARS) tar - --install: all install_docs install_sw -+install: install_docs install_sw - - install_sw: - @$(PERL) $(TOP)/util/mkdir-p.pl $(INSTALL_PREFIX)$(INSTALLTOP)/bin \ diff --git a/Build_android/openssl/openssl-1.0.2m.patch b/Build_android/openssl/openssl-1.0.2m.patch deleted file mode 100644 index 8314b1e7fd..0000000000 --- a/Build_android/openssl/openssl-1.0.2m.patch +++ /dev/null @@ -1,108 +0,0 @@ -This patch applies several changes that enable OpenSSL 1.0.2m to be built -for Android using either Clang or GCC toolchains. - -An alias for the android-armv7 target, named android-armeabi, is added for -compatability with the OpenSSL 1.1.0 configuration target names. Support for -the AArch64 archicture is also added, as well as targets using the Clang -compiler. - -Clang does not recognize some of the ARM assembly nmenonics that are used in -OpenSSL. In particular, the 'adrl' pseudo instruction is not supported. To -further complicate matters, Clang doesn't support immediate fixup values so -the alternative adr/sub sequence used for the Thumb2 code path cannot be -used either. Instead it is replaced with a sequence of instructions that -computes the offset at runtime. It utilizes register r4 for computing the -intermediate result, which is first saved to and later restored from the -stack. The upstream bug in LLVM can be found here: -https://llvm.org/bugs/show_bug.cgi?id=24350 - -diff -Naur org/Configure mod/Configure ---- org/Configure 2017-11-02 07:32:57.000000000 -0700 -+++ mod/Configure 2018-01-17 20:39:03.152448900 -0800 -@@ -471,10 +471,17 @@ - "linux-alpha+bwx-ccc","ccc:-fast -readonly_strings -DL_ENDIAN::-D_REENTRANT:::SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_PTR DES_RISC1 DES_UNROLL:${alpha_asm}", - - # Android: linux-* but without pointers to headers and libs. --"android","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", --"android-x86","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:".eval{my $asm=${x86_elf_asm};$asm=~s/:elf/:android/;$asm}.":dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", --"android-armv7","gcc:-march=armv7-a -mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", --"android-mips","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android","gcc:-mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-x86","gcc:-mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:".eval{my $asm=${x86_elf_asm};$asm=~s/:elf/:android/;$asm}.":dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-armv7","gcc:-march=armv7-a -mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-armeabi","gcc:-march=armv7-a -mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android64-aarch64","gcc:-march=armv8-a -mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${aarch64_asm}:linux64:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-mips","gcc:-mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-x86-clang","clang:-target i686-none-linux-android --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:".eval{my $asm=${x86_elf_asm};$asm=~s/:elf/:android/;$asm}.":dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-armv7-clang","clang:-target armv7-none-linux-androideabi --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-armeabi-clang","clang:-target armv7-none-linux-androideabi --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android64-aarch64-clang","clang:-target aarch64-none-linux-android --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${aarch64_asm}:linux64:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-mips-clang","clang:-target mipsel-none-linux-android --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", - - #### *BSD [do see comment about ${BSDthreads} above!] - "BSD-generic32","gcc:-O3 -fomit-frame-pointer -Wall::${BSDthreads}:::BN_LLONG RC2_CHAR RC4_INDEX DES_INT DES_UNROLL:${no_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -diff -Naur org/crypto/bn/asm/armv4-gf2m.pl mod/crypto/bn/asm/armv4-gf2m.pl ---- org/crypto/bn/asm/armv4-gf2m.pl 2017-11-02 07:32:57.000000000 -0700 -+++ mod/crypto/bn/asm/armv4-gf2m.pl 2018-01-17 20:39:03.163187500 -0800 -@@ -213,8 +213,8 @@ - .align 5 - .LNEON: - ldr r12, [sp] @ 5th argument -- vmov.32 $a, r2, r1 -- vmov.32 $b, r12, r3 -+ vmov $a, r2, r1 -+ vmov $b, r12, r3 - vmov.i64 $k48, #0x0000ffffffffffff - vmov.i64 $k32, #0x00000000ffffffff - vmov.i64 $k16, #0x000000000000ffff -diff -Naur org/crypto/sha/asm/sha256-armv4.pl mod/crypto/sha/asm/sha256-armv4.pl ---- org/crypto/sha/asm/sha256-armv4.pl 2017-11-02 07:32:58.000000000 -0700 -+++ mod/crypto/sha/asm/sha256-armv4.pl 2018-01-17 20:39:03.173547800 -0800 -@@ -576,6 +576,7 @@ - my @MSG=map("q$_",(8..11)); - my ($W0,$W1,$ABCD_SAVE,$EFGH_SAVE)=map("q$_",(12..15)); - my $Ktbl="r3"; -+my $Temp="r4"; - - $code.=<<___; - #if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) -@@ -591,7 +592,13 @@ - sha256_block_data_order_armv8: - .LARMv8: - vld1.32 {$ABCD,$EFGH},[$ctx] --# ifdef __thumb2__ -+# if defined(__clang__) -+ stmdb sp!,{r4,lr} -+ adr $Ktbl,.LARMv8 -+ ldr $Temp,=K256 -+ sub $Temp,$Ktbl,$Temp -+ sub $Ktbl,$Ktbl,$Temp -+# elif defined(__thumb2__) - adr $Ktbl,.LARMv8 - sub $Ktbl,$Ktbl,#.LARMv8-K256 - # else -@@ -655,7 +662,12 @@ - - vst1.32 {$ABCD,$EFGH},[$ctx] - -+# ifdef __clang__ -+ ldmia sp!,{r4,pc} -+# else - ret @ bx lr -+# endif -+ - .size sha256_block_data_order_armv8,.-sha256_block_data_order_armv8 - #endif - ___ -diff -Naur org/Makefile.org mod/Makefile.org ---- org/Makefile.org 2017-11-02 07:32:57.000000000 -0700 -+++ mod/Makefile.org 2018-01-17 20:39:03.187911200 -0800 -@@ -540,7 +540,7 @@ - @$(MAKE) SDIRS='$(SDIRS)' clean - @$(MAKE) TAR='$(TAR)' TARFLAGS='$(TARFLAGS)' $(DISTTARVARS) tar - --install: all install_docs install_sw -+install: install_docs install_sw - - install_sw: - @$(PERL) $(TOP)/util/mkdir-p.pl $(INSTALL_PREFIX)$(INSTALLTOP)/bin \ diff --git a/Build_android/openssl/openssl-1.0.2n.patch b/Build_android/openssl/openssl-1.0.2n.patch deleted file mode 100644 index 7e96205923..0000000000 --- a/Build_android/openssl/openssl-1.0.2n.patch +++ /dev/null @@ -1,108 +0,0 @@ -This patch applies several changes that enable OpenSSL 1.0.2n to be built -for Android using either Clang or GCC toolchains. - -An alias for the android-armv7 target, named android-armeabi, is added for -compatability with the OpenSSL 1.1.0 configuration target names. Support for -the AArch64 archicture is also added, as well as targets using the Clang -compiler. - -Clang does not recognize some of the ARM assembly nmenonics that are used in -OpenSSL. In particular, the 'adrl' pseudo instruction is not supported. To -further complicate matters, Clang doesn't support immediate fixup values so -the alternative adr/sub sequence used for the Thumb2 code path cannot be -used either. Instead it is replaced with a sequence of instructions that -computes the offset at runtime. It utilizes register r4 for computing the -intermediate result, which is first saved to and later restored from the -stack. The upstream bug in LLVM can be found here: -https://llvm.org/bugs/show_bug.cgi?id=24350 - -diff -Naur org/Configure mod/Configure ---- org/Configure 2017-12-07 05:16:38.000000000 -0800 -+++ mod/Configure 2018-01-17 20:41:03.880613500 -0800 -@@ -471,10 +471,17 @@ - "linux-alpha+bwx-ccc","ccc:-fast -readonly_strings -DL_ENDIAN::-D_REENTRANT:::SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_PTR DES_RISC1 DES_UNROLL:${alpha_asm}", - - # Android: linux-* but without pointers to headers and libs. --"android","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", --"android-x86","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:".eval{my $asm=${x86_elf_asm};$asm=~s/:elf/:android/;$asm}.":dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", --"android-armv7","gcc:-march=armv7-a -mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", --"android-mips","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android","gcc:-mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-x86","gcc:-mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:".eval{my $asm=${x86_elf_asm};$asm=~s/:elf/:android/;$asm}.":dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-armv7","gcc:-march=armv7-a -mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-armeabi","gcc:-march=armv7-a -mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android64-aarch64","gcc:-march=armv8-a -mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${aarch64_asm}:linux64:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-mips","gcc:-mandroid --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-x86-clang","clang:-target i686-none-linux-android --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:".eval{my $asm=${x86_elf_asm};$asm=~s/:elf/:android/;$asm}.":dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-armv7-clang","clang:-target armv7-none-linux-androideabi --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-armeabi-clang","clang:-target armv7-none-linux-androideabi --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android64-aarch64-clang","clang:-target aarch64-none-linux-android --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${aarch64_asm}:linux64:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"android-mips-clang","clang:-target mipsel-none-linux-android --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot \$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -B\$(ANDROID_LINK_SYSROOT)/lib -D__ANDROID_API__=\$(ANDROID_API) -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", - - #### *BSD [do see comment about ${BSDthreads} above!] - "BSD-generic32","gcc:-O3 -fomit-frame-pointer -Wall::${BSDthreads}:::BN_LLONG RC2_CHAR RC4_INDEX DES_INT DES_UNROLL:${no_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -diff -Naur org/crypto/bn/asm/armv4-gf2m.pl mod/crypto/bn/asm/armv4-gf2m.pl ---- org/crypto/bn/asm/armv4-gf2m.pl 2017-12-07 05:16:38.000000000 -0800 -+++ mod/crypto/bn/asm/armv4-gf2m.pl 2018-01-17 20:41:03.891956700 -0800 -@@ -213,8 +213,8 @@ - .align 5 - .LNEON: - ldr r12, [sp] @ 5th argument -- vmov.32 $a, r2, r1 -- vmov.32 $b, r12, r3 -+ vmov $a, r2, r1 -+ vmov $b, r12, r3 - vmov.i64 $k48, #0x0000ffffffffffff - vmov.i64 $k32, #0x00000000ffffffff - vmov.i64 $k16, #0x000000000000ffff -diff -Naur org/crypto/sha/asm/sha256-armv4.pl mod/crypto/sha/asm/sha256-armv4.pl ---- org/crypto/sha/asm/sha256-armv4.pl 2017-12-07 05:16:38.000000000 -0800 -+++ mod/crypto/sha/asm/sha256-armv4.pl 2018-01-17 20:41:03.901983600 -0800 -@@ -576,6 +576,7 @@ - my @MSG=map("q$_",(8..11)); - my ($W0,$W1,$ABCD_SAVE,$EFGH_SAVE)=map("q$_",(12..15)); - my $Ktbl="r3"; -+my $Temp="r4"; - - $code.=<<___; - #if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) -@@ -591,7 +592,13 @@ - sha256_block_data_order_armv8: - .LARMv8: - vld1.32 {$ABCD,$EFGH},[$ctx] --# ifdef __thumb2__ -+# if defined(__clang__) -+ stmdb sp!,{r4,lr} -+ adr $Ktbl,.LARMv8 -+ ldr $Temp,=K256 -+ sub $Temp,$Ktbl,$Temp -+ sub $Ktbl,$Ktbl,$Temp -+# elif defined(__thumb2__) - adr $Ktbl,.LARMv8 - sub $Ktbl,$Ktbl,#.LARMv8-K256 - # else -@@ -655,7 +662,12 @@ - - vst1.32 {$ABCD,$EFGH},[$ctx] - -+# ifdef __clang__ -+ ldmia sp!,{r4,pc} -+# else - ret @ bx lr -+# endif -+ - .size sha256_block_data_order_armv8,.-sha256_block_data_order_armv8 - #endif - ___ -diff -Naur org/Makefile.org mod/Makefile.org ---- org/Makefile.org 2017-12-07 05:16:38.000000000 -0800 -+++ mod/Makefile.org 2018-01-17 20:41:03.916748800 -0800 -@@ -540,7 +540,7 @@ - @$(MAKE) SDIRS='$(SDIRS)' clean - @$(MAKE) TAR='$(TAR)' TARFLAGS='$(TARFLAGS)' $(DISTTARVARS) tar - --install: all install_docs install_sw -+install: install_docs install_sw - - install_sw: - @$(PERL) $(TOP)/util/mkdir-p.pl $(INSTALL_PREFIX)$(INSTALLTOP)/bin \ diff --git a/Build_android/openssl/openssl-1.1.0g.patch b/Build_android/openssl/openssl-1.1.0g.patch deleted file mode 100644 index 77a92779d7..0000000000 --- a/Build_android/openssl/openssl-1.1.0g.patch +++ /dev/null @@ -1,76 +0,0 @@ -This patch applies several changes that enable OpenSSL 1.1.0g to be built -for Android using either Clang or GCC toolchains. - -diff -Naur org/Configurations/10-main.conf mod/Configurations/10-main.conf ---- org/Configurations/10-main.conf 2017-11-02 07:29:01.000000000 -0700 -+++ mod/Configurations/10-main.conf 2018-01-18 10:59:41.675138500 -0800 -@@ -910,15 +910,27 @@ - # systems are perfectly capable of executing binaries targeting - # Froyo. Keep in mind that in the nutshell Android builds are - # about JNI, i.e. shared libraries, not applications. -- cflags => add(picker(default => "-mandroid -fPIC --sysroot=\$(CROSS_SYSROOT) -Wa,--noexecstack")), -+ cflags => add(picker(default => "-mandroid -fPIC --sysroot=\$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -D__ANDROID_API__=\$(ANDROID_API) -Wa,--noexecstack")), - bin_cflags => "-pie", - }, -+ "android-clang" => { -+ inherit_from => [ "linux-generic32" ], -+ cc => "clang", -+ cflags => add(picker(default => "-fPIC --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot=\$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -D__ANDROID_API__=\$(ANDROID_API) -Wextra -Wno-missing-field-initializers -Wno-unused-parameter -Qunused-arguments -Wa,--noexecstack")), -+}, - "android-x86" => { - inherit_from => [ "android", asm("x86_asm") ], - cflags => add(picker(release => "-fomit-frame-pointer")), - bn_ops => "BN_LLONG", - perlasm_scheme => "android", - }, -+ "android-x86-clang" => { -+ inherit_from => [ "android-clang", asm("x86_asm") ], -+ cflags => add(picker(default => "-target i686-none-linux-android", -+ release => "-fomit-frame-pointer")), -+ bn_ops => "BN_LLONG", -+ perlasm_scheme => "android", -+ }, - ################################################################ - # Contemporary Android applications can provide multiple JNI - # providers in .apk, targeting multiple architectures. Among -@@ -943,20 +955,38 @@ - "android-armeabi" => { - inherit_from => [ "android", asm("armv4_asm") ], - }, -+ "android-armeabi-clang" => { -+ inherit_from => [ "android-clang", asm("armv4_asm") ], -+ cflags => add("-target armv7-none-linux-androideabi"), -+ }, - "android-mips" => { - inherit_from => [ "android", asm("mips32_asm") ], - perlasm_scheme => "o32", - }, -- -+ "android-mips-clang" => { -+ inherit_from => [ "android-clang", asm("mips32_asm") ], -+ cflags => add("-target mipsel-none-linux-android"), -+ perlasm_scheme => "o32", -+ }, - "android64" => { - inherit_from => [ "linux-generic64" ], -- cflags => add(picker(default => "-mandroid -fPIC --sysroot=\$(CROSS_SYSROOT) -Wa,--noexecstack")), -+ cflags => add(picker(default => "-mandroid -fPIC --sysroot=\$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -D__ANDROID_API__=\$(ANDROID_API) -Wa,--noexecstack")), - bin_cflags => "-pie", - }, -+ "android64-clang" => { -+ inherit_from => [ "linux-generic64" ], -+ cc => "clang", -+ cflags => add(picker(default => "-fPIC --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot=\$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -D__ANDROID_API__=\$(ANDROID_API) -Wextra -Wno-missing-field-initializers -Wno-unused-parameter -Qunused-arguments -Wa,--noexecstack")), -+ }, - "android64-aarch64" => { - inherit_from => [ "android64", asm("aarch64_asm") ], - perlasm_scheme => "linux64", - }, -+ "android64-aarch64-clang" => { -+ inherit_from => [ "android64-clang", asm("aarch64_asm") ], -+ cflags => add("-target aarch64-none-linux-android"), -+ perlasm_scheme => "linux64", -+ }, - - #### *BSD - "BSD-generic32" => { diff --git a/Build_android/openssl/openssl-1.1.0j.patch b/Build_android/openssl/openssl-1.1.0j.patch deleted file mode 100644 index 77a92779d7..0000000000 --- a/Build_android/openssl/openssl-1.1.0j.patch +++ /dev/null @@ -1,76 +0,0 @@ -This patch applies several changes that enable OpenSSL 1.1.0g to be built -for Android using either Clang or GCC toolchains. - -diff -Naur org/Configurations/10-main.conf mod/Configurations/10-main.conf ---- org/Configurations/10-main.conf 2017-11-02 07:29:01.000000000 -0700 -+++ mod/Configurations/10-main.conf 2018-01-18 10:59:41.675138500 -0800 -@@ -910,15 +910,27 @@ - # systems are perfectly capable of executing binaries targeting - # Froyo. Keep in mind that in the nutshell Android builds are - # about JNI, i.e. shared libraries, not applications. -- cflags => add(picker(default => "-mandroid -fPIC --sysroot=\$(CROSS_SYSROOT) -Wa,--noexecstack")), -+ cflags => add(picker(default => "-mandroid -fPIC --sysroot=\$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -D__ANDROID_API__=\$(ANDROID_API) -Wa,--noexecstack")), - bin_cflags => "-pie", - }, -+ "android-clang" => { -+ inherit_from => [ "linux-generic32" ], -+ cc => "clang", -+ cflags => add(picker(default => "-fPIC --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot=\$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -D__ANDROID_API__=\$(ANDROID_API) -Wextra -Wno-missing-field-initializers -Wno-unused-parameter -Qunused-arguments -Wa,--noexecstack")), -+}, - "android-x86" => { - inherit_from => [ "android", asm("x86_asm") ], - cflags => add(picker(release => "-fomit-frame-pointer")), - bn_ops => "BN_LLONG", - perlasm_scheme => "android", - }, -+ "android-x86-clang" => { -+ inherit_from => [ "android-clang", asm("x86_asm") ], -+ cflags => add(picker(default => "-target i686-none-linux-android", -+ release => "-fomit-frame-pointer")), -+ bn_ops => "BN_LLONG", -+ perlasm_scheme => "android", -+ }, - ################################################################ - # Contemporary Android applications can provide multiple JNI - # providers in .apk, targeting multiple architectures. Among -@@ -943,20 +955,38 @@ - "android-armeabi" => { - inherit_from => [ "android", asm("armv4_asm") ], - }, -+ "android-armeabi-clang" => { -+ inherit_from => [ "android-clang", asm("armv4_asm") ], -+ cflags => add("-target armv7-none-linux-androideabi"), -+ }, - "android-mips" => { - inherit_from => [ "android", asm("mips32_asm") ], - perlasm_scheme => "o32", - }, -- -+ "android-mips-clang" => { -+ inherit_from => [ "android-clang", asm("mips32_asm") ], -+ cflags => add("-target mipsel-none-linux-android"), -+ perlasm_scheme => "o32", -+ }, - "android64" => { - inherit_from => [ "linux-generic64" ], -- cflags => add(picker(default => "-mandroid -fPIC --sysroot=\$(CROSS_SYSROOT) -Wa,--noexecstack")), -+ cflags => add(picker(default => "-mandroid -fPIC --sysroot=\$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -D__ANDROID_API__=\$(ANDROID_API) -Wa,--noexecstack")), - bin_cflags => "-pie", - }, -+ "android64-clang" => { -+ inherit_from => [ "linux-generic64" ], -+ cc => "clang", -+ cflags => add(picker(default => "-fPIC --gcc-toolchain=\$(ANDROID_GCC_TOOLCHAIN) --sysroot=\$(ANDROID_LINK_SYSROOT) -isystem \$(ANDROID_SYSROOT)/usr/include -isystem \$(ANDROID_SYSROOT)/usr/include/\$(ANDROID_TRIPLE) -D__ANDROID_API__=\$(ANDROID_API) -Wextra -Wno-missing-field-initializers -Wno-unused-parameter -Qunused-arguments -Wa,--noexecstack")), -+ }, - "android64-aarch64" => { - inherit_from => [ "android64", asm("aarch64_asm") ], - perlasm_scheme => "linux64", - }, -+ "android64-aarch64-clang" => { -+ inherit_from => [ "android64-clang", asm("aarch64_asm") ], -+ cflags => add("-target aarch64-none-linux-android"), -+ perlasm_scheme => "linux64", -+ }, - - #### *BSD - "BSD-generic32" => { diff --git a/Build_iOS/.gitignore b/Build_iOS/.gitignore deleted file mode 100644 index 93f4744bb6..0000000000 --- a/Build_iOS/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -# iOS folders that dependencies get stored in -boostoniphone/ -boost -boost.framework/ -ios-cmake/ -openssl/ -OpenSSL-for-iPhone/ \ No newline at end of file diff --git a/Build_iOS/CMakeLists.txt b/Build_iOS/CMakeLists.txt deleted file mode 100644 index 0cf1b62467..0000000000 --- a/Build_iOS/CMakeLists.txt +++ /dev/null @@ -1,133 +0,0 @@ -project(casablanca-ios NONE) -cmake_minimum_required(VERSION 3.1) - -enable_testing() - -set(LIB_CPPREST libcpprest.a) -set(LIB_CPPREST_LIB_DIR "${CMAKE_CURRENT_BINARY_DIR}/lib") - -if (CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET) - set (ENV{CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET} ${CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET}) -endif() - -set(TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/ios-cmake/ios.toolchain.cmake") - -set(SIM_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/build.i386" CACHE INTERNAL "") -set(SIM_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../Release" CACHE INTERNAL "") - -set(SIM64_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/build.x86_64" CACHE INTERNAL "") -set(SIM64_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../Release" CACHE INTERNAL "") - -set(ARM_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/build.arm" CACHE INTERNAL "") -set(ARM_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../Release" CACHE INTERNAL "") - -if (DISABLE_BITCODE) - set (ENABLE_BITCODE_ARG -DENABLE_BITCODE=OFF) -endif() - -if (INCLUDE_32BIT) - set (IOS_PLATFORM_VALUE OS) -else() - set (IOS_PLATFORM_VALUE OS64) -endif() - -if (DEPLOYMENT_TARGET) - set (DEPLOYMENT_TARGET -DIOS_DEPLOYMENT_TARGET=${DEPLOYMENT_TARGET}) -endif() - -add_test(NAME ios_runner - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../Release/tests/common/testrunner/ios - COMMAND xcodebuild test -project ios_runner.xcodeproj -configuration=${CMAKE_BUILD_TYPE} -scheme ios_runner -destination "platform=iOS Simulator,name=iPhone 6" LIBRARY_SEARCH_PATH=${SIM64_BINARY_DIR} - ) - -if (INCLUDE_32BIT) -set (SIM_BINARY_LIB ${SIM_BINARY_DIR}/Binaries/${CMAKE_BUILD_TYPE}/${LIB_CPPREST}) -file(MAKE_DIRECTORY ${SIM_BINARY_DIR}) -execute_process(WORKING_DIRECTORY ${SIM_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} - -GXcode - -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} - -DIOS_PLATFORM=SIMULATOR - -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - "${DEPLOYMENT_TARGET}" - "${SIM_SOURCE_DIR}" -) -else() -set (SIM_BINARY_LIB "") -endif() - -file(MAKE_DIRECTORY ${SIM64_BINARY_DIR}) -execute_process(WORKING_DIRECTORY ${SIM64_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} - -GXcode - -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} - -DIOS_PLATFORM=SIMULATOR64 - -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - "${DEPLOYMENT_TARGET}" - "${SIM64_SOURCE_DIR}" -) - -file(MAKE_DIRECTORY ${ARM_BINARY_DIR}) -execute_process(WORKING_DIRECTORY ${ARM_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} - -GXcode - -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} - -DIOS_PLATFORM=${IOS_PLATFORM_VALUE} - -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - "${DEPLOYMENT_TARGET}" - "${ENABLE_BITCODE_ARG}" - "${ARM_SOURCE_DIR}" - ) - -if (INCLUDE_32BIT) -set (SIM_TARGET sim) -## Simulator i386 version -add_custom_target(sim - COMMAND ${CMAKE_COMMAND} - --build ${SIM_BINARY_DIR} - --config ${CMAKE_BUILD_TYPE} - COMMENT "Building for i386 (simulator)" -VERBATIM -) -else() -set (SIM_TARGET "") -endif() - -## Simulator x86_64 version -add_custom_target(sim64 - COMMAND ${CMAKE_COMMAND} - --build ${SIM64_BINARY_DIR} - --config ${CMAKE_BUILD_TYPE} - COMMENT "Building for x86_64 (simulator)" -VERBATIM -) - -## ARM version -add_custom_target(arm - COMMAND ${CMAKE_COMMAND} - --build ${ARM_BINARY_DIR} - --config ${CMAKE_BUILD_TYPE} - COMMENT "Building for arm" - VERBATIM -) - -add_custom_command( - OUTPUT ${LIB_CPPREST_LIB_DIR}/${LIB_CPPREST} - COMMAND mkdir -p "${LIB_CPPREST_LIB_DIR}" - COMMAND lipo -create - -output "${LIB_CPPREST_LIB_DIR}/${LIB_CPPREST}" - ${SIM_BINARY_LIB} - ${SIM64_BINARY_DIR}/Binaries/${CMAKE_BUILD_TYPE}/${LIB_CPPREST} - ${ARM_BINARY_DIR}/Binaries/${CMAKE_BUILD_TYPE}/${LIB_CPPREST} - COMMAND cp -R "${CMAKE_CURRENT_SOURCE_DIR}/../Release/include" "${CMAKE_CURRENT_BINARY_DIR}" - DEPENDS - ${SIM_TARGET} - sim64 - arm - ${SIM_BINARY_LIB} - "${SIM64_BINARY_DIR}/Binaries/${CMAKE_BUILD_TYPE}/${LIB_CPPREST}" - "${ARM_BINARY_DIR}/Binaries/${CMAKE_BUILD_TYPE}/${LIB_CPPREST}" - VERBATIM -) - -add_custom_target(cpprest ALL DEPENDS "${LIB_CPPREST_LIB_DIR}/${LIB_CPPREST}") diff --git a/Build_iOS/README.md b/Build_iOS/README.md deleted file mode 100644 index a5c58cc98a..0000000000 --- a/Build_iOS/README.md +++ /dev/null @@ -1 +0,0 @@ -Please consult the documentation [here](https://github.com/Microsoft/cpprestsdk/wiki/How-to-build-for-iOS) for iOS compilation. diff --git a/Build_iOS/configure.sh b/Build_iOS/configure.sh deleted file mode 100755 index d4240d8943..0000000000 --- a/Build_iOS/configure.sh +++ /dev/null @@ -1,165 +0,0 @@ -#!/usr/bin/env bash -set -e - -usage() { - echo "Usage: configure.sh [-build_type type] [-deployment_target version] [-config_only] [-include_32bit] [-no_bitcode]" - echo " -build_type defines the CMAKE_BUILD_TYPE used. Defaults to Release." - echo " -deployment_target defines minimum iOS Deployment Target. The default is dependent on ios.toolchain.cmake and currently defaults to 8.0" - echo " -config_only only configures cmake (no make invoked)." - echo " -include_32bit includes the 32-bit arm architectures." - echo " -no_bitcode disables bitcode" - echo " -clean deletes build directory prior to configuring" -} - -ABS_PATH="`dirname \"$0\"`" # relative -ABS_PATH="`( cd \"${ABS_PATH}\" && pwd )`" # absolutized and normalized -# Make sure that the path to this file exists and can be retrieved! -if [ -z "${ABS_PATH}" ]; then - echo "Could not fetch the ABS_PATH." - exit 1 -fi - -CONFIG_ONLY=0 -INCLUDE_32BIT="" -DISABLE_BITCODE="" -DEPLOYMENT_TARGET="" -CLEAN=0 - -# Command line argument parsing -while (( "$#" )); do - case "$1" in - -build_type) - if [ "$#" -lt 2 ] || [[ "$2" == -* ]] ; then - usage - echo "Error: argument $1 expecting a value to follow." - exit 1 - fi - - CPPRESTSDK_BUILD_TYPE=$2 - shift 2 - ;; - -deployment_target) - if [ "$#" -lt 2 ] || [[ "$2" == -* ]] ; then - usage - echo "Error: argument $1 expecting a value to follow." - exit 1 - fi - - DEPLOYMENT_TARGET="-DDEPLOYMENT_TARGET=$2" - shift 2 - ;; - -config_only) - CONFIG_ONLY=1 - shift 1 - ;; - -include_32bit) - INCLUDE_32BIT="-DINCLUDE_32BIT=ON" - shift 1 - ;; - -no_bitcode) - DISABLE_BITCODE="-DDISABLE_BITCODE=ON" - shift 1 - ;; - -clean) - CLEAN=1 - shift 1 - ;; - *) - usage - echo "Error: unsupported argument $1" - exit 1 - ;; - esac -done - -## Configuration -DEFAULT_BOOST_VERSION=1.67.0 -DEFAULT_OPENSSL_VERSION=1.0.2o -BOOST_VERSION=${BOOST_VERSION:-${DEFAULT_BOOST_VERSION}} -OPENSSL_VERSION=${OPENSSL_VERSION:-${DEFAULT_OPENSSL_VERSION}} -CPPRESTSDK_BUILD_TYPE=${CPPRESTSDK_BUILD_TYPE:-Release} - -############################ No need to edit anything below this line - -## Set some needed variables -IOS_SDK_VERSION=`xcrun --sdk iphoneos --show-sdk-version` - -## Buildsteps below - -## Fetch submodules just in case -git submodule update --init - -## Build Boost - -if [ ! -e $ABS_PATH/boost.framework ] && [ ! -d $ABS_PATH/boost ]; then - if [ ! -d "${ABS_PATH}/Apple-Boost-BuildScript" ]; then - git clone https://github.com/faithfracture/Apple-Boost-BuildScript ${ABS_PATH}/Apple-Boost-BuildScript - fi - pushd ${ABS_PATH}/Apple-Boost-BuildScript - git checkout 1b94ec2e2b5af1ee036d9559b96e70c113846392 - BOOST_LIBS="thread chrono filesystem regex system random" ./boost.sh -ios -tvos --boost-version $BOOST_VERSION - popd - mv ${ABS_PATH}/Apple-Boost-BuildScript/build/boost/${BOOST_VERSION}/ios/framework/boost.framework ${ABS_PATH} - mv ${ABS_PATH}/boost.framework/Versions/A/Headers ${ABS_PATH}/boost.headers - mkdir -p ${ABS_PATH}/boost.framework/Versions/A/Headers - mv ${ABS_PATH}/boost.headers ${ABS_PATH}/boost.framework/Versions/A/Headers/boost -fi - -## Build OpenSSL - -if [ ! -e ${ABS_PATH}/openssl/lib/libcrypto.a ]; then - if [ ! -d "${ABS_PATH}/OpenSSL-for-iPhone" ]; then - git clone --depth=1 https://github.com/x2on/OpenSSL-for-iPhone.git ${ABS_PATH}/OpenSSL-for-iPhone - fi - pushd ${ABS_PATH}/OpenSSL-for-iPhone - git checkout 10019638e80e8a8a5fc19642a840d8a69fac7349 - ./build-libssl.sh --version=${OPENSSL_VERSION} - popd - mkdir -p ${ABS_PATH}/openssl/lib - if [ -e ${ABS_PATH}/OpenSSL-for-iPhone/bin/iPhoneOS${IOS_SDK_VERSION}-arm64.sdk/include ] - then - cp -r ${ABS_PATH}/OpenSSL-for-iPhone/bin/iPhoneOS${IOS_SDK_VERSION}-arm64.sdk/include ${ABS_PATH}/openssl - else - echo 'Could not find OpenSSL for iPhone' - exit 1 - fi - cp ${ABS_PATH}/OpenSSL-for-iPhone/include/LICENSE ${ABS_PATH}/openssl - lipo -create -output ${ABS_PATH}/openssl/lib/libssl.a ${ABS_PATH}/OpenSSL-for-iPhone/bin/iPhone*/lib/libssl.a - lipo -create -output ${ABS_PATH}/openssl/lib/libcrypto.a ${ABS_PATH}/OpenSSL-for-iPhone/bin/iPhone*/lib/libcrypto.a -fi - -## Fetch CMake toolchain - -if [ ! -e ${ABS_PATH}/ios-cmake/ios.toolchain.cmake ]; then - if [ ! -d "${ABS_PATH}/ios-cmake" ]; then - git clone https://github.com/leetal/ios-cmake ${ABS_PATH}/ios-cmake - fi - pushd ${ABS_PATH}/ios-cmake - git checkout 2.1.2 - popd -fi - -## Build CPPRestSDK -if [ -d "${ABS_PATH}/build.${CPPRESTSDK_BUILD_TYPE}.ios" ]; then - if [ "$CLEAN" -eq 1 ]; then - echo "Removing directory ${ABS_PATH}/build.${CPPRESTSDK_BUILD_TYPE}.ios prior to configuring." - rm -rf "${ABS_PATH}/build.${CPPRESTSDK_BUILD_TYPE}.ios" - else - printf "WARNING: Running configure on an already existing configuration.\nAny changes to the existing configuration will not be picked up.\nEither remove the directory and re-run configure or run configure with the -clean flag.\n\n" - fi -fi - -mkdir -p ${ABS_PATH}/build.${CPPRESTSDK_BUILD_TYPE}.ios -pushd ${ABS_PATH}/build.${CPPRESTSDK_BUILD_TYPE}.ios -cmake -DCMAKE_BUILD_TYPE=${CPPRESTSDK_BUILD_TYPE} .. ${INCLUDE_32BIT} ${DISABLE_BITCODE} ${DEPLOYMENT_TARGET} -if [ "$CONFIG_ONLY" -eq 0 ]; then - make - printf "\n\n===================================================================================\n" - echo ">>>> The final library is available in 'build.${CPPRESTSDK_BUILD_TYPE}.ios/lib/libcpprest.a'" - printf "===================================================================================\n\n" -else - printf "\n\n===================================================================================\n" - echo ">>>> Configuration complete. Run 'make' in 'build.${CPPRESTSDK_BUILD_TYPE}.ios' to build." - printf "===================================================================================\n\n" -fi -popd diff --git a/HTTP_CLIENT_GET_PICTURE/HTTP_CLIENT_GET_PICTURE.cpp b/HTTP_CLIENT_GET_PICTURE/HTTP_CLIENT_GET_PICTURE.cpp new file mode 100644 index 0000000000..583ce42a1a --- /dev/null +++ b/HTTP_CLIENT_GET_PICTURE/HTTP_CLIENT_GET_PICTURE.cpp @@ -0,0 +1,163 @@ +// HTTP_CLIENT_GET_PICTURE.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 +//https://www.cnblogs.com/highway-9/p/6021238.html + +//#include +// +//int main() +//{ +// std::cout << "Hello World!\n"; +//} + +// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单 +// 调试程序: F5 或调试 >“开始调试”菜单 + +// 入门使用技巧: +// 1. 使用解决方案资源管理器窗口添加/管理文件 +// 2. 使用团队资源管理器窗口连接到源代码管理 +// 3. 使用输出窗口查看生成输出和其他消息 +// 4. 使用错误列表窗口查看错误 +// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目 +// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// 请求并解析url +bool get_result(const std::string& url, const std::string& pattern, std::vector& vec) +{ + try + { + //Converts to a platform dependent Unicode string type. 这是转unicode + web::http::client::http_client client(web::uri(utility::conversions::to_string_t(url))); + //获取服务端的应答 + web::http::http_response response = client.request(web::http::methods::GET).get(); + + concurrency::streams::stringstreambuf buffer; + response.body().read_to_end(buffer).get(); + std::string& str = buffer.collection(); + + // 使用C++11提供的正则表达式库 + std::regex r(pattern); + for (std::sregex_iterator iter(str.begin(), str.end(), r), end; iter != end; ++iter) + { + std::cout << iter->str() << std::endl; + vec.emplace_back(iter->str()); + } + } + catch (std::exception& e) + { + std::cout << "Exception: " << e.what() << std::endl; + return false; + } + + return true; +} + +// 获取图片 +bool get_result(const std::string& url, std::string& picture) +{ + try + { + //创建客户端 + web::http::client::http_client client(web::uri(utility::conversions::to_string_t(url))); + //获取get的应答 + web::http::http_response response = client.request(web::http::methods::GET).get(); + //读取应答 + concurrency::streams::stringstreambuf buffer; + response.body().read_to_end(buffer).get(); + //基于内存的流buffer,不可用于生产者和消费者 + picture = buffer.collection(); + } + catch (std::exception& e) + { + std::cout <<__FUNCTION__<< url<<" Exception: " << e.what() << std::endl; + return false; + } + + return true; +} + +// 保存图片 +bool write_to_file(const std::string& file_path, const std::string& data) +{ + try + { + std::ofstream file; + file.open(file_path, std::ios::out | std::ios::binary); + if (!file.good()) + { + return false; + } + file.write(data.c_str(), data.size()); + file.close(); + } + catch (std::exception& e) + { + std::cout << "Exception: " << e.what() << std::endl; + return false; + } + + return true; +} + +int main() +{ + // [1] 请求每一页,将子页面的url保存在sub_url_vec里面 + std::vector sub_url_vec; + //类似 url: http://www.51ztzj.com/desk/54887.htm + std::string pattern = "/desk/[0-9]+.htm"; + for (int i = 1; i <= 32; ++i) + { + // 创意主题 + //类似 url: url: http://www.51ztzj.com/dbizhi/category_27_1.htm#content_anchor + std::string url = "http://www.51ztzj.com/dbizhi/category_27_" + std::to_string(i) + ".htm#content_anchor"; + std::cout << "Start get " << i << " page, url: " << url << std::endl; + // 请求并解析url + if (!get_result(url, pattern, sub_url_vec)) + { + std::cout << "Get " << i << " page failed" << std::endl; + } + } + + // 最终的图片url:http://img.51ztzj.com//upload/image/20130220/2013022014_670x419.jpg + // [2] 将子页面的图片url解析出来放入picture_url_vec + std::vector picture_url_vec; + pattern = "http://img.51ztzj.com//upload/image/.+/.+_670x419.jpg"; + for (std::size_t i = 0; i < sub_url_vec.size(); ++i) + { + std::string url = "http://www.51ztzj.com" + sub_url_vec[i]; + std::cout << "Start get " << i + 1 << " sub page, url: " << url << std::endl; + // 请求并解析url + if (!get_result(url, pattern, picture_url_vec)) + { + std::cout << "Get " << i + 1 << " sub page failed" << std::endl; + } + } + + // [3] 最后遍历picture_url_vec,然后一个一个的下载图片 + for (std::size_t i = 0; i < picture_url_vec.size(); ++i) + { + std::cout << "Start download " << i + 1 << " picture, url: " << picture_url_vec[i] << std::endl; + std::string picture; + // 获取图片 + if (!get_result(picture_url_vec[i], picture)) + { + std::cout << "Download " << i + 1 << " picture failed" << std::endl; + } + + std::string file_path = "./download/" + std::to_string(i) + ".jpg"; + // 保存图片 + if (!write_to_file(file_path, picture)) + { + std::cout << "Write to file failed: " << i + 1 << std::endl; + } + } + + return 0; +} \ No newline at end of file diff --git a/HTTP_CLIENT_GET_PICTURE/HTTP_CLIENT_GET_PICTURE.vcxproj b/HTTP_CLIENT_GET_PICTURE/HTTP_CLIENT_GET_PICTURE.vcxproj new file mode 100644 index 0000000000..8fd708d1c4 --- /dev/null +++ b/HTTP_CLIENT_GET_PICTURE/HTTP_CLIENT_GET_PICTURE.vcxproj @@ -0,0 +1,163 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {5A72CAB6-2338-4984-9FE5-AED77A2824F8} + Win32Proj + HTTPCLIENTGETPICTURE + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + false + $(SolutionDir)$(Configuration)\Binaries\Release + + + true + + + true + + + false + + + + + + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + ../Release/include;%(AdditionalIncludeDirectories) + + + Console + true + true + true + ../WIN32/Release/Binaries/Release + ..\WIN32\Release\Binaries\Release\cpprest140_2_10.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + + + Level3 + Disabled + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + + + Level3 + MaxSpeed + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/HTTP_CLIENT_GET_PICTURE/HTTP_CLIENT_GET_PICTURE.vcxproj.filters b/HTTP_CLIENT_GET_PICTURE/HTTP_CLIENT_GET_PICTURE.vcxproj.filters new file mode 100644 index 0000000000..9a49aea79f --- /dev/null +++ b/HTTP_CLIENT_GET_PICTURE/HTTP_CLIENT_GET_PICTURE.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 源文件 + + + \ No newline at end of file diff --git a/HTTP_SIMPLE_CLIENT/HTTP_FULL_CLIENT.cpp b/HTTP_SIMPLE_CLIENT/HTTP_FULL_CLIENT.cpp new file mode 100644 index 0000000000..447779acbe --- /dev/null +++ b/HTTP_SIMPLE_CLIENT/HTTP_FULL_CLIENT.cpp @@ -0,0 +1,87 @@ + +//https://mariusbancila.ro/blog/2017/11/19/revisited-full-fledged-client-server-example-with-c-rest-sdk-2-10/ +#include "def.h" +/* +Notice there are slight changes in the way output is formatted, both in the server and the client application. The rest +is mostly unchanged, except for the handling of JSON, that has changed significatly since version 1.1. Again, please see +the original post for an explanation of the code. + +The output from running these client and server applications is shown below. On the left is the client output, and on +the right the server output. +*/ +void display_json(json::value const& jvalue, utility::string_t const& prefix) +{ + std::wcout << prefix << jvalue.serialize() << std::endl; +} + +pplx::task make_task_request(http_client& client, method mtd, json::value const& jvalue) +{ + return (mtd == methods::GET || mtd == methods::HEAD) ? client.request(mtd, L"/restdemo") + : client.request(mtd, L"/restdemo", jvalue); +} + +void make_request(http_client& client, method mtd, json::value const& jvalue) +{ + make_task_request(client, mtd, jvalue) + .then([](http_response response) { + if (response.status_code() == status_codes::OK) + { + return response.extract_json(); + } + return pplx::task_from_result(json::value()); + }) + .then([](pplx::task previousTask) { + try + { + display_json(previousTask.get(), L"R: "); + } + catch (http_exception const& e) + { + std::wcout << e.what() << std::endl; + } + }) + .wait(); +} + + +int full_client_main() +{ + http_client client(U("http://localhost:8888")); + + auto putvalue = json::value::object(); + putvalue[L"one"] = json::value::string(L"100"); + putvalue[L"two"] = json::value::string(L"200"); + + std::wcout << L"\nPUT (add values)\n"; + display_json(putvalue, L"S: "); + make_request(client, methods::PUT, putvalue); + + // + auto getvalue = json::value::array(); + getvalue[0] = json::value::string(L"one"); + getvalue[1] = json::value::string(L"two"); + getvalue[2] = json::value::string(L"three"); + + std::wcout << L"\nPOST (get some values)\n"; + display_json(getvalue, L"S: "); + make_request(client, methods::POST, getvalue); + + auto delvalue = json::value::array(); + delvalue[0] = json::value::string(L"one"); + + std::wcout << L"\nDELETE (delete values)\n"; + display_json(delvalue, L"S: "); + make_request(client, methods::DEL, delvalue); + + std::wcout << L"\nPOST (get some values)\n"; + display_json(getvalue, L"S: "); + make_request(client, methods::POST, getvalue); + + auto nullvalue = json::value::null(); + + std::wcout << L"\nGET (get all values)\n"; + display_json(nullvalue, L"S: "); + make_request(client, methods::GET, nullvalue); + + return 0; +} \ No newline at end of file diff --git a/HTTP_SIMPLE_CLIENT/HTTP_SIMPLE_CLIENT.cpp b/HTTP_SIMPLE_CLIENT/HTTP_SIMPLE_CLIENT.cpp new file mode 100644 index 0000000000..ef7ab3e07e --- /dev/null +++ b/HTTP_SIMPLE_CLIENT/HTTP_SIMPLE_CLIENT.cpp @@ -0,0 +1,60 @@ +// HTTP_SIMPLE_CLIENT.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 +// +#include "def.h" +//#include +// +//int main() +//{ +// std::cout << "Hello World!\n"; +//} + +// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单 +// 调试程序: F5 或调试 >“开始调试”菜单 + +// 入门使用技巧: +// 1. 使用解决方案资源管理器窗口添加/管理文件 +// 2. 使用团队资源管理器窗口连接到源代码管理 +// 3. 使用输出窗口查看生成输出和其他消息 +// 4. 使用错误列表窗口查看错误 +// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目 +// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件 +//https://segmentfault.com/q/1010000002869889 + + +//#if USE_SIMPLE_CLIENT +//int main(int argc, char* argv[]) +//#else +int main_simple(int argc, char* argv[]) +//#endif +{ + auto fileStream = std::make_shared(); + // Open stream to output file. + pplx::task requestTask = fstream::open_ostream(U("results.html")) + .then([=](ostream outFile) { + *fileStream = outFile; + // Create http_client to send the request. + http_client client(U("http://www.bing.com/")); + http_client localclient(U("http://localhost:8888")); + printf("create client and send request \n"); + return localclient.request(methods::GET); + }) + .then([=](http_response response) { + printf("Received response status code:%u\n", response.status_code()); + system("pause"); + return response.body().read_to_end(fileStream->streambuf()); + }) + .then([=](size_t) { + printf("close file stream \n"); + return fileStream->close(); }); + try + { + requestTask.wait(); + } + catch (const std::exception& e) + { + printf("Error exception:%s\n", e.what()); + system("pause"); + } + + return 0; +} diff --git a/HTTP_SIMPLE_CLIENT/HTTP_SIMPLE_CLIENT.vcxproj b/HTTP_SIMPLE_CLIENT/HTTP_SIMPLE_CLIENT.vcxproj new file mode 100644 index 0000000000..58e365c45c --- /dev/null +++ b/HTTP_SIMPLE_CLIENT/HTTP_SIMPLE_CLIENT.vcxproj @@ -0,0 +1,179 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {05071389-F9F3-4C44-B155-A15E43CA3FFD} + Win32Proj + HTTPSIMPLECLIENT + 10.0.10586.0 + + + + Application + true + v142 + Unicode + + + Application + false + v140 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + false + $(SolutionDir)$(Configuration)\Binaries\Release + + + true + + + true + + + false + + + + + + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + D:\TEACHER\100educationteacher\depends\dw3rd\openssl-1.1.0f-vs2015\include;D:\TEACHER\100educationteacher\depends\dw3rd\openssl2015-1.0.0d_vs2015\include0000;D:\TEACHER\100educationteacher\depends\dw3rd\boost2015-1.66.0.140\include;../simple_web;../Release/include + + + Console + true + true + true + D:\TEACHER\100educationteacher\depends\dw3rd\openssl-1.1.0f-vs2015\lib;D:\TEACHER\100educationteacher\depends\dw3rd\openssl2015-1.0.0d_vs2015\lib\release\000;D:\TEACHER\100educationteacher\depends\dw3rd\boost2015-1.66.0.140\lib\release;../WIN32/Release/Binaries/Release + ..\WIN32\Release\Binaries\Release\cpprest140_2_10.lib;libcryptoMT.lib;libsslMT.lib;crypt32.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + + + Level3 + Disabled + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + + + Level3 + MaxSpeed + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/HTTP_SIMPLE_CLIENT/HTTP_SIMPLE_CLIENT.vcxproj.filters b/HTTP_SIMPLE_CLIENT/HTTP_SIMPLE_CLIENT.vcxproj.filters new file mode 100644 index 0000000000..a88235d7b1 --- /dev/null +++ b/HTTP_SIMPLE_CLIENT/HTTP_SIMPLE_CLIENT.vcxproj.filters @@ -0,0 +1,66 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + \ No newline at end of file diff --git a/HTTP_SIMPLE_CLIENT/def.h b/HTTP_SIMPLE_CLIENT/def.h new file mode 100644 index 0000000000..52831895d1 --- /dev/null +++ b/HTTP_SIMPLE_CLIENT/def.h @@ -0,0 +1,28 @@ +#pragma once + +#include "cpprest/filestream.h" +#include "cpprest/http_client.h" + +using namespace utility; // Common utilities like string conversions +using namespace web; // Common features like URIs. +using namespace web::http; // Common HTTP functionality +using namespace web::http::client; // HTTP client features +using namespace concurrency::streams; // Asynchronous streams + + +#include +#include +//#pragma comment(lib, "cpprest_2_10") +// +//using namespace web; +//using namespace web::http; +//using namespace web::http::client; +// +//#include +//using namespace std; + + + +int main_simple(int argc, char* argv[]); +int full_client_main(); +int simple_https_client(); \ No newline at end of file diff --git a/HTTP_SIMPLE_CLIENT/main.cpp b/HTTP_SIMPLE_CLIENT/main.cpp new file mode 100644 index 0000000000..b2606d058d --- /dev/null +++ b/HTTP_SIMPLE_CLIENT/main.cpp @@ -0,0 +1,11 @@ + + +#include "def.h" + +int main(int argc ,char * argv[]) +{ + //full_client_main(); + simple_https_client(); + return 0; + +} \ No newline at end of file diff --git a/HTTP_SIMPLE_CLIENT/results.html b/HTTP_SIMPLE_CLIENT/results.html new file mode 100644 index 0000000000..b45ef6fec8 --- /dev/null +++ b/HTTP_SIMPLE_CLIENT/results.html @@ -0,0 +1 @@ +Hello, World! \ No newline at end of file diff --git a/HTTP_SIMPLE_CLIENT/simple_https_client.cpp b/HTTP_SIMPLE_CLIENT/simple_https_client.cpp new file mode 100644 index 0000000000..e19468a73a --- /dev/null +++ b/HTTP_SIMPLE_CLIENT/simple_https_client.cpp @@ -0,0 +1,24 @@ +#include "client_https.hpp" +#include + +using namespace std; + +typedef SimpleWeb::Client HttpsClient; + +int simple_https_client() +{ + try + { + HttpsClient client("github.com",false); + + + auto r1 = client.request("GET", "/"); + cout << r1->content.rdbuf() << endl; + } + catch //(std::exception* e) + (boost::system::system_error &e) + { + cout << e.what() << endl; + } + return 0; +} \ No newline at end of file diff --git a/HTTP_SIMPLE_SERVER/HTTP_FULL_SERVER.cpp b/HTTP_SIMPLE_SERVER/HTTP_FULL_SERVER.cpp new file mode 100644 index 0000000000..c2ffd67962 --- /dev/null +++ b/HTTP_SIMPLE_SERVER/HTTP_FULL_SERVER.cpp @@ -0,0 +1,384 @@ + +#include "http_svr.h" +// https://mariusbancila.ro/blog/2013/08/19/full-fledged-client-server-example-with-cpprest-sdk-110/ +// https://mariusbancila.ro/blog/2017/11/19/revisited-full-fledged-client-server-example-with-c-rest-sdk-2-10/ +namespace full_svr + + +{ +#if 0 +void display_json(json::value const& jvalue, utility::string_t const& prefix) +{ + std::wcout << prefix << jvalue.serialize() << std::endl; +} + + + /* + n this simple implementation the dictionary is a std::map. + Its content is not persisted to disk, it is reloaded each time the server starts. + */ +std::map dictionary; +//http://cn.voidcc.com/question/p-uoiiighz-boe.html +typedef std::vector> field_map; + +/* +Lets now look at the handlers. As mentioned earlier the GET method is a bit different than the others. A GET request +should return all the key-value pairs in the servers dictionary. Its implementation looks like this: + +handlers implementation */ +void handle_get(http_request request) +{ + TRACE(L"\nhandle GET\n"); + + + //Dzǿûе + // json::value::field_map answer; + field_map answer; + for (auto const& p : dictionary) + { + // answer.push_back(std::make_pair(json::value(p.first), json::value(p.second))); + answer.push_back(std::make_pair(p.first, json::value(p.second))); + } + //http://cn.voidcc.com/question/p-uoiiighz-boe.html + request.reply(status_codes::OK, json::value::object(answer)); +} + + +void handle_request(http_request request, std::function action) +{ + field_map answer; + + request.extract_json() + .then([&answer, &action](pplx::task task) { + try + { + //б + auto& const jvalue = task.get(); + + if (!jvalue.is_null()) + { + action(jvalue, answer); + } + } + catch (http_exception const& e) + { + std::wcout << e.what() << std::endl; + } + }) + .wait(); + + request.reply(status_codes::OK, json::value::object(answer)); +} +void handle_post(http_request request) +{ + TRACE("\nhandle POST\n"); + + handle_request(request, [](json::value& jvalue, field_map& answer) { + // + for (auto const& e : jvalue.as_array()) + { + //еÿһ + if (e.is_string()) + { + auto key = e.as_string(); + //ڷ˵ֵkeyanswer + auto pos = dictionary.find(key); + if (pos == dictionary.end()) + { + answer.push_back(make_pair(key, json::value(L""))); + } + else + { + answer.push_back(make_pair(pos->first, json::value(pos->second))); + } + } + } + }); +} +void handle_put(http_request request) +{ + TRACE("\nhandle PUT\n"); + + handle_request(request, [](json::value& jvalue, field_map& answer) { + for (auto const& e : jvalue.as_object()) + { + if (e.second.is_string()) + { + auto key = e.first; + auto value = e.second.as_string(); + + if (dictionary.find(key) == dictionary.end()) + { + TRACE_ACTION(L"added", key, value); + answer.push_back(make_pair(key, json::value(L""))); + } + else + { + TRACE_ACTION(L"updated", key, value); + answer.push_back(make_pair(key, json::value(L""))); + } + + dictionary[key] = value; + } + } + }); +} + +void handle_del(http_request request) +{ + TRACE("\nhandle DEL\n"); + + //handle_requestlambdaʽ std::function action + handle_request(request, [](json::value& jvalue, field_map& answer) { + std::set keys; + for (auto const& e : jvalue.as_array()) + { + if (e.is_string()) + { + auto key = e.as_string(); + + auto pos = dictionary.find(key); + if (pos == dictionary.end()) + { + answer.push_back(make_pair(key, json::value(L""))); + } + else + { + TRACE_ACTION(L"deleted", pos->first, pos->second); + answer.push_back(make_pair(key, json::value(L""))); + keys.insert(key); + } + } + } + + for (auto const& key : keys) + dictionary.erase(key); + }); +} +int svr_main(int argc, char** argv) +{ + http_listener listener(L"http://localhost/restdemo"); + + listener.support(methods::GET, handle_get); + listener.support(methods::POST, handle_post); + listener.support(methods::PUT, handle_put); + listener.support(methods::DEL, handle_del); + + try + { + listener.open().then([&listener]() { TRACE(L"\nstarting to listen\n"); }).wait(); + + while (true) + ; + } + catch (std::exception const& e) + { + std::wcout << e.what() << std::endl; + } + + return 0; +} +#else /// https://mariusbancila.ro/blog/2017/11/19/revisited-full-fledged-client-server-example-with-c-rest-sdk-2-10/ + +/* +I will not reiterate all the details described in the former article. However, in summary, the server maintains a +dictionary of values (both keys and values are strings). Through HTTP calls a client can retrieve the content of the +dictionary, add new values, update or delete existing ones. + +ͻҪǶԷ˵dictionaryȡ/޸ +*/ +std::map dictionary; + +void display_json(json::value const& jvalue, utility::string_t const& prefix) +{ + std::wcout << prefix << jvalue.serialize() << std::endl; +} + +void handle_get(http_request request) +{ + TRACE(L"\nhandle GET\n"); + + auto answer = json::value::object(); + + for (auto const& p : dictionary) + { + answer[p.first] = json::value::string(p.second); + } + + display_json(json::value::null(), L"R: "); + display_json(answer, L"S: "); + + request.reply(status_codes::OK, answer); +} + +void handle_request(http_request request, std::function action) +{ + auto answer = web::json::value::object(); + + request.extract_json() + .then([&answer, &action](pplx::task task) { + try + { + auto const& jvalue = task.get(); + display_json(jvalue, L"R: "); + + if (!jvalue.is_null()) + { + action(jvalue, answer); + } + else + { + std::wcout << "jvalue.is_null() !!!!err!!!!" << std::endl; + } + } + catch (http_exception const& e) + { + std::wcout << e.what() << std::endl; + } + }) + .wait(); + + + display_json(answer, L"S: "); + + request.reply(status_codes::OK, answer); +} + +void handle_post(http_request request) +{ + TRACE("\nhandle POST\n"); + + handle_request(request, [](json::value const& jvalue, json::value& answer) { + for (auto const& e : jvalue.as_array()) + { + if (e.is_string()) + { + auto key = e.as_string(); + auto pos = dictionary.find(key); + + if (pos == dictionary.end()) + { + answer[key] = json::value::string(L""); + } + else + { + answer[pos->first] = json::value::string(pos->second); + } + } + } + }); +} + +void handle_put(http_request request) +{ + TRACE("\nhandle PUT\n"); + + handle_request(request, [](json::value const& jvalue, json::value& answer) { + for (auto const& e : jvalue.as_object()) + { + if (e.second.is_string()) + { + auto key = e.first; + auto value = e.second.as_string(); + + if (dictionary.find(key) == dictionary.end()) + { + TRACE_ACTION(L"added", key, value); + answer[key] = json::value::string(L""); + } + else + { + TRACE_ACTION(L"updated", key, value); + answer[key] = json::value::string(L""); + } + + dictionary[key] = value; + } + } + }); +} + +void handle_del(http_request request) +{ + TRACE("\nhandle DEL\n"); + + handle_request(request, [](json::value const& jvalue, json::value& answer) { + std::set keys; + for (auto const& e : jvalue.as_array()) + { + if (e.is_string()) + { + auto key = e.as_string(); + + auto pos = dictionary.find(key); + if (pos == dictionary.end()) + { + answer[key] = json::value::string(L""); + } + else + { + TRACE_ACTION(L"deleted", pos->first, pos->second); + answer[key] = json::value::string(L""); + keys.insert(key); + } + } + } + + for (auto const& key : keys) + dictionary.erase(key); + }); +} +} + +/* +starting to listen + +handle PUT +R: {"one":"100","two":"200"} +added (one, 100) +added (two, 200) +S: {"one":"","two":""} + +handle POST +R: ["one","two","three"] +S: {"one":"100","three":"","two":"200"} + +handle DEL +R: ["one"] +deleted (one, 100) +S: {"one":""} + +handle POST +R: ["one","two","three"] +S: {"one":"","three":"","two":"200"} + +handle GET +R: null +S: {"two":"200"} + +*/ +int full_svr_main(int argc, char** argv) +{ + http_listener listener(L"http://localhost:8888/restdemo"); + + listener.support(methods::GET, full_svr::handle_get); + listener.support(methods::POST, full_svr::handle_post); + listener.support(methods::PUT, full_svr::handle_put); + listener.support(methods::DEL, full_svr::handle_del); + + try + { + listener.open().then([&listener]() { TRACE(L"\nstarting to listen\n"); }).wait(); + + while (true) + ; + } + catch (std::exception const& e) + { + std::wcout << e.what() << std::endl; + } + + return 0; +} + +#endif diff --git a/HTTP_SIMPLE_SERVER/HTTP_SIMPLE_SERVER.cpp b/HTTP_SIMPLE_SERVER/HTTP_SIMPLE_SERVER.cpp new file mode 100644 index 0000000000..3422042eba --- /dev/null +++ b/HTTP_SIMPLE_SERVER/HTTP_SIMPLE_SERVER.cpp @@ -0,0 +1,65 @@ +// HTTP_SIMPLE_SERVER.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 +// + +#include "http_svr.h" +//#include +// +// int main() +//{ +// std::cout << "Hello World!\n"; +//} + +// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单 +// 调试程序: F5 或调试 >“开始调试”菜单 + +// 入门使用技巧: +// 1. 使用解决方案资源管理器窗口添加/管理文件 +// 2. 使用团队资源管理器窗口连接到源代码管理 +// 3. 使用输出窗口查看生成输出和其他消息 +// 4. 使用错误列表窗口查看错误 +// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目 +// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件 +// https : // segmentfault.com/q/1010000002869889 + +namespace simple_svr +{ + + +void sshandle_get(http_request message) { message.reply(status_codes::OK, U("Hello, World!")); }; + +void sshandle_post(http_request message) { message.reply(status_codes::NotFound); }; + +void sshandle_put(http_request message) { message.reply(status_codes::NotFound); }; + +void sshandle_delete(http_request message) { message.reply(status_codes::NotFound); }; +} // namespace simple_svr + +int main_simple_server(int argc, char** argv) +{ + uri_builder uri(U("http://localhost:8888")); + http_listener listener(uri.to_uri()); + + listener.support(methods::GET, simple_svr::sshandle_get); + listener.support(methods::POST, simple_svr::sshandle_post); + listener.support(methods::PUT, simple_svr::sshandle_put); + listener.support(methods::DEL, simple_svr::sshandle_delete); + + try + { + listener.open().then([&listener]() { TRACE(L"\nstarting to listen\n"); }).wait(); + + while (true) + ; + } + catch (std::exception const& e) + { + std::wcout << e.what() << std::endl; + } + catch (...) + { + std::wcout << "Unknown exception" << std::endl; + } + + return 0; +} + diff --git a/HTTP_SIMPLE_SERVER/HTTP_SIMPLE_SERVER.vcxproj b/HTTP_SIMPLE_SERVER/HTTP_SIMPLE_SERVER.vcxproj new file mode 100644 index 0000000000..9a8f3a8c27 --- /dev/null +++ b/HTTP_SIMPLE_SERVER/HTTP_SIMPLE_SERVER.vcxproj @@ -0,0 +1,168 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {BB0FB695-74B7-473B-B034-68F9FF0F3ED0} + Win32Proj + HTTPSIMPLESERVER + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + false + $(SolutionDir)$(Configuration)\Binaries\Release + + + true + + + true + + + false + + + + + + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + ../Release/include + + + Console + true + true + true + ../WIN32/Release/Binaries/Release + ..\WIN32\Release\Binaries\Release\cpprest140_2_10.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + + + Level3 + Disabled + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + + + Level3 + MaxSpeed + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + + + + + \ No newline at end of file diff --git a/HTTP_SIMPLE_SERVER/HTTP_SIMPLE_SERVER.vcxproj.filters b/HTTP_SIMPLE_SERVER/HTTP_SIMPLE_SERVER.vcxproj.filters new file mode 100644 index 0000000000..4fc8977625 --- /dev/null +++ b/HTTP_SIMPLE_SERVER/HTTP_SIMPLE_SERVER.vcxproj.filters @@ -0,0 +1,33 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 源文件 + + + 源文件 + + + 源文件 + + + + + 头文件 + + + \ No newline at end of file diff --git a/HTTP_SIMPLE_SERVER/http_svr.h b/HTTP_SIMPLE_SERVER/http_svr.h new file mode 100644 index 0000000000..e5ddd9538a --- /dev/null +++ b/HTTP_SIMPLE_SERVER/http_svr.h @@ -0,0 +1,51 @@ +#pragma once + + +#if 0 +#include "cpprest/asyncrt_utils.h" +#include "cpprest/http_client.h" +#include "cpprest/http_listener.h" +#include "cpprest/json.h" +#include "cpprest/uri.h" +using namespace web::http::experimental::listener; +using namespace web::http; +using namespace web; + + + +#define TRACE(msg) std::wcout << msg +#define TRACE_ACTION(a, k, v) std::wcout << a << L" (" << k << L", " << v << L")\n" + + +#endif + + +#include +#include + // cpprest140_2_10.lib + //#pragma comment(lib, "cpprest140_2_10") + +using namespace web; +using namespace web::http; +/* https://ruby-china.org/topics/16982 +ȥ꣬΢Դ˴Ϊ Casablanca C++ REST SDKĿҪΪC++ ʱӷ RESTful +񡣵һܣNew experimental features such as HTTP Listener +libraryܵij֣ΪΪһȽϾDZĿ򵥵˵ +CasablancaԴһԭƼ֮˫ɵİЩCC++Delphi VB +дĵת Web õʱ㴴Ƽʱ +*/ +using namespace web::http::experimental::listener; + +#include +#include +#include +#include +//using namespace std; + + +#define TRACE(msg) std::wcout << msg +#define TRACE_ACTION(a, k, v) std::wcout << a << L" (" << k << L", " << v << L")\n" + + +int main_simple_server(int argc, char** argv); +int full_svr_main(int argc, char** argv); \ No newline at end of file diff --git a/HTTP_SIMPLE_SERVER/main.cpp b/HTTP_SIMPLE_SERVER/main.cpp new file mode 100644 index 0000000000..39a58fd0d5 --- /dev/null +++ b/HTTP_SIMPLE_SERVER/main.cpp @@ -0,0 +1,10 @@ +//#include "HTTP_SIMPLE_SERVER.cpp" +//#include "HTTP_FULL_SERVER.cpp" +#include "http_svr.h" + +int main(int argc, char** argv) +{ + + full_svr_main(argc, argv); + return 0; +} \ No newline at end of file diff --git a/JSON/JSON/File.h b/JSON/JSON/File.h new file mode 100644 index 0000000000..94433368f2 --- /dev/null +++ b/JSON/JSON/File.h @@ -0,0 +1,61 @@ +#pragma once +#include +#include "Path.h" +#include + +class File +{ +public: + File() = default; + File(const Path& path) : FilePath(path) {} + + const std::string& Read() + { + if (!Data.empty()) + { + return Data; + } + std::fstream FileStream; + + FileStream.open(FilePath.FullPath.c_str(), std::ios::in); + + if (!FileStream) + { + //Logger::Log(Logger::LogType::Error, "File IO: Failed to load file " + FilePath.LocalPath); + std::cout << " File IO: Failed to load file "<(FileStream)), (std::istreambuf_iterator())); + + FileStream.close(); + IsOpen = false; + + return Data; + } + + void Write() + { + std::ofstream out(FilePath.FullPath); + out << Data; + out.close(); + } + + void Write(const std::string& Contents) + { + Data = Contents; + Write(); + } + + void Reset() { Data.clear(); } + + std::string Data; + Path FilePath; + +private: + bool IsOpen = false; +}; \ No newline at end of file diff --git a/JSON/JSON/JSON.cpp b/JSON/JSON/JSON.cpp new file mode 100644 index 0000000000..74cbd25fcc --- /dev/null +++ b/JSON/JSON/JSON.cpp @@ -0,0 +1,554 @@ +// JSON.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 +// +#include "File.h" +#include +#include +#include +#include + +// for convenience +using json = nlohmann::json; + +#include + +//创建json对象 +/* +{ + "pi": 3.141, + "happy": true, + "name": "Niels", + "nothing": null, + "answer": { + "everything": 42 + }, + "list": [1, 0, 2], + "object": { + "currency": "USD", + "value": 42.99 + } +} +*/ +void createJson() +{ + /* + { + "answer": { + "everyting": 42 + }, + "happy": true, + "list": [ + 1, + 0, + 2 + ], + "name": "Niels", + "nothing": null, + "object": { + "currency": "USD", + "value": 42.99 + }, + "pi": 3.141 + } + */ + // empty structure null + json j; + // add a number that is stored as double (note the implicit conversion of j to an object) + j["pi"] = 3.141; + // add a boolean that is stored as bool + j["happy"] = true; + + // add a string that is stored as std::string + j["name"] = "Niels"; + + // add another null object by passing nullptr + j["nothing"] = nullptr; + + // add another null object by passing nullptr + j["nothing"] = nullptr; + + // add an object inside the object + j["answer"]["everyting"] = 42; + + // add an array that is stored as std::vector (using an initializer list) + j["list"] = {1, 0, 2}; + + // add another object ,using an initializer list of pairs + j["object"] = {{"currency", "USD"}, {"value", 42.99}}; + + /////////////////////////j2和j3都跟j不一样吧TODO + // https://blog.csdn.net/forrid/article/details/78867679 + // instead ,you could also write (which looks very similar to the json above) + json j2 = {{"pi", 3.143}, + {"happy", true}, + {"NAME", "CHLL"}, + {"NOTHING", nullptr}, + {"ANSWER", {"EVERYTHINS"}, 42}, + {"list", {1, 0, 2}}, + {"object", {{"currency", "USD"}, {"value", 42.99}}}}; + std::cout << std::setw(4) << j << std::endl; + std::cout << "=============================" << std::endl; + + std::cout << std::setw(4) << j2 << std::endl; + json j3 = {"pi", + 3.143, + "happy", + true, + "NAME", + "CHLL", + "NOTHING", + nullptr, + {"ANSWER", {"EVERYTHINS"}, 42}, + "list", + {1, 0, 2}, + "object", + {"currency", "USD", "value", 42.99}}; + std::cout << "=============================" << std::endl; + std::cout << std::setw(4) << j3 << std::endl; + + ////////////序列化 + // 从字符串字面量创建对象 + /* +j4 { +"happy": true, +"pi": 3.141 +} + */ + json j4 = "{\"happy\": true, \"pi\": 3.141}"_json; + // 最好是使用原始字符串字面量 + /* +j5{ +"happy": true, +"pi": 3.141 +} + */ + auto j5 = R"({"happy": true, "pi": 3.141})"_json; + // 显式地分析 + auto j6 = json::parse("{\"happy\": true, \"pi\": 3.141}"); + std::cout << "j4 " << std::setw(4) << j4 << std::endl; + std::cout << "j5" << std::setw(4) << j5 << std::endl; + std::cout << "j6" << std::setw(4) << j6 << std::endl; + + // 显式地转换至字符串 + std::string s = j6.dump(); + // 传入缩进空格数,使用良好的打印形式进行序列化 + std::cout << j6.dump(4) << std::endl; +} +/*https://www.json.cn/ +{ + "project": "client-logs", + "region": "henzhen", + "logStore": "com-web", + "source": "127.0.0.1", + "encode" : 2, + "content":[{ + "key1" : "%E5%86%85%E5%AE%B91", + "key2" : "%E5%86%AE%B91", + + + + + + + + + + + + + "key3" : "内容3" + },{ + "key1" : "内容1", + "key2" : "内容2", + "key3" : "%E5%86%85%E5%AE%B93" + }] +} + +*/ +void create100() +{ + std::cout << "=============================" << std::endl; + // json j = json::parse("{ \ "project \" : \ "client-logs \",\ "region \" : \"henzhen \",\"logStore \" : + // \"com-web \",\"source \" : \"127.0.0.1 \",\ "encode" : 2,}"); + // auto j5 = R"({"happy": true, "pi": 3.141})"_json; + json raw = R"({ + "project": "client-logs", + "region": "shenzhen", + "logStore": "com-web", + "source": "127.0.0.1", + "encode" : 2, + "content":[0,1,2] +})"_json; + // std::cout <<"comj:"<< std::setw(4) << j << std::endl; + std::cout << std::setw(4) << raw << std::endl; +} +void createarray() +{ + std::cout << "=============================" << std::endl; + //创建一个空数组 + json empty_array_explicit = json::array(); + // 创建一个空对象的两种方式 + json empty_object_implicit = json({}); + json empty_object_explicit = json::object(); + + // array是一个数组,可以用数字直接下标访问。 + json array = {"a", 6, "xin", 8}; + std::cout << "array[0]" << std::setw(4) << array[0] << std::endl; + + /* + // add an object inside the object +j["answer"]["everyting"] = 42; + +// add an array that is stored as std::vector (using an initializer list) +j["list"] = {1, 0, 2}; + +// add another object ,using an initializer list of pairs +j["object"] = {{"currency", "USD"}, {"value", 42.99}}; + */ + json j; + // add a number that is stored as double (note the implicit conversion of j to an object) + //会覆盖啊 TODO + /* +"content": { +"5": "5", +"6": 42.99, +"7": "8" +}, + */ + j["content"] = {{"currency", "USD"}, {"value", 42.99}, {"nihao", "home"}}; + j["content"] = {{"1", "2"}, {"3", 42.99}, {"4", "5"}}; + j["content"] = {{"5", "5"}, {"6", 42.99}, {"7", "8"}}; + j["module"] = "china"; + std::cout << std::setw(4) << j << std::endl; + + std::cout << "=============================" << std::endl; + //怎么变为了这个样子: "1content": " [ \"one\", \"two\", \"three\" ]", ??????TODO + j["1_content"] = R"( [ "one", "two", "three" ])"; + /* + "2_content": "[\n { \"op\": \"replace\", \"path\": \"/baz\", \"value\": \"boo\" },\n { \"op\": \"add\", + \"path\": \"/hello\", \"value\": [\"world\"] },\n { \"op\": \"remove\", \"path\": \"/foo\"} \n]", + */ + j["2_content"] = R"([ + { "op": "replace", "path": "/baz", "value": "boo" }, + { "op": "add", "path": "/hello", "value": ["world"] }, + { "op": "remove", "path": "/foo"} +])"; + /* + 3 是这样的,看起来这个就符合要求 +"3_content": [ +{ +"op": "replace", +"path": "/baz", +"value": "boo" +}, +{ +"op": "add", +"path": "/hello", +"value": [ +"world" +] +}, +{ +"op": "remove", +"path": "/foo" +} +], + */ + //这个也符号要求,j["2_content"] 的方法可以直接转为json的字符串 + j["3_content"] = json::parse( + "[ { \"op\": \"replace\", \"path\": \"/baz\", \"value\": \"boo\" },\n { \"op\": \"add\", \"path\": " + "\"/hello\", \"value\": [\"world\"] },\n { \"op\": \"remove\", \"path\": \"/foo\"} ]"); + /* + GOOD! + 厉害了,这个符合要求 +"4_content": [ +{ +"currency": "USD", +"nihao": "home", +"value": 42.99 +}, +{ +"5": "5", +"6": 42.99, +"7": "8" +}, +{ +"5": "5", +"6": 42.99, +"7": "8" +} +], + */ + json m1 = {{"currency", "USD"}, {"value", 42.99}, {"nihao", "home"}}; + json m2 = {{"1", "2"}, {"3", 42.99}, {"4", "5"}}; + json m3 = {{"5", "5"}, {"6", 42.99}, {"7", "8"}}; + //这样符合要求 + j["4_content"] = {m1, m3, m3}; + std::cout << std::setw(4) << j << std::endl; +} +void creatPatch() +{ + // a JSON value + json j_original = R"({ + "baz": ["one", "two", "three"], + "foo": "bar" +})"_json; + + // https://www.jianshu.com/p/69e57f2af904 + // a JSON patch (RFC 6902) + json j_patch = R"([ + { "op": "replace", "path": "/baz", "value": "boo" }, + { "op": "add", "path": "/hello", "value": ["world"] }, + { "op": "remove", "path": "/foo"} +])"_json; +} +class Component +{ +public: + Component(std::string type) { name = type; } + /* + { + "TIME": "china_2", + "Type": "1_china" +}, + */ + void Serialize(json& outJson) + { + outJson["Type"] = std::to_string(++id) + "_" + name; + outJson["TIME"] = name + "_" + std::to_string(++id); + } + static int id; + +private: + std::string name; +}; +int Component::id = 0; +/* +d + +[ +{ + "Components": [ + { + "Type": "1_china" + }, + { + "Type": "1_usa" + }, + { + "Type": "1_english" + } + ], + "Name": "zhangbin" +} +] + +*/ +void createVecor(json& d) +{ + json thing; + thing["Name"] = "zhangbin"; + json& componentsJson = thing["Components"]; + + std::vector sss; + sss.push_back(Component("china")); + sss.push_back(Component("usa")); + sss.push_back(Component("english")); + auto comps = sss; + for (auto comp : comps) + { + json compJson; + comp.Serialize(compJson); + /* + 从vector来自动变为数组 +[ +{ +"TIME": "china_2", +"Type": "1_china" +}, +{ +"TIME": "usa_4", +"Type": "3_usa" +}, +{ +"TIME": "english_6", +"Type": "5_english" +} +], + */ + componentsJson.push_back(compJson); + } + std::cout << "===========thing==================" << std::endl; + /* +//{ +//"Components": [ +//{ +// "Type": "1_china" +//}, +//{ +// "Type": "2_usa" +//}, +//{ +// "Type": "3_english" +//} +//], +//"Name": "zhangbin" +//} + */ + std::cout << std::setw(4) << thing << std::endl; + d.push_back(thing); + d.push_back(thing); +} +void jsonR_parse(std::string json_string) +{ + // json j_patch = R"([ + // { "op": "replace", "path": "/baz", "value": "boo" }, + // { "op": "add", "path": "/hello", "value": ["world"] }, + // { "op": "remove", "path": "/foo"} + //])"_json; + auto jj = json::parse(json_string); + std::cout << std::setw(4) << jj << std::endl; +} +Path FilePath; +void save(std::string fileName, json& world) +{ + // void Scene::Save(std::string fileName, Transform * root) + { + FilePath = Path(fileName); + + File worldFile(FilePath); + + + worldFile.Write(world.dump(4)); + std::cout << world.dump(4) << std::endl; + } +} + + + +void strdump(std::string str) { std::cout << "#####:" << std::setw(4) << str << std::endl; } +void push(json& m) +{ + json up; + up["project"] = "1111"; + up["region"] = "222222"; + up["logStore"] = "44444"; + // TODO IP 地址获取 + up["source"] = "127.0.0.1"; + up["encode"] = "3333"; + up["content"].push_back(m); + std::cout << std::setw(4) << up << std::endl; + strdump(up.dump()); +} +void ELK(const std::string& jsonstr) +{ + auto j = json::parse(jsonstr); + push(j); +} + + +#include "show_mac.h" +int main() +{ + std::cout << "Hello World!\n"; + createJson(); + create100(); + createarray(); + std::cout << "=============================" << std::endl; + /* +[ +{ +"Components": [ + { + "Type": "1_china" + }, + { + "Type": "1_usa" + }, + { + "Type": "1_english" + } +], +"Name": "zhangbin" +}, +{ +"Components": [ + { + "Type": "1_china" + }, + { + "Type": "1_usa" + }, + { + "Type": "1_english" + } +], +"Name": "zhangbin" +} +] + */ + json ddd; + createVecor(ddd); + std::cout << std::setw(4) << ddd << std::endl; + json d; + d["content"] = ddd; + std::cout << "=============================" << std::endl; + /* +{ +"content": [ +{ + "Components": [ + { + "Type": "1_china" + }, + { + "Type": "1_usa" + }, + { + "Type": "1_english" + } + ], + "Name": "zhangbin" +}, +{ + "Components": [ + { + "Type": "1_china" + }, + { + "Type": "1_usa" + }, + { + "Type": "1_english" + } + ], + "Name": "zhangbin" +} +] +} + */ + std::cout << std::setw(4) << d << std::endl; + // E:\netttttt\http\zhangbincpprestsdk\WIN32\Release下面,跟exe同目录 + save("ssave.txt", d); + + ///// + std::cout << "show mac..............." << std::endl; + // showmac(); + + std::string str = R"({"traceId":"client_test_str", "spanId":"client_test_spanId"})"; + jsonR_parse(str); + json m1 = {{"currency", "USD"}, {"value", 42.99}, {"nihao", "home"}}; + ELK(m1.dump()); + system("pause"); + return 0; +} + +// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单 +// 调试程序: F5 或调试 >“开始调试”菜单 + +// 入门使用技巧: +// 1. 使用解决方案资源管理器窗口添加/管理文件 +// 2. 使用团队资源管理器窗口连接到源代码管理 +// 3. 使用输出窗口查看生成输出和其他消息 +// 4. 使用错误列表窗口查看错误 +// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目 +// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件 diff --git a/JSON/JSON/JSON.vcxproj b/JSON/JSON/JSON.vcxproj new file mode 100644 index 0000000000..0597540da6 --- /dev/null +++ b/JSON/JSON/JSON.vcxproj @@ -0,0 +1,170 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {BE66C1CF-258B-4BD1-9ED5-7BD4235342D1} + Win32Proj + JSON + 10.0.10586.0 + + + + Application + true + v142 + Unicode + + + Application + false + v140 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + false + + + true + + + true + + + false + + + + + + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;_CONSOLE;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions) + true + E:\edu100dev\100protosdkPC\eduprotosdk\depends\dw3rd\boost2015-1.66.0.140\include;../../ + + + Console + true + true + true + E:\edu100dev\100protosdkPC\eduprotosdk\depends\dw3rd\boost2015-1.66.0.140\lib\release + + + + + + + Level3 + Disabled + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + + + Level3 + Disabled + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + + + Level3 + MaxSpeed + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/JSON/JSON/JSON.vcxproj.filters b/JSON/JSON/JSON.vcxproj.filters new file mode 100644 index 0000000000..9dc1b3c7e4 --- /dev/null +++ b/JSON/JSON/JSON.vcxproj.filters @@ -0,0 +1,48 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {f8ca67a3-d831-4417-be8b-f40360fb3f5e} + + + + + 源文件 + + + 源文件 + + + + + nlohmann + + + nlohmann + + + nlohmann + + + 头文件 + + + 头文件 + + + nlohmann + + + \ No newline at end of file diff --git a/JSON/JSON/path.h b/JSON/JSON/path.h new file mode 100644 index 0000000000..08f0e9ec99 --- /dev/null +++ b/JSON/JSON/path.h @@ -0,0 +1,89 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "boost/filesystem.hpp" // includes all needed Boost.Filesystem declarations + + +class Path +{ +public: + Path() = default; + + explicit Path(const std::string& InFile) + { + char buf[1024]; + GetModuleFileNameA(NULL, buf, 1024); + std::string ProgramPath(buf); + + std::replace(ProgramPath.begin(), ProgramPath.end(), '\\', '/'); + size_t pos = ProgramPath.find_last_of("/"); + ProgramPath = ProgramPath.substr(0, pos + 1); + + std::string assetPrefix; +#if ME_EDITOR + assetPrefix = "../../"; +#endif + LocalPath = InFile; + + std::replace(LocalPath.begin(), LocalPath.end(), '\\', '/'); + + size_t path = LocalPath.find(':'); + if (path != std::string::npos) + { + FullPath = LocalPath; + } + else + { + FullPath = ProgramPath + assetPrefix + LocalPath; + } + + path = LocalPath.rfind("Assets"); + if (path != std::string::npos) + { + LocalPath = LocalPath.substr(path, LocalPath.size()); + } + +#if ME_EDITOR + if (!std::filesystem::exists(FullPath)) + { + std::string tempPath = ProgramPath + assetPrefix + "Engine/" + LocalPath; + if (std::filesystem::exists(tempPath)) + { + FullPath = std::move(tempPath); + assetPrefix = assetPrefix.append("Engine/"); + } + } +#endif + // if (std::filesystem::is_regular_file((FullPath))) + if (boost::filesystem::is_regular_file(FullPath)) + { + IsFile = true; + pos = FullPath.find_last_of("/"); + Directory = FullPath.substr(0, pos + 1); + } + else + { + IsFolder = true; + Directory = FullPath; + } + +#if ME_PLATFORM_UWP + std::replace(LocalPath.begin(), LocalPath.end(), '/', '\\'); +#endif + } + + ~Path() {} + bool IsFile = false; + bool IsFolder = false; + std::string FullPath; + std::string LocalPath; + std::string Directory; +}; \ No newline at end of file diff --git a/JSON/JSON/show_mac.h b/JSON/JSON/show_mac.h new file mode 100644 index 0000000000..7e93a0ca3d --- /dev/null +++ b/JSON/JSON/show_mac.h @@ -0,0 +1,3 @@ +#pragma once + +int showmac(); diff --git a/JSON/JSON/win_macaddress.cpp b/JSON/JSON/win_macaddress.cpp new file mode 100644 index 0000000000..62b1dbe914 --- /dev/null +++ b/JSON/JSON/win_macaddress.cpp @@ -0,0 +1,41 @@ + +#include // htons() htonl() and other helper functions +#pragma comment(lib, "WS2_32.lib") +#include // Used to find information about the device such as default gateway and hardware addresses + +#include +#pragma comment(lib, "Iphlpapi.lib") +#include +#include +/*#include */ +/*#include +#include */ +#include +#include +int showmac() +{ + ULONG MAC[2], size = 6; + LPBYTE buffer; + char data[20]; + /* + 1 > win_macaddress.cpp(16) + : error C4996 : 'inet_addr' : Use inet_pton() or + InetPton() instead or + define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings + inet_aton() תַip(192.168.1.10)Ϊֵ + */ + + //in_addr address; + //inet_aton("192.168.1.10", &address); + //if (SendARP(address, 0, MAC, &size) == NO_ERROR) + if (SendARP(inet_addr("192.168.1.10"), 0, MAC, &size) == NO_ERROR) + { + buffer = (LPBYTE)MAC; + + // access the address one byte at a time + sprintf_s( + data, "%02X:%02X:%02X:%02X:%02X:%02X", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); + } + std::cout << data << std::endl; + return 0; +} \ No newline at end of file diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index c689205590..33c2de130e 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -62,8 +62,9 @@ endif() include(cmake/cpprest_find_boost.cmake) include(cmake/cpprest_find_zlib.cmake) include(cmake/cpprest_find_openssl.cmake) -include(cmake/cpprest_find_websocketpp.cmake) -include(cmake/cpprest_find_brotli.cmake) +#win32 暂时不加这个 +#include(cmake/cpprest_find_websocketpp.cmake) +#include(cmake/cpprest_find_brotli.cmake) include(CheckIncludeFiles) include(GNUInstallDirs) diff --git a/Release/cmake/cpprest_find_boost.cmake b/Release/cmake/cpprest_find_boost.cmake index 3c857bafa0..8213a68722 100644 --- a/Release/cmake/cpprest_find_boost.cmake +++ b/Release/cmake/cpprest_find_boost.cmake @@ -47,8 +47,9 @@ function(cpprest_find_boost) cpprestsdk_find_boost_android_package(Boost ${BOOST_VERSION} EXACT REQUIRED COMPONENTS random system thread filesystem chrono atomic) elseif(UNIX) find_package(Boost REQUIRED COMPONENTS random system thread filesystem chrono atomic date_time regex) - else() - find_package(Boost REQUIRED COMPONENTS system date_time regex) + else() ###win32? + ######先屏蔽TODO 怎么也找不到 + #find_package(Boost REQUIRED COMPONENTS system date_time regex) endif() add_library(cpprestsdk_boost_internal INTERFACE) diff --git a/Release/include/pplx/pplx.h b/Release/include/pplx/pplx.h index d9ba9c619a..43fd8170f2 100644 --- a/Release/include/pplx/pplx.h +++ b/Release/include/pplx/pplx.h @@ -49,7 +49,7 @@ #include "pplx/pplxlinux.h" #endif // _WIN32 -// Common implementation across all the non-concrt versions +// Common implementation across all the non-concrt versions зconcrt汾ͨʵ #include "pplx/pplxcancellation_token.h" #include diff --git a/Release/include/pplx/pplxcancellation_token.h b/Release/include/pplx/pplxcancellation_token.h index b7ad1a07a2..e593f35e77 100644 --- a/Release/include/pplx/pplxcancellation_token.h +++ b/Release/include/pplx/pplxcancellation_token.h @@ -4,7 +4,7 @@ * * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * - * Parallel Patterns Library : cancellation_token + * Parallel Patterns Library : cancellation_token * * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ****/ @@ -26,7 +26,7 @@ #include #include -#pragma pack(push, _CRT_PACKING) +#pragma pack(push, _CRT_PACKING ) // All header files are required to be protected from the macro new #pragma push_macro("new") #undef new diff --git a/Release/include/pplx/pplxinterface.h b/Release/include/pplx/pplxinterface.h index 4e5ca5bfc6..53a146d425 100644 --- a/Release/include/pplx/pplxinterface.h +++ b/Release/include/pplx/pplxinterface.h @@ -90,7 +90,7 @@ struct scheduler_ptr private: std::shared_ptr m_sharedScheduler; - scheduler_interface* m_scheduler; + scheduler_interface* m_scheduler; //raw pointer }; /// diff --git a/Release/include/pplx/pplxwin.h b/Release/include/pplx/pplxwin.h index 95a23b3158..0e1f21b684 100644 --- a/Release/include/pplx/pplxwin.h +++ b/Release/include/pplx/pplxwin.h @@ -12,7 +12,7 @@ ****/ #pragma once - +//MS VC++ 12.0 _MSC_VER = 1800 (VisualStudio 2013) #if !defined(_WIN32) || _MSC_VER < 1800 || CPPREST_FORCE_PPLX #include "cpprest/details/cpprest_compat.h" diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index 89d2bc55c3..9d510d64db 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -65,9 +65,11 @@ elseif(CPPREST_WEBSOCKETS_IMPL STREQUAL "wspp") websockets/client/ws_client_impl.h websockets/client/ws_client_wspp.cpp ) - cpprest_find_websocketpp() - target_link_libraries(cpprest PRIVATE cpprestsdk_websocketpp_internal) - cpprest_find_boost() + ###WIN32暂时不要webpp + #cpprest_find_websocketpp() + #target_link_libraries(cpprest PRIVATE cpprestsdk_websocketpp_internal) + ####TODO BOOST的三个库怎么也找不到,先屏蔽 + #cpprest_find_boost() cpprest_find_openssl() target_link_libraries(cpprest PUBLIC cpprestsdk_boost_internal cpprestsdk_openssl_internal) else() @@ -81,7 +83,8 @@ if(CPPREST_EXCLUDE_COMPRESSION) endif() target_compile_definitions(cpprest PRIVATE -DCPPREST_EXCLUDE_COMPRESSION=1) else() - cpprest_find_zlib() +######ZLIB 怎么也找到不到 TODO ,先屏蔽 + # cpprest_find_zlib() target_link_libraries(cpprest PRIVATE cpprestsdk_zlib_internal) if(CPPREST_EXCLUDE_BROTLI) target_compile_definitions(cpprest PRIVATE -DCPPREST_EXCLUDE_BROTLI=1) diff --git a/Release/tests/functional/json/parsing_tests.cpp b/Release/tests/functional/json/parsing_tests.cpp index cf5a261bf0..cb353f5f72 100644 --- a/Release/tests/functional/json/parsing_tests.cpp +++ b/Release/tests/functional/json/parsing_tests.cpp @@ -519,23 +519,23 @@ SUITE(parsing_tests) v.serialize(os); VERIFY_ARE_EQUAL(s2, to_string_t(os.str())); } - - TEST(Japanese) - { - utility::string_t ws = U("\"こんにちは\""); - std::string s = to_utf8string(ws); - - std::stringstream ss; - ss << s; - json::value v = json::value::parse(ss); - auto s2 = v.serialize(); - - VERIFY_ARE_EQUAL(s2, ws); - - std::stringstream os; - v.serialize(os); - VERIFY_ARE_EQUAL(s2, to_string_t(os.str())); - } + //日语编译不过 + //TEST(Japanese) + //{ + // utility::string_t ws = U("\"こんにちは\""); + // std::string s = to_utf8string(ws); + + // std::stringstream ss; + // ss << s; + // json::value v = json::value::parse(ss); + // auto s2 = v.serialize(); + + // VERIFY_ARE_EQUAL(s2, ws); + + // std::stringstream os; + // v.serialize(os); + // VERIFY_ARE_EQUAL(s2, to_string_t(os.str())); + //} TEST(Russian) { diff --git a/VIServer/Classes/ClientProtocolDefines.h b/VIServer/Classes/ClientProtocolDefines.h new file mode 100644 index 0000000000..31f3d8c48b --- /dev/null +++ b/VIServer/Classes/ClientProtocolDefines.h @@ -0,0 +1,11 @@ +#ifndef LOSEMYMIND_CLIENTPROTOCOLDEFINES_H +#define LOSEMYMIND_CLIENTPROTOCOLDEFINES_H + +#include "FoundationKit/Base/Types.h" +USING_NS_FK; + +#define CLIENT_LOGIN 1000 +#define CLIENT_CHAT 1001 + + +#endif // LOSEMYMIND_CLIENTPROTOCOLDEFINES_H diff --git a/VIServer/Classes/ConnectionManager.cpp b/VIServer/Classes/ConnectionManager.cpp new file mode 100644 index 0000000000..0f8760ae6d --- /dev/null +++ b/VIServer/Classes/ConnectionManager.cpp @@ -0,0 +1,126 @@ + +#include "ConnectionManager.h" +#include +#include +#include +#include +#include "FoundationKit/Base/MathEx.h" +#include "FoundationKit/Base/DataStream.h" +#include "FoundationKit/Foundation/unique_id.hpp" +#include "Networking/IProtocol.h" + +#define LISTENSERVER_DEFAULT_PORT 4159 +#define LISTENSERVER_DEFAULT_ENDPOINT IPv4Endpoint(IPv4Address(127, 0, 0, 1), LISTENSERVER_DEFAULT_PORT) + +ConnectionManager::ConnectionManager() + :_tcpListener(nullptr) + , _bStartup(false) +{ + +} + +ConnectionManager::~ConnectionManager() +{ + +} + +// ƶӼ +bool ConnectionManager::Startup() +{ + // ѾˣôʲôҲ + if (_bStartup)return true; + // һTCPƶ + // LISTENSERVER_DEFAULT_ENDPOINTΪIPַͶ˿ڡ + _tcpListener = new TcpListener(LISTENSERVER_DEFAULT_ENDPOINT); + // 󶨴ͻӽĺпͻӽTcpListener + // HandleListenerConnectionAccepted + _tcpListener->OnConnectionAccepted() = std::bind(&ConnectionManager::HandleListenerConnectionAccepted, this, std::placeholders::_1, std::placeholders::_2); + _bStartup = true; + LOG_INFO(">>Server listen endpoint[%s]", _tcpListener->GetLocalEndpoint().ToString().c_str()); + return true; +} + +// ӹرպԴͷš +void ConnectionManager::Shutdown() +{ + _tcpListener->Stop(); + SAFE_DELETE(_tcpListener); + for (auto iter : _clients) + { + SAFE_DELETE(iter.second); + } + _bStartup = false; +} + +// ղͻϢ +void ConnectionManager::update(float deltaTime) +{ + std::unique_lock uniqueLock(_addClientMutex); + ClientMap tempClients = _clients; + uniqueLock.unlock(); + + for (auto clientPair : tempClients) + { + Socket *client = clientPair.second; + uint32 dataSize = 0; + // ͻǷ״̬ + if (client->GetConnectionState() == ESocketConnectionState::Connected) + { + // ͻǷпɶȡ + if (client->HasPendingData(dataSize)) + { + std::vector datagram(MathEx::min(dataSize, 65507u)); + int32 bytesRead = 0; + // + if (client->Recv(datagram.data(), datagram.size(), bytesRead)) + { + // ַЭ + DataStream dataStream; + dataStream.reset(datagram.data(), datagram.size()); + IProtocol::DispathStreamProtocol(clientPair.first, dataStream); + } + } + else + { + + } + } + else + { + // ɾӶϿĿͻ + HandleClientDisconnected(clientPair.first); + } + } +} + +// ͻӽ +bool ConnectionManager::HandleListenerConnectionAccepted(Socket* ClientSocket, const IPv4Endpoint& ClientEndpoint) +{ + std::lock_guard lockClient(_addClientMutex); + _clients.insert(std::make_pair(unique_id::create(), ClientSocket)); + return true; +} + +// ͻ˶Ͽ +void ConnectionManager::HandleClientDisconnected(uint64 clientId) +{ + std::lock_guard lockClient(_addClientMutex); + auto iterFind = _clients.find(clientId); + if (iterFind != _clients.end()) + { + _clients.erase(clientId); + } +} + +// ݿͻIDؿͻ˶ +Socket* ConnectionManager::getClientByID(uint64 clientId) +{ + std::lock_guard lockClient(_addClientMutex); + auto iterFind = _clients.find(clientId); + if (iterFind != _clients.end()) + { + return iterFind->second; + } + return nullptr; +} + diff --git a/VIServer/Classes/ConnectionManager.h b/VIServer/Classes/ConnectionManager.h new file mode 100644 index 0000000000..f7817084a9 --- /dev/null +++ b/VIServer/Classes/ConnectionManager.h @@ -0,0 +1,61 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "FoundationKit/GenericPlatformMacros.h" +#include "FoundationKit/Foundation/Singleton.h" +#include "Networking/TcpListener.h" +#include "Networking/IPv4Address.h" +#include "Networking/IPv4Endpoint.h" +#include "Networking/SocketBSD.h" + +USING_NS_FK; + + +class ConnectionManager : public Singleton +{ + ConnectionManager(); + friend Singleton; +public: + typedef std::unordered_map ClientMap; + + ~ConnectionManager(); + + // + bool Startup(); + + // ر + void Shutdown(); + + // ÿ֡ + void update(float deltaTime); + + + // ͻӽ + bool HandleListenerConnectionAccepted(Socket* ClientSocket, const IPv4Endpoint& ClientEndpoint); + + // ͻ˶Ͽ + void HandleClientDisconnected(uint64 clientId); + + // ݿͻIDؿͻ˶ + Socket* getClientByID(uint64 clientId); + +protected: + + // TCP Ӽͻӡ + TcpListener* _tcpListener; + ClientMap _clients; + std::mutex _addClientMutex; + + bool _bStartup; +}; + + + + + + + diff --git a/VIServer/Classes/FoundationKit/Base/Data.cpp b/VIServer/Classes/FoundationKit/Base/Data.cpp new file mode 100644 index 0000000000..9357b74f00 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Base/Data.cpp @@ -0,0 +1,107 @@ +/**************************************************************************** +Copyright (c) 2013-2014 libo. + +losemymind.libo@gmail.com + +****************************************************************************/ +#include +#include "Data.h" + +NS_FK_BEGIN +const Data Data::Null; + +Data::Data() +:_bytes(nullptr) +,_size(0) +,_ownMem(false) +{ +} + +Data::Data(Data&& other) +:_bytes(nullptr) +,_size(0) +,_ownMem(false) +{ + move(other); +} + +Data::Data(const Data& other) +:_bytes(nullptr) +,_size(0) +,_ownMem(false) +{ + copy(other._bytes, other._size); +} + +Data::~Data() +{ + clear(); +} + +Data& Data::operator= (const Data& other) +{ + copy(other._bytes, other._size); + return *this; +} + +Data& Data::operator= (Data&& other) +{ + move(other); + return *this; +} + +void Data::move(Data& other) +{ + _ownMem = other._ownMem; + _bytes = other._bytes; + _size = other._size; + other._bytes = nullptr; + other._size = 0; +} + +bool Data::isNull() const +{ + return (_bytes == nullptr || _size == 0); +} + +unsigned char* Data::getBytes() const +{ + return _bytes; +} + +size_t Data::getSize() const +{ + return _size; +} + +void Data::copy(unsigned char* bytes, const size_t size) +{ + clear(); + + if (size > 0) + { + _ownMem = true; + _size = size; + _bytes = new unsigned char[sizeof(unsigned char) * _size]; + memcpy(_bytes, bytes, _size); + } +} + +void Data::fastSet(unsigned char* bytes, const size_t size, bool needDelete /*= false*/) +{ + clear(); + _ownMem = needDelete; + _bytes = bytes; + _size = size; +} + +void Data::clear() +{ + if (_ownMem) + delete[] _bytes; + _bytes = nullptr; + _size = 0; +} + +NS_FK_END + diff --git a/VIServer/Classes/FoundationKit/Base/Data.h b/VIServer/Classes/FoundationKit/Base/Data.h new file mode 100644 index 0000000000..4f607c2b07 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Base/Data.h @@ -0,0 +1,72 @@ +/**************************************************************************** +Copyright (c) 2013-2014 libo. + +losemymind.libo@gmail.com + +****************************************************************************/ +#ifndef LOSEMYMIND_DATA_H +#define LOSEMYMIND_DATA_H + +#pragma once +#include "FoundationKit/GenericPlatformMacros.h" +#include + +NS_FK_BEGIN + +class Data +{ +public: + static const Data Null; + + Data(); + Data(const Data& other); + Data(Data&& other); + ~Data(); + + // Assignment operator + Data& operator= (const Data& other); + Data& operator= (Data&& other); + + unsigned char* getBytes() const; + + size_t getSize() const; + + /** Copies the buffer pointer and its size. + * @note This method will copy the whole buffer. + * Developer should free the pointer after invoking this method. + * @see Data::fastSet + */ + void copy(unsigned char* bytes, const size_t size); + + /** Fast set the buffer pointer and its size. Please use it carefully. + * @param bytes The buffer pointer, note that it have to be allocated by 'malloc' or 'calloc', + * since in the destructor of Data, the buffer will be deleted by 'free'. + * @note 1. This method will move the ownship of 'bytes'pointer to Data, + * 2. The pointer should not be used outside after it was passed to this method. + * @see Data::copy + */ + void fastSet(unsigned char* bytes, const size_t size, bool needDelete = false); + + /** Clears data, free buffer and reset data size */ + void clear(); + + /** Check whether the data is null. */ + bool isNull() const; + +private: + void move(Data& other); + +private: + unsigned char* _bytes; + size_t _size; + bool _ownMem; +}; + +NS_FK_END +#endif // LOSEMYMIND_DATA_H + + + + + + diff --git a/VIServer/Classes/FoundationKit/Base/DataStream.cpp b/VIServer/Classes/FoundationKit/Base/DataStream.cpp new file mode 100644 index 0000000000..4fc2588f70 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Base/DataStream.cpp @@ -0,0 +1,188 @@ +/**************************************************************************** + Copyright (c) 2015 libo All rights reserved. + + losemymind.libo@gmail.com + +****************************************************************************/ + +#include +#include "DataStream.h" + +NS_FK_BEGIN + +DataStream::DataStream() +: _readIndex(0) +, _burnAfterReading(false) +{ +} +DataStream::DataStream(const DataStream& pDataStream) + : _buffer(pDataStream.getBuffer()) + , _readIndex(pDataStream._readIndex) + , _burnAfterReading(pDataStream._burnAfterReading) +{ +} + +DataStream::DataStream(DataStream&& pDataStream) + : _buffer(std::move(pDataStream._buffer)) + , _readIndex(pDataStream._readIndex) + , _burnAfterReading(pDataStream._burnAfterReading) +{ +} + +DataStream& DataStream::operator=(const DataStream& pDataStream) +{ + _buffer = pDataStream.getBuffer(); + _burnAfterReading = pDataStream._burnAfterReading; + _readIndex = pDataStream._readIndex; + return *this; +} + +DataStream& DataStream::operator=(DataStream&& pDataStream) +{ + _buffer = std::move(pDataStream._buffer); + _burnAfterReading = pDataStream._burnAfterReading; + _readIndex = pDataStream._readIndex; + return *this; +} + +DataStream& DataStream::operator << (const uint8* data) +{ + *this << ustring(data); + return *this; +} + +DataStream& DataStream::operator << (const std::string& data) +{ + this->write((const uint8*)data.c_str(), data.size()); + return *this; +} + +DataStream& DataStream::operator << (const ustring& data) +{ + *this << data.size(); + _buffer.append(data.c_str(), data.size()); + return *this; +} + +DataStream& DataStream::operator >> (uint8* data) +{ + size_type size = 0; + *this >> size; + + // Check for fake string size to prevent memory hacks + if (size > _buffer.size()) + { + std::ostringstream os; + os << "String size (" << size << ") > packet size (" << _buffer.size() << ")"; + throw std::out_of_range(os.str()); + } + if (size == 0) + { + data = (uint8*)""; + return *this; + } + + read(data, size); + return *this; +} + +DataStream& DataStream::operator >> (std::string& data) +{ + ustring temp; + *this >> temp; + data.assign((const char*)temp.c_str(), temp.size()); + return *this; +} + +DataStream& DataStream::operator>>(ustring& data) +{ + size_type size = 0; + *this >> size; + + // Check for fake string size to prevent memory hacks + if(size > _buffer.size()) + { + std::ostringstream os; + os << "String size (" << size << ") > packet size (" << _buffer.size() << ")"; + throw std::out_of_range(os.str()); + } + if(size == 0) + { + data = (uint8*)""; + return *this; + } + + //data = _buffer.substr(0,size); + data = _buffer.substr(getReadIndex(), size); + data.shrink_to_fit(); + //_buffer.erase(0,size); + readIndexIncrement(size); + return *this; +} + +void DataStream::write(const uint8* data, size_type pSize) +{ + *this << pSize; + _buffer.append(data, pSize); + +} + +void DataStream::read(uint8* data, size_type dataSize) +{ + //memcpy(data,&_buffer[0],dataSize); + //_buffer.erase(0,dataSize); + memcpy(data, &_buffer[getReadIndex()], dataSize); + readIndexIncrement(dataSize); +} + +void DataStream::clear() +{ + _buffer.clear(); + _readIndex = 0; +} + +void DataStream::reset(const ustring& data) +{ + _buffer.clear(); + _buffer.append(data); + _readIndex = 0; +} + +void DataStream::reset(const uint8* data, size_type size) +{ + _buffer.clear(); + _buffer.append(data, size); + _readIndex = 0; +} + +size_t DataStream::size() +{ + return _buffer.size(); +} + +const ustring& DataStream::getBuffer()const +{ + return _buffer; +} + +const uint8* DataStream::c_str() +{ + return _buffer.c_str(); +} + +DataStream::size_type DataStream::getReadIndex() +{ + if (_burnAfterReading) + return 0; + return _readIndex; +} + +void DataStream::readIndexIncrement(size_type count) +{ + if (_burnAfterReading) + _buffer.erase(0, count); + else + _readIndex += count; +} + +NS_FK_END \ No newline at end of file diff --git a/VIServer/Classes/FoundationKit/Base/DataStream.h b/VIServer/Classes/FoundationKit/Base/DataStream.h new file mode 100644 index 0000000000..28d5d2cc6e --- /dev/null +++ b/VIServer/Classes/FoundationKit/Base/DataStream.h @@ -0,0 +1,207 @@ +/**************************************************************************** + Copyright (c) 2015 libo All rights reserved. + + losemymind.libo@gmail.com + +****************************************************************************/ +#ifndef LOSEMYMIND_DATASTREAM_H +#define LOSEMYMIND_DATASTREAM_H + +#pragma once + +#include +#include +#include +#include +#include +#include +#include "FoundationKit/GenericPlatformMacros.h" +#include "FoundationKit/Base/Types.h" +NS_FK_BEGIN + +class DataStream +{ +public: + typedef uint32 size_type; + DataStream(); + DataStream(const DataStream& pDataStream); + DataStream(DataStream&& pDataStream); + DataStream& operator=(const DataStream& pDataStream); + DataStream& operator=(DataStream&& pDataStream); + + template::value>::type > + DataStream& operator<<(T data) + { + _buffer.append((uint8*)&data, sizeof(T)); + return *this; + } + + DataStream& operator<<(const uint8* data); + DataStream& operator<<(const std::string& data); + DataStream& operator<<(const ustring& data); + + template::value>::type > + DataStream& operator>>(T& data) + { + read(data); + return *this; + } + + DataStream& operator>>(uint8* data); + DataStream& operator>>(std::string& data); + DataStream& operator>>(ustring& data); + + template + DataStream& operator<<(const std::map& data) + { + return writeAssociativeContainer(data); + } + + template + DataStream& operator>>(std::map& data) + { + return readAssociativeContainer, K, V>(data); + } + + template + DataStream& operator<<(const std::unordered_map& data) + { + return writeAssociativeContainer(data); + } + + template + DataStream& operator>>(std::unordered_map& data) + { + return readAssociativeContainer, K, V>(data); + } + + template + DataStream& operator<<(const std::vector& data) + { + return writeSequenceContainer(data); + } + + template + DataStream& operator>>(std::vector& data) + { + return readSequenceContainer, V>(data); + } + + template + DataStream& operator<<(const std::list& data) + { + return writeSequenceContainer(data); + } + + template + DataStream& operator>>(std::list& data) + { + return readSequenceContainer, V>(data); + } + + void write(const uint8_t* data, size_type pSize); + + template< typename T > + void read(T& data) + { + if (size() < sizeof(T)) + { + data = T(); + return; + } + memcpy(&data, &_buffer[getReadIndex()], sizeof(T)); + readIndexIncrement(sizeof(T)); + //memcpy(&data, &_buffer[0], sizeof(T)); + //_buffer.erase(0, sizeof(T)); + } + + template< typename T > + inline T read() + { + T ret; + read(ret); + return ret; + } + + void read(uint8_t* data, size_type dataSize); + + + void clear(); + void reset(const ustring& data); + void reset(const uint8* data, size_type size); + size_t size(); + const uint8* c_str(); + const ustring& getBuffer()const; + + void setBurnAfterReading(bool val){ _burnAfterReading = val; } +private: + template + DataStream& writeSequenceContainer(const C& data) + { + *this << data.size(); + for(auto iter : data) + { + *this << iter; + } + return *this; + } + + template + DataStream& readSequenceContainer(C& data) + { + size_t size=0; + *this >> size; + + for(size_t i = 0; i < size; ++i) + { + V value; + *this >> value; + data.push_back(value); + } + + return *this; + } + + template + DataStream& writeAssociativeContainer(const C& data) + { + *this << data.size(); + for(auto& iter : data) + { + *this << iter.first << iter.second; + } + return *this; + } + + template + DataStream& readAssociativeContainer(C& data) + { + size_t size=0; + *this >> size; + for(size_t i = 0; i < size; ++i) + { + K key; + V value; + *this >> key >> value; + data.insert(std::pair(key, value)); + } + return *this; + } + + size_type getReadIndex(); + + void readIndexIncrement(size_type count); + +protected: + ustring _buffer; + size_type _readIndex; + bool _burnAfterReading; +}; + +NS_FK_END +#endif // LOSEMYMIND_DATASTREAM_H + + + + + diff --git a/VIServer/Classes/FoundationKit/Base/DateTime.cpp b/VIServer/Classes/FoundationKit/Base/DateTime.cpp new file mode 100644 index 0000000000..46d0cfd902 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Base/DateTime.cpp @@ -0,0 +1,420 @@ +/**************************************************************************** +Copyright (c) 2016 libo All rights reserved. + +losemymind.libo@gmail.com + +****************************************************************************/ +#include +#include +#include "FoundationKit/Foundation/StringUtils.h" +#include "FoundationKit/Base/MathEx.h" +#include "FoundationKit/Platform/Platform.h" +#include "DateTime.h" + +NS_FK_BEGIN + +/* DateTime constants + *****************************************************************************/ + +const int32 DateTime::DaysPerMonth[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; +const int32 DateTime::DaysToMonth[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; + + +/* DateTime structors + *****************************************************************************/ + +DateTime::DateTime( int32 year, int32 month, int32 day, int32 hour, int32 minute, int32 second, int32 millisecond ) +{ + LOG_ASSERT(validate(year, month, day, hour, minute, second, millisecond), "Input date time is invalid."); + + int32 totalDays = 0; + + if ((month > 2) && isLeapYear(year)) + { + ++totalDays; + } + + year--; // the current year is not a full year yet + month--; // the current month is not a full month yet + + totalDays += year * 365; + totalDays += year / 4; // leap year day every four years... + totalDays -= year / 100; // ...except every 100 years... + totalDays += year / 400; // ...but also every 400 years + totalDays += DaysToMonth[month]; // days in this year up to last month + totalDays += day - 1; // days in this month minus today + + _ticks = totalDays * ETimespan::TicksPerDay + + hour * ETimespan::TicksPerHour + + minute * ETimespan::TicksPerMinute + + second * ETimespan::TicksPerSecond + + millisecond * ETimespan::TicksPerMillisecond; +} + + +void DateTime::getDate( int32& outYear, int32& outMonth, int32& outDay ) const +{ + int32 i, j, k, l, n; + l = MathEx::floorToInt(static_cast(getJulianDay() + 0.5)) + 68569; + n = 4 * l / 146097; + l = l - (146097 * n + 3) / 4; + i = 4000 * (l + 1) / 1461001; + l = l - 1461 * i / 4 + 31; + j = 80 * l / 2447; + k = l - 2447 * j / 80; + l = j / 11; + j = j + 2 - 12 * l; + i = 100 * (n - 49) + i + l; + + outYear = i; + outMonth = j; + outDay = k; +} + + +int32 DateTime::getDay() const +{ + int32 year, month, day; + getDate(year, month, day); + return day; +} + + +EDayOfWeek DateTime::getDayOfWeek() const +{ + // January 1, 0001 was a Monday + return static_cast((_ticks / ETimespan::TicksPerDay) % 7); +} + + +int32 DateTime::getDayOfYear() const +{ + int32 year, month, day; + getDate(year, month, day); + for (int32 currentMonth = 1; currentMonth < month; ++currentMonth) + { + day += daysInMonth(year, currentMonth); + } + return day; +} + + +int32 DateTime::getHour12() const +{ + int32 hour = getHour(); + if (hour < 1) + { + return 12; + } + if (hour > 12) + { + return (hour - 12); + } + return hour; +} + + +int32 DateTime::getMonth() const +{ + int32 year, month, day; + getDate(year, month, day); + return month; +} + + +int32 DateTime::getYear() const +{ + int32 year, month, day; + getDate(year, month, day); + return year; +} + + +std::string DateTime::toIso8601() const +{ + return toString("%Y-%m-%dT%H:%M:%S.%sZ"); +} + + +std::string DateTime::toString() const +{ + return toString("%Y.%m.%d-%H.%M.%S"); +} + + +std::string DateTime::toString( const char* format ) const +{ + std::string result; + + if (format != nullptr) + { + while (*format != '\0') + { + if ((*format == '%') && (*(++format) != '\0')) + { + switch (*format) + { + case 'a': result += isMorning() ? "am" : "pm"; break; + case 'A': result += isMorning() ? "AM" : "PM"; break; + case 'd': result += StringUtils::format("%02i", getDay()); break; + case 'D': result += StringUtils::format("%03i", getDayOfYear()); break; + case 'm': result += StringUtils::format("%02i", getMonth()); break; + case 'y': result += StringUtils::format("%02i", getYear() % 100); break; + case 'Y': result += StringUtils::format("%04i", getYear()); break; + case 'h': result += StringUtils::format("%02i", getHour12()); break; + case 'H': result += StringUtils::format("%02i", getHour()); break; + case 'M': result += StringUtils::format("%02i", getMinute()); break; + case 'S': result += StringUtils::format("%02i", getSecond()); break; + case 's': result += StringUtils::format("%03i", getMillisecond()); break; + default: result += *format; + } + } + else + { + result += *format; + } + + // move to the next one + format++; + } + } + + return result; +} + + +/* DateTime static interface + *****************************************************************************/ + +int32 DateTime::daysInMonth( int32 year, int32 month ) +{ + LOG_ASSERT((month >= 1) && (month <= 12), "The month param is invaild."); + if ((month == 2) && isLeapYear(year)) + { + return 29; + } + return DaysPerMonth[month]; +} + + +int32 DateTime::daysInYear( int32 year ) +{ + if (isLeapYear(year)) + { + return 366; + } + return 365; +} + + +bool DateTime::isLeapYear( int32 year ) +{ + if ((year % 4) == 0) + { + return (((year % 100) != 0) || ((year % 400) == 0)); + } + return false; +} + + +DateTime DateTime::now() +{ + int32 year, month, day, dayOfWeek; + int32 hour, minute, second, millisecond; + Platform::systemTime(year, month, dayOfWeek, day, hour, minute, second, millisecond); + return DateTime(year, month, day, hour, minute, second, millisecond); +} + +DateTime DateTime::utcNow() +{ + int32 year, month, day, dayOfWeek; + int32 hour, minute, second, millisecond; + Platform::utcTime(year, month, dayOfWeek, day, hour, minute, second, millisecond); + return DateTime(year, month, day, hour, minute, second, millisecond); +} + +bool DateTime::parse( const std::string& dateTimeString, DateTime& outDateTime ) +{ + // first replace -, : and . with space + std::string fixedString = dateTimeString; + std::replace(fixedString.begin(), fixedString.end(), '-', ' '); + std::replace(fixedString.begin(), fixedString.end(), ':', ' '); + std::replace(fixedString.begin(), fixedString.end(), '.', ' '); + + std::vector tokens; + + // split up on a single delimiter + StringUtils::split(fixedString, ' ', tokens); + // make sure it parsed it properly (within reason) + if ((tokens.size() < 6) || (tokens.size() > 7)) + { + return false; + } + + const int32 year = std::atoi(tokens[0].c_str()); + const int32 month = std::atoi(tokens[1].c_str()); + const int32 day = std::atoi(tokens[2].c_str()); + const int32 hour = std::atoi(tokens[3].c_str()); + const int32 minute = std::atoi(tokens[4].c_str()); + const int32 second = std::atoi(tokens[5].c_str()); + const int32 millisecond = tokens.size() > 6 ? std::atoi(tokens[6].c_str()) : 0; + + if (!validate(year, month, day, hour, minute, second, millisecond)) + { + return false; + } + + // convert the tokens to numbers + outDateTime._ticks = DateTime(year, month, day, hour, minute, second, millisecond)._ticks; + + return true; +} + + +bool DateTime::parseIso8601( const char* dateTimeString, DateTime& outDateTime ) +{ + // DateOnly: YYYY-MM-DD + // DateTime: YYYY-mm-ddTHH:MM:SS(.ssss)(Z|+th:tm|-th:tm) + + const char* dtPtr = dateTimeString; + char* next = nullptr; + + int32 year = 0, month = 0, day = 0; + int32 hour = 0, minute = 0, second = 0, millisecond = 0; + int32 tzHour = 0, tzMinute = 0; + + // get date + year = static_cast(std::strtol(dtPtr, &next, 10)); + + if ((next <= dtPtr) || (*next == '\0')) + { + return false; + } + + dtPtr = next + 1; // skip separator + month = static_cast(std::strtol(dtPtr, &next, 10)); + + if ((next <= dtPtr) || (*next == '\0')) + { + return false; + } + + dtPtr = next + 1; // skip separator + day = static_cast(std::strtol(dtPtr, &next, 10)); + + if (next <= dtPtr) + { + return false; + } + + // check whether this is date and time + if (*next == 'T') + { + dtPtr = next + 1; + + // parse time + hour = static_cast(std::strtol(dtPtr, &next, 10)); + + if ((next <= dtPtr) || (*next == '\0')) + { + return false; + } + + dtPtr = next + 1; // skip separator + minute = static_cast(std::strtol(dtPtr, &next, 10)); + + if ((next <= dtPtr) || (*next == '\0')) + { + return false; + } + + dtPtr = next + 1; // skip separator + second = static_cast(std::strtol(dtPtr, &next, 10)); + + if (next <= dtPtr) + { + return false; + } + + // check for milliseconds + if (*next == '.') + { + dtPtr = next + 1; + millisecond = static_cast(std::strtol(dtPtr, &next, 10)); + + // should be no more than 3 digits + if ((next <= dtPtr) || (next > dtPtr + 3)) + { + return false; + } + + for (PTRINT Digits = next - dtPtr; Digits < 3; ++Digits) + { + millisecond *= 10; + } + } + + // see if the timezone offset is included + if (*next == '+' || *next == '-') + { + // include the separator since it's + or - + dtPtr = next; + + // parse the timezone offset + tzHour = static_cast(std::strtol(dtPtr, &next, 10)); + + if ((next <= dtPtr) || (*next == '\0')) + { + return false; + } + + dtPtr = next + 1; // skip separator + tzMinute = static_cast(std::strtol(dtPtr, &next, 10)); + + if (next <= dtPtr) + { + return false; + } + } + else if ((*next != '\0') && (*next != 'Z')) + { + return false; + } + } + else if (*next != '\0') + { + return false; + } + + if (!validate(year, month, day, hour, minute, second, millisecond)) + { + return false; + } + + DateTime Final(year, month, day, hour, minute, second, millisecond); + + // adjust for the timezone (bringing the DateTime into UTC) + int32 TzOffsetMinutes = (tzHour < 0) ? tzHour * 60 - tzMinute : tzHour * 60 + tzMinute; + Final -= Timespan(0, TzOffsetMinutes, 0); + outDateTime = Final; + + return true; +} + +bool DateTime::validate( int32 year, int32 month, int32 day, int32 hour, int32 minute, int32 second, int32 millisecond ) +{ + return (year >= 1) && (year <= 9999) && + (month >= 1) && (month <= 12) && + (day >= 1) && (day <= daysInMonth(year, month)) && + (hour >= 0) && (hour <= 23) && + (minute >= 0) && (minute <= 59) && + (second >= 0) && (second <= 59) && + (millisecond >= 0) && (millisecond <= 999); +} + + +NS_FK_END + + + + diff --git a/VIServer/Classes/FoundationKit/Base/DateTime.h b/VIServer/Classes/FoundationKit/Base/DateTime.h new file mode 100644 index 0000000000..5e152ffd87 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Base/DateTime.h @@ -0,0 +1,658 @@ +/**************************************************************************** +Copyright (c) 2016 libo All rights reserved. + +losemymind.libo@gmail.com + +****************************************************************************/ +#ifndef LOSEMYMIND_DATETIME_H +#define LOSEMYMIND_DATETIME_H + +#pragma once +#include +#include "FoundationKit/GenericPlatformMacros.h" +#include "FoundationKit/Base/Types.h" +#include "Timespan.h" + +NS_FK_BEGIN + +/** + * Enumerates the days of the week in 7-day calendars. + */ +enum class EDayOfWeek +{ + Monday = 0, + Tuesday, + Wednesday, + Thursday, + Friday, + Saturday, + Sunday +}; + + +/** + * Enumerates the months of the year in 12-month calendars. + */ +enum class EMonthOfYear +{ + January = 1, + February, + March, + April, + May, + June, + July, + August, + September, + October, + November, + December +}; + + +/** + * Implements a date and time. + * + * Values of this type represent dates and times between Midnight 00:00:00, January 1, 0001 and + * Midnight 23:59:59.9999999, December 31, 9999 in the Gregorian calendar. Internally, the time + * values are stored in ticks of 0.1 microseconds (= 100 nanoseconds) since January 1, 0001. + * + * To retrieve the current local date and time, use the DateTime.Now() method. To retrieve the + * current UTC time, use the DateTime.UtcNow() method instead. + * + * This class also provides methods to convert dates and times from and to string representations, + * calculate the number of days in a given month and year, check for leap years and determine the + * time of day, day of week and month of year of a given date and time. + * + * The companion struct Timespan is provided for enabling date and time based arithmetic, such as + * calculating the difference between two dates or adding a certain amount of time to a given date. + * + * Ranges of dates and times can be represented by the FDateRange class. + * + * @see Timespan + */ +class DateTime +{ +public: + + /** Default constructor (no initialization). */ + DateTime() { } + + /** + * Creates and initializes a new instance with the specified number of ticks. + * + * @param Ticks The ticks representing the date and time. + */ + explicit DateTime( int64 inTicks ) + : _ticks(inTicks) + { } + + /** + * Creates and initializes a new instance with the specified year, month, day, hour, minute, second and millisecond. + * + * @param year The year. + * @param month The month. + * @param day The day. + * @param hour The hour (optional). + * @param minute The minute (optional). + * @param second The second (optional). + * @param millisecond The millisecond (optional). + */ + DateTime( int32 year, int32 month, int32 day, int32 hour = 0, int32 minute = 0, int32 second = 0, int32 millisecond = 0 ); + +public: + + /** + * Returns result of adding the given time span to this date. + * + * @return A date whose value is the sum of this date and the given time span. + * @see Timespan + */ + DateTime operator+( const Timespan& other ) const + { + return DateTime(_ticks + other.getTicks()); + } + + /** + * Adds the given time span to this date. + * + * @return This date. + * @see Timespan + */ + DateTime& operator+=(const Timespan& other) + { + _ticks += other.getTicks(); + return *this; + } + + /** + * Returns time span between this date and the given date. + * + * @return A time span whose value is the difference of this date and the given date. + * @see Timespan + */ + Timespan operator-(const DateTime& other) const + { + return Timespan(_ticks - other.getTicks()); + } + + /** + * Returns result of subtracting the given time span from this date. + * + * @return A date whose value is the difference of this date and the given time span. + * @see Timespan + */ + DateTime operator-(const Timespan& other) const + { + return DateTime(_ticks - other.getTicks()); + } + + /** + * Subtracts the given time span from this date. + * + * @return This date. + * @see Timespan + */ + DateTime& operator-=(const Timespan& other) + { + _ticks -= other.getTicks(); + return *this; + } + + /** + * Compares this date with the given date for equality. + * + * @param other The date to compare with. + * @return true if the dates are equal, false otherwise. + */ + bool operator==(const DateTime& other) const + { + return (_ticks == other._ticks); + } + + /** + * Compares this date with the given date for inequality. + * + * @param other The date to compare with. + * @return true if the dates are not equal, false otherwise. + */ + bool operator!=( const DateTime& Other ) const + { + return (_ticks != Other._ticks); + } + + /** + * Checks whether this date is greater than the given date. + * + * @param other The date to compare with. + * @return true if this date is greater, false otherwise. + */ + bool operator>( const DateTime& Other ) const + { + return (_ticks > Other._ticks); + } + + /** + * Checks whether this date is greater than or equal to the date span. + * + * @param other The date to compare with. + * @return true if this date is greater or equal, false otherwise. + */ + bool operator>=( const DateTime& Other ) const + { + return (_ticks >= Other._ticks); + } + + /** + * Checks whether this date is less than the given date. + * + * @param other The date to compare with. + * @return true if this date is less, false otherwise. + */ + bool operator<( const DateTime& Other ) const + { + return (_ticks < Other._ticks); + } + + /** + * Checks whether this date is less than or equal to the given date. + * + * @param other The date to compare with. + * @return true if this date is less or equal, false otherwise. + */ + bool operator<=( const DateTime& Other ) const + { + return (_ticks <= Other._ticks); + } + +public: + + /** + * Gets the date part of this date. + * + * The time part is truncated and becomes 00:00:00.000. + * + * @return A DateTime object containing the date. + */ + DateTime getDate() const + { + return DateTime(_ticks - (_ticks % ETimespan::TicksPerDay)); + } + + /** + * Gets the date components of this date. + * + * @param outYear Will contain the year. + * @param outMonth Will contain the number of the month (1-12). + * @param outDay Will contain the number of the day (1-31). + */ + void getDate( int32& outYear, int32& outMonth, int32& outDay ) const; + + /** + * Gets this date's day part (1 to 31). + * + * @return Day of the month. + * @see getHour, getHour12, getMillisecond, getMinute, getMonth, getSecond, getYear + */ + int32 getDay() const; + + /** + * Calculates this date's day of the week (Sunday - Saturday). + * + * @return The week day. + * @see getDayOfYear, getMonthOfYear, getTimeOfDay + */ + EDayOfWeek getDayOfWeek() const; + + /** + * Gets this date's day of the year. + * + * @return The day of year. + * @see getDayOfWeek, getMonthOfYear, getTimeOfDay + */ + int32 getDayOfYear() const; + + /** + * Gets this date's hour part in 24-hour clock format (0 to 23). + * + * @return The hour. + * @see getDay, getDayOfWeek, getDayOfYear, getHour12, getMillisecond, getMinute, getMonth, getSecond, getYear + */ + int32 getHour() const + { + return (int32)((_ticks / ETimespan::TicksPerHour) % 24); + } + + /** + * Gets this date's hour part in 12-hour clock format (1 to 12). + * + * @return The hour in AM/PM format. + * @see getDay, getHour, getMillisecond, getMinute, getMonth, getSecond, getYear + */ + int32 getHour12() const; + + /** + * Returns the Julian Day for this date. + * + * The Julian Day is the number of days since the inception of the Julian calendar at noon on + * Monday, January 1, 4713 B.C.E. The minimum Julian Day that can be represented in DateTime is + * 1721425.5, which corresponds to Monday, January 1, 0001 in the Gregorian calendar. + * + * @return Julian Day. + * @see fromJulianDay, getModifiedJulianDay + */ + double getJulianDay() const + { + return (double)(1721425.5 + _ticks / ETimespan::TicksPerDay); + } + + /** + * Returns the Modified Julian day. + * + * The Modified Julian Day is calculated by subtracting 2400000.5, which corresponds to midnight UTC on + * November 17, 1858 in the Gregorian calendar. + * + * @return Modified Julian Day + * @see getJulianDay + */ + double getModifiedJulianDay() const + { + return (getJulianDay() - 2400000.5); + } + + /** + * Gets this date's millisecond part (0 to 999). + * + * @return The millisecond. + * @see getDay, getHour, getHour12, getMinute, getMonth, getSecond, getYear + */ + int32 getMillisecond() const + { + return (int32)((_ticks / ETimespan::TicksPerMillisecond) % 1000); + } + + /** + * Gets this date's minute part (0 to 59). + * + * @return The minute. + * @see getDay, getHour, getHour12, getMillisecond, getMonth, getSecond, getYear + */ + int32 getMinute() const + { + return (int32)((_ticks / ETimespan::TicksPerMinute) % 60); + } + + /** + * Gets this date's the month part (1 to 12). + * + * @return The month. + * @see getDay, getHour, getHour12, getMillisecond, getMinute, getSecond, getYear + */ + int32 getMonth() const; + + /** + * Gets the date's month of the year (January to December). + * + * @return Month of year. + * @see getDayOfWeek, getDayOfYear, getTimeOfDay + */ + EMonthOfYear getMonthOfYear() const + { + return static_cast(getMonth()); + } + + /** + * Gets this date's second part. + * + * @return The second. + * @see getDay, getHour, getHour12, getMillisecond, getMinute, getMonth, getYear + */ + int32 getSecond() const + { + return (int32)((_ticks / ETimespan::TicksPerSecond) % 60); + } + + /** + * Gets this date's representation as number of ticks. + * + * @return Number of ticks since midnight, January 1, 0001. + */ + int64 getTicks() const + { + return _ticks; + } + + /** + * Gets the time elapsed since midnight of this date. + * + * @param Time of day since midnight. + * @see getDayOfWeek, getDayOfYear, getMonthOfYear + */ + Timespan getTimeOfDay() const + { + return Timespan(_ticks % ETimespan::TicksPerDay); + } + + /** + * Gets this date's year part. + * + * @return The year. + * @see GetDay, GetHour, GetHour12, GetMillisecond, GetMinute, GetMonth, GetSecond + */ + int32 getYear() const; + + /** + * Gets whether this date's time is in the afternoon. + * + * @param true if it is in the afternoon, false otherwise. + * @see isMorning + */ + bool isAfternoon() const + { + return (getHour() >= 12); + } + + /** + * Gets whether this date's time is in the morning. + * + * @param true if it is in the morning, false otherwise. + * @see isAfternoon + */ + bool isMorning() const + { + return (getHour() < 12); + } + + /** + * Returns the ISO-8601 string representation of the DateTime. + * + * The resulting string assumes that the DateTime is in UTC. + * + * @return String representation. + * @see parseIso8601, toString + */ + std::string toIso8601() const; + + /** + * Returns the string representation of this date using a default format. + * + * The returned string has the following format: + * yyyy.mm.dd-hh.mm.ss + * + * @return String representation. + * @see parse, toIso8601 + */ + std::string toString() const; + + /** + * Returns the string representation of this date. + * + * @param format The format of the returned string. + * @return String representation. + * @see parse, toIso8601 + */ + std::string toString( const char* format ) const; + + /** + * Returns this date as the number of seconds since the Unix Epoch (January 1st of 1970). + * + * @return Time of day. + * @see fromUnixTimestamp + */ + int64 toUnixTimestamp() const + { + return (_ticks - DateTime(1970, 1, 1)._ticks) / ETimespan::TicksPerSecond; + } + +public: + + /** + * Gets the number of days in the year and month. + * + * @param year The year. + * @param month The month. + * @return The number of days + * @see daysInYear + */ + static int32 daysInMonth( int32 year, int32 month ); + + /** + * Gets the number of days in the given year. + * + * @param year The year. + * @return The number of days. + * @see daysInMonth + */ + static int32 daysInYear( int32 year ); + + /** + * Returns the proleptic Gregorian date for the given Julian Day. + * + * @param JulianDay The Julian Day. + * @return Gregorian date and time. + * @see getJulianDay + */ + static DateTime fromJulianDay( double julianDay ) + { + return DateTime((int64)((julianDay - 1721425.5) * ETimespan::TicksPerDay)); + } + + /** + * Returns the date from Unix time (seconds from midnight 1970-01-01) + * + * @param UnixTime Unix time (seconds from midnight 1970-01-01) + * @return Gregorian date and time. + * @see toUnixTimestamp + */ + static DateTime fromUnixTimestamp( int64 unixTime ) + { + return DateTime(1970, 1, 1) + Timespan(unixTime * ETimespan::TicksPerSecond); + } + + /** + * Checks whether the given year is a leap year. + * + * A leap year is a year containing one additional day in order to keep the calendar synchronized + * with the astronomical year. All years divisible by 4, but not divisible by 100 - except if they + * are also divisible by 400 - are leap years. + * + * @param year The year to check. + * @return true if the year is a leap year, false otherwise. + */ + static bool isLeapYear( int32 year ); + + /** + * Returns the maximum date value. + * + * The maximum date value is December 31, 9999, 23:59:59.9999999. + * + * @see minValue + */ + static DateTime maxValue() + { + return DateTime(3652059 * ETimespan::TicksPerDay - 1); + } + + /** + * Returns the minimum date value. + * + * The minimum date value is January 1, 0001, 00:00:00.0. + * + * @see maxValue + */ + static DateTime minValue() + { + return DateTime(0); + } + + /** + * Gets the local date and time on this computer. + * + * This method takes into account the local computer's time zone and daylight saving + * settings. For time zone independent time comparisons, and when comparing times + * between different computers, please use UtcNow() instead. + * + * @return Current date and time. + * @see Today, utcNow + */ + static DateTime now(); + + /** + * Gets the UTC date and time on this computer. + * + * This method returns the Coordinated Universal Time (UTC), which does not take the + * local computer's time zone and daylight savings settings into account. It should be + * used when comparing dates and times that should be independent of the user's locale. + * To get the date and time in the current locale, use Now() instead. + * + * @return Current date and time. + * @see Now + */ + static DateTime utcNow(); + + + /** + * Converts a string to a date and time. + * + * Currently, the string must be in the format written by either DateTime.ToString() or + * FTimeStamp.TimestampToFString(). Other formats are not supported at this time. + * + * @param dateTimeString The string to convert. + * @param outDateTime Will contain the parsed date and time. + * @return true if the string was converted successfully, false otherwise. + */ + static bool parse( const std::string& dateTimeString, DateTime& outDateTime ); + + /** + * Parses a date string in ISO-8601 format. + * + * @param dateTimeString The string to be parsed + * @param outDateTime DateTime object (in UTC) corresponding to the input string (which may have been in any timezone). + * @return true if the string was converted successfully, false otherwise. + * @see Parse, ToIso8601 + */ + static bool parseIso8601( const char* dateTimeString, DateTime& outDateTime ); + + /** + * Gets the local date on this computer. + * + * The time component is set to 00:00:00 + * + * @return Current date. + * @see Now, UtcNow + */ + static DateTime today() + { + return now().getDate(); + } + + /** + * Validates the given components of a date and time value. + * + * The allow ranges for the components are: + * year: 1 - 9999 + * month: 1 - 12 + * day: 1 - daysInMonth(month) + * hour: 0 - 23 + * minute: 0 - 59 + * second: 0 - 59 + * millisecond: 0 - 999 + * + * @return true if the components are valid, false otherwise. + */ + static bool validate( int32 year, int32 month, int32 day, int32 hour, int32 minute, int32 second, int32 millisecond ); + +public: + + /** + * Gets the hash for the specified date and time. + * + * @param dateTime The date and time to get the hash for. + * @return Hash value. + */ + size_t getHash() + { + return std::hash()(this->_ticks); + } + +protected: + + /** Holds the days per month in a non-leap year. */ + static const int32 DaysPerMonth[]; + + /** Holds the cumulative days per month in a non-leap year. */ + static const int32 DaysToMonth[]; + +private: + + /** Holds the ticks in 100 nanoseconds resolution since January 1, 0001 A.D. */ + int64 _ticks; +}; + + +NS_FK_END + + +#endif // LOSEMYMIND_DATETIME_H + + diff --git a/VIServer/Classes/FoundationKit/Base/MathContent.h b/VIServer/Classes/FoundationKit/Base/MathContent.h new file mode 100644 index 0000000000..85c453e9ed --- /dev/null +++ b/VIServer/Classes/FoundationKit/Base/MathContent.h @@ -0,0 +1,80 @@ +#ifndef LOSEMYMIND_MATHCONTENT_H +#define LOSEMYMIND_MATHCONTENT_H +#pragma once +#include +#include +#include "FoundationKit/GenericPlatformMacros.h" + +#define MATH_PIOVER2 1.57079632679489661923f +#define MATH_PIOVER4 0.785398163397448309616f +#define MATH_EPSILON 0.000001f + +NS_FK_BEGIN + +namespace MathEx +{ + /// A few useful constants + const int MaxInt = (std::numeric_limits::max)(); + const double MaxDouble = (std::numeric_limits::max)(); + const double MinDouble = (std::numeric_limits::min)(); + const float MaxFloat = (std::numeric_limits::max)(); + const float MinFloat = (std::numeric_limits::min)(); + + const float SmailFloat = 1.0e-37f; + const float Tolerance = 2e-37f; + + /// Represents the log base ten of e(0.4342945). + const float Log10E = 0.4342945f; + + /// Represents the log base two of e(1.442695). + const float Log2E = 1.442695f; + + /// A tiny floating point value. + const float Epsilon = 1.4013e-045f; + + /// Represents the mathematical constant e(2.71828175). + const float ExponentialE = 2.71828f; + + /// The golden ratio. Oooooh! + const float GoldenRatio = 1.61803f; + + /// Grad-to-degrees conversion constant. + const float Grad2Deg = 0.9f; + + /// Degrees-to-grad conversion constant. + const float Deg2Grad = 1.1111111f; + + /// Radians-to-degrees conversion constant. + const float Rad2Deg = 57.29577951f; + + /// Degrees-to-radians conversion constant. + const float Deg2Rad = 0.0174532925f; + + /// Radians-to-grad conversion constant. + const float Rad2Grad = 63.6619772f; + + /// Grad-to-radians conversion constant. + const float Grad2Rad = 0.015708f; + + /// A representation of positive infinity. + const float Infinity = MaxFloat;// 1.0f / 0.0f; + + /// A representation of negative infinity. + const float NegativeInfinity = MinFloat;// -1.0f / 0.0f; + + /// The infamous 3.14159265358979... value. + const float PI = 3.14159f; + const double TwoPi = PI * 2; + const double HalfPi = PI / 2; + const double QuarterPi = PI / 4; + +} + + +NS_FK_END + +#endif // LOSEMYMIND_MATHCONTENT_H + + + + diff --git a/VIServer/Classes/FoundationKit/Base/MathEx.cpp b/VIServer/Classes/FoundationKit/Base/MathEx.cpp new file mode 100644 index 0000000000..967ebcee3f --- /dev/null +++ b/VIServer/Classes/FoundationKit/Base/MathEx.cpp @@ -0,0 +1,46 @@ +/**************************************************************************** + Copyright (c) 2015 libo All rights reserved. + + losemymind.libo@gmail.com + + ****************************************************************************/ + +#include "MathEx.h" +NS_FK_BEGIN + +namespace MathEx +{ + +int nextPowerOfTwo( int val ) +{ + if (val < 0) + return 0; + val |= val >> 1; + val |= val >> 2; + val |= val >> 4; + val |= val >> 8; + val |= val >> 16; + return val + 1; +} + +int closestPowerOfTwo( int val ) +{ + int b = nextPowerOfTwo(val); + int c = b / 2; + return val - c < b - val ? c : b; +} + +double standardDeviation( const std::vector& vec ) +{ + double sd = 0.0; + double dAverage = average(vec); + for (unsigned int i=0; i < vec.size(); ++i) + { + sd +=(vec[i]- dAverage)*(vec[i] - dAverage); + } + sd = sd / vec.size(); + return sqrt(sd); +} + +} // namespace MathEx +NS_FK_END \ No newline at end of file diff --git a/VIServer/Classes/FoundationKit/Base/MathEx.h b/VIServer/Classes/FoundationKit/Base/MathEx.h new file mode 100644 index 0000000000..7accb843b3 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Base/MathEx.h @@ -0,0 +1,363 @@ +/**************************************************************************** + Copyright (c) 2015 libo All rights reserved. + + losemymind.libo@gmail.com +****************************************************************************/ + +// https://github.com/mosra/magnum/tree/master/src/Magnum/Math + + +#ifndef LOSEMYMIND_MATHEX_H +#define LOSEMYMIND_MATHEX_H +#pragma once +#include +#include +#include +#include +#include "FoundationKit/GenericPlatformMacros.h" +#include "FoundationKit/Base/MathContent.h" + +NS_FK_BEGIN + +/// Provides constants and static methods for trigonometric, +/// logarithmic and other common mathematical functions. +namespace MathEx +{ + + /// returns the maximum of two values + template< typename T > + FORCEINLINE typename std::enable_if< std::is_arithmetic::value, T >::type + max(T v1, T v2) + { + return v1 > v2 ? v1 : v2; + } + + /// returns the minimum of two values + template ::value, T>::type > + FORCEINLINE T min(T v1, T v2) + { + return v1 < v2 ? v1 : v2; + } + + /// Returns the absolute value of val. + template< typename T> + FORCEINLINE T abs(T val, typename std::enable_if< std::is_arithmetic::value>::type* = nullptr) + { + return std::abs(val); + } + + /// Returns the arc-cosine of val - the angle in radians whose cosine is val. + template< typename T > + FORCEINLINE typename std::enable_if< std::is_arithmetic::value, T >::type + acos(T val) + { + return std::acos(val); + } + + /// Returns the arc-sine of val - the angle in radians whose sine is val. + template< typename T > + FORCEINLINE typename std::enable_if< std::is_arithmetic::value, T >::type + asin(const T val) + { + return std::asin(val); + } + + /// Returns the arc-tangent of val - the angle in radians whose tangent is val. + template< typename T > + FORCEINLINE typename std::enable_if< std::is_arithmetic::value, T >::type + atan(const T val) + { + return std::atan(val); + } + + /// Returns the angle in radians whose Tan is y/x. + template< typename T > + FORCEINLINE typename std::enable_if< std::is_arithmetic::value, T >::type + atan2(const T y, const T x) + { + return std::atan2(y, x); + } + + /// Returns the smallest integer greater to or equal to val. + template< typename T > + FORCEINLINE typename std::enable_if< std::is_arithmetic::value, T >::type + ceil(const T val) + { + return std::ceil(val); + } + + /// Returns the smallest integer greater to or equal to val. + template< typename T > + FORCEINLINE int ceilToInt(const T val, typename std::enable_if< std::is_arithmetic::value >::type* = nullptr) + { + return static_cast(std::ceil(val)); + } + + /// Returns the largest integer smaller to or equal to val. + template< typename T > + FORCEINLINE typename std::enable_if< std::is_arithmetic::value, T >::type + floor(T val) + { + return std::floor(val); + } + + /// Returns the largest integer smaller to or equal to val. + template< typename T > + FORCEINLINE int floorToInt(T val, typename std::enable_if< std::is_arithmetic::value >::type* = nullptr) + { + return static_cast(std::floor(val)); + } + + /// Clamps val value between a minimum and maximum value. + template< typename T> + FORCEINLINE typename std::enable_if< std::is_arithmetic::value, T >::type + clamp(T val, T minVal, T maxVal) + { + return std::min(std::max(val, minVal), maxVal); + } + + /// Clamps value between 0 and 1 and returns value. + template< typename T> + FORCEINLINE typename std::enable_if< std::is_arithmetic::value, T >::type + clamp01(T val) + { + return std::min(std::max(val, 0), 1); + } + + /// Returns the cosine of angle f in radians. + template< typename T > + FORCEINLINE typename std::enable_if< std::is_arithmetic::value, T >::type + cos(T val) + { + return std::cos(val); + } + + /// Returns e raised to the specified power. + template< typename T > + FORCEINLINE typename std::enable_if< std::is_arithmetic::value, T >::type + exp(T power) + { + return std::exp(power); + } + + /// Returns the natural (base e) logarithm of val specified value. + template< typename T > + FORCEINLINE typename std::enable_if< std::is_arithmetic::value, T >::type + log(T val) + { + return std::log(val); + } + + /// Returns the base 10 logarithm of val specified value. + template< typename T > + FORCEINLINE typename std::enable_if< std::is_arithmetic::value, T >::type + log10(T val0) + { + return std::log10(val0); + } + + + /// Returns the sign of val. + template + FORCEINLINE typename std::enable_if< std::is_arithmetic::value, T >::type + sign(T val) + { + return (val >(T)0) ? (T)1 : ((val < (T)0) ? (T)-1 : (T)0); + } + + /// Returns the sine of angle val in radians. + template + FORCEINLINE typename std::enable_if< std::is_arithmetic::value, T >::type + sin(T val) + { + return std::sin(val); + } + + /// Returns square root of val. + template + FORCEINLINE typename std::enable_if< std::is_arithmetic::value, T >::type + sqrt(T val) + { + return std::sqrt(val); + } + + /// Returns the tangent of angle val in radians. + template + FORCEINLINE typename std::enable_if< std::is_arithmetic::value, T >::type + tan(T val) + { + return std::tan(val); + } + + /// Returns f raised to power p. + template< typename T, typename U > + FORCEINLINE T pow(T f, U p, + typename std::enable_if< std::is_arithmetic::value >::type* = nullptr, + typename std::enable_if< std::is_arithmetic::value >::type* = nullptr) + { + return std::pow(f, p); + } + + /** + * Compares two values if they are similar. + * Due to floating point imprecision it is not + * recommended to compare floats using the equal + * operator. eg. 1.0 == 10.0 / 10.0 might not return true. + */ + template< typename T1, typename T2 > + FORCEINLINE bool approximately(const T1 a, const T2 b, + typename std::enable_if< std::is_arithmetic::value >::type* = nullptr, + typename std::enable_if< std::is_arithmetic::value >::type* = nullptr) + { + return roughlyEqual(a, b, 0.1f); + } + + /// Interpolates between from and to by t. t is clamped between 0 and 1. + template< typename T, typename U, typename V> + FORCEINLINE float Lerp(T from, U to, V t, + typename std::enable_if< std::is_arithmetic::value >::type* = nullptr, + typename std::enable_if< std::is_arithmetic::value >::type* = nullptr, + typename std::enable_if< std::is_arithmetic::value >::type* = nullptr) + { + return t >= 1 ? to : t < 0 ? from : from + (to - from) * t; + } + + /** + * Compares two floating point values if they are similar. + * @param[in] v1 First value. + * @param[in] v2 Second value. + * @param[in] threshold The threshold of similarity + * @return True if the values are similar, otherwise false. + */ + template< typename T, typename U, typename V> + FORCEINLINE bool roughlyEqual(const T v1, const U v2, const V threshold = 0.01f) + { + return std::abs(v1 - v2) <= threshold; + } + + /// Returns f rounded to the nearest integer. + template + FORCEINLINE typename std::enable_if< std::is_arithmetic::value, T >::type + round(T val) + { +#if TARGET_PLATFORM == PLATFORM_ANDROID + return (val > T(0)) ? std::floor(val + T(0.5)) : std::ceil(val - T(0.5)); +#else + return std::round(val); +#endif + } + + FORCEINLINE bool equal(const float& v1, const float& v2) + { + return (std::fabs(v1 - v2) < 1E-12); + } + + FORCEINLINE bool equal(const double& v1, const double& v2) + { + return (std::fabs(v1 - v2) < 1E-12); + } + + template< typename T > + FORCEINLINE bool fuzzyEqual(T v1, T v2, T var) + { + return(v1 - var <= v2 && v2 <= v1 + var); + } + + /// Return true if the parameter is equal to zero + FORCEINLINE bool isZero(double val) + { + return ((-MinDouble < val) && (val < MinDouble)); + } + + /// Returns if the value is powered by two. + FORCEINLINE bool isPowerOfTwo(int val) + { + return (val > 0) && ((val & (val - 1)) == 0); + } + + FORCEINLINE double sigmoid(double input, double response = 1.0) + { + return (1.0 / (1.0 + exp(-input / response))); + } + + // return true is the third parameter is in the range described by the first two + template< typename T, typename U, typename V> + FORCEINLINE bool inRange(T start, U end, V val) + { + if (start < end) + { + return ((val > start) && (val < end)); + } + else + { + return ((val < start) && (val > end)); + } + } + + + /** Converts radians to degrees. + * This method uses double precission internally, + * though it returns single float + * Factor = 180 / pi + * @param[in] radians The angle in radians. + * @return The angle in degrees. + */ + FORCEINLINE float radiansToDegrees(float radians) + { + return static_cast(radians * 57.295779513082320876798154814105); + } + + /** Converts degrees to radians. + * This method uses double precission internally, + * though it returns single float + * Factor = pi / 180 + * @param[in] degrees The angle in degrees. + * @return The angle in radians. + */ + FORCEINLINE float degreesToRadians(float degrees) + { + return static_cast(degrees * 0.017453292519943295769236907684886); + } + + template + double average(const std::vector& vec, + typename std::enable_if< std::is_arithmetic::value >::type* = nullptr) + { + double dAverage = 0.0; + for (auto& i : vec ) + { + dAverage += static_cast(i); + } + return dAverage / static_cast(vec.size()); + } + + /// Get the next power of two after val value. + int nextPowerOfTwo(int val); + + /// Returns the closest power of two to val value. + int closestPowerOfTwo(int val); + + double standardDeviation(const std::vector& vec); + +} // namespace Math + +NS_FK_END + +#endif // LOSEMYMIND_MATHEX_H + + + + + + + + + + + + + + + + + diff --git a/VIServer/Classes/FoundationKit/Base/TimeEx.cpp b/VIServer/Classes/FoundationKit/Base/TimeEx.cpp new file mode 100644 index 0000000000..2df2d3657a --- /dev/null +++ b/VIServer/Classes/FoundationKit/Base/TimeEx.cpp @@ -0,0 +1,172 @@ +/**************************************************************************** +Copyright (c) 2016 libo All rights reserved. + +losemymind.libo@gmail.com + +****************************************************************************/ +#include "TimeEx.h" +NS_FK_BEGIN + + Time::Time() + : m_TimeDuration() + { + + } + + Time::Time(const Time & t) + : m_TimeDuration(t.m_TimeDuration) + { + + } + + Time::Time(Time && t) + : m_TimeDuration(t.m_TimeDuration) + { + + } + + Time::Time(const std::chrono::high_resolution_clock::time_point& timePoint) + : m_TimeDuration(timePoint.time_since_epoch()) + { + + } + + Time::~Time() + { + + } + + Time & Time::operator=(const Time & t) + { + m_TimeDuration = t.m_TimeDuration; + return * this; + } + + Time & Time::operator=(Time && t) + { + m_TimeDuration = t.m_TimeDuration; + return * this; + } + + Time & Time::operator+=(const Time & t) + { + m_TimeDuration += t.m_TimeDuration; + return * this; + } + + Time & Time::operator-=(const Time & t) + { + m_TimeDuration -= t.m_TimeDuration; + return * this; + } + + Time & Time::operator*=(const std::chrono::high_resolution_clock::duration::rep & t) + { + m_TimeDuration *= t; + return * this; + } + + Time & Time::operator/=(const std::chrono::high_resolution_clock::duration::rep & t) + { + m_TimeDuration /= t; + return * this; + } + + Time & Time::operator%=(const std::chrono::high_resolution_clock::duration::rep & t) + { + m_TimeDuration %= t; + return * this; + } + + Time & Time::operator%=(const Time & t) + { + m_TimeDuration %= t.m_TimeDuration; + return * this; + } + + Time Time::operator+(const Time & t) const + { + Time time(*this); + time += t; + return time; + } + + Time Time::operator-(const Time & t) const + { + Time time(*this); + time -= t; + return time; + } + + Time & Time::operator++() + { + ++m_TimeDuration; + return * this; + } + + Time Time::operator++(int32) + { + Time time(*this); + time.m_TimeDuration++; + return time; + } + + Time & Time::operator--() + { + --m_TimeDuration; + return * this; + } + + Time Time::operator--(int32) + { + Time time(*this); + time.m_TimeDuration--; + return time; + } + + double Time::hours() const + { + //return (std::chrono::duration_cast (m_TimeDuration).count()); + return (std::chrono::duration_cast (m_TimeDuration).count()); + } + + double Time::minutes() const + { + //return (std::chrono::duration_cast (m_TimeDuration).count()); + return (std::chrono::duration_cast (m_TimeDuration).count()); + } + + double Time::seconds() const + { + //return (std::chrono::duration_cast (m_TimeDuration).count()); + return (std::chrono::duration_cast (m_TimeDuration).count()); + } + + double Time::milliseconds() const + { + //return (std::chrono::duration_cast (m_TimeDuration).count()); + return (std::chrono::duration_cast (m_TimeDuration).count()); + } + + double Time::microseconds() const + { + //return (std::chrono::duration_cast (m_TimeDuration).count()); + return (std::chrono::duration_cast (m_TimeDuration).count()); + } + + double Time::nanoseconds() const + { + //return (std::chrono::duration_cast (m_TimeDuration).count()); + return (std::chrono::duration_cast (m_TimeDuration).count()); + } + + Time Time::now() + { + return Time(std::chrono::high_resolution_clock::now()); + } + +NS_FK_END + + + + diff --git a/VIServer/Classes/FoundationKit/Base/TimeEx.h b/VIServer/Classes/FoundationKit/Base/TimeEx.h new file mode 100644 index 0000000000..fc814e2afa --- /dev/null +++ b/VIServer/Classes/FoundationKit/Base/TimeEx.h @@ -0,0 +1,63 @@ +/**************************************************************************** +Copyright (c) 2016 libo All rights reserved. + +losemymind.libo@gmail.com + +****************************************************************************/ +#ifndef LOSEMYMIND_TIME_H +#define LOSEMYMIND_TIME_H + +#pragma once +#include "FoundationKit/GenericPlatformMacros.h" +#include "FoundationKit/Base/Types.h" +#include +NS_FK_BEGIN + +typedef std::chrono::duration nanoseconds_f; +typedef std::chrono::duration microseconds_f; +typedef std::chrono::duration milliseconds_f; +typedef std::chrono::duration seconds_f; +typedef std::chrono::duration > minutes_f; +typedef std::chrono::duration > hours_f; + +class Time final +{ +public: + Time(); + Time(const Time & t); + Time(Time && t); + Time(const std::chrono::high_resolution_clock::time_point& timePoint); + + ~Time(); + + static Time now(); + Time & operator=(const Time & t); + Time & operator=(Time && t); + Time & operator+=(const Time & t); + Time & operator-=(const Time & t); + Time & operator*=(const std::chrono::high_resolution_clock::duration::rep & t); + Time & operator/=(const std::chrono::high_resolution_clock::duration::rep & t); + Time & operator%=(const std::chrono::high_resolution_clock::duration::rep & t); + Time & operator%=(const Time & t); + Time & operator++(); + Time & operator--(); + Time operator+(const Time & t) const; + Time operator-(const Time & t) const; + Time operator++(int32 t); + Time operator--(int32 t); + double hours() const; + double minutes() const; + double seconds() const; + double milliseconds() const; + double microseconds() const; + double nanoseconds() const; +private: + std::chrono::high_resolution_clock::duration m_TimeDuration; + +}; + +NS_FK_END + + + +#endif // LOSEMYMIND_TIME_H diff --git a/VIServer/Classes/FoundationKit/Base/Timer.h b/VIServer/Classes/FoundationKit/Base/Timer.h new file mode 100644 index 0000000000..2be492dbc9 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Base/Timer.h @@ -0,0 +1,63 @@ +#pragma once +#include +#include "FoundationKit/GenericPlatformMacros.h" +#include "FoundationKit/Base/TimeEx.h" +NS_FK_BEGIN + +class Timer +{ +public: + typedef std::chrono::high_resolution_clock clock_type; + Timer() : _begin(clock_type::now()){} + + void reset() + { + _begin = clock_type::now(); + } + + double nanoseconds()const + { + return elapsed(); + } + + double microseconds()const + { + return elapsed(); + } + + double milliseconds()const + { + return elapsed(); + } + + double seconds()const + { + return elapsed(); + } + + double minutes()const + { + return elapsed(); + } + + double hours()const + { + return elapsed(); + } + + double days() + { + return elapsed< std::chrono::duration >>(); + } +protected: + template + double elapsed()const + { + return std::chrono::duration_cast(clock_type::now() - _begin).count(); + } +private: + //std::chrono::time_point _begin; + clock_type::time_point _begin; +}; + +NS_FK_END \ No newline at end of file diff --git a/VIServer/Classes/FoundationKit/Base/Timespan.cpp b/VIServer/Classes/FoundationKit/Base/Timespan.cpp new file mode 100644 index 0000000000..98e06935fa --- /dev/null +++ b/VIServer/Classes/FoundationKit/Base/Timespan.cpp @@ -0,0 +1,135 @@ +/**************************************************************************** +Copyright (c) 2016 libo All rights reserved. + +losemymind.libo@gmail.com + +****************************************************************************/ +#include +#include "FoundationKit/Foundation/StringUtils.h" +#include "FoundationKit/Base/MathEx.h" +#include "Timespan.h" + +NS_FK_BEGIN + +std::string Timespan::toString() const +{ + if (getDays() == 0) + { + return toString("%n%h:%m:%s.%f"); + } + + return toString("%n%d.%h:%m:%s.%f"); +} + + +std::string Timespan::toString( const char* format ) const +{ + std::string result; + + while (*format != '\0') + { + if ((*format == '%') && (*++format != '\0')) + { + switch (*format) + { + case 'n': if (_ticks < 0) result += '-'; break; + case 'N': result += (_ticks < 0) ? '-' : '+'; break; + case 'd': result += StringUtils::format("%i", MathEx::abs(getDays())); break; + case 'h': result += StringUtils::format("%02i", MathEx::abs(getHours())); break; + case 'm': result += StringUtils::format("%02i", MathEx::abs(getMinutes())); break; + case 's': result += StringUtils::format("%02i", MathEx::abs(getSeconds())); break; + case 'f': result += StringUtils::format("%03i", MathEx::abs(getMilliseconds())); break; + case 'D': result += StringUtils::format("%f", MathEx::abs(getTotalDays())); break; + case 'H': result += StringUtils::format("%f", MathEx::abs(getTotalHours())); break; + case 'M': result += StringUtils::format("%f", MathEx::abs(getTotalMinutes())); break; + case 'S': result += StringUtils::format("%f", MathEx::abs(getTotalSeconds())); break; + case 'F': result += StringUtils::format("%f", MathEx::abs(getTotalMilliseconds())); break; + default: + result += *format; + } + } + else + { + result += *format; + } + + ++format; + } + + return result; +} + + +/* Timespan static interface + *****************************************************************************/ + +Timespan Timespan::fromDays( double days ) +{ + LOG_ASSERT((days >= minValue().getTotalDays()) && (days <= maxValue().getTotalDays()), "The days param invalid."); + return Timespan(static_cast(days * ETimespan::TicksPerDay)); +} + +Timespan Timespan::fromHours( double hours ) +{ + LOG_ASSERT((hours >= minValue().getTotalHours()) && (hours <= maxValue().getTotalHours()), "The hours param invalid."); + return Timespan(static_cast(hours * ETimespan::TicksPerHour)); +} + +Timespan Timespan::fromMinutes(double minutes) +{ + LOG_ASSERT((minutes >= minValue().getTotalMinutes()) && (minutes <= maxValue().getTotalMinutes()), "The minutes param invalid."); + return Timespan(static_cast(minutes * ETimespan::TicksPerMinute)); +} + +Timespan Timespan::fromSeconds(double seconds) +{ + LOG_ASSERT((seconds >= minValue().getTotalSeconds()) && (seconds <= maxValue().getTotalSeconds()), "The seconds param invalid."); + return Timespan(static_cast(seconds * ETimespan::TicksPerSecond)); +} + +Timespan Timespan::fromMilliseconds( double milliseconds ) +{ + LOG_ASSERT((milliseconds >= minValue().getTotalMilliseconds()) && (milliseconds <= maxValue().getTotalMilliseconds()), "The milliseconds param invalid."); + return Timespan(static_cast(milliseconds * ETimespan::TicksPerMillisecond)); +} + + +bool Timespan::parse( const std::string& timespanString, Timespan& outTimespan ) +{ + // @todo gmp: implement stricter Timespan parsing; this implementation is too forgiving. + std::string tokenString = timespanString; + std::replace(tokenString.begin(), tokenString.end(), '.', ':'); + bool Negative = (tokenString[0] == '-'); + std::replace(tokenString.begin(), tokenString.end(), '-', ':'); + + std::vector tokens; + StringUtils::split(tokenString, ':', tokens); + + + if (tokens.size() == 4) + { + tokens.insert(tokens.begin(), "0"); + } + + if (tokens.size() == 5) + { + outTimespan.assign(std::atoi(tokens[0].c_str()), std::atoi(tokens[1].c_str()), std::atoi(tokens[2].c_str()), std::atoi(tokens[3].c_str()), std::atoi(tokens[4].c_str())); + if (Negative) + { + outTimespan._ticks *= -1; + } + return true; + } + return false; +} + + +void Timespan::assign( int32 days, int32 hours, int32 minutes, int32 seconds, int32 milliseconds ) +{ + int64 totalms = 1000 * (60 * 60 * 24 * (int64)days + 60 * 60 * (int64)hours + 60 * (int64)minutes + (int64)seconds) + (int64)milliseconds; + LOG_ASSERT((totalms >= minValue().getTotalMilliseconds()) && (totalms <= maxValue().getTotalMilliseconds()), "Total millisecond is invalid."); + _ticks = totalms * ETimespan::TicksPerMillisecond; +} + +NS_FK_END + diff --git a/VIServer/Classes/FoundationKit/Base/Timespan.h b/VIServer/Classes/FoundationKit/Base/Timespan.h new file mode 100644 index 0000000000..99e1f1dea4 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Base/Timespan.h @@ -0,0 +1,567 @@ +/**************************************************************************** +Copyright (c) 2016 libo All rights reserved. + +losemymind.libo@gmail.com + +****************************************************************************/ + +#ifndef LOSEMYMIND_TIMESPAN_H +#define LOSEMYMIND_TIMESPAN_H +#pragma once + +#include +#include +#include +#include "FoundationKit/GenericPlatformMacros.h" +#include "FoundationKit/Base/Types.h" + +NS_FK_BEGIN + +namespace ETimespan +{ + /** The number of timespan ticks per millisecond. */ + const int64 TicksPerMillisecond = 10000; + /** The number of timespan ticks per second. */ + const int64 TicksPerSecond = 10000000; + /** The number of timespan ticks per minute. */ + const int64 TicksPerMinute = 600000000; + /** The number of timespan ticks per hour. */ + const int64 TicksPerHour = 36000000000; + /** The number of timespan ticks per day. */ + const int64 TicksPerDay = 864000000000; + /** The number of timespan ticks per week. */ + const int64 TicksPerWeek = 6048000000000; +} + + +/** + * Implements a time span. + * + * A time span is the difference between two dates and times. For example, the time span between + * 12:00:00 January 1, 2000 and 18:00:00 January 2, 2000 is 30.0 hours. Time spans are measured in + * positive or negative ticks depending on whether the difference is measured forward or backward. + * Each tick has a resolution of 0.1 microseconds (= 100 nanoseconds). + * + * In conjunction with the companion class FDateTime, time spans can be used to perform date and time + * based arithmetic, such as calculating the difference between two dates or adding a certain amount + * of time to a given date. + * + * @see DateTime + */ +class Timespan +{ +public: + + /** Default constructor (no initialization). */ + Timespan() { } + + /** + * Creates and initializes a new time interval with the specified number of ticks. + * + * @param inTicks The number of ticks. + */ + explicit Timespan(int64 inTicks) + : _ticks(inTicks) + { } + + /** + * Creates and initializes a new time interval with the specified number of hours, minutes and seconds. + * + * @param hours The hours component. + * @param minutes The minutes component. + * @param seconds The seconds component. + */ + Timespan(int32 hours, int32 minutes, int32 seconds) + { + assign(0, hours, minutes, seconds, 0); + } + + /** + * Creates and initializes a new time interval with the specified number of days, hours, minutes and seconds. + * + * @param days The days component. + * @param hours The hours component. + * @param minutes The minutes component. + * @param seconds The seconds component. + */ + Timespan(int32 days, int32 hours, int32 minutes, int32 seconds) + { + assign(days, hours, minutes, seconds, 0); + } + + /** + * Creates and initializes a new time interval with the specified number of days, hours, minutes and seconds. + * + * @param days The days component. + * @param hours The hours component. + * @param minutes The minutes component. + * @param seconds The seconds component. + * @param milliseconds The milliseconds component. + */ + Timespan(int32 days, int32 hours, int32 minutes, int32 seconds, int32 milliseconds) + { + assign(days, hours, minutes, seconds, milliseconds); + } + +public: + + /** + * Returns result of adding the given time span to this time span. + * + * @return A time span whose value is the sum of this time span and the given time span. + */ + Timespan operator+(const Timespan& other) const + { + return Timespan(_ticks + other._ticks); + } + + /** + * Adds the given time span to this time span. + * + * @return This time span. + */ + Timespan& operator+=(const Timespan& other) + { + _ticks += other._ticks; + return *this; + } + + /** + * Returns the inverse of this time span. + * + * The value of this time span must be greater than Timespan::MinValue(), or else an overflow will occur. + * + * @return Inverse of this time span. + */ + Timespan operator-() const + { + return Timespan(-_ticks); + } + + /** + * Returns the result of subtracting the given time span from this time span. + * + * @param Other The time span to compare with. + * @return A time span whose value is the difference of this time span and the given time span. + */ + Timespan operator-(const Timespan& other) const + { + return Timespan(_ticks - other._ticks); + } + + /** + * Subtracts the given time span from this time span. + * + * @param Other The time span to subtract. + * @return This time span. + */ + Timespan& operator-=(const Timespan& other) + { + _ticks -= other._ticks; + return *this; + } + + /** + * Returns the result of multiplying the this time span with the given scalar. + * + * @param Scalar The scalar to multiply with. + * @return A time span whose value is the product of this time span and the given scalar. + */ + Timespan operator*(float scalar) const + { + return Timespan(static_cast(_ticks * scalar)); + } + + /** + * Multiplies this time span with the given scalar. + * + * @param Scalar The scalar to multiply with. + * @return This time span. + */ + Timespan& operator*=(float scalar) + { + _ticks = (int64)(_ticks * scalar); + return *this; + } + + /** + * Compares this time span with the given time span for equality. + * + * @param Other The time span to compare with. + * @return true if the time spans are equal, false otherwise. + */ + bool operator==(const Timespan& other) const + { + return (_ticks == other._ticks); + } + + /** + * Compares this time span with the given time span for inequality. + * + * @param Other The time span to compare with. + * @return true if the time spans are not equal, false otherwise. + */ + bool operator!=(const Timespan& other) const + { + return (_ticks != other._ticks); + } + + /** + * Checks whether this time span is greater than the given time span. + * + * @param Other The time span to compare with. + * @return true if this time span is greater, false otherwise. + */ + bool operator>(const Timespan& other) const + { + return (_ticks > other._ticks); + } + + /** + * Checks whether this time span is greater than or equal to the given time span. + * + * @param Other The time span to compare with. + * @return true if this time span is greater or equal, false otherwise. + */ + bool operator>=(const Timespan& other) const + { + return (_ticks >= other._ticks); + } + + /** + * Checks whether this time span is less than the given time span. + * + * @param Other The time span to compare with. + * @return true if this time span is less, false otherwise. + */ + bool operator<(const Timespan& other) const + { + return (_ticks < other._ticks); + } + + /** + * Checks whether this time span is less than or equal to the given time span. + * + * @param Other The time span to compare with. + * @return true if this time span is less or equal, false otherwise. + */ + bool operator<=( const Timespan& other ) const + { + return (_ticks <= other._ticks); + } + +public: + + /** + * Returns a time span with the absolute value of this time span. + * + * This method may overflow the timespan if its value is equal to MinValue. + * + * @return Duration of this time span. + * @see minValue + */ + Timespan getDuration() + { + return Timespan(_ticks >= 0 ? _ticks : -_ticks); + } + + /** + * Gets the days component of this time span. + * + * @return Days component. + */ + int32 getDays() const + { + return static_cast(_ticks / ETimespan::TicksPerDay); + } + + /** + * Gets the hours component of this time span. + * + * @return Hours component. + * @see getTotalHours + */ + int32 getHours() const + { + return static_cast((_ticks / ETimespan::TicksPerHour) % 24); + } + + /** + * Gets the minutes component of this time span. + * + * @return Minutes component. + * @see getTotalMinutes + */ + int32 getMinutes() const + { + return static_cast((_ticks / ETimespan::TicksPerMinute) % 60); + } + + /** + * Gets the seconds component of this time span. + * + * @return Seconds component. + * @see getTotalSeconds + */ + int32 getSeconds() const + { + return static_cast((_ticks / ETimespan::TicksPerSecond) % 60); + } + + /** + * Gets the milliseconds component of this time span. + * + * @return Milliseconds component. + * @see getTotalMilliseconds + */ + int32 getMilliseconds() const + { + return static_cast((_ticks / ETimespan::TicksPerMillisecond) % 1000); + } + + /** + * Gets the number of ticks represented by this time span. + * + * @return Number of ticks. + */ + int64 getTicks() const + { + return _ticks; + } + + /** + * Gets the total number of days represented by this time span. + * + * @return Number of days. + * @see getDays + */ + double getTotalDays() const + { + return static_cast(_ticks / ETimespan::TicksPerDay); + } + + /** + * Gets the total number of hours represented by this time span. + * + * @return Number of hours. + * @see getHours + */ + double getTotalHours() const + { + return static_cast(_ticks / ETimespan::TicksPerHour); + } + + /** + * Gets the total number of milliseconds represented by this time span. + * + * @return Number of milliseconds. + * @see getMilliseconds + */ + double getTotalMilliseconds() const + { + return static_cast(_ticks / ETimespan::TicksPerMillisecond); + } + + /** + * Gets the total number of minutes represented by this time span. + * + * @return Number of minutes. + * @see getMinutes + */ + double getTotalMinutes() const + { + return static_cast(_ticks / ETimespan::TicksPerMinute); + } + + /** + * Gets the total number of seconds represented by this time span. + * + * @return Number of seconds. + * @see getSeconds + */ + double getTotalSeconds() const + { + return static_cast(_ticks / ETimespan::TicksPerSecond); + } + + /** + * Returns the string representation of this time span using a default format. + * + * The returned string has the following format: + * [-][d.]hh:mm:ss.fff + * + * @return String representation. + * @see parse + */ + std::string toString() const; + + /** + * Converts this time span to its string representation. + * + * The following formatting codes are available: + * %n - prints the minus sign (for negative time spans only) + * %N - prints the minus or plus sign (always) + * %d - prints the time span's days part + * %h - prints the time span's hours part (0..23) + * %m - prints the time span's minutes part (0..59) + * %s - prints the time span's seconds part (0..59) + * %f - prints the time span's milliseconds part (0..999) + * %D - prints the total number of days (without minus sign) + * %H - prints the total number of hours (without minus sign) + * %M - prints the total number of minutes (without minus sign) + * %S - prints the total number of seconds (without minus sign) + * %F - prints the total number of milliseconds (without minus sign) + * + * @param Format - The format of the returned string. + * @return String representation. + * @see parse + */ + std::string toString( const char* format ) const; + +public: + + /** + * Creates a time span that represents the specified number of days. + * + * @param Days The number of days. + * @return Time span. + * @see fromHours, fromMilliseconds, fromMinutes, fromSeconds + */ + static Timespan fromDays( double days ); + + /** + * Creates a time span that represents the specified number of hours. + * + * @param Hours The number of hours. + * @return Time span. + * @see fromDays, fromMilliseconds, fromMinutes, fromSeconds + */ + static Timespan fromHours( double hours ); + + /** + * Creates a time span that represents the specified number of minutes. + * + * @param Minutes The number of minutes. + * @return Time span. + * @see fromDays, fromHours, fromMilliseconds, fromSeconds + */ + static Timespan fromMinutes(double minutes); + + /** + * Creates a time span that represents the specified number of seconds. + * + * @param Seconds The number of seconds. + * @return Time span. + * @see fromDays, fromHours, fromMilliseconds, fromMinutes + */ + static Timespan fromSeconds(double seconds); + + /** + * Creates a time span that represents the specified number of milliseconds. + * + * @param Milliseconds The number of milliseconds. + * @return Time span. + * @see fromDays, fromHours, fromMinutes, fromSeconds + */ + static Timespan fromMilliseconds( double milliseconds ); + + /** + * Returns the maximum time span value. + * + * The maximum time span value is slightly more than 10,675,199 days. + * + * @return Maximum time span. + * @see minValue,Zero + */ + static Timespan maxValue() + { + return Timespan(9223372036854775807); + } + + /** + * Returns the minimum time span value. + * + * The minimum time span value is slightly less than -10,675,199 days. + * + * @return Minimum time span. + * @see maxValue, zeroValue + */ + static Timespan minValue() + { + return Timespan(-9223372036854775807 - 1); + } + + /** + * Converts a string to a time span. + * + * Currently, the string must be in the format written by Timespan.ToString(). + * Other formats are not supported at this time. + * + * @param TimespanString The string to convert. + * @param OutTimespan Will contain the parsed time span. + * @return true if the string was converted successfully, false otherwise. + * @see ToString + */ + static bool parse( const std::string& timespanString, Timespan& outTimespan ); + + /** + * Returns the zero time span value. + * + * The zero time span value can be used in comparison operations with other time spans. + * + * @return Zero time span. + * @see MaxValue, MinValue + */ + static Timespan zero() + { + return Timespan(0); + } + + /** + * Gets the hash for the specified time span. + * + * @param Timespan The timespan to get the hash for. + * @return Hash value. + */ + size_t getHash() + { + return std::hash()(this->_ticks); + } + +protected: + + /** + * Assigns the specified components to this time span. + * + * @param days The days component. + * @param hours The hours component. + * @param minutes The minutes component. + * @param seconds The seconds component. + * @param milliseconds The milliseconds component. + */ + void assign( int32 days, int32 hours, int32 minutes, int32 seconds, int32 milliseconds ); + +private: + + /** Holds the time span in 100 nanoseconds resolution. */ + int64 _ticks; +}; + + +/** + * Pre-multiplies a time span with the given scalar. + * + * @param Scalar The scalar to pre-multiply with. + * @param Timespan The time span to multiply. + */ +inline Timespan operator*( float scalar, const Timespan& timespan ) +{ + return timespan.operator*(scalar); +} + + +NS_FK_END + + + +#endif // LOSEMYMIND_TIMESPAN_H diff --git a/VIServer/Classes/FoundationKit/Base/Types.h b/VIServer/Classes/FoundationKit/Base/Types.h new file mode 100644 index 0000000000..c685339e80 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Base/Types.h @@ -0,0 +1,84 @@ +/**************************************************************************** + Copyright (c) 2015 libo All rights reserved. + + losemymind.libo@gmail.com + + ****************************************************************************/ + +#ifndef LOSEMYMIND_TYPES_H +#define LOSEMYMIND_TYPES_H +#pragma once + +#include +#include "FoundationKit/GenericPlatformMacros.h" + +NS_FK_BEGIN + +//--------------------------------------------------------------------- +// Utility for automatically setting up the pointer-sized integer type +// http://zh.cppreference.com/w/cpp/language/types +//--------------------------------------------------------------------- + +template +struct SelectIntPointerType +{ + // nothing here are is it an error if the partial specializations fail +}; + +template +struct SelectIntPointerType +{ + typedef T64BITS type; // select the 64 bit type +}; + +template +struct SelectIntPointerType +{ + typedef T32BITS type; // select the 32 bit type +}; + + +// Unsigned base types. +typedef unsigned char uint8; // 8-bit unsigned. +typedef unsigned short int uint16; // 16-bit unsigned. +typedef unsigned int uint32; // 32-bit unsigned. +typedef unsigned long long uint64; // 64-bit unsigned. + +// Signed base types. +typedef signed char int8; // 8-bit signed. +typedef signed short int int16; // 16-bit signed. +typedef signed int int32; // 32-bit signed. +typedef signed long long int64; // 64-bit signed. + +typedef float float32; // 32-bit signed. +typedef double float64; // 64-bit signed. +typedef long double float128; // 128-bit signed. + +// Character types. +typedef char ANSICHAR; // An ANSI character - 8-bit fixed-width representation of 7-bit characters. +typedef wchar_t WIDECHAR; // A wide character - In-memory only. ?-bit fixed-width representation of the platform's natural wide character set. Could be different sizes on different platforms. +typedef uint8 CHAR8; // An 8-bit character type - In-memory only. 8-bit representation. Should really be char8_t but making this the generic option is easier for compilers which don't fully support C++11 yet (i.e. MSVC). +typedef uint16 CHAR16; // A 16-bit character type - In-memory only. 16-bit representation. Should really be char16_t but making this the generic option is easier for compilers which don't fully support C++11 yet (i.e. MSVC). +typedef uint32 CHAR32; // A 32-bit character type - In-memory only. 32-bit representation. Should really be char32_t but making this the generic option is easier for compilers which don't fully support C++11 yet (i.e. MSVC). +typedef WIDECHAR TCHAR; // A switchable character - In-memory only. Either ANSICHAR or WIDECHAR, depending on a licensee's requirements. + +typedef SelectIntPointerType::type UPTRINT; // unsigned int the same size as a pointer +typedef SelectIntPointerType::type PTRINT; // signed int the same size as a pointer + +typedef UPTRINT address; + +typedef std::basic_string, std::allocator > ustring; + +template +struct allocator_traits +{ + typedef std::allocator<_Ty> type; +}; + +template +using allocator_traits_t = typename allocator_traits<_Ty>::type; + +NS_FK_END +#endif // LOSEMYMIND_TYPES_H + + diff --git a/VIServer/Classes/FoundationKit/Base/noncopyable.hpp b/VIServer/Classes/FoundationKit/Base/noncopyable.hpp new file mode 100644 index 0000000000..6ce2701f26 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Base/noncopyable.hpp @@ -0,0 +1,41 @@ +/**************************************************************************** + Copyright (c) 2015 libo All rights reserved. + + losemymind.libo@gmail.com + +****************************************************************************/ +#ifndef LOSEMYMIND_NONCOPYABLE_H +#define LOSEMYMIND_NONCOPYABLE_H + +#pragma once +#include "FoundationKit/GenericPlatformMacros.h" + +NS_FK_BEGIN +// Private copy constructor and copy assignment ensure classes derived from +// class noncopyable cannot be copied. + +// Contributed by libo + +namespace noncopyable_ // protection from unintended ADL +{ + class noncopyable + { + protected: + constexpr noncopyable() = default; + ~noncopyable() = default; + noncopyable(const noncopyable&) = delete; + noncopyable& operator=(const noncopyable&) = delete; + }; +} + +typedef noncopyable_::noncopyable noncopyable; + +NS_FK_END +#endif // LOSEMYMIND_NONCOPYABLE_H + + + + + + + diff --git a/VIServer/Classes/FoundationKit/Crypto/Base64.cpp b/VIServer/Classes/FoundationKit/Crypto/Base64.cpp new file mode 100644 index 0000000000..db66cb7746 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Crypto/Base64.cpp @@ -0,0 +1,256 @@ + +#include "Base64.h" + +NS_FK_BEGIN + +/** The table used to encode a 6 bit value as an ascii character */ +uint8 Base64::EncodingAlphabet[64] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', + 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', + 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; + +/** The table used to convert an ascii character into a 6 bit value */ +uint8 Base64::DecodingAlphabet[256] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x3E, 0xFF, 0xFF, 0xFF, 0x3F, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, + 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, + 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, + 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + + +Base64::Base64() +{ + +} + +/** + * Encodes the source into a Base64 string + * + * @param Source the binary payload to stringify + * @param Length the length of the payload that needs encoding + * + * @return the stringified form of the binary data + */ +std::string Base64::encode(const uint8* source, uint32 length) +{ + // Each 3 uint8 set of data expands to 4 bytes and must be padded to 4 bytes + uint32 expectedLength = (length + 2) / 3 * 4; + std::string outBuffer; + outBuffer.reserve(expectedLength); + + char encodedBytes[5]; + // Null terminate this so we can append it easily as a string + encodedBytes[4] = 0; + // Loop through the buffer converting 3 bytes of binary data at a time + while (length >= 3) + { + uint8 A = *source++; + uint8 B = *source++; + uint8 C = *source++; + length -= 3; + // The algorithm takes 24 bits of data (3 bytes) and breaks it into 4 6bit chunks represented as ascii + uint32 byteTriplet = A << 16 | B << 8 | C; + // Use the 6bit block to find the representation ascii character for it + encodedBytes[3] = EncodingAlphabet[byteTriplet & 0x3F]; + // Shift each time to get the next 6 bit chunk + byteTriplet >>= 6; + encodedBytes[2] = EncodingAlphabet[byteTriplet & 0x3F]; + byteTriplet >>= 6; + encodedBytes[1] = EncodingAlphabet[byteTriplet & 0x3F]; + byteTriplet >>= 6; + encodedBytes[0] = EncodingAlphabet[byteTriplet & 0x3F]; + // Now we can append this buffer to our destination string + outBuffer += encodedBytes; + } + // Since this algorithm operates on blocks, we may need to pad the last chunks + if (length > 0) + { + uint8 A = *source++; + uint8 B = 0; + uint8 C = 0; + // Grab the second character if it is a 2 uint8 finish + if (length == 2) + { + B = *source; + } + uint32 byteTriplet = A << 16 | B << 8 | C; + // Pad with = to make a 4 uint8 chunk + encodedBytes[3] = '='; + byteTriplet >>= 6; + // If there's only one 1 uint8 left in the source, then you need 2 pad chars + if (length == 1) + { + encodedBytes[2] = '='; + } + else + { + encodedBytes[2] = EncodingAlphabet[byteTriplet & 0x3F]; + } + // Now encode the remaining bits the same way + byteTriplet >>= 6; + encodedBytes[1] = EncodingAlphabet[byteTriplet & 0x3F]; + byteTriplet >>= 6; + encodedBytes[0] = EncodingAlphabet[byteTriplet & 0x3F]; + outBuffer += encodedBytes; + } + return outBuffer; +} + +/** + * Decodes a Base64 string into an array of bytes + * + * @param source the stringified data to convert + * @param length the length of the buffer being converted + * @param dest the out buffer that will be filled with the decoded data + * @param padCount the out count of the padding on the orignal buffer (0 to 2) + * + * @return true if the buffer was decoded, false if it failed to decode + */ +bool Base64::decode(const char* source, uint32 length, uint8* dest, uint32& padCount) +{ + padCount = 0; + uint8 DecodedValues[4]; + while (length) + { + // Decode the next 4 BYTEs + for (int32 Index = 0; Index < 4; Index++) + { + // Tell the caller if there were any pad bytes + if (*source == '=') + { + padCount++; + } + DecodedValues[Index] = DecodingAlphabet[(int32)(*source++)]; + // Abort on values that we don't understand + if (DecodedValues[Index] == 0xFF) + { + return false; + } + } + length -= 4; + // Rebuild the original 3 bytes from the 4 chunks of 6 bits + uint32 OriginalTriplet = DecodedValues[0]; + OriginalTriplet <<= 6; + OriginalTriplet |= DecodedValues[1]; + OriginalTriplet <<= 6; + OriginalTriplet |= DecodedValues[2]; + OriginalTriplet <<= 6; + OriginalTriplet |= DecodedValues[3]; + // Now we can tear the uint32 into bytes + dest[2] = OriginalTriplet & 0xFF; + OriginalTriplet >>= 8; + dest[1] = OriginalTriplet & 0xFF; + OriginalTriplet >>= 8; + dest[0] = OriginalTriplet & 0xFF; + dest += 3; + } + return true; +} + + + +/** + * Encodes a binary uint8 array into a Base64 string + * + * @param source the binary data to convert + * + * @return a string that encodes the binary data in a way that can be safely transmitted via various Internet protocols + */ +std::string Base64::encode(const ustring& source) +{ + return encode(source.c_str(), static_cast(source.size())); +} + +/** + * Decodes a Base64 string into an array of bytes + * + * @param source the stringified data to convert + * @param dest the out buffer that will be filled with the decoded data + * + * @return true if the buffer was decoded, false if it failed to decode + */ +bool Base64::decode(const std::string& source, ustring& dest) +{ + uint32 length = static_cast(source.length()); + // Size must be a multiple of 4 + if (length % 4) + { + return false; + } + // Each 4 uint8 chunk of characters is 3 bytes of data + uint32 expectedLength = length / 4 * 3; + // Add the number we need for output + dest.assign(expectedLength,0x00); + uint8* buffer = dest.get_allocator().address(dest.front()); + uint32 padCount = 0; + bool bWasSuccessful = decode(source.c_str(), length, buffer, padCount); + if (bWasSuccessful) + { + if (padCount > 0) + { + dest.erase(expectedLength - padCount, padCount); + } + } + return bWasSuccessful; +} + +/** + * Encodes a std::string into a Base64 string + * + * @param source the string data to convert + * + * @return a string that encodes the binary data in a way that can be safely transmitted via various Internet protocols + */ +std::string Base64::encode(const std::string& source) +{ + return encode(reinterpret_cast(source.c_str()), static_cast(source.size())); +} + +/** + * Decodes a Base64 string into a std::string + * + * @param source the stringified data to convert + * @param dest the out buffer that will be filled with the decoded data + */ +bool Base64::decode(const std::string& source, std::string& dest) +{ + uint32 length = static_cast(source.size()); + // Size must be a multiple of 4 + if (length % 4) + { + return false; + } + // Each 4 uint8 chunk of characters is 3 bytes of data + uint32 expectedLength = length / 4 * 3; + dest.assign(expectedLength,0x00); + uint8* buffer = reinterpret_cast(dest.get_allocator().address(dest.front())); + uint32 padCount = 0; + bool bWasSuccessful = decode(source.c_str(), length, buffer, padCount); + if (bWasSuccessful) + { + if (padCount > 0) + { + buffer[expectedLength - padCount] = 0; + } + else + { + dest.push_back('\0'); + } + } + return bWasSuccessful; +} + +NS_FK_END + + diff --git a/VIServer/Classes/FoundationKit/Crypto/Base64.h b/VIServer/Classes/FoundationKit/Crypto/Base64.h new file mode 100644 index 0000000000..f543fa38d1 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Crypto/Base64.h @@ -0,0 +1,93 @@ +#ifndef LOSEMYMIND_BASE64_H +#define LOSEMYMIND_BASE64_H +#pragma once +#include +#include +#include "FoundationKit/Base/Types.h" + +NS_FK_BEGIN + + /** + * Class for encoding/decoding Base64 data (RFC 4648) + */ +class Base64 +{ + /** + * Base64 supports encoding any 3 uint8 chunk of binary data into a 4 uint8 set of characters from the alphabet below + */ + static uint8 EncodingAlphabet[64]; + + /** + * Used to do a reverse look up from the encoded alphabet to the original 6 bit value + */ + static uint8 DecodingAlphabet[256]; + + /** Ctor hidden on purpose, use static methods only */ + Base64(); + + /** + * Encodes the source into a Base64 string + * + * @param source the binary payload to stringify + * @param length the length of the payload that needs encoding + * + * @return the stringified form of the binary data + */ + static std::string encode(const uint8* source, uint32 length); + + /** + * Decodes a Base64 string into an array of bytes + * + * @param source the stringified data to convert + * @param length the length of the buffer being converted + * @param dest the out buffer that will be filled with the decoded data + * @param padCount the out count of the padding on the orignal buffer (0 to 2) + * + * @return TRUE if the buffer was decoded, FALSE if it failed to decode + */ + static bool decode(const char* source, uint32 length, uint8* dest, uint32& padCount); + +public: + + /** + * Encodes a binary uint8 array into a Base64 string + * + * @param source the binary data to convert + * + * @return a string that encodes the binary data in a way that can be safely transmitted via various Internet protocols + */ + static std::string encode(const ustring& source); + + /** + * Decodes a Base64 string into an array of bytes + * + * @param source the stringified data to convert + * @param dest the out buffer that will be filled with the decoded data + */ + static bool decode(const std::string& source, ustring& dest); + + /** + * Encodes a std::string into a Base64 string + * + * @param source the string data to convert + * + * @return a string that encodes the binary data in a way that can be safely transmitted via various Internet protocols + */ + static std::string encode(const std::string& source); + + /** + * Decodes a Base64 string into a std::string + * + * @param source the stringified data to convert + * @param dest the out buffer that will be filled with the decoded data + */ + static bool decode(const std::string& source, std::string& dest); +}; + +NS_FK_END + +#endif // LOSEMYMIND_BASE64_H + + + + diff --git a/VIServer/Classes/FoundationKit/Crypto/aes.cpp b/VIServer/Classes/FoundationKit/Crypto/aes.cpp new file mode 100644 index 0000000000..86d22f48f6 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Crypto/aes.cpp @@ -0,0 +1,1375 @@ +/********************************************************************************* + + Copyright 2006-2009 MakingThings + + Licensed under the Apache License, + Version 2.0 (the "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + 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 "aes.h" +#include + +NS_FK_BEGIN + +static int aesSetupEncrypt( unsigned long* rk, const unsigned char* key, int keybits); +static int aesSetupDecrypt( unsigned long *rk, const unsigned char *key, int keybits); +static void aesDoEncrypt( const unsigned long *rk, int nrounds, + const unsigned char plaintext[16], unsigned char ciphertext[16]); +static void aesDoDecrypt( const unsigned long *rk, int nrounds, + const unsigned char ciphertext[16], unsigned char plaintext[16]); + +#define FULL_UNROLL + +typedef unsigned long u32; +typedef unsigned char u8; + +/** + * -defgroup AES AES + * Encrypt and decrypt data using AES (Advanced Encryption Standard). + * + * AES is a block cipher adopted for use by the NSA (US government agency). According to Wikipedia, + * "This marks the first time the public has had access to a cipher approved by the NSA for + * top secret information." Pretty cool, right? This is a good way to send info privately + * from your Make Controller over the network, to a web server for example. + * + * AES requires that both sides of communication have access to the same key. So both your Make + * Controller, and whatever other device it's communicating with need to know about the same + * password so they can decrypt data that has been encrypted by the other. + * + * There are several different flavors of AES. There are two main ways in which AES libraries + * differ: + * - the way they chain blocks + * - the way they pad data + * + * This library uses ECB (Electronic Code Book) chaining, and pads data with a character + * that corresponds to the number of bytes needed to pad to 16. Check the Wikipedia article + * for an explanation - http://en.wikipedia.org/wiki/Advanced_Encryption_Standard + * + * The lookup tables used in this library will use somewhere between 8 and 13 kB of program space, + * depending on the compiler optimization you use. Memory usage is pretty minimal. + * + * Code is used and adapted from Philip J. Erdelsky - see http://www.efgh.com/software/rijndael.htm + * for the original. + * -ingroup dataformats + */ + +static const u32 Te0[256] = +{ + 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, + 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, + 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, + 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, + 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, + 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, + 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, + 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, + 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, + 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, + 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, + 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, + 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, + 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, + 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, + 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, + 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, + 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, + 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, + 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, + 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, + 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, + 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, + 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, + 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, + 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, + 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, + 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, + 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, + 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, + 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, + 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, + 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, + 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, + 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, + 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, + 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, + 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, + 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, + 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, + 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, + 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, + 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, + 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, + 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, + 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, + 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, + 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, + 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, + 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, + 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, + 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, + 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, + 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, + 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, + 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, + 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, + 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, + 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, + 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, + 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, + 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, + 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, + 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, +}; + +static const u32 Te1[256] = +{ + 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, + 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, + 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, + 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, + 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, + 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, + 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, + 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, + 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, + 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, + 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, + 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, + 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, + 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, + 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, + 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, + 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, + 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, + 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, + 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, + 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, + 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, + 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, + 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, + 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, + 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, + 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, + 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, + 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, + 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, + 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, + 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, + 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, + 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, + 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, + 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, + 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, + 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, + 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, + 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, + 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, + 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, + 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, + 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, + 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, + 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, + 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, + 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, + 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, + 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, + 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, + 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, + 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, + 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, + 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, + 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, + 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, + 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, + 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, + 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, + 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, + 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, + 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, + 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, +}; + +static const u32 Te2[256] = +{ + 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, + 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, + 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, + 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, + 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, + 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, + 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, + 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, + 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, + 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, + 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, + 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, + 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, + 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, + 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, + 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, + 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, + 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, + 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, + 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, + 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, + 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, + 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, + 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, + 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, + 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, + 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, + 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, + 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, + 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, + 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, + 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, + 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, + 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, + 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, + 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, + 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, + 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, + 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, + 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, + 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, + 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, + 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, + 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, + 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, + 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, + 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, + 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, + 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, + 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, + 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, + 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, + 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, + 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, + 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, + 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, + 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, + 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, + 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, + 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, + 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, + 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, + 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, + 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, +}; + +static const u32 Te3[256] = +{ + 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, + 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, + 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, + 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, + 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, + 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, + 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, + 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, + 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, + 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, + 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, + 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, + 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, + 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, + 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, + 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, + 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, + 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, + 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, + 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, + 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, + 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, + 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, + 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, + 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, + 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, + 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, + 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, + 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, + 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, + 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, + 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, + 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, + 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, + 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, + 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, + 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, + 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, + 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, + 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, + 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, + 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, + 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, + 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, + 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, + 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, + 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, + 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, + 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, + 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, + 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, + 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, + 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, + 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, + 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, + 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, + 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, + 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, + 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, + 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, + 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, + 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, + 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, + 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, +}; + +static const u32 Te4[256] = +{ + 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, + 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, + 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, + 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, + 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, + 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, + 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, + 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, + 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, + 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, + 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, + 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, + 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, + 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, + 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, + 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, + 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, + 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, + 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, + 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, + 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, + 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, + 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, + 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, + 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, + 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, + 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, + 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, + 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, + 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, + 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, + 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, + 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, + 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, + 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, + 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, + 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, + 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, + 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, + 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, + 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, + 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, + 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, + 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, + 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, + 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, + 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, + 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, + 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, + 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, + 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, + 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, + 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, + 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, + 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, + 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, + 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, + 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, + 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, + 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, + 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, + 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, + 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, + 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, +}; + +static const u32 Td0[256] = +{ + 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, + 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, + 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, + 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, + 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, + 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, + 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, + 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, + 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, + 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, + 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, + 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, + 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, + 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, + 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, + 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, + 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, + 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, + 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, + 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, + 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, + 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, + 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, + 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, + 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, + 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, + 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, + 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, + 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, + 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, + 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, + 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, + 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, + 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, + 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, + 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, + 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, + 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, + 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, + 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, + 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, + 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, + 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, + 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, + 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, + 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, + 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, + 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, + 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, + 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, + 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, + 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, + 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, + 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, + 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, + 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, + 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, + 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, + 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, + 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, + 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, + 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, + 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, + 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, +}; + +static const u32 Td1[256] = +{ + 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, + 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, + 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, + 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, + 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, + 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, + 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, + 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, + 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, + 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, + 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, + 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, + 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, + 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, + 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, + 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, + 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, + 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, + 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, + 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, + 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, + 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, + 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, + 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, + 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, + 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, + 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, + 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, + 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, + 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, + 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, + 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, + 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, + 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, + 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, + 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, + 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, + 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, + 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, + 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, + 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, + 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, + 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, + 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, + 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, + 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, + 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, + 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, + 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, + 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, + 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, + 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, + 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, + 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, + 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, + 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, + 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, + 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, + 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, + 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, + 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, + 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, + 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, + 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, +}; + +static const u32 Td2[256] = +{ + 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, + 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, + 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, + 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, + 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, + 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, + 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, + 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, + 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, + 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, + 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, + 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, + 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, + 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, + 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, + 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, + 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, + 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, + 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, + 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, + 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, + 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, + 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, + 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, + 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, + 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, + 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, + 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, + 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, + 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, + 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, + 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, + 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, + 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, + 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, + 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, + 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, + 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, + 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, + 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, + 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, + 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, + 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, + 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, + 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, + 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, + 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, + 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, + 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, + 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, + 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, + 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, + 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, + 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, + 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, + 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, + 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, + 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, + 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, + 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, + 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, + 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, + 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, + 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, +}; + +static const u32 Td3[256] = +{ + 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, + 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, + 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, + 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, + 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, + 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, + 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, + 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, + 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, + 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, + 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, + 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, + 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, + 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, + 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, + 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, + 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, + 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, + 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, + 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, + 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, + 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, + 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, + 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, + 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, + 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, + 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, + 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, + 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, + 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, + 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, + 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, + 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, + 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, + 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, + 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, + 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, + 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, + 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, + 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, + 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, + 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, + 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, + 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, + 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, + 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, + 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, + 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, + 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, + 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, + 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, + 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, + 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, + 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, + 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, + 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, + 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, + 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, + 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, + 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, + 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, + 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, + 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, + 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, +}; + +static const u32 Td4[256] = +{ + 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, + 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, + 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, + 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, + 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, + 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, + 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, + 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, + 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, + 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, + 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, + 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, + 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, + 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, + 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, + 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, + 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, + 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, + 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, + 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, + 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, + 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, + 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, + 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, + 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, + 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, + 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, + 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, + 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, + 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, + 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, + 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, + 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, + 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, + 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, + 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, + 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, + 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, + 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, + 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, + 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, + 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, + 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, + 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, + 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, + 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, + 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, + 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, + 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, + 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, + 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, + 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, + 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, + 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, + 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, + 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, + 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, + 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, + 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, + 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, + 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, + 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, + 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, + 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU, +}; + +static const u32 rcon[] = +{ + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x1B000000, 0x36000000, + /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; + +#define GETU32(plaintext) (((u32)(plaintext)[0] << 24) ^ \ + ((u32)(plaintext)[1] << 16) ^ \ + ((u32)(plaintext)[2] << 8) ^ \ + ((u32)(plaintext)[3])) + +#define PUTU32(ciphertext, st) { (ciphertext)[0] = (u8)((st) >> 24); \ + (ciphertext)[1] = (u8)((st) >> 16); \ + (ciphertext)[2] = (u8)((st) >> 8); \ + (ciphertext)[3] = (u8)(st); } + +/* + * Expand the cipher key into the encryption key schedule. + * + * @return the number of rounds for the given cipher key size. + */ +// static +int aesSetupEncrypt(u32 *rk, const u8 *key, int keybits) +{ + int i = 0; + u32 temp; + + rk[0] = GETU32(key ); + rk[1] = GETU32(key + 4); + rk[2] = GETU32(key + 8); + rk[3] = GETU32(key + 12); + if (keybits == 128) + { + for (;;) + { + temp = rk[3]; + rk[4] = rk[0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + if (++i == 10) + return 10; + rk += 4; + } + } + rk[4] = GETU32(key + 16); + rk[5] = GETU32(key + 20); + if (keybits == 192) + { + for (;;) + { + temp = rk[ 5]; + rk[ 6] = rk[ 0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[ 7] = rk[ 1] ^ rk[ 6]; + rk[ 8] = rk[ 2] ^ rk[ 7]; + rk[ 9] = rk[ 3] ^ rk[ 8]; + if (++i == 8) + return 12; + rk[10] = rk[ 4] ^ rk[ 9]; + rk[11] = rk[ 5] ^ rk[10]; + rk += 6; + } + } + rk[6] = GETU32(key + 24); + rk[7] = GETU32(key + 28); + if (keybits == 256) + { + for (;;) + { + temp = rk[ 7]; + rk[ 8] = rk[ 0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[ 9] = rk[ 1] ^ rk[ 8]; + rk[10] = rk[ 2] ^ rk[ 9]; + rk[11] = rk[ 3] ^ rk[10]; + if (++i == 7) + return 14; + temp = rk[11]; + rk[12] = rk[ 4] ^ + (Te4[(temp >> 24) ] & 0xff000000) ^ + (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(temp ) & 0xff] & 0x000000ff); + rk[13] = rk[ 5] ^ rk[12]; + rk[14] = rk[ 6] ^ rk[13]; + rk[15] = rk[ 7] ^ rk[14]; + rk += 8; + } + } + return 0; +} + +/* + * Expand the cipher key into the decryption key schedule. + * + * @return the number of rounds for the given cipher key size. + */ +int aesSetupDecrypt(u32 *rk, const u8 *key, int keybits) +{ + + int nrounds = 0; + + /* expand the cipher key: */ + nrounds = aesSetupEncrypt(rk, key, keybits); + + u32 tmpSwap = 0; + /* invert the order of the round keys: */ + for (int i = 0, j = 4*nrounds; i < j; i += 4, j -= 4) + { + tmpSwap = rk[i ]; rk[i ] = rk[j ]; rk[j ] = tmpSwap; + tmpSwap = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = tmpSwap; + tmpSwap = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = tmpSwap; + tmpSwap = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = tmpSwap; + } + /* apply the inverse MixColumn transform to all round keys but the first and the last: */ + for (int i = 1; i < nrounds; i++) + { + rk += 4; + rk[0] = + Td0[Te4[(rk[0] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[0] ) & 0xff] & 0xff]; + rk[1] = + Td0[Te4[(rk[1] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[1] ) & 0xff] & 0xff]; + rk[2] = + Td0[Te4[(rk[2] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[2] ) & 0xff] & 0xff]; + rk[3] = + Td0[Te4[(rk[3] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[3] ) & 0xff] & 0xff]; + } + return nrounds; +} + +/* + * Expand the cipher key into the decryption key schedule. + * + * @return the number of rounds for the given cipher key size. + */ +void aesDoEncrypt(const u32 *rk, int nrounds, const u8 plaintext[16], u8 ciphertext[16]) +{ + u32 s0, s1, s2, s3, t0, t1, t2, t3; + #ifndef FULL_UNROLL + int r; + #endif /* ?FULL_UNROLL */ + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(plaintext ) ^ rk[0]; + s1 = GETU32(plaintext + 4) ^ rk[1]; + s2 = GETU32(plaintext + 8) ^ rk[2]; + s3 = GETU32(plaintext + 12) ^ rk[3]; + #ifdef FULL_UNROLL + /* round 1: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7]; + /* round 2: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; + if (nrounds > 10) + { + /* round 10: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47]; + if (nrounds > 12) + { + /* round 12: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55]; + } + } + rk += nrounds << 2; + #else /* !FULL_UNROLL */ + /* + * nrounds - 1 full rounds: + */ + r = nrounds >> 1; + for (;;) + { + t0 = + Te0[(s0 >> 24) ] ^ + Te1[(s1 >> 16) & 0xff] ^ + Te2[(s2 >> 8) & 0xff] ^ + Te3[(s3 ) & 0xff] ^ + rk[4]; + t1 = + Te0[(s1 >> 24) ] ^ + Te1[(s2 >> 16) & 0xff] ^ + Te2[(s3 >> 8) & 0xff] ^ + Te3[(s0 ) & 0xff] ^ + rk[5]; + t2 = + Te0[(s2 >> 24) ] ^ + Te1[(s3 >> 16) & 0xff] ^ + Te2[(s0 >> 8) & 0xff] ^ + Te3[(s1 ) & 0xff] ^ + rk[6]; + t3 = + Te0[(s3 >> 24) ] ^ + Te1[(s0 >> 16) & 0xff] ^ + Te2[(s1 >> 8) & 0xff] ^ + Te3[(s2 ) & 0xff] ^ + rk[7]; + rk += 8; + if (--r == 0) + break; + s0 = + Te0[(t0 >> 24) ] ^ + Te1[(t1 >> 16) & 0xff] ^ + Te2[(t2 >> 8) & 0xff] ^ + Te3[(t3 ) & 0xff] ^ + rk[0]; + s1 = + Te0[(t1 >> 24) ] ^ + Te1[(t2 >> 16) & 0xff] ^ + Te2[(t3 >> 8) & 0xff] ^ + Te3[(t0 ) & 0xff] ^ + rk[1]; + s2 = + Te0[(t2 >> 24) ] ^ + Te1[(t3 >> 16) & 0xff] ^ + Te2[(t0 >> 8) & 0xff] ^ + Te3[(t1 ) & 0xff] ^ + rk[2]; + s3 = + Te0[(t3 >> 24) ] ^ + Te1[(t0 >> 16) & 0xff] ^ + Te2[(t1 >> 8) & 0xff] ^ + Te3[(t2 ) & 0xff] ^ + rk[3]; + } + #endif /* ?FULL_UNROLL */ + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Te4[(t0 >> 24) ] & 0xff000000) ^ + (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t3 ) & 0xff] & 0x000000ff) ^ + rk[0]; + PUTU32(ciphertext , s0); + s1 = + (Te4[(t1 >> 24) ] & 0xff000000) ^ + (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t0 ) & 0xff] & 0x000000ff) ^ + rk[1]; + PUTU32(ciphertext + 4, s1); + s2 = + (Te4[(t2 >> 24) ] & 0xff000000) ^ + (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t1 ) & 0xff] & 0x000000ff) ^ + rk[2]; + PUTU32(ciphertext + 8, s2); + s3 = + (Te4[(t3 >> 24) ] & 0xff000000) ^ + (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t2 ) & 0xff] & 0x000000ff) ^ + rk[3]; + PUTU32(ciphertext + 12, s3); +} + +void aesDoDecrypt(const u32 *rk, int nrounds, const u8 ciphertext[16], + u8 plaintext[16]) +{ + u32 s0, s1, s2, s3, t0, t1, t2, t3; + #ifndef FULL_UNROLL + int r; + #endif /* ?FULL_UNROLL */ + + /** + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(ciphertext ) ^ rk[0]; + s1 = GETU32(ciphertext + 4) ^ rk[1]; + s2 = GETU32(ciphertext + 8) ^ rk[2]; + s3 = GETU32(ciphertext + 12) ^ rk[3]; + #ifdef FULL_UNROLL + /* round 1: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7]; + /* round 2: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39]; + if (nrounds > 10) + { + /* round 10: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47]; + if (nrounds > 12) + { + /* round 12: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55]; + } + } + rk += nrounds << 2; + #else /* !FULL_UNROLL */ + /* + * nrounds - 1 full rounds: + */ + r = nrounds >> 1; + for (;;) + { + t0 = + Td0[(s0 >> 24) ] ^ + Td1[(s3 >> 16) & 0xff] ^ + Td2[(s2 >> 8) & 0xff] ^ + Td3[(s1 ) & 0xff] ^ + rk[4]; + t1 = + Td0[(s1 >> 24) ] ^ + Td1[(s0 >> 16) & 0xff] ^ + Td2[(s3 >> 8) & 0xff] ^ + Td3[(s2 ) & 0xff] ^ + rk[5]; + t2 = + Td0[(s2 >> 24) ] ^ + Td1[(s1 >> 16) & 0xff] ^ + Td2[(s0 >> 8) & 0xff] ^ + Td3[(s3 ) & 0xff] ^ + rk[6]; + t3 = + Td0[(s3 >> 24) ] ^ + Td1[(s2 >> 16) & 0xff] ^ + Td2[(s1 >> 8) & 0xff] ^ + Td3[(s0 ) & 0xff] ^ + rk[7]; + rk += 8; + if (--r == 0) + break; + s0 = + Td0[(t0 >> 24) ] ^ + Td1[(t3 >> 16) & 0xff] ^ + Td2[(t2 >> 8) & 0xff] ^ + Td3[(t1 ) & 0xff] ^ + rk[0]; + s1 = + Td0[(t1 >> 24) ] ^ + Td1[(t0 >> 16) & 0xff] ^ + Td2[(t3 >> 8) & 0xff] ^ + Td3[(t2 ) & 0xff] ^ + rk[1]; + s2 = + Td0[(t2 >> 24) ] ^ + Td1[(t1 >> 16) & 0xff] ^ + Td2[(t0 >> 8) & 0xff] ^ + Td3[(t3 ) & 0xff] ^ + rk[2]; + s3 = + Td0[(t3 >> 24) ] ^ + Td1[(t2 >> 16) & 0xff] ^ + Td2[(t1 >> 8) & 0xff] ^ + Td3[(t0 ) & 0xff] ^ + rk[3]; + } + #endif /* ?FULL_UNROLL */ + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Td4[(t0 >> 24) ] & 0xff000000) ^ + (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t1 ) & 0xff] & 0x000000ff) ^ + rk[0]; + PUTU32(plaintext , s0); + s1 = + (Td4[(t1 >> 24) ] & 0xff000000) ^ + (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t2 ) & 0xff] & 0x000000ff) ^ + rk[1]; + PUTU32(plaintext + 4, s1); + s2 = + (Td4[(t2 >> 24) ] & 0xff000000) ^ + (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t3 ) & 0xff] & 0x000000ff) ^ + rk[2]; + PUTU32(plaintext + 8, s2); + s3 = + (Td4[(t3 >> 24) ] & 0xff000000) ^ + (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t0 ) & 0xff] & 0x000000ff) ^ + rk[3]; + PUTU32(plaintext + 12, s3); +} + +#define KEYLENGTH(keybits) ((keybits)/8) +#define RKLENGTH(keybits) ((keybits)/8+28) +#define NROUNDS(keybits) ((keybits)/32+6) + +#define KEYBITS 128 +#define BLOCK_SIZE 16 + + +namespace aes{ + +int aesEncrypt(unsigned char* output, int outlen, unsigned char* input, int inlen, unsigned char* password) +{ + unsigned long rk[RKLENGTH(KEYBITS)]; + unsigned char key[KEYLENGTH(KEYBITS)]; + int nrounds; + int totalout = outlen; + + memcpy(key, password, BLOCK_SIZE); // gotta be 16 coming in + nrounds = aesSetupEncrypt(rk, key, KEYBITS); // initialize the encrypt buffer + while(inlen) { + unsigned char plaintext[BLOCK_SIZE]; + unsigned char ciphertext[BLOCK_SIZE]; + unsigned int j; + // grab bytes from the input and stuff them in plaintext + for(j = 0; j < BLOCK_SIZE; j++) { + if(inlen) { + plaintext[j] = *input++; + inlen--; + } + else + break; + } + + char c = static_cast(BLOCK_SIZE - j); // pad with the character that corresponds to how many bytes we need to pad + unsigned int orig_block_size = j; + for (; j < BLOCK_SIZE; j++) // if we didn't get 16 bytes, pad plaintext + plaintext[j] = c; + aesDoEncrypt(rk, nrounds, plaintext, ciphertext); + if(outlen < BLOCK_SIZE) // not enough room to write out + return -1; + memcpy(output, ciphertext, BLOCK_SIZE); + output += BLOCK_SIZE; + outlen -= BLOCK_SIZE; + + if(orig_block_size == BLOCK_SIZE && inlen == 0) { // the last chunk was 16 bytes. encrypt another round so we know how to decrypt the padding + memset(plaintext, BLOCK_SIZE, BLOCK_SIZE); // pad 16 bytes with the value 16 + aesDoEncrypt(rk, nrounds, plaintext, ciphertext); + if(outlen < BLOCK_SIZE) // not enough room to write out + return -1; + memcpy(output, ciphertext, BLOCK_SIZE); + output += BLOCK_SIZE; + outlen -= BLOCK_SIZE; + } + } + return totalout - outlen; +} + +int aesDecrypt(unsigned char* output, int outlen, unsigned char* input, int inlen, unsigned char* password) +{ + unsigned long rk[RKLENGTH(KEYBITS)]; + unsigned char key[KEYLENGTH(KEYBITS)]; + int nrounds; + int totalout = outlen; + + memcpy(key, password, BLOCK_SIZE); // gotta be 16 coming in + nrounds = aesSetupDecrypt(rk, key, KEYBITS); + while(inlen) { + unsigned char plaintext[BLOCK_SIZE]; + unsigned char ciphertext[BLOCK_SIZE]; + + if(inlen < BLOCK_SIZE) // the ciphered text should be in 16 byte chunks + return -1; + memcpy(ciphertext, input, BLOCK_SIZE); // stuff a block from input in ciphertext + input += BLOCK_SIZE; + inlen -= BLOCK_SIZE; + aesDoDecrypt(rk, nrounds, ciphertext, plaintext); + if(inlen < BLOCK_SIZE) { // we're on our last block. check the padding to determine the size of the original data + int padlen = plaintext[BLOCK_SIZE-1]; // look at the last byte + if(padlen < 1 || padlen > 16) // check for bogus padlen + return -1; + int datalen = BLOCK_SIZE - padlen; + if(outlen < datalen) // not enough room to write out + return -1; + memcpy(output, plaintext, datalen); // stuff only data (no padding) into the output + outlen -= datalen; + } + else { // proceed as normal + if(outlen < BLOCK_SIZE) // not enough room to write out + return -1; + memcpy(output, plaintext, BLOCK_SIZE); // stuff a decrypted block into the output + output += BLOCK_SIZE; + outlen -= BLOCK_SIZE; + } + } + return totalout - outlen; +} + +} // namespace aes + +NS_FK_END + + + + diff --git a/VIServer/Classes/FoundationKit/Crypto/aes.h b/VIServer/Classes/FoundationKit/Crypto/aes.h new file mode 100644 index 0000000000..af0b2b7fb1 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Crypto/aes.h @@ -0,0 +1,79 @@ +/********************************************************************************* + + Copyright 2006-2009 MakingThings + + Licensed under the Apache License, + Version 2.0 (the "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + 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. + +*********************************************************************************/ +#pragma once + +#include "FoundationKit/GenericPlatformMacros.h" // for NS_FK_BEGIN NS_FK_END +NS_FK_BEGIN + +#ifdef __cplusplus +extern "C" { +#endif + +namespace aes{ + +/** + * Encrypt a block of data using AES. + * + * @param[out] output A pointer to the buffer into which the encrypted data will be written. + * @param[out] outlen The maximum number of bytes to write into the output buffer. + * @param[in] input A pointer to the data to be encrypted. + * @param[in] inlen The number of bytes of data to encrypt. + * @param[in] password The password, or key, used to encrypt the data. Must be 16 bytes long. + * @return The number of bytes encrypted, or -1 on failure. + * + * @code + * #define BUFF_SIZE 256 + * unsigned char cipherbuf[BUFF_SIZE]; // the buffer that will be written into + * unsigned char plaintext[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // the text to encrypt + * unsigned char secret[] = "A SECRET PASSWORD"; // 16 bytes long + * int written = aesEncrypt(cipherbuf, BUFF_SIZE, plaintext, 26, secret); + * @endcode + */ +int aesEncrypt(unsigned char* output, int outlen, unsigned char* input, int inlen, unsigned char* password); + +/** + * Decrypt a block of AES encrypted data. + * + * @param[out] output A pointer to the buffer into which the decrypted data will be written. + * @param[out] outlen The maximum number of bytes of data to write into the output buffer. + * @param[in] input A pointer to the encrypted block to be decrytped. + * @param[in] inlen The number of bytes to be decrypted. + * @param[in] password The password, or key, used to encrypt the data. Must be 16 bytes long. + * @return The number of bytes written, or -1 on failure. + * + * @code + * //first encrypt some data, then decrypt it and make sure we get out what we put in + * unsigned char cipherbuf[256]; + * unsigned char plainbuf[256]; + * unsigned char plaintext[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // our plaintext to encrypt + * unsigned char secret[] = "A SECRET PASSWORD"; // 16 bytes long + * + * int written = aesEncrypt(cipherbuf, 256, plaintext, 26, secret); + * written = aesDecrypt(plainbuf, 256, cipherbuf, written, secret); + * //we now have our original plaintext in plainbuf + * @endcode + */ +int aesDecrypt(unsigned char* output, int outlen, unsigned char* input, int inlen, unsigned char* password); + +} //namespace aes + +#ifdef __cplusplus +} +#endif + +NS_FK_END + diff --git a/VIServer/Classes/FoundationKit/Crypto/md5.hpp b/VIServer/Classes/FoundationKit/Crypto/md5.hpp new file mode 100644 index 0000000000..fe51002ed4 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Crypto/md5.hpp @@ -0,0 +1,401 @@ +/**************************************************************************** + Copyright (c) 2013-2014 libo. + + losemymind.libo@gmail.com + +****************************************************************************/ +#pragma once + +/* + * This package supports both compile-time and run-time determination of CPU + * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be + * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is + * defined as non-zero, the code will be compiled to run only on big-endian + * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to + * run on either big- or little-endian CPUs, but will run slightly less + * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. + */ +#include +#include +#include +#include "FoundationKit/GenericPlatformMacros.h" // for NS_FK_BEGIN NS_FK_END + +/// Provides MD5 hashing functionality +NS_FK_BEGIN + +namespace MD5{ + +typedef unsigned char md5_byte_t; /* 8-bit byte */ +typedef unsigned int md5_word_t; /* 32-bit word */ + +/* Define the state of the MD5 Algorithm. */ +typedef struct md5_state_s { + md5_word_t count[2]; /* message length in bits, lsw first */ + md5_word_t abcd[4]; /* digest buffer */ + md5_byte_t buf[64]; /* accumulate block */ +} md5_state_t; + +/* Initialize the algorithm. */ +inline void md5_init(md5_state_t *pms); + +/* Append a string to the message. */ +inline void md5_append(md5_state_t *pms, md5_byte_t const * data, size_t nbytes); + +/* Finish the message and return the digest. */ +inline void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); + +#undef ZSW_MD5_BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ +#ifdef ARCH_IS_BIG_ENDIAN +# define ZSW_MD5_BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) +#else +# define ZSW_MD5_BYTE_ORDER 0 +#endif + +#define ZSW_MD5_T_MASK ((md5_word_t)~0) +#define ZSW_MD5_T1 /* 0xd76aa478 */ (ZSW_MD5_T_MASK ^ 0x28955b87) +#define ZSW_MD5_T2 /* 0xe8c7b756 */ (ZSW_MD5_T_MASK ^ 0x173848a9) +#define ZSW_MD5_T3 0x242070db +#define ZSW_MD5_T4 /* 0xc1bdceee */ (ZSW_MD5_T_MASK ^ 0x3e423111) +#define ZSW_MD5_T5 /* 0xf57c0faf */ (ZSW_MD5_T_MASK ^ 0x0a83f050) +#define ZSW_MD5_T6 0x4787c62a +#define ZSW_MD5_T7 /* 0xa8304613 */ (ZSW_MD5_T_MASK ^ 0x57cfb9ec) +#define ZSW_MD5_T8 /* 0xfd469501 */ (ZSW_MD5_T_MASK ^ 0x02b96afe) +#define ZSW_MD5_T9 0x698098d8 +#define ZSW_MD5_T10 /* 0x8b44f7af */ (ZSW_MD5_T_MASK ^ 0x74bb0850) +#define ZSW_MD5_T11 /* 0xffff5bb1 */ (ZSW_MD5_T_MASK ^ 0x0000a44e) +#define ZSW_MD5_T12 /* 0x895cd7be */ (ZSW_MD5_T_MASK ^ 0x76a32841) +#define ZSW_MD5_T13 0x6b901122 +#define ZSW_MD5_T14 /* 0xfd987193 */ (ZSW_MD5_T_MASK ^ 0x02678e6c) +#define ZSW_MD5_T15 /* 0xa679438e */ (ZSW_MD5_T_MASK ^ 0x5986bc71) +#define ZSW_MD5_T16 0x49b40821 +#define ZSW_MD5_T17 /* 0xf61e2562 */ (ZSW_MD5_T_MASK ^ 0x09e1da9d) +#define ZSW_MD5_T18 /* 0xc040b340 */ (ZSW_MD5_T_MASK ^ 0x3fbf4cbf) +#define ZSW_MD5_T19 0x265e5a51 +#define ZSW_MD5_T20 /* 0xe9b6c7aa */ (ZSW_MD5_T_MASK ^ 0x16493855) +#define ZSW_MD5_T21 /* 0xd62f105d */ (ZSW_MD5_T_MASK ^ 0x29d0efa2) +#define ZSW_MD5_T22 0x02441453 +#define ZSW_MD5_T23 /* 0xd8a1e681 */ (ZSW_MD5_T_MASK ^ 0x275e197e) +#define ZSW_MD5_T24 /* 0xe7d3fbc8 */ (ZSW_MD5_T_MASK ^ 0x182c0437) +#define ZSW_MD5_T25 0x21e1cde6 +#define ZSW_MD5_T26 /* 0xc33707d6 */ (ZSW_MD5_T_MASK ^ 0x3cc8f829) +#define ZSW_MD5_T27 /* 0xf4d50d87 */ (ZSW_MD5_T_MASK ^ 0x0b2af278) +#define ZSW_MD5_T28 0x455a14ed +#define ZSW_MD5_T29 /* 0xa9e3e905 */ (ZSW_MD5_T_MASK ^ 0x561c16fa) +#define ZSW_MD5_T30 /* 0xfcefa3f8 */ (ZSW_MD5_T_MASK ^ 0x03105c07) +#define ZSW_MD5_T31 0x676f02d9 +#define ZSW_MD5_T32 /* 0x8d2a4c8a */ (ZSW_MD5_T_MASK ^ 0x72d5b375) +#define ZSW_MD5_T33 /* 0xfffa3942 */ (ZSW_MD5_T_MASK ^ 0x0005c6bd) +#define ZSW_MD5_T34 /* 0x8771f681 */ (ZSW_MD5_T_MASK ^ 0x788e097e) +#define ZSW_MD5_T35 0x6d9d6122 +#define ZSW_MD5_T36 /* 0xfde5380c */ (ZSW_MD5_T_MASK ^ 0x021ac7f3) +#define ZSW_MD5_T37 /* 0xa4beea44 */ (ZSW_MD5_T_MASK ^ 0x5b4115bb) +#define ZSW_MD5_T38 0x4bdecfa9 +#define ZSW_MD5_T39 /* 0xf6bb4b60 */ (ZSW_MD5_T_MASK ^ 0x0944b49f) +#define ZSW_MD5_T40 /* 0xbebfbc70 */ (ZSW_MD5_T_MASK ^ 0x4140438f) +#define ZSW_MD5_T41 0x289b7ec6 +#define ZSW_MD5_T42 /* 0xeaa127fa */ (ZSW_MD5_T_MASK ^ 0x155ed805) +#define ZSW_MD5_T43 /* 0xd4ef3085 */ (ZSW_MD5_T_MASK ^ 0x2b10cf7a) +#define ZSW_MD5_T44 0x04881d05 +#define ZSW_MD5_T45 /* 0xd9d4d039 */ (ZSW_MD5_T_MASK ^ 0x262b2fc6) +#define ZSW_MD5_T46 /* 0xe6db99e5 */ (ZSW_MD5_T_MASK ^ 0x1924661a) +#define ZSW_MD5_T47 0x1fa27cf8 +#define ZSW_MD5_T48 /* 0xc4ac5665 */ (ZSW_MD5_T_MASK ^ 0x3b53a99a) +#define ZSW_MD5_T49 /* 0xf4292244 */ (ZSW_MD5_T_MASK ^ 0x0bd6ddbb) +#define ZSW_MD5_T50 0x432aff97 +#define ZSW_MD5_T51 /* 0xab9423a7 */ (ZSW_MD5_T_MASK ^ 0x546bdc58) +#define ZSW_MD5_T52 /* 0xfc93a039 */ (ZSW_MD5_T_MASK ^ 0x036c5fc6) +#define ZSW_MD5_T53 0x655b59c3 +#define ZSW_MD5_T54 /* 0x8f0ccc92 */ (ZSW_MD5_T_MASK ^ 0x70f3336d) +#define ZSW_MD5_T55 /* 0xffeff47d */ (ZSW_MD5_T_MASK ^ 0x00100b82) +#define ZSW_MD5_T56 /* 0x85845dd1 */ (ZSW_MD5_T_MASK ^ 0x7a7ba22e) +#define ZSW_MD5_T57 0x6fa87e4f +#define ZSW_MD5_T58 /* 0xfe2ce6e0 */ (ZSW_MD5_T_MASK ^ 0x01d3191f) +#define ZSW_MD5_T59 /* 0xa3014314 */ (ZSW_MD5_T_MASK ^ 0x5cfebceb) +#define ZSW_MD5_T60 0x4e0811a1 +#define ZSW_MD5_T61 /* 0xf7537e82 */ (ZSW_MD5_T_MASK ^ 0x08ac817d) +#define ZSW_MD5_T62 /* 0xbd3af235 */ (ZSW_MD5_T_MASK ^ 0x42c50dca) +#define ZSW_MD5_T63 0x2ad7d2bb +#define ZSW_MD5_T64 /* 0xeb86d391 */ (ZSW_MD5_T_MASK ^ 0x14792c6e) + +static void md5_process(md5_state_t *pms, md5_byte_t const * data /*[64]*/) +{ + md5_word_t + a = pms->abcd[0], b = pms->abcd[1], + c = pms->abcd[2], d = pms->abcd[3]; + md5_word_t t; +#if ZSW_MD5_BYTE_ORDER > 0 + /* Define storage only for big-endian CPUs. */ + md5_word_t X[16]; +#else + /* Define storage for little-endian or both types of CPUs. */ + md5_word_t xbuf[16]; + md5_word_t const * X; +#endif + + { +#if ZSW_MD5_BYTE_ORDER == 0 + /* + * Determine dynamically whether this is a big-endian or + * little-endian machine, since we can use a more efficient + * algorithm on the latter. + */ + static int const w = 1; + + if (*((md5_byte_t const *)&w)) /* dynamic little-endian */ +#endif +#if ZSW_MD5_BYTE_ORDER <= 0 /* little-endian */ + { + /* + * On little-endian machines, we can process properly aligned + * data without copying it. + */ + if (!((data - (md5_byte_t const *)0) & 3)) { + /* data are properly aligned */ + X = (md5_word_t const *)data; + } else { + /* not aligned */ + std::memcpy(xbuf, data, 64); + X = xbuf; + } + } +#endif +#if ZSW_MD5_BYTE_ORDER == 0 + else /* dynamic big-endian */ +#endif +#if ZSW_MD5_BYTE_ORDER >= 0 /* big-endian */ + { + /* + * On big-endian machines, we must arrange the bytes in the + * right order. + */ + const md5_byte_t *xp = data; + int i; + +# if ZSW_MD5_BYTE_ORDER == 0 + X = xbuf; /* (dynamic only) */ +# else +# define xbuf X /* (static only) */ +# endif + for (i = 0; i < 16; ++i, xp += 4) + xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); + } +#endif + } + +#define ZSW_MD5_ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + + /* Round 1. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ +#define ZSW_MD5_F(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + ZSW_MD5_F(b,c,d) + X[k] + Ti;\ + a = ZSW_MD5_ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 7, ZSW_MD5_T1); + SET(d, a, b, c, 1, 12, ZSW_MD5_T2); + SET(c, d, a, b, 2, 17, ZSW_MD5_T3); + SET(b, c, d, a, 3, 22, ZSW_MD5_T4); + SET(a, b, c, d, 4, 7, ZSW_MD5_T5); + SET(d, a, b, c, 5, 12, ZSW_MD5_T6); + SET(c, d, a, b, 6, 17, ZSW_MD5_T7); + SET(b, c, d, a, 7, 22, ZSW_MD5_T8); + SET(a, b, c, d, 8, 7, ZSW_MD5_T9); + SET(d, a, b, c, 9, 12, ZSW_MD5_T10); + SET(c, d, a, b, 10, 17, ZSW_MD5_T11); + SET(b, c, d, a, 11, 22, ZSW_MD5_T12); + SET(a, b, c, d, 12, 7, ZSW_MD5_T13); + SET(d, a, b, c, 13, 12, ZSW_MD5_T14); + SET(c, d, a, b, 14, 17, ZSW_MD5_T15); + SET(b, c, d, a, 15, 22, ZSW_MD5_T16); +#undef SET + + /* Round 2. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ +#define ZSW_MD5_G(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + ZSW_MD5_G(b,c,d) + X[k] + Ti;\ + a = ZSW_MD5_ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 1, 5, ZSW_MD5_T17); + SET(d, a, b, c, 6, 9, ZSW_MD5_T18); + SET(c, d, a, b, 11, 14, ZSW_MD5_T19); + SET(b, c, d, a, 0, 20, ZSW_MD5_T20); + SET(a, b, c, d, 5, 5, ZSW_MD5_T21); + SET(d, a, b, c, 10, 9, ZSW_MD5_T22); + SET(c, d, a, b, 15, 14, ZSW_MD5_T23); + SET(b, c, d, a, 4, 20, ZSW_MD5_T24); + SET(a, b, c, d, 9, 5, ZSW_MD5_T25); + SET(d, a, b, c, 14, 9, ZSW_MD5_T26); + SET(c, d, a, b, 3, 14, ZSW_MD5_T27); + SET(b, c, d, a, 8, 20, ZSW_MD5_T28); + SET(a, b, c, d, 13, 5, ZSW_MD5_T29); + SET(d, a, b, c, 2, 9, ZSW_MD5_T30); + SET(c, d, a, b, 7, 14, ZSW_MD5_T31); + SET(b, c, d, a, 12, 20, ZSW_MD5_T32); +#undef SET + + /* Round 3. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ +#define ZSW_MD5_H(x, y, z) ((x) ^ (y) ^ (z)) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + ZSW_MD5_H(b,c,d) + X[k] + Ti;\ + a = ZSW_MD5_ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 5, 4, ZSW_MD5_T33); + SET(d, a, b, c, 8, 11, ZSW_MD5_T34); + SET(c, d, a, b, 11, 16, ZSW_MD5_T35); + SET(b, c, d, a, 14, 23, ZSW_MD5_T36); + SET(a, b, c, d, 1, 4, ZSW_MD5_T37); + SET(d, a, b, c, 4, 11, ZSW_MD5_T38); + SET(c, d, a, b, 7, 16, ZSW_MD5_T39); + SET(b, c, d, a, 10, 23, ZSW_MD5_T40); + SET(a, b, c, d, 13, 4, ZSW_MD5_T41); + SET(d, a, b, c, 0, 11, ZSW_MD5_T42); + SET(c, d, a, b, 3, 16, ZSW_MD5_T43); + SET(b, c, d, a, 6, 23, ZSW_MD5_T44); + SET(a, b, c, d, 9, 4, ZSW_MD5_T45); + SET(d, a, b, c, 12, 11, ZSW_MD5_T46); + SET(c, d, a, b, 15, 16, ZSW_MD5_T47); + SET(b, c, d, a, 2, 23, ZSW_MD5_T48); +#undef SET + + /* Round 4. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ +#define ZSW_MD5_I(x, y, z) ((y) ^ ((x) | ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + ZSW_MD5_I(b,c,d) + X[k] + Ti;\ + a = ZSW_MD5_ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 6, ZSW_MD5_T49); + SET(d, a, b, c, 7, 10, ZSW_MD5_T50); + SET(c, d, a, b, 14, 15, ZSW_MD5_T51); + SET(b, c, d, a, 5, 21, ZSW_MD5_T52); + SET(a, b, c, d, 12, 6, ZSW_MD5_T53); + SET(d, a, b, c, 3, 10, ZSW_MD5_T54); + SET(c, d, a, b, 10, 15, ZSW_MD5_T55); + SET(b, c, d, a, 1, 21, ZSW_MD5_T56); + SET(a, b, c, d, 8, 6, ZSW_MD5_T57); + SET(d, a, b, c, 15, 10, ZSW_MD5_T58); + SET(c, d, a, b, 6, 15, ZSW_MD5_T59); + SET(b, c, d, a, 13, 21, ZSW_MD5_T60); + SET(a, b, c, d, 4, 6, ZSW_MD5_T61); + SET(d, a, b, c, 11, 10, ZSW_MD5_T62); + SET(c, d, a, b, 2, 15, ZSW_MD5_T63); + SET(b, c, d, a, 9, 21, ZSW_MD5_T64); +#undef SET + + /* Then perform the following additions. (That is increment each + of the four registers by the value it had before this block + was started.) */ + pms->abcd[0] += a; + pms->abcd[1] += b; + pms->abcd[2] += c; + pms->abcd[3] += d; +} + +void md5_init(md5_state_t *pms) +{ + pms->count[0] = pms->count[1] = 0; + pms->abcd[0] = 0x67452301; + pms->abcd[1] = /*0xefcdab89*/ ZSW_MD5_T_MASK ^ 0x10325476; + pms->abcd[2] = /*0x98badcfe*/ ZSW_MD5_T_MASK ^ 0x67452301; + pms->abcd[3] = 0x10325476; +} + +void md5_append(md5_state_t *pms, md5_byte_t const * data, size_t nbytes) +{ + md5_byte_t const * p = data; + size_t left = nbytes; + int offset = (pms->count[0] >> 3) & 63; + md5_word_t nbits = (md5_word_t)(nbytes << 3); + + if (nbytes <= 0) + return; + + /* Update the message length. */ + pms->count[1] += nbytes >> 29; + pms->count[0] += nbits; + if (pms->count[0] < nbits) + pms->count[1]++; + + /* Process an initial partial block. */ + if (offset) { + int copy = (offset + nbytes > 64 ? 64 - offset : static_cast(nbytes)); + + std::memcpy(pms->buf + offset, p, copy); + if (offset + copy < 64) + return; + p += copy; + left -= copy; + md5_process(pms, pms->buf); + } + + /* Process full blocks. */ + for (; left >= 64; p += 64, left -= 64) + md5_process(pms, p); + + /* Process a final partial block. */ + if (left) + std::memcpy(pms->buf, p, left); +} + +void md5_finish(md5_state_t *pms, md5_byte_t digest[16]) +{ + static md5_byte_t const pad[64] = { + 0x80, 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 + }; + md5_byte_t data[8]; + int i; + + /* Save the length before padding. */ + for (i = 0; i < 8; ++i) + data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); + /* Pad to 56 bytes mod 64. */ + md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); + /* Append the length. */ + md5_append(pms, data, 8); + for (i = 0; i < 16; ++i) + digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); +} + +// some convenience c++ functions +inline std::string md5_hash_string(std::string const & s) +{ + char digest[16]; + + md5_state_t state; + + md5_init(&state); + md5_append(&state, (md5_byte_t const *)s.c_str(), s.size()); + md5_finish(&state, (md5_byte_t *)digest); + + std::string ret; + ret.resize(16); + std::copy(digest,digest+16,ret.begin()); + + return ret; +} + + + +inline std::string md5_hash_hex(std::string const & input) +{ + static const char hexval[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + std::string hash = md5_hash_string(input); + std::string hex; + for (size_t i = 0; i < hash.size(); i++) { + hex.push_back(hexval[((hash[i] >> 4) & 0xF)]); + hex.push_back(hexval[(hash[i]) & 0x0F]); + } + + return hex; +} +} // namespace MD5 +NS_FK_END diff --git a/VIServer/Classes/FoundationKit/Crypto/sha1.hpp b/VIServer/Classes/FoundationKit/Crypto/sha1.hpp new file mode 100644 index 0000000000..ca65b0fb85 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Crypto/sha1.hpp @@ -0,0 +1,155 @@ +/**************************************************************************** + Copyright (c) 2013-2014 libo. + + losemymind.libo@gmail.com + +****************************************************************************/ +#pragma once + +#include "FoundationKit/GenericPlatformMacros.h" // for NS_FK_BEGIN NS_FK_END +NS_FK_BEGIN + + +namespace Sha1 { +namespace{ + // Rotate an integer value to left. + inline const unsigned int rol(const unsigned int value, + const unsigned int steps) + { + return ((value << steps) | (value >> (32 - steps))); + } + + // Sets the first 16 integers in the buffert to zero. + // Used for clearing the W buffert. + inline void clearWBuffert(unsigned int* buffert) + { + for (int pos = 16; --pos >= 0;) + { + buffert[pos] = 0; + } + } + + inline void innerHash(unsigned int* result, unsigned int* w) + { + unsigned int a = result[0]; + unsigned int b = result[1]; + unsigned int c = result[2]; + unsigned int d = result[3]; + unsigned int e = result[4]; + + int round = 0; + + #define sha1macro(func,val) \ + { \ + const unsigned int t = rol(a, 5) + (func) + e + val + w[round]; \ + e = d; \ + d = c; \ + c = rol(b, 30); \ + b = a; \ + a = t; \ + } + + while (round < 16) + { + sha1macro((b & c) | (~b & d), 0x5a827999) + ++round; + } + while (round < 20) + { + w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); + sha1macro((b & c) | (~b & d), 0x5a827999) + ++round; + } + while (round < 40) + { + w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); + sha1macro(b ^ c ^ d, 0x6ed9eba1) + ++round; + } + while (round < 60) + { + w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); + sha1macro((b & c) | (b & d) | (c & d), 0x8f1bbcdc) + ++round; + } + while (round < 80) + { + w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); + sha1macro(b ^ c ^ d, 0xca62c1d6) + ++round; + } + + #undef sha1macro + + result[0] += a; + result[1] += b; + result[2] += c; + result[3] += d; + result[4] += e; + } +} // namespace + + /** + * @param src points to any kind of data to be hashed. + * @param bytelength the number of bytes to hash from the src pointer. + * @param hash should point to a buffer of at least 20 bytes of size for storing the sha1 result in. + */ +inline void calc(const void* src, const int bytelength, unsigned char* hash) +{ + // Init the result array. + unsigned int result[5] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 }; + + // Cast the void src pointer to be the byte array we can work with. + const unsigned char* sarray = (const unsigned char*) src; + + // The reusable round buffer + unsigned int w[80]; + + // Loop through all complete 64byte blocks. + const int endOfFullBlocks = bytelength - 64; + int endCurrentBlock; + int currentBlock = 0; + + while (currentBlock <= endOfFullBlocks) + { + endCurrentBlock = currentBlock + 64; + + // Init the round buffer with the 64 byte block data. + for (int roundPos = 0; currentBlock < endCurrentBlock; currentBlock += 4) + { + // This line will swap endian on big endian and keep endian on little endian. + w[roundPos++] = (unsigned int) sarray[currentBlock + 3] + | (((unsigned int) sarray[currentBlock + 2]) << 8) + | (((unsigned int) sarray[currentBlock + 1]) << 16) + | (((unsigned int) sarray[currentBlock]) << 24); + } + innerHash(result, w); + } + + // Handle the last and not full 64 byte block if existing. + endCurrentBlock = bytelength - currentBlock; + clearWBuffert(w); + int lastBlockBytes = 0; + for (;lastBlockBytes < endCurrentBlock; ++lastBlockBytes) + { + w[lastBlockBytes >> 2] |= (unsigned int) sarray[lastBlockBytes + currentBlock] << ((3 - (lastBlockBytes & 3)) << 3); + } + w[lastBlockBytes >> 2] |= 0x80 << ((3 - (lastBlockBytes & 3)) << 3); + if (endCurrentBlock >= 56) + { + innerHash(result, w); + clearWBuffert(w); + } + w[15] = bytelength << 3; + innerHash(result, w); + + // Store hash in result pointer, and make sure we get in in the correct order on both endian models. + for (int hashByte = 20; --hashByte >= 0;) + { + hash[hashByte] = (result[hashByte >> 2] >> (((3 - hashByte) & 0x3) << 3)) & 0xff; + } + +} // calc + +} // namespace Sha1 +NS_FK_END \ No newline at end of file diff --git a/VIServer/Classes/FoundationKit/Foundation/ByteSwap.h b/VIServer/Classes/FoundationKit/Foundation/ByteSwap.h new file mode 100644 index 0000000000..dd668e71ed --- /dev/null +++ b/VIServer/Classes/FoundationKit/Foundation/ByteSwap.h @@ -0,0 +1,67 @@ +#ifndef LOSEMYMIND_BYTESWAP_H +#define LOSEMYMIND_BYTESWAP_H + + +#pragma once +#include "FoundationKit/Base/Types.h" +NS_FK_BEGIN + +//=============== Endian ==================== +//Other impl see:https://sourceforge.net/p/predef/wiki/Endianness/ +//if (ENDIANNESS_ORDER == ENDIANNESS_LITTLE_ENDIAN) +// std::cout << "Is little system" << std::endl; +//else if (ENDIANNESS_ORDER == ENDIANNESS_BIG_ENDIAN) +// std::cout << "Is big system" << std::endl; +//else if (ENDIANNESS_ORDER == ENDIANNESS_PDP_ENDIAN) +// std::cout << "Is pop system" << std::endl; +//else +// std::cout << "Is unknow system" << std::endl; + +const int ENDIANNESS_ORDER = 0xFFFFFFFF & 1; +const int ENDIANNESS_LITTLE_ENDIAN = 0x00000001; +const int ENDIANNESS_BIG_ENDIAN = 0x01000000; +const int ENDIANNESS_PDP_ENDIAN = 0x00010000; +const int ENDIANNESS_UNKNOWN_ENDIAN = 0xFFFFFFFF; + + +static char *ENDIAN_SWAP128(char *val) +{ + static char swp[16]; + swp[0] = val[15]; + swp[1] = val[14]; + swp[2] = val[13]; + swp[3] = val[12]; + swp[4] = val[11]; + swp[5] = val[10]; + swp[6] = val[9]; + swp[7] = val[8]; + swp[8] = val[7]; + swp[9] = val[6]; + swp[10] = val[5]; + swp[11] = val[4]; + swp[12] = val[3]; + swp[13] = val[2]; + swp[14] = val[1]; + swp[15] = val[0]; + return swp; +} + +/// when define returns true it means that our architecture uses big endian +#define HOST_IS_BIG_ENDIAN (bool)(*(unsigned short *)"\0\xff" < 0x100) +#define ENDIAN_SWAP16(i) ((i & 0x00ff) << 8 | (i &0xff00) >> 8) +#define ENDIAN_SWAP32(i) ((i & 0x000000ff) << 24 | (i & 0x0000ff00) << 8 | (i & 0x00ff0000) >> 8 | (i & 0xff000000) >> 24) +#define ENDIAN_SWAP64(val)((((val) >> 56) & 0x00000000000000FF) | (((val) >> 40) & 0x000000000000FF00) |(((val) >> 24) & 0x0000000000FF0000) | (((val) >> 8) & 0x00000000FF000000) |(((val) << 8) & 0x000000FF00000000) | (((val) << 24) & 0x0000FF0000000000) |(((val) << 40) & 0x00FF000000000000) | (((val) << 56) & 0xFF00000000000000)) +#define SWAP_INT16_LITTLE_TO_HOST(i) ((HOST_IS_BIG_ENDIAN == true)? ENDIAN_SWAP16(i) : (i) ) +#define SWAP_INT32_LITTLE_TO_HOST(i) ((HOST_IS_BIG_ENDIAN == true)? ENDIAN_SWAP32(i) : (i) ) +#define SWAP_INT64_LITTLE_TO_HOST(i) ((HOST_IS_BIG_ENDIAN == true)? ENDIAN_SWAP64(i) : (i) ) +#define SWAP_INT16_BIG_TO_HOST(i) ((HOST_IS_BIG_ENDIAN == true)? (i): ENDIAN_SWAP16(i) ) +#define SWAP_INT32_BIG_TO_HOST(i) ((HOST_IS_BIG_ENDIAN == true)? (i): ENDIAN_SWAP32(i) ) +#define SWAP_INT64_BIG_TO_HOST(i) ((HOST_IS_BIG_ENDIAN == true)? (i): ENDIAN_SWAP64(i) ) + +//=============== Endian End ================= + +NS_FK_END + +#endif // LOSEMYMIND_BYTESWAP_H + + diff --git a/VIServer/Classes/FoundationKit/Foundation/Exception.cpp b/VIServer/Classes/FoundationKit/Foundation/Exception.cpp new file mode 100644 index 0000000000..ad1a838e24 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Foundation/Exception.cpp @@ -0,0 +1,173 @@ +/**************************************************************************** + Copyright (c) 2015 libo All rights reserved. + + losemymind.libo@gmail.com + +****************************************************************************/ + +#include +#include "Exception.h" + +NS_FK_BEGIN + +Exception::Exception(int code): _pNested(nullptr), _code(code) +{ +} + + +Exception::Exception(const std::string& msg, int code): _msg(msg), _pNested(nullptr), _code(code) +{ +} + + +Exception::Exception(const std::string& msg, const std::string& arg, int code): _msg(msg), _pNested(nullptr), _code(code) +{ + if (!arg.empty()) + { + _msg.append(": "); + _msg.append(arg); + } +} + +Exception::Exception(const std::string& msg, const Exception& nested, int code): _msg(msg), _pNested(nested.clone()), _code(code) +{ +} + +Exception::Exception(const Exception& exc): + std::exception(exc), + _msg(exc._msg), + _code(exc._code) +{ + _pNested = exc._pNested ? exc._pNested->clone() : 0; +} + + +Exception::~Exception() throw() +{ + delete _pNested; +} + + +Exception& Exception::operator = (const Exception& exc) +{ + if (&exc != this) + { + delete _pNested; + _msg = exc._msg; + _pNested = exc._pNested ? exc._pNested->clone() : 0; + _code = exc._code; + } + return *this; +} + + +const char* Exception::name() const throw() +{ + return "Exception"; +} + + +const char* Exception::className() const throw() +{ + return typeid(*this).name(); +} + + +const char* Exception::what() const throw() +{ + return name(); +} + + +std::string Exception::displayText() const +{ + std::string txt = name(); + if (!_msg.empty()) + { + txt.append(": "); + txt.append(_msg); + } + return txt; +} + + +void Exception::extendedMessage(const std::string& arg) +{ + if (!arg.empty()) + { + if (!_msg.empty()) _msg.append(": "); + _msg.append(arg); + } +} + + +Exception* Exception::clone() const +{ + return new Exception(*this); +} + + +void Exception::rethrow() const +{ + throw *this; +} + + +IMPLEMENT_EXCEPTION(LogicException, Exception, "Logic exception") +IMPLEMENT_EXCEPTION(AssertionViolationException, LogicException, "Assertion violation") +IMPLEMENT_EXCEPTION(NullPointerException, LogicException, "Null pointer") +IMPLEMENT_EXCEPTION(NullValueException, LogicException, "Null value") +IMPLEMENT_EXCEPTION(BugcheckException, LogicException, "Bugcheck") +IMPLEMENT_EXCEPTION(InvalidArgumentException, LogicException, "Invalid argument") +IMPLEMENT_EXCEPTION(NotImplementedException, LogicException, "Not implemented") +IMPLEMENT_EXCEPTION(RangeException, LogicException, "Out of range") +IMPLEMENT_EXCEPTION(IllegalStateException, LogicException, "Illegal state") +IMPLEMENT_EXCEPTION(InvalidAccessException, LogicException, "Invalid access") +IMPLEMENT_EXCEPTION(SignalException, LogicException, "Signal received") +IMPLEMENT_EXCEPTION(UnhandledException, LogicException, "Unhandled exception") + +IMPLEMENT_EXCEPTION(RuntimeException, Exception, "Runtime exception") +IMPLEMENT_EXCEPTION(NotFoundException, RuntimeException, "Not found") +IMPLEMENT_EXCEPTION(ExistsException, RuntimeException, "Exists") +IMPLEMENT_EXCEPTION(TimeoutException, RuntimeException, "Timeout") +IMPLEMENT_EXCEPTION(SystemException, RuntimeException, "System exception") +IMPLEMENT_EXCEPTION(RegularExpressionException, RuntimeException, "Error in regular expression") +IMPLEMENT_EXCEPTION(LibraryLoadException, RuntimeException, "Cannot load library") +IMPLEMENT_EXCEPTION(LibraryAlreadyLoadedException, RuntimeException, "Library already loaded") +IMPLEMENT_EXCEPTION(NoThreadAvailableException, RuntimeException, "No thread available") +IMPLEMENT_EXCEPTION(PropertyNotSupportedException, RuntimeException, "Property not supported") +IMPLEMENT_EXCEPTION(PoolOverflowException, RuntimeException, "Pool overflow") +IMPLEMENT_EXCEPTION(NoPermissionException, RuntimeException, "No permission") +IMPLEMENT_EXCEPTION(OutOfMemoryException, RuntimeException, "Out of memory") +IMPLEMENT_EXCEPTION(DataException, RuntimeException, "Data error") + +IMPLEMENT_EXCEPTION(InterruptedException, RuntimeException, "Interrupted") +IMPLEMENT_EXCEPTION(IndexOutOfBoundsException, RuntimeException, "Index out of bounds") +IMPLEMENT_EXCEPTION(UnsupportedOperationException, RuntimeException, "Unsupported operation") +IMPLEMENT_EXCEPTION(EmptyStackException, RuntimeException, "Empty stack") +IMPLEMENT_EXCEPTION(StackOverflowException, RuntimeException, "Stack overflow") +IMPLEMENT_EXCEPTION(ArithmeticException, RuntimeException, "Arithmetic error") + +IMPLEMENT_EXCEPTION(DataFormatException, DataException, "Bad data format") +IMPLEMENT_EXCEPTION(SyntaxException, DataException, "Syntax error") +IMPLEMENT_EXCEPTION(CircularReferenceException, DataException, "Circular reference") +IMPLEMENT_EXCEPTION(PathSyntaxException, SyntaxException, "Bad path syntax") +IMPLEMENT_EXCEPTION(IOException, RuntimeException, "I/O error") +IMPLEMENT_EXCEPTION(ProtocolException, IOException, "Protocol error") +IMPLEMENT_EXCEPTION(FileException, IOException, "File access error") +IMPLEMENT_EXCEPTION(FileExistsException, FileException, "File exists") +IMPLEMENT_EXCEPTION(FileNotFoundException, FileException, "File not found") +IMPLEMENT_EXCEPTION(PathNotFoundException, FileException, "Path not found") +IMPLEMENT_EXCEPTION(FileReadOnlyException, FileException, "File is read-only") +IMPLEMENT_EXCEPTION(FileAccessDeniedException, FileException, "Access to file denied") +IMPLEMENT_EXCEPTION(CreateFileException, FileException, "Cannot create file") +IMPLEMENT_EXCEPTION(OpenFileException, FileException, "Cannot open file") +IMPLEMENT_EXCEPTION(WriteFileException, FileException, "Cannot write file") +IMPLEMENT_EXCEPTION(ReadFileException, FileException, "Cannot read file") +IMPLEMENT_EXCEPTION(UnknownURISchemeException, RuntimeException, "Unknown URI scheme") + + +IMPLEMENT_EXCEPTION(ApplicationException, Exception, "Application exception") +IMPLEMENT_EXCEPTION(BadCastException, RuntimeException, "Bad cast exception") + +NS_FK_END \ No newline at end of file diff --git a/VIServer/Classes/FoundationKit/Foundation/Exception.h b/VIServer/Classes/FoundationKit/Foundation/Exception.h new file mode 100644 index 0000000000..bbc6f3d745 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Foundation/Exception.h @@ -0,0 +1,270 @@ +/**************************************************************************** + Copyright (c) 2015 libo All rights reserved. + + losemymind.libo@gmail.com + +****************************************************************************/ +#pragma once + +#include +#include +#include "FoundationKit/GenericPlatformMacros.h" + +NS_FK_BEGIN + +/** + * This is the base class for all exceptions defined + * in Foundation class library. + */ +class Exception: public std::exception +{ +public: + /** + * Creates an exception. + * @param [in] msg The exception message. + * @param [in] code The exception code. + */ + Exception(const std::string& msg, int code = 0); + + /** + * Creates an exception. + * @param [in] msg The exception message. + * @param [in] arg Exception message arg. + * @param [in] code The exception code. + */ + Exception(const std::string& msg, const std::string& arg, int code = 0); + + /** + * Creates an exception and stores a clone + * of the nested exception. + */ + Exception(const std::string& msg, const Exception& nested, int code = 0); + + + Exception(const Exception& exc); + + /** + * Destroys the exception and deletes the nested exception. + */ + ~Exception() throw(); + + Exception& operator = (const Exception& exc); + + /** + * Returns a static string describing the exception. + */ + virtual const char* name() const throw(); + + /** + * Returns the name of the exception class. + */ + virtual const char* className() const throw(); + + /** + * Returns a static string describing the exception. + */ + virtual const char* what() const throw(); + + /** + * Returns a pointer to the nested exception, or + * null if no nested exception exists. + */ + const Exception* nested() const; + + /** + * Returns the message text. + */ + const std::string& message() const; + + /** + * Returns the exception code if defined. + */ + int code() const; + + /** + * Returns a string consisting of the + * message name and the message text. + */ + std::string displayText() const; + + /** + * Creates an exact copy of the exception. + * The copy can later be thrown again by + * invoking rethrow() on it. + */ + virtual Exception* clone() const; + + /** + * (Re)Throws the exception. + * This is useful for temporarily storing a + * copy of an exception (see clone()), then + * throwing it again. + */ + virtual void rethrow() const; + +protected: + Exception(int code = 0); + void message(const std::string& msg); + void extendedMessage(const std::string& arg); + +private: + std::string _msg; + Exception* _pNested; + int _code; +}; + + +// +// inlines +// +inline const Exception* Exception::nested() const +{ + return _pNested; +} + + +inline const std::string& Exception::message() const +{ + return _msg; +} + + +inline void Exception::message(const std::string& msg) +{ + _msg = msg; +} + + +inline int Exception::code() const +{ + return _code; +} + +/** + * Macros for quickly declaring and implementing exception classes. + * Unfortunately, we cannot use a template here because character + * pointers (which we need for specifying the exception name) + * are not allowed as template arguments. + */ +#define DECLARE_EXCEPTION_CODE(CLS, BASE, CODE) \ + class CLS: public BASE \ + { \ + public: \ + CLS(int code = CODE); \ + CLS(const std::string& msg, int code = CODE); \ + CLS(const std::string& msg, const std::string& arg, int code = CODE); \ + CLS(const std::string& msg, const Exception& exc, int code = CODE); \ + CLS(const CLS& exc); \ + ~CLS() throw(); \ + CLS& operator = (const CLS& exc); \ + const char* name() const throw(); \ + const char* className() const throw(); \ + Exception* clone() const; \ + void rethrow() const; \ + }; + +#define DECLARE_EXCEPTION(CLS, BASE) \ + DECLARE_EXCEPTION_CODE(CLS, BASE, 0) + +#define IMPLEMENT_EXCEPTION(CLS, BASE, NAME) \ + CLS::CLS(int code): BASE(code) \ + { \ + } \ + CLS::CLS(const std::string& msg, int code): BASE(msg, code) \ + { \ + } \ + CLS::CLS(const std::string& msg, const std::string& arg, int code): BASE(msg, arg, code) \ + { \ + } \ + CLS::CLS(const std::string& msg, const Exception& exc, int code): BASE(msg, exc, code) \ + { \ + } \ + CLS::CLS(const CLS& exc): BASE(exc) \ + { \ + } \ + CLS::~CLS() throw() \ + { \ + } \ + CLS& CLS::operator = (const CLS& exc) \ + { \ + BASE::operator = (exc); \ + return *this; \ + } \ + const char* CLS::name() const throw() \ + { \ + return NAME; \ + } \ + const char* CLS::className() const throw() \ + { \ + return typeid(*this).name(); \ + } \ + Exception* CLS::clone() const \ + { \ + return new CLS(*this); \ + } \ + void CLS::rethrow() const \ + { \ + throw *this; \ + } + + +// +// Standard exception classes +// +DECLARE_EXCEPTION(LogicException, Exception) +DECLARE_EXCEPTION(AssertionViolationException, LogicException) +DECLARE_EXCEPTION(NullPointerException, LogicException) +DECLARE_EXCEPTION(NullValueException, LogicException) +DECLARE_EXCEPTION(BugcheckException, LogicException) +DECLARE_EXCEPTION(InvalidArgumentException, LogicException) +DECLARE_EXCEPTION(NotImplementedException, LogicException) +DECLARE_EXCEPTION(RangeException, LogicException) +DECLARE_EXCEPTION(IllegalStateException, LogicException) +DECLARE_EXCEPTION(InvalidAccessException, LogicException) +DECLARE_EXCEPTION(SignalException, LogicException) +DECLARE_EXCEPTION(UnhandledException, LogicException) + +DECLARE_EXCEPTION(RuntimeException, Exception) +DECLARE_EXCEPTION(NotFoundException, RuntimeException) +DECLARE_EXCEPTION(ExistsException, RuntimeException) +DECLARE_EXCEPTION(TimeoutException, RuntimeException) +DECLARE_EXCEPTION(SystemException, RuntimeException) +DECLARE_EXCEPTION(RegularExpressionException, RuntimeException) +DECLARE_EXCEPTION(LibraryLoadException, RuntimeException) +DECLARE_EXCEPTION(LibraryAlreadyLoadedException, RuntimeException) +DECLARE_EXCEPTION(NoThreadAvailableException, RuntimeException) +DECLARE_EXCEPTION(PropertyNotSupportedException, RuntimeException) +DECLARE_EXCEPTION(PoolOverflowException, RuntimeException) +DECLARE_EXCEPTION(NoPermissionException, RuntimeException) +DECLARE_EXCEPTION(OutOfMemoryException, RuntimeException) +DECLARE_EXCEPTION(DataException, RuntimeException) +DECLARE_EXCEPTION(InterruptedException, RuntimeException) +DECLARE_EXCEPTION(IndexOutOfBoundsException, RuntimeException) +DECLARE_EXCEPTION(UnsupportedOperationException, RuntimeException) +DECLARE_EXCEPTION(EmptyStackException, RuntimeException) +DECLARE_EXCEPTION(StackOverflowException, RuntimeException) +DECLARE_EXCEPTION(ArithmeticException, RuntimeException) + +DECLARE_EXCEPTION(DataFormatException, DataException) +DECLARE_EXCEPTION(SyntaxException, DataException) +DECLARE_EXCEPTION(CircularReferenceException, DataException) +DECLARE_EXCEPTION(PathSyntaxException, SyntaxException) +DECLARE_EXCEPTION(IOException, RuntimeException) +DECLARE_EXCEPTION(ProtocolException, IOException) +DECLARE_EXCEPTION(FileException, IOException) +DECLARE_EXCEPTION(FileExistsException, FileException) +DECLARE_EXCEPTION(FileNotFoundException, FileException) +DECLARE_EXCEPTION(PathNotFoundException, FileException) +DECLARE_EXCEPTION(FileReadOnlyException, FileException) +DECLARE_EXCEPTION(FileAccessDeniedException, FileException) +DECLARE_EXCEPTION(CreateFileException, FileException) +DECLARE_EXCEPTION(OpenFileException, FileException) +DECLARE_EXCEPTION(WriteFileException, FileException) +DECLARE_EXCEPTION(ReadFileException, FileException) +DECLARE_EXCEPTION(UnknownURISchemeException, RuntimeException) + +DECLARE_EXCEPTION(ApplicationException, Exception) +DECLARE_EXCEPTION(BadCastException, RuntimeException) + +NS_FK_END + diff --git a/VIServer/Classes/FoundationKit/Foundation/Logger.cpp b/VIServer/Classes/FoundationKit/Foundation/Logger.cpp new file mode 100644 index 0000000000..3af2d26a55 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Foundation/Logger.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** + Copyright (c) 2015 libo All rights reserved. + + losemymind.libo@gmail.com + +****************************************************************************/ +#include +#include +#include "Logger.h" +#include "FoundationKit/Foundation/StringUtils.h" + +#if (TARGET_PLATFORM == PLATFORM_WIN32) +#include +#endif + +#if (TARGET_PLATFORM == PLATFORM_ANDROID) +#include +#endif + + +NS_FK_BEGIN + +static const size_t MAX_LOG_LENGTH = 1024; +static const char* LevelMsg[] = {"TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"}; + + +Logger::State::State():enabled(true){} + +void Logger::log( Level level, const char* message, ... ) +{ + Logger::State& state = _states[level]; + if (!state.enabled) + return; + std::string strPreMsg = LevelMsg[level]; + strPreMsg += ":"; + va_list args; + + // Declare a moderately sized buffer on the stack that should be + // large enough to accommodate most log requests. + int size = MAX_LOG_LENGTH; + //char stackBuffer[MAX_LOG_LENGTH] = { 0 }; + std::vector dynamicBuffer(MAX_LOG_LENGTH); + char* str = &dynamicBuffer[0]; + for (;;) + { + va_start(args, message); + // Pass one less than size to leave room for NULL terminator + int needed = vsnprintf(str, size - 1, message, args); + va_end(args); + // NOTE: Some platforms return -1 when vsnprintf runs out of room, while others return + // the number of characters actually needed to fill the buffer. + if (needed >= 0 && needed < size) + { + // Successfully wrote buffer. Added a NULL terminator in case it wasn't written. + str[needed] = '\0'; + break; + } + size = needed > 0 ? (needed + 1) : (size * 2); + dynamicBuffer.resize(size); + str = &dynamicBuffer[0]; + } + strPreMsg += str; + strPreMsg += "\n"; + +#if (TARGET_PLATFORM == PLATFORM_ANDROID) + __android_log_print(ANDROID_LOG_DEBUG, "FoundationKit", "%s", strPreMsg.c_str()); +#elif TARGET_PLATFORM == PLATFORM_WIN32 + std::wstring wstr = StringUtils::string2UTF8wstring(strPreMsg); + OutputDebugStringW(wstr.c_str()); + printf("%s", strPreMsg.c_str()); + fflush(stdout); +#else + // Linux, Mac, iOS, etc + fprintf(stdout, "%s", strPreMsg.c_str()); + fflush(stdout); +#endif +} + +bool Logger::isEnabled( Level level ) +{ + return _states[level].enabled; +} + +void Logger::setEnabled( Level level, bool enabled ) +{ + _states[level].enabled = enabled; +} + + +NS_FK_END + + diff --git a/VIServer/Classes/FoundationKit/Foundation/Logger.h b/VIServer/Classes/FoundationKit/Foundation/Logger.h new file mode 100644 index 0000000000..babfc6c006 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Foundation/Logger.h @@ -0,0 +1,83 @@ +/**************************************************************************** + Copyright (c) 2015 libo All rights reserved. + + losemymind.libo@gmail.com + +****************************************************************************/ +#pragma once +#include "Singleton.h" + +NS_FK_BEGIN + +class Logger : public Singleton +{ + friend class Singleton < Logger >; + Logger(){}; +public: + /** + * Enumeration of valid log levels. + */ + enum Level + { + LV_TRACE = 0, + LV_DEBUG, + LV_INFO, + LV_WARN, + LV_ERROR, + LV_FATAL, + }; +private: + struct State + { + State(); + bool enabled; + }; + +public: + /** + * Logs a message at the specified log level. + * + * This method accepts a variable argument list with the same formatting specification + * as printf. Therefore, the message parameter can include any format specifiers that + * are supported by printf. + * + * @param level Log level. + * @param message Log message. + */ + void log(Level level, const char* message, ...); + + /** + * Determines if logging is currently enabled for the given level. + * + * @param level Log level. + * + * @return True if logging is enabled for this level, or false if it is disabled. + */ + bool isEnabled(Level level); + + /** + * Enables or disables logging at the given level. + * + * @param level Log level to enable or disable. + * @param enabled True to enable the logger for the given level, false to disable it. + */ + void setEnabled(Level level, bool enabled); +private: + State _states[6]; +}; +NS_FK_END + +extern void _log_(const char* message, ...); + +#ifdef FK_DEBUG +#define LOG_DEBUG(format, ...) Logger::getInstance()->log(Logger::Level::LV_DEBUG, format, ##__VA_ARGS__) +#else +#define LOG_DEBUG(format, ...) +#endif +#define LOG_TRACE(format, ...) Logger::getInstance()->log(Logger::Level::LV_TRACE, format, ##__VA_ARGS__) +#define LOG_INFO( format, ...) Logger::getInstance()->log(Logger::Level::LV_INFO, format, ##__VA_ARGS__) +#define LOG_WARN( format, ...) Logger::getInstance()->log(Logger::Level::LV_WARN, format, ##__VA_ARGS__) +#define LOG_ERROR(format, ...) Logger::getInstance()->log(Logger::Level::LV_ERROR, format, ##__VA_ARGS__) +#define LOG_FATAL(format, ...) Logger::getInstance()->log(Logger::Level::LV_FATAL, format, ##__VA_ARGS__) + + diff --git a/VIServer/Classes/FoundationKit/Foundation/Singleton.h b/VIServer/Classes/FoundationKit/Foundation/Singleton.h new file mode 100644 index 0000000000..88ea69b572 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Foundation/Singleton.h @@ -0,0 +1,67 @@ +/**************************************************************************** + Copyright (c) 2015 libo All rights reserved. + + losemymind.libo@gmail.com + +****************************************************************************/ +#pragma once + +#include +#include +#include "FoundationKit/Base/noncopyable.hpp" +#include "FoundationKit/GenericPlatformMacros.h" +NS_FK_BEGIN + +template< typename T, bool destroy_on_exit = true > +class Singleton : noncopyable +{ + typedef T instance_type; + typedef instance_type* instance_pointer; + typedef volatile instance_pointer volatile_instance_pointer; + static std::once_flag m_once; + static volatile_instance_pointer m_instance; + static void destroy(); + +public: + inline static instance_pointer getInstance() + { + std::call_once(m_once, [&]{ + m_instance = new (std::nothrow) instance_type(); + if (destroy_on_exit) + { + ::atexit(destroy); + } + }); + return m_instance; + } + + inline static void destroyInstance() + { + if (!destroy_on_exit) + { + destroy(); + } + } +}; + + +template< typename T, bool destroy_on_exit > +void Singleton< T, destroy_on_exit>::destroy() +{ + typedef char T_must_be_complete_type[sizeof(T) == 0 ? -1 : 1]; + T_must_be_complete_type dummy; (void)dummy; + delete m_instance; + m_instance = nullptr; +} + +template< typename T, bool destroy_on_exit > +typename Singleton< T, destroy_on_exit >::volatile_instance_pointer + Singleton::m_instance = nullptr; + +template< class T, bool destroy_on_exit > +std::once_flag Singleton::m_once; + +NS_FK_END + + + diff --git a/VIServer/Classes/FoundationKit/Foundation/StringUtils.cpp b/VIServer/Classes/FoundationKit/Foundation/StringUtils.cpp new file mode 100644 index 0000000000..a0d5f3bfb6 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Foundation/StringUtils.cpp @@ -0,0 +1,243 @@ +/**************************************************************************** + Copyright (c) 2015 libo All rights reserved. + + losemymind.libo@gmail.com + +****************************************************************************/ +#include +#include +#include +#include +#include +#include +//#include +#include "StringUtils.h" +#include "FoundationKit/external/ConvertUTF/ConvertUTF.h" + +NS_FK_BEGIN + +std::string StringUtils::tolower( const std::string& str ) +{ + std::string ret; + for (auto ch : str) + { + if (ch >= 'A' && ch <= 'Z') + ret += ch | 32; + else + ret += ch; + } + return ret; +} + +std::string StringUtils::toupper( const std::string& str ) +{ + std::string ret; + for (auto ch : str) + { + if (ch >= 'a' && ch <= 'z') + ret += ch ^ 32; + else + ret += ch; + } + return ret; +} + +std::string StringUtils::format( const char* format, ... ) +{ + const static unsigned int MAX_STRING_LENGTH = 64; + va_list arglist; + int size = MAX_STRING_LENGTH; + std::vector dynamicBuffer(MAX_STRING_LENGTH); + char* str = &dynamicBuffer[0]; + for (;;) + { + va_start(arglist, format); + // Pass one less than size to leave room for NULL terminator + int needed = vsnprintf(str, size - 1, format, arglist); + va_end(arglist); + + // NOTE: Some platforms return -1 when vsnprintf runs out of room, while others return + // the number of characters actually needed to fill the buffer. + if (needed >= 0 && needed < size) + { + // Successfully wrote buffer. Added a NULL terminator in case it wasn't written. + str[needed] = '\0'; + break; + } + size = needed > 0 ? (needed + 1) : (size * 2); + dynamicBuffer.resize(size); + str = &dynamicBuffer[0]; + } + return str; +} + +std::string & StringUtils::ltrim( std::string &s ) +{ + s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); + return s; +} + +std::string & StringUtils::rtrim( std::string &s ) +{ + s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), s.end()); + return s; +} + +std::string & StringUtils::trim( std::string &s ) +{ + return ltrim(rtrim(s)); +} + +std::vector & StringUtils::split( const std::string &s, char delim, std::vector &elems ) +{ + std::stringstream ss(s); + std::string item; + while (std::getline(ss, item, delim)) + { + elems.push_back(item); + } + return elems; +} + +std::vector StringUtils::split( const std::string &s, char delim ) +{ + std::vector elems; + split(s, delim, elems); + return elems; +} + +std::string StringUtils::join(std::string delim, std::vector values) +{ + std::string ret; + size_t index = 0; + size_t valuesSize = values.size(); + for (auto& str : values) + { + ++index; + ret.append(str); + if (index < valuesSize) + { + ret.append(delim); + } + } + return ret; +} + +bool StringUtils::isNumber( const std::string& val ) +{ + std::stringstream str(val); + float tst; + str >> tst; + return !str.fail() && str.eof(); +} + + +// Other impl see:http://blog.poxiao.me/p/unicode-character-encoding-conversion-in-cpp11/ + +std::string StringUtils::wstring2UTF8string(const std::wstring &input) +{ + std::locale old_loc = std::locale::global(std::locale("")); + const wchar_t* src_wstr = input.c_str(); + size_t buffer_size = input.size() * 4 + 1; + char* dst_str = new char[buffer_size]; + memset(dst_str, 0, buffer_size); + wcstombs(dst_str, src_wstr, buffer_size); + std::string result = dst_str; + delete[]dst_str; + std::locale::global(old_loc); + return result; +} + +std::wstring StringUtils::string2UTF8wstring(const std::string &input) +{ + std::locale old_loc = std::locale::global(std::locale("")); + const char* src_str = input.c_str(); + const size_t buffer_size = input.size() + 1; + wchar_t* dst_wstr = new wchar_t[buffer_size]; + wmemset(dst_wstr, 0, buffer_size); + mbstowcs(dst_wstr, src_str, buffer_size); + std::wstring result = dst_wstr; + delete[]dst_wstr; + std::locale::global(old_loc); + return result; +} + + +bool StringUtils::UTF8ToUTF16(const std::string& utf8, std::u16string& outUtf16) +{ + if (utf8.empty()) + { + outUtf16.clear(); + return true; + } + + bool ret = false; + + const size_t utf16Bytes = (utf8.length() + 1) * sizeof(char16_t); + char16_t* utf16 = (char16_t*)malloc(utf16Bytes); + memset(utf16, 0, utf16Bytes); + + char* utf16ptr = reinterpret_cast(utf16); + const UTF8* error = nullptr; + + if (llvm::ConvertUTF8toWide(2, utf8, utf16ptr, error)) + { + outUtf16 = utf16; + ret = true; + } + free(utf16); + return ret; +} + +bool StringUtils::UTF16ToUTF8(const std::u16string& utf16, std::string& outUtf8) +{ + if (utf16.empty()) + { + outUtf8.clear(); + return true; + } + + return llvm::convertUTF16ToUTF8String(utf16, outUtf8); +} + +/* +std::u16string StringUtils::UTF8ToUTF16(const std::string &s) +{ + std::wstring_convert, char16_t> conv; + return conv.from_bytes(s); +} + +std::u32string StringUtils::UTF8ToUTF32(const std::string &s) +{ + std::wstring_convert, char32_t> conv; + return conv.from_bytes(s); +} + +std::string StringUtils::UTF16ToUTF8(const std::u16string &s) +{ + std::wstring_convert, char16_t> conv; + return conv.to_bytes(s); +} + +std::u32string StringUtils::UTF16ToUTF32(const std::u16string &s) +{ + const char16_t *pData = s.c_str(); + std::wstring_convert, char32_t> conv; + return conv.from_bytes(reinterpret_cast(pData), reinterpret_cast(pData + s.length())); +} + +std::string StringUtils::UTF32ToUTF8(const std::u32string &s) +{ + std::wstring_convert, char32_t> conv; + return conv.to_bytes(s); +} + + +std::u16string StringUtils::UTF32ToUTF16(const std::u32string &s) +{ + std::wstring_convert, char32_t> conv; + std::string bytes = conv.to_bytes(s); + return std::u16string(reinterpret_cast(bytes.c_str()), bytes.length() / sizeof(char16_t)); +} +*/ +NS_FK_END diff --git a/VIServer/Classes/FoundationKit/Foundation/StringUtils.h b/VIServer/Classes/FoundationKit/Foundation/StringUtils.h new file mode 100644 index 0000000000..95404a6372 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Foundation/StringUtils.h @@ -0,0 +1,153 @@ +/**************************************************************************** + Copyright (c) 2015 libo All rights reserved. + + losemymind.libo@gmail.com + +****************************************************************************/ +#ifndef LOSEMYMIND_STRINGUTILS_H +#define LOSEMYMIND_STRINGUTILS_H + +#pragma once +#include +#include +#include +#include +#include "FoundationKit/GenericPlatformMacros.h" + +NS_FK_BEGIN + +class StringUtils +{ +public: + static std::string tolower(const std::string& str); + + static std::string toupper(const std::string& str); + + static std::string format(const char* format, ...); + + // trim from start + static std::string <rim(std::string &s); + + // trim from end + static std::string &rtrim(std::string &s); + + // trim from both ends + static std::string &trim(std::string &s); + + static std::vector &split(const std::string &s, char delim, std::vector &elems); + + static std::vector split(const std::string &s, char delim); + + static std::string join(std::string delim, std::vector values); + + /** + * @brief Converts basic numeric types to strings. + * @param[in] val The basic numeric. + * @param[in] percision Number of precision. + * @usage tostring(val); + */ + template + static std::string to_string(_Val val,int precision = 2) + { + std::ostringstream oss; + oss << std::fixed << std::setprecision(precision) << val; + return oss.str(); + } + + /** + * @brief Converts boolean types to strings. + * @usage tostring(val); + */ + static std::string to_string(bool val) + { + return val ? "true" : "false"; + } + + static bool isNumber(const std::string& val); + + /** + * Convert std::wstring to std::string, the string code page is UTF-8. + */ + static std::string wstring2UTF8string(const std::wstring &input); + + /** + * Convert std::string to std::wstring, the string code page is UTF-8. + */ + static std::wstring string2UTF8wstring(const std::string &input); + + + static std::wstring string2wstring(std::string s) + { + std::wstring ws; + ws.assign(s.begin(), s.end()); + return ws; + } + + static std::string wstring2string(std::wstring ws) + { + std::string s; + s.assign(ws.begin(), ws.end()); + return s; + } + + static unsigned char* to_unsigned(char* p) + { + return reinterpret_cast(p); + } + + static unsigned char* to_unsigned(std::string& str) + { + return reinterpret_cast(&*str.begin()); + } + + + /** + * @brief Converts utf8 string to utf16 string. + * @param utf8 The utf8 string to be converted. + * @param outUtf16 The output utf16 string. + * @return True if succeed, otherwise false. + * @note Please check the return value before using \p outUtf16 + * e.g. + * @code + * std::u16string utf16; + * bool ret = StringUtils::UTF8ToUTF16("hello", utf16); + * if (ret) { + * do_some_thing_with_utf16(utf16); + * } + * @endcode + */ + static bool UTF8ToUTF16(const std::string& utf8, std::u16string& outUtf16); + + /** + * @brief Converts utf16 string to utf8 string. + * @param utf16 The utf16 string to be converted. + * @param outUtf8 The output utf8 string. + * @return True if succeed, otherwise false. + * @note Please check the return value before using \p outUtf8 + * e.g. + * @code + * std::string utf8; + * bool ret = StringUtils::UTF16ToUTF8(u"\u4f60\u597d", utf16); + * if (ret) { + * do_some_thing_with_utf8(utf8); + * } + * @endcode + */ + static bool UTF16ToUTF8(const std::u16string& utf16, std::string& outUtf8); + + /** + static std::u16string UTF8ToUTF16(const std::string &s); + static std::u32string UTF8ToUTF32(const std::string &s); + static std::string UTF16ToUTF8(const std::u16string &s); + static std::u32string UTF16ToUTF32(const std::u16string &s); + static std::string UTF32ToUTF8(const std::u32string &s); + static std::u16string UTF32ToUTF16(const std::u32string &s); + */ + + +}; + +NS_FK_END +#endif // LOSEMYMIND_STRINGUTILS_H + + diff --git a/VIServer/Classes/FoundationKit/Foundation/unique_id.cpp b/VIServer/Classes/FoundationKit/Foundation/unique_id.cpp new file mode 100644 index 0000000000..c4eece7908 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Foundation/unique_id.cpp @@ -0,0 +1,9 @@ + +#include "unique_id.hpp" +NS_FK_BEGIN +uint64_t unique_id::sequence = 0; +uint64_t unique_id::machineid = 0; + +NS_FK_END + + diff --git a/VIServer/Classes/FoundationKit/Foundation/unique_id.hpp b/VIServer/Classes/FoundationKit/Foundation/unique_id.hpp new file mode 100644 index 0000000000..26d81af505 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Foundation/unique_id.hpp @@ -0,0 +1,52 @@ + +#pragma once +#include +#include +#include +#include +#include "FoundationKit/Base/Types.h" +#include "FoundationKit/Platform/Platform.h" + +NS_FK_BEGIN + +const uint64 INVALID_UNIQUE_ID = -1; +static const uint64_t sequence_max = (std::numeric_limits::max)(); +struct unique_id +{ + static uint64_t sequence; + static uint64_t machineid; + static uint64 create() + { + int64 uniqueid = 0; + int64 timestamp = std::chrono::high_resolution_clock::now().time_since_epoch().count(); + + if (machineid == 0) + { + std::vector machineid_arr = Platform::getMacAddressRaw(); + std::stringstream ss; + ss << std::hex << std::setfill('0'); + + for (unsigned i = 0; i < 6; ++i) + ss << std::setw(2) << int(machineid_arr[i]); + + ss >> machineid; + + if (machineid == 0) + return INVALID_UNIQUE_ID; + } + + uniqueid = timestamp << 22; + uniqueid |= (machineid & 0x3FF) << 12; + uniqueid |= sequence++ & 0xFFF; + if (sequence == sequence_max) + { + sequence = 0; + } + return uniqueid; + } +}; + + + +NS_FK_END + diff --git a/VIServer/Classes/FoundationKit/GenericPlatformMacros.cpp b/VIServer/Classes/FoundationKit/GenericPlatformMacros.cpp new file mode 100644 index 0000000000..1d23222406 --- /dev/null +++ b/VIServer/Classes/FoundationKit/GenericPlatformMacros.cpp @@ -0,0 +1,86 @@ +#include "GenericPlatformMacros.h" +#include "FoundationKit/Foundation/StringUtils.h" +#include +#include +#if (TARGET_PLATFORM == PLATFORM_ANDROID) +#include +#elif (TARGET_PLATFORM == PLATFORM_WIN32) +#include +#endif +USING_NS_FK; + + +void __fail__(const char* expr, const char* file, int line) +{ +#if (DEBUG_MODE==1) + +# if defined(EMSCRIPTEN) && EMSCRIPTEN + __assert_fail(expr, file, line, ""); +# elif defined __native_client__ + __assert(expr, line, file); // WHY. +# elif defined __ANDROID__ + __assert(file, line, expr); +# elif defined __clang__ || defined __GNU_LIBRARY__ || (defined __GNUC__ && defined __APPLE__) + __assert(expr, file, line); +# elif defined __GNUC__ + _assert(expr, file, line); +# elif defined _MSC_VER + _CrtDbgReport(_CRT_ASSERT, file, line, expr, ""); +# else +# error UNSUPPORTED COMPILER +# endif +#endif // (DEBUG_MODE==1) + +} + +void __log__(const char* file, int line, const char* message, ...) +{ + static const size_t MAX_LOG_LENGTH = 1024; + // Declare a moderately sized buffer on the stack that should be + // large enough to accommodate most log requests. + int size = MAX_LOG_LENGTH; + //char stackBuffer[MAX_LOG_LENGTH] = { 0 }; + std::vector dynamicBuffer(MAX_LOG_LENGTH); + char* str = &dynamicBuffer[0]; + std::string logMessage; + logMessage += file ? file : ""; + logMessage += ":"; + logMessage += StringUtils::to_string(line); + va_list args; + for (;;) + { + va_start(args, message); + // Pass one less than size to leave room for NULL terminator + int needed = vsnprintf(str, size - 1, message, args); + va_end(args); + // NOTE: Some platforms return -1 when vsnprintf runs out of room, while others return + // the number of characters actually needed to fill the buffer. + if (needed >= 0 && needed < size) + { + // Successfully wrote buffer. Added a NULL terminator in case it wasn't written. + str[needed] = '\0'; + break; + } + size = needed > 0 ? (needed + 1) : (size * 2); + dynamicBuffer.resize(size); + str = &dynamicBuffer[0]; + } + logMessage += str; + +#if (TARGET_PLATFORM == PLATFORM_ANDROID) + __android_log_print(ANDROID_LOG_INFO, "LoseMyMind", "%s", logMessage.c_str()); +#elif TARGET_PLATFORM == PLATFORM_WIN32 + std::wstring wstr = StringUtils::string2UTF8wstring(logMessage.c_str()); + OutputDebugStringW(wstr.c_str()); + printf("%s", logMessage.c_str()); + fflush(stdout); +#else + // Linux, Mac, iOS, etc + fprintf(stdout, "%s", logMessage.c_str()); + fflush(stdout); +#endif +} + + + + diff --git a/VIServer/Classes/FoundationKit/GenericPlatformMacros.h b/VIServer/Classes/FoundationKit/GenericPlatformMacros.h new file mode 100644 index 0000000000..18d8d04e52 --- /dev/null +++ b/VIServer/Classes/FoundationKit/GenericPlatformMacros.h @@ -0,0 +1,220 @@ + +#ifndef LOSEMYMIND_GENERICPLATFORMMACROS_H +#define LOSEMYMIND_GENERICPLATFORMMACROS_H +#pragma once +#include +// namespace FoundationKit {} +#ifdef __cplusplus + #define NS_FK_BEGIN namespace FoundationKit { + #define NS_FK_END } + #define USING_NS_FK using namespace FoundationKit +#else + #define NS_FK_BEGIN + #define NS_FK_END + #define USING_NS_FK +#endif + +#if __cplusplus < 201103L +#define constexpr +#define noexcept +#endif + +// see https://sourceforge.net/p/predef/wiki/Compilers/ +// or boost\config\select_platform_config.hpp +// define supported target platform macro which to uses. +#define PLATFORM_UNKNOWN 0 +#define PLATFORM_IOS 1 +#define PLATFORM_ANDROID 2 +#define PLATFORM_WIN32 3 +#define PLATFORM_LINUX 4 +#define PLATFORM_MAC 5 + +#define TARGET_PLATFORM PLATFORM_UNKNOWN + +#if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) +// TARGET_OS_IPHONE inlcudes TARGET_OS_IOS TARGET_OS_TV and TARGET_OS_WATCH. see TargetConditionals.h +#include +#endif + +#if (TARGET_OS_IOS ) + #undef TARGET_PLATFORM + #define TARGET_PLATFORM PLATFORM_IOS + /** + * Macro for marking up deprecated code, functions and types. + * + * Features that are marked as deprecated are scheduled to be removed from the code base + * in a future release. If you are using a deprecated feature in your code, you should + * replace it before upgrading to the next release. See the Upgrade Notes in the release + * notes for the release in which the feature was marked deprecated. + * + * Sample usage (note the slightly different syntax for classes and structures): + * + * DEPRECATED(4.6, "Message") + * void Function(); + * + * struct DEPRECATED(4.6, "Message") MODULE_API MyStruct + * { + * // StructImplementation + * }; + * class DEPRECATED(4.6, "Message") MODULE_API MyClass + * { + * // ClassImplementation + * }; + * + * @param VERSION The release number in which the feature was marked deprecated. + * @param MESSAGE A message containing upgrade notes. + */ + #define DEPRECATED(VERSION, MESSAGE) __attribute__((deprecated(MESSAGE " Please update your code to the new API before upgrading to the next release, otherwise your project will no longer compile."))) + // Symbol export and import definitions + #define SYMBOL_EXPORT + #define SYMBOL_IMPORT + // Alignment. + #define ATTRIBUTE_PACK(n) __attribute__((packed,aligned(n))) + #define ATTRIBUTE_ALIGN(n) __attribute__((aligned(n))) + #define ATTRIBUTE_UNUSED __attribute__((unused))//__attribute__((__unused__)) ? + #define FORCEINLINE inline __attribute__ ((always_inline)) /* Force code to be inline */ + #define FORCENOINLINE __attribute__((noinline)) /* Force code to NOT be inline */ + #define THREAD_LOCAL __thread + #define FILEPATH_MAX MAX_PATH + + +#elif defined(__ANDROID__) || defined(ANDROID) + #undef TARGET_PLATFORM + #define TARGET_PLATFORM PLATFORM_ANDROID + #define DEPRECATED(VERSION, MESSAGE) __attribute__((deprecated(MESSAGE " Please update your code to the new API before upgrading to the next release, otherwise your project will no longer compile."))) + // Symbol export and import definitions + #define SYMBOL_EXPORT __attribute__((visibility("default"))) + #define SYMBOL_IMPORT __attribute__((visibility("default"))) + // Alignment. + #define ATTRIBUTE_PACK(n) __attribute__((packed,aligned(n))) + #define ATTRIBUTE_ALIGN(n) __attribute__((aligned(n))) + #define ATTRIBUTE_UNUSED __attribute__((unused))//__attribute__((__unused__)) ? + #define FORCEINLINE inline __attribute__ ((always_inline)) /* Force code to be inline */ + #define FORCENOINLINE __attribute__((noinline)) /* Force code to NOT be inline */ + #define THREAD_LOCAL __thread + #define FILEPATH_MAX PATH_MAX + + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) + #undef TARGET_PLATFORM + #define TARGET_PLATFORM PLATFORM_WIN32 + #define DEPRECATED(VERSION, MESSAGE) __declspec(deprecated(MESSAGE " Please update your code to the new API before upgrading to the next release, otherwise your project will no longer compile.")) + // Symbol export and import definitions + #define SYMBOL_EXPORT __declspec(dllexport) + #define SYMBOL_IMPORT __declspec(dllimport) + // Alignment. + #define ATTRIBUTE_PACK(n) + #define ATTRIBUTE_ALIGN(n) __declspec(align(n)) + #define ATTRIBUTE_UNUSED + #define FORCEINLINE __forceinline /* Force code to be inline */ + #define FORCENOINLINE __declspec(noinline) /* Force code to NOT be inline */ + #define THREAD_LOCAL __declspec(thread) + #define FILEPATH_MAX MAX_PATH + +#elif (defined(linux) || defined(__linux) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__)) && !defined(_CRAYC) + #undef TARGET_PLATFORM + #define TARGET_PLATFORM PLATFORM_LINUX + #define DEPRECATED(VERSION, MESSAGE) __attribute__((deprecated(MESSAGE " Please update your code to the new API before upgrading to the next release, otherwise your project will no longer compile."))) + // Symbol export and import definitions + #define SYMBOL_EXPORT __attribute__((visibility("default"))) + #define SYMBOL_IMPORT __attribute__((visibility("default"))) + // Alignment. + #define ATTRIBUTE_PACK(n) __attribute__((packed,aligned(n))) + #define ATTRIBUTE_ALIGN(n) __attribute__((aligned(n))) + #define ATTRIBUTE_UNUSED __attribute__((unused))//__attribute__((__unused__)) ? + #define FORCEINLINE inline __attribute__ ((always_inline)) /* Force code to be inline */ + #define FORCENOINLINE __attribute__((noinline)) /* Force code to NOT be inline */ + #define THREAD_LOCAL __thread + #define FILEPATH_MAX PATH_MAX + +#elif(TARGET_OS_MAC) + #undef TARGET_PLATFORM + #define TARGET_PLATFORM PLATFORM_MAC + #define DEPRECATED(VERSION, MESSAGE) __attribute__((deprecated(MESSAGE " Please update your code to the new API before upgrading to the next release, otherwise your project will no longer compile."))) + // Symbol export and import definitions + #define SYMBOL_EXPORT + #define SYMBOL_IMPORT + // Alignment. + #define ATTRIBUTE_PACK(n) __attribute__((packed,aligned(n))) + #define ATTRIBUTE_ALIGN(n) __attribute__((aligned(n))) + #define ATTRIBUTE_UNUSED __attribute__((unused)) //__attribute__((__unused__)) ? + #define FORCEINLINE inline __attribute__ ((always_inline)) /* Force code to be inline */ + #define FORCENOINLINE __attribute__((noinline)) /* Force code to NOT be inline */ + #define THREAD_LOCAL __thread + #define FILEPATH_MAX MAX_PATH + +#else + #error Unknown platform +#endif + +#define UNUSED_ARG(arg) do{(void)(arg);}while(0) + +#define SAFE_DELETE(p) do { delete (p); (p) = nullptr; } while(0) +#define SAFE_DELETE_ARRAY(p) do { if(p) { delete[] (p); (p) = nullptr; } } while(0) +#define SAFE_FREE(p) do { if(p) { free(p); (p) = nullptr; } } while(0) +#define SAFE_RELEASE(p) do { if(p) { (p)->release(); } } while(0) +#define SAFE_RELEASE_NULL(p) do { if(p) { (p)->release(); (p) = nullptr; } } while(0) +#define SAFE_RETAIN(p) do { if(p) { (p)->retain(); } } while(0) +#define BREAK_IF(cond) if(cond) break + +// Make a string to Wide string +#define TEXT_HELPER(a,b) a ## b +#define MAKE_TEXT(s) TEXT_HELPER(L, s) + +// Helper macro STRINGIZE: +// Converts the parameter X to a string after macro replacement +// on X has been performed. +#define STRINGIZE_HELPER(X) #X +#define STRINGIZE(X) STRINGIZE_HELPER(X) + +//#pragma message(COMPILE_MSG "Show compile message") +#define COMPILE_MSG __FILE__ "(" STRINGIZE(__LINE__) "):Warning:" + +extern void __fail__(const char* expr, const char* file, int line); +extern void __log__(const char* file, int line, const char* message, ...); +#if defined(_DEBUG) || defined(DEBUG) + #define ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : (__fail__(#CHECK, __FILE__, __LINE__), (EXPR))) + #define LOG_ASSERT(cond, msg,...) do{if (!(cond)){ __log__(__FILE__, __LINE__, msg, ##__VA_ARGS__);assert(cond);}} while (false) + #define DEBUG_MODE 1 +#else + #define ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR) + #define LOG_ASSERT(cond, msg,...) do{}while(false) + #define DEBUG_MODE 0 +#endif +#define LOG_CONDITION(cond,msg,...) do{if ((cond)){ __log__(__FILE__, __LINE__, msg, ##__VA_ARGS__);}} while (false) + +//=============================================================================================== +// Platform Pre-Setup +//=============================================================================================== +#if (TARGET_PLATFORM == PLATFORM_WIN32) +__pragma (warning(disable:4127)) +#define _XKEYCHECK_H // disable windows xkeycheck.h + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN 1 +#endif + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS 1 +#endif + +#ifndef _SCL_SECURE_NO_WARNINGS +#define _SCL_SECURE_NO_WARNINGS 1 +#endif + +#include + +#endif //(TARGET_PLATFORM == PLATFORM_WIN32) + +// IOS,ANDROID,MAC platform must be defined USE_FILE32API +//#ifndef USE_FILE32API +//#define USE_FILE32API 1 +//#endif + + +#endif // #ifndef LOSEMYMIND_GENERICPLATFORMMACROS_H + diff --git a/VIServer/Classes/FoundationKit/Platform/Environment.h b/VIServer/Classes/FoundationKit/Platform/Environment.h new file mode 100644 index 0000000000..a5fc0b42ea --- /dev/null +++ b/VIServer/Classes/FoundationKit/Platform/Environment.h @@ -0,0 +1,32 @@ +/**************************************************************************** + Copyright (c) 2016 libo All rights reserved. + + losemymind.libo@gmail.com + + ****************************************************************************/ +#ifndef LOSEMYMIND_ENVIRONMENT_H +#define LOSEMYMIND_ENVIRONMENT_H +#pragma once + +#include +#include "FoundationKit/GenericPlatformMacros.h" + +NS_FK_BEGIN + +class Environment +{ +public: + static std::string GetEnvironmentVariable(const std::string& variable); + static bool HasEnvironmentVariable(const std::string& variable); + static void SetEnvironmentVariable(const std::string& variable, const std::string& value); + static std::string GetMachineName(); + static std::string GetOSVersion(); +}; + + +NS_FK_END + + +#endif // LOSEMYMIND_ENVIRONMENT_H + + diff --git a/VIServer/Classes/FoundationKit/Platform/FileUtils.cpp b/VIServer/Classes/FoundationKit/Platform/FileUtils.cpp new file mode 100644 index 0000000000..4bfa46f273 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Platform/FileUtils.cpp @@ -0,0 +1,649 @@ +/**************************************************************************** + Copyright (c) 2015 libo All rights reserved. + + losemymind.libo@gmail.com + + ****************************************************************************/ +#include +#include +#include // for DIR +#include "FileUtils.h" +#include "FoundationKit/Foundation/Logger.h" +#include "FoundationKit/Foundation/StringUtils.h" +#include "unzip.h" + +//#include //ndk is not support + +#if (TARGET_PLATFORM==PLATFORM_WIN32) +#include +#endif + +#if (TARGET_PLATFORM==PLATFORM_IOS) +#define MINIZIP_FROM_SYSTEM +#endif + +NS_FK_BEGIN + +static Data getData(const std::string& filename, bool forString) +{ + if (filename.empty()) + { + return Data::Null; + } + + Data ret; + unsigned char* buffer = nullptr; + size_t size = 0; + size_t readsize = 0; + const char* mode = nullptr; + + if (forString) + mode = "rt"; + else + mode = "rb"; + + auto fileutils = FileUtils::getInstance(); + do + { + // Read the file from hardware + std::string fullPath = fileutils->fullPathForFilename(filename); + FILE *fp = fopen(fullPath.c_str(), mode); + BREAK_IF(!fp); + fseek(fp, 0, SEEK_END); + size = ftell(fp); + fseek(fp, 0, SEEK_SET); + + if (forString) + { + buffer = new unsigned char[sizeof(unsigned char) * (size + 1)]; + buffer[size] = '\0'; + } + else + { + buffer = new unsigned char[sizeof(unsigned char) * (size)]; + } + + readsize = fread(buffer, sizeof(unsigned char), size, fp); + fclose(fp); + + if (forString && readsize <= size) + { + buffer[readsize] = '\0'; + } + } while (0); + + if (nullptr == buffer || 0 == readsize) + { + LOG_ERROR("Get data from file %s failed", filename.c_str()); + } + else + { + ret.fastSet(buffer, readsize, true); + } + + return ret; +} + +FileUtils::FileUtils() +{ + initRootPath(); +} + +FileUtils::~FileUtils() +{ + +} + +void FileUtils::setDefaultResourceRootPath(const std::string& path) +{ + LOG_ASSERT(!path.empty(), "setDefaultResourceRootPath:Invalid path."); + _resourceRootPath = path; + if (_resourceRootPath.back() != '/' || _resourceRootPath.back() != '\\') + { + _resourceRootPath.push_back('/'); + } + + _resourceRootPath = convertPathFormatToUnixStyle(_resourceRootPath); +} + +std::string FileUtils::getResourceRootPath() +{ + return _resourceRootPath; +} + + +std::string FileUtils::fullPathForFilename(const std::string &filename) const +{ + if (filename.empty()) + { + return ""; + } + + if (isAbsolutePath(filename)) + { + return filename; + } + + for (const auto& searchIt : _searchPaths) + { + std::string fullPath = _resourceRootPath + searchIt + filename; + if (isFileExist(fullPath)) + { + return fullPath; + } + } + + // The file wasn't found, return empty string. + return ""; +} + +void FileUtils::setSearchPaths(const std::vector& searchPaths) +{ + _searchPaths = searchPaths; +} + +void FileUtils::addSearchPath(const std::string & searchpath, const bool front /*= false*/) +{ + std::string prefix; + if (!isAbsolutePath(searchpath)) + prefix = _resourceRootPath; + + std::string path = prefix + searchpath; + if (path.length() > 0 && path[path.length() - 1] != '/') + { + path += "/"; + } + if (front) { + _searchPaths.insert(_searchPaths.begin(), path); + } + else { + _searchPaths.push_back(path); + } +} + +const std::vector& FileUtils::getSearchPaths() const +{ + return _searchPaths; +} + +void FileUtils::setWritablePath(const std::string& writablePath) +{ + _writablePath = writablePath; +} + +bool FileUtils::isDirectoryExist(const std::string& dirPath) const +{ +#if (TARGET_PLATFORM==PLATFORM_WIN32) + std::wstring utf16Str = StringUtils::string2UTF8wstring(dirPath); + unsigned long fAttrib = GetFileAttributes(reinterpret_cast(utf16Str.c_str())); + if (fAttrib != INVALID_FILE_ATTRIBUTES && (fAttrib & FILE_ATTRIBUTE_DIRECTORY)) + { + return true; + } + return false; +#else + struct stat st; + if (stat(dirPath.c_str(), &st) == 0) + { + return S_ISDIR(st.st_mode); + } + return false; +#endif +} + +bool FileUtils::isDirectory(const std::string& path)const +{ + return path[path.size() - 1] == '/' || path[path.size() - 1] == '\\'; +} + +bool FileUtils::isAbsolutePath(const std::string& path) const +{ +#if (TARGET_PLATFORM==PLATFORM_WIN32) + if ((path.length() > 2 && + ((path[0] >= 'a' && path[0] <= 'z') || (path[0] >= 'A' && path[0] <= 'Z'))&& + path[1] == ':') || (path[0] == '/' && path[1] == '/')) + { + return true; + } + return false; +#else + return (path[0] == '/'); +#endif +} + +#if (TARGET_PLATFORM==PLATFORM_WIN32) +#else +#endif + + +std::string FileUtils::readStringFromFile(const std::string& filename) +{ + Data data = getData(filename, true); + if (data.isNull()) + return ""; + + std::string ret((const char*)data.getBytes()); + return ret; +} + +Data FileUtils::readDataFromFile(const std::string& filename) +{ + return getData(filename, false); +} + +Data FileUtils::readDataFromZip(const std::string& zipFilePath, const std::string& filename, size_t *size) +{ + Data retData; + unzFile file = nullptr; + *size = 0; + + do + { + BREAK_IF(zipFilePath.empty()); + + file = unzOpen(zipFilePath.c_str()); + BREAK_IF(!file); + + // FIXME: Other platforms should use upstream minizip like mingw-w64 +#ifdef MINIZIP_FROM_SYSTEM + int ret = unzLocateFile(file, filename.c_str(), NULL); +#else + int ret = unzLocateFile(file, filename.c_str(), 1); +#endif + BREAK_IF(UNZ_OK != ret); + + char filePathA[260]; + unz_file_info fileInfo; + ret = unzGetCurrentFileInfo(file, &fileInfo, filePathA, sizeof(filePathA), nullptr, 0, nullptr, 0); + BREAK_IF(UNZ_OK != ret); + + ret = unzOpenCurrentFile(file); + BREAK_IF(UNZ_OK != ret); + unsigned char * buffer = (unsigned char*)malloc(fileInfo.uncompressed_size); + int readedSize = unzReadCurrentFile(file, buffer, static_cast(fileInfo.uncompressed_size)); + LOG_ASSERT(readedSize == 0 || readedSize == (int)fileInfo.uncompressed_size, "the file size is wrong"); + UNUSED_ARG(readedSize); + *size = fileInfo.uncompressed_size; + unzCloseCurrentFile(file); + + retData.fastSet(buffer, *size, true); + + } while (0); + + if (file) + { + unzClose(file); + } + + return retData; +} + +bool FileUtils::writeStringToFile(const std::string& dataStr, const std::string& fullPath) +{ + Data retData; + retData.copy((unsigned char*)dataStr.c_str(), dataStr.size()); + return writeDataToFile(retData, fullPath); +} + +bool FileUtils::writeDataToFile(Data retData, const std::string& fullPath) +{ + LOG_ASSERT(!fullPath.empty() && retData.getSize() != 0, "Invalid parameters."); + do + { + size_t size = 0; + const char* mode = "wb"; + // Read the file from hardware + FILE *fp = fopen(fullPath.c_str(), mode); + BREAK_IF(!fp); + size = retData.getSize(); + fwrite(retData.getBytes(), size, 1, fp); + fclose(fp); + return true; + } while (0); + + return false; +} + +std::string FileUtils::getFileExtension(const std::string& filePath) const +{ + std::string fileExtension; + size_t pos = filePath.find_last_of('.'); + if (pos != std::string::npos) + { + fileExtension = filePath.substr(pos, filePath.length()); + + std::transform(fileExtension.begin(), fileExtension.end(), fileExtension.begin(), ::tolower); + } + + return fileExtension; +} + +std::string FileUtils::getFileName(const std::string& filePath)const +{ + std::string fileName = ""; + if (!isDirectory(filePath)) + { + size_t pos = filePath.find_last_of("/"); + if (pos != std::string::npos) + { + fileName = filePath.substr(pos + 1); + } + } + return fileName; +} + +std::string FileUtils::getFileNameWithoutExtension(const std::string& filePath)const +{ + std::string fileName = ""; + if (!isDirectory(filePath)) + { + size_t posStart = filePath.find_last_of("/"); + size_t posEnd = filePath.find_last_of("."); + if (posEnd == std::string::npos) + posEnd = filePath.size() - 1; + if (posStart != std::string::npos) + { + fileName = filePath.substr(posStart + 1, posEnd - posStart-1); + } + } + return fileName; +} + +std::string FileUtils::getFilePathWithoutFileName(const std::string& filePath)const +{ + std::string fileDir = ""; + if (!isDirectory(filePath)) + { + size_t pos = filePath.find_last_of("/"); + if (pos != std::string::npos) + { + fileDir = filePath.substr(0, pos + 1); + } + } + return fileDir; +} + +long FileUtils::getFileSize(const std::string &filepath)const +{ + LOG_ASSERT(!filepath.empty(), "Invalid path"); + + std::string fullpath = filepath; + if (!isAbsolutePath(filepath)) + { + fullpath = fullPathForFilename(filepath); + if (fullpath.empty()) + return 0; + } + + struct stat info; + // Get data associated with "crt_stat.c": + int result = stat(fullpath.c_str(), &info); + + // Check if statistics are valid: + if (result != 0) + { + // Failed + return -1; + } + else + { + return (long)(info.st_size); + } +} +bool FileUtils::copyFile(const std::string &oldfullpath, const std::string &newfullpath)const +{ + bool ret = false; + const size_t BUFF_SIZE = 1024; + do + { + BREAK_IF(oldfullpath == newfullpath); + const long srcFileSize = getFileSize(oldfullpath); + FILE *fpSrc = fopen(oldfullpath.c_str(), "rb"); + BREAK_IF(!fpSrc); + FILE *fpDes = fopen(newfullpath.c_str(), "wb"); + BREAK_IF(!fpDes); + char read_buff[BUFF_SIZE]; + long readedSize = 0; + long unreadSize = srcFileSize; + while (readedSize < srcFileSize) + { + if (unreadSize > BUFF_SIZE) + { + readedSize += fread(read_buff, sizeof(char), BUFF_SIZE, fpSrc); + fwrite(read_buff, 1, BUFF_SIZE, fpDes); + } + else + { + readedSize += fread(read_buff, sizeof(char), unreadSize, fpSrc); + fwrite(read_buff, 1, unreadSize, fpDes); + } + unreadSize = srcFileSize - readedSize; + } + fclose(fpSrc); + fclose(fpDes); + ret = true; + } while (false); + return ret; +} + +void FileUtils::getFilesFromDir(const std::string& dirPath, std::vector& files, bool includeChild)const +{ + std::string finallyPath = dirPath; + if (*(finallyPath.end() - 1) != '/' && *(finallyPath.end() - 1) != '\\') + { + finallyPath.append("/"); + } + DIR* dir =opendir(finallyPath.c_str()); + if (!dir) return; + dirent* entry = readdir(dir); + while (entry) + { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + { + entry = readdir(dir); + continue; + } + + if (entry->d_type == DT_REG) + { + files.push_back(finallyPath + entry->d_name); + } + if (entry->d_type == DT_DIR && includeChild) + { + std::string strChildDir = finallyPath + entry->d_name; + getFilesFromDir(strChildDir, files, includeChild); + } + + entry = readdir(dir); + } + closedir(dir); +} + +void FileUtils::getDirs(const std::string& dirPath, std::vector& dirs, bool includeChild)const +{ + std::string finallyPath = dirPath; + if (*(finallyPath.end() - 1) != '/' && *(finallyPath.end() - 1) != '\\') + { + finallyPath.append("/"); + } + DIR* dir = opendir(finallyPath.c_str()); + if (!dir) return; + dirent* entry = readdir(dir); + while (entry) + { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + { + entry = readdir(dir); + continue; + } + if (entry->d_type == DT_DIR) + { + dirs.push_back(finallyPath+entry->d_name); + if (includeChild) + { + getDirs(finallyPath + entry->d_name, dirs, includeChild); + } + } + + entry = readdir(dir); + } + closedir(dir); +} + +std::string FileUtils::getDirName(const std::string& dirPath)const +{ + std::string tempPath = convertPathFormatToUnixStyle(dirPath); + std::string dirName; + size_t pos = tempPath.find_last_of('/'); + if (pos != std::string::npos) + { + dirName = tempPath.substr(pos+1, tempPath.length()); + } + + return dirName; +} + + +#if (TARGET_PLATFORM == PLATFORM_WIN32) +// windows os implement should override in platform specific FileUtiles class +//bool moveFile(const std::string &oldfullpath, const std::string &newfullpath)const; +//bool createDirectory(const std::string& dirPath); +//bool removeDirectory(const std::string& dirPath); +//bool removeFile(const std::string &filepath); +//bool renameFile(const std::string &path, const std::string &oldname, const std::string &name); +//bool renameFile(const std::string &oldfullpath, const std::string &newfullpath); +#else +// default implements for unix like os +#include +#include +#include + +bool FileUtils::moveFile(const std::string &oldfullpath, const std::string &newfullpath)const +{ + return rename(oldfullpath.c_str(), oldfullpath.c_str()) != -1; +} + + +bool FileUtils::createDirectory(const std::string& path) +{ + LOG_ASSERT(!path.empty(), "Invalid path"); + + if (isDirectoryExist(path)) + return true; + + // Split the path + size_t start = 0; + size_t found = path.find_first_of("/\\", start); + std::string subpath; + std::vector dirs; + + if (found != std::string::npos) + { + while (true) + { + subpath = path.substr(start, found - start + 1); + if (!subpath.empty()) + dirs.push_back(subpath); + start = found + 1; + found = path.find_first_of("/\\", start); + if (found == std::string::npos) + { + if (start < path.length()) + { + dirs.push_back(path.substr(start)); + } + break; + } + } + } + + // Create path recursively + subpath = ""; + for (int i = 0; i < dirs.size(); ++i) + { + subpath += dirs[i]; + DIR *dir = opendir(subpath.c_str()); + + if (!dir) + { + // directory doesn't exist, should create a new one + + int ret = mkdir(subpath.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); + if (ret != 0 && (errno != EEXIST)) + { + // current directory can not be created, sub directories can not be created too + // should return + return false; + } + } + else + { + // directory exists, should close opened dir + closedir(dir); + } + } + return true; +} + +#if (TARGET_PLATFORM == PLATFORM_IOS) || (TARGET_PLATFORM == PLATFORM_MAC) +// IOS MAC implement should override in platform specific FileUtiles class +// bool FileUtils::removeDirectory(const std::string& path) +#else +bool FileUtils::removeDirectory(const std::string& path) +{ + if (path.size() > 0 && path[path.size() - 1] != '/') + { + LOG_ERROR("Fail to remove directory, path must termniate with '/': %s", path.c_str()); + return false; + } + + std::string command = "rm -r "; + // Path may include space. + command += "\"" + path + "\""; + if (system(command.c_str()) >= 0) + return true; + else + return false; +} +#endif //(TARGET_PLATFORM == PLATFORM_IOS) || (TARGET_PLATFORM == PLATFORM_MAC) + +bool FileUtils::removeFile(const std::string &path) +{ + if (remove(path.c_str())) { + return false; + } + else { + return true; + } +} + +bool FileUtils::renameFile(const std::string &oldfullpath, const std::string &newfullpath) +{ + LOG_ASSERT(!oldfullpath.empty(), "Invalid path"); + LOG_ASSERT(!newfullpath.empty(), "Invalid path"); + + int errorCode = rename(oldfullpath.c_str(), newfullpath.c_str()); + + if (0 != errorCode) + { + LOG_ERROR("Fail to rename file %s to %s !Error code is %d", oldfullpath.c_str(), newfullpath.c_str(), errorCode); + return false; + } + return true; +} + +bool FileUtils::renameFile(const std::string &path, const std::string &oldname, const std::string &name) +{ + LOG_ASSERT(!path.empty(), "Invalid path"); + std::string oldPath = path + oldname; + std::string newPath = path + name; + + return this->renameFile(oldPath, newPath); +} + + + +#endif //(TARGET_PLATFORM == PLATFORM_WIN32) || (TARGET_PLATFORM == PLATFORM_WINRT) + + +NS_FK_END diff --git a/VIServer/Classes/FoundationKit/Platform/FileUtils.h b/VIServer/Classes/FoundationKit/Platform/FileUtils.h new file mode 100644 index 0000000000..9505c4c254 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Platform/FileUtils.h @@ -0,0 +1,249 @@ +/**************************************************************************** + Copyright (c) 2015 libo All rights reserved. + + losemymind.libo@gmail.com + + ****************************************************************************/ +#ifndef LOSEMYMIND_FILEUTILS_H +#define LOSEMYMIND_FILEUTILS_H +#pragma once + +#include "FoundationKit/GenericPlatformMacros.h" +#include "FoundationKit/Base/Data.h" +#include "FoundationKit/Foundation/Singleton.h" +#include +#include + +NS_FK_BEGIN + +class FileUtils : public Singleton +{ +public: + ~FileUtils(); + + /** + * Set default resource root path. + */ + void setDefaultResourceRootPath(const std::string& path); + + std::string getResourceRootPath(); + + std::string fullPathForFilename(const std::string &filename) const; + + void setSearchPaths(const std::vector& searchPaths); + void addSearchPath(const std::string & searchpath, const bool front = false); + const std::vector& getSearchPaths() const; + void setWritablePath(const std::string& writablePath); + std::string getWritablePath() const; + + /** + * Checks whether the path is a directory. + * + * @param dirPath The path of the directory, it could be a relative or an absolute path. + * @return True if the directory exists, false if not. + */ + bool isDirectoryExist(const std::string& dirPath) const; + + + /** + * Checks whether the 'path' is a directory. + * + * @param path The path of the directory, it could be a relative or an absolute path. + * @return True if the 'path' is a directory, false if not. + */ + bool isDirectory(const std::string& path)const; + + /** + * Checks whether the path is an absolute path. + * + * @note On Android, if the parameter passed in is relative to "assets/", this method will treat it as an absolute path. + * Also on Blackberry, path starts with "app/native/Resources/" is treated as an absolute path. + * + * @param path The path that needs to be checked. + * @return True if it's an absolute path, false if not. + */ + bool isAbsolutePath(const std::string& path) const; + + /** + * Gets string from a file. + */ + std::string readStringFromFile(const std::string& filename); + + /** + * Creates binary data from a file. + * @return A data object. + */ + Data readDataFromFile(const std::string& filename); + + /** + * Gets resource file data from a zip file. + * + * @param[in] filename The resource file name which contains the relative path of the zip file. + * @param[out] size If the file read operation succeeds, it will be the data size, otherwise 0. + * @return Upon success, a pointer to the data is returned, otherwise nullptr. + * @warning Recall: you are responsible for calling free() on any Non-nullptr pointer returned. + */ + Data readDataFromZip(const std::string& zipFilePath, const std::string& filename, size_t *size); + + /** + * write a string into a file + * + * @param dataStr the string want to save + * @param fullPath The full path to the file you want to save a string + * @return bool True if write success + */ + bool writeStringToFile(const std::string& dataStr, const std::string& fullPath); + + /** + * write Data into a file + * + *@param retData the data want to save + *@param fullPath The full path to the file you want to save a string + *@return bool + */ + bool writeDataToFile(Data retData, const std::string& fullPath); + + /** + * Gets filename extension is a suffix (separated from the base filename by a dot) in lower case. + * Examples of filename extensions are .png, .jpeg, .exe, .dmg and .txt. + * @param filePath The path of the file, it could be a relative or absolute path. + * @return suffix for filename in lower case or empty if a dot not found. + */ + std::string getFileExtension(const std::string& filePath) const; + + std::string getFileName(const std::string& filePath)const; + std::string getFileNameWithoutExtension(const std::string& filePath)const; + std::string getFilePathWithoutFileName(const std::string& filePath)const; + + /** + * Retrieve the file size. + * + * @note If a relative path was passed in, it will be inserted a default root path at the beginning. + * @param filepath The path of the file, it could be a relative or absolute path. + * @return The file size. + */ + long getFileSize(const std::string &filepath)const; + + /** + * copy a file + * + * @param oldfullpath The current fullpath of the file. Includes path and name. + * @param newfullpath The new fullpath of the file. Includes path and name. + * @return True if the file have been copy successfully, false if not. + */ + bool copyFile(const std::string &oldfullpath, const std::string &newfullpath)const; + + /** + * move a file + * + * @param oldfullpath The current fullpath of the file. Includes path and name. + * @param newfullpath The new fullpath of the file. Includes path and name. + * @return True if the file have been move successfully, false if not. + */ + bool moveFile(const std::string &oldfullpath, const std::string &newfullpath)const; + + + /** + * get all files from a directory + * + * @param dirPath The path of the directory. + */ + void getFilesFromDir(const std::string& dirPath, std::vector& files, bool includeChild = false)const; + + /** + * get all files from a directory + * + * @param dirPath The path of the directory. + */ + void getDirs(const std::string& dirPath, std::vector& dirs, bool includeChild = false)const; + + std::string getDirName(const std::string& dirPath)const ; + + //===================================================================== + // Implementation in platform + //===================================================================== + + /** + * Checks whether a file exists. + * + * @note If a relative path was passed in, it will be inserted a default root path at the beginning. + * @param filename The path of the file, it could be a relative or absolute path. + * @return True if the file exists, false if not. + */ + bool isFileExist(const std::string& filename) const; + + /** + * Creates a directory. + * + * @param dirPath The path of the directory, it must be an absolute path. + * @return True if the directory have been created successfully, false if not. + */ + bool createDirectory(const std::string& dirPath); + + /** + * Removes a directory. + * + * @param dirPath The full path of the directory, it must be an absolute path. + * @return True if the directory have been removed successfully, false if not. + */ + bool removeDirectory(const std::string& dirPath); + + /** + * Removes a file. + * + * @param filepath The full path of the file, it must be an absolute path. + * @return True if the file have been removed successfully, false if not. + */ + bool removeFile(const std::string &filepath); + + /** + * Renames a file under the given directory. + * + * @param path The parent directory path of the file, it must be an absolute path. + * @param oldname The current name of the file. + * @param name The new name of the file. + * @return True if the file have been renamed successfully, false if not. + */ + bool renameFile(const std::string &path, const std::string &oldname, const std::string &name); + + /** + * Renames a file under the given directory. + * + * @param oldfullpath The current fullpath of the file. Includes path and name. + * @param newfullpath The new fullpath of the file. Includes path and name. + * @return True if the file have been renamed successfully, false if not. + */ + bool renameFile(const std::string &oldfullpath, const std::string &newfullpath); + +protected: + friend Singleton < FileUtils > ; + FileUtils(); + void initRootPath(); + + std::string _resourceRootPath; + std::string _writablePath; + std::vector _searchPaths; + + +}; + +// D:\aaa\bbb\ccc\ddd\abc.txt --> D:/aaa/bbb/ccc/ddd/abc.txt +static inline std::string convertPathFormatToUnixStyle(const std::string& path) +{ + std::string ret = path; + size_t len = ret.length(); + for (size_t i = 0; i < len; ++i) + { + if (ret[i] == '\\') + { + ret[i] = '/'; + } + } + return ret; +} + +NS_FK_END +#endif // LOSEMYMIND_FILEUTILS_H + + + diff --git a/VIServer/Classes/FoundationKit/Platform/OpenGL.h b/VIServer/Classes/FoundationKit/Platform/OpenGL.h new file mode 100644 index 0000000000..ec71d7aa8d --- /dev/null +++ b/VIServer/Classes/FoundationKit/Platform/OpenGL.h @@ -0,0 +1,80 @@ +/**************************************************************************** +Copyright (c) 2015 libo. + +losemymind.libo@gmail.com + +****************************************************************************/ +#ifndef LOSEMYMIND_OPENGL_H +#define LOSEMYMIND_OPENGL_H +#pragma once + +#include "FoundationKit/GenericPlatformMacros.h" + +#if (TARGET_PLATFORM == PLATFORM_IOS) + #define glClearDepth glClearDepthf + #define glDeleteVertexArrays glDeleteVertexArraysOES + #define glGenVertexArrays glGenVertexArraysOES + #define glBindVertexArray glBindVertexArrayOES + #define glMapBuffer glMapBufferOES + #define glUnmapBuffer glUnmapBufferOES + #define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_OES + #define GL_WRITE_ONLY GL_WRITE_ONLY_OES + #include + #include + +#elif (TARGET_PLATFORM == PLATFORM_ANDROID) + #define glClearDepth glClearDepthf + #define glDeleteVertexArrays glDeleteVertexArraysOES + #define glGenVertexArrays glGenVertexArraysOES + #define glBindVertexArray glBindVertexArrayOES + #define glMapBuffer glMapBufferOES + #define glUnmapBuffer glUnmapBufferOES + #define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_OES + #define GL_WRITE_ONLY GL_WRITE_ONLY_OES + // GL_GLEXT_PROTOTYPES isn't defined in glplatform.h on android ndk r7 + // we manually define it here + #include + #ifndef GL_GLEXT_PROTOTYPES + #define GL_GLEXT_PROTOTYPES 1 + #endif + // normal process + #include + #include + // gl2.h doesn't define GLchar on Android + typedef char GLchar; + // android defines GL_BGRA_EXT but not GL_BRGA + #ifndef GL_BGRA + #define GL_BGRA 0x80E1 + #endif + //declare here while define in EGLView_android.cpp + extern PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOESEXT; + extern PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOESEXT; + extern PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOESEXT; + #define glGenVertexArraysOES glGenVertexArraysOESEXT + #define glBindVertexArrayOES glBindVertexArrayOESEXT + #define glDeleteVertexArraysOES glDeleteVertexArraysOESEXT + + +#elif (TARGET_PLATFORM == PLATFORM_WIN32) + #include + #define CC_GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8 + +#elif (TARGET_PLATFORM == PLATFORM_LINUX) + #define CC_GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8 + +#elif (TARGET_PLATFORM == PLATFORM_MAC) + #import + #import + #import + #define CC_GL_DEPTH24_STENCIL8 -1 + #define glDeleteVertexArrays glDeleteVertexArraysAPPLE + #define glGenVertexArrays glGenVertexArraysAPPLE + #define glBindVertexArray glBindVertexArrayAPPLE + #define glClearDepthf glClearDepth + #define glDepthRangef glDepthRange + #define glReleaseShaderCompiler(xxx) + +#endif + + +#endif // LOSEMYMIND_OPENGL_H \ No newline at end of file diff --git a/VIServer/Classes/FoundationKit/Platform/Platform.cpp b/VIServer/Classes/FoundationKit/Platform/Platform.cpp new file mode 100644 index 0000000000..126868b545 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Platform/Platform.cpp @@ -0,0 +1,61 @@ +/**************************************************************************** +Copyright (c) 2015 libo. + +losemymind.libo@gmail.com + +****************************************************************************/ +#include "Platform.h" +NS_FK_BEGIN + +Platform::Platform() +{ + +} + +Platform::~Platform() +{ + +} + +// Default getTickCount impl +//int64 Platform::getTickCount() +//{ +// struct timeval tv; +// struct timezone tz; +// gettimeofday(&tv, &tz); +// return (int64)tv.tv_sec * 1000000 + tv.tv_usec; +//} + +int64 Platform::getCPUTickCount() +{ +#if defined(__i386__) + int64 x; + __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x)); + return x; +#elif defined(__x86_64__) + unsigned hi, lo; + __asm__ __volatile__("rdtsc" : "=a"(lo), "=d"(hi)); + return (int64)lo | ((int64)hi << 32); +#elif defined(__ppc__) + int64 result = 0; + unsigned upper, lower, tmp; + __asm__ volatile( + "0: \n" + "\tmftbu %0 \n" + "\tmftb %1 \n" + "\tmftbu %2 \n" + "\tcmpw %2,%0 \n" + "\tbne 0b \n" + : "=r"(upper), "=r"(lower), "=r"(tmp) + ); + return lower | ((int64)upper << 32); + +#elif defined _MSC_VER && defined WIN32 && defined _M_IX86 + __asm _emit 0x0f; + __asm _emit 0x31; +#else + return getTickCount(); +#endif +} + +NS_FK_END diff --git a/VIServer/Classes/FoundationKit/Platform/Platform.h b/VIServer/Classes/FoundationKit/Platform/Platform.h new file mode 100644 index 0000000000..5d64ea66c9 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Platform/Platform.h @@ -0,0 +1,57 @@ +/**************************************************************************** +Copyright (c) 2015 libo. + +losemymind.libo@gmail.com + +****************************************************************************/ +#ifndef LOSEMYMIND_PLATFORM_H +#define LOSEMYMIND_PLATFORM_H + +#pragma once +#include +#include +#include +#include "FoundationKit/GenericPlatformMacros.h" +#include "FoundationKit/Base/Types.h" + +NS_FK_BEGIN + +class Platform +{ +public: + Platform(); + ~Platform(); + + // MB + static float getTotalMemory(); + + // MB + static float getFreeMemory(); + + // MB + static float getProcessMemory(); + + + static std::string getMacAddress(bool isRaw = false); + + static std::string getDeviceId(); + + static std::string getDeviceName(); + + static std::string getOperatingSystemVersion(); + + static std::string getCPUArchitecture(); + + static void systemTime(int32& year, int32& month, int32& dayOfWeek, int32& day, int32& hour, int32& min, int32& sec, int32& msec); + static void utcTime(int32& year, int32& month, int32& dayOfWeek, int32& day, int32& hour, int32& min, int32& sec, int32& msec); + static int64 getTickCount(); + static int64 getCPUTickCount(); + + static std::vector getMacAddressRaw(); + +}; + +NS_FK_END +#endif // LOSEMYMIND_PLATFORM_H + + diff --git a/VIServer/Classes/FoundationKit/Platform/windows/EnvironmentWindows.cpp b/VIServer/Classes/FoundationKit/Platform/windows/EnvironmentWindows.cpp new file mode 100644 index 0000000000..8dcfa014d4 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Platform/windows/EnvironmentWindows.cpp @@ -0,0 +1,112 @@ + + +#include +#include "FoundationKit/Platform/Environment.h" +#include "FoundationKit/Foundation/Exception.h" +#include "FoundationKit/Foundation/Logger.h" + +NS_FK_BEGIN + +std::string Environment::GetEnvironmentVariable(const std::string& variable) +{ + DWORD len = GetEnvironmentVariableA(variable.c_str(), 0, 0); + if (len == 0) return ""; //throw NotFoundException(variable); + char* buffer = new char[len]; + GetEnvironmentVariableA(variable.c_str(), buffer, len); + std::string result(buffer); + delete[] buffer; + return result; +} + +bool Environment::HasEnvironmentVariable(const std::string& variable) +{ + DWORD len = GetEnvironmentVariableA(variable.c_str(), 0, 0); + return len > 0; +} + +void Environment::SetEnvironmentVariable(const std::string& variable, const std::string& value) +{ + if (SetEnvironmentVariableA(variable.c_str(), value.c_str()) == 0) + { + std::string msg = "cannot set environment variable: "; + msg.append(variable); + throw SystemException(msg); + } +} + +typedef LONG(NTAPI* fnRtlGetVersion)(PRTL_OSVERSIONINFOW lpVersionInformation); +std::string Environment::GetMachineName() +{ + RTL_OSVERSIONINFOEXW verInfo = { 0 }; + verInfo.dwOSVersionInfoSize = sizeof(verInfo); + static auto RtlGetVersion = (fnRtlGetVersion)GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlGetVersion"); + if (RtlGetVersion != 0) + RtlGetVersion((PRTL_OSVERSIONINFOW)&verInfo); + + switch (verInfo.dwMajorVersion) + { + case 10: + switch (verInfo.dwMinorVersion) + { + case 0: + return verInfo.wProductType == VER_NT_WORKSTATION ? "Windows 10" : "Windows Server 2016"; + } + case 6: + switch (verInfo.dwMinorVersion) + { + case 0: + return verInfo.wProductType == VER_NT_WORKSTATION ? "Windows Vista" : "Windows Server 2008"; + case 1: + return verInfo.wProductType == VER_NT_WORKSTATION ? "Windows 7" : "Windows Server 2008 R2"; + case 2: + return verInfo.wProductType == VER_NT_WORKSTATION ? "Windows 8" : "Windows Server 2012"; + case 3: + return verInfo.wProductType == VER_NT_WORKSTATION ? "Windows 8.1" : "Windows Server 2012 R2"; + default: + return "Unknown"; + } + case 5: + switch (verInfo.dwMinorVersion) + { + case 0: + return "Windows 2000"; + case 1: + return "Windows XP"; + case 2: + return "Windows Server 2003/Windows Server 2003 R2"; + default: + return "Unknown"; + } + default: + return "Unknown"; + } +} + +std::string Environment::GetOSVersion() +{ + RTL_OSVERSIONINFOEXW verInfo = { 0 }; + verInfo.dwOSVersionInfoSize = sizeof(verInfo); + static auto RtlGetVersion = (fnRtlGetVersion)GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlGetVersion"); + if (RtlGetVersion != 0 && RtlGetVersion((PRTL_OSVERSIONINFOW)&verInfo) == 0) + { + std::ostringstream str; + str << verInfo.dwMajorVersion << "." << verInfo.dwMinorVersion << " (Build " << (verInfo.dwBuildNumber & 0xFFFF); + if (verInfo.szCSDVersion[0]) str << ": " << verInfo.szCSDVersion; + str << ")"; + return str.str(); + } + else + { + //throw SystemException("Cannot get OS version information"); + LOG_ERROR("***** Cannot get OS version information."); + } + return ""; +} + + + +NS_FK_END + + + + diff --git a/VIServer/Classes/FoundationKit/Platform/windows/FileUtils_win32.cpp b/VIServer/Classes/FoundationKit/Platform/windows/FileUtils_win32.cpp new file mode 100644 index 0000000000..51013b9c99 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Platform/windows/FileUtils_win32.cpp @@ -0,0 +1,260 @@ +/**************************************************************************** +Copyright (c) 2015 libo. + +losemymind.libo@gmail.com + +****************************************************************************/ +#include "FoundationKit/GenericPlatformMacros.h" +#if (TARGET_PLATFORM == PLATFORM_WIN32) + +#include +#include +#include +#include +#include +#include "FoundationKit/Foundation/StringUtils.h" +#include "FoundationKit/Foundation/Logger.h" +#include "FoundationKit/Platform/FileUtils.h" + +NS_FK_BEGIN + +void FileUtils::initRootPath() +{ + if (0 == _resourceRootPath.length()) + { + WCHAR *pUtf16ExePath = nullptr; + + // If app character set is Unicode, the program entry use wmain, + // else use main, change _get_wpgmptr to _get_pgmptr + _get_wpgmptr(&pUtf16ExePath); + // We need only directory part without exe + WCHAR *pUtf16DirEnd = wcsrchr(pUtf16ExePath, L'\\'); + char utf8ExeDir[MAX_PATH] = { 0 }; + WideCharToMultiByte(CP_ACP, 0, pUtf16ExePath, pUtf16DirEnd - pUtf16ExePath + 1, utf8ExeDir, sizeof(utf8ExeDir), nullptr, nullptr); + _resourceRootPath = convertPathFormatToUnixStyle(utf8ExeDir); + } +} + +bool FileUtils::isFileExist(const std::string& filename) const +{ + if (filename.empty()) + return false; + + std::string fullPath = filename; + if (!isAbsolutePath(fullPath)) + { + fullPath.insert(0, _resourceRootPath); + } + + DWORD attr = GetFileAttributesW(StringUtils::string2UTF8wstring(fullPath).c_str()); + if (attr == INVALID_FILE_ATTRIBUTES || (attr & FILE_ATTRIBUTE_DIRECTORY)) + return false; + return true; +} + +bool FileUtils::moveFile(const std::string &oldfullpath, const std::string &newfullpath)const +{ + return MoveFileA(oldfullpath.c_str(), newfullpath.c_str()) != 0; +} + +bool FileUtils::createDirectory(const std::string& dirPath) +{ + if (isDirectoryExist(dirPath)) + return true; + + std::wstring path = StringUtils::string2UTF8wstring(dirPath); + + // Split the path + size_t start = 0; + size_t found = path.find_first_of(L"/\\", start); + std::wstring subpath; + std::vector dirs; + + if (found != std::wstring::npos) + { + while (true) + { + subpath = path.substr(start, found - start + 1); + if (!subpath.empty()) + dirs.push_back(subpath); + start = found + 1; + found = path.find_first_of(L"/\\", start); + if (found == std::wstring::npos) + { + if (start < path.length()) + { + dirs.push_back(path.substr(start)); + } + break; + } + } + } + + if ((GetFileAttributes(path.c_str())) == INVALID_FILE_ATTRIBUTES) + { + subpath = L""; + for (unsigned int i = 0; i < dirs.size(); ++i) + { + subpath += dirs[i]; + + std::string utf8Path = StringUtils::wstring2UTF8string(subpath); + if (!isDirectoryExist(utf8Path)) + { + BOOL ret = CreateDirectory(subpath.c_str(), NULL); + if (!ret && ERROR_ALREADY_EXISTS != GetLastError()) + { + LOG_ERROR("Fail create directory %s !Error code is 0x%x", utf8Path.c_str(), GetLastError()); + return false; + } + } + } + } + return true; +} + +bool FileUtils::removeDirectory(const std::string& dirPath) +{ + std::wstring wpath = StringUtils::string2UTF8wstring(dirPath); + std::wstring files = wpath + L"*.*"; + WIN32_FIND_DATA wfd; + HANDLE search = FindFirstFileEx(files.c_str(), FindExInfoStandard, &wfd, FindExSearchNameMatch, NULL, 0); + bool ret = true; + if (search != INVALID_HANDLE_VALUE) + { + BOOL find = true; + while (find) + { + //. .. + if (wfd.cFileName[0] != '.') + { + std::wstring temp = wpath + wfd.cFileName; + if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + temp += '/'; + ret = ret && this->removeDirectory(StringUtils::wstring2UTF8string(temp)); + } + else + { + SetFileAttributes(temp.c_str(), FILE_ATTRIBUTE_NORMAL); + ret = ret && DeleteFile(temp.c_str()); + } + } + find = FindNextFile(search, &wfd); + } + FindClose(search); + } + if (ret && RemoveDirectory(wpath.c_str())) + { + return true; + } + return false; +} + +bool FileUtils::removeFile(const std::string &filepath) +{ + std::regex pat("\\/"); + std::string win32path = std::regex_replace(filepath, pat, "\\"); + if (DeleteFile(StringUtils::string2UTF8wstring(win32path).c_str())) + { + return true; + } + else + { + LOG_ERROR("Fail remove file %s !Error code is 0x%x", filepath.c_str(), GetLastError()); + return false; + } +} + +bool FileUtils::renameFile(const std::string &path, const std::string &oldname, const std::string &name) +{ + std::string oldPath = path + oldname; + std::string newPath = path + name; + + std::regex pat("\\/"); + std::string _old = std::regex_replace(oldPath, pat, "\\"); + std::string _new = std::regex_replace(newPath, pat, "\\"); + + return renameFile(_old, _new); +} + +bool FileUtils::renameFile(const std::string &oldfullpath, const std::string &newfullpath) +{ + if (FileUtils::getInstance()->isFileExist(newfullpath)) + { + if (!DeleteFileA(newfullpath.c_str())) + { + LOG_ERROR("Fail to delete file %s !Error code is 0x%x", newfullpath.c_str(), GetLastError()); + } + } + + if (MoveFileA(oldfullpath.c_str(), newfullpath.c_str())) + { + return true; + } + else + { + LOG_ERROR("Fail to rename file %s to %s !Error code is 0x%x", oldfullpath.c_str(), newfullpath.c_str(), GetLastError()); + return false; + } +} + + +std::string FileUtils::getWritablePath() const +{ + if (_writablePath.length()) + { + return _writablePath; + } + + // Get full path of executable, e.g. c:\Program Files (x86)\My Game Folder\MyGame.exe + WCHAR full_path[MAX_PATH + 1] = { 0 }; + ::GetModuleFileName(nullptr, full_path, MAX_PATH + 1); + + // Debug app uses executable directory; Non-debug app uses local app data directory + //#ifndef _DEBUG + // Get filename of executable only, e.g. MyGame.exe + WCHAR *base_name = wcsrchr(full_path, '\\'); + std::wstring retPath; + if (base_name) + { + WCHAR app_data_path[MAX_PATH + 1]; + + // Get local app data directory, e.g. C:\Documents and Settings\username\Local Settings\Application Data + if (SUCCEEDED(SHGetFolderPath(nullptr, CSIDL_LOCAL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, app_data_path))) + { + std::wstring ret(app_data_path); + + // Adding executable filename, e.g. C:\Documents and Settings\username\Local Settings\Application Data\MyGame.exe + ret += base_name; + + // Remove ".exe" extension, e.g. C:\Documents and Settings\username\Local Settings\Application Data\MyGame + ret = ret.substr(0, ret.rfind(L".")); + + ret += L"\\"; + + // Create directory + if (SUCCEEDED(SHCreateDirectoryEx(nullptr, ret.c_str(), nullptr))) + { + retPath = ret; + } + } + } + if (retPath.empty()) + //#endif // not defined _DEBUG + { + // If fetching of local app data directory fails, use the executable one + retPath = full_path; + + // remove xxx.exe + retPath = retPath.substr(0, retPath.rfind(L"\\") + 1); + } + + return convertPathFormatToUnixStyle(StringUtils::wstring2UTF8string(retPath)); +} + + +NS_FK_END + +#endif + + diff --git a/VIServer/Classes/FoundationKit/Platform/windows/PlatformWindows.cpp b/VIServer/Classes/FoundationKit/Platform/windows/PlatformWindows.cpp new file mode 100644 index 0000000000..90e720d7f0 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Platform/windows/PlatformWindows.cpp @@ -0,0 +1,214 @@ +/**************************************************************************** +Copyright (c) 2015 libo. + +losemymind.libo@gmail.com + +****************************************************************************/ +#ifdef WIN32 +#include +#include +#include +#include +#include +#include "FoundationKit/GenericPlatformMacros.h" +#include "FoundationKit/Platform/Platform.h" +#include "FoundationKit/Platform/OpenGL.h" +#include "FoundationKit/Platform/Environment.h" +#include "FoundationKit/Foundation/Logger.h" +#include "FoundationKit/Foundation/StringUtils.h" +#include "FoundationKit/Base/Types.h" +#include "FoundationKit/Crypto/md5.hpp" + + +#pragma comment(lib,"Psapi.lib") + +// for getMacAddressUseGetAdaptersInfo +#include +#pragma comment(lib, "iphlpapi.lib") + + +NS_FK_BEGIN + +float Platform::getTotalMemory() +{ + long megabyte = 1024 * 1024; + MEMORYSTATUSEX memInfo; + memInfo.dwLength = sizeof(MEMORYSTATUSEX); + GlobalMemoryStatusEx(&memInfo); + DWORDLONG physical_memory = memInfo.ullTotalPhys; + return static_cast((physical_memory / megabyte)); +} + +float Platform::getFreeMemory() +{ + long megabyte = 1024 * 1024; + MEMORYSTATUSEX memInfo; + memInfo.dwLength = sizeof(MEMORYSTATUSEX); + GlobalMemoryStatusEx(&memInfo); + DWORDLONG free_memory = memInfo.ullAvailPhys; + return static_cast(free_memory / megabyte); +} + +float Platform::getProcessMemory() +{ + long megabyte = 1024 * 1024; + PROCESS_MEMORY_COUNTERS_EX pmc; + GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc)); + SIZE_T used_memory = pmc.WorkingSetSize; + return static_cast(used_memory / megabyte); +} + + + +std::string Platform::getMacAddress(bool isRaw /*= false*/) +{ + std::string result; + IP_ADAPTER_INFO IpAddresses[16]; + ULONG OutBufferLength = sizeof(IP_ADAPTER_INFO) * 16; + // Read the adapters + uint32 RetVal = GetAdaptersInfo(IpAddresses, &OutBufferLength); + if (RetVal == NO_ERROR) + { + PIP_ADAPTER_INFO AdapterList = IpAddresses; + // Walk the set of addresses copying each one + while (AdapterList) + { + // If there is an address to read + if (AdapterList->AddressLength > 0) + { + if (isRaw) + { + result = std::string((char*)&AdapterList->Address[0], 6); + } + else + { + // Copy the data and say we did + result = StringUtils::format("%02X%02X%02X%02X%02X%02X" + , AdapterList->Address[0] + , AdapterList->Address[1] + , AdapterList->Address[2] + , AdapterList->Address[3] + , AdapterList->Address[4] + , AdapterList->Address[5]); + } + + break; + } + AdapterList = AdapterList->Next; + } + } + return result; +} + +std::string Platform::getDeviceId() +{ + return MD5::md5_hash_hex(getMacAddress().c_str()); +} + +std::string Platform::getDeviceName() +{ + return Environment::GetMachineName(); +} + +std::string Platform::getOperatingSystemVersion() +{ + return Environment::GetOSVersion(); +} + +std::string Platform::getCPUArchitecture() +{ + SYSTEM_INFO stInfo; + GetSystemInfo(&stInfo); + //GetNativeSystemInfo(&stInfo); + WORD procArch = stInfo.wProcessorArchitecture; + if (procArch == PROCESSOR_ARCHITECTURE_INTEL) return "Intel x86"; + if (procArch == PROCESSOR_ARCHITECTURE_MIPS) return "mips"; + if (procArch == PROCESSOR_ARCHITECTURE_ALPHA) return "alpha x86"; + if (procArch == PROCESSOR_ARCHITECTURE_PPC) return "ppc"; + if (procArch == PROCESSOR_ARCHITECTURE_SHX) return "shx"; + if (procArch == PROCESSOR_ARCHITECTURE_ARM) return "arm"; + if (procArch == PROCESSOR_ARCHITECTURE_IA64) return "Intel x64"; + if (procArch == PROCESSOR_ARCHITECTURE_ALPHA64) return "alpha x64"; + if (procArch == PROCESSOR_ARCHITECTURE_MSIL) return "msil"; + if (procArch == PROCESSOR_ARCHITECTURE_AMD64) return "amd64"; + if (procArch == PROCESSOR_ARCHITECTURE_IA32_ON_WIN64) return "wow64"; + if (procArch == PROCESSOR_ARCHITECTURE_UNKNOWN) return "Intel x86"; + return "Unknown"; +} + +void Platform::systemTime(int32& year, int32& month, int32& dayOfWeek, int32& day, int32& hour, int32& min, int32& sec, int32& msec) +{ + SYSTEMTIME st; + GetLocalTime(&st); + year = st.wYear; + month = st.wMonth; + dayOfWeek = st.wDayOfWeek; + day = st.wDay; + hour = st.wHour; + min = st.wMinute; + sec = st.wSecond; + msec = st.wMilliseconds; +} + +void Platform::utcTime(int32& year, int32& month, int32& dayOfWeek, int32& day, int32& hour, int32& min, int32& sec, int32& msec) +{ + SYSTEMTIME st; + GetSystemTime(&st); + + year = st.wYear; + month = st.wMonth; + dayOfWeek = st.wDayOfWeek; + day = st.wDay; + hour = st.wHour; + min = st.wMinute; + sec = st.wSecond; + msec = st.wMilliseconds; +} + +int64 Platform::getTickCount() +{ + LARGE_INTEGER counter; + QueryPerformanceCounter(&counter); + return (int64)counter.QuadPart; +} + + +std::vector Platform::getMacAddressRaw() +{ + std::vector result; + IP_ADAPTER_INFO IpAddresses[16]; + ULONG OutBufferLength = sizeof(IP_ADAPTER_INFO) * 16; + // Read the adapters + uint32 RetVal = GetAdaptersInfo(IpAddresses, &OutBufferLength); + if (RetVal == NO_ERROR) + { + PIP_ADAPTER_INFO AdapterList = IpAddresses; + // Walk the set of addresses copying each one + while (AdapterList) + { + // If there is an address to read + if (AdapterList->AddressLength > 0) + { + result.resize(AdapterList->AddressLength); + std::memcpy(result.data(), AdapterList->Address, result.size()); + break; + } + AdapterList = AdapterList->Next; + } + } + return result; +} + + +NS_FK_END + +#endif + + + + + + + + + diff --git a/VIServer/Classes/FoundationKit/Platform/windows/ProtectedMemoryAllocator.cpp b/VIServer/Classes/FoundationKit/Platform/windows/ProtectedMemoryAllocator.cpp new file mode 100644 index 0000000000..2b43a9de1a --- /dev/null +++ b/VIServer/Classes/FoundationKit/Platform/windows/ProtectedMemoryAllocator.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +Copyright (c) 2015 libo. + +losemymind.libo@gmail.com + +****************************************************************************/ +#include "ProtectedMemoryAllocator.h" +#include +#include +ProtectedMemoryAllocator::ProtectedMemoryAllocator(size_t pool_size) + : _poolSize(pool_size) + , _nextAllocOffset(0) + , _valid(false) +{ + void* pAddress = VirtualAlloc(nullptr, _poolSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + _valid = (pAddress != nullptr); + _baseAddress = (unsigned long)pAddress; + assert(_valid); +} + +ProtectedMemoryAllocator::~ProtectedMemoryAllocator() +{ + VirtualFree(reinterpret_cast(_baseAddress), 0, MEM_RELEASE); +} + +char* ProtectedMemoryAllocator::allocate(vm_size_t size) +{ + if (_valid && _nextAllocOffset + size <= _poolSize) + { + char* p = reinterpret_cast(_baseAddress + _nextAllocOffset); + _nextAllocOffset += size; + return p; + } + return nullptr; +} + +bool ProtectedMemoryAllocator::protect() +{ + DWORD oldProp; + BOOL ret = VirtualProtect(reinterpret_cast(_baseAddress), _poolSize, PAGE_READONLY, &oldProp); + return ret != 0; +} + +bool ProtectedMemoryAllocator::unProtect() +{ + DWORD oldProp; + BOOL ret = VirtualProtect(reinterpret_cast(_baseAddress), _poolSize, PAGE_READWRITE, &oldProp); + return ret != 0; +} + +bool ProtectedMemoryAllocator::protect(vm_address_t address, vm_size_t size) +{ + DWORD oldProp; + BOOL ret = VirtualProtect(reinterpret_cast(address), size, PAGE_READONLY, &oldProp); + return ret != 0; +} + +bool ProtectedMemoryAllocator::unProtect(vm_address_t address, vm_size_t size) +{ + DWORD oldProp; + BOOL ret = VirtualProtect(reinterpret_cast(address), size, PAGE_READWRITE, &oldProp); + return ret != 0; +} diff --git a/VIServer/Classes/FoundationKit/Platform/windows/ProtectedMemoryAllocator.h b/VIServer/Classes/FoundationKit/Platform/windows/ProtectedMemoryAllocator.h new file mode 100644 index 0000000000..9f076ede13 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Platform/windows/ProtectedMemoryAllocator.h @@ -0,0 +1,75 @@ +/**************************************************************************** +Copyright (c) 2015 libo. + +losemymind.libo@gmail.com + +****************************************************************************/ +#ifndef LOSEMYMIND_PROTECTEDMEMORYALLOCATOR_H +#define LOSEMYMIND_PROTECTEDMEMORYALLOCATOR_H +#pragma once +#include + +typedef uintptr_t vm_offset_t; +typedef uintptr_t vm_size_t; +typedef vm_offset_t vm_address_t; + +class ProtectedMemoryAllocator +{ +public: + ProtectedMemoryAllocator() = delete; + ProtectedMemoryAllocator(const ProtectedMemoryAllocator&) = delete; + ProtectedMemoryAllocator& operator = (const ProtectedMemoryAllocator&) = delete; + + explicit ProtectedMemoryAllocator(size_t pool_size); + ~ProtectedMemoryAllocator(); + + char* allocate(vm_size_t size); + + char* getBaseAddress(){ return reinterpret_cast(_baseAddress); } + + vm_size_t getTotalSize(){ return _poolSize; } + + vm_size_t getAllocatedSize(){ return _nextAllocOffset; } + + bool protect(); + + bool unProtect(); + + static bool protect(vm_address_t address, vm_size_t size); + + static bool unProtect(vm_address_t address, vm_size_t size); + +private: + vm_size_t _poolSize; + vm_address_t _baseAddress; + vm_size_t _nextAllocOffset; + bool _valid; +}; + + +class ProtectedMemoryLocker +{ +public: + ProtectedMemoryLocker() = delete; + ProtectedMemoryLocker(const ProtectedMemoryLocker&) = delete; + ProtectedMemoryLocker& operator = (const ProtectedMemoryLocker&) = delete; + + explicit ProtectedMemoryLocker(ProtectedMemoryAllocator* allocator) :_allocator(allocator) + { + _mutex.lock(); + _allocator->unProtect(); + } + + ~ProtectedMemoryLocker() + { + _allocator->protect(); + _mutex.unlock(); + } + +private: + std::mutex _mutex; + ProtectedMemoryAllocator *_allocator; +}; +#endif // LOSEMYMIND_PROTECTEDMEMORYALLOCATOR_H + + diff --git a/VIServer/Classes/FoundationKit/Platform/windows/ProtectedMemoryAllocatorTest.h b/VIServer/Classes/FoundationKit/Platform/windows/ProtectedMemoryAllocatorTest.h new file mode 100644 index 0000000000..a0b25f6050 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Platform/windows/ProtectedMemoryAllocatorTest.h @@ -0,0 +1,46 @@ +#ifndef LOSEMYMIND_PROTECTEDMEMORYALLOCATORTEST_H +#define LOSEMYMIND_PROTECTEDMEMORYALLOCATORTEST_H + + + +#pragma once + + +#include "ProtectedMemoryAllocator.h" + +class MemObj +{ +public: + MemObj(int val):mem(val){} + ~MemObj(){}; + void set(int val){ mem = val; } + int get(){ return mem; } +private: + int mem; +}; + + +void TestProtectedMemoryAllocator() +{ + ProtectedMemoryAllocator mem_pool(2048); + + MemObj* pMemObj = new (mem_pool.allocate(sizeof(MemObj)))MemObj(100); + int v0 = pMemObj->get(); // 100 + pMemObj->set(200); + v0 = pMemObj->get(); // 200 + + mem_pool.protect(); + //pMemObj->set(300); //crash! because pMemObj memory is readonly. + { + ProtectedMemoryLocker lock(&mem_pool); + pMemObj->set(400); + } + + //pMemObj->set(500);//crash! because pMemObj memory is readonly. + +} + + +#endif // LOSEMYMIND_PROTECTEDMEMORYALLOCATORTEST_H + + diff --git a/VIServer/Classes/FoundationKit/Platform/windows/system/dirent.h b/VIServer/Classes/FoundationKit/Platform/windows/system/dirent.h new file mode 100644 index 0000000000..1c379bb6f3 --- /dev/null +++ b/VIServer/Classes/FoundationKit/Platform/windows/system/dirent.h @@ -0,0 +1,960 @@ +/* +* Dirent interface for Microsoft Visual Studio +* Version 1.21 +* +* Copyright (C) 2006-2012 Toni Ronkko +* This file is part of dirent. Dirent may be freely distributed +* under the MIT license. For all details and documentation, see +* https://github.com/tronkko/dirent +*/ +#ifndef _MSC_VER +#error "Use this header only with Microsoft Visual C++ compiles!." +#endif +#ifndef DIRENT_H +#define DIRENT_H +#include "FoundationKit/GenericPlatformMacros.h" +#if (TARGET_PLATFORM ==PLATFORM_WIN32 ) +#pragma warning( push ) +#pragma warning( disable : 4505 ) +#include +/* +* Include windows.h without Windows Sockets 1.1 to prevent conflicts with +* Windows Sockets 2.0. +*/ +#ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Indicates that d_type field is available in dirent structure */ +#define _DIRENT_HAVE_D_TYPE + +/* Indicates that d_namlen field is available in dirent structure */ +#define _DIRENT_HAVE_D_NAMLEN + +/* Entries missing from MSVC 6.0 */ +#if !defined(FILE_ATTRIBUTE_DEVICE) +# define FILE_ATTRIBUTE_DEVICE 0x40 +#endif + +/* File type and permission flags for stat(), general mask */ +#if !defined(S_IFMT) +# define S_IFMT _S_IFMT +#endif + +/* Directory bit */ +#if !defined(S_IFDIR) +# define S_IFDIR _S_IFDIR +#endif + +/* Character device bit */ +#if !defined(S_IFCHR) +# define S_IFCHR _S_IFCHR +#endif + +/* Pipe bit */ +#if !defined(S_IFFIFO) +# define S_IFFIFO _S_IFFIFO +#endif + +/* Regular file bit */ +#if !defined(S_IFREG) +# define S_IFREG _S_IFREG +#endif + +/* Read permission */ +#if !defined(S_IREAD) +# define S_IREAD _S_IREAD +#endif + +/* Write permission */ +#if !defined(S_IWRITE) +# define S_IWRITE _S_IWRITE +#endif + +/* Execute permission */ +#if !defined(S_IEXEC) +# define S_IEXEC _S_IEXEC +#endif + +/* Pipe */ +#if !defined(S_IFIFO) +# define S_IFIFO _S_IFIFO +#endif + +/* Block device */ +#if !defined(S_IFBLK) +# define S_IFBLK 0 +#endif + +/* Link */ +#if !defined(S_IFLNK) +# define S_IFLNK 0 +#endif + +/* Socket */ +#if !defined(S_IFSOCK) +# define S_IFSOCK 0 +#endif + +/* Read user permission */ +#if !defined(S_IRUSR) +# define S_IRUSR S_IREAD +#endif + +/* Write user permission */ +#if !defined(S_IWUSR) +# define S_IWUSR S_IWRITE +#endif + +/* Execute user permission */ +#if !defined(S_IXUSR) +# define S_IXUSR 0 +#endif + +/* Read group permission */ +#if !defined(S_IRGRP) +# define S_IRGRP 0 +#endif + +/* Write group permission */ +#if !defined(S_IWGRP) +# define S_IWGRP 0 +#endif + +/* Execute group permission */ +#if !defined(S_IXGRP) +# define S_IXGRP 0 +#endif + +/* Read others permission */ +#if !defined(S_IROTH) +# define S_IROTH 0 +#endif + +/* Write others permission */ +#if !defined(S_IWOTH) +# define S_IWOTH 0 +#endif + +/* Execute others permission */ +#if !defined(S_IXOTH) +# define S_IXOTH 0 +#endif + +/* Maximum length of file name */ +#if !defined(PATH_MAX) +# define PATH_MAX MAX_PATH +#endif +#if !defined(FILENAME_MAX) +# define FILENAME_MAX MAX_PATH +#endif +#if !defined(NAME_MAX) +# define NAME_MAX FILENAME_MAX +#endif + +/* File type flags for d_type */ +#define DT_UNKNOWN 0 +#define DT_REG S_IFREG +#define DT_DIR S_IFDIR +#define DT_FIFO S_IFIFO +#define DT_SOCK S_IFSOCK +#define DT_CHR S_IFCHR +#define DT_BLK S_IFBLK +#define DT_LNK S_IFLNK + +/* Macros for converting between st_mode and d_type */ +#define IFTODT(mode) ((mode) & S_IFMT) +#define DTTOIF(type) (type) + +/* +* File type macros. Note that block devices, sockets and links cannot be +* distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are +* only defined for compatibility. These macros should always return false +* on Windows. +*/ +#if !defined(S_ISFIFO) +# define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) +#endif +#if !defined(S_ISDIR) +# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#endif +#if !defined(S_ISREG) +# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) +#endif +#if !defined(S_ISLNK) +# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) +#endif +#if !defined(S_ISSOCK) +# define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) +#endif +#if !defined(S_ISCHR) +# define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) +#endif +#if !defined(S_ISBLK) +# define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) +#endif + +/* Return the exact length of d_namlen without zero terminator */ +#define _D_EXACT_NAMLEN(p) ((p)->d_namlen) + +/* Return number of bytes needed to store d_namlen */ +#define _D_ALLOC_NAMLEN(p) (PATH_MAX) + + +#ifdef __cplusplus +extern "C" { +#endif + + + /* Wide-character version */ + struct _wdirent { + /* Always zero */ + long d_ino; + + /* Structure size */ + unsigned short d_reclen; + + /* Length of name without \0 */ + size_t d_namlen; + + /* File type */ + int d_type; + + /* File name */ + wchar_t d_name[PATH_MAX]; + }; + typedef struct _wdirent _wdirent; + + struct _WDIR { + /* Current directory entry */ + struct _wdirent ent; + + /* Private file data */ + WIN32_FIND_DATAW data; + + /* True if data is valid */ + int cached; + + /* Win32 search handle */ + HANDLE handle; + + /* Initial directory name */ + wchar_t *patt; + }; + typedef struct _WDIR _WDIR; + + static _WDIR *_wopendir(const wchar_t *dirname); + static struct _wdirent *_wreaddir(_WDIR *dirp); + static int _wclosedir(_WDIR *dirp); + static void _wrewinddir(_WDIR* dirp); + + + /* For compatibility with Symbian */ +#define wdirent _wdirent +#define WDIR _WDIR +#define wopendir _wopendir +#define wreaddir _wreaddir +#define wclosedir _wclosedir +#define wrewinddir _wrewinddir + + + /* Multi-byte character versions */ + struct dirent { + /* Always zero */ + long d_ino; + + /* Structure size */ + unsigned short d_reclen; + + /* Length of name without \0 */ + size_t d_namlen; + + /* File type */ + int d_type; + + /* File name */ + char d_name[PATH_MAX]; + }; + typedef struct dirent dirent; + + struct DIR { + struct dirent ent; + struct _WDIR *wdirp; + }; + typedef struct DIR DIR; + + static DIR *opendir(const char *dirname); + static struct dirent *readdir(DIR *dirp); + static int closedir(DIR *dirp); + static void rewinddir(DIR* dirp); + + + /* Internal utility functions */ + static WIN32_FIND_DATAW *dirent_first(_WDIR *dirp); + static WIN32_FIND_DATAW *dirent_next(_WDIR *dirp); + + static int dirent_mbstowcs_s( + size_t *pReturnValue, + wchar_t *wcstr, + size_t sizeInWords, + const char *mbstr, + size_t count); + + static int dirent_wcstombs_s( + size_t *pReturnValue, + char *mbstr, + size_t sizeInBytes, + const wchar_t *wcstr, + size_t count); + + static void dirent_set_errno(int error); + + /* + * Open directory stream DIRNAME for read and return a pointer to the + * internal working area that is used to retrieve individual directory + * entries. + */ + static _WDIR* + _wopendir( + const wchar_t *dirname) + { + _WDIR *dirp = NULL; + int error; + + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno(ENOENT); + return NULL; + } + + /* Allocate new _WDIR structure */ + dirp = (_WDIR*)malloc(sizeof(struct _WDIR)); + if (dirp != NULL) { + DWORD n; + + /* Reset _WDIR structure */ + dirp->handle = INVALID_HANDLE_VALUE; + dirp->patt = NULL; + dirp->cached = 0; + + /* Compute the length of full path plus zero terminator + * + * Note that on WinRT there's no way to convert relative paths + * into absolute paths, so just assume its an absolute path. + */ +# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + n = wcslen(dirname); +# else + n = GetFullPathNameW(dirname, 0, NULL, NULL); +# endif + + /* Allocate room for absolute directory name and search pattern */ + dirp->patt = (wchar_t*)malloc(sizeof(wchar_t) * n + 16); + if (dirp->patt) { + + /* + * Convert relative directory name to an absolute one. This + * allows rewinddir() to function correctly even when current + * working directory is changed between opendir() and rewinddir(). + * + * Note that on WinRT there's no way to convert relative paths + * into absolute paths, so just assume its an absolute path. + */ +# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + wcsncpy_s(dirp->patt, n + 1, dirname, n); +# else + n = GetFullPathNameW(dirname, n, dirp->patt, NULL); +# endif + if (n > 0) { + wchar_t *p; + + /* Append search pattern \* to the directory name */ + p = dirp->patt + n; + if (dirp->patt < p) { + switch (p[-1]) { + case '\\': + case '/': + case ':': + /* Directory ends in path separator, e.g. c:\temp\ */ + /*NOP*/; + break; + + default: + /* Directory name doesn't end in path separator */ + *p++ = '\\'; + } + } + *p++ = '*'; + *p = '\0'; + + /* Open directory stream and retrieve the first entry */ + if (dirent_first(dirp)) { + /* Directory stream opened successfully */ + error = 0; + } + else { + /* Cannot retrieve first entry */ + error = 1; + dirent_set_errno(ENOENT); + } + + } + else { + /* Cannot retrieve full path name */ + dirent_set_errno(ENOENT); + error = 1; + } + + } + else { + /* Cannot allocate memory for search pattern */ + error = 1; + } + + } + else { + /* Cannot allocate _WDIR structure */ + error = 1; + } + + /* Clean up in case of error */ + if (error && dirp) { + _wclosedir(dirp); + dirp = NULL; + } + + return dirp; + } + + /* + * Read next directory entry. The directory entry is returned in dirent + * structure in the d_name field. Individual directory entries returned by + * this function include regular files, sub-directories, pseudo-directories + * "." and ".." as well as volume labels, hidden files and system files. + */ + static struct _wdirent* + _wreaddir( + _WDIR *dirp) + { + WIN32_FIND_DATAW *datap; + struct _wdirent *entp; + + /* Read next directory entry */ + datap = dirent_next(dirp); + if (datap) { + size_t n; + DWORD attr; + + /* Pointer to directory entry to return */ + entp = &dirp->ent; + + /* + * Copy file name as wide-character string. If the file name is too + * long to fit in to the destination buffer, then truncate file name + * to PATH_MAX characters and zero-terminate the buffer. + */ + n = 0; + while (n + 1 < PATH_MAX && datap->cFileName[n] != 0) { + entp->d_name[n] = datap->cFileName[n]; + n++; + } + dirp->ent.d_name[n] = 0; + + /* Length of file name excluding zero terminator */ + entp->d_namlen = n; + + /* File type */ + attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { + entp->d_type = DT_CHR; + } + else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { + entp->d_type = DT_DIR; + } + else { + entp->d_type = DT_REG; + } + + /* Reset dummy fields */ + entp->d_ino = 0; + entp->d_reclen = sizeof(struct _wdirent); + + } + else { + + /* Last directory entry read */ + entp = NULL; + + } + + return entp; + } + + /* + * Close directory stream opened by opendir() function. This invalidates the + * DIR structure as well as any directory entry read previously by + * _wreaddir(). + */ + static int + _wclosedir( + _WDIR *dirp) + { + int ok; + if (dirp) { + + /* Release search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) { + FindClose(dirp->handle); + dirp->handle = INVALID_HANDLE_VALUE; + } + + /* Release search pattern */ + if (dirp->patt) { + free(dirp->patt); + dirp->patt = NULL; + } + + /* Release directory structure */ + free(dirp); + ok = /*success*/0; + + } + else { + /* Invalid directory stream */ + dirent_set_errno(EBADF); + ok = /*failure*/-1; + } + return ok; + } + + /* + * Rewind directory stream such that _wreaddir() returns the very first + * file name again. + */ + static void + _wrewinddir( + _WDIR* dirp) + { + if (dirp) { + /* Release existing search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) { + FindClose(dirp->handle); + } + + /* Open new search handle */ + dirent_first(dirp); + } + } + + /* Get first directory entry (internal) */ + static WIN32_FIND_DATAW* + dirent_first( + _WDIR *dirp) + { + WIN32_FIND_DATAW *datap; + + /* Open directory and retrieve the first entry */ + dirp->handle = FindFirstFileExW( + dirp->patt, FindExInfoStandard, &dirp->data, + FindExSearchNameMatch, NULL, 0); + if (dirp->handle != INVALID_HANDLE_VALUE) { + + /* a directory entry is now waiting in memory */ + datap = &dirp->data; + dirp->cached = 1; + + } + else { + + /* Failed to re-open directory: no directory entry in memory */ + dirp->cached = 0; + datap = NULL; + + } + return datap; + } + + /* Get next directory entry (internal) */ + static WIN32_FIND_DATAW* + dirent_next( + _WDIR *dirp) + { + WIN32_FIND_DATAW *p; + + /* Get next directory entry */ + if (dirp->cached != 0) { + + /* A valid directory entry already in memory */ + p = &dirp->data; + dirp->cached = 0; + + } + else if (dirp->handle != INVALID_HANDLE_VALUE) { + + /* Get the next directory entry from stream */ + if (FindNextFileW(dirp->handle, &dirp->data) != FALSE) { + /* Got a file */ + p = &dirp->data; + } + else { + /* The very last entry has been processed or an error occured */ + FindClose(dirp->handle); + dirp->handle = INVALID_HANDLE_VALUE; + p = NULL; + } + + } + else { + + /* End of directory stream reached */ + p = NULL; + + } + + return p; + } + + /* + * Open directory stream using plain old C-string. + */ + static DIR* + opendir( + const char *dirname) + { + struct DIR *dirp; + int error; + + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno(ENOENT); + return NULL; + } + + /* Allocate memory for DIR structure */ + dirp = (DIR*)malloc(sizeof(struct DIR)); + if (dirp) { + wchar_t wname[PATH_MAX]; + size_t n; + + /* Convert directory name to wide-character string */ + error = dirent_mbstowcs_s(&n, wname, PATH_MAX, dirname, PATH_MAX); + if (!error) { + + /* Open directory stream using wide-character name */ + dirp->wdirp = _wopendir(wname); + if (dirp->wdirp) { + /* Directory stream opened */ + error = 0; + } + else { + /* Failed to open directory stream */ + error = 1; + } + + } + else { + /* + * Cannot convert file name to wide-character string. This + * occurs if the string contains invalid multi-byte sequences or + * the output buffer is too small to contain the resulting + * string. + */ + error = 1; + } + + } + else { + /* Cannot allocate DIR structure */ + error = 1; + } + + /* Clean up in case of error */ + if (error && dirp) { + free(dirp); + dirp = NULL; + } + + return dirp; + } + + /* + * Read next directory entry. + * + * When working with text consoles, please note that file names returned by + * readdir() are represented in the default ANSI code page while any output to + * console is typically formatted on another code page. Thus, non-ASCII + * characters in file names will not usually display correctly on console. The + * problem can be fixed in two ways: (1) change the character set of console + * to 1252 using chcp utility and use Lucida Console font, or (2) use + * _cprintf function when writing to console. The _cprinf() will re-encode + * ANSI strings to the console code page so many non-ASCII characters will + * display correcly. + */ + static struct dirent* + readdir( + DIR *dirp) + { + WIN32_FIND_DATAW *datap; + struct dirent *entp; + + /* Read next directory entry */ + datap = dirent_next(dirp->wdirp); + if (datap) { + size_t n; + int error; + + /* Attempt to convert file name to multi-byte string */ + error = dirent_wcstombs_s( + &n, dirp->ent.d_name, PATH_MAX, datap->cFileName, PATH_MAX); + + /* + * If the file name cannot be represented by a multi-byte string, + * then attempt to use old 8+3 file name. This allows traditional + * Unix-code to access some file names despite of unicode + * characters, although file names may seem unfamiliar to the user. + * + * Be ware that the code below cannot come up with a short file + * name unless the file system provides one. At least + * VirtualBox shared folders fail to do this. + */ + if (error && datap->cAlternateFileName[0] != '\0') { + error = dirent_wcstombs_s( + &n, dirp->ent.d_name, PATH_MAX, + datap->cAlternateFileName, PATH_MAX); + } + + if (!error) { + DWORD attr; + + /* Initialize directory entry for return */ + entp = &dirp->ent; + + /* Length of file name excluding zero terminator */ + entp->d_namlen = n - 1; + + /* File attributes */ + attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { + entp->d_type = DT_CHR; + } + else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { + entp->d_type = DT_DIR; + } + else { + entp->d_type = DT_REG; + } + + /* Reset dummy fields */ + entp->d_ino = 0; + entp->d_reclen = sizeof(struct dirent); + + } + else { + /* + * Cannot convert file name to multi-byte string so construct + * an errornous directory entry and return that. Note that + * we cannot return NULL as that would stop the processing + * of directory entries completely. + */ + entp = &dirp->ent; + entp->d_name[0] = '?'; + entp->d_name[1] = '\0'; + entp->d_namlen = 1; + entp->d_type = DT_UNKNOWN; + entp->d_ino = 0; + entp->d_reclen = 0; + } + + } + else { + /* No more directory entries */ + entp = NULL; + } + + return entp; + } + + /* + * Close directory stream. + */ + static int + closedir( + DIR *dirp) + { + int ok; + if (dirp) { + + /* Close wide-character directory stream */ + ok = _wclosedir(dirp->wdirp); + dirp->wdirp = NULL; + + /* Release multi-byte character version */ + free(dirp); + + } + else { + + /* Invalid directory stream */ + dirent_set_errno(EBADF); + ok = /*failure*/-1; + + } + return ok; + } + + /* + * Rewind directory stream to beginning. + */ + static void + rewinddir( + DIR* dirp) + { + /* Rewind wide-character string directory stream */ + _wrewinddir(dirp->wdirp); + } + + /* Convert multi-byte string to wide character string */ + static int + dirent_mbstowcs_s( + size_t *pReturnValue, + wchar_t *wcstr, + size_t sizeInWords, + const char *mbstr, + size_t count) + { + int error; + std::locale old_loc = std::locale::global(std::locale("")); +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 or later */ + error = mbstowcs_s(pReturnValue, wcstr, sizeInWords, mbstr, count); + +#else + + /* Older Visual Studio or non-Microsoft compiler */ + size_t n; + + /* Convert to wide-character string (or count characters) */ + n = mbstowcs(wcstr, mbstr, sizeInWords); + if (!wcstr || n < count) { + + /* Zero-terminate output buffer */ + if (wcstr && sizeInWords) { + if (n >= sizeInWords) { + n = sizeInWords - 1; + } + wcstr[n] = 0; + } + + /* Length of resuting multi-byte string WITH zero terminator */ + if (pReturnValue) { + *pReturnValue = n + 1; + } + + /* Success */ + error = 0; + + } + else { + + /* Could not convert string */ + error = 1; + + } + +#endif + std::locale::global(old_loc); + return error; + } + + /* Convert wide-character string to multi-byte string */ + static int + dirent_wcstombs_s( + size_t *pReturnValue, + char *mbstr, + size_t sizeInBytes, /* max size of mbstr */ + const wchar_t *wcstr, + size_t count) + { + int error; + std::locale old_loc = std::locale::global(std::locale("")); +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 or later */ + error = wcstombs_s(pReturnValue, mbstr, sizeInBytes, wcstr, count); + +#else + + /* Older Visual Studio or non-Microsoft compiler */ + size_t n; + + /* Convert to multi-byte string (or count the number of bytes needed) */ + n = wcstombs(mbstr, wcstr, sizeInBytes); + if (!mbstr || n < count) { + + /* Zero-terminate output buffer */ + if (mbstr && sizeInBytes) { + if (n >= sizeInBytes) { + n = sizeInBytes - 1; + } + mbstr[n] = '\0'; + } + + /* Length of resulting multi-bytes string WITH zero-terminator */ + if (pReturnValue) { + *pReturnValue = n + 1; + } + + /* Success */ + error = 0; + + } + else { + + /* Cannot convert string */ + error = 1; + + } + +#endif + std::locale::global(old_loc); + return error; + } + + /* Set errno variable */ + static void + dirent_set_errno( + int error) + { +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 and later */ + _set_errno(error); + +#else + + /* Non-Microsoft compiler or older Microsoft compiler */ + errno = error; + +#endif + } + + +#ifdef __cplusplus +} +#endif + +//#pragma warning( pop ) +#endif //#if (TARGET_PLATFORM ==PLATFORM_WIN32 ) +#endif /*DIRENT_H*/ diff --git a/VIServer/Classes/FoundationKit/Platform/windows/system/dirent_patch.txt b/VIServer/Classes/FoundationKit/Platform/windows/system/dirent_patch.txt new file mode 100644 index 0000000000..88c6f1b15f --- /dev/null +++ b/VIServer/Classes/FoundationKit/Platform/windows/system/dirent_patch.txt @@ -0,0 +1,41 @@ ++#ifndef _MSC_VER ++#error "Use this header only with Microsoft Visual C++ compiles!." ++#endif +#ifndef DIRENT_H +#define DIRENT_H ++#include "FoundationKit/GenericPlatformMacros.h" ++#if (TARGET_PLATFORM ==PLATFORM_WIN32 ) ++#pragma warning( push ) ++#pragma warning( disable : 4505 ) ++#include + + static int + dirent_mbstowcs_s( + size_t *pReturnValue, + wchar_t *wcstr, + size_t sizeInWords, + const char *mbstr, + size_t count) + { + int error; ++ std::locale old_loc = std::locale::global(std::locale("")); + +#endif ++ std::locale::global(old_loc); + return error; + + + static int + dirent_wcstombs_s( + size_t *pReturnValue, + char *mbstr, + size_t sizeInBytes, /* max size of mbstr */ + const wchar_t *wcstr, + size_t count) + { + int error; ++ std::locale old_loc = std::locale::global(std::locale("")); + +#endif ++ std::locale::global(old_loc); + return error; diff --git a/VIServer/Classes/FoundationKit/external/ConvertUTF/ConvertUTF.c b/VIServer/Classes/FoundationKit/external/ConvertUTF/ConvertUTF.c new file mode 100644 index 0000000000..0abde66fb4 --- /dev/null +++ b/VIServer/Classes/FoundationKit/external/ConvertUTF/ConvertUTF.c @@ -0,0 +1,589 @@ +/*===--- ConvertUTF.c - Universal Character Names conversions ---------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===------------------------------------------------------------------------=*/ +/* + * Copyright 2001-2004 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + +/* --------------------------------------------------------------------- + + Conversions between UTF32, UTF-16, and UTF-8. Source code file. + Author: Mark E. Davis, 1994. + Rev History: Rick McGowan, fixes & updates May 2001. + Sept 2001: fixed const & error conditions per + mods suggested by S. Parent & A. Lillich. + June 2002: Tim Dodd added detection and handling of incomplete + source sequences, enhanced error detection, added casts + to eliminate compiler warnings. + July 2003: slight mods to back out aggressive FFFE detection. + Jan 2004: updated switches in from-UTF8 conversions. + Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions. + + See the header file "ConvertUTF.h" for complete documentation. + +------------------------------------------------------------------------ */ + + +#include "ConvertUTF.h" +#ifdef CVTUTF_DEBUG +#include +#endif + +#include + +static const int halfShift = 10; /* used for shifting by 10 bits */ + +static const UTF32 halfBase = 0x0010000UL; +static const UTF32 halfMask = 0x3FFUL; + +#define UNI_SUR_HIGH_START (UTF32)0xD800 +#define UNI_SUR_HIGH_END (UTF32)0xDBFF +#define UNI_SUR_LOW_START (UTF32)0xDC00 +#define UNI_SUR_LOW_END (UTF32)0xDFFF +#define false 0 +#define true 1 + +/* --------------------------------------------------------------------- */ + +/* + * Index into the table below with the first byte of a UTF-8 sequence to + * get the number of trailing bytes that are supposed to follow it. + * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is + * left as-is for anyone who may want to do such conversion, which was + * allowed in earlier algorithms. + */ +static const char trailingBytesForUTF8[256] = { + 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, + 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, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 +}; + +/* + * Magic values subtracted from a buffer value during UTF8 conversion. + * This table contains as many values as there might be trailing bytes + * in a UTF-8 sequence. + */ +static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, + 0x03C82080UL, 0xFA082080UL, 0x82082080UL }; + +/* + * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed + * into the first byte, depending on how many bytes follow. There are + * as many entries in this table as there are UTF-8 sequence types. + * (I.e., one byte sequence, two byte... etc.). Remember that sequencs + * for *legal* UTF-8 will be 4 or fewer bytes total. + */ +static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + +/* --------------------------------------------------------------------- */ + +/* The interface converts a whole buffer to avoid function-call overhead. + * Constants have been gathered. Loops & conditionals have been removed as + * much as possible for efficiency, in favor of drop-through switches. + * (See "Note A" at the bottom of the file for equivalent code.) + * If your compiler supports it, the "isLegalUTF8" call can be turned + * into an inline function. + */ + + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF32toUTF16 ( + const UTF32** sourceStart, const UTF32* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF32* source = *sourceStart; + UTF16* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch; + if (target >= targetEnd) { + result = targetExhausted; break; + } + ch = *source++; + if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ + /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + if (flags == strictConversion) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + *target++ = (UTF16)ch; /* normal case */ + } + } else if (ch > UNI_MAX_LEGAL_UTF32) { + if (flags == strictConversion) { + result = sourceIllegal; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + /* target is a character in range 0xFFFF - 0x10FFFF. */ + if (target + 1 >= targetEnd) { + --source; /* Back up source pointer! */ + result = targetExhausted; break; + } + ch -= halfBase; + *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); + *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); + } + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF16toUTF32 ( + const UTF16** sourceStart, const UTF16* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF16* source = *sourceStart; + UTF32* target = *targetStart; + UTF32 ch, ch2; + while (source < sourceEnd) { + const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ + ch = *source++; + /* If we have a surrogate pair, convert to UTF32 first. */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { + /* If the 16 bits following the high surrogate are in the source buffer... */ + if (source < sourceEnd) { + ch2 = *source; + /* If it's a low surrogate, convert to UTF32. */ + if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { + ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + + (ch2 - UNI_SUR_LOW_START) + halfBase; + ++source; + } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } else { /* We don't have the 16 bits following the high surrogate. */ + --source; /* return to the high surrogate */ + result = sourceExhausted; + break; + } + } else if (flags == strictConversion) { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + if (target >= targetEnd) { + source = oldSource; /* Back up source pointer! */ + result = targetExhausted; break; + } + *target++ = ch; + } + *sourceStart = source; + *targetStart = target; +#ifdef CVTUTF_DEBUG +if (result == sourceIllegal) { + fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2); + fflush(stderr); +} +#endif + return result; +} +ConversionResult ConvertUTF16toUTF8 ( + const UTF16** sourceStart, const UTF16* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF16* source = *sourceStart; + UTF8* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch; + unsigned short bytesToWrite = 0; + const UTF32 byteMask = 0xBF; + const UTF32 byteMark = 0x80; + const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ + ch = *source++; + /* If we have a surrogate pair, convert to UTF32 first. */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { + /* If the 16 bits following the high surrogate are in the source buffer... */ + if (source < sourceEnd) { + UTF32 ch2 = *source; + /* If it's a low surrogate, convert to UTF32. */ + if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { + ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + + (ch2 - UNI_SUR_LOW_START) + halfBase; + ++source; + } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } else { /* We don't have the 16 bits following the high surrogate. */ + --source; /* return to the high surrogate */ + result = sourceExhausted; + break; + } + } else if (flags == strictConversion) { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + /* Figure out how many bytes the result will require */ + if (ch < (UTF32)0x80) { bytesToWrite = 1; + } else if (ch < (UTF32)0x800) { bytesToWrite = 2; + } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; + } else if (ch < (UTF32)0x110000) { bytesToWrite = 4; + } else { bytesToWrite = 3; + ch = UNI_REPLACEMENT_CHAR; + } + + target += bytesToWrite; + if (target > targetEnd) { + source = oldSource; /* Back up source pointer! */ + target -= bytesToWrite; result = targetExhausted; break; + } + switch (bytesToWrite) { /* note: everything falls through. */ + case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]); + } + target += bytesToWrite; + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF32toUTF8 ( + const UTF32** sourceStart, const UTF32* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF32* source = *sourceStart; + UTF8* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch; + unsigned short bytesToWrite = 0; + const UTF32 byteMask = 0xBF; + const UTF32 byteMark = 0x80; + ch = *source++; + if (flags == strictConversion ) { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + /* + * Figure out how many bytes the result will require. Turn any + * illegally large UTF32 things (> Plane 17) into replacement chars. + */ + if (ch < (UTF32)0x80) { bytesToWrite = 1; + } else if (ch < (UTF32)0x800) { bytesToWrite = 2; + } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; + } else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4; + } else { bytesToWrite = 3; + ch = UNI_REPLACEMENT_CHAR; + result = sourceIllegal; + } + + target += bytesToWrite; + if (target > targetEnd) { + --source; /* Back up source pointer! */ + target -= bytesToWrite; result = targetExhausted; break; + } + switch (bytesToWrite) { /* note: everything falls through. */ + case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]); + } + target += bytesToWrite; + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +/* + * Utility routine to tell whether a sequence of bytes is legal UTF-8. + * This must be called with the length pre-determined by the first byte. + * If not calling this from ConvertUTF8to*, then the length can be set by: + * length = trailingBytesForUTF8[*source]+1; + * and the sequence is illegal right away if there aren't that many bytes + * available. + * If presented with a length > 4, this returns false. The Unicode + * definition of UTF-8 goes up to 4-byte sequences. + */ + +static Boolean isLegalUTF8(const UTF8 *source, int length) { + UTF8 a; + const UTF8 *srcptr = source+length; + switch (length) { + default: return false; + /* Everything else falls through when "true"... */ + case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + case 2: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + + switch (*source) { + /* no fall-through in this inner switch */ + case 0xE0: if (a < 0xA0) return false; break; + case 0xED: if (a > 0x9F) return false; break; + case 0xF0: if (a < 0x90) return false; break; + case 0xF4: if (a > 0x8F) return false; break; + default: if (a < 0x80) return false; + } + + case 1: if (*source >= 0x80 && *source < 0xC2) return false; + } + if (*source > 0xF4) return false; + return true; +} + +/* --------------------------------------------------------------------- */ + +/* + * Exported function to return whether a UTF-8 sequence is legal or not. + * This is not used here; it's just exported. + */ +Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) { + int length = trailingBytesForUTF8[*source]+1; + if (length > sourceEnd - source) { + return false; + } + return isLegalUTF8(source, length); +} + +/* --------------------------------------------------------------------- */ + +/* + * Exported function to return the total number of bytes in a codepoint + * represented in UTF-8, given the value of the first byte. + */ +unsigned getNumBytesForUTF8(UTF8 first) { + return trailingBytesForUTF8[first] + 1; +} + +int getUTF8StringLength(const UTF8* utf8) +{ + const UTF8** source = &utf8; + const UTF8* sourceEnd = utf8 + strlen((const char*)utf8); + int ret = 0; + while (*source != sourceEnd) { + int length = trailingBytesForUTF8[**source] + 1; + if (length > sourceEnd - *source || !isLegalUTF8(*source, length)) + return 0; + *source += length; + ++ret; + } + return ret; +} + + +/* --------------------------------------------------------------------- */ + +/* + * Exported function to return whether a UTF-8 string is legal or not. + * This is not used here; it's just exported. + */ +Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd) { + while (*source != sourceEnd) { + int length = trailingBytesForUTF8[**source] + 1; + if (length > sourceEnd - *source || !isLegalUTF8(*source, length)) + return false; + *source += length; + } + return true; +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF8toUTF16 ( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF8* source = *sourceStart; + UTF16* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch = 0; + unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; + if (extraBytesToRead >= sourceEnd - source) { + result = sourceExhausted; break; + } + /* Do this check whether lenient or strict */ + if (!isLegalUTF8(source, extraBytesToRead+1)) { + result = sourceIllegal; + break; + } + /* + * The cases all fall through. See "Note A" below. + */ + switch (extraBytesToRead) { + case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ + case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ + case 3: ch += *source++; ch <<= 6; + case 2: ch += *source++; ch <<= 6; + case 1: ch += *source++; ch <<= 6; + case 0: ch += *source++; + } + ch -= offsetsFromUTF8[extraBytesToRead]; + + if (target >= targetEnd) { + source -= (extraBytesToRead+1); /* Back up source pointer! */ + result = targetExhausted; break; + } + if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + if (flags == strictConversion) { + source -= (extraBytesToRead+1); /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + *target++ = (UTF16)ch; /* normal case */ + } + } else if (ch > UNI_MAX_UTF16) { + if (flags == strictConversion) { + result = sourceIllegal; + source -= (extraBytesToRead+1); /* return to the start */ + break; /* Bail out; shouldn't continue */ + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + /* target is a character in range 0xFFFF - 0x10FFFF. */ + if (target + 1 >= targetEnd) { + source -= (extraBytesToRead+1); /* Back up source pointer! */ + result = targetExhausted; break; + } + ch -= halfBase; + *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); + *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); + } + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF8toUTF32 ( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF8* source = *sourceStart; + UTF32* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch = 0; + unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; + if (extraBytesToRead >= sourceEnd - source) { + result = sourceExhausted; break; + } + /* Do this check whether lenient or strict */ + if (!isLegalUTF8(source, extraBytesToRead+1)) { + result = sourceIllegal; + break; + } + /* + * The cases all fall through. See "Note A" below. + */ + switch (extraBytesToRead) { + case 5: ch += *source++; ch <<= 6; + case 4: ch += *source++; ch <<= 6; + case 3: ch += *source++; ch <<= 6; + case 2: ch += *source++; ch <<= 6; + case 1: ch += *source++; ch <<= 6; + case 0: ch += *source++; + } + ch -= offsetsFromUTF8[extraBytesToRead]; + + if (target >= targetEnd) { + source -= (extraBytesToRead+1); /* Back up the source pointer! */ + result = targetExhausted; break; + } + if (ch <= UNI_MAX_LEGAL_UTF32) { + /* + * UTF-16 surrogate values are illegal in UTF-32, and anything + * over Plane 17 (> 0x10FFFF) is illegal. + */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + if (flags == strictConversion) { + source -= (extraBytesToRead+1); /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + *target++ = ch; + } + } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */ + result = sourceIllegal; + *target++ = UNI_REPLACEMENT_CHAR; + } + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- + + Note A. + The fall-through switches in UTF-8 reading code save a + temp variable, some decrements & conditionals. The switches + are equivalent to the following loop: + { + int tmpBytesToRead = extraBytesToRead+1; + do { + ch += *source++; + --tmpBytesToRead; + if (tmpBytesToRead) ch <<= 6; + } while (tmpBytesToRead > 0); + } + In UTF-8 writing code, the switches on "bytesToWrite" are + similarly unrolled loops. + + --------------------------------------------------------------------- */ diff --git a/VIServer/Classes/FoundationKit/external/ConvertUTF/ConvertUTF.h b/VIServer/Classes/FoundationKit/external/ConvertUTF/ConvertUTF.h new file mode 100644 index 0000000000..3ef4ca14b7 --- /dev/null +++ b/VIServer/Classes/FoundationKit/external/ConvertUTF/ConvertUTF.h @@ -0,0 +1,253 @@ +/*===--- ConvertUTF.h - Universal Character Names conversions ---------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *==------------------------------------------------------------------------==*/ +/* + * Copyright 2001-2004 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + +/* --------------------------------------------------------------------- + + Conversions between UTF32, UTF-16, and UTF-8. Header file. + + Several funtions are included here, forming a complete set of + conversions between the three formats. UTF-7 is not included + here, but is handled in a separate source file. + + Each of these routines takes pointers to input buffers and output + buffers. The input buffers are const. + + Each routine converts the text between *sourceStart and sourceEnd, + putting the result into the buffer between *targetStart and + targetEnd. Note: the end pointers are *after* the last item: e.g. + *(sourceEnd - 1) is the last item. + + The return result indicates whether the conversion was successful, + and if not, whether the problem was in the source or target buffers. + (Only the first encountered problem is indicated.) + + After the conversion, *sourceStart and *targetStart are both + updated to point to the end of last text successfully converted in + the respective buffers. + + Input parameters: + sourceStart - pointer to a pointer to the source buffer. + The contents of this are modified on return so that + it points at the next thing to be converted. + targetStart - similarly, pointer to pointer to the target buffer. + sourceEnd, targetEnd - respectively pointers to the ends of the + two buffers, for overflow checking only. + + These conversion functions take a ConversionFlags argument. When this + flag is set to strict, both irregular sequences and isolated surrogates + will cause an error. When the flag is set to lenient, both irregular + sequences and isolated surrogates are converted. + + Whether the flag is strict or lenient, all illegal sequences will cause + an error return. This includes sequences such as: , , + or in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code + must check for illegal sequences. + + When the flag is set to lenient, characters over 0x10FFFF are converted + to the replacement character; otherwise (when the flag is set to strict) + they constitute an error. + + Output parameters: + The value "sourceIllegal" is returned from some routines if the input + sequence is malformed. When "sourceIllegal" is returned, the source + value will point to the illegal value that caused the problem. E.g., + in UTF-8 when a sequence is malformed, it points to the start of the + malformed sequence. + + Author: Mark E. Davis, 1994. + Rev History: Rick McGowan, fixes & updates May 2001. + Fixes & updates, Sept 2001. + +------------------------------------------------------------------------ */ + +#ifndef LLVM_SUPPORT_CONVERTUTF_H +#define LLVM_SUPPORT_CONVERTUTF_H + +#include /* ptrdiff_t */ +/* --------------------------------------------------------------------- + The following 4 definitions are compiler-specific. + The C standard does not guarantee that wchar_t has at least + 16 bits, so wchar_t is no less portable than unsigned short! + All should be unsigned values to avoid sign extension during + bit mask & shift operations. +------------------------------------------------------------------------ */ + +typedef unsigned int UTF32; /* at least 32 bits */ +typedef unsigned short UTF16; /* at least 16 bits */ +typedef unsigned char UTF8; /* typically 8 bits */ +typedef unsigned char Boolean; /* 0 or 1 */ + +/* Some fundamental constants */ +#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD +#define UNI_MAX_BMP (UTF32)0x0000FFFF +#define UNI_MAX_UTF16 (UTF32)0x0010FFFF +#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF +#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF + +#define UNI_MAX_UTF8_BYTES_PER_CODE_POINT 4 + +#define UNI_UTF16_BYTE_ORDER_MARK_NATIVE 0xFEFF +#define UNI_UTF16_BYTE_ORDER_MARK_SWAPPED 0xFFFE + +typedef enum { + conversionOK, /* conversion successful */ + sourceExhausted, /* partial character in source, but hit end */ + targetExhausted, /* insuff. room in target for conversion */ + sourceIllegal /* source sequence is illegal/malformed */ +} ConversionResult; + +typedef enum { + strictConversion = 0, + lenientConversion +} ConversionFlags; + +/* This is for C++ and does no harm in C */ +#ifdef __cplusplus +extern "C" { +#endif + +ConversionResult ConvertUTF8toUTF16 ( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF8toUTF32 ( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF16toUTF8 ( + const UTF16** sourceStart, const UTF16* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF32toUTF8 ( + const UTF32** sourceStart, const UTF32* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF16toUTF32 ( + const UTF16** sourceStart, const UTF16* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF32toUTF16 ( + const UTF32** sourceStart, const UTF32* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); + +Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd); + +Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd); + +unsigned getNumBytesForUTF8(UTF8 firstByte); + +int getUTF8StringLength(const UTF8* utf8); + +#ifdef __cplusplus +} + +/*************************************************************************/ +/* Below are LLVM-specific wrappers of the functions above. */ + +//#include "llvm/ADT/ArrayRef.h" +//#include "llvm/ADT/StringRef.h" + +#include +#include +namespace llvm { + +/** + * Convert an UTF8 StringRef to UTF8, UTF16, or UTF32 depending on + * WideCharWidth. The converted data is written to ResultPtr, which needs to + * point to at least WideCharWidth * (Source.Size() + 1) bytes. On success, + * ResultPtr will point one after the end of the copied string. On failure, + * ResultPtr will not be changed, and ErrorPtr will be set to the location of + * the first character which could not be converted. + * \return true on success. + */ +bool ConvertUTF8toWide(unsigned WideCharWidth, const std::string& Source, + char *&ResultPtr, const UTF8 *&ErrorPtr); + +/** + * Convert an Unicode code point to UTF8 sequence. + * + * \param Source a Unicode code point. + * \param [in,out] ResultPtr pointer to the output buffer, needs to be at least + * \c UNI_MAX_UTF8_BYTES_PER_CODE_POINT bytes. On success \c ResultPtr is + * updated one past end of the converted sequence. + * + * \returns true on success. + */ +bool ConvertCodePointToUTF8(unsigned Source, char *&ResultPtr); + +/** + * Convert the first UTF8 sequence in the given source buffer to a UTF32 + * code point. + * + * \param [in,out] source A pointer to the source buffer. If the conversion + * succeeds, this pointer will be updated to point to the byte just past the + * end of the converted sequence. + * \param sourceEnd A pointer just past the end of the source buffer. + * \param [out] target The converted code + * \param flags Whether the conversion is strict or lenient. + * + * \returns conversionOK on success + * + * \sa ConvertUTF8toUTF32 + */ +static inline ConversionResult convertUTF8Sequence(const UTF8 **source, + const UTF8 *sourceEnd, + UTF32 *target, + ConversionFlags flags) { + if (*source == sourceEnd) + return sourceExhausted; + unsigned size = getNumBytesForUTF8(**source); + if ((ptrdiff_t)size > sourceEnd - *source) + return sourceExhausted; + return ConvertUTF8toUTF32(source, *source + size, &target, target + 1, flags); +} + +/** + * Returns true if a blob of text starts with a UTF-16 big or little endian byte + * order mark. + */ +bool hasUTF16ByteOrderMark(const char* SrcBytes, size_t len); + +/** + * Converts a stream of raw bytes assumed to be UTF16 into a UTF8 std::string. + * + * \param [in] SrcBytes A buffer of what is assumed to be UTF-16 encoded text. + * \param [out] Out Converted UTF-8 is stored here on success. + * \returns true on success + */ +bool convertUTF16ToUTF8String(const std::u16string& utf16, std::string &Out); + +} /* end namespace llvm */ + +#endif + +/* --------------------------------------------------------------------- */ + +#endif diff --git a/VIServer/Classes/FoundationKit/external/ConvertUTF/ConvertUTFWrapper.cpp b/VIServer/Classes/FoundationKit/external/ConvertUTF/ConvertUTFWrapper.cpp new file mode 100644 index 0000000000..278bdd4897 --- /dev/null +++ b/VIServer/Classes/FoundationKit/external/ConvertUTF/ConvertUTFWrapper.cpp @@ -0,0 +1,144 @@ +//===-- ConvertUTFWrapper.cpp - Wrap ConvertUTF.h with clang data types -----=== +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ConvertUTF.h" +//#include "llvm/Support/SwapByteOrder.h" +#include +#include +#include // uint16_t +#include +#include + +namespace llvm { + +bool ConvertUTF8toWide(unsigned WideCharWidth, const std::string& Source, + char *&ResultPtr, const UTF8 *&ErrorPtr) { + assert(WideCharWidth == 1 || WideCharWidth == 2 || WideCharWidth == 4); + ConversionResult result = conversionOK; + // Copy the character span over. + if (WideCharWidth == 1) { + const UTF8 *Pos = reinterpret_cast(Source.data()); + if (!isLegalUTF8String(&Pos, reinterpret_cast(Source.data() + Source.length()))) { + result = sourceIllegal; + ErrorPtr = Pos; + } else { + memcpy(ResultPtr, Source.data(), Source.size()); + ResultPtr += Source.size(); + } + } else if (WideCharWidth == 2) { + const UTF8 *sourceStart = (const UTF8*)Source.data(); + // FIXME: Make the type of the result buffer correct instead of + // using reinterpret_cast. + UTF16 *targetStart = reinterpret_cast(ResultPtr); + ConversionFlags flags = strictConversion; + result = ConvertUTF8toUTF16( + &sourceStart, sourceStart + Source.size(), + &targetStart, targetStart + 2*Source.size(), flags); + if (result == conversionOK) + ResultPtr = reinterpret_cast(targetStart); + else + ErrorPtr = sourceStart; + } else if (WideCharWidth == 4) { + const UTF8 *sourceStart = (const UTF8*)Source.data(); + // FIXME: Make the type of the result buffer correct instead of + // using reinterpret_cast. + UTF32 *targetStart = reinterpret_cast(ResultPtr); + ConversionFlags flags = strictConversion; + result = ConvertUTF8toUTF32( + &sourceStart, sourceStart + Source.size(), + &targetStart, targetStart + 4*Source.size(), flags); + if (result == conversionOK) + ResultPtr = reinterpret_cast(targetStart); + else + ErrorPtr = sourceStart; + } + assert((result != targetExhausted) + && "ConvertUTF8toUTFXX exhausted target buffer"); + return result == conversionOK; +} + +bool ConvertCodePointToUTF8(unsigned Source, char *&ResultPtr) { + const UTF32 *SourceStart = &Source; + const UTF32 *SourceEnd = SourceStart + 1; + UTF8 *TargetStart = reinterpret_cast(ResultPtr); + UTF8 *TargetEnd = TargetStart + 4; + ConversionResult CR = ConvertUTF32toUTF8(&SourceStart, SourceEnd, + &TargetStart, TargetEnd, + strictConversion); + if (CR != conversionOK) + return false; + + ResultPtr = reinterpret_cast(TargetStart); + return true; +} + +bool hasUTF16ByteOrderMark(const char* S, size_t len) { + return (len >= 2 && + ((S[0] == '\xff' && S[1] == '\xfe') || + (S[0] == '\xfe' && S[1] == '\xff'))); +} + +/// SwapByteOrder_16 - This function returns a byte-swapped representation of +/// the 16-bit argument. +inline uint16_t SwapByteOrder_16(uint16_t value) { +#if defined(_MSC_VER) && !defined(_DEBUG) + // The DLL version of the runtime lacks these functions (bug!?), but in a + // release build they're replaced with BSWAP instructions anyway. + return _byteswap_ushort(value); +#else + uint16_t Hi = value << 8; + uint16_t Lo = value >> 8; + return Hi | Lo; +#endif +} + +bool convertUTF16ToUTF8String(const std::u16string& utf16, std::string &Out) { + assert(Out.empty()); + + // Avoid OOB by returning early on empty input. + if (utf16.empty()) + return true; + + const UTF16 *Src = reinterpret_cast(utf16.data()); + const UTF16 *SrcEnd = reinterpret_cast(utf16.data() + utf16.length()); + + // Byteswap if necessary. + std::vector ByteSwapped; + if (Src[0] == UNI_UTF16_BYTE_ORDER_MARK_SWAPPED) { + ByteSwapped.insert(ByteSwapped.end(), Src, SrcEnd); + for (size_t I = 0, E = ByteSwapped.size(); I != E; ++I) + ByteSwapped[I] = SwapByteOrder_16(ByteSwapped[I]); + Src = &ByteSwapped[0]; + SrcEnd = &ByteSwapped[ByteSwapped.size() - 1] + 1; + } + + // Skip the BOM for conversion. + if (Src[0] == UNI_UTF16_BYTE_ORDER_MARK_NATIVE) + Src++; + + // Just allocate enough space up front. We'll shrink it later. + Out.resize(utf16.length() * UNI_MAX_UTF8_BYTES_PER_CODE_POINT + 1); + UTF8 *Dst = reinterpret_cast(&Out[0]); + UTF8 *DstEnd = Dst + Out.size(); + + ConversionResult CR = + ConvertUTF16toUTF8(&Src, SrcEnd, &Dst, DstEnd, strictConversion); + assert(CR != targetExhausted); + + if (CR != conversionOK) { + Out.clear(); + return false; + } + + Out.resize(reinterpret_cast(Dst) - &Out[0]); + return true; +} + +} // end namespace llvm + diff --git a/VIServer/Classes/FoundationKit/external/unzip/ioapi.cpp b/VIServer/Classes/FoundationKit/external/unzip/ioapi.cpp new file mode 100644 index 0000000000..4ca6f0e89d --- /dev/null +++ b/VIServer/Classes/FoundationKit/external/unzip/ioapi.cpp @@ -0,0 +1,251 @@ +/* ioapi.h -- IO base function header for compress/uncompress .zip + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + +*/ + +#include "ioapi.h" + + +voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode) +{ + if (pfilefunc->zfile_func64.zopen64_file != NULL) + return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode); + else + { + return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,(const char*)filename,mode); + } +} + +long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin) +{ + if (pfilefunc->zfile_func64.zseek64_file != NULL) + return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin); + else + { + uLong offsetTruncated = (uLong)offset; + if (offsetTruncated != offset) + return -1; + else + return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin); + } +} + +ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream) +{ + if (pfilefunc->zfile_func64.zseek64_file != NULL) + return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream); + else + { + uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream); + if ((tell_uLong) == ((uLong)-1)) + return (ZPOS64_T)-1; + else + return tell_uLong; + } +} + +void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32) +{ + p_filefunc64_32->zfile_func64.zopen64_file = NULL; + p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file; + p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; + p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file; + p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file; + p_filefunc64_32->zfile_func64.ztell64_file = NULL; + p_filefunc64_32->zfile_func64.zseek64_file = NULL; + p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file; + p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; + p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque; + p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file; + p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file; +} + + + +static voidpf ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode)); +static uLong ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +static uLong ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size)); +static ZPOS64_T ZCALLBACK ftell64_file_func OF((voidpf opaque, voidpf stream)); +static long ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); +static int ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream)); +static int ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream)); + +static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode) +{ + (void)(opaque); + FILE* file = NULL; + const char* mode_fopen = NULL; + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) + mode_fopen = "rb"; + else + if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + mode_fopen = "r+b"; + else + if (mode & ZLIB_FILEFUNC_MODE_CREATE) + mode_fopen = "wb"; + + if ((filename!=NULL) && (mode_fopen != NULL)) + file = fopen(filename, mode_fopen); + return file; +} + +static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode) +{ + (void)(opaque); + FILE* file = NULL; + const char* mode_fopen = NULL; + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) + mode_fopen = "rb"; + else + if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + mode_fopen = "r+b"; + else + if (mode & ZLIB_FILEFUNC_MODE_CREATE) + mode_fopen = "wb"; + + if ((filename!=NULL) && (mode_fopen != NULL)) + { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_MARMALADE || CC_TARGET_PLATFORM == CC_PLATFORM_BADA || CC_TARGET_PLATFORM == CC_PLATFORM_BLACKBERRY || CC_TARGET_PLATFORM == CC_PLATFORM_NACL || CC_TARGET_PLATFORM == CC_PLATFORM_EMSCRIPTEN) + file = NULL; +#else + file = fopen64((const char*)filename, mode_fopen); +#endif + } + + return file; +} + + +static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size) +{ + (void)(opaque); + uLong ret; + ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + +static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size) +{ + (void)(opaque); + uLong ret; + ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + +static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream) +{ + (void)(opaque); + long ret; + ret = ftell((FILE *)stream); + return ret; +} + + +static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream) +{ + (void)(opaque); + (void)(stream); + ZPOS64_T ret; +#if (CC_TARGET_PLATFORM == CC_PLATFORM_MARMALADE || CC_TARGET_PLATFORM == CC_PLATFORM_BADA || CC_TARGET_PLATFORM == CC_PLATFORM_BLACKBERRY || CC_TARGET_PLATFORM == CC_PLATFORM_NACL || CC_TARGET_PLATFORM == CC_PLATFORM_EMSCRIPTEN) + ret = 0; +#else + ret = ftello64((FILE *)stream); +#endif + return ret; +} + +static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offset, int origin) +{ + (void)(opaque); + int fseek_origin=0; + long ret; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + fseek_origin = SEEK_CUR; + break; + case ZLIB_FILEFUNC_SEEK_END : + fseek_origin = SEEK_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + fseek_origin = SEEK_SET; + break; + default: return -1; + } + ret = 0; + if (fseek((FILE *)stream, offset, fseek_origin) != 0) + ret = -1; + return ret; +} + +static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) +{ + (void)(opaque); + int fseek_origin=0; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + fseek_origin = SEEK_CUR; + break; + case ZLIB_FILEFUNC_SEEK_END : + fseek_origin = SEEK_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + fseek_origin = SEEK_SET; + break; + default: return -1; + } + if(fseeko64((FILE *)stream, static_cast(offset), fseek_origin) != 0) + return -1; + return 0; + +} + + +static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream) +{ + (void)(opaque); + int ret; + ret = fclose((FILE *)stream); + return ret; +} + +static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream) +{ + (void)(opaque); + int ret; + ret = ferror((FILE *)stream); + return ret; +} + +void fill_fopen_filefunc (zlib_filefunc_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen_file = fopen_file_func; + pzlib_filefunc_def->zread_file = fread_file_func; + pzlib_filefunc_def->zwrite_file = fwrite_file_func; + pzlib_filefunc_def->ztell_file = ftell_file_func; + pzlib_filefunc_def->zseek_file = fseek_file_func; + pzlib_filefunc_def->zclose_file = fclose_file_func; + pzlib_filefunc_def->zerror_file = ferror_file_func; + pzlib_filefunc_def->opaque = NULL; +} + +void fill_fopen64_filefunc (zlib_filefunc64_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen64_file = fopen64_file_func; + pzlib_filefunc_def->zread_file = fread_file_func; + pzlib_filefunc_def->zwrite_file = fwrite_file_func; + pzlib_filefunc_def->ztell64_file = ftell64_file_func; + pzlib_filefunc_def->zseek64_file = fseek64_file_func; + pzlib_filefunc_def->zclose_file = fclose_file_func; + pzlib_filefunc_def->zerror_file = ferror_file_func; + pzlib_filefunc_def->opaque = NULL; +} + diff --git a/VIServer/Classes/FoundationKit/external/unzip/ioapi.h b/VIServer/Classes/FoundationKit/external/unzip/ioapi.h new file mode 100644 index 0000000000..c65319a127 --- /dev/null +++ b/VIServer/Classes/FoundationKit/external/unzip/ioapi.h @@ -0,0 +1,195 @@ +/* ioapi.h -- IO base function header for compress/uncompress .zip + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + + Changes + + Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this) + Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux. + More if/def section may be needed to support other platforms + Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows. + (but you should use iowin32.c for windows instead) + +*/ + +#ifndef _ZLIBIOAPI64_H +#define _ZLIBIOAPI64_H + +#if (!defined(_WIN32)) && (!defined(WIN32)) + + // Linux needs this to support file operation on files larger then 4+GB + // But might need better if/def to select just the platforms that needs them. + + #ifndef __USE_FILE_OFFSET64 + #define __USE_FILE_OFFSET64 + #endif + #ifndef __USE_LARGEFILE64 + #define __USE_LARGEFILE64 + #endif + #ifndef _LARGEFILE64_SOURCE + #define _LARGEFILE64_SOURCE + #endif + #ifndef _FILE_OFFSET_BIT + #define _FILE_OFFSET_BIT 64 + #endif +#endif + +#include +#include +#include "zlib.h" + +#ifndef OF +#define OF _Z_OF +#endif + +#if defined(USE_FILE32API) +#define fopen64 fopen +#define ftello64 ftell +#define fseeko64 fseek +#else +#ifdef _MSC_VER + #define fopen64 fopen + #if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC))) + #define ftello64 _ftelli64 + #define fseeko64 _fseeki64 + #else // old MSC + #define ftello64 ftell + #define fseeko64 fseek + #endif +#endif +#endif + +/* +#ifndef ZPOS64_T + #ifdef _WIN32 + #define ZPOS64_T fpos_t + #else + #include + #define ZPOS64_T uint64_t + #endif +#endif +*/ + +#ifdef HAVE_MINIZIP64_CONF_H +#include "mz64conf.h" +#endif + +/* a type chosen by DEFINE */ +#ifdef HAVE_64BIT_INT_CUSTOM +typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T; +#else +#ifdef HAS_STDINT_H +#include "stdint.h" +typedef uint64_t ZPOS64_T; +#else + + +#if defined(_MSC_VER) || defined(__BORLANDC__) +typedef unsigned __int64 ZPOS64_T; +#else +typedef unsigned long long int ZPOS64_T; +#endif +#endif +#endif + + + +#define ZLIB_FILEFUNC_SEEK_CUR (1) +#define ZLIB_FILEFUNC_SEEK_END (2) +#define ZLIB_FILEFUNC_SEEK_SET (0) + +#define ZLIB_FILEFUNC_MODE_READ (1) +#define ZLIB_FILEFUNC_MODE_WRITE (2) +#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) + +#define ZLIB_FILEFUNC_MODE_EXISTING (4) +#define ZLIB_FILEFUNC_MODE_CREATE (8) + + +#ifndef ZCALLBACK + #if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) + #define ZCALLBACK CALLBACK + #else + #define ZCALLBACK + #endif +#endif + + + + +typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); +typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); +typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); +typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); + +typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); +typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); + + +/* here is the "old" 32 bits structure structure */ +typedef struct zlib_filefunc_def_s +{ + open_file_func zopen_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell_file_func ztell_file; + seek_file_func zseek_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + voidpf opaque; +} zlib_filefunc_def; + +typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream)); +typedef long (ZCALLBACK *seek64_file_func) OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); +typedef voidpf (ZCALLBACK *open64_file_func) OF((voidpf opaque, const void* filename, int mode)); + +typedef struct zlib_filefunc64_def_s +{ + open64_file_func zopen64_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell64_file_func ztell64_file; + seek64_file_func zseek64_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + voidpf opaque; +} zlib_filefunc64_def; + +void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def)); +void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); + +/* now internal definition, only for zip.c and unzip.h */ +typedef struct zlib_filefunc64_32_def_s +{ + zlib_filefunc64_def zfile_func64; + open_file_func zopen32_file; + tell_file_func ztell32_file; + seek_file_func zseek32_file; +} zlib_filefunc64_32_def; + + +#define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) +#define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) +//#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream)) +//#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode)) +#define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream)) +#define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream)) + +voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)); +long call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)); +ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)); + +void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32); + +#define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode))) +#define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream))) +#define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode))) + +#endif diff --git a/VIServer/Classes/FoundationKit/external/unzip/ioapi_mem.cpp b/VIServer/Classes/FoundationKit/external/unzip/ioapi_mem.cpp new file mode 100644 index 0000000000..5b6f08d490 --- /dev/null +++ b/VIServer/Classes/FoundationKit/external/unzip/ioapi_mem.cpp @@ -0,0 +1,255 @@ +/* ioapi_mem.c -- IO base function header for compress/uncompress .zip + files using zlib + zip or unzip API + + This version of ioapi is designed to access memory rather than files. + We do use a region of memory to put data in to and take it out of. We do + not have auto-extending buffers and do not inform anyone else that the + data has been written. It is really intended for accessing a zip archive + embedded in an application such that I can write an installer with no + external files. Creation of archives has not been attempted, although + parts of the framework are present. + + Based on Unzip ioapi.c version 0.22, May 19th, 2003 + + Copyright (C) 1998-2003 Gilles Vollant + (C) 2003 Justin Fletcher + + This file is under the same license as the Unzip tool it is distributed + with. + */ + + +#include +#include +#include + +#include "zlib.h" +#include "ioapi_mem.h" + +#ifdef _MSC_VER + +#define strtoull _strtoui64 + +#endif + + + +voidpf ZCALLBACK fopen_mem_func (voidpf opaque, + const char* filename, + int mode) +{ + (void)(opaque); + ourmemory_t *mem = (ourmemory_t*)malloc(sizeof(ourmemory_t)); + + if (mem==NULL) return NULL; /* Can't allocate space, so failed */ + + /* Filenames are specified in the form : + * + + * This may not work where memory addresses are longer than the + * size of an int and therefore may need addressing for 64bit + * architectures + */ + memset(mem, 0, sizeof(ourmemory_t)); + char *pEnd = NULL; + void *base = NULL; + unsigned long size = 0; + + base = (void*)strtoull(filename, &pEnd, 16); + if (!base) + { + free(mem); + return NULL; + } + size = strtoul(pEnd, &pEnd, 16); + if (!size) + { + free(mem); + return NULL; + } + + mem->base = base; + mem->size = size; + + if (mode & ZLIB_FILEFUNC_MODE_CREATE) { + mem->limit = 0; /* When writing we start with 0 bytes written */ + } else { + mem->limit = mem->size; + } + mem->cur_offset = 0; + + return mem; +} + +voidpf ZCALLBACK fopen_mem_func64_32 (voidpf opaque, + const void* filename, + int mode) +{ + (void)(opaque); + ourmemory_t *mem = (ourmemory_t*)malloc(sizeof(ourmemory_t)); + + if (mem==NULL) return NULL; /* Can't allocate space, so failed */ + + /* Filenames are specified in the form : + * + + * This may not work where memory addresses are longer than the + * size of an int and therefore may need addressing for 64bit + * architectures + */ + memset(mem, 0, sizeof(ourmemory_t)); + char *pEnd = NULL; + void *base = NULL; + unsigned long size = 0; + + base = (void*)strtoull((const char*)filename, &pEnd, 16); + if (!base) + { + free(mem); + return NULL; + } + size = strtoul(pEnd, &pEnd, 16); + if (!size) + { + free(mem); + return NULL; + } + + mem->base = base; + mem->size = size; + + if (mode & ZLIB_FILEFUNC_MODE_CREATE) { + mem->limit=0; /* When writing we start with 0 bytes written */ + } else { + mem->limit=mem->size; + } + + mem->cur_offset = 0; + + return mem; +} + +uLong ZCALLBACK fread_mem_func (voidpf opaque, voidpf stream, void* buf, uLong size) +{ + (void)(opaque); + ourmemory_t *mem = (ourmemory_t *)stream; + + if (size > mem->size - mem->cur_offset) { + size = mem->size - mem->cur_offset; + } + + memcpy(buf, (char*)mem->base + mem->cur_offset, size); + mem->cur_offset+=size; + + return size; +} + + +uLong ZCALLBACK fwrite_mem_func (voidpf opaque, voidpf stream, const void* buf, uLong size) +{ + (void)(opaque); + ourmemory_t *mem = (ourmemory_t *)stream; + + if (size > mem->size - mem->cur_offset) { + size = mem->size - mem->cur_offset; + } + + memcpy((char*)mem->base + mem->cur_offset, buf, size); + mem->cur_offset+=size; + if (mem->cur_offset > mem->limit) { + mem->limit = mem->cur_offset; + } + + return size; +} + +long ZCALLBACK ftell_mem_func (voidpf opaque, voidpf stream) +{ + (void)(opaque); + ourmemory_t *mem = (ourmemory_t *)stream; + + return mem->cur_offset; +} + +long ZCALLBACK fseek_mem_func (voidpf opaque, voidpf stream, uLong offset, int origin) +{ + (void)(opaque); + ourmemory_t *mem = (ourmemory_t *)stream; + uLong new_pos; + switch (origin) { + case ZLIB_FILEFUNC_SEEK_CUR : { + new_pos = mem->cur_offset + offset; + break; + } + case ZLIB_FILEFUNC_SEEK_END : { + new_pos = mem->limit + offset; + break; + } + case ZLIB_FILEFUNC_SEEK_SET : { + new_pos = offset; + break; + } + default: { + return -1; + } + } + + if (new_pos > mem->size) return 1; /* Failed to seek that far */ + + if (new_pos > mem->limit) { + memset((char*)mem->base + mem->limit, 0, new_pos - mem->limit); + } + + mem->cur_offset = new_pos; + return 0; +} + +int ZCALLBACK fclose_mem_func (voidpf opaque, voidpf stream) +{ + (void)(opaque); + ourmemory_t *mem = (ourmemory_t *)stream; + + /* Note that once we've written to the buffer we don't tell anyone + about it here. Probably the opaque handle could be used to inform + some other component of how much data was written. + + This, and other aspects of writing through this interface, has + not been tested. + */ + + free (mem); + return 0; +} + +int ZCALLBACK ferror_mem_func (voidpf opaque, voidpf stream) +{ + (void)(opaque); + (void)(stream); + /* We never return errors */ + return 0; +} + +void fill_memory_filefunc (zlib_filefunc_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen_file = fopen_mem_func; + pzlib_filefunc_def->zread_file = fread_mem_func; + pzlib_filefunc_def->zwrite_file = fwrite_mem_func; + pzlib_filefunc_def->ztell_file = ftell_mem_func; + pzlib_filefunc_def->zseek_file = fseek_mem_func; + pzlib_filefunc_def->zclose_file = fclose_mem_func; + pzlib_filefunc_def->zerror_file = ferror_mem_func; + pzlib_filefunc_def->opaque = NULL; +} + +void fill_memory_filefunc64_32 (zlib_filefunc64_32_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen32_file = fopen_mem_func; + pzlib_filefunc_def->zfile_func64.zopen64_file = fopen_mem_func64_32; + pzlib_filefunc_def->zfile_func64.zread_file = fread_mem_func; + pzlib_filefunc_def->zfile_func64.zwrite_file = fwrite_mem_func; + pzlib_filefunc_def->ztell32_file = ftell_mem_func; + pzlib_filefunc_def->zseek32_file = fseek_mem_func; + pzlib_filefunc_def->zfile_func64.zseek64_file = NULL; + pzlib_filefunc_def->zfile_func64.zclose_file = fclose_mem_func; + pzlib_filefunc_def->zfile_func64.zerror_file = ferror_mem_func; + pzlib_filefunc_def->zfile_func64.opaque = NULL; +} + diff --git a/VIServer/Classes/FoundationKit/external/unzip/ioapi_mem.h b/VIServer/Classes/FoundationKit/external/unzip/ioapi_mem.h new file mode 100644 index 0000000000..20df283936 --- /dev/null +++ b/VIServer/Classes/FoundationKit/external/unzip/ioapi_mem.h @@ -0,0 +1,59 @@ +#ifndef FoundationKit_ioapi_mem_H +#define FoundationKit_ioapi_mem_H + + + +#include "ioapi.h" + +voidpf ZCALLBACK fopen_mem_func OF(( + voidpf opaque, + const char* filename, + int mode)); + +voidpf ZCALLBACK fopen_mem_func64_32 OF(( + voidpf opaque, + const void* filename, + int mode)); + +uLong ZCALLBACK fread_mem_func OF(( + voidpf opaque, + voidpf stream, + void* buf, + uLong size)); + +uLong ZCALLBACK fwrite_mem_func OF(( + voidpf opaque, + voidpf stream, + const void* buf, + uLong size)); + +long ZCALLBACK ftell_mem_func OF(( + voidpf opaque, + voidpf stream)); + +long ZCALLBACK fseek_mem_func OF(( + voidpf opaque, + voidpf stream, + uLong offset, + int origin)); + +int ZCALLBACK fclose_mem_func OF(( + voidpf opaque, + voidpf stream)); + +int ZCALLBACK ferror_mem_func OF(( + voidpf opaque, + voidpf stream)); + +void fill_memory_filefunc64_32 (zlib_filefunc64_32_def* pzlib_filefunc_def); + + +typedef struct ourmemory_s { + void *base; /* Base of the region of memory we're using */ + uLong size; /* Size of the region of memory we're using */ + uLong limit; /* Furthest we've written */ + uLong cur_offset; /* Current offset in the area */ +} ourmemory_t; + + +#endif // FoundationKit_ioapi_mem_H diff --git a/VIServer/Classes/FoundationKit/external/unzip/unzip.cpp b/VIServer/Classes/FoundationKit/external/unzip/unzip.cpp new file mode 100644 index 0000000000..aafe53521d --- /dev/null +++ b/VIServer/Classes/FoundationKit/external/unzip/unzip.cpp @@ -0,0 +1,2169 @@ +/* unzip.c -- IO for uncompress .zip files using zlib + Version 1.1, February 14h, 2010 + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications of Unzip for Zip64 + Copyright (C) 2007-2008 Even Rouault + + Modifications for Zip64 support on both zip and unzip + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + + + ------------------------------------------------------------------------------------ + Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of + compatibility with older software. The following is from the original crypt.c. + Code woven in by Terry Thorsen 1/2003. + + Copyright (c) 1990-2000 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2000-Apr-09 or later + (the contents of which are also included in zip.h) for terms of use. + If, for some reason, all these files are missing, the Info-ZIP license + also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html + + crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + + ------------------------------------------------------------------------------------ + + Changes in unzip.c + + 2007-2008 - Even Rouault - Addition of cpl_unzGetCurrentFileZStreamPos + 2007-2008 - Even Rouault - Decoration of symbol names unz* -> cpl_unz* + 2007-2008 - Even Rouault - Remove old C style function prototypes + 2007-2008 - Even Rouault - Add unzip support for ZIP64 + + Copyright (C) 2007-2008 Even Rouault + + + Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again). + Oct-2009 - Mathias Svensson - Fixed problem if uncompressed size was > 4G and compressed size was <4G + should only read the compressed/uncompressed size from the Zip64 format if + the size from normal header was 0xFFFFFFFF + Oct-2009 - Mathias Svensson - Applied some bug fixes from patches received from Gilles Vollant + Oct-2009 - Mathias Svensson - Applied support to unzip files with compression method BZIP2 (bzip2 lib is required) + Patch created by Daniel Borca + + Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer + + Copyright (C) 1998 - 2010 Gilles Vollant, Even Rouault, Mathias Svensson + +*/ + + +#include +#include +#include + +#ifndef NOUNCRYPT + #define NOUNCRYPT +#endif + +#include "zlib.h" +#include "unzip.h" +#include "ioapi_mem.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + + +#ifndef CASESENSITIVITYDEFAULT_NO +# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) +# define CASESENSITIVITYDEFAULT_NO +# endif +#endif + + +#ifndef UNZ_BUFSIZE +#define UNZ_BUFSIZE (16384) +#endif + +#ifndef UNZ_MAXFILENAMEINZIP +#define UNZ_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) + + +const char unz_copyright[] = + " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; + +/* unz_file_info_interntal contain internal info about a file in zipfile*/ +typedef struct unz_file_info64_internal_s +{ + ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */ +} unz_file_info64_internal; + + +/* file_in_zip_read_info_s contain internal information about a file in zipfile, + when reading and decompress it */ +typedef struct +{ + char *read_buffer; /* internal buffer for compressed data */ + z_stream stream; /* zLib stream structure for inflate */ + +#ifdef HAVE_BZIP2 + bz_stream bstream; /* bzLib stream structure for bziped */ +#endif + + ZPOS64_T pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ + uLong stream_initialised; /* flag set if stream structure is initialized*/ + + ZPOS64_T offset_local_extrafield;/* offset of the local extra field */ + uInt size_local_extrafield;/* size of the local extra field */ + ZPOS64_T pos_local_extrafield; /* position in the local extra field in read*/ + ZPOS64_T total_out_64; + + uLong crc32; /* crc32 of all data uncompressed */ + uLong crc32_wait; /* crc32 we must obtain after decompress all */ + ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */ + ZPOS64_T rest_read_uncompressed;/*number of byte to be obtained after decomp*/ + zlib_filefunc64_32_def z_filefunc; + voidpf filestream; /* io structure of the zipfile */ + uLong compression_method; /* compression method (0==store) */ + ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + int raw; +} file_in_zip64_read_info_s; + + +/* unz64_s contain internal information about the zipfile +*/ +typedef struct +{ + zlib_filefunc64_32_def z_filefunc; + int is64bitOpenFunction; + voidpf filestream; /* io structure of the zipfile */ + unz_global_info64 gi; /* public global information */ + ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + ZPOS64_T num_file; /* number of the current file in the zipfile*/ + ZPOS64_T pos_in_central_dir; /* pos of the current file in the central dir*/ + ZPOS64_T current_file_ok; /* flag about the usability of the current file*/ + ZPOS64_T central_pos; /* position of the beginning of the central dir*/ + + ZPOS64_T size_central_dir; /* size of the central directory */ + ZPOS64_T offset_central_dir; /* offset of start of central directory with + respect to the starting disk number */ + + unz_file_info64 cur_file_info; /* public info about the current file in zip*/ + unz_file_info64_internal cur_file_info_internal; /* private info about it*/ + file_in_zip64_read_info_s* pfile_in_zip_read; /* structure about the current + file if we are decompressing it */ + int encrypted; + + int isZip64; + +# ifndef NOUNCRYPT + unsigned long keys[3]; /* keys defining the pseudo-random sequence */ + const unsigned long* pcrc_32_tab; +# endif +} unz64_s; + + +#ifndef NOUNCRYPT +#include "crypt.h" +#endif + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been successfully opened for reading. +*/ + + +local int unz64local_getByte OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + int *pi)); + +local int unz64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi) +{ + unsigned char c; + int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); + if (err==1) + { + *pi = (int)c; + return UNZ_OK; + } + else + { + if (ZERROR64(*pzlib_filefunc_def,filestream)) + return UNZ_ERRNO; + else + return UNZ_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int unz64local_getShort OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int unz64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX) +{ + uLong x ; + int i = 0; + int err; + + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((uLong)i)<<8; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unz64local_getLong OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int unz64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX) +{ + uLong x ; + int i = 0; + int err; + + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((uLong)i)<<8; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((uLong)i)<<16; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<24; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unz64local_getLong64 OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + ZPOS64_T *pX)); + + +local int unz64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + ZPOS64_T *pX) +{ + ZPOS64_T x ; + int i = 0; + int err; + + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (ZPOS64_T)i; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<8; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<16; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<24; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<32; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<40; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<48; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<56; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +/* My own strcmpi / strcasecmp */ +local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2) +{ + for (;;) + { + char c1=*(fileName1++); + char c2=*(fileName2++); + if ((c1>='a') && (c1<='z')) + c1 -= 0x20; + if ((c2>='a') && (c2<='z')) + c2 -= 0x20; + if (c1=='\0') + return ((c2=='\0') ? 0 : -1); + if (c2=='\0') + return 1; + if (c1c2) + return 1; + } +} + + +#ifdef CASESENSITIVITYDEFAULT_NO +#define CASESENSITIVITYDEFAULTVALUE 2 +#else +#define CASESENSITIVITYDEFAULTVALUE 1 +#endif + +#ifndef STRCMPCASENOSENTIVEFUNCTION +#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal +#endif + +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparison is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparison is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is default of your operating system + (like 1 on Unix, 2 on Windows) + +*/ +int ZEXPORT unzStringFileNameCompare (const char* fileName1, + const char* fileName2, + int iCaseSensitivity) + +{ + if (iCaseSensitivity==0) + iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; + + if (iCaseSensitivity==1) + return strcmp(fileName1,fileName2); + + return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); +} + +#ifndef BUFREADCOMMENT +#define BUFREADCOMMENT (0x400) +#endif + +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local ZPOS64_T unz64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); +local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) +{ + unsigned char* buf; + ZPOS64_T uSizeFile; + ZPOS64_T uBackRead; + ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ + ZPOS64_T uPosFound=0; + + if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); + if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + return uPosFound; +} + + +/* + Locate the Central directory 64 of a zipfile (at the end, just before + the global comment) +*/ +local ZPOS64_T unz64local_SearchCentralDir64 OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream)); + +local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream) +{ + unsigned char* buf; + ZPOS64_T uSizeFile; + ZPOS64_T uBackRead; + ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ + ZPOS64_T uPosFound=0; + uLong uL; + ZPOS64_T relativeOffset; + + if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); + if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + if (uPosFound == 0) + return 0; + + /* Zip64 end of central directory locator */ + if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0) + return 0; + + /* the signature, already checked */ + if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) + return 0; + + /* number of the disk with the start of the zip64 end of central directory */ + if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) + return 0; + if (uL != 0) + return 0; + + /* relative offset of the zip64 end of central directory record */ + if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK) + return 0; + + /* total number of disks */ + if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) + return 0; + if (uL != 1) + return 0; + + /* Goto end of central directory record */ + if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0) + return 0; + + /* the signature */ + if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) + return 0; + + if (uL != 0x06064b50) + return 0; + + return relativeOffset; +} + +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer + "zlib/zlib114.zip". + If the zipfile cannot be opened (file doesn't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ +local unzFile unzOpenInternal (const void *path, + zlib_filefunc64_32_def* pzlib_filefunc64_32_def, + int is64bitOpenFunction) +{ + unz64_s us; + unz64_s *s; + ZPOS64_T central_pos; + uLong uL; + + uLong number_disk; /* number of the current dist, used for + spanning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spanning ZIP, unsupported, always 0*/ + ZPOS64_T number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + + int err=UNZ_OK; + + if (unz_copyright[0]!=' ') + return NULL; + + us.z_filefunc.zseek32_file = NULL; + us.z_filefunc.ztell32_file = NULL; + if (pzlib_filefunc64_32_def==NULL) + fill_fopen64_filefunc(&us.z_filefunc.zfile_func64); + else + us.z_filefunc = *pzlib_filefunc64_32_def; + us.is64bitOpenFunction = is64bitOpenFunction; + + + + us.filestream = ZOPEN64(us.z_filefunc, + path, + ZLIB_FILEFUNC_MODE_READ | + ZLIB_FILEFUNC_MODE_EXISTING); + if (us.filestream==NULL) + return NULL; + + central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream); + if (central_pos) + { + uLong uS; + ZPOS64_T uL64; + + us.isZip64 = 1; + + if (ZSEEK64(us.z_filefunc, us.filestream, + central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + /* the signature, already checked */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + + /* size of zip64 end of central directory record */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&uL64)!=UNZ_OK) + err=UNZ_ERRNO; + + /* version made by */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK) + err=UNZ_ERRNO; + + /* version needed to extract */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of this disk */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of the disk with the start of the central directory */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central directory on this disk */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central directory */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((number_entry_CD!=us.gi.number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=UNZ_BADZIPFILE; + + /* size of the central directory */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + us.gi.size_comment = 0; + } + else + { + central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream); + if (central_pos==0) + err=UNZ_ERRNO; + + us.isZip64 = 0; + + if (ZSEEK64(us.z_filefunc, us.filestream, + central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + /* the signature, already checked */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of this disk */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of the disk with the start of the central directory */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir on this disk */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + us.gi.number_entry = uL; + + /* total number of entries in the central dir */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + number_entry_CD = uL; + + if ((number_entry_CD!=us.gi.number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=UNZ_BADZIPFILE; + + /* size of the central directory */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + us.size_central_dir = uL; + + /* offset of start of central directory with respect to the + starting disk number */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + us.offset_central_dir = uL; + + /* zipfile comment length */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK) + err=UNZ_ERRNO; + } + + if ((central_pospfile_in_zip_read!=NULL) + unzCloseCurrentFile(file); + + ZCLOSE64(s->z_filefunc, s->filestream); + TRYFREE(s); + return UNZ_OK; +} + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ +int ZEXPORT unzGetGlobalInfo64 (unzFile file, unz_global_info64* pglobal_info) +{ + unz64_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + *pglobal_info=s->gi; + return UNZ_OK; +} + +int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info32) +{ + unz64_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + /* to do : check if number_entry is not truncated */ + pglobal_info32->number_entry = (uLong)s->gi.number_entry; + pglobal_info32->size_comment = s->gi.size_comment; + return UNZ_OK; +} +/* + Translate date/time from Dos format to tm_unz (readable more easily) +*/ +local void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm) +{ + ZPOS64_T uDate; + uDate = (ZPOS64_T)(ulDosDate>>16); + ptm->tm_mday = (uInt)(uDate&0x1f) ; + ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; + ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; + + ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); + ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; + ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; +} + +/* + Get Info about the current file in the zipfile, with internal only info +*/ +local int unz64local_GetCurrentFileInfoInternal OF((unzFile file, + unz_file_info64 *pfile_info, + unz_file_info64_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); + +local int unz64local_GetCurrentFileInfoInternal (unzFile file, + unz_file_info64 *pfile_info, + unz_file_info64_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize) +{ + unz64_s* s; + unz_file_info64 file_info; + unz_file_info64_internal file_info_internal; + int err=UNZ_OK; + uLong uMagic; + long lSeek=0; + uLong uL; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + if (ZSEEK64(s->z_filefunc, s->filestream, + s->pos_in_central_dir+s->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + + /* we check the magic */ + if (err==UNZ_OK) + { + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x02014b50) + err=UNZ_BADZIPFILE; + } + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK) + err=UNZ_ERRNO; + + unz64local_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) + err=UNZ_ERRNO; + file_info.compressed_size = uL; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) + err=UNZ_ERRNO; + file_info.uncompressed_size = uL; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK) + err=UNZ_ERRNO; + + // relative offset of local header + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) + err=UNZ_ERRNO; + file_info_internal.offset_curfile = uL; + + lSeek+=file_info.size_filename; + if ((err==UNZ_OK) && (szFileName!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_filename0) && (fileNameBufferSize>0)) + if (ZREAD64(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek -= uSizeRead; + } + + // Read extrafield + if ((err==UNZ_OK) && (extraField!=NULL)) + { + ZPOS64_T uSizeRead ; + if (file_info.size_file_extraz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + + if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) + if (ZREAD64(s->z_filefunc, s->filestream,extraField,(uLong)uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + + lSeek += file_info.size_file_extra - (uLong)uSizeRead; + } + else + lSeek += file_info.size_file_extra; + + + if ((err==UNZ_OK) && (file_info.size_file_extra != 0)) + { + uLong acc = 0; + + // since lSeek now points to after the extra field we need to move back + lSeek -= file_info.size_file_extra; + + if (lSeek!=0) + { + if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + + while(acc < file_info.size_file_extra) + { + uLong headerId; + uLong dataSize; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&headerId) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&dataSize) != UNZ_OK) + err=UNZ_ERRNO; + + /* ZIP64 extra fields */ + if (headerId == 0x0001) + { + uLong uL2; + + if (file_info.uncompressed_size == (ZPOS64_T)(unsigned long)-1) + { + if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) + err=UNZ_ERRNO; + } + + if (file_info.compressed_size == (ZPOS64_T)(unsigned long)-1) + { + if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) + err=UNZ_ERRNO; + } + + if (file_info_internal.offset_curfile == (ZPOS64_T)(unsigned long)-1) + { + /* Relative Header offset */ + if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) + err=UNZ_ERRNO; + } + + if(file_info.disk_num_start == (unsigned long)-1) + { + /* Disk Start Number */ + if (unz64local_getLong(&s->z_filefunc, s->filestream, &uL2) != UNZ_OK) + err=UNZ_ERRNO; + } + + } + else + { + if (ZSEEK64(s->z_filefunc, s->filestream,dataSize,ZLIB_FILEFUNC_SEEK_CUR)!=0) + err=UNZ_ERRNO; + } + + acc += 2 + 2 + dataSize; + } + } + + if ((err==UNZ_OK) && (szComment!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_commentz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) { + //lSeek=0; + } + else + err=UNZ_ERRNO; + } + + if ((file_info.size_file_comment>0) && (commentBufferSize>0)) + if (ZREAD64(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + //lSeek+=file_info.size_file_comment - uSizeRead; + } + //else + // lSeek+=file_info.size_file_comment; + + + if ((err==UNZ_OK) && (pfile_info!=NULL)) + *pfile_info=file_info; + + if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) + *pfile_info_internal=file_info_internal; + + return err; +} + + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. +*/ +int ZEXPORT unzGetCurrentFileInfo64 (unzFile file, + unz_file_info64 * pfile_info, + char * szFileName, uLong fileNameBufferSize, + void *extraField, uLong extraFieldBufferSize, + char* szComment, uLong commentBufferSize) +{ + return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL, + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); +} + +int ZEXPORT unzGetCurrentFileInfo (unzFile file, + unz_file_info * pfile_info, + char * szFileName, uLong fileNameBufferSize, + void *extraField, uLong extraFieldBufferSize, + char* szComment, uLong commentBufferSize) +{ + int err; + unz_file_info64 file_info64; + err = unz64local_GetCurrentFileInfoInternal(file,&file_info64,NULL, + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); + if (err==UNZ_OK) + { + pfile_info->version = file_info64.version; + pfile_info->version_needed = file_info64.version_needed; + pfile_info->flag = file_info64.flag; + pfile_info->compression_method = file_info64.compression_method; + pfile_info->dosDate = file_info64.dosDate; + pfile_info->crc = file_info64.crc; + + pfile_info->size_filename = file_info64.size_filename; + pfile_info->size_file_extra = file_info64.size_file_extra; + pfile_info->size_file_comment = file_info64.size_file_comment; + + pfile_info->disk_num_start = file_info64.disk_num_start; + pfile_info->internal_fa = file_info64.internal_fa; + pfile_info->external_fa = file_info64.external_fa; + + pfile_info->tmu_date = file_info64.tmu_date, + + + pfile_info->compressed_size = (uLong)file_info64.compressed_size; + pfile_info->uncompressed_size = (uLong)file_info64.uncompressed_size; + + } + return err; +} + +/* + Set the current file of the zipfile to the first file + with retrieving an information about the file. + return UNZ_OK if there is no problem +*/ +int ZEXPORT unzGoToFirstFile64 (unzFile file, + unz_file_info64 *pfile_info, + char *szFileName, + uLong fileNameBufferSize) +{ + int err=UNZ_OK; + unz64_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + s->pos_in_central_dir=s->offset_central_dir; + s->num_file=0; + err=unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + szFileName,fileNameBufferSize,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + if (pfile_info) + *pfile_info = s->cur_file_info; + return err; +} + +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ +int ZEXPORT unzGoToFirstFile (unzFile file) +{ + return unzGoToFirstFile64(file, NULL, NULL, 0); +} + +/* + Set the current file of the zipfile to the next file + with retrieving an information about the file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ +int ZEXPORT unzGoToNextFile64 (unzFile file, + unz_file_info64 *pfile_info, + char *szFileName, + uLong fileNameBufferSize) +{ + unz64_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */ + if (s->num_file+1==s->gi.number_entry) + return UNZ_END_OF_LIST_OF_FILE; + + s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + + s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; + s->num_file++; + err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + szFileName,fileNameBufferSize,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + if (pfile_info) + *pfile_info = s->cur_file_info; + return err; +} + +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ +int ZEXPORT unzGoToNextFile (unzFile file) +{ + return unzGoToNextFile64(file, NULL, NULL, 0); +} + + +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzipStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ +int ZEXPORT unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity) +{ + unz64_s* s; + int err; + + /* We remember the 'current' position in the file so that we can jump + * back there if we fail. + */ + unz_file_info64 cur_file_infoSaved; + unz_file_info64_internal cur_file_info_internalSaved; + ZPOS64_T num_fileSaved; + ZPOS64_T pos_in_central_dirSaved; + + + if (file==NULL) + return UNZ_PARAMERROR; + + if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) + return UNZ_PARAMERROR; + + s=(unz64_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + /* Save the current state */ + num_fileSaved = s->num_file; + pos_in_central_dirSaved = s->pos_in_central_dir; + cur_file_infoSaved = s->cur_file_info; + cur_file_info_internalSaved = s->cur_file_info_internal; + + err = unzGoToFirstFile(file); + + while (err == UNZ_OK) + { + char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; + err = unzGetCurrentFileInfo64(file,NULL, + szCurrentFileName,sizeof(szCurrentFileName)-1, + NULL,0,NULL,0); + if (err == UNZ_OK) + { + if (unzStringFileNameCompare(szCurrentFileName, + szFileName,iCaseSensitivity)==0) + return UNZ_OK; + err = unzGoToNextFile(file); + } + } + + /* We failed, so restore the state of the 'current file' to where we + * were. + */ + s->num_file = num_fileSaved ; + s->pos_in_central_dir = pos_in_central_dirSaved ; + s->cur_file_info = cur_file_infoSaved; + s->cur_file_info_internal = cur_file_info_internalSaved; + return err; +} + + +/* +/////////////////////////////////////////// +// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net) +// I need random access +// +// Further optimization could be realized by adding an ability +// to cache the directory in memory. The goal being a single +// comprehensive file read to put the file I need in a memory. +*/ + +/* +typedef struct unz_file_pos_s +{ + ZPOS64_T pos_in_zip_directory; // offset in file + ZPOS64_T num_of_file; // # of file +} unz_file_pos; +*/ + +int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos* file_pos) +{ + unz64_s* s; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + file_pos->pos_in_zip_directory = s->pos_in_central_dir; + file_pos->num_of_file = s->num_file; + + return UNZ_OK; +} + +int ZEXPORT unzGetFilePos( + unzFile file, + unz_file_pos* file_pos) +{ + unz64_file_pos file_pos64; + int err = unzGetFilePos64(file,&file_pos64); + if (err==UNZ_OK) + { + file_pos->pos_in_zip_directory = (uLong)file_pos64.pos_in_zip_directory; + file_pos->num_of_file = (uLong)file_pos64.num_of_file; + } + return err; +} + +int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos) +{ + unz64_s* s; + int err; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + + /* jump to the right spot */ + s->pos_in_central_dir = file_pos->pos_in_zip_directory; + s->num_file = file_pos->num_of_file; + + /* set the current file */ + err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + /* return results */ + s->current_file_ok = (err == UNZ_OK); + return err; +} + +int ZEXPORT unzGoToFilePos( + unzFile file, + unz_file_pos* file_pos) +{ + unz64_file_pos file_pos64; + if (file_pos == NULL) + return UNZ_PARAMERROR; + + file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory; + file_pos64.num_of_file = file_pos->num_of_file; + return unzGoToFilePos64(file,&file_pos64); +} + +/* +// Unzip Helper Functions - should be here? +/////////////////////////////////////////// +*/ + +/* + Read the local header of the current zipfile + Check the coherency of the local header and info in the end of central + directory about this file + store in *piSizeVar the size of extra info in local header + (filename and size of extra field data) +*/ +local int unz64local_CheckCurrentFileCoherencyHeader (unz64_s* s, uInt* piSizeVar, + ZPOS64_T * poffset_local_extrafield, + uInt * psize_local_extrafield) +{ + uLong uMagic,uData,uFlags; + uLong size_filename; + uLong size_extra_field; + int err=UNZ_OK; + + *piSizeVar = 0; + *poffset_local_extrafield = 0; + *psize_local_extrafield = 0; + + if (ZSEEK64(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile + + s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + + if (err==UNZ_OK) + { + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x04034b50) + err=UNZ_BADZIPFILE; + } + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; +/* + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) + err=UNZ_BADZIPFILE; +*/ + if (unz64local_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) + err=UNZ_BADZIPFILE; + + if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && +/* #ifdef HAVE_BZIP2 */ + (s->cur_file_info.compression_method!=Z_BZIP2ED) && +/* #endif */ + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */ + err=UNZ_ERRNO; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */ + err=UNZ_ERRNO; + else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */ + err=UNZ_ERRNO; + else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) + err=UNZ_BADZIPFILE; + + *piSizeVar += (uInt)size_filename; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK) + err=UNZ_ERRNO; + *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + + SIZEZIPLOCALHEADER + size_filename; + *psize_local_extrafield = (uInt)size_extra_field; + + *piSizeVar += (uInt)size_extra_field; + + return err; +} + +/* + Open for reading data the current file in the zipfile. + If there is no error and the file is opened, the return value is UNZ_OK. +*/ +int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method, + int* level, int raw, const char* password) +{ + int err=UNZ_OK; + uInt iSizeVar; + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + ZPOS64_T offset_local_extrafield; /* offset of the local extra field */ + uInt size_local_extrafield; /* size of the local extra field */ +# ifndef NOUNCRYPT + char source[12]; +# else + if (password != NULL) + return UNZ_PARAMERROR; +# endif + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + if (!s->current_file_ok) + return UNZ_PARAMERROR; + + if (s->pfile_in_zip_read != NULL) + unzCloseCurrentFile(file); + + if (unz64local_CheckCurrentFileCoherencyHeader(s,&iSizeVar, &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) + return UNZ_BADZIPFILE; + + pfile_in_zip_read_info = (file_in_zip64_read_info_s*)ALLOC(sizeof(file_in_zip64_read_info_s)); + if (pfile_in_zip_read_info==NULL) + return UNZ_INTERNALERROR; + + pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); + pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; + pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; + pfile_in_zip_read_info->pos_local_extrafield=0; + pfile_in_zip_read_info->raw=raw; + + if (pfile_in_zip_read_info->read_buffer==NULL) + { + TRYFREE(pfile_in_zip_read_info); + return UNZ_INTERNALERROR; + } + + pfile_in_zip_read_info->stream_initialised=0; + + if (method!=NULL) + *method = (int)s->cur_file_info.compression_method; + + if (level!=NULL) + { + *level = 6; + switch (s->cur_file_info.flag & 0x06) + { + case 6 : *level = 1; break; + case 4 : *level = 2; break; + case 2 : *level = 9; break; + } + } + + if ((s->cur_file_info.compression_method!=0) && +/* #ifdef HAVE_BZIP2 */ + (s->cur_file_info.compression_method!=Z_BZIP2ED) && +/* #endif */ + (s->cur_file_info.compression_method!=Z_DEFLATED)) { + + //err=UNZ_BADZIPFILE; + } + pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; + pfile_in_zip_read_info->crc32=0; + pfile_in_zip_read_info->total_out_64=0; + pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method; + pfile_in_zip_read_info->filestream=s->filestream; + pfile_in_zip_read_info->z_filefunc=s->z_filefunc; + pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; + + pfile_in_zip_read_info->stream.total_out = 0; + + if ((s->cur_file_info.compression_method==Z_BZIP2ED) && (!raw)) + { +#ifdef HAVE_BZIP2 + pfile_in_zip_read_info->bstream.bzalloc = (void *(*) (void *, int, int))0; + pfile_in_zip_read_info->bstream.bzfree = (free_func)0; + pfile_in_zip_read_info->bstream.opaque = (voidpf)0; + pfile_in_zip_read_info->bstream.state = (voidpf)0; + + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)0; + pfile_in_zip_read_info->stream.next_in = (voidpf)0; + pfile_in_zip_read_info->stream.avail_in = 0; + + err=BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised=Z_BZIP2ED; + else + { + TRYFREE(pfile_in_zip_read_info); + return err; + } +#else + pfile_in_zip_read_info->raw=1; +#endif + } + else if ((s->cur_file_info.compression_method==Z_DEFLATED) && (!raw)) + { + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)0; + pfile_in_zip_read_info->stream.next_in = 0; + pfile_in_zip_read_info->stream.avail_in = 0; + + err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised=Z_DEFLATED; + else + { + TRYFREE(pfile_in_zip_read_info); + return err; + } + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. + * In unzip, i don't wait absolutely Z_STREAM_END because I known the + * size of both compressed and uncompressed data + */ + } + pfile_in_zip_read_info->rest_read_compressed = + s->cur_file_info.compressed_size ; + pfile_in_zip_read_info->rest_read_uncompressed = + s->cur_file_info.uncompressed_size ; + + + pfile_in_zip_read_info->pos_in_zipfile = + s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + + iSizeVar; + + pfile_in_zip_read_info->stream.avail_in = (uInt)0; + + s->pfile_in_zip_read = pfile_in_zip_read_info; + s->encrypted = 0; + +# ifndef NOUNCRYPT + if (password != NULL) + { + int i; + s->pcrc_32_tab = get_crc_table(); + init_keys(password,s->keys,s->pcrc_32_tab); + if (ZSEEK64(s->z_filefunc, s->filestream, + s->pfile_in_zip_read->pos_in_zipfile + + s->pfile_in_zip_read->byte_before_the_zipfile, + SEEK_SET)!=0) + return UNZ_INTERNALERROR; + if(ZREAD64(s->z_filefunc, s->filestream,source, 12)<12) + return UNZ_INTERNALERROR; + + for (i = 0; i<12; i++) + zdecode(s->keys,s->pcrc_32_tab,source[i]); + + s->pfile_in_zip_read->pos_in_zipfile+=12; + s->encrypted=1; + } +# endif + + + return UNZ_OK; +} + +int ZEXPORT unzOpenCurrentFile (unzFile file) +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); +} + +int ZEXPORT unzOpenCurrentFilePassword (unzFile file, const char* password) +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, password); +} + +int ZEXPORT unzOpenCurrentFile2 (unzFile file, int* method, int* level, int raw) +{ + return unzOpenCurrentFile3(file, method, level, raw, NULL); +} + +/** Addition for GDAL : START */ + +ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64( unzFile file) +{ + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + s=(unz64_s*)file; + if (file==NULL) + return 0; //UNZ_PARAMERROR; + pfile_in_zip_read_info=s->pfile_in_zip_read; + if (pfile_in_zip_read_info==NULL) + return 0; //UNZ_PARAMERROR; + return pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile; +} + +/** Addition for GDAL : END */ + +/* + Read bytes from the current file. + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if some bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ +int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len) +{ + int err=UNZ_OK; + uInt iRead = 0; + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if (pfile_in_zip_read_info->read_buffer == NULL) + return UNZ_END_OF_LIST_OF_FILE; + if (len==0) + return 0; + + pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; + + pfile_in_zip_read_info->stream.avail_out = (uInt)len; + + if ((len>pfile_in_zip_read_info->rest_read_uncompressed) && + (!(pfile_in_zip_read_info->raw))) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_uncompressed; + + if ((len>pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in) && + (pfile_in_zip_read_info->raw)) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in; + + while (pfile_in_zip_read_info->stream.avail_out>0) + { + if ((pfile_in_zip_read_info->stream.avail_in==0) && + (pfile_in_zip_read_info->rest_read_compressed>0)) + { + uInt uReadThis = UNZ_BUFSIZE; + if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; + if (uReadThis == 0) + return UNZ_EOF; + if (ZSEEK64(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + if (ZREAD64(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->read_buffer, + uReadThis)!=uReadThis) + return UNZ_ERRNO; + + +# ifndef NOUNCRYPT + if(s->encrypted) + { + uInt i; + for(i=0;iread_buffer[i] = + zdecode(s->keys,s->pcrc_32_tab, + pfile_in_zip_read_info->read_buffer[i]); + } +# endif + + + pfile_in_zip_read_info->pos_in_zipfile += uReadThis; + + pfile_in_zip_read_info->rest_read_compressed-=uReadThis; + + pfile_in_zip_read_info->stream.next_in = + (Bytef*)pfile_in_zip_read_info->read_buffer; + pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; + } + + if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw)) + { + uInt uDoCopy,i ; + + if ((pfile_in_zip_read_info->stream.avail_in == 0) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + return (iRead==0) ? UNZ_EOF : iRead; + + if (pfile_in_zip_read_info->stream.avail_out < + pfile_in_zip_read_info->stream.avail_in) + uDoCopy = pfile_in_zip_read_info->stream.avail_out ; + else + uDoCopy = pfile_in_zip_read_info->stream.avail_in ; + + for (i=0;istream.next_out+i) = + *(pfile_in_zip_read_info->stream.next_in+i); + + pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uDoCopy; + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, + pfile_in_zip_read_info->stream.next_out, + uDoCopy); + pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; + pfile_in_zip_read_info->stream.avail_in -= uDoCopy; + pfile_in_zip_read_info->stream.avail_out -= uDoCopy; + pfile_in_zip_read_info->stream.next_out += uDoCopy; + pfile_in_zip_read_info->stream.next_in += uDoCopy; + pfile_in_zip_read_info->stream.total_out += uDoCopy; + iRead += uDoCopy; + } + else if (pfile_in_zip_read_info->compression_method==Z_BZIP2ED) + { +#ifdef HAVE_BZIP2 + uLong uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + uLong uOutThis; + + pfile_in_zip_read_info->bstream.next_in = (char*)pfile_in_zip_read_info->stream.next_in; + pfile_in_zip_read_info->bstream.avail_in = pfile_in_zip_read_info->stream.avail_in; + pfile_in_zip_read_info->bstream.total_in_lo32 = pfile_in_zip_read_info->stream.total_in; + pfile_in_zip_read_info->bstream.total_in_hi32 = 0; + pfile_in_zip_read_info->bstream.next_out = (char*)pfile_in_zip_read_info->stream.next_out; + pfile_in_zip_read_info->bstream.avail_out = pfile_in_zip_read_info->stream.avail_out; + pfile_in_zip_read_info->bstream.total_out_lo32 = pfile_in_zip_read_info->stream.total_out; + pfile_in_zip_read_info->bstream.total_out_hi32 = 0; + + uTotalOutBefore = pfile_in_zip_read_info->bstream.total_out_lo32; + bufBefore = (const Bytef *)pfile_in_zip_read_info->bstream.next_out; + + err=BZ2_bzDecompress(&pfile_in_zip_read_info->bstream); + + uTotalOutAfter = pfile_in_zip_read_info->bstream.total_out_lo32; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis; + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,bufBefore, (uInt)(uOutThis)); + pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis; + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + + pfile_in_zip_read_info->stream.next_in = (Bytef*)pfile_in_zip_read_info->bstream.next_in; + pfile_in_zip_read_info->stream.avail_in = pfile_in_zip_read_info->bstream.avail_in; + pfile_in_zip_read_info->stream.total_in = pfile_in_zip_read_info->bstream.total_in_lo32; + pfile_in_zip_read_info->stream.next_out = (Bytef*)pfile_in_zip_read_info->bstream.next_out; + pfile_in_zip_read_info->stream.avail_out = pfile_in_zip_read_info->bstream.avail_out; + pfile_in_zip_read_info->stream.total_out = pfile_in_zip_read_info->bstream.total_out_lo32; + + if (err==BZ_STREAM_END) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=BZ_OK) + break; +#endif + } // end Z_BZIP2ED + else + { + ZPOS64_T uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + ZPOS64_T uOutThis; + int flush=Z_SYNC_FLUSH; + + uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; + bufBefore = pfile_in_zip_read_info->stream.next_out; + + /* + if ((pfile_in_zip_read_info->rest_read_uncompressed == + pfile_in_zip_read_info->stream.avail_out) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + flush = Z_FINISH; + */ + err=inflate(&pfile_in_zip_read_info->stream,flush); + + if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL)) + err = Z_DATA_ERROR; + + uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis; + + pfile_in_zip_read_info->crc32 = + crc32(pfile_in_zip_read_info->crc32,bufBefore, + (uInt)(uOutThis)); + + pfile_in_zip_read_info->rest_read_uncompressed -= + uOutThis; + + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + + if (err==Z_STREAM_END) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=Z_OK) + break; + } + } + + if (err==Z_OK) + return iRead; + return err; +} + + +/* + Give the current position in uncompressed data +*/ +z_off_t ZEXPORT unztell (unzFile file) +{ + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + return (z_off_t)pfile_in_zip_read_info->stream.total_out; +} + +ZPOS64_T ZEXPORT unztell64 (unzFile file) +{ + + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return (ZPOS64_T)-1; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return (ZPOS64_T)-1; + + return pfile_in_zip_read_info->total_out_64; +} + + +/* + return 1 if the end of file was reached, 0 elsewhere +*/ +int ZEXPORT unzeof (unzFile file) +{ + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + return 1; + else + return 0; +} + + + +/* +Read extra field from the current file (opened by unzOpenCurrentFile) +This is the local-header version of the extra field (sometimes, there is +more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field that can be read + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ +int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len) +{ + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + uInt read_now; + ZPOS64_T size_to_read; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + size_to_read = (pfile_in_zip_read_info->size_local_extrafield - + pfile_in_zip_read_info->pos_local_extrafield); + + if (buf==NULL) + return (int)size_to_read; + + if (len>size_to_read) + read_now = (uInt)size_to_read; + else + read_now = (uInt)len ; + + if (read_now==0) + return 0; + + if (ZSEEK64(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->offset_local_extrafield + + pfile_in_zip_read_info->pos_local_extrafield, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (ZREAD64(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + buf,read_now)!=read_now) + return UNZ_ERRNO; + + return (int)read_now; +} + +/* + Close the file in zip opened with unzipOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ +int ZEXPORT unzCloseCurrentFile (unzFile file) +{ + int err=UNZ_OK; + + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) && + (!pfile_in_zip_read_info->raw)) + { + if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) + err=UNZ_CRCERROR; + } + + + TRYFREE(pfile_in_zip_read_info->read_buffer); + pfile_in_zip_read_info->read_buffer = NULL; + if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED) + inflateEnd(&pfile_in_zip_read_info->stream); +#ifdef HAVE_BZIP2 + else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED) + BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream); +#endif + + + pfile_in_zip_read_info->stream_initialised = 0; + TRYFREE(pfile_in_zip_read_info); + + s->pfile_in_zip_read=NULL; + + return err; +} + + +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ +int ZEXPORT unzGetGlobalComment (unzFile file, char * szComment, uLong uSizeBuf) +{ + unz64_s* s; + uLong uReadThis ; + if (file==NULL) + return (int)UNZ_PARAMERROR; + s=(unz64_s*)file; + + uReadThis = uSizeBuf; + if (uReadThis>s->gi.size_comment) + uReadThis = s->gi.size_comment; + + if (ZSEEK64(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (uReadThis>0) + { + *szComment='\0'; + if (ZREAD64(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis) + return UNZ_ERRNO; + } + + if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) + *(szComment+s->gi.size_comment)='\0'; + return (int)uReadThis; +} + +/* Additions by RX '2004 */ +ZPOS64_T ZEXPORT unzGetOffset64(unzFile file) +{ + unz64_s* s; + + if (file==NULL) + return 0; //UNZ_PARAMERROR; + s=(unz64_s*)file; + if (!s->current_file_ok) + return 0; + if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff) + if (s->num_file==s->gi.number_entry) + return 0; + return s->pos_in_central_dir; +} + +uLong ZEXPORT unzGetOffset (unzFile file) +{ + ZPOS64_T offset64; + + if (file==NULL) + return 0; //UNZ_PARAMERROR; + offset64 = unzGetOffset64(file); + return (uLong)offset64; +} + +int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos) +{ + unz64_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + + s->pos_in_central_dir = pos; + s->num_file = s->gi.number_entry; /* hack */ + err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + +int ZEXPORT unzSetOffset (unzFile file, uLong pos) +{ + return unzSetOffset64(file,pos); +} + diff --git a/VIServer/Classes/FoundationKit/external/unzip/unzip.h b/VIServer/Classes/FoundationKit/external/unzip/unzip.h new file mode 100644 index 0000000000..1a8ba09c51 --- /dev/null +++ b/VIServer/Classes/FoundationKit/external/unzip/unzip.h @@ -0,0 +1,451 @@ +/* unzip.h -- IO for uncompress .zip files using zlib + Version 1.1, February 14h, 2010 + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications of Unzip for Zip64 + Copyright (C) 2007-2008 Even Rouault + + Modifications for Zip64 support on both zip and unzip + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + + --------------------------------------------------------------------------------- + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + --------------------------------------------------------------------------------- + + Changes + + See header of unzip64.c + +*/ + +#ifndef _unz64_H +#define _unz64_H + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#ifndef _ZLIBIOAPI_H +#include "ioapi.h" +#endif + +#ifdef HAVE_BZIP2 +#include "bzlib.h" +#endif + +#define Z_BZIP2ED 12 + +#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagunzFile__ { int unused; } unzFile__; +typedef unzFile__ *unzFile; +#else +typedef voidp unzFile; +#endif + + +#define UNZ_OK (0) +#define UNZ_END_OF_LIST_OF_FILE (-100) +#define UNZ_ERRNO (Z_ERRNO) +#define UNZ_EOF (0) +#define UNZ_PARAMERROR (-102) +#define UNZ_BADZIPFILE (-103) +#define UNZ_INTERNALERROR (-104) +#define UNZ_CRCERROR (-105) + +/* tm_unz contain date/time info */ +typedef struct tm_unz_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_unz; + +/* unz_global_info structure contain global data about the ZIPfile + These data comes from the end of central dir */ +typedef struct unz_global_info64_s +{ + ZPOS64_T number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info64; + +typedef struct unz_global_info_s +{ + uLong number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info; + +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_info64_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + ZPOS64_T compressed_size; /* compressed size 8 bytes */ + ZPOS64_T uncompressed_size; /* uncompressed size 8 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info64; + +typedef struct unz_file_info_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + uLong compressed_size; /* compressed size 4 bytes */ + uLong uncompressed_size; /* uncompressed size 4 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info; + +int unzStringFileNameCompare OF ((const char* fileName1, + const char* fileName2, + int iCaseSensitivity)); +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparison is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparison is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is default of your operating system + (like 1 on Unix, 2 on Windows) +*/ + + +unzFile unzOpen OF((const char *path)); +unzFile unzOpen64 OF((const void *path)); +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer + "zlib/zlib113.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. + the "64" function take a const void* pointer, because the path is just the + value passed to the open64_file_func callback. + Under Windows, if UNICODE is defined, using fill_fopen64_filefunc, the path + is a pointer to a wide unicode string (LPCTSTR is LPCWSTR), so const char* + does not describe the reality +*/ + +unzFile unzOpenBuffer OF((const void* buffer, uLong size)); + +unzFile unzOpen2 OF((const char *path, + zlib_filefunc_def* pzlib_filefunc_def)); +/* + Open a Zip file, like unzOpen, but provide a set of file low level API + for read/write the zip file (see ioapi.h) +*/ + +unzFile unzOpen2_64 OF((const void *path, + zlib_filefunc64_def* pzlib_filefunc_def)); +/* + Open a Zip file, like unz64Open, but provide a set of file low level API + for read/write the zip file (see ioapi.h) +*/ + +int unzClose OF((unzFile file)); +/* + Close a ZipFile opened with unzipOpen. + If there is files inside the .Zip opened with unzOpenCurrentFile (see later), + these files MUST be closed with unzipCloseCurrentFile before call unzipClose. + return UNZ_OK if there is no problem. */ + +int unzGetGlobalInfo OF((unzFile file, + unz_global_info *pglobal_info)); + +int unzGetGlobalInfo64 OF((unzFile file, + unz_global_info64 *pglobal_info)); +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ + + +int unzGetGlobalComment OF((unzFile file, + char *szComment, + uLong uSizeBuf)); +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ + + +/***************************************************************************/ +/* Unzip package allow you browse the directory of the zipfile */ + +int unzGoToFirstFile OF((unzFile file)); + +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ + +int unzGoToFirstFile64 OF((unzFile file, + unz_file_info64 *pfile_info, + char *szFileName, + uLong fileNameBufferSize)); +/* + Set the current file of the zipfile to the first file + with retrieving an information about the file. + return UNZ_OK if there is no problem +*/ + +int unzGoToNextFile OF((unzFile file)); +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ + +int unzGoToNextFile64 OF((unzFile file, + unz_file_info64 *pfile_info, + char *szFileName, + uLong fileNameBufferSize)); +/* + Set the current file of the zipfile to the next file + with retrieving an information about the file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ + +int unzLocateFile OF((unzFile file, + const char *szFileName, + int iCaseSensitivity)); +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ + + +/* ****************************************** */ +/* Ryan supplied functions */ +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_pos_s +{ + uLong pos_in_zip_directory; /* offset in zip file directory */ + uLong num_of_file; /* # of file */ +} unz_file_pos; + +int unzGetFilePos( + unzFile file, + unz_file_pos* file_pos); + +int unzGoToFilePos( + unzFile file, + unz_file_pos* file_pos); + +typedef struct unz64_file_pos_s +{ + ZPOS64_T pos_in_zip_directory; /* offset in zip file directory */ + ZPOS64_T num_of_file; /* # of file */ +} unz64_file_pos; + +int unzGetFilePos64( + unzFile file, + unz64_file_pos* file_pos); + +int unzGoToFilePos64( + unzFile file, + const unz64_file_pos* file_pos); + +/* ****************************************** */ + +int unzGetCurrentFileInfo64 OF((unzFile file, + unz_file_info64 *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); + +int unzGetCurrentFileInfo OF((unzFile file, + unz_file_info *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); +/* + Get Info about the current file + if pfile_info!=NULL, the *pfile_info structure will contain some info about + the current file + if szFileName!=NULL, the filename string will be copied in szFileName + (fileNameBufferSize is the size of the buffer) + if extraField!=NULL, the extra field information will be copied in extraField + (extraFieldBufferSize is the size of the buffer). + This is the Central-header version of the extra field + if szComment!=NULL, the comment string of the file will be copied in szComment + (commentBufferSize is the size of the buffer) +*/ + + +/** Addition for GDAL : START */ + +ZPOS64_T unzGetCurrentFileZStreamPos64 OF((unzFile file)); + +/** Addition for GDAL : END */ + + +/***************************************************************************/ +/* for reading the content of the current zipfile, you can open it, read data + from it, and close it (you can close it before reading all the file) + */ + +int unzOpenCurrentFile OF((unzFile file)); +/* + Open for reading data the current file in the zipfile. + If there is no error, the return value is UNZ_OK. +*/ + +int unzOpenCurrentFilePassword OF((unzFile file, + const char* password)); +/* + Open for reading data the current file in the zipfile. + password is a crypting password + If there is no error, the return value is UNZ_OK. +*/ + +int unzOpenCurrentFile2 OF((unzFile file, + int* method, + int* level, + int raw)); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + +int unzOpenCurrentFile3 OF((unzFile file, + int* method, + int* level, + int raw, + const char* password)); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + + +int unzCloseCurrentFile OF((unzFile file)); +/* + Close the file in zip opened with unzOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ + +int unzReadCurrentFile OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read bytes from the current file (opened by unzOpenCurrentFile) + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if some bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ + +z_off_t unztell OF((unzFile file)); + +ZPOS64_T unztell64 OF((unzFile file)); +/* + Give the current position in uncompressed data +*/ + +int unzeof OF((unzFile file)); +/* + return 1 if the end of file was reached, 0 elsewhere +*/ + +int unzGetLocalExtrafield OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ + +/***************************************************************************/ + +/* Get the current file offset */ +ZPOS64_T unzGetOffset64 (unzFile file); +uLong unzGetOffset (unzFile file); + +/* Set the current file offset */ +int unzSetOffset64 (unzFile file, ZPOS64_T pos); +int unzSetOffset (unzFile file, uLong pos); + + +#endif /* _unz64_H */ diff --git a/VIServer/Classes/FoundationKit/external/zlib/zconf.h b/VIServer/Classes/FoundationKit/external/zlib/zconf.h new file mode 100644 index 0000000000..02ce56c431 --- /dev/null +++ b/VIServer/Classes/FoundationKit/external/zlib/zconf.h @@ -0,0 +1,428 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ + +/* all linked symbols */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzgetc z_gzgetc +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzwrite z_gzwrite +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetHeader z_inflateGetHeader +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# define uncompress z_uncompress +# define zError z_zError +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# define gzFile z_gzFile +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef STDC +# include /* for off_t */ +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +#endif + +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +# define z_off64_t off64_t +#else +# define z_off64_t z_off_t +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/VIServer/Classes/FoundationKit/external/zlib/zlib.h b/VIServer/Classes/FoundationKit/external/zlib/zlib.h new file mode 100644 index 0000000000..bfbba83e8e --- /dev/null +++ b/VIServer/Classes/FoundationKit/external/zlib/zlib.h @@ -0,0 +1,1613 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.5, April 19th, 2010 + + Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.5" +#define ZLIB_VERNUM 0x1250 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 2 +#define ZLIB_VER_REVISION 5 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use in the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). Some + output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed code + block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the stream + are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least the + value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + binary. This field is only for information purposes and does not affect the + compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the + exact value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit() does not process any header information -- that is deferred + until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing will + resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all the uncompressed data. (The size + of the uncompressed data may have been saved by the compressor for this + purpose.) The next operation on this stream must be inflateEnd to deallocate + the decompression state. The use of Z_FINISH is never required, but can be + used to inform inflate that a faster approach may be used for the single + inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK or Z_TREES is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained, so applications that need that information should + instead use raw inflate, see inflateInit2() below, or inflateBack() and + perform their own processing of the gzip header and trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by the + caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any call + of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. The + stream will keep the same compression level and any other attributes that + may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression level is changed, the input available so far is + compressed with the old level (and may be flushed); the new level will take + effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to be + compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if + strm->avail_out was zero. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. The application must insure that the + dictionary that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been + found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the + success case, the application may save the current current value of total_in + which indicates where valid compressed data was found. In the error case, + the application may repeatedly call inflateSync, providing more input each + time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above or -1 << 16 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the normal + behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed buffer. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef voidp gzFile; /* opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); + + Opens a gzip (.gz) file for reading or writing. The mode parameter is as + in fopen ("rb" or "wb") but can also include a compression level ("wb9") or + a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only + compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' + for fixed code compression as in "wb9F". (See the description of + deflateInit2 for more information about the strategy parameter.) Also "a" + can be used instead of "w" to request that the gzip stream that will be + written be appended to the file. "+" will result in an error, since reading + and writing to the same gzip file is not supported. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen associates a gzFile with the file descriptor fd. File descriptors + are obtained from calls like open, dup, creat, pipe or fileno (if the file + has been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +/* + Set the internal buffer size used by this library's functions. The + default buffer size is 8192 bytes. This function must be called after + gzopen() or gzdopen(), and before any other calls that read or write the + file. The buffer memory allocation is always deferred to the first read or + write. Two buffers are allocated, either both of the specified size when + writing, or one of the specified size and the other twice that size when + reading. A larger buffer size of, for example, 64K or 128K bytes will + noticeably increase the speed of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. If + the input file was not in gzip format, gzread copies the given number of + bytes into the buffer. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream, or failing that, reading the rest + of the input file directly without decompression. The entire input file + will be read if gzread is called until it returns less than the requested + len. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. +*/ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes written or 0 in case of + error. +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the arguments to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or 0 in case of error. The number of + uncompressed bytes written is limited to 8191, or one less than the buffer + size given to gzbuffer(). The caller should assure that this limit is not + exceeded. If it is exceeded, then gzprintf() will return an error (0) with + nothing written. In this case, there may also be a buffer overflow with + unpredictable consequences, which is possible only if zlib was compiled with + the insecure functions sprintf() or vsprintf() because the secure snprintf() + or vsnprintf() functions were not available. This can be determined using + zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or a + newline character is read and transferred to buf, or an end-of-file + condition is encountered. If any characters are read or if len == 1, the + string is terminated with a null character. If no characters are read due + to an end-of-file or len < 1, then the buffer is left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte or -1 + in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read as the first character + on the next read. At least one character of push-back is allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter flush + is as in the deflate() function. The return value is the zlib error number + (see function gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatented gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); + + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); + + Returns the starting position for the next gzread or gzwrite on the given + compressed file. This position represents a number of bytes in the + uncompressed data stream, and is zero when starting, even if appending or + reading a gzip stream from the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Returns the current offset in the file being read or written. This offset + includes the count of bytes that precede the gzip stream, for example when + appending or when using gzdopen() for reading. When reading, the offset + does not include as yet unused buffered input. This information can be used + for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns true (1) if the end-of-file indicator has been set while reading, + false (0) otherwise. Note that the end-of-file indicator is set only if the + read tried to go past the end of the input, but came up short. Therefore, + just like feof(), gzeof() may return false even if there is no more data to + read, in the event that the last read request was for the exact number of + bytes remaining in the input file. This will happen if the input file size + is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. This state can change from + false to true while reading the input file if the end of a gzip stream is + reached, but is followed by data that is not another gzip stream. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file and + deallocates the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the given + compressed file. errnum is set to zlib error number. If an error occurred + in the file system and not in the compression library, errnum is set to + Z_ERRNO and the application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is Z_NULL, this function returns the + required initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is Z_NULL, this function returns the required + initial value for the for the crc. Pre- and post-conditioning (one's + complement) is performed within this function so it shouldn't be done by the + application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0 +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# ifdef _LARGEFILE64_SOURCE + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); +#endif + +/* hack for buggy compilers */ +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; +#endif + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/VIServer/Classes/NetworkProtocols.cpp b/VIServer/Classes/NetworkProtocols.cpp new file mode 100644 index 0000000000..0971e5e74f --- /dev/null +++ b/VIServer/Classes/NetworkProtocols.cpp @@ -0,0 +1,38 @@ +#include "NetworkProtocols.h" +#include +#include "Networking/IProtocol.h" +#include "Networking/SocketBSD.h" +#include "VIServer.h" +#include "ClientProtocolDefines.h" +#include "ConnectionManager.h" + + +// Э +class ClientChat : IProtocol +{ +public: + ClientChat(int32 idx) :IProtocol(idx){} + + virtual void ProcessStreamProtocol(uint64 clientID, DataStream & stream) + { + std::string msg; + stream >> msg; + LOG_INFO(">>RECV:%s", msg.c_str()); + + auto client = ConnectionManager::getInstance()->getClientByID(clientID); + + int bytesSend; + char* sendMsg = "I recv you send msg."; + client->Send((unsigned char*)sendMsg, strlen(sendMsg), bytesSend); + } +}; + + +IMPLEMENT_PROTOCOL(ClientChat, CLIENT_CHAT); + + + + + + + diff --git a/VIServer/Classes/NetworkProtocols.h b/VIServer/Classes/NetworkProtocols.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/VIServer/Classes/Networking/IPAddressBSD.h b/VIServer/Classes/Networking/IPAddressBSD.h new file mode 100644 index 0000000000..7f219ab53e --- /dev/null +++ b/VIServer/Classes/Networking/IPAddressBSD.h @@ -0,0 +1,230 @@ +#ifndef LOSEMYMIND_IPADDRESSBSD_H +#define LOSEMYMIND_IPADDRESSBSD_H + + + +#pragma once +#include +#include +#include "socket_types.hpp" +#include "FoundationKit/Base/Types.h" +#include "FoundationKit/Foundation/StringUtils.h" + +USING_NS_FK; + +/** + * Represents an internet ip address, using the relatively standard SOCKADDR_IN structure. All data is in network byte order + */ +class InternetAddrBSD +{ +protected: + /** The internet ip address structure */ + sockaddr_in _Addr; + +public: + /** + * Constructor. Sets address to default state + */ + InternetAddrBSD() + { + memset(&_Addr, 0x00, sizeof(sockaddr_in)); + _Addr.sin_family = AF_INET; + } + /** + * Sets the ip address from a host byte order uint32 + * + * @param inAddr the new address to use (must convert to network byte order) + */ + virtual void SetIp(uint32 inAddr) + { + _Addr.sin_addr.s_addr = htonl(inAddr); + } + + /** + * Sets the ip address from a string ("A.B.C.D:PORT") + * + * @param inAddr the string containing the new ip address to use + */ + virtual void SetIp(const char* inAddr, bool& bIsValid) + { + int32 A, B, C, D; + int32 port = 0; + + std::string addressString = inAddr; + + std::vector portTokens = StringUtils::split(addressString, ':'); + + + // look for a port number + if (portTokens.size() > 1) + { + port = std::atoi(portTokens[1].c_str()); + } + + // now split the part before the : into a.b.c.d + + std::vector addrTokens = StringUtils::split(portTokens[0], ':'); + + + if (addrTokens.size() < 4) + { + bIsValid = false; + return; + } + + A = std::atoi(addrTokens[0].c_str()); + B = std::atoi(addrTokens[1].c_str()); + C = std::atoi(addrTokens[2].c_str()); + D = std::atoi(addrTokens[3].c_str()); + + // Make sure the address was valid + if ((A & 0xFF) == A && (B & 0xFF) == B && (C & 0xFF) == C && (D & 0xFF) == D) + { + SetIp((A << 24) | (B << 16) | (C << 8) | (D << 0)); + + if (port != 0) + { + SetPort(port); + } + + bIsValid = true; + } + else + { + //debugf(TEXT("Invalid IP address string (%s) passed to SetIp"),InAddr); + bIsValid = false; + } + } + + /** + * Sets the ip address using a network byte order ip address + * + * @param IpAddr the new ip address to use + */ + void SetIp(const in_addr& ipAddr) + { + _Addr.sin_addr = ipAddr; + } + + + /** + * Copies the network byte order ip address to a host byte order dword + * + * @param OutAddr the out param receiving the ip address + */ + virtual void GetIp(uint32& outAddr) const + { + outAddr = ntohl(_Addr.sin_addr.s_addr); + } + + /** + * Copies the network byte order ip address + * + * @param OutAddr the out param receiving the ip address + */ + void GetIp(in_addr& outAddr) const + { + outAddr = _Addr.sin_addr; + } + + /** + * Sets the port number from a host byte order int + * + * @param InPort the new port to use (must convert to network byte order) + */ + virtual void SetPort(int32 InPort) + { + _Addr.sin_port = htons(InPort); + } + + /** + * Copies the port number from this address and places it into a host byte order int + * + * @param OutPort the host byte order int that receives the port + */ + virtual void GetPort(int32& OutPort) const + { + OutPort = ntohs(_Addr.sin_port); + } + + /** + * Returns the port number from this address in host byte order + */ + virtual int32 GetPort(void) const + { + return ntohs(_Addr.sin_port); + } + + /** Sets the address to be any address */ + virtual void SetAnyAddress(void) + { + SetIp(INADDR_ANY); + SetPort(0); + } + + /** Sets the address to broadcast */ + virtual void SetBroadcastAddress() + { + SetIp(INADDR_BROADCAST); + SetPort(0); + } + + /** + * Converts this internet ip address to string form + * + * @param bAppendPort whether to append the port information or not + */ + virtual std::string ToString(bool bAppendPort) const + { + uint32 LocalAddr = ntohl(_Addr.sin_addr.s_addr); + + // Get the individual bytes + const int32 A = (LocalAddr >> 24) & 0xFF; + const int32 B = (LocalAddr >> 16) & 0xFF; + const int32 C = (LocalAddr >> 8) & 0xFF; + const int32 D = (LocalAddr >> 0) & 0xFF; + if (bAppendPort) + { + return StringUtils::format("%i.%i.%i.%i:%i",A,B,C,D,GetPort()); + } + else + { + return StringUtils::format("%i.%i.%i.%i", A, B, C, D); + } + } + + /** + * Compares two internet ip addresses for equality + * + * @param Other the address to compare against + */ + virtual bool operator==(const InternetAddrBSD& Other) const + { + InternetAddrBSD& OtherBSD = (InternetAddrBSD&)Other; + return _Addr.sin_addr.s_addr == OtherBSD._Addr.sin_addr.s_addr && + _Addr.sin_port == OtherBSD._Addr.sin_port && + _Addr.sin_family == OtherBSD._Addr.sin_family; + } + + /** + * Is this a well formed internet address + * + * @return true if a valid IP, false otherwise + */ + virtual bool IsValid() const + { + return _Addr.sin_addr.s_addr != 0; + } + + operator sockaddr*(void) + { + return (sockaddr*)&_Addr; + } + + operator const sockaddr*(void) const + { + return (const sockaddr*)&_Addr; + } +}; + +#endif // LOSEMYMIND_IPADDRESSBSD_H diff --git a/VIServer/Classes/Networking/IProtocol.cpp b/VIServer/Classes/Networking/IProtocol.cpp new file mode 100644 index 0000000000..a7ecb7e5f9 --- /dev/null +++ b/VIServer/Classes/Networking/IProtocol.cpp @@ -0,0 +1,42 @@ + +#include "IProtocol.h" +#include "FoundationKit/Foundation/Logger.h" + +// 协议池实例 +IProtocol::PROTOCOLS & IProtocol::GetProtoclsPool () +{ + static IProtocol::PROTOCOLS protocols; + return protocols; +} + +// 每个协议一个协议ID +IProtocol::IProtocol(int32 idx) +{ + //LOG_ASSERT(GetMatchedProtocol(idx) == nullptr, "***** 协议id 已经存在,请重新指定。"); + PROTOCOLS & pool = GetProtoclsPool(); + pool.insert(std::pair< int32, IProtocol* >(idx, this)); +} + +// 根据协议ID获得协议的实例 +IProtocol * IProtocol::GetMatchedProtocol(int32 idx) +{ + PROTOCOLS & pool = GetProtoclsPool(); + PROTOCOLS::iterator it = pool.find( idx ); + if ( it != pool.end() ) + return it->second; + return nullptr; +} + +void IProtocol::DispathStreamProtocol(uint64 clientID, DataStream & stream) +{ + int32 idx = stream.read(); + IProtocol * pProtocol = GetMatchedProtocol( idx ); + if ( pProtocol ) + { + pProtocol->ProcessStreamProtocol(clientID, stream); + } + else + { + LOG_ERROR("***** Cannot found procotol by id[%d]", idx); + } +} diff --git a/VIServer/Classes/Networking/IProtocol.h b/VIServer/Classes/Networking/IProtocol.h new file mode 100644 index 0000000000..733012fb59 --- /dev/null +++ b/VIServer/Classes/Networking/IProtocol.h @@ -0,0 +1,49 @@ +#ifndef LOSEMYMIND_IPROTOCOL_H +#define LOSEMYMIND_IPROTOCOL_H + +#include +#include "FoundationKit/Base/Types.h" +#include "FoundationKit/Base/DataStream.h" + +USING_NS_FK; + +/** +@brief 实现接收客户端协议的接口 +*/ +class IProtocol +{ + typedef std::unordered_map< int32, IProtocol * > PROTOCOLS; +private: + /** + * @brief 禁止默认建构 + */ + IProtocol() {} + + /** + * @brief 管理各个协议的MAP + */ + static PROTOCOLS & GetProtoclsPool (); + + /** + * @brief 根据协议ID获得协议的指针 + */ + static IProtocol * GetMatchedProtocol(int32 idx); +public: + IProtocol(int32 idx); + virtual ~IProtocol() {} + + /** + * @brief 分发原始流协议 + */ + static void DispathStreamProtocol(uint64 clientID, DataStream & stream); + + + /** + * @brief 处理原始流协议 + */ + virtual void ProcessStreamProtocol(uint64 clientID, DataStream & stream) {} +}; + +#define IMPLEMENT_PROTOCOL(CLS,IDX) CLS G_PROTOCOL_##CLS(IDX) + +#endif // LOSEMYMIND_IPROTOCOL_H diff --git a/VIServer/Classes/Networking/IPv4Address.h b/VIServer/Classes/Networking/IPv4Address.h new file mode 100644 index 0000000000..1b9d3315c6 --- /dev/null +++ b/VIServer/Classes/Networking/IPv4Address.h @@ -0,0 +1,262 @@ +// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved. + +#ifndef LOSEMYMIND_IPV4ADDRESS_H +#define LOSEMYMIND_IPV4ADDRESS_H + +#pragma once +#include +#include "FoundationKit/GenericPlatformMacros.h" +#include "FoundationKit/Foundation/ByteSwap.h" +#include "FoundationKit/Base/Types.h" +#include "FoundationKit/Foundation/StringUtils.h" +USING_NS_FK; + +/** + * Implements an IPv4 address. + */ +struct IPv4Address +{ + union + { + /** The IP address value as A.B.C.D components. */ + struct + { +#if (ENDIANNESS_ORDER == ENDIANNESS_LITTLE_ENDIAN) + #if _MSC_VER + uint8 D, C, B, A; + #else + uint8 D GCC_ALIGN(4); + uint8 C, B, A; + #endif +#else + uint8 A, B, C, D; +#endif + }; + + /** The IP address value in host byte order. */ + uint32 Value; + }; + +public: + + /** Default constructor. */ + IPv4Address() { } + + /** + * Creates and initializes a new IPv4 address with the specified components. + * + * The created IP address has the value A.B.C.D. + * + * @param InA The first component. + * @param InB The second component. + * @param InC The third component. + * @param InD The fourth component. + */ + IPv4Address(uint8 InA, uint8 InB, uint8 InC, uint8 InD) +#if (ENDIANNESS_ORDER == ENDIANNESS_LITTLE_ENDIAN) + : D(InD) + , C(InC) + , B(InB) + , A(InA) +#else + : A(InA) + , B(InB) + , C(InC) + , D(InD) +#endif // (ENDIANNESS_ORDER == ENDIANNESS_LITTLE_ENDIAN) + { } + + /** + * Creates and initializes a new IPv4 address with the specified value. + * + * @param InValue The address value (in host byte order). + */ + IPv4Address(uint32 InValue) + : Value(InValue) + { } + +public: + + /** + * Compares this IPv4 address with the given address for equality. + * + * @param Other The address to compare with. + * @return true if the addresses are equal, false otherwise. + */ + bool operator==(const IPv4Address& Other) const + { + return (Value == Other.Value); + } + + /** + * Compares this IPv4 address with the given address for inequality. + * + * @param Other The address to compare with. + * @return true if the addresses are not equal, false otherwise. + */ + bool operator!=(const IPv4Address& Other) const + { + return (Value != Other.Value); + } + +public: + + /** + * Checks whether this IP address is a global multicast address. + * + * Global multicast addresses are in the range 224.0.1.0 to 238.255.255.255. + * + * @return true if it is a global multicast address, false otherwise. + * @see IsLinkLocalMulticast, IsOrganizationLocalMulticast, IsSiteLocalMulticast + */ + bool IsGlobalMulticast() const + { + return (((A >= 224) && A <= 238) && !((A == 224) && (B == 0) && (C == 0))); + } + + /** + * Checks whether this IP address is link local. + * + * Link local addresses are in the range 169.254.0.0/16 + * + * @return true if it is link local, false otherwise. + */ + bool IsLinkLocal() const + { + return ((A == 169) && (B == 254)); + } + + /** + * Checks whether this IP address is a link local multicast address. + * + * Link local multicast addresses have the form 224.0.0.x. + * + * @return true if it is a link local multicast address, false otherwise. + * @see IsGlobalMulticast, IsOrganizationLocalMulticast, IsSiteLocalMulticast + */ + bool IsLinkLocalMulticast() const + { + return ((A >= 224) && (B == 0) && (C == 0)); + } + + /** + * Checks whether this IP address is a loopback address. + * + * Loopback addresses have the form 127.x.x.x + * + * @return true if it is a loopback address, false otherwise. + * @see IsMulticastAddress + */ + bool IsLoopbackAddress() const + { + return (A == 127); + } + + /** + * Checks whether this IP address is a multicast address. + * + * Multicast addresses are in the range 224.0.0.0 to 239.255.255.255. + * + * @return true if it is a multicast address, false otherwise. + * @see IsLoopbackAddress + */ + bool IsMulticastAddress() const + { + return ((A >= 224) && (A <= 239)); + } + + /** + * Checks whether this IP address is a organization local multicast address. + * + * Organization local multicast addresses are in the range 239.192.x.x to 239.195.x.x. + * + * @return true if it is a site local multicast address, false otherwise. + * @see IsGlobalMulticast, IsLinkLocalMulticast, IsSiteLocalMulticast + */ + bool IsOrganizationLocalMulticast() const + { + return ((A == 239) && (B >= 192) && (B <= 195)); + } + + /** + * Checks whether this IP address is a site local address. + * + * Site local addresses have one of the following forms: + * 10.x.x.x + * 172.16.x.x + * 192.168.x.x + * + * @return true if it is a site local address, false otherwise. + */ + bool IsSiteLocalAddress() const + { + return ((A == 10) || ((A == 172) && (B == 16)) || ((A == 192) && (B == 168))); + } + + /** + * Checks whether this IP address is a site local multicast address. + * + * Site local multicast addresses have the form 239.255.0.x. + * + * @return true if it is a site local multicast address, false otherwise. + * @see IsGlobalMulticast, IsLinkLocalMulticast, IsOrganizationLocalMulticast + */ + bool IsSiteLocalMulticast() const + { + return ((A == 239) && (B == 255)); + } + + /** + * Gets the string representation for this address. + * + * @return String representation. + * @see Parse, ToText + */ + std::string ToString() const + { + return StringUtils::format("%i.%i.%i.%i", A, B, C, D); + } + +public: + + /** + * Converts a string to an IPv4 address. + * + * @param AddressString The string to convert. + * @param OutAddress Will contain the parsed address. + * @return true if the string was converted successfully, false otherwise. + * @see ToString + */ + static bool Parse(const std::string& AddressString, IPv4Address& OutAddress) + { + std::vector Tokens = StringUtils::split(AddressString, '.'); + if (Tokens.size() == 4) + { + OutAddress.A = std::stoi(Tokens[0].c_str()); + OutAddress.B = std::stoi(Tokens[1].c_str()); + OutAddress.C = std::stoi(Tokens[2].c_str()); + OutAddress.D = std::stoi(Tokens[3].c_str()); + return true; + } + return false; + } + +public: + + /** Defines the wild card address, which is 0.0.0.0 */ + static const IPv4Address Any; + + /** Defines the internal loopback address, which is 127.0.0.1 */ + static const IPv4Address InternalLoopback; + + /** Defines the broadcast address for the 'zero network' (i.e. LAN), which is 255.255.255.255. */ + static const IPv4Address LanBroadcast; +}; + + + + +#endif // LOSEMYMIND_IPV4ADDRESS_H + + + diff --git a/VIServer/Classes/Networking/IPv4Endpoint.h b/VIServer/Classes/Networking/IPv4Endpoint.h new file mode 100644 index 0000000000..b2bb490e34 --- /dev/null +++ b/VIServer/Classes/Networking/IPv4Endpoint.h @@ -0,0 +1,150 @@ +#ifndef LOSEMYMIND_IPV4ENDPOINT_H +#define LOSEMYMIND_IPV4ENDPOINT_H + + + +#pragma once +#include +#include "IPv4Address.h" +#include "IPAddressBSD.h" + +/** + * Implements an endpoint for IPv4 networks. + * + * An endpoint consists of an IPv4 address and a port number. + * + * @todo gmp: add IPv6 support and rename this to FIpEndpoint? + */ +struct IPv4Endpoint +{ + /** Holds the endpoint's IP address. */ + IPv4Address Address; + + /** Holds the endpoint's port number. */ + uint16 Port; + +public: + + /** Default constructor. */ + IPv4Endpoint() { } + + /** + * Creates and initializes a new IPv4 endpoint with the specified NetID and port. + * + * @param InAddress The endpoint's IP address. + * @param InPort The endpoint's port number. + */ + IPv4Endpoint(const IPv4Address& InAddress, uint16 InPort) + : Address(InAddress) + , Port(InPort) + { } + + /** + * Creates and initializes a new IPv4 endpoint from a given FInternetAddr object. + * + * Note: this constructor will be removed after the socket subsystem has been refactored. + * + * @param InternetAddrBSD The Internet address. + */ + IPv4Endpoint(const std::shared_ptr& InternetAddr) + { + int32 OutPort; + InternetAddr->GetIp(Address.Value); + InternetAddr->GetPort(OutPort); + Port = OutPort; + } + +public: + + /** + * Compares this IPv4 endpoint with the given endpoint for equality. + * + * @param Other The endpoint to compare with. + * @return true if the endpoints are equal, false otherwise. + */ + bool operator==(const IPv4Endpoint& Other) const + { + return ((Address == Other.Address) && (Port == Other.Port)); + } + + /** + * Compares this IPv4 address with the given endpoint for inequality. + * + * @param Other The endpoint to compare with. + * @return true if the endpoints are not equal, false otherwise. + */ + bool operator!=(const IPv4Endpoint& Other) const + { + return ((Address != Other.Address) || (Port != Other.Port)); + } + + +public: + + /** + * Converts this endpoint to an FInternetAddr object. + * + * Note: this method will be removed after the socket subsystem is refactored. + * + * @return Internet address object representing this endpoint. + */ + std::shared_ptr ToInternetAddr() const + { + std::shared_ptr InternetAddr = std::shared_ptr(new InternetAddrBSD); + { + InternetAddr->SetIp(Address.Value); + InternetAddr->SetPort(Port); + } + return InternetAddr; + } + + /** + * Gets a string representation for this endpoint. + * + * @return String representation. + * @see Parse, ToText + */ + std::string ToString() const + { + return StringUtils::format("%s:%i", Address.ToString().c_str(), Port); + } + +public: + + /** + * Converts a string to an IPv4 endpoint. + * + * @param EndpointString The string to convert. + * @param OutEndpoint Will contain the parsed endpoint. + * @return true if the string was converted successfully, false otherwise. + * @see ToString + */ + static bool Parse(const std::string& EndpointString, IPv4Endpoint& OutEndpoint) + { + std::vector Tokens = StringUtils::split(EndpointString, ':'); + + if (Tokens.size() == 2) + { + if (IPv4Address::Parse(Tokens[0], OutEndpoint.Address)) + { + OutEndpoint.Port = std::atoi(Tokens[1].c_str()); + + return true; + } + } + + return false; + } + +public: + + /** Defines the wild card endpoint, which is 0.0.0.0:0 */ + static const IPv4Endpoint Any; + +}; + + + + + +#endif // LOSEMYMIND_IPV4ENDPOINT_H diff --git a/VIServer/Classes/Networking/Socket.cpp b/VIServer/Classes/Networking/Socket.cpp new file mode 100644 index 0000000000..5d54caf7f8 --- /dev/null +++ b/VIServer/Classes/Networking/Socket.cpp @@ -0,0 +1,47 @@ + +#include "Socket.h" +#include "FoundationKit/Foundation/Logger.h" + +// +// Socket stats implementation +// + +bool Socket::SendTo(const uint8* data, int32 count, int32& bytesSent, const InternetAddrBSD& destination) +{ + LOG_INFO("***** Socket '%s' SendTo %i Bytes", _SocketDescription.c_str(), bytesSent); + return true; +} + + +bool Socket::Send(const uint8* data, int32 count, int32& bytesSent) +{ + LOG_INFO("***** Socket '%s' Send %i Bytes", _SocketDescription.c_str(), bytesSent); + return true; +} + + +bool Socket::RecvFrom(uint8* data, int32 bufferSize, int32& bytesRead, InternetAddrBSD& source, ESocketReceiveFlags flags) +{ + if (bytesRead > 0) + { + LOG_INFO("***** Socket '%s' RecvFrom %i Bytes", _SocketDescription.c_str(), bytesRead); + } + return true; +} + + +bool Socket::Recv(uint8* data, int32 bufferSize, int32& bytesRead, ESocketReceiveFlags flags) +{ + if (bytesRead > 0) + { + LOG_INFO("***** Socket '%s' Recv %i Bytes", _SocketDescription.c_str(), bytesRead); + } + return true; +} + + + + + + + diff --git a/VIServer/Classes/Networking/Socket.h b/VIServer/Classes/Networking/Socket.h new file mode 100644 index 0000000000..6727ab0cec --- /dev/null +++ b/VIServer/Classes/Networking/Socket.h @@ -0,0 +1,429 @@ +#ifndef LOSEMYMIND_SOCKET_H +#define LOSEMYMIND_SOCKET_H + +#pragma once + +#include +#include "FoundationKit/Base/Types.h" +#include "FoundationKit/Base/Timespan.h" +#include "IPAddressBSD.h" +#include "winsock_init.hpp" + +USING_NS_FK; + +/** Indicates the type of socket being used (streaming or datagram) */ +enum class ESocketType +{ + /** Not bound to a protocol yet */ + Unknown, + /** A UDP type socket */ + Datagram, + /** A TCP type socket */ + Streaming +}; + +/** Indicates the connection state of the socket */ +enum class ESocketConnectionState +{ + NotConnected, + Connected, + /** Indicates that the end point refused the connection or couldn't be reached */ + ConnectionError +}; + +/** + * Enumerates socket wait conditions. + */ +enum class ESocketWaitConditions +{ + /** + * Wait until data is available for reading. + */ + WaitForRead, + + /** + * Wait until data can be written. + */ + WaitForWrite, + + /** + * Wait until data is available for reading or can be written. + */ + WaitForReadOrWrite +}; + + + +/** + * Enumerates socket receive flags. + */ +enum ESocketReceiveFlags +{ + /** + * Return as much data as is currently available in the input queue, + * up to the specified size of the receive buffer. + */ + None = 0, + + /** + * Copy received data into the buffer without removing it from the input queue. + */ + Peek = 2, + + /** + * Block the receive call until either the supplied buffer is full, the connection + * has been closed, the request has been canceled, or an error occurred. + */ + WaitAll = 0x100 +}; + +inline int TranslateFlags(ESocketReceiveFlags flags) +{ + int TranslatedFlags = 0; + + if (flags & ESocketReceiveFlags::Peek) + { + TranslatedFlags |= MSG_PEEK; + } + + if (flags & ESocketReceiveFlags::WaitAll) + { + TranslatedFlags |= MSG_WAITALL; + } + + return TranslatedFlags; +} + + +/** + * This is our abstract base class that hides the platform specific socket implementation + */ +class Socket +{ +protected: + /** Indicates the type of socket this is */ + const ESocketType _SocketType; + + /** Debug description of socket usage. */ + std::string _SocketDescription; + +public: + + /** Default ctor */ + inline Socket() + : _SocketType(ESocketType::Unknown) + , _SocketDescription("") + { + } + + /** + * Specifies the type of socket being created + * + * @param InSocketType the type of socket being created + * @param InSocketDescription the debug description of the socket + */ + inline Socket(ESocketType socketType, const std::string& socketDescription) : + _SocketType(socketType), + _SocketDescription(socketDescription) + { + } + + /** + * Virtual destructor + */ + virtual ~Socket() + { + } + + /** + * Closes the socket + * + * @return true if it closes without errors, false otherwise + */ + virtual bool Close() = 0; + + /** + * Binds a socket to a network byte ordered address + * + * @param Addr the address to bind to + * + * @return true if successful, false otherwise + */ + virtual bool Bind(const InternetAddrBSD& addr) = 0; + + /** + * Connects a socket to a network byte ordered address + * + * @param Addr the address to connect to + * + * @return true if successful, false otherwise + */ + virtual bool Connect(const InternetAddrBSD& addr) = 0; + + /** + * Places the socket into a state to listen for incoming connections + * + * @param MaxBacklog the number of connections to queue before refusing them + * + * @return true if successful, false otherwise + */ + virtual bool Listen(int32 maxBacklog) = 0; + + /** + * Queries the socket to determine if there is a pending connection + * + * @param bHasPendingConnection out parameter indicating whether a connection is pending or not + * + * @return true if successful, false otherwise + */ + virtual bool HasPendingConnection(bool& bHasPendingConnection) = 0; + + /** + * Queries the socket to determine if there is pending data on the queue + * + * @param PendingDataSize out parameter indicating how much data is on the pipe for a single recv call + * + * @return true if the socket has data, false otherwise + */ + virtual bool HasPendingData(uint32& pendingDataSize) = 0; + + /** + * Accepts a connection that is pending + * + * @param SocketDescription debug description of socket + * @return The new (heap-allocated) socket, or NULL if unsuccessful. + */ + virtual class Socket* Accept(const std::string& socketDescription) = 0; + + /** + * Accepts a connection that is pending + * + * @param OutAddr the address of the connection + * @param SocketDescription debug description of socket + * + * @return The new (heap-allocated) socket, or NULL if unsuccessful. + */ + virtual class Socket* Accept(InternetAddrBSD& outAddr, const std::string& socketDescription) = 0; + + /** + * Sends a buffer to a network byte ordered address + * + * @param Data the buffer to send + * @param Count the size of the data to send + * @param BytesSent out param indicating how much was sent + * @param Destination the network byte ordered address to send to + */ + virtual bool SendTo(const uint8* data, int32 count, int32& bytesSent, const InternetAddrBSD& destination); + + /** + * Sends a buffer on a connected socket + * + * @param Data the buffer to send + * @param Count the size of the data to send + * @param BytesSent out param indicating how much was sent + */ + virtual bool Send(const uint8* data, int32 count, int32& bytesSent); + + /** + * Reads a chunk of data from the socket. Gathers the source address too + * + * @param Data the buffer to read into + * @param BufferSize the max size of the buffer + * @param BytesRead out param indicating how many bytes were read from the socket + * @param Source out param receiving the address of the sender of the data + * @param Flags the receive flags + */ + virtual bool RecvFrom(uint8* data, int32 bufferSize, int32& bytesRead, InternetAddrBSD& source, ESocketReceiveFlags flags = ESocketReceiveFlags::None); + + /** + * Reads a chunk of data from a connected socket + * + * @param Data the buffer to read into + * @param BufferSize the max size of the buffer + * @param BytesRead out param indicating how many bytes were read from the socket + * @param Flags the receive flags + */ + virtual bool Recv(uint8* Data, int32 BufferSize, int32& BytesRead, ESocketReceiveFlags flags = ESocketReceiveFlags::None); + + /** + * Blocks until the specified condition is met. + * + * @param Condition - The condition to wait for. + * @param WaitTime - The maximum time to wait. + * + * @return true if the condition was met, false if the time limit expired or an error occurred. + */ + virtual bool Wait(ESocketWaitConditions Condition, Timespan waitTime) = 0; + + /** + * Determines the connection state of the socket + */ + virtual ESocketConnectionState GetConnectionState() = 0; + + /** + * Reads the address the socket is bound to and returns it + * + * @param OutAddr address the socket is bound to + */ + virtual void GetAddress(InternetAddrBSD& outAddr) = 0; + + /** + * Reads the address of the peer the socket is connected to + * + * @param OutAddr address of the peer the socket is connected to + * @return return true if the address was retrieved correctly + */ + virtual bool GetPeerAddress(InternetAddrBSD& outAddr) = 0; + + /** + * Sets this socket into non-blocking mode + * + * @param bIsNonBlocking whether to enable blocking or not + * + * @return true if successful, false otherwise + */ + virtual bool SetNonBlocking(bool bIsNonBlocking = true) = 0; + + /** + * Sets a socket into broadcast mode (UDP only) + * + * @param bAllowBroadcast whether to enable broadcast or not + * + * @return true if successful, false otherwise + */ + virtual bool SetBroadcast(bool bAllowBroadcast = true) = 0; + + /** + * Joins this socket to the specified multicast group. + * + * The multicast group address must be in the range 224.0.0.0 to 239.255.255.255. + * + * @param GroupAddress - The IP address of the multicast group. + * + * @return true on success, false otherwise. + * + * @see LeaveMulticastGroup + * @see SetMulticastLoopback + * @see SetMulticastTtl + */ + virtual bool JoinMulticastGroup(const InternetAddrBSD& groupAddress) = 0; + + /** + * Removes this UDP client from the specified multicast group. + * + * @param The multicast group address to leave. + * + * @return true on success, false otherwise. + * + * @see JoinMulticastGroup + * @see SetMulticastLoopback + * @see SetMulticastTtl + */ + virtual bool LeaveMulticastGroup(const InternetAddrBSD& groupAddress) = 0; + + /** + * Enables or disables multicast loopback on the socket (UDP only). + * + * This setting determines whether multicast datagrams are looped + * back to the sending socket. By default, multicast loopback is + * enabled. It must be enabled if more than one listener is present + * on a host. + * + * @param bLoopback - Whether loopback should be enabled. + * + * @see LeaveMulticastGroup + * @see JoinMulticastGroup + * @see SetMulticastTtl + */ + virtual bool SetMulticastLoopback (bool bLoopback) = 0; + + /** + * Sets the time to live (TTL) for multicast datagrams. + * + * The default TTL for multicast datagrams is 1, which prevents them + * from being forwarded beyond the local subnet. Higher values will + * allow multicast datagrams to be sent into neighboring subnets, if + * multicast capable routers are present. + * + * @param TimeToLive - Number of hops the datagram can make. + * + * @see LeaveMulticastGroup + * @see JoinMulticastGroup + * @see SetMulticastLoopback + */ + virtual bool SetMulticastTtl (uint8 TimeToLive) = 0; + + /** + * Sets whether a socket can be bound to an address in use + * + * @param bAllowReuse whether to allow reuse or not + * + * @return true if the call succeeded, false otherwise + */ + virtual bool SetReuseAddr(bool bAllowReuse = true) = 0; + + /** + * Sets whether and how long a socket will linger after closing + * + * @param bShouldLinger whether to have the socket remain open for a time period after closing or not + * @param Timeout the amount of time to linger before closing + * + * @return true if the call succeeded, false otherwise + */ + virtual bool SetLinger(bool bShouldLinger = true, int32 Timeout = 0) = 0; + + /** + * Enables error queue support for the socket + * + * @param bUseErrorQueue whether to enable error queuing or not + * + * @return true if the call succeeded, false otherwise + */ + virtual bool SetRecvErr(bool bUseErrorQueue = true) = 0; + + /** + * Sets the size of the send buffer to use + * + * @param Size the size to change it to + * @param NewSize the out value returning the size that was set (in case OS can't set that) + * + * @return true if the call succeeded, false otherwise + */ + virtual bool SetSendBufferSize(int32 Size, int32& NewSize) = 0; + + /** + * Sets the size of the receive buffer to use + * + * @param Size the size to change it to + * @param NewSize the out value returning the size that was set (in case OS can't set that) + * + * @return true if the call succeeded, false otherwise + */ + virtual bool SetReceiveBufferSize(int32 Size, int32& NewSize) = 0; + + /** + * Reads the port this socket is bound to. + */ + virtual int32 GetPortNo() = 0; + + /** + * @return The type of protocol the socket is bound to + */ + FORCEINLINE ESocketType GetSocketType() const + { + return _SocketType; + } + + /** + * @return The debug description of the socket + */ + FORCEINLINE std::string GetDescription() const + { + return _SocketDescription; + } +}; + + + + +#endif // LOSEMYMIND_SOCKET_H diff --git a/VIServer/Classes/Networking/SocketBSD.cpp b/VIServer/Classes/Networking/SocketBSD.cpp new file mode 100644 index 0000000000..e03d247f4e --- /dev/null +++ b/VIServer/Classes/Networking/SocketBSD.cpp @@ -0,0 +1,436 @@ + +#include "SocketBSD.h" +#include "FoundationKit/Foundation/Logger.h" + +USING_NS_FK; + +#if ((TARGET_PLATFORM == PLATFORM_ANDROID) ||(TARGET_PLATFORM == PLATFORM_LINUX)) + +#define PLATFORM_HAS_BSD_SOCKET_FEATURE_IOCTL 1 +# include + +#endif + +#if TARGET_PLATFORM == PLATFORM_WIN32 +#define PLATFORM_HAS_BSD_SOCKET_FEATURE_WINSOCKETS 1 +#endif + + +/* FSocket overrides + *****************************************************************************/ + +bool SocketBSD::Close(void) +{ + if (_Socket != INVALID_SOCKET) + { + int32 error = closesocket(_Socket); + _Socket = INVALID_SOCKET; + return error == 0; + } + return false; +} + + +bool SocketBSD::Bind(const InternetAddrBSD& addr) +{ + return bind(_Socket, (sockaddr*)(InternetAddrBSD&)addr, sizeof(sockaddr_in)) == 0; +} + + +bool SocketBSD::Connect(const InternetAddrBSD& addr) +{ + int32 Return = connect(_Socket, (sockaddr*)(InternetAddrBSD&)addr, sizeof(sockaddr_in)); + + // "would block" is not an error + return ((Return == 0) || (Return == EWOULDBLOCK)); +} + + +bool SocketBSD::Listen(int32 maxBacklog) +{ + return listen(_Socket, maxBacklog) == 0; +} + + +bool SocketBSD::HasPendingConnection(bool& bHasPendingConnection) +{ + bool bHasSucceeded = false; + bHasPendingConnection = false; + + // make sure socket has no error state + if (HasState(ESocketBSDParam::HasError) == ESocketBSDReturn::No) + { + // get the read state + ESocketBSDReturn State = HasState(ESocketBSDParam::CanRead); + + // turn the result into the outputs + bHasSucceeded = State != ESocketBSDReturn::EncounteredError; + bHasPendingConnection = State == ESocketBSDReturn::Yes; + } + + return bHasSucceeded; +} + + +bool SocketBSD::HasPendingData(uint32& pendingDataSize) +{ + pendingDataSize = 0; + + // make sure socket has no error state + if (HasState(ESocketBSDParam::CanRead) == ESocketBSDReturn::Yes) + { +#if TARGET_PLATFORM == PLATFORM_WIN32 + // See if there is any pending data on the read socket + if (ioctlsocket(_Socket, FIONREAD, (u_long*)(&pendingDataSize)) == 0) +#else + if (ioctl(_Socket, FIONREAD, (u_long*)(&pendingDataSize)) == 0) +#endif + { + return (pendingDataSize > 0); + } + } + + return false; +} + + +Socket* SocketBSD::Accept(const std::string& socketDescription) +{ + SOCKET newSocket = accept(_Socket, NULL, NULL); + + if (newSocket != INVALID_SOCKET) + { + return new SocketBSD(newSocket, _SocketType, socketDescription); + } + + return NULL; +} + + +Socket* SocketBSD::Accept(InternetAddrBSD& outAddr, const std::string& socketDescription) +{ + int32 aockaddrLen = sizeof(sockaddr_in); + SOCKET newSocket = accept(_Socket, *(InternetAddrBSD*)(&outAddr), &aockaddrLen); + + if (newSocket != INVALID_SOCKET) + { + return new SocketBSD(newSocket, _SocketType, socketDescription); + } + + return NULL; +} + + +bool SocketBSD::SendTo(const uint8* data, int32 count, int32& bytesSent, const InternetAddrBSD& destination) +{ + // Write the data and see how much was written + bytesSent = sendto(_Socket, (const char*)data, count, 0, (InternetAddrBSD&)destination, sizeof(sockaddr_in)); + + bool Result = bytesSent >= 0; + if (Result) + { + _LastActivityTime = DateTime::utcNow(); + } + return Result; +} + + +bool SocketBSD::Send(const uint8* data, int32 count, int32& bytesSent) +{ + bytesSent = send(_Socket, (const char*)data, count, 0); + + bool Result = bytesSent >= 0; + if (Result) + { + _LastActivityTime = DateTime::utcNow(); + } + return Result; +} + + +bool SocketBSD::RecvFrom(uint8* data, int32 bufferSize, int32& bytesRead, InternetAddrBSD& source, ESocketReceiveFlags flags) +{ + int32 aockaddrLen = sizeof(sockaddr_in); + sockaddr& Addr = *(InternetAddrBSD&)source; + + const int TranslatedFlags = TranslateFlags(flags); + + // Read into the buffer and set the source address + bytesRead = recvfrom(_Socket, (char*)data, bufferSize, TranslatedFlags, &Addr, &aockaddrLen); + + if (bytesRead < 0) + { + bytesRead = 0; + return false; + } + _LastActivityTime = DateTime::utcNow(); + return true; +} + + +bool SocketBSD::Recv(uint8* data, int32 bufferSize, int32& bytesRead, ESocketReceiveFlags flags) +{ + const int TranslatedFlags = TranslateFlags(flags); + bytesRead = recv(_Socket, (char*)data, bufferSize, TranslatedFlags); + + bool Result = bytesRead >= 0; + if (Result) + { + _LastActivityTime = DateTime::utcNow(); + } + return Result; +} + + +bool SocketBSD::Wait(ESocketWaitConditions condition, Timespan waitTime) +{ + if ((condition == ESocketWaitConditions::WaitForRead) || (condition == ESocketWaitConditions::WaitForReadOrWrite)) + { + if (HasState(ESocketBSDParam::CanRead, waitTime) == ESocketBSDReturn::Yes) + { + return true; + } + } + + if ((condition == ESocketWaitConditions::WaitForWrite) || (condition == ESocketWaitConditions::WaitForReadOrWrite)) + { + if (HasState(ESocketBSDParam::CanWrite, waitTime) == ESocketBSDReturn::Yes) + { + return true; + } + } + + return false; +} + + +ESocketConnectionState SocketBSD::GetConnectionState(void) +{ + ESocketConnectionState CurrentState = ESocketConnectionState::ConnectionError; + + // look for an existing error + if (HasState(ESocketBSDParam::HasError) == ESocketBSDReturn::No) + { + if (DateTime::utcNow() - _LastActivityTime > Timespan::fromSeconds(5)) + { + // get the write state + ESocketBSDReturn WriteState = HasState(ESocketBSDParam::CanWrite, Timespan::fromMilliseconds(1)); + ESocketBSDReturn ReadState = HasState(ESocketBSDParam::CanRead, Timespan::fromMilliseconds(1)); + + // translate yes or no (error is already set) + if (WriteState == ESocketBSDReturn::Yes || ReadState == ESocketBSDReturn::Yes) + { + CurrentState = ESocketConnectionState::Connected; + _LastActivityTime = DateTime::utcNow(); + } + else if (WriteState == ESocketBSDReturn::No && ReadState == ESocketBSDReturn::No) + { + CurrentState = ESocketConnectionState::NotConnected; + } + } + else + { + CurrentState = ESocketConnectionState::Connected; + } + } + + return CurrentState; +} + + +void SocketBSD::GetAddress(InternetAddrBSD& outAddr) +{ + InternetAddrBSD& addr = (InternetAddrBSD&)outAddr; + int32 aockaddrLen = sizeof(sockaddr_in); + + // Figure out what ip/port we are bound to + int Result = getsockname(_Socket, addr, &aockaddrLen); + + if (Result != 0) + { + LOG_ERROR("***** Failed to read address for socket with for error:%d", Result); + } +} + + +bool SocketBSD::GetPeerAddress(InternetAddrBSD& OutAddr) +{ + InternetAddrBSD& Addr = (InternetAddrBSD&)OutAddr; + int32 aockaddrLen = sizeof(sockaddr_in); + + // Figure out what ip/port we are bound to + int Result = getpeername(_Socket, Addr, &aockaddrLen); + + if (Result != 0) + { + LOG_ERROR("***** Failed to read address for socket with for error:%d", Result); + } + return Result == 0; +} + +bool SocketBSD::SetNonBlocking(bool bIsNonBlocking) +{ + u_long Value = bIsNonBlocking ? true : false; + +#if PLATFORM_HAS_BSD_SOCKET_FEATURE_WINSOCKETS + return ioctlsocket(_Socket,FIONBIO,&Value) == 0; +#else + int Flags = fcntl(Socket, F_GETFL, 0); + //Set the flag or clear it, without destroying the other flags. + Flags = bIsNonBlocking ? Flags | O_NONBLOCK : Flags ^ (Flags & O_NONBLOCK); + int err = fcntl(Socket, F_SETFL, Flags); + return (err == 0 ? true : false); +#endif + +} + + +bool SocketBSD::SetBroadcast(bool bAllowBroadcast) +{ + int Param = bAllowBroadcast ? 1 : 0; + return setsockopt(_Socket,SOL_SOCKET,SO_BROADCAST,(char*)&Param,sizeof(Param)) == 0; +} + + +bool SocketBSD::JoinMulticastGroup(const InternetAddrBSD& groupAddress) +{ + ip_mreq imr; + + imr.imr_interface.s_addr = INADDR_ANY; + imr.imr_multiaddr = ((sockaddr_in*)&**((InternetAddrBSD*)(&groupAddress)))->sin_addr; + return (setsockopt(_Socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&imr, sizeof(imr)) == 0); +} + + +bool SocketBSD::LeaveMulticastGroup(const InternetAddrBSD& groupAddress) +{ + ip_mreq imr; + imr.imr_interface.s_addr = INADDR_ANY; + imr.imr_multiaddr = ((sockaddr_in*)&**((InternetAddrBSD*)(&groupAddress)))->sin_addr; + return (setsockopt(_Socket, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char*)&imr, sizeof(imr)) == 0); +} + + +bool SocketBSD::SetMulticastLoopback(bool bLoopback) +{ + return (setsockopt(_Socket, IPPROTO_IP, IP_MULTICAST_LOOP, (char*)&bLoopback, sizeof(bLoopback)) == 0); +} + + +bool SocketBSD::SetMulticastTtl(uint8 timeToLive) +{ + return (setsockopt(_Socket, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&timeToLive, sizeof(timeToLive)) == 0); +} + + +bool SocketBSD::SetReuseAddr(bool bAllowReuse) +{ + int Param = bAllowReuse ? 1 : 0; + return setsockopt(_Socket,SOL_SOCKET,SO_REUSEADDR,(char*)&Param,sizeof(Param)) == 0; +} + + +bool SocketBSD::SetLinger(bool bShouldLinger,int32 timeout) +{ + linger ling; + ling.l_onoff = bShouldLinger; + ling.l_linger = timeout; + return setsockopt(_Socket,SOL_SOCKET,SO_LINGER,(char*)&ling,sizeof(ling)) == 0; +} + + +bool SocketBSD::SetRecvErr(bool bUseErrorQueue) +{ + // Not supported, but return true to avoid spurious log messages + return true; +} + + +bool SocketBSD::SetSendBufferSize(int32 size,int32& newSize) +{ + int32 typeSize = sizeof(int32); + bool bOk = setsockopt(_Socket, SOL_SOCKET, SO_SNDBUF, (char*)&size, sizeof(int32)) == 0; + + // Read the value back in case the size was modified + getsockopt(_Socket, SOL_SOCKET, SO_SNDBUF, (char*)&newSize, &typeSize); + + return bOk; +} + + +bool SocketBSD::SetReceiveBufferSize(int32 Size,int32& NewSize) +{ + int32 typeSize = sizeof(int32); + bool bOk = setsockopt(_Socket,SOL_SOCKET,SO_RCVBUF,(char*)&Size,sizeof(int32)) == 0; + + // Read the value back in case the size was modified + getsockopt(_Socket, SOL_SOCKET, SO_RCVBUF, (char*)&NewSize, &typeSize); + + return bOk; +} + + +int32 SocketBSD::GetPortNo(void) +{ + sockaddr_in Addr; + + int32 sockaddrLen = sizeof(sockaddr_in); + + // Figure out what ip/port we are bound to + bool bOk = getsockname(_Socket, (sockaddr*)&Addr, &sockaddrLen) == 0; + + if (bOk == false) + { + LOG_ERROR("***** Failed to read address for socket "); + } + + // Read the port number + return ntohs(Addr.sin_port); +} + + +/* SocketBSD implementation +*****************************************************************************/ + +ESocketBSDReturn SocketBSD::HasState(ESocketBSDParam state, Timespan waitTime) +{ +//#if PLATFORM_HAS_BSD_SOCKET_FEATURE_SELECT + // convert WaitTime to a timeval + timeval Time; + Time.tv_sec = (int32)waitTime.getTotalSeconds(); + Time.tv_usec = waitTime.getMilliseconds() * 1000; + + fd_set SocketSet; + + // Set up the socket sets we are interested in (just this one) + FD_ZERO(&SocketSet); + FD_SET(_Socket, &SocketSet); + + // Check the status of the state + int32 SelectStatus = 0; + switch (state) + { + case ESocketBSDParam::CanRead: + SelectStatus = select(_Socket + 1, &SocketSet, NULL, NULL, &Time); + break; + + case ESocketBSDParam::CanWrite: + SelectStatus = select(_Socket + 1, NULL, &SocketSet, NULL, &Time); + break; + + case ESocketBSDParam::HasError: + SelectStatus = select(_Socket + 1, NULL, NULL, &SocketSet, &Time); + break; + } + + // if the select returns a positive number, the socket had the state, 0 means didn't have it, and negative is API error condition (not socket's error state) + return SelectStatus > 0 ? ESocketBSDReturn::Yes : + SelectStatus == 0 ? ESocketBSDReturn::No : + ESocketBSDReturn::EncounteredError; +//#else + //LOG_ERROR("***** This platform doesn't support select(), but SocketBSD::HasState was not overridden"); + //return ESocketBSDReturn::EncounteredError; +//#endif +} + + diff --git a/VIServer/Classes/Networking/SocketBSD.h b/VIServer/Classes/Networking/SocketBSD.h new file mode 100644 index 0000000000..6ca8c31809 --- /dev/null +++ b/VIServer/Classes/Networking/SocketBSD.h @@ -0,0 +1,129 @@ +#ifndef LOSEMYMIND_SOCKETBSD_H +#define LOSEMYMIND_SOCKETBSD_H + + +#pragma once + + +#include +#include "Socket.h" +#include "FoundationKit/Base/DateTime.h" + + +/** + * Enumerates BSD socket state parameters. + */ +enum class ESocketBSDParam +{ + CanRead, + CanWrite, + HasError, +}; + + +/** + * Enumerates BSD socket state return values. + */ +enum class ESocketBSDReturn +{ + Yes, + No, + EncounteredError, +}; + + +/** + * Implements a BSD network socket. + */ +class SocketBSD : public Socket +{ +public: + + /** + * Assigns a BSD socket to this object. + * + * @param InSocket the socket to assign to this object. + * @param InSocketType the type of socket that was created. + * @param InSocketDescription the debug description of the socket. + */ + SocketBSD(SOCKET inSocket, ESocketType inSocketType, const std::string& inSocketDescription) + : Socket(inSocketType, inSocketDescription) + , _Socket(inSocket) + { } + + /** + * Destructor. + * + * Closes the socket if it is still open + */ + virtual ~SocketBSD() + { + Close(); + } + +public: + + /** + * Gets the Socket for anyone who knows they have an SocketBSD. + * + * @return The native socket. + */ + SOCKET GetNativeSocket() + { + return _Socket; + } + +public: + + // Socket overrides + + virtual bool Close() override; + virtual bool Bind(const InternetAddrBSD& addr) override; + virtual bool Connect(const InternetAddrBSD& addr) override; + virtual bool Listen(int32 maxBacklog) override; + virtual bool HasPendingConnection(bool& bHasPendingConnection) override; + virtual bool HasPendingData(uint32& pendingDataSize) override; + virtual class Socket* Accept(const std::string& socketDescription) override; + virtual class Socket* Accept(InternetAddrBSD& outAddr, const std::string& socketDescription) override; + virtual bool SendTo(const uint8* data, int32 count, int32& bytesSent, const InternetAddrBSD& destination) override; + virtual bool Send(const uint8* data, int32 count, int32& bytesSent) override; + virtual bool RecvFrom(uint8* data, int32 bufferSize, int32& bytesRead, InternetAddrBSD& source, ESocketReceiveFlags flags = ESocketReceiveFlags::None) override; + virtual bool Recv(uint8* data, int32 bufferSize, int32& bytesRead, ESocketReceiveFlags flags = ESocketReceiveFlags::None) override; + virtual bool Wait(ESocketWaitConditions condition, Timespan waitTime) override; + virtual ESocketConnectionState GetConnectionState() override; + virtual void GetAddress(InternetAddrBSD& outAddr) override; + virtual bool GetPeerAddress(InternetAddrBSD& outAddr) override; + virtual bool SetNonBlocking(bool bIsNonBlocking = true) override; + virtual bool SetBroadcast(bool bAllowBroadcast = true) override; + virtual bool JoinMulticastGroup(const InternetAddrBSD& groupAddress) override; + virtual bool LeaveMulticastGroup(const InternetAddrBSD& groupAddress) override; + virtual bool SetMulticastLoopback(bool bLoopback) override; + virtual bool SetMulticastTtl(uint8 timeToLive) override; + virtual bool SetReuseAddr(bool bAllowReuse = true) override; + virtual bool SetLinger(bool bShouldLinger = true, int32 timeout = 0) override; + virtual bool SetRecvErr(bool bUseErrorQueue = true) override; + virtual bool SetSendBufferSize(int32 size,int32& newSize) override; + virtual bool SetReceiveBufferSize(int32 size,int32& newSize) override; + virtual int32 GetPortNo() override; + +protected: + + /** This is generally select(), but makes it easier for platforms without select to replace it. */ + virtual ESocketBSDReturn HasState(ESocketBSDParam State, Timespan WaitTime = Timespan(0)); + + /** Updates this socket's time of last activity. */ + void UpdateActivity() + { + _LastActivityTime = DateTime::utcNow(); + } + + /** Holds the BSD socket object. */ + SOCKET _Socket; + + /** Last activity time. */ + DateTime _LastActivityTime; + +}; + + +#endif // LOSEMYMIND_SOCKETBSD_H diff --git a/VIServer/Classes/Networking/StaticMember.cpp b/VIServer/Classes/Networking/StaticMember.cpp new file mode 100644 index 0000000000..8813e76cb6 --- /dev/null +++ b/VIServer/Classes/Networking/StaticMember.cpp @@ -0,0 +1,9 @@ + +#include "IPv4Address.h" +#include "IPv4Endpoint.h" + +const IPv4Address IPv4Address::Any(0, 0, 0, 0); +const IPv4Address IPv4Address::InternalLoopback(127, 0, 0, 1); +const IPv4Address IPv4Address::LanBroadcast(255, 255, 255, 255); + +const IPv4Endpoint IPv4Endpoint::Any(IPv4Address(0, 0, 0, 0), 0); diff --git a/VIServer/Classes/Networking/TcpListener.h b/VIServer/Classes/Networking/TcpListener.h new file mode 100644 index 0000000000..1cc1bd8558 --- /dev/null +++ b/VIServer/Classes/Networking/TcpListener.h @@ -0,0 +1,201 @@ +#ifndef LOSEMYMIND_TCPLISTENER_H +#define LOSEMYMIND_TCPLISTENER_H + + + +#pragma once +#include +#include +#include "FoundationKit/Base/Timespan.h" +#include "Socket.h" +#include "IPv4Address.h" +#include "IPv4Endpoint.h" +#include "TcpSocketBuilder.h" + +USING_NS_FK; + +typedef std::function OnTcpListenerConnectionAccepted; + + + +/** + * Implements a runnable that listens for incoming TCP connections. + */ +class TcpListener +{ +public: + + /** + * Creates and initializes a new instance from the specified IP endpoint. + * + * @param LocalEndpoint The local IP endpoint to listen on. + * @param SleepTime The time to sleep between checking for pending connections (default = 0 seconds). + */ + TcpListener(const IPv4Endpoint& LocalEndpoint, const Timespan& InSleepTime = Timespan::zero()) + : _DeleteSocket(true) + , _Endpoint(LocalEndpoint) + , _SleepTime(InSleepTime) + , _Socket(nullptr) + , _Stopping(false) + { + _Thread = std::thread(std::bind(&TcpListener::Run, this)); + } + + /** + * Creates and initializes a new instance from the specified socket. + * + * @param InSocket The socket to listen on. + * @param SleepTime The time to sleep between checking for pending connections (default = 0 seconds). + */ + TcpListener(Socket& InSocket, const Timespan& InSleepTime = Timespan::zero()) + : _DeleteSocket(false) + , _SleepTime(InSleepTime) + , _Socket(&InSocket) + , _Stopping(false) + { + std::shared_ptr LocalAddress = std::shared_ptr(new InternetAddrBSD); + _Socket->GetAddress(*LocalAddress); + _Endpoint = IPv4Endpoint(LocalAddress); + _Thread = std::thread(std::bind(&TcpListener::Run, this)); + } + + /** Destructor. */ + ~TcpListener() + { + Stop(); + _Thread.join(); + if (_DeleteSocket && (_Socket != nullptr)) + { + delete _Socket; + _Socket = nullptr; + } + } + +public: + + /** + * Gets the listener's local IP endpoint. + * + * @return IP endpoint. + */ + const IPv4Endpoint& GetLocalEndpoint() const + { + return _Endpoint; + } + + /** + * Gets the listener's network socket. + * + * @return Network socket. + */ + Socket* GetSocket() const + { + return _Socket; + } + + /** + * Checks whether the listener is listening for incoming connections. + * + * @return true if it is listening, false otherwise. + */ + bool IsActive() const + { + return ((_Socket != nullptr) && !_Stopping); + } + + virtual void Stop() + { + _Stopping = true; + } +public: + + /** + * Gets a delegate to be invoked when an incoming connection has been accepted. + * + * If this delegate is not bound, the listener will reject all incoming connections. + * To temporarily disable accepting connections, use the Enable() and Disable() methods. + * + * @return The delegate. + * @see Enable, Disable + */ + OnTcpListenerConnectionAccepted& OnConnectionAccepted() + { + return ConnectionAcceptedDelegate; + } + +public: + + + virtual uint32 Run() + { + if (_Socket == nullptr) + { + _Socket = TcpSocketBuilder("TcpListener server") + .AsReusable() + .BoundToEndpoint(_Endpoint) + .Listening(8); + + int32 NewSize = 0; + _Socket->SetReceiveBufferSize(2 * 1024 * 1024, NewSize); + } + + std::shared_ptr RemoteAddress = std::shared_ptr(new InternetAddrBSD); + + while (!_Stopping) + { + bool Pending; + + // handle incoming connections + if (_Socket->HasPendingConnection(Pending) && Pending) + { + Socket* ConnectionSocket = _Socket->Accept(*RemoteAddress, "TcpListener client"); + + if (ConnectionSocket != nullptr) + { + bool Accepted = false; + + if (ConnectionAcceptedDelegate) + { + Accepted = ConnectionAcceptedDelegate(ConnectionSocket, IPv4Endpoint(RemoteAddress)); + } + + if (!Accepted) + { + ConnectionSocket->Close(); + delete ConnectionSocket; + } + } + } + + std::this_thread::sleep_for(std::chrono::seconds(_SleepTime.getSeconds())); + } + + return 0; + } + +private: + + /** Holds a flag indicating whether the socket should be deleted in the destructor. */ + bool _DeleteSocket; + + /** Holds the server endpoint. */ + IPv4Endpoint _Endpoint; + + /** Holds the time to sleep between checking for pending connections. */ + Timespan _SleepTime; + + /** Holds the server socket. */ + Socket* _Socket; + + /** Holds a flag indicating that the thread is stopping. */ + bool _Stopping; + + /** Holds the thread object. */ + std::thread _Thread; + +private: + + /** Holds a delegate to be invoked when an incoming connection has been accepted. */ + OnTcpListenerConnectionAccepted ConnectionAcceptedDelegate; +}; +#endif // LOSEMYMIND_TCPLISTENER_H diff --git a/VIServer/Classes/Networking/TcpSocketBuilder.h b/VIServer/Classes/Networking/TcpSocketBuilder.h new file mode 100644 index 0000000000..82cb3d3740 --- /dev/null +++ b/VIServer/Classes/Networking/TcpSocketBuilder.h @@ -0,0 +1,302 @@ +#ifndef LOSEMYMIND_TCPSOCKETBUILDER_H +#define LOSEMYMIND_TCPSOCKETBUILDER_H + + +#pragma once +#include +#include "FoundationKit/Base/Types.h" +#include "FoundationKit/Foundation/Logger.h" +#include "IPv4Endpoint.h" +#include "SocketBSD.h" +USING_NS_FK; + +/** + * Implements a fluent builder for TCP sockets. + */ +class TcpSocketBuilder +{ +public: + + /** + * Creates and initializes a new instance. + * + * @param InDescription Debug description for the socket. + */ + TcpSocketBuilder(const std::string& InDescription) + : _Blocking(false) + , _Bound(false) + , _BoundEndpoint(IPv4Address::Any, 0) + , _Description(InDescription) + , _Linger(false) + , _LingerTimeout(0) + , _Listen(false) + , _ReceiveBufferSize(0) + , _Reusable(false) + , _SendBufferSize(0) + { } + +public: + + /** + * Sets socket operations to be blocking. + * + * @return This instance (for method chaining). + * @see AsNonBlocking, AsReusable + */ + TcpSocketBuilder AsBlocking() + { + _Blocking = true; + + return *this; + } + + /** + * Sets socket operations to be non-blocking. + * + * @return This instance (for method chaining). + * @see AsBlocking, AsReusable + */ + TcpSocketBuilder AsNonBlocking() + { + _Blocking = false; + + return *this; + } + + /** + * Makes the bound address reusable by other sockets. + * + * @return This instance (for method chaining). + * @see AsNonBlocking, AsNonBlocking + */ + TcpSocketBuilder AsReusable() + { + _Reusable = true; + + return *this; + } + + /** + * Sets the local address to bind the socket to. + * + * Unless specified in a subsequent call to BoundToPort(), a random + * port number will be assigned by the underlying provider. + * + * @param Address The IP address to bind the socket to. + * @return This instance (for method chaining). + * @see BoundToEndpoint, BoundToPort + */ + TcpSocketBuilder BoundToAddress(const IPv4Address& Address) + { + _BoundEndpoint = IPv4Endpoint(Address, _BoundEndpoint.Port); + _Bound = true; + + return *this; + } + + /** + * Sets the local endpoint to bind the socket to. + * + * @param Endpoint The IP endpoint to bind the socket to. + * @return This instance (for method chaining). + * @see BoundToAddress, BoundToPort + */ + TcpSocketBuilder BoundToEndpoint(const IPv4Endpoint& Endpoint) + { + _BoundEndpoint = Endpoint; + _Bound = true; + + return *this; + } + + /** + * Sets the local port to bind the socket to. + * + * Unless specified in a subsequent call to BoundToAddress(), the local + * address will be determined automatically by the underlying provider. + * + * @param Port The local port number to bind the socket to. + * @return This instance (for method chaining). + * @see BoundToAddress, BoundToEndpoint + */ + TcpSocketBuilder BoundToPort(int32 Port) + { + _BoundEndpoint = IPv4Endpoint(_BoundEndpoint.Address, Port); + _Bound = true; + + return *this; + } + + /** + * Sets how long the socket will linger after closing. + * + * @param Timeout The amount of time to linger before closing. + * @return This instance (for method chaining). + */ + TcpSocketBuilder Lingering(int32 Timeout) + { + _Linger = true; + _LingerTimeout = Timeout; + + return *this; + } + + /** + * Sets the socket into a listening state for incoming connections. + * + * @param MaxBacklog The number of connections to queue before refusing them. + * @return This instance (for method chaining). + */ + TcpSocketBuilder Listening(int32 MaxBacklog) + { + _Listen = true; + _ListenBacklog = MaxBacklog; + + return *this; + } + + /** + * Specifies the desired size of the receive buffer in bytes (0 = default). + * + * The socket creation will not fail if the desired size cannot be set or + * if the actual size is less than the desired size. + * + * @param SizeInBytes The size of the buffer. + * @return This instance (for method chaining). + * @see WithSendBufferSize + */ + TcpSocketBuilder WithReceiveBufferSize(int32 SizeInBytes) + { + _ReceiveBufferSize = SizeInBytes; + + return *this; + } + + /** + * Specifies the desired size of the send buffer in bytes (0 = default). + * + * The socket creation will not fail if the desired size cannot be set or + * if the actual size is less than the desired size. + * + * @param SizeInBytes The size of the buffer. + * @return This instance (for method chaining). + * @see WithReceiveBufferSize + */ + TcpSocketBuilder WithSendBufferSize(int32 SizeInBytes) + { + _SendBufferSize = SizeInBytes; + + return *this; + } + +public: + + /** + * Implicit conversion operator that builds the socket as configured. + * + * @return The built socket. + */ + operator Socket*() const + { + return Build(); + } + + /** + * Builds the socket as configured. + * + * @return The built socket. + */ + Socket* Build() const + { + + + SOCKET nativeSocket = INVALID_SOCKET; + // Creates a stream (TCP) socket + nativeSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + Socket* NewSocket = (nativeSocket != INVALID_SOCKET) ? new SocketBSD(nativeSocket, ESocketType::Streaming, _Description) : nullptr; + + if (NewSocket != nullptr) + { + ::SetHandleInformation((HANDLE)nativeSocket, HANDLE_FLAG_INHERIT, 0); + + bool Error = !NewSocket->SetReuseAddr(_Reusable) || + !NewSocket->SetLinger(_Linger, _LingerTimeout) || + !NewSocket->SetRecvErr(); + + if (!Error) + { + Error = _Bound && !NewSocket->Bind(*_BoundEndpoint.ToInternetAddr()); + } + + if (!Error) + { + Error = _Listen && !NewSocket->Listen(_ListenBacklog); + } + + if (!Error) + { + Error = !NewSocket->SetNonBlocking(!_Blocking); + } + + if (!Error) + { + int32 OutNewSize; + + if (_ReceiveBufferSize > 0) + { + NewSocket->SetReceiveBufferSize(_ReceiveBufferSize, OutNewSize); + } + + if (_SendBufferSize > 0) + { + NewSocket->SetSendBufferSize(_SendBufferSize, OutNewSize); + } + } + + if (Error) + { + LOG_ERROR("***** TcpSocketBuilder: Failed to create the socket %s as configured", _Description.c_str()); + SAFE_DELETE(NewSocket); + } + } + + + return NewSocket; + } + +private: + + /** Holds a flag indicating whether socket operations are blocking. */ + bool _Blocking; + + /** Holds a flag indicating whether the socket should be bound. */ + bool _Bound; + + /** Holds the IP address (and port) that the socket will be bound to. */ + IPv4Endpoint _BoundEndpoint; + + /** Holds the socket's debug description text. */ + std::string _Description; + + /** Holds a flag indicating whether the socket should linger after closing. */ + bool _Linger; + + /** Holds the amount of time the socket will linger before closing. */ + int32 _LingerTimeout; + + /** Holds a flag indicating whether the socket should listen for incoming connections. */ + bool _Listen; + + /** Holds the number of connections to queue up before refusing them. */ + int32 _ListenBacklog; + + /** The desired size of the receive buffer in bytes (0 = default). */ + int32 _ReceiveBufferSize; + + /** Holds a flag indicating whether the bound address can be reused by other sockets. */ + bool _Reusable; + + /** The desired size of the send buffer in bytes (0 = default). */ + int32 _SendBufferSize; +}; +#endif // LOSEMYMIND_TCPSOCKETBUILDER_H diff --git a/VIServer/Classes/Networking/config.hpp b/VIServer/Classes/Networking/config.hpp new file mode 100644 index 0000000000..c797490336 --- /dev/null +++ b/VIServer/Classes/Networking/config.hpp @@ -0,0 +1,666 @@ +// +// detail/config.hpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef STDNET_DETAIL_CONFIG_HPP +#define STDNET_DETAIL_CONFIG_HPP + +// Default to a header-only implementation. The user must specifically request +// separate compilation by defining either STDNET_SEPARATE_COMPILATION or +// STDNET_DYN_LINK (as a DLL/shared library implies separate compilation). +#if !defined(STDNET_HEADER_ONLY) +# if !defined(STDNET_SEPARATE_COMPILATION) +# if !defined(STDNET_DYN_LINK) +# define STDNET_HEADER_ONLY 1 +# endif // !defined(STDNET_DYN_LINK) +# endif // !defined(STDNET_SEPARATE_COMPILATION) +#endif // !defined(STDNET_HEADER_ONLY) + +#if defined(STDNET_HEADER_ONLY) +# define STDNET_DECL inline +#else // defined(STDNET_HEADER_ONLY) +# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CODEGEARC__) +// We need to import/export our code only if the user has specifically asked +// for it by defining STDNET_DYN_LINK. +# if defined(STDNET_DYN_LINK) +// Export if this is our own source, otherwise import. +# if defined(STDNET_SOURCE) +# define STDNET_DECL __declspec(dllexport) +# else // defined(STDNET_SOURCE) +# define STDNET_DECL __declspec(dllimport) +# endif // defined(STDNET_SOURCE) +# endif // defined(STDNET_DYN_LINK) +# endif // defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CODEGEARC__) +#endif // defined(STDNET_HEADER_ONLY) + +// If STDNET_DECL isn't defined yet define it now. +#if !defined(STDNET_DECL) +# define STDNET_DECL +#endif // !defined(STDNET_DECL) + +// Microsoft Visual C++ detection. +#if !defined(STDNET_MSVC) +# if defined(_MSC_VER) && !defined(__MWERKS__) && !defined(__EDG_VERSION__) +# define STDNET_MSVC _MSC_VER +# endif // defined(_MSC_VER) && !defined(__MWERKS__) && !defined(__EDG_VERSION__) +#endif // defined(STDNET_MSVC) + +// Support move construction and assignment on compilers known to allow it. +#if !defined(STDNET_HAS_MOVE) +# if !defined(STDNET_DISABLE_MOVE) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_HAS_MOVE 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# endif // !defined(STDNET_DISABLE_MOVE) +#endif // !defined(STDNET_HAS_MOVE) + +// If STDNET_MOVE_CAST isn't defined, and move support is available, define +// STDNET_MOVE_ARG and STDNET_MOVE_CAST to take advantage of rvalue +// references and perfect forwarding. +#if defined(STDNET_HAS_MOVE) && !defined(STDNET_MOVE_CAST) +# define STDNET_MOVE_ARG(type) type&& +# define STDNET_MOVE_CAST(type) static_cast +#endif // defined(STDNET_HAS_MOVE) && !defined(STDNET_MOVE_CAST) + +// If STDNET_MOVE_CAST still isn't defined, default to a C++03-compatible +// implementation. Note that older g++ and MSVC versions don't like it when you +// pass a non-member function through a const reference, so for most compilers +// we'll play it safe and stick with the old approach of passing the handler by +// value. +#if !defined(STDNET_MOVE_CAST) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1)) || (__GNUC__ > 4) +# define STDNET_MOVE_ARG(type) const type& +# else // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1)) || (__GNUC__ > 4) +# define STDNET_MOVE_ARG(type) type +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1)) || (__GNUC__ > 4) +# elif defined(STDNET_MSVC) +# if (_MSC_VER >= 1400) +# define STDNET_MOVE_ARG(type) const type& +# else // (_MSC_VER >= 1400) +# define STDNET_MOVE_ARG(type) type +# endif // (_MSC_VER >= 1400) +# else +# define STDNET_MOVE_ARG(type) type +# endif +# define STDNET_MOVE_CAST(type) static_cast +#endif // !defined_STDNET_MOVE_CAST + +// Support variadic templates on compilers known to allow it. +#if !defined(STDNET_HAS_VARIADIC_TEMPLATES) +# if !defined(STDNET_DISABLE_VARIADIC_TEMPLATES) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_HAS_VARIADIC_TEMPLATES 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(__clang__) +# if __has_feature(cxx_variadic_templates) +# define STDNET_HAS_VARIADIC_TEMPLATES 1 +# endif // __has_feature(cxx_noexcept) +# endif // defined(__clang__) +# endif // !defined(STDNET_DISABLE_VARIADIC_TEMPLATES) +#endif // !defined(STDNET_HAS_VARIADIC_TEMPLATES) + +// Support the noexcept specifier on compilers known to allow it. +#if !defined(STDNET_NOEXCEPT) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_NOEXCEPT noexcept +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(__clang__) +# if __has_feature(cxx_noexcept) +# define STDNET_NOEXCEPT noexcept +# endif // __has_feature(cxx_noexcept) +# endif // defined(__clang__) +# if !defined(STDNET_NOEXCEPT) +# define STDNET_NOEXCEPT +# endif // !defined(STDNET_NOEXCEPT) +#endif // !defined(STDNET_NOEXCEPT) + +// Support deleted functions on compilers known to allow it. +#if !defined(STDNET_DELETED) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_DELETED = delete +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(__clang__) +# if __has_feature(cxx_deleted_functions) +# define STDNET_DELETED = delete +# endif // __has_feature(cxx_noexcept) +# endif // defined(__clang__) +# if !defined(STDNET_DELETED) +# define STDNET_DELETED +# endif // !defined(STDNET_DELETED) +#endif // !defined(STDNET_DELETED) + +// Support relaxed constexpr on compilers known to allow it. +#if !defined(STDNET_CONSTEXPR) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_HAS_CONSTEXPR 1 +# define STDNET_CONSTEXPR constexpr +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(__clang__) +# if __has_feature(cxx_constexpr) +# define STDNET_HAS_CONSTEXPR 1 +# define STDNET_CONSTEXPR constexpr +# endif // __has_feature(cxx_constexpr) +# endif // defined(__clang__) +# if !defined(STDNET_CONSTEXPR) +# define STDNET_CONSTEXPR +# endif // !defined(STDNET_CONSTEXPR) +#endif // !defined(STDNET_CONSTEXPR) + +// Standard library support for system errors. +#if !defined(STDNET_HAS_STD_SYSTEM_ERROR) +# if !defined(STDNET_DISABLE_STD_SYSTEM_ERROR) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_HAS_STD_SYSTEM_ERROR 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# endif // !defined(STDNET_DISABLE_STD_SYSTEM_ERROR) +#endif // !defined(STDNET_HAS_STD_SYSTEM_ERROR) + +// Compliant C++11 compilers put noexcept specifiers on error_category members. +#if !defined(STDNET_ERROR_CATEGORY_NOEXCEPT) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_ERROR_CATEGORY_NOEXCEPT noexcept(true) +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(__clang__) +# if __has_feature(cxx_noexcept) +# define STDNET_ERROR_CATEGORY_NOEXCEPT noexcept(true) +# endif // __has_feature(cxx_noexcept) +# endif // defined(__clang__) +# if !defined(STDNET_ERROR_CATEGORY_NOEXCEPT) +# define STDNET_ERROR_CATEGORY_NOEXCEPT +# endif // !defined(STDNET_ERROR_CATEGORY_NOEXCEPT) +#endif // !defined(STDNET_ERROR_CATEGORY_NOEXCEPT) + +// Standard library support for arrays. +#if !defined(STDNET_HAS_STD_ARRAY) +# if !defined(STDNET_DISABLE_STD_ARRAY) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_HAS_STD_ARRAY 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(STDNET_MSVC) +# if (_MSC_VER >= 1600) +# define STDNET_HAS_STD_ARRAY 1 +# endif // (_MSC_VER >= 1600) +# endif // defined(STDNET_MSVC) +# endif // !defined(STDNET_DISABLE_STD_ARRAY) +#endif // !defined(STDNET_HAS_STD_ARRAY) + +// Standard library support for shared_ptr and weak_ptr. +#if !defined(STDNET_HAS_STD_SHARED_PTR) +# if !defined(STDNET_DISABLE_STD_SHARED_PTR) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_HAS_STD_SHARED_PTR 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(STDNET_MSVC) +# if (_MSC_VER >= 1600) +# define STDNET_HAS_STD_SHARED_PTR 1 +# endif // (_MSC_VER >= 1600) +# endif // defined(STDNET_MSVC) +# endif // !defined(STDNET_DISABLE_STD_SHARED_PTR) +#endif // !defined(STDNET_HAS_STD_SHARED_PTR) + +// Standard library support for atomic operations. +#if !defined(STDNET_HAS_STD_ATOMIC) +# if !defined(STDNET_DISABLE_STD_ATOMIC) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_HAS_STD_ATOMIC 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# endif // !defined(STDNET_DISABLE_STD_ATOMIC) +#endif // !defined(STDNET_HAS_STD_ATOMIC) + +// Standard library support for chrono. Some standard libraries (such as the +// libstdc++ shipped with gcc 4.6) provide monotonic_clock as per early C++0x +// drafts, rather than the eventually standardised name of steady_clock. +#if !defined(STDNET_HAS_STD_CHRONO) +# if !defined(STDNET_DISABLE_STD_CHRONO) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_HAS_STD_CHRONO 1 +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ == 6)) +# define STDNET_HAS_STD_CHRONO_MONOTONIC_CLOCK 1 +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ == 6)) +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# endif // !defined(STDNET_DISABLE_STD_CHRONO) +#endif // !defined(STDNET_HAS_STD_CHRONO) + +// Standard library support for addressof. +#if !defined(STDNET_HAS_STD_ADDRESSOF) +# if !defined(STDNET_DISABLE_STD_ADDRESSOF) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_HAS_STD_ADDRESSOF 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# endif // !defined(STDNET_DISABLE_STD_ADDRESSOF) +#endif // !defined(STDNET_HAS_STD_ADDRESSOF) + +// Standard library support for the function class. +#if !defined(STDNET_HAS_STD_FUNCTION) +# if !defined(STDNET_DISABLE_STD_FUNCTION) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_HAS_STD_FUNCTION 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# endif // !defined(STDNET_DISABLE_STD_FUNCTION) +#endif // !defined(STDNET_HAS_STD_FUNCTION) + +// Standard library support for type traits. +#if !defined(STDNET_HAS_STD_TYPE_TRAITS) +# if !defined(STDNET_DISABLE_STD_TYPE_TRAITS) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_HAS_STD_TYPE_TRAITS 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# endif // !defined(STDNET_DISABLE_STD_TYPE_TRAITS) +#endif // !defined(STDNET_HAS_STD_TYPE_TRAITS) + +// Standard library support for the cstdint header. +#if !defined(STDNET_HAS_CSTDINT) +# if !defined(STDNET_DISABLE_CSTDINT) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_HAS_CSTDINT 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# endif // !defined(STDNET_DISABLE_CSTDINT) +#endif // !defined(STDNET_HAS_CSTDINT) + +// Windows target. +#if !defined(STDNET_WINDOWS) +# if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +# define STDNET_WINDOWS 1 +# endif // defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +#endif // !defined(STDNET_WINDOWS) + +// Windows: target OS version. +#if defined(STDNET_WINDOWS) || defined(__CYGWIN__) +# if !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS) +# if defined(_MSC_VER) || defined(__BORLANDC__) +# pragma message( \ + "Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately. For example:\n"\ + "- add -D_WIN32_WINNT=0x0501 to the compiler command line; or\n"\ + "- add _WIN32_WINNT=0x0501 to your project's Preprocessor Definitions.\n"\ + "Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target).") +# else // defined(_MSC_VER) || defined(__BORLANDC__) +# warning Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately. +# warning For example, add -D_WIN32_WINNT=0x0501 to the compiler command line. +# warning Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target). +# endif // defined(_MSC_VER) || defined(__BORLANDC__) +# define _WIN32_WINNT 0x0501 +# endif // !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS) +# if defined(_MSC_VER) +# if defined(_WIN32) && !defined(WIN32) +# if !defined(_WINSOCK2API_) +# define WIN32 // Needed for correct types in winsock2.h +# else // !defined(_WINSOCK2API_) +# error Please define the macro WIN32 in your compiler options +# endif // !defined(_WINSOCK2API_) +# endif // defined(_WIN32) && !defined(WIN32) +# endif // defined(_MSC_VER) +# if defined(__BORLANDC__) +# if defined(__WIN32__) && !defined(WIN32) +# if !defined(_WINSOCK2API_) +# define WIN32 // Needed for correct types in winsock2.h +# else // !defined(_WINSOCK2API_) +# error Please define the macro WIN32 in your compiler options +# endif // !defined(_WINSOCK2API_) +# endif // defined(__WIN32__) && !defined(WIN32) +# endif // defined(__BORLANDC__) +# if defined(__CYGWIN__) +# if !defined(__USE_W32_SOCKETS) +# error You must add -D__USE_W32_SOCKETS to your compiler options. +# endif // !defined(__USE_W32_SOCKETS) +# endif // defined(__CYGWIN__) +#endif // defined(STDNET_WINDOWS) || defined(__CYGWIN__) + +// Windows: minimise header inclusion. +#if defined(STDNET_WINDOWS) || defined(__CYGWIN__) +# if !defined(STDNET_NO_WIN32_LEAN_AND_MEAN) +# if !defined(WIN32_LEAN_AND_MEAN) +# define WIN32_LEAN_AND_MEAN +# endif // !defined(WIN32_LEAN_AND_MEAN) +# endif // !defined(STDNET_NO_WIN32_LEAN_AND_MEAN) +#endif // defined(STDNET_WINDOWS) || defined(__CYGWIN__) + +// Windows: suppress definition of "min" and "max" macros. +#if defined(STDNET_WINDOWS) || defined(__CYGWIN__) +# if !defined(STDNET_NO_NOMINMAX) +# if !defined(NOMINMAX) +# define NOMINMAX 1 +# endif // !defined(NOMINMAX) +# endif // !defined(STDNET_NO_NOMINMAX) +#endif // defined(STDNET_WINDOWS) || defined(__CYGWIN__) + +// Windows: No ANSI API calls. +#if !defined(STDNET_NO_ANSI_APIS) +# if defined(STDNET_WINDOWS) && defined(UNDER_CE) +# define STDNET_NO_ANSI_APIS 1 +# endif // defined(STDNET_WINDOWS) && defined(UNDER_CE) +#endif // !defined(STDNET_NO_ANSI_APIS) + +// Windows: IO Completion Ports. +#if !defined(STDNET_HAS_IOCP) +# if defined(STDNET_WINDOWS) || defined(__CYGWIN__) +# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400) +# if !defined(UNDER_CE) +# if !defined(STDNET_DISABLE_IOCP) +# define STDNET_HAS_IOCP 1 +# endif // !defined(STDNET_DISABLE_IOCP) +# endif // !defined(UNDER_CE) +# endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400) +# endif // defined(STDNET_WINDOWS) || defined(__CYGWIN__) +#endif // !defined(STDNET_HAS_IOCP) + +// Linux: epoll, eventfd and timerfd. +#if defined(__linux__) +# include +# if !defined(STDNET_HAS_EPOLL) +# if !defined(STDNET_DISABLE_EPOLL) +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,45) +# define STDNET_HAS_EPOLL 1 +# endif // LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,45) +# endif // !defined(STDNET_DISABLE_EPOLL) +# endif // !defined(STDNET_HAS_EPOLL) +# if !defined(STDNET_HAS_EVENTFD) +# if !defined(STDNET_DISABLE_EVENTFD) +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) +# define STDNET_HAS_EVENTFD 1 +# endif // LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) +# endif // !defined(STDNET_DISABLE_EVENTFD) +# endif // !defined(STDNET_HAS_EVENTFD) +# if !defined(STDNET_HAS_TIMERFD) +# if defined(STDNET_HAS_EPOLL) +# if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8) +# define STDNET_HAS_TIMERFD 1 +# endif // (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8) +# endif // defined(STDNET_HAS_EPOLL) +# endif // !defined(STDNET_HAS_TIMERFD) +#endif // defined(__linux__) + +// Mac OS X, FreeBSD, NetBSD, OpenBSD: kqueue. +#if (defined(__MACH__) && defined(__APPLE__)) \ + || defined(__FreeBSD__) \ + || defined(__NetBSD__) \ + || defined(__OpenBSD__) +# if !defined(STDNET_HAS_KQUEUE) +# if !defined(STDNET_DISABLE_KQUEUE) +# define STDNET_HAS_KQUEUE 1 +# endif // !defined(STDNET_DISABLE_KQUEUE) +# endif // !defined(STDNET_HAS_KQUEUE) +#endif // (defined(__MACH__) && defined(__APPLE__)) + // || defined(__FreeBSD__) + // || defined(__NetBSD__) + // || defined(__OpenBSD__) + +// Solaris: /dev/poll. +#if defined(__sun) +# if !defined(STDNET_HAS_DEV_POLL) +# if !defined(STDNET_DISABLE_DEV_POLL) +# define STDNET_HAS_DEV_POLL 1 +# endif // !defined(STDNET_DISABLE_DEV_POLL) +# endif // !defined(STDNET_HAS_DEV_POLL) +#endif // defined(__sun) + +// Serial ports. +#if !defined(STDNET_HAS_SERIAL_PORT) +# if defined(STDNET_HAS_IOCP) \ + || !defined(STDNET_WINDOWS) && !defined(__CYGWIN__) +# if !defined(__SYMBIAN32__) +# if !defined(STDNET_DISABLE_SERIAL_PORT) +# define STDNET_HAS_SERIAL_PORT 1 +# endif // !defined(STDNET_DISABLE_SERIAL_PORT) +# endif // !defined(__SYMBIAN32__) +# endif // defined(STDNET_HAS_IOCP) + // || !defined(STDNET_WINDOWS) && !defined(__CYGWIN__) +#endif // !defined(STDNET_HAS_SERIAL_PORT) + +// Windows: stream handles. +#if !defined(STDNET_HAS_WINDOWS_STREAM_HANDLE) +# if !defined(STDNET_DISABLE_WINDOWS_STREAM_HANDLE) +# if defined(STDNET_HAS_IOCP) +# define STDNET_HAS_WINDOWS_STREAM_HANDLE 1 +# endif // defined(STDNET_HAS_IOCP) +# endif // !defined(STDNET_DISABLE_WINDOWS_STREAM_HANDLE) +#endif // !defined(STDNET_HAS_WINDOWS_STREAM_HANDLE) + +// Windows: random access handles. +#if !defined(STDNET_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) +# if !defined(STDNET_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE) +# if defined(STDNET_HAS_IOCP) +# define STDNET_HAS_WINDOWS_RANDOM_ACCESS_HANDLE 1 +# endif // defined(STDNET_HAS_IOCP) +# endif // !defined(STDNET_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE) +#endif // !defined(STDNET_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) + +// Windows: object handles. +#if !defined(STDNET_HAS_WINDOWS_OBJECT_HANDLE) +# if !defined(STDNET_DISABLE_WINDOWS_OBJECT_HANDLE) +# if defined(STDNET_WINDOWS) || defined(__CYGWIN__) +# if !defined(UNDER_CE) +# define STDNET_HAS_WINDOWS_OBJECT_HANDLE 1 +# endif // !defined(UNDER_CE) +# endif // defined(STDNET_WINDOWS) || defined(__CYGWIN__) +# endif // !defined(STDNET_DISABLE_WINDOWS_OBJECT_HANDLE) +#endif // !defined(STDNET_HAS_WINDOWS_OBJECT_HANDLE) + +// Windows: OVERLAPPED wrapper. +#if !defined(STDNET_HAS_WINDOWS_OVERLAPPED_PTR) +# if !defined(STDNET_DISABLE_WINDOWS_OVERLAPPED_PTR) +# if defined(STDNET_HAS_IOCP) +# define STDNET_HAS_WINDOWS_OVERLAPPED_PTR 1 +# endif // defined(STDNET_HAS_IOCP) +# endif // !defined(STDNET_DISABLE_WINDOWS_OVERLAPPED_PTR) +#endif // !defined(STDNET_HAS_WINDOWS_OVERLAPPED_PTR) + +// POSIX: stream-oriented file descriptors. +#if !defined(STDNET_HAS_POSIX_STREAM_DESCRIPTOR) +# if !defined(STDNET_DISABLE_POSIX_STREAM_DESCRIPTOR) +# if !defined(STDNET_WINDOWS) && !defined(__CYGWIN__) +# define STDNET_HAS_POSIX_STREAM_DESCRIPTOR 1 +# endif // !defined(STDNET_WINDOWS) && !defined(__CYGWIN__) +# endif // !defined(STDNET_DISABLE_POSIX_STREAM_DESCRIPTOR) +#endif // !defined(STDNET_HAS_POSIX_STREAM_DESCRIPTOR) + +// UNIX domain sockets. +#if !defined(STDNET_HAS_LOCAL_SOCKETS) +# if !defined(STDNET_DISABLE_LOCAL_SOCKETS) +# if !defined(STDNET_WINDOWS) && !defined(__CYGWIN__) +# define STDNET_HAS_LOCAL_SOCKETS 1 +# endif // !defined(STDNET_WINDOWS) && !defined(__CYGWIN__) +# endif // !defined(STDNET_DISABLE_LOCAL_SOCKETS) +#endif // !defined(STDNET_HAS_LOCAL_SOCKETS) + +// Can use sigaction() instead of signal(). +#if !defined(STDNET_HAS_SIGACTION) +# if !defined(STDNET_DISABLE_SIGACTION) +# if !defined(STDNET_WINDOWS) && !defined(__CYGWIN__) +# define STDNET_HAS_SIGACTION 1 +# endif // !defined(STDNET_WINDOWS) && !defined(__CYGWIN__) +# endif // !defined(STDNET_DISABLE_SIGACTION) +#endif // !defined(STDNET_HAS_SIGACTION) + +// Can use signal(). +#if !defined(STDNET_HAS_SIGNAL) +# if !defined(STDNET_DISABLE_SIGNAL) +# if !defined(UNDER_CE) +# define STDNET_HAS_SIGNAL 1 +# endif // !defined(UNDER_CE) +# endif // !defined(STDNET_DISABLE_SIGNAL) +#endif // !defined(STDNET_HAS_SIGNAL) + +// Whether standard iostreams are disabled. +//#if !defined(STDNET_NO_IOSTREAM) +//# define STDNET_NO_IOSTREAM 1 +//#endif // !defined(STDNET_NO_IOSTREAM) + +// Whether exception handling is disabled. +//#if !defined(STDNET_NO_EXCEPTIONS) +//# define STDNET_NO_EXCEPTIONS 1 +//#endif // !defined(STDNET_NO_EXCEPTIONS) + +// Whether the typeid operator is supported. +//#if !defined(STDNET_NO_TYPEID) +//# define STDNET_NO_TYPEID 1 +//#endif // !defined(STDNET_NO_TYPEID) + +// On POSIX (and POSIX-like) platforms we need to include unistd.h in order to +// get access to the various platform feature macros, e.g. to be able to test +// for threads support. +#if !defined(STDNET_HAS_UNISTD_H) +# if defined(unix) \ + || defined(__unix) \ + || defined(_XOPEN_SOURCE) \ + || defined(_POSIX_SOURCE) \ + || (defined(__MACH__) && defined(__APPLE__)) \ + || defined(__FreeBSD__) \ + || defined(__NetBSD__) \ + || defined(__OpenBSD__) \ + || defined(__linux__) +# define STDNET_HAS_UNISTD_H 1 +# endif +#endif // !defined(STDNET_HAS_UNISTD_H) +#if defined(STDNET_HAS_UNISTD_H) +# include +#endif // defined(STDNET_HAS_UNISTD_H) + +// Threads. +#if !defined(STDNET_HAS_THREADS) +# if !defined(STDNET_DISABLE_THREADS) +# if defined(_MSC_VER) && defined(_MT) +# define STDNET_HAS_THREADS 1 +# elif defined(__BORLANDC__) && defined(__MT__) +# define STDNET_HAS_THREADS 1 +# elif defined(_POSIX_THREADS) +# define STDNET_HAS_THREADS 1 +# endif // defined(_MSC_VER) && defined(_MT) +# endif // !defined(STDNET_DISABLE_THREADS) +#endif // !defined(STDNET_HAS_THREADS) + +// POSIX threads. +#if !defined(STDNET_HAS_PTHREADS) +# if defined(STDNET_HAS_THREADS) +# if defined(_POSIX_THREADS) +# define STDNET_HAS_PTHREADS 1 +# endif // defined(_POSIX_THREADS) +# endif // defined(STDNET_HAS_THREADS) +#endif // !defined(STDNET_HAS_PTHREADS) + +// Helper to prevent macro expansion. +#define STDNET_PREVENT_MACRO_SUBSTITUTION + +// Helper to define in-class constants. +#if !defined(STDNET_STATIC_CONSTANT) +# define STDNET_STATIC_CONSTANT(type, assignment) \ + static const type assignment +#endif // !defined(STDNET_STATIC_CONSTANT) + +// Microsoft Visual C++'s secure C runtime library. +#if !defined(STDNET_HAS_SECURE_RTL) +# if !defined(STDNET_DISABLE_SECURE_RTL) +# if defined(STDNET_MSVC) \ + && (STDNET_MSVC >= 1400) \ + && !defined(UNDER_CE) +# define STDNET_HAS_SECURE_RTL 1 +# endif // defined(STDNET_MSVC) + // && (STDNET_MSVC >= 1400) + // && !defined(UNDER_CE) +# endif // !defined(STDNET_DISABLE_SECURE_RTL) +#endif // !defined(STDNET_HAS_SECURE_RTL) + +// Handler hooking. Disabled for ancient Borland C++ and gcc compilers. +#if !defined(STDNET_HAS_HANDLER_HOOKS) +# if !defined(STDNET_DISABLE_HANDLER_HOOKS) +# if defined(__GNUC__) +# if (__GNUC__ >= 3) +# define STDNET_HAS_HANDLER_HOOKS 1 +# endif // (__GNUC__ >= 3) +# elif !defined(__BORLANDC__) +# define STDNET_HAS_HANDLER_HOOKS 1 +# endif // !defined(__BORLANDC__) +# endif // !defined(STDNET_DISABLE_HANDLER_HOOKS) +#endif // !defined(STDNET_HAS_HANDLER_HOOKS) + +// Support for the __thread keyword extension. +#if !defined(STDNET_DISABLE_THREAD_KEYWORD_EXTENSION) +# if defined(__linux__) +# if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) +# if ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3) +# if !defined(__INTEL_COMPILER) && !defined(__ICL) +# define STDNET_HAS_THREAD_KEYWORD_EXTENSION 1 +# elif defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1100) +# define STDNET_HAS_THREAD_KEYWORD_EXTENSION 1 +# endif // defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1100) +# endif // ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3) +# endif // defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) +# endif // defined(__linux__) +#endif // !defined(STDNET_DISABLE_THREAD_KEYWORD_EXTENSION) + +// Support for POSIX ssize_t typedef. +#if !defined(STDNET_DISABLE_SSIZE_T) +# if defined(__linux__) \ + || (defined(__MACH__) && defined(__APPLE__)) +# define STDNET_HAS_SSIZE_T 1 +# endif // defined(__linux__) + // || (defined(__MACH__) && defined(__APPLE__)) +#endif // !defined(STDNET_DISABLE_SSIZE_T) + +#endif // STDNET_DETAIL_CONFIG_HPP diff --git a/VIServer/Classes/Networking/old_win_sdk_compat.hpp b/VIServer/Classes/Networking/old_win_sdk_compat.hpp new file mode 100644 index 0000000000..c306dd7e53 --- /dev/null +++ b/VIServer/Classes/Networking/old_win_sdk_compat.hpp @@ -0,0 +1,218 @@ +// +// detail/old_win_sdk_compat.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef STDNET_DETAIL_OLD_WIN_SDK_COMPAT_HPP +#define STDNET_DETAIL_OLD_WIN_SDK_COMPAT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "config.hpp" + +#if defined(STDNET_WINDOWS) || defined(__CYGWIN__) + +// Guess whether we are building against on old Platform SDK. +#if !defined(IN6ADDR_ANY_INIT) +#define STDNET_HAS_OLD_WIN_SDK 1 +#endif // !defined(IN6ADDR_ANY_INIT) + +#if defined(STDNET_HAS_OLD_WIN_SDK) + +// Emulation of types that are missing from old Platform SDKs. +// +// N.B. this emulation is also used if building for a Windows 2000 target with +// a recent (i.e. Vista or later) SDK, as the SDK does not provide IPv6 support +// in that case. + +#include "push_options.hpp" + +namespace std { +namespace experimental { +namespace net { +namespace detail { + +enum +{ + sockaddr_storage_maxsize = 128, // Maximum size. + sockaddr_storage_alignsize = (sizeof(__int64)), // Desired alignment. + sockaddr_storage_pad1size = (sockaddr_storage_alignsize - sizeof(short)), + sockaddr_storage_pad2size = (sockaddr_storage_maxsize - + (sizeof(short) + sockaddr_storage_pad1size + sockaddr_storage_alignsize)) +}; + +struct sockaddr_storage_emulation +{ + short ss_family; + char __ss_pad1[sockaddr_storage_pad1size]; + __int64 __ss_align; + char __ss_pad2[sockaddr_storage_pad2size]; +}; + +struct in6_addr_emulation +{ + union + { + u_char Byte[16]; + u_short Word[8]; + } u; +}; + +#if !defined(s6_addr) +# define _S6_un u +# define _S6_u8 Byte +# define s6_addr _S6_un._S6_u8 +#endif // !defined(s6_addr) + +struct sockaddr_in6_emulation +{ + short sin6_family; + u_short sin6_port; + u_long sin6_flowinfo; + in6_addr_emulation sin6_addr; + u_long sin6_scope_id; +}; + +struct ipv6_mreq_emulation +{ + in6_addr_emulation ipv6mr_multiaddr; + unsigned int ipv6mr_interface; +}; + +struct addrinfo_emulation +{ + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + size_t ai_addrlen; + char* ai_canonname; + sockaddr* ai_addr; + addrinfo_emulation* ai_next; +}; + +#if !defined(AI_PASSIVE) +# define AI_PASSIVE 0x1 +#endif + +#if !defined(AI_CANONNAME) +# define AI_CANONNAME 0x2 +#endif + +#if !defined(AI_NUMERICHOST) +# define AI_NUMERICHOST 0x4 +#endif + +#if !defined(EAI_AGAIN) +# define EAI_AGAIN WSATRY_AGAIN +#endif + +#if !defined(EAI_BADFLAGS) +# define EAI_BADFLAGS WSAEINVAL +#endif + +#if !defined(EAI_FAIL) +# define EAI_FAIL WSANO_RECOVERY +#endif + +#if !defined(EAI_FAMILY) +# define EAI_FAMILY WSAEAFNOSUPPORT +#endif + +#if !defined(EAI_MEMORY) +# define EAI_MEMORY WSA_NOT_ENOUGH_MEMORY +#endif + +#if !defined(EAI_NODATA) +# define EAI_NODATA WSANO_DATA +#endif + +#if !defined(EAI_NONAME) +# define EAI_NONAME WSAHOST_NOT_FOUND +#endif + +#if !defined(EAI_SERVICE) +# define EAI_SERVICE WSATYPE_NOT_FOUND +#endif + +#if !defined(EAI_SOCKTYPE) +# define EAI_SOCKTYPE WSAESOCKTNOSUPPORT +#endif + +#if !defined(NI_NOFQDN) +# define NI_NOFQDN 0x01 +#endif + +#if !defined(NI_NUMERICHOST) +# define NI_NUMERICHOST 0x02 +#endif + +#if !defined(NI_NAMEREQD) +# define NI_NAMEREQD 0x04 +#endif + +#if !defined(NI_NUMERICSERV) +# define NI_NUMERICSERV 0x08 +#endif + +#if !defined(NI_DGRAM) +# define NI_DGRAM 0x10 +#endif + +#if !defined(IPPROTO_IPV6) +# define IPPROTO_IPV6 41 +#endif + +#if !defined(IPV6_UNICAST_HOPS) +# define IPV6_UNICAST_HOPS 4 +#endif + +#if !defined(IPV6_MULTICAST_IF) +# define IPV6_MULTICAST_IF 9 +#endif + +#if !defined(IPV6_MULTICAST_HOPS) +# define IPV6_MULTICAST_HOPS 10 +#endif + +#if !defined(IPV6_MULTICAST_LOOP) +# define IPV6_MULTICAST_LOOP 11 +#endif + +#if !defined(IPV6_JOIN_GROUP) +# define IPV6_JOIN_GROUP 12 +#endif + +#if !defined(IPV6_LEAVE_GROUP) +# define IPV6_LEAVE_GROUP 13 +#endif + +} // namespace detail +} // namespace net +} // namespace experimental +} // namespace std + +#include "pop_options.hpp" + +#endif // defined(STDNET_HAS_OLD_WIN_SDK) + +// Even newer Platform SDKs that support IPv6 may not define IPV6_V6ONLY. +#if !defined(IPV6_V6ONLY) +# define IPV6_V6ONLY 27 +#endif + +// Some SDKs (e.g. Windows CE) don't define IPPROTO_ICMPV6. +#if !defined(IPPROTO_ICMPV6) +# define IPPROTO_ICMPV6 58 +#endif + +#endif // defined(STDNET_WINDOWS) || defined(__CYGWIN__) + +#endif // STDNET_DETAIL_OLD_WIN_SDK_COMPAT_HPP diff --git a/VIServer/Classes/Networking/pop_options.hpp b/VIServer/Classes/Networking/pop_options.hpp new file mode 100644 index 0000000000..8aa375e96b --- /dev/null +++ b/VIServer/Classes/Networking/pop_options.hpp @@ -0,0 +1,98 @@ +// +// detail/pop_options.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +// No header guard + +#if defined(__COMO__) + +// Comeau C++ + +#elif defined(__DMC__) + +// Digital Mars C++ + +#elif defined(__INTEL_COMPILER) || defined(__ICL) \ + || defined(__ICC) || defined(__ECC) + +// Intel C++ + +#elif defined(__GNUC__) + +// GNU C++ + +# if defined(__MINGW32__) || defined(__CYGWIN__) +# pragma pack (pop) +# endif + +# if defined(__OBJC__) +# if !defined(__APPLE_CC__) || (__APPLE_CC__ <= 1) +# if defined(STDNET_OBJC_WORKAROUND) +# undef Protocol +# undef id +# undef STDNET_OBJC_WORKAROUND +# endif +# endif +# endif + +#elif defined(__KCC) + +// Kai C++ + +#elif defined(__sgi) + +// SGI MIPSpro C++ + +#elif defined(__DECCXX) + +// Compaq Tru64 Unix cxx + +#elif defined(__ghs) + +// Greenhills C++ + +#elif defined(__BORLANDC__) + +// Borland C++ + +# pragma option pop +# pragma nopushoptwarn +# pragma nopackwarning + +#elif defined(__MWERKS__) + +// Metrowerks CodeWarrior + +#elif defined(__SUNPRO_CC) + +// Sun Workshop Compiler C++ + +#elif defined(__HP_aCC) + +// HP aCC + +#elif defined(__MRC__) || defined(__SC__) + +// MPW MrCpp or SCpp + +#elif defined(__IBMCPP__) + +// IBM Visual Age + +#elif defined(_MSC_VER) + +// Microsoft Visual C++ +// +// Must remain the last #elif since some other vendors (Metrowerks, for example) +// also #define _MSC_VER + +# pragma warning (pop) +# pragma pack (pop) + +#endif diff --git a/VIServer/Classes/Networking/push_options.hpp b/VIServer/Classes/Networking/push_options.hpp new file mode 100644 index 0000000000..ec64373c6f --- /dev/null +++ b/VIServer/Classes/Networking/push_options.hpp @@ -0,0 +1,127 @@ +// +// detail/push_options.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +// No header guard + +#if defined(__COMO__) + +// Comeau C++ + +#elif defined(__DMC__) + +// Digital Mars C++ + +#elif defined(__INTEL_COMPILER) || defined(__ICL) \ + || defined(__ICC) || defined(__ECC) + +// Intel C++ + +#elif defined(__GNUC__) + +// GNU C++ + +# if defined(__MINGW32__) || defined(__CYGWIN__) +# pragma pack (push, 8) +# endif + +# if defined(__OBJC__) +# if !defined(__APPLE_CC__) || (__APPLE_CC__ <= 1) +# if !defined(STDNET_DISABLE_OBJC_WORKAROUND) +# if !defined(Protocol) && !defined(id) +# define Protocol cpp_Protocol +# define id cpp_id +# define STDNET_OBJC_WORKAROUND +# endif +# endif +# endif +# endif + +#elif defined(__KCC) + +// Kai C++ + +#elif defined(__sgi) + +// SGI MIPSpro C++ + +#elif defined(__DECCXX) + +// Compaq Tru64 Unix cxx + +#elif defined(__ghs) + +// Greenhills C++ + +#elif defined(__BORLANDC__) + +// Borland C++ + +# pragma option push -a8 -b -Ve- -Vx- -w-inl -vi- +# pragma nopushoptwarn +# pragma nopackwarning +# if !defined(__MT__) +# error Multithreaded RTL must be selected. +# endif // !defined(__MT__) + +#elif defined(__MWERKS__) + +// Metrowerks CodeWarrior + +#elif defined(__SUNPRO_CC) + +// Sun Workshop Compiler C++ + +#elif defined(__HP_aCC) + +// HP aCC + +#elif defined(__MRC__) || defined(__SC__) + +// MPW MrCpp or SCpp + +#elif defined(__IBMCPP__) + +// IBM Visual Age + +#elif defined(_MSC_VER) + +// Microsoft Visual C++ +// +// Must remain the last #elif since some other vendors (Metrowerks, for example) +// also #define _MSC_VER + +# pragma warning (disable:4103) +# pragma warning (push) +# pragma warning (disable:4127) +# pragma warning (disable:4180) +# pragma warning (disable:4244) +# pragma warning (disable:4355) +# pragma warning (disable:4512) +# pragma warning (disable:4675) +# if defined(_M_IX86) && defined(_Wp64) +// The /Wp64 option is broken. If you want to check 64 bit portability, use a +// 64 bit compiler! +# pragma warning (disable:4311) +# pragma warning (disable:4312) +# endif // defined(_M_IX86) && defined(_Wp64) +# pragma pack (push, 8) +// Note that if the /Og optimisation flag is enabled with MSVC6, the compiler +// has a tendency to incorrectly optimise away some calls to member template +// functions, even though those functions contain code that should not be +// optimised away! Therefore we will always disable this optimisation option +// for the MSVC6 compiler. +# if (_MSC_VER < 1300) +# pragma optimize ("g", off) +# endif +# if !defined(_MT) +# error Multithreaded RTL must be selected. +# endif // !defined(_MT) + +#endif diff --git a/VIServer/Classes/Networking/socket_types.hpp b/VIServer/Classes/Networking/socket_types.hpp new file mode 100644 index 0000000000..7f06f86b68 --- /dev/null +++ b/VIServer/Classes/Networking/socket_types.hpp @@ -0,0 +1,186 @@ +// +// detail/socket_types.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef STDNET_DETAIL_SOCKET_TYPES_HPP +#define STDNET_DETAIL_SOCKET_TYPES_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "config.hpp" + +#if defined(STDNET_WINDOWS) || defined(__CYGWIN__) +# if defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_) +# error WinSock.h has already been included +# endif // defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_) +# if defined(__BORLANDC__) +# include // Needed for __errno +# if !defined(_WSPIAPI_H_) +# define _WSPIAPI_H_ +# define STDNET_WSPIAPI_H_DEFINED +# endif // !defined(_WSPIAPI_H_) +# endif // defined(__BORLANDC__) +# include +# include +# include +# if defined(STDNET_WSPIAPI_H_DEFINED) +# undef _WSPIAPI_H_ +# undef STDNET_WSPIAPI_H_DEFINED +# endif // defined(STDNET_WSPIAPI_H_DEFINED) +# if !defined(STDNET_NO_DEFAULT_LINKED_LIBS) +# if defined(UNDER_CE) +# pragma comment(lib, "ws2.lib") +# elif defined(_MSC_VER) || defined(__BORLANDC__) +# pragma comment(lib, "ws2_32.lib") +# pragma comment(lib, "mswsock.lib") +# endif // defined(_MSC_VER) || defined(__BORLANDC__) +# endif // !defined(STDNET_NO_DEFAULT_LINKED_LIBS) +# include "old_win_sdk_compat.hpp" +#else +# include +# if !defined(__SYMBIAN32__) +# include +# endif +# include +# include +# include +# if defined(__hpux) +# include +# endif +# if !defined(__hpux) || defined(__SELECT) +# include +# endif +# include +# include +# include +# include +# if !defined(__SYMBIAN32__) +# include +# endif +# include +# include +# include +# include +# if defined(__sun) +# include +# include +# endif +#endif + +#include "push_options.hpp" + +namespace std { +namespace experimental { +namespace net { +namespace detail { + +#if defined(STDNET_WINDOWS) || defined(__CYGWIN__) +typedef SOCKET socket_type; +const SOCKET invalid_socket = INVALID_SOCKET; +const int socket_error_retval = SOCKET_ERROR; +const int max_addr_v4_str_len = 256; +const int max_addr_v6_str_len = 256; +typedef sockaddr socket_addr_type; +typedef in_addr in4_addr_type; +typedef ip_mreq in4_mreq_type; +typedef sockaddr_in sockaddr_in4_type; +# if defined(STDNET_HAS_OLD_WIN_SDK) +typedef in6_addr_emulation in6_addr_type; +typedef ipv6_mreq_emulation in6_mreq_type; +typedef sockaddr_in6_emulation sockaddr_in6_type; +typedef sockaddr_storage_emulation sockaddr_storage_type; +typedef addrinfo_emulation addrinfo_type; +# else +typedef in6_addr in6_addr_type; +typedef ipv6_mreq in6_mreq_type; +typedef sockaddr_in6 sockaddr_in6_type; +typedef sockaddr_storage sockaddr_storage_type; +typedef addrinfo addrinfo_type; +# endif +typedef unsigned long ioctl_arg_type; +typedef u_long u_long_type; +typedef u_short u_short_type; +typedef int signed_size_type; +const int shutdown_receive = SD_RECEIVE; +const int shutdown_send = SD_SEND; +const int shutdown_both = SD_BOTH; +const int message_peek = MSG_PEEK; +const int message_out_of_band = MSG_OOB; +const int message_do_not_route = MSG_DONTROUTE; +const int message_end_of_record = 0; // Not supported on Windows. +# if defined (_WIN32_WINNT) +const int max_iov_len = 64; +# else +const int max_iov_len = 16; +# endif +#else +typedef int socket_type; +const int invalid_socket = -1; +const int socket_error_retval = -1; +const int max_addr_v4_str_len = INET_ADDRSTRLEN; +#if defined(INET6_ADDRSTRLEN) +const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE; +#else // defined(INET6_ADDRSTRLEN) +const int max_addr_v6_str_len = 256; +#endif // defined(INET6_ADDRSTRLEN) +typedef sockaddr socket_addr_type; +typedef in_addr in4_addr_type; +# if defined(__hpux) +// HP-UX doesn't provide ip_mreq when _XOPEN_SOURCE_EXTENDED is defined. +struct in4_mreq_type +{ + struct in_addr imr_multiaddr; + struct in_addr imr_interface; +}; +# else +typedef ip_mreq in4_mreq_type; +# endif +typedef sockaddr_in sockaddr_in4_type; +typedef in6_addr in6_addr_type; +typedef ipv6_mreq in6_mreq_type; +typedef sockaddr_in6 sockaddr_in6_type; +typedef sockaddr_storage sockaddr_storage_type; +typedef sockaddr_un sockaddr_un_type; +typedef addrinfo addrinfo_type; +typedef int ioctl_arg_type; +typedef uint32_t u_long_type; +typedef uint16_t u_short_type; +#if defined(STDNET_HAS_SSIZE_T) +typedef ssize_t signed_size_type; +#else // defined(STDNET_HAS_SSIZE_T) +typedef int signed_size_type; +#endif // defined(STDNET_HAS_SSIZE_T) +const int shutdown_receive = SHUT_RD; +const int shutdown_send = SHUT_WR; +const int shutdown_both = SHUT_RDWR; +const int message_peek = MSG_PEEK; +const int message_out_of_band = MSG_OOB; +const int message_do_not_route = MSG_DONTROUTE; +const int message_end_of_record = MSG_EOR; +# if defined(IOV_MAX) +const int max_iov_len = IOV_MAX; +# else +// POSIX platforms are not required to define IOV_MAX. +const int max_iov_len = 16; +# endif +#endif +const int custom_socket_option_level = 0xA5100000; +const int enable_connection_aborted_option = 1; +const int always_fail_option = 2; + +} // namespace detail +} // namespace net +} // namespace experimental +} // namespace std + +#include "pop_options.hpp" + +#endif // STDNET_DETAIL_SOCKET_TYPES_HPP diff --git a/VIServer/Classes/Networking/winsock_init.hpp b/VIServer/Classes/Networking/winsock_init.hpp new file mode 100644 index 0000000000..1dbe8e0ed8 --- /dev/null +++ b/VIServer/Classes/Networking/winsock_init.hpp @@ -0,0 +1,86 @@ +// +// detail/winsock_init.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef STDNET_DETAIL_WINSOCK_INIT_HPP +#define STDNET_DETAIL_WINSOCK_INIT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "config.hpp" + +#if defined(STDNET_WINDOWS) || defined(__CYGWIN__) + +#include "push_options.hpp" + + +class winsock_init_base +{ +protected: + // Structure to track result of initialisation and number of uses. POD is used + // to ensure that the values are zero-initialised prior to any code being run. + struct data + { + long init_count_; + long result_; + }; + + STDNET_DECL static void startup(data& d, + unsigned char major, unsigned char minor); + + STDNET_DECL static void cleanup(data& d); + + STDNET_DECL static void throw_on_error(data& d); +}; + +template +class winsock_init : private winsock_init_base +{ +public: + winsock_init(bool allow_throw = true) + { + startup(data_, Major, Minor); + if (allow_throw) + throw_on_error(data_); + } + + winsock_init(const winsock_init&) + { + startup(data_, Major, Minor); + throw_on_error(data_); + } + + ~winsock_init() + { + cleanup(data_); + } + +private: + static data data_; +}; + +template +winsock_init_base::data winsock_init::data_; + +// Static variable to ensure that winsock is initialised before main, and +// therefore before any other threads can get started. +static const winsock_init<>& winsock_init_instance = winsock_init<>(false); + + +#include "pop_options.hpp" + +#if defined(STDNET_HEADER_ONLY) +# include "winsock_init.ipp" +#endif // defined(STDNET_HEADER_ONLY) + +#endif // defined(STDNET_WINDOWS) || defined(__CYGWIN__) + +#endif // STDNET_DETAIL_WINSOCK_INIT_HPP diff --git a/VIServer/Classes/Networking/winsock_init.ipp b/VIServer/Classes/Networking/winsock_init.ipp new file mode 100644 index 0000000000..7f923e7def --- /dev/null +++ b/VIServer/Classes/Networking/winsock_init.ipp @@ -0,0 +1,59 @@ +// +// detail/impl/winsock_init.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef STDNET_DETAIL_IMPL_WINSOCK_INIT_IPP +#define STDNET_DETAIL_IMPL_WINSOCK_INIT_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "config.hpp" + +#if defined(STDNET_WINDOWS) || defined(__CYGWIN__) + +#include "socket_types.hpp" +#include "winsock_init.hpp" +#include "push_options.hpp" + + +void winsock_init_base::startup(data& d, + unsigned char major, unsigned char minor) +{ + if (::InterlockedIncrement(&d.init_count_) == 1) + { + WSADATA wsa_data; + long result = ::WSAStartup(MAKEWORD(major, minor), &wsa_data); + ::InterlockedExchange(&d.result_, result); + } +} + +void winsock_init_base::cleanup(data& d) +{ + if (::InterlockedDecrement(&d.init_count_) == 0) + { + ::WSACleanup(); + } +} + +void winsock_init_base::throw_on_error(data& d) +{ + long result = ::InterlockedExchangeAdd(&d.result_, 0); + if (result != 0) + { + + } +} + +#include "pop_options.hpp" + +#endif // defined(STDNET_WINDOWS) || defined(__CYGWIN__) + +#endif // STDNET_DETAIL_IMPL_WINSOCK_INIT_IPP diff --git a/VIServer/Classes/ServerProtocolDefines.h b/VIServer/Classes/ServerProtocolDefines.h new file mode 100644 index 0000000000..de56fcf678 --- /dev/null +++ b/VIServer/Classes/ServerProtocolDefines.h @@ -0,0 +1,11 @@ +#ifndef LOSEMYMIND_SERVERPROTOCOLDEFINES_H +#define LOSEMYMIND_SERVERPROTOCOLDEFINES_H + + + + + + + + +#endif // LOSEMYMIND_SERVERPROTOCOLDEFINES_H diff --git a/VIServer/Classes/VIServer.cpp b/VIServer/Classes/VIServer.cpp new file mode 100644 index 0000000000..bbb5b62661 --- /dev/null +++ b/VIServer/Classes/VIServer.cpp @@ -0,0 +1,181 @@ +#include "VIServer.h" +#include +#include +#include +#include +#include +#include "FoundationKit/Base/MathEx.h" +#include "FoundationKit/Base/DataStream.h" +#include "FoundationKit/Foundation/unique_id.hpp" +#include "Networking/IProtocol.h" +#include "ConnectionManager.h" + +USING_NS_FK; + +// һ꣬󶨷ִк +#define BIND_COMMAND(FUN) std::bind(&VIServer::FUN,this) + + +// ȡϵͳʱ䡣 +int gettimeofday(struct timeval * val, struct timezone *) +{ + if (val) + { + LARGE_INTEGER liTime, liFreq; + QueryPerformanceFrequency(&liFreq); + QueryPerformanceCounter(&liTime); + val->tv_sec = (long)(liTime.QuadPart / liFreq.QuadPart); + val->tv_usec = (long)(liTime.QuadPart * 1000000.0 / liFreq.QuadPart - val->tv_sec * 1000000.0); + } + return 0; +} + +// VIServer캯 +VIServer::VIServer() + :_blaunched(false) + , _deltaTime(0.0f) + , _exit(false) +{ + _lastUpdate = new struct timeval; + memset(_lastUpdate, 0, sizeof(timeval)); +} + +// VIServer +VIServer::~VIServer() +{ + _readCommandThread.detach(); +} + +// +void VIServer::setup() +{ + // Ϣ + LOG_INFO(">>......"); + + // ˳ + _commandMap["exit"] = [this]() + { + this->setExit(true); + }; + + // + _commandMap["start"] = BIND_COMMAND(start); + // ֹͣ + _commandMap["stop"] = BIND_COMMAND(stop); + + // һ̨̣߳ + _readCommandThread = std::thread([this] + { + // + std::string cmd; + // ѭȴ + while (true) + { + // ȴȡ + std::cin >> cmd; + // ̻߳ȥȡִ + pushMessage(cmd); + + // ̨˳exit + // ô˳߳ + if (cmd == "exit") + { + break; + } + } + }); + + // + start(); + LOG_INFO(">>"); +} + +// º +void VIServer::update(bool& bExit) +{ + // һ֡һܹ֡˶ʱ + calculateDeltaTime(); + + // ס_commandList̷߳Դռ + std::unique_lock lock(_commandMutex); + // бһʱ_readCommandThread߳̿Լ + std::list copyCommand = _commandList; + // Ѿʱбˡ + _commandList.clear(); + // _commandList_readCommandThread߳̿Է + lock.unlock(); + + // бִӦĺ + for (auto cmd : copyCommand) + { + if (_commandMap.find(cmd) != _commandMap.end()) + { + _commandMap[cmd](); + } + } + + // Ƿ˳ + bExit = getExit(); + + // ӹĸº + ConnectionManager::getInstance()->update(_deltaTime); + +} + +// һ֡һִ֡еʱ䡣 +void VIServer::calculateDeltaTime() +{ + struct timeval timeNow; + + if (gettimeofday(&timeNow, nullptr) != 0) + { + _deltaTime = 0; + return; + } + _deltaTime = (timeNow.tv_sec - _lastUpdate->tv_sec) + (timeNow.tv_usec - _lastUpdate->tv_usec) / 1000000.0f; + _deltaTime = MathEx::max(0.f, _deltaTime); + + *_lastUpdate = timeNow; +} + +// ̨ +void VIServer::pushMessage(std::string& comMsg) +{ + std::lock_guard lock(_commandMutex); + _commandList.push_back(comMsg); +} + +// ÷Ƿ˳ +void VIServer::setExit(bool bExit) +{ + _exit = bExit; +} + +// ȡǷ˳ +bool VIServer::getExit() +{ + return _exit; +} + +// +void VIServer::start() +{ + //û򴴽һӹܿƶ + if (!_blaunched) + { + ConnectionManager::getInstance()->Startup(); + } + + _blaunched = true; +} + +// ֹͣ +void VIServer::stop() +{ + LOG_INFO(">>ֹͣ......"); + _blaunched = false; + ConnectionManager::getInstance()->Shutdown(); + +} + + diff --git a/VIServer/Classes/VIServer.h b/VIServer/Classes/VIServer.h new file mode 100644 index 0000000000..8f2de27df6 --- /dev/null +++ b/VIServer/Classes/VIServer.h @@ -0,0 +1,107 @@ + +/** + * ߼Ĺܣ + * 1.̨ + * 2.ܺʹƶ + * 3.ܺʹ豸ӡ + */ + +#pragma once +// ߳̿ +#include +// +#include +// +#include +// ַ +#include +// unordered_map +#include +// +#include +// ƽ̨ +#include "FoundationKit/GenericPlatformMacros.h" +// ģ +#include "FoundationKit/Foundation/Singleton.h" +// TCPӼ +#include "Networking/TcpListener.h" +// IPv4 ַ +#include "Networking/IPv4Address.h" +// IPv4 ַ +#include "Networking/IPv4Endpoint.h" +// socket +#include "Networking/SocketBSD.h" + +USING_NS_FK; + +// ͨģSingletonVIServerΪ +class VIServer : public Singleton +{ + //VIServerĹ캯Ϊprivate˴VIServer + VIServer(); + // ʹԪSingletonԵVIServerĹ캯 + friend Singleton; +public: + // ̨бִеĺ + typedef std::unordered_map > CommandMap; + + // VIServerִڴͷš + ~VIServer(); + + // ʼ + void setup(); + + // ·߼ + void update(bool& bExit); + + // ̨浽 _commandList, ߳ + // ȥȡЩȥִ. + void pushMessage(std::string& comMsg); + + // ÷ǷҪ˳ + void setExit(bool bExit); + // ȡǷ˳ + bool getExit(); + + //====================== + // + void start(); + // ֹͣ + void stop(); + +private: + // ÿ֡еʱ + void calculateDeltaTime(); + + // ǷѾ + bool _blaunched; + + // ÿ֡еʱ䣬λ롣 + float _deltaTime; + + // ¼ѭµʱ + struct timeval *_lastUpdate; + + // _exitΪtrue,˳ + bool _exit; + + // ̨ڿƷ + std::list _commandList; + + // 󣬱֤_commandList̰߳ȫġ + std::mutex _commandMutex; + + // ϣ¼ֵ֧Ѿִеķ + CommandMap _commandMap; + + // ڶȡ̨̡߳ + std::thread _readCommandThread; + +}; + + + + + + + diff --git a/VIServer/Classes/main.cpp b/VIServer/Classes/main.cpp new file mode 100644 index 0000000000..8d6200e651 --- /dev/null +++ b/VIServer/Classes/main.cpp @@ -0,0 +1,91 @@ + + +#include +#include "VIServer.h" + + +// ߳ID +DWORD g_dwMainThreadId; + +// Ƿ˳ true˳false˳ +bool g_appExit = false; + +// ̨¼ص +BOOL WINAPI ConsoleEventCallback(DWORD dwCtrlType) +{ + if (dwCtrlType == CTRL_CLOSE_EVENT) + { + PostThreadMessage(g_dwMainThreadId, WM_QUIT, 0, 0); + g_appExit = true; + return FALSE; + } + return FALSE; +} + +// ֡صʱ䡣 +static LARGE_INTEGER G_FrameInterval; + +// óÿ֡õʱ +// setFrameInterval(1/60.f) // 60֡ +// setFrameInterval(1/30.f) // 30֡ +static void setFrameInterval(float interval) +{ + LARGE_INTEGER nFreq; + QueryPerformanceFrequency(&nFreq); + G_FrameInterval.QuadPart = (LONGLONG)(interval * nFreq.QuadPart); +} + +// +int main(int argv, char** argc) +{ + + // ȡ߳ID + g_dwMainThreadId = GetCurrentThreadId(); + + // ϵͳSetConsoleCtrlHandler ÿ̨¼ص + SetConsoleCtrlHandler(ConsoleEventCallback, TRUE); + + // 浱ǰʱ֡ʱ + LARGE_INTEGER nNow; + LARGE_INTEGER nLast; + + //ȡʱ + QueryPerformanceCounter(&nLast); + + // óΪ60֡1ӵ60Ρ + setFrameInterval(1/60.f); + + // ʼ + VIServer::getInstance()->setup(); + + // ʶΪ״̬˳ + // ֵexitʱֵ + bool bExit = false; + + // ѭΪûexitûеرհť + while (!bExit && !g_appExit) + { + //ȡʱ丳nNow + QueryPerformanceCounter(&nNow); + + // ǰʱȥ֡µʱ 1/60ô͵÷º + if (nNow.QuadPart - nLast.QuadPart > G_FrameInterval.QuadPart) + { + // ֡õʱ + nLast.QuadPart = nNow.QuadPart - (nNow.QuadPart % G_FrameInterval.QuadPart); + // ÷ĸº·״̬ + VIServer::getInstance()->update(bExit); + } + else + { + Sleep(1); + } + } + + // ˳ + int exitCode = 0; + SetConsoleCtrlHandler(ConsoleEventCallback, FALSE); + system("pause"); + return exitCode; + +} \ No newline at end of file diff --git a/VIServer/README.md b/VIServer/README.md new file mode 100644 index 0000000000..1a0414b800 --- /dev/null +++ b/VIServer/README.md @@ -0,0 +1,2 @@ +# VIServer +For my lover diff --git a/VIServer/TCPClient.zip b/VIServer/TCPClient.zip new file mode 100644 index 0000000000..286bdc28d5 Binary files /dev/null and b/VIServer/TCPClient.zip differ diff --git a/VIServer/TCPClient/TCPClient.sln b/VIServer/TCPClient/TCPClient.sln new file mode 100644 index 0000000000..5d8294eded --- /dev/null +++ b/VIServer/TCPClient/TCPClient.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.40629.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TCPClient", "TCPClient\TCPClient.vcxproj", "{D32F4FF9-AD77-4F1F-9728-2D8A3FC41B6B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D32F4FF9-AD77-4F1F-9728-2D8A3FC41B6B}.Debug|Win32.ActiveCfg = Debug|Win32 + {D32F4FF9-AD77-4F1F-9728-2D8A3FC41B6B}.Debug|Win32.Build.0 = Debug|Win32 + {D32F4FF9-AD77-4F1F-9728-2D8A3FC41B6B}.Release|Win32.ActiveCfg = Release|Win32 + {D32F4FF9-AD77-4F1F-9728-2D8A3FC41B6B}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/VIServer/TCPClient/TCPClient/ClientProtocolDefines.h b/VIServer/TCPClient/TCPClient/ClientProtocolDefines.h new file mode 100644 index 0000000000..da50d5c26a --- /dev/null +++ b/VIServer/TCPClient/TCPClient/ClientProtocolDefines.h @@ -0,0 +1,8 @@ +#ifndef LOSEMYMIND_CLIENTPROTOCOLDEFINES_H +#define LOSEMYMIND_CLIENTPROTOCOLDEFINES_H + +const int CLIENT_LOGIN = 1000; +const int CLIENT_CHAT = 1001; + + +#endif // LOSEMYMIND_CLIENTPROTOCOLDEFINES_H diff --git a/VIServer/TCPClient/TCPClient/TCPClient.cpp b/VIServer/TCPClient/TCPClient/TCPClient.cpp new file mode 100644 index 0000000000..5937520053 --- /dev/null +++ b/VIServer/TCPClient/TCPClient/TCPClient.cpp @@ -0,0 +1,87 @@ +/* +* tcpclient.c - A simple TCP client +* usage: tcpclient +*/ +#include +#include +#include +#include "socket_types.hpp" +#include "winsock_init.hpp" +#include "ClientProtocolDefines.h" + +#define BUFSIZE 1024 + +/* +* error - wrapper for perror +*/ +void error(char *msg) { + perror(msg); + //exit(0); +} + +int main(int argc, char **argv) { + int sockfd, portno, n; + struct sockaddr_in serveraddr; + struct hostent *server; + char *hostname; + char buf[BUFSIZE]; + + portno = 4159; + + /* socket: create the socket */ + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) + error("ERROR opening socket"); + + /* gethostbyname: get the server's DNS entry */ + + + /* build the server's Internet address */ + memset((char *)&serveraddr, 0,sizeof(serveraddr)); + serveraddr.sin_family = AF_INET; + serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1"); + //memcpy((char *)server->h_addr, (char *)&serveraddr.sin_addr.s_addr, server->h_length); + serveraddr.sin_port = htons(portno); + + /* connect: create a connection with the server */ + if (connect(sockfd, (sockaddr*)&serveraddr, sizeof(sockaddr_in)) < 0) + error("ERROR connecting"); + + while (true) + { + /* get message line from the user */ + printf("Please enter msg: "); + memset(buf, 0, BUFSIZE); + fgets(buf, BUFSIZE, stdin); + + int sendCount = 0; + char DataStream[1024] = { 0 }; + char* pDataStream = DataStream; + memcpy(pDataStream, &CLIENT_CHAT, sizeof(int)); + pDataStream += sizeof(int); + sendCount += sizeof(int); + int msgLen = strlen(buf); + memcpy(pDataStream, &msgLen, sizeof(int)); + pDataStream += sizeof(int); + sendCount += sizeof(int); + memcpy(pDataStream, (char*)buf, msgLen); + sendCount += strlen(buf); + /* send the message line to the server */ + n = send(sockfd, DataStream, sendCount, 0); + if (n < 0) + error("ERROR writing to socket"); + + /* print the server's reply */ + memset(buf, 0, BUFSIZE); + n = recv(sockfd, buf, BUFSIZE, 0); + if (n < 0) + error("ERROR reading from socket"); + printf("Echo from server: %s \n", buf); + } + + closesocket(sockfd); + + system("pause"); + + return 0; +} \ No newline at end of file diff --git a/VIServer/TCPClient/TCPClient/TCPClient.vcxproj b/VIServer/TCPClient/TCPClient/TCPClient.vcxproj new file mode 100644 index 0000000000..668fc44785 --- /dev/null +++ b/VIServer/TCPClient/TCPClient/TCPClient.vcxproj @@ -0,0 +1,95 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {D32F4FF9-AD77-4F1F-9728-2D8A3FC41B6B} + Win32Proj + TCPClient + + + + Application + true + v120_xp + Unicode + + + Application + false + v120 + true + Unicode + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;_LIB;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/VIServer/TCPClient/TCPClient/TCPClient.vcxproj.filters b/VIServer/TCPClient/TCPClient/TCPClient.vcxproj.filters new file mode 100644 index 0000000000..bf1b827f8f --- /dev/null +++ b/VIServer/TCPClient/TCPClient/TCPClient.vcxproj.filters @@ -0,0 +1,45 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 源文件 + + + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + \ No newline at end of file diff --git a/VIServer/TCPClient/TCPClient/config.hpp b/VIServer/TCPClient/TCPClient/config.hpp new file mode 100644 index 0000000000..c797490336 --- /dev/null +++ b/VIServer/TCPClient/TCPClient/config.hpp @@ -0,0 +1,666 @@ +// +// detail/config.hpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef STDNET_DETAIL_CONFIG_HPP +#define STDNET_DETAIL_CONFIG_HPP + +// Default to a header-only implementation. The user must specifically request +// separate compilation by defining either STDNET_SEPARATE_COMPILATION or +// STDNET_DYN_LINK (as a DLL/shared library implies separate compilation). +#if !defined(STDNET_HEADER_ONLY) +# if !defined(STDNET_SEPARATE_COMPILATION) +# if !defined(STDNET_DYN_LINK) +# define STDNET_HEADER_ONLY 1 +# endif // !defined(STDNET_DYN_LINK) +# endif // !defined(STDNET_SEPARATE_COMPILATION) +#endif // !defined(STDNET_HEADER_ONLY) + +#if defined(STDNET_HEADER_ONLY) +# define STDNET_DECL inline +#else // defined(STDNET_HEADER_ONLY) +# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CODEGEARC__) +// We need to import/export our code only if the user has specifically asked +// for it by defining STDNET_DYN_LINK. +# if defined(STDNET_DYN_LINK) +// Export if this is our own source, otherwise import. +# if defined(STDNET_SOURCE) +# define STDNET_DECL __declspec(dllexport) +# else // defined(STDNET_SOURCE) +# define STDNET_DECL __declspec(dllimport) +# endif // defined(STDNET_SOURCE) +# endif // defined(STDNET_DYN_LINK) +# endif // defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CODEGEARC__) +#endif // defined(STDNET_HEADER_ONLY) + +// If STDNET_DECL isn't defined yet define it now. +#if !defined(STDNET_DECL) +# define STDNET_DECL +#endif // !defined(STDNET_DECL) + +// Microsoft Visual C++ detection. +#if !defined(STDNET_MSVC) +# if defined(_MSC_VER) && !defined(__MWERKS__) && !defined(__EDG_VERSION__) +# define STDNET_MSVC _MSC_VER +# endif // defined(_MSC_VER) && !defined(__MWERKS__) && !defined(__EDG_VERSION__) +#endif // defined(STDNET_MSVC) + +// Support move construction and assignment on compilers known to allow it. +#if !defined(STDNET_HAS_MOVE) +# if !defined(STDNET_DISABLE_MOVE) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_HAS_MOVE 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# endif // !defined(STDNET_DISABLE_MOVE) +#endif // !defined(STDNET_HAS_MOVE) + +// If STDNET_MOVE_CAST isn't defined, and move support is available, define +// STDNET_MOVE_ARG and STDNET_MOVE_CAST to take advantage of rvalue +// references and perfect forwarding. +#if defined(STDNET_HAS_MOVE) && !defined(STDNET_MOVE_CAST) +# define STDNET_MOVE_ARG(type) type&& +# define STDNET_MOVE_CAST(type) static_cast +#endif // defined(STDNET_HAS_MOVE) && !defined(STDNET_MOVE_CAST) + +// If STDNET_MOVE_CAST still isn't defined, default to a C++03-compatible +// implementation. Note that older g++ and MSVC versions don't like it when you +// pass a non-member function through a const reference, so for most compilers +// we'll play it safe and stick with the old approach of passing the handler by +// value. +#if !defined(STDNET_MOVE_CAST) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1)) || (__GNUC__ > 4) +# define STDNET_MOVE_ARG(type) const type& +# else // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1)) || (__GNUC__ > 4) +# define STDNET_MOVE_ARG(type) type +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1)) || (__GNUC__ > 4) +# elif defined(STDNET_MSVC) +# if (_MSC_VER >= 1400) +# define STDNET_MOVE_ARG(type) const type& +# else // (_MSC_VER >= 1400) +# define STDNET_MOVE_ARG(type) type +# endif // (_MSC_VER >= 1400) +# else +# define STDNET_MOVE_ARG(type) type +# endif +# define STDNET_MOVE_CAST(type) static_cast +#endif // !defined_STDNET_MOVE_CAST + +// Support variadic templates on compilers known to allow it. +#if !defined(STDNET_HAS_VARIADIC_TEMPLATES) +# if !defined(STDNET_DISABLE_VARIADIC_TEMPLATES) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_HAS_VARIADIC_TEMPLATES 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(__clang__) +# if __has_feature(cxx_variadic_templates) +# define STDNET_HAS_VARIADIC_TEMPLATES 1 +# endif // __has_feature(cxx_noexcept) +# endif // defined(__clang__) +# endif // !defined(STDNET_DISABLE_VARIADIC_TEMPLATES) +#endif // !defined(STDNET_HAS_VARIADIC_TEMPLATES) + +// Support the noexcept specifier on compilers known to allow it. +#if !defined(STDNET_NOEXCEPT) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_NOEXCEPT noexcept +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(__clang__) +# if __has_feature(cxx_noexcept) +# define STDNET_NOEXCEPT noexcept +# endif // __has_feature(cxx_noexcept) +# endif // defined(__clang__) +# if !defined(STDNET_NOEXCEPT) +# define STDNET_NOEXCEPT +# endif // !defined(STDNET_NOEXCEPT) +#endif // !defined(STDNET_NOEXCEPT) + +// Support deleted functions on compilers known to allow it. +#if !defined(STDNET_DELETED) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_DELETED = delete +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(__clang__) +# if __has_feature(cxx_deleted_functions) +# define STDNET_DELETED = delete +# endif // __has_feature(cxx_noexcept) +# endif // defined(__clang__) +# if !defined(STDNET_DELETED) +# define STDNET_DELETED +# endif // !defined(STDNET_DELETED) +#endif // !defined(STDNET_DELETED) + +// Support relaxed constexpr on compilers known to allow it. +#if !defined(STDNET_CONSTEXPR) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_HAS_CONSTEXPR 1 +# define STDNET_CONSTEXPR constexpr +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(__clang__) +# if __has_feature(cxx_constexpr) +# define STDNET_HAS_CONSTEXPR 1 +# define STDNET_CONSTEXPR constexpr +# endif // __has_feature(cxx_constexpr) +# endif // defined(__clang__) +# if !defined(STDNET_CONSTEXPR) +# define STDNET_CONSTEXPR +# endif // !defined(STDNET_CONSTEXPR) +#endif // !defined(STDNET_CONSTEXPR) + +// Standard library support for system errors. +#if !defined(STDNET_HAS_STD_SYSTEM_ERROR) +# if !defined(STDNET_DISABLE_STD_SYSTEM_ERROR) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_HAS_STD_SYSTEM_ERROR 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# endif // !defined(STDNET_DISABLE_STD_SYSTEM_ERROR) +#endif // !defined(STDNET_HAS_STD_SYSTEM_ERROR) + +// Compliant C++11 compilers put noexcept specifiers on error_category members. +#if !defined(STDNET_ERROR_CATEGORY_NOEXCEPT) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_ERROR_CATEGORY_NOEXCEPT noexcept(true) +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(__clang__) +# if __has_feature(cxx_noexcept) +# define STDNET_ERROR_CATEGORY_NOEXCEPT noexcept(true) +# endif // __has_feature(cxx_noexcept) +# endif // defined(__clang__) +# if !defined(STDNET_ERROR_CATEGORY_NOEXCEPT) +# define STDNET_ERROR_CATEGORY_NOEXCEPT +# endif // !defined(STDNET_ERROR_CATEGORY_NOEXCEPT) +#endif // !defined(STDNET_ERROR_CATEGORY_NOEXCEPT) + +// Standard library support for arrays. +#if !defined(STDNET_HAS_STD_ARRAY) +# if !defined(STDNET_DISABLE_STD_ARRAY) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_HAS_STD_ARRAY 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(STDNET_MSVC) +# if (_MSC_VER >= 1600) +# define STDNET_HAS_STD_ARRAY 1 +# endif // (_MSC_VER >= 1600) +# endif // defined(STDNET_MSVC) +# endif // !defined(STDNET_DISABLE_STD_ARRAY) +#endif // !defined(STDNET_HAS_STD_ARRAY) + +// Standard library support for shared_ptr and weak_ptr. +#if !defined(STDNET_HAS_STD_SHARED_PTR) +# if !defined(STDNET_DISABLE_STD_SHARED_PTR) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_HAS_STD_SHARED_PTR 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(STDNET_MSVC) +# if (_MSC_VER >= 1600) +# define STDNET_HAS_STD_SHARED_PTR 1 +# endif // (_MSC_VER >= 1600) +# endif // defined(STDNET_MSVC) +# endif // !defined(STDNET_DISABLE_STD_SHARED_PTR) +#endif // !defined(STDNET_HAS_STD_SHARED_PTR) + +// Standard library support for atomic operations. +#if !defined(STDNET_HAS_STD_ATOMIC) +# if !defined(STDNET_DISABLE_STD_ATOMIC) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_HAS_STD_ATOMIC 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# endif // !defined(STDNET_DISABLE_STD_ATOMIC) +#endif // !defined(STDNET_HAS_STD_ATOMIC) + +// Standard library support for chrono. Some standard libraries (such as the +// libstdc++ shipped with gcc 4.6) provide monotonic_clock as per early C++0x +// drafts, rather than the eventually standardised name of steady_clock. +#if !defined(STDNET_HAS_STD_CHRONO) +# if !defined(STDNET_DISABLE_STD_CHRONO) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_HAS_STD_CHRONO 1 +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ == 6)) +# define STDNET_HAS_STD_CHRONO_MONOTONIC_CLOCK 1 +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ == 6)) +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# endif // !defined(STDNET_DISABLE_STD_CHRONO) +#endif // !defined(STDNET_HAS_STD_CHRONO) + +// Standard library support for addressof. +#if !defined(STDNET_HAS_STD_ADDRESSOF) +# if !defined(STDNET_DISABLE_STD_ADDRESSOF) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_HAS_STD_ADDRESSOF 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# endif // !defined(STDNET_DISABLE_STD_ADDRESSOF) +#endif // !defined(STDNET_HAS_STD_ADDRESSOF) + +// Standard library support for the function class. +#if !defined(STDNET_HAS_STD_FUNCTION) +# if !defined(STDNET_DISABLE_STD_FUNCTION) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_HAS_STD_FUNCTION 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# endif // !defined(STDNET_DISABLE_STD_FUNCTION) +#endif // !defined(STDNET_HAS_STD_FUNCTION) + +// Standard library support for type traits. +#if !defined(STDNET_HAS_STD_TYPE_TRAITS) +# if !defined(STDNET_DISABLE_STD_TYPE_TRAITS) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_HAS_STD_TYPE_TRAITS 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# endif // !defined(STDNET_DISABLE_STD_TYPE_TRAITS) +#endif // !defined(STDNET_HAS_STD_TYPE_TRAITS) + +// Standard library support for the cstdint header. +#if !defined(STDNET_HAS_CSTDINT) +# if !defined(STDNET_DISABLE_CSTDINT) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define STDNET_HAS_CSTDINT 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# endif // !defined(STDNET_DISABLE_CSTDINT) +#endif // !defined(STDNET_HAS_CSTDINT) + +// Windows target. +#if !defined(STDNET_WINDOWS) +# if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +# define STDNET_WINDOWS 1 +# endif // defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +#endif // !defined(STDNET_WINDOWS) + +// Windows: target OS version. +#if defined(STDNET_WINDOWS) || defined(__CYGWIN__) +# if !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS) +# if defined(_MSC_VER) || defined(__BORLANDC__) +# pragma message( \ + "Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately. For example:\n"\ + "- add -D_WIN32_WINNT=0x0501 to the compiler command line; or\n"\ + "- add _WIN32_WINNT=0x0501 to your project's Preprocessor Definitions.\n"\ + "Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target).") +# else // defined(_MSC_VER) || defined(__BORLANDC__) +# warning Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately. +# warning For example, add -D_WIN32_WINNT=0x0501 to the compiler command line. +# warning Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target). +# endif // defined(_MSC_VER) || defined(__BORLANDC__) +# define _WIN32_WINNT 0x0501 +# endif // !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS) +# if defined(_MSC_VER) +# if defined(_WIN32) && !defined(WIN32) +# if !defined(_WINSOCK2API_) +# define WIN32 // Needed for correct types in winsock2.h +# else // !defined(_WINSOCK2API_) +# error Please define the macro WIN32 in your compiler options +# endif // !defined(_WINSOCK2API_) +# endif // defined(_WIN32) && !defined(WIN32) +# endif // defined(_MSC_VER) +# if defined(__BORLANDC__) +# if defined(__WIN32__) && !defined(WIN32) +# if !defined(_WINSOCK2API_) +# define WIN32 // Needed for correct types in winsock2.h +# else // !defined(_WINSOCK2API_) +# error Please define the macro WIN32 in your compiler options +# endif // !defined(_WINSOCK2API_) +# endif // defined(__WIN32__) && !defined(WIN32) +# endif // defined(__BORLANDC__) +# if defined(__CYGWIN__) +# if !defined(__USE_W32_SOCKETS) +# error You must add -D__USE_W32_SOCKETS to your compiler options. +# endif // !defined(__USE_W32_SOCKETS) +# endif // defined(__CYGWIN__) +#endif // defined(STDNET_WINDOWS) || defined(__CYGWIN__) + +// Windows: minimise header inclusion. +#if defined(STDNET_WINDOWS) || defined(__CYGWIN__) +# if !defined(STDNET_NO_WIN32_LEAN_AND_MEAN) +# if !defined(WIN32_LEAN_AND_MEAN) +# define WIN32_LEAN_AND_MEAN +# endif // !defined(WIN32_LEAN_AND_MEAN) +# endif // !defined(STDNET_NO_WIN32_LEAN_AND_MEAN) +#endif // defined(STDNET_WINDOWS) || defined(__CYGWIN__) + +// Windows: suppress definition of "min" and "max" macros. +#if defined(STDNET_WINDOWS) || defined(__CYGWIN__) +# if !defined(STDNET_NO_NOMINMAX) +# if !defined(NOMINMAX) +# define NOMINMAX 1 +# endif // !defined(NOMINMAX) +# endif // !defined(STDNET_NO_NOMINMAX) +#endif // defined(STDNET_WINDOWS) || defined(__CYGWIN__) + +// Windows: No ANSI API calls. +#if !defined(STDNET_NO_ANSI_APIS) +# if defined(STDNET_WINDOWS) && defined(UNDER_CE) +# define STDNET_NO_ANSI_APIS 1 +# endif // defined(STDNET_WINDOWS) && defined(UNDER_CE) +#endif // !defined(STDNET_NO_ANSI_APIS) + +// Windows: IO Completion Ports. +#if !defined(STDNET_HAS_IOCP) +# if defined(STDNET_WINDOWS) || defined(__CYGWIN__) +# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400) +# if !defined(UNDER_CE) +# if !defined(STDNET_DISABLE_IOCP) +# define STDNET_HAS_IOCP 1 +# endif // !defined(STDNET_DISABLE_IOCP) +# endif // !defined(UNDER_CE) +# endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400) +# endif // defined(STDNET_WINDOWS) || defined(__CYGWIN__) +#endif // !defined(STDNET_HAS_IOCP) + +// Linux: epoll, eventfd and timerfd. +#if defined(__linux__) +# include +# if !defined(STDNET_HAS_EPOLL) +# if !defined(STDNET_DISABLE_EPOLL) +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,45) +# define STDNET_HAS_EPOLL 1 +# endif // LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,45) +# endif // !defined(STDNET_DISABLE_EPOLL) +# endif // !defined(STDNET_HAS_EPOLL) +# if !defined(STDNET_HAS_EVENTFD) +# if !defined(STDNET_DISABLE_EVENTFD) +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) +# define STDNET_HAS_EVENTFD 1 +# endif // LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) +# endif // !defined(STDNET_DISABLE_EVENTFD) +# endif // !defined(STDNET_HAS_EVENTFD) +# if !defined(STDNET_HAS_TIMERFD) +# if defined(STDNET_HAS_EPOLL) +# if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8) +# define STDNET_HAS_TIMERFD 1 +# endif // (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8) +# endif // defined(STDNET_HAS_EPOLL) +# endif // !defined(STDNET_HAS_TIMERFD) +#endif // defined(__linux__) + +// Mac OS X, FreeBSD, NetBSD, OpenBSD: kqueue. +#if (defined(__MACH__) && defined(__APPLE__)) \ + || defined(__FreeBSD__) \ + || defined(__NetBSD__) \ + || defined(__OpenBSD__) +# if !defined(STDNET_HAS_KQUEUE) +# if !defined(STDNET_DISABLE_KQUEUE) +# define STDNET_HAS_KQUEUE 1 +# endif // !defined(STDNET_DISABLE_KQUEUE) +# endif // !defined(STDNET_HAS_KQUEUE) +#endif // (defined(__MACH__) && defined(__APPLE__)) + // || defined(__FreeBSD__) + // || defined(__NetBSD__) + // || defined(__OpenBSD__) + +// Solaris: /dev/poll. +#if defined(__sun) +# if !defined(STDNET_HAS_DEV_POLL) +# if !defined(STDNET_DISABLE_DEV_POLL) +# define STDNET_HAS_DEV_POLL 1 +# endif // !defined(STDNET_DISABLE_DEV_POLL) +# endif // !defined(STDNET_HAS_DEV_POLL) +#endif // defined(__sun) + +// Serial ports. +#if !defined(STDNET_HAS_SERIAL_PORT) +# if defined(STDNET_HAS_IOCP) \ + || !defined(STDNET_WINDOWS) && !defined(__CYGWIN__) +# if !defined(__SYMBIAN32__) +# if !defined(STDNET_DISABLE_SERIAL_PORT) +# define STDNET_HAS_SERIAL_PORT 1 +# endif // !defined(STDNET_DISABLE_SERIAL_PORT) +# endif // !defined(__SYMBIAN32__) +# endif // defined(STDNET_HAS_IOCP) + // || !defined(STDNET_WINDOWS) && !defined(__CYGWIN__) +#endif // !defined(STDNET_HAS_SERIAL_PORT) + +// Windows: stream handles. +#if !defined(STDNET_HAS_WINDOWS_STREAM_HANDLE) +# if !defined(STDNET_DISABLE_WINDOWS_STREAM_HANDLE) +# if defined(STDNET_HAS_IOCP) +# define STDNET_HAS_WINDOWS_STREAM_HANDLE 1 +# endif // defined(STDNET_HAS_IOCP) +# endif // !defined(STDNET_DISABLE_WINDOWS_STREAM_HANDLE) +#endif // !defined(STDNET_HAS_WINDOWS_STREAM_HANDLE) + +// Windows: random access handles. +#if !defined(STDNET_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) +# if !defined(STDNET_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE) +# if defined(STDNET_HAS_IOCP) +# define STDNET_HAS_WINDOWS_RANDOM_ACCESS_HANDLE 1 +# endif // defined(STDNET_HAS_IOCP) +# endif // !defined(STDNET_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE) +#endif // !defined(STDNET_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) + +// Windows: object handles. +#if !defined(STDNET_HAS_WINDOWS_OBJECT_HANDLE) +# if !defined(STDNET_DISABLE_WINDOWS_OBJECT_HANDLE) +# if defined(STDNET_WINDOWS) || defined(__CYGWIN__) +# if !defined(UNDER_CE) +# define STDNET_HAS_WINDOWS_OBJECT_HANDLE 1 +# endif // !defined(UNDER_CE) +# endif // defined(STDNET_WINDOWS) || defined(__CYGWIN__) +# endif // !defined(STDNET_DISABLE_WINDOWS_OBJECT_HANDLE) +#endif // !defined(STDNET_HAS_WINDOWS_OBJECT_HANDLE) + +// Windows: OVERLAPPED wrapper. +#if !defined(STDNET_HAS_WINDOWS_OVERLAPPED_PTR) +# if !defined(STDNET_DISABLE_WINDOWS_OVERLAPPED_PTR) +# if defined(STDNET_HAS_IOCP) +# define STDNET_HAS_WINDOWS_OVERLAPPED_PTR 1 +# endif // defined(STDNET_HAS_IOCP) +# endif // !defined(STDNET_DISABLE_WINDOWS_OVERLAPPED_PTR) +#endif // !defined(STDNET_HAS_WINDOWS_OVERLAPPED_PTR) + +// POSIX: stream-oriented file descriptors. +#if !defined(STDNET_HAS_POSIX_STREAM_DESCRIPTOR) +# if !defined(STDNET_DISABLE_POSIX_STREAM_DESCRIPTOR) +# if !defined(STDNET_WINDOWS) && !defined(__CYGWIN__) +# define STDNET_HAS_POSIX_STREAM_DESCRIPTOR 1 +# endif // !defined(STDNET_WINDOWS) && !defined(__CYGWIN__) +# endif // !defined(STDNET_DISABLE_POSIX_STREAM_DESCRIPTOR) +#endif // !defined(STDNET_HAS_POSIX_STREAM_DESCRIPTOR) + +// UNIX domain sockets. +#if !defined(STDNET_HAS_LOCAL_SOCKETS) +# if !defined(STDNET_DISABLE_LOCAL_SOCKETS) +# if !defined(STDNET_WINDOWS) && !defined(__CYGWIN__) +# define STDNET_HAS_LOCAL_SOCKETS 1 +# endif // !defined(STDNET_WINDOWS) && !defined(__CYGWIN__) +# endif // !defined(STDNET_DISABLE_LOCAL_SOCKETS) +#endif // !defined(STDNET_HAS_LOCAL_SOCKETS) + +// Can use sigaction() instead of signal(). +#if !defined(STDNET_HAS_SIGACTION) +# if !defined(STDNET_DISABLE_SIGACTION) +# if !defined(STDNET_WINDOWS) && !defined(__CYGWIN__) +# define STDNET_HAS_SIGACTION 1 +# endif // !defined(STDNET_WINDOWS) && !defined(__CYGWIN__) +# endif // !defined(STDNET_DISABLE_SIGACTION) +#endif // !defined(STDNET_HAS_SIGACTION) + +// Can use signal(). +#if !defined(STDNET_HAS_SIGNAL) +# if !defined(STDNET_DISABLE_SIGNAL) +# if !defined(UNDER_CE) +# define STDNET_HAS_SIGNAL 1 +# endif // !defined(UNDER_CE) +# endif // !defined(STDNET_DISABLE_SIGNAL) +#endif // !defined(STDNET_HAS_SIGNAL) + +// Whether standard iostreams are disabled. +//#if !defined(STDNET_NO_IOSTREAM) +//# define STDNET_NO_IOSTREAM 1 +//#endif // !defined(STDNET_NO_IOSTREAM) + +// Whether exception handling is disabled. +//#if !defined(STDNET_NO_EXCEPTIONS) +//# define STDNET_NO_EXCEPTIONS 1 +//#endif // !defined(STDNET_NO_EXCEPTIONS) + +// Whether the typeid operator is supported. +//#if !defined(STDNET_NO_TYPEID) +//# define STDNET_NO_TYPEID 1 +//#endif // !defined(STDNET_NO_TYPEID) + +// On POSIX (and POSIX-like) platforms we need to include unistd.h in order to +// get access to the various platform feature macros, e.g. to be able to test +// for threads support. +#if !defined(STDNET_HAS_UNISTD_H) +# if defined(unix) \ + || defined(__unix) \ + || defined(_XOPEN_SOURCE) \ + || defined(_POSIX_SOURCE) \ + || (defined(__MACH__) && defined(__APPLE__)) \ + || defined(__FreeBSD__) \ + || defined(__NetBSD__) \ + || defined(__OpenBSD__) \ + || defined(__linux__) +# define STDNET_HAS_UNISTD_H 1 +# endif +#endif // !defined(STDNET_HAS_UNISTD_H) +#if defined(STDNET_HAS_UNISTD_H) +# include +#endif // defined(STDNET_HAS_UNISTD_H) + +// Threads. +#if !defined(STDNET_HAS_THREADS) +# if !defined(STDNET_DISABLE_THREADS) +# if defined(_MSC_VER) && defined(_MT) +# define STDNET_HAS_THREADS 1 +# elif defined(__BORLANDC__) && defined(__MT__) +# define STDNET_HAS_THREADS 1 +# elif defined(_POSIX_THREADS) +# define STDNET_HAS_THREADS 1 +# endif // defined(_MSC_VER) && defined(_MT) +# endif // !defined(STDNET_DISABLE_THREADS) +#endif // !defined(STDNET_HAS_THREADS) + +// POSIX threads. +#if !defined(STDNET_HAS_PTHREADS) +# if defined(STDNET_HAS_THREADS) +# if defined(_POSIX_THREADS) +# define STDNET_HAS_PTHREADS 1 +# endif // defined(_POSIX_THREADS) +# endif // defined(STDNET_HAS_THREADS) +#endif // !defined(STDNET_HAS_PTHREADS) + +// Helper to prevent macro expansion. +#define STDNET_PREVENT_MACRO_SUBSTITUTION + +// Helper to define in-class constants. +#if !defined(STDNET_STATIC_CONSTANT) +# define STDNET_STATIC_CONSTANT(type, assignment) \ + static const type assignment +#endif // !defined(STDNET_STATIC_CONSTANT) + +// Microsoft Visual C++'s secure C runtime library. +#if !defined(STDNET_HAS_SECURE_RTL) +# if !defined(STDNET_DISABLE_SECURE_RTL) +# if defined(STDNET_MSVC) \ + && (STDNET_MSVC >= 1400) \ + && !defined(UNDER_CE) +# define STDNET_HAS_SECURE_RTL 1 +# endif // defined(STDNET_MSVC) + // && (STDNET_MSVC >= 1400) + // && !defined(UNDER_CE) +# endif // !defined(STDNET_DISABLE_SECURE_RTL) +#endif // !defined(STDNET_HAS_SECURE_RTL) + +// Handler hooking. Disabled for ancient Borland C++ and gcc compilers. +#if !defined(STDNET_HAS_HANDLER_HOOKS) +# if !defined(STDNET_DISABLE_HANDLER_HOOKS) +# if defined(__GNUC__) +# if (__GNUC__ >= 3) +# define STDNET_HAS_HANDLER_HOOKS 1 +# endif // (__GNUC__ >= 3) +# elif !defined(__BORLANDC__) +# define STDNET_HAS_HANDLER_HOOKS 1 +# endif // !defined(__BORLANDC__) +# endif // !defined(STDNET_DISABLE_HANDLER_HOOKS) +#endif // !defined(STDNET_HAS_HANDLER_HOOKS) + +// Support for the __thread keyword extension. +#if !defined(STDNET_DISABLE_THREAD_KEYWORD_EXTENSION) +# if defined(__linux__) +# if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) +# if ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3) +# if !defined(__INTEL_COMPILER) && !defined(__ICL) +# define STDNET_HAS_THREAD_KEYWORD_EXTENSION 1 +# elif defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1100) +# define STDNET_HAS_THREAD_KEYWORD_EXTENSION 1 +# endif // defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1100) +# endif // ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3) +# endif // defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) +# endif // defined(__linux__) +#endif // !defined(STDNET_DISABLE_THREAD_KEYWORD_EXTENSION) + +// Support for POSIX ssize_t typedef. +#if !defined(STDNET_DISABLE_SSIZE_T) +# if defined(__linux__) \ + || (defined(__MACH__) && defined(__APPLE__)) +# define STDNET_HAS_SSIZE_T 1 +# endif // defined(__linux__) + // || (defined(__MACH__) && defined(__APPLE__)) +#endif // !defined(STDNET_DISABLE_SSIZE_T) + +#endif // STDNET_DETAIL_CONFIG_HPP diff --git a/VIServer/TCPClient/TCPClient/old_win_sdk_compat.hpp b/VIServer/TCPClient/TCPClient/old_win_sdk_compat.hpp new file mode 100644 index 0000000000..c306dd7e53 --- /dev/null +++ b/VIServer/TCPClient/TCPClient/old_win_sdk_compat.hpp @@ -0,0 +1,218 @@ +// +// detail/old_win_sdk_compat.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef STDNET_DETAIL_OLD_WIN_SDK_COMPAT_HPP +#define STDNET_DETAIL_OLD_WIN_SDK_COMPAT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "config.hpp" + +#if defined(STDNET_WINDOWS) || defined(__CYGWIN__) + +// Guess whether we are building against on old Platform SDK. +#if !defined(IN6ADDR_ANY_INIT) +#define STDNET_HAS_OLD_WIN_SDK 1 +#endif // !defined(IN6ADDR_ANY_INIT) + +#if defined(STDNET_HAS_OLD_WIN_SDK) + +// Emulation of types that are missing from old Platform SDKs. +// +// N.B. this emulation is also used if building for a Windows 2000 target with +// a recent (i.e. Vista or later) SDK, as the SDK does not provide IPv6 support +// in that case. + +#include "push_options.hpp" + +namespace std { +namespace experimental { +namespace net { +namespace detail { + +enum +{ + sockaddr_storage_maxsize = 128, // Maximum size. + sockaddr_storage_alignsize = (sizeof(__int64)), // Desired alignment. + sockaddr_storage_pad1size = (sockaddr_storage_alignsize - sizeof(short)), + sockaddr_storage_pad2size = (sockaddr_storage_maxsize - + (sizeof(short) + sockaddr_storage_pad1size + sockaddr_storage_alignsize)) +}; + +struct sockaddr_storage_emulation +{ + short ss_family; + char __ss_pad1[sockaddr_storage_pad1size]; + __int64 __ss_align; + char __ss_pad2[sockaddr_storage_pad2size]; +}; + +struct in6_addr_emulation +{ + union + { + u_char Byte[16]; + u_short Word[8]; + } u; +}; + +#if !defined(s6_addr) +# define _S6_un u +# define _S6_u8 Byte +# define s6_addr _S6_un._S6_u8 +#endif // !defined(s6_addr) + +struct sockaddr_in6_emulation +{ + short sin6_family; + u_short sin6_port; + u_long sin6_flowinfo; + in6_addr_emulation sin6_addr; + u_long sin6_scope_id; +}; + +struct ipv6_mreq_emulation +{ + in6_addr_emulation ipv6mr_multiaddr; + unsigned int ipv6mr_interface; +}; + +struct addrinfo_emulation +{ + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + size_t ai_addrlen; + char* ai_canonname; + sockaddr* ai_addr; + addrinfo_emulation* ai_next; +}; + +#if !defined(AI_PASSIVE) +# define AI_PASSIVE 0x1 +#endif + +#if !defined(AI_CANONNAME) +# define AI_CANONNAME 0x2 +#endif + +#if !defined(AI_NUMERICHOST) +# define AI_NUMERICHOST 0x4 +#endif + +#if !defined(EAI_AGAIN) +# define EAI_AGAIN WSATRY_AGAIN +#endif + +#if !defined(EAI_BADFLAGS) +# define EAI_BADFLAGS WSAEINVAL +#endif + +#if !defined(EAI_FAIL) +# define EAI_FAIL WSANO_RECOVERY +#endif + +#if !defined(EAI_FAMILY) +# define EAI_FAMILY WSAEAFNOSUPPORT +#endif + +#if !defined(EAI_MEMORY) +# define EAI_MEMORY WSA_NOT_ENOUGH_MEMORY +#endif + +#if !defined(EAI_NODATA) +# define EAI_NODATA WSANO_DATA +#endif + +#if !defined(EAI_NONAME) +# define EAI_NONAME WSAHOST_NOT_FOUND +#endif + +#if !defined(EAI_SERVICE) +# define EAI_SERVICE WSATYPE_NOT_FOUND +#endif + +#if !defined(EAI_SOCKTYPE) +# define EAI_SOCKTYPE WSAESOCKTNOSUPPORT +#endif + +#if !defined(NI_NOFQDN) +# define NI_NOFQDN 0x01 +#endif + +#if !defined(NI_NUMERICHOST) +# define NI_NUMERICHOST 0x02 +#endif + +#if !defined(NI_NAMEREQD) +# define NI_NAMEREQD 0x04 +#endif + +#if !defined(NI_NUMERICSERV) +# define NI_NUMERICSERV 0x08 +#endif + +#if !defined(NI_DGRAM) +# define NI_DGRAM 0x10 +#endif + +#if !defined(IPPROTO_IPV6) +# define IPPROTO_IPV6 41 +#endif + +#if !defined(IPV6_UNICAST_HOPS) +# define IPV6_UNICAST_HOPS 4 +#endif + +#if !defined(IPV6_MULTICAST_IF) +# define IPV6_MULTICAST_IF 9 +#endif + +#if !defined(IPV6_MULTICAST_HOPS) +# define IPV6_MULTICAST_HOPS 10 +#endif + +#if !defined(IPV6_MULTICAST_LOOP) +# define IPV6_MULTICAST_LOOP 11 +#endif + +#if !defined(IPV6_JOIN_GROUP) +# define IPV6_JOIN_GROUP 12 +#endif + +#if !defined(IPV6_LEAVE_GROUP) +# define IPV6_LEAVE_GROUP 13 +#endif + +} // namespace detail +} // namespace net +} // namespace experimental +} // namespace std + +#include "pop_options.hpp" + +#endif // defined(STDNET_HAS_OLD_WIN_SDK) + +// Even newer Platform SDKs that support IPv6 may not define IPV6_V6ONLY. +#if !defined(IPV6_V6ONLY) +# define IPV6_V6ONLY 27 +#endif + +// Some SDKs (e.g. Windows CE) don't define IPPROTO_ICMPV6. +#if !defined(IPPROTO_ICMPV6) +# define IPPROTO_ICMPV6 58 +#endif + +#endif // defined(STDNET_WINDOWS) || defined(__CYGWIN__) + +#endif // STDNET_DETAIL_OLD_WIN_SDK_COMPAT_HPP diff --git a/VIServer/TCPClient/TCPClient/pop_options.hpp b/VIServer/TCPClient/TCPClient/pop_options.hpp new file mode 100644 index 0000000000..8aa375e96b --- /dev/null +++ b/VIServer/TCPClient/TCPClient/pop_options.hpp @@ -0,0 +1,98 @@ +// +// detail/pop_options.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +// No header guard + +#if defined(__COMO__) + +// Comeau C++ + +#elif defined(__DMC__) + +// Digital Mars C++ + +#elif defined(__INTEL_COMPILER) || defined(__ICL) \ + || defined(__ICC) || defined(__ECC) + +// Intel C++ + +#elif defined(__GNUC__) + +// GNU C++ + +# if defined(__MINGW32__) || defined(__CYGWIN__) +# pragma pack (pop) +# endif + +# if defined(__OBJC__) +# if !defined(__APPLE_CC__) || (__APPLE_CC__ <= 1) +# if defined(STDNET_OBJC_WORKAROUND) +# undef Protocol +# undef id +# undef STDNET_OBJC_WORKAROUND +# endif +# endif +# endif + +#elif defined(__KCC) + +// Kai C++ + +#elif defined(__sgi) + +// SGI MIPSpro C++ + +#elif defined(__DECCXX) + +// Compaq Tru64 Unix cxx + +#elif defined(__ghs) + +// Greenhills C++ + +#elif defined(__BORLANDC__) + +// Borland C++ + +# pragma option pop +# pragma nopushoptwarn +# pragma nopackwarning + +#elif defined(__MWERKS__) + +// Metrowerks CodeWarrior + +#elif defined(__SUNPRO_CC) + +// Sun Workshop Compiler C++ + +#elif defined(__HP_aCC) + +// HP aCC + +#elif defined(__MRC__) || defined(__SC__) + +// MPW MrCpp or SCpp + +#elif defined(__IBMCPP__) + +// IBM Visual Age + +#elif defined(_MSC_VER) + +// Microsoft Visual C++ +// +// Must remain the last #elif since some other vendors (Metrowerks, for example) +// also #define _MSC_VER + +# pragma warning (pop) +# pragma pack (pop) + +#endif diff --git a/VIServer/TCPClient/TCPClient/push_options.hpp b/VIServer/TCPClient/TCPClient/push_options.hpp new file mode 100644 index 0000000000..ec64373c6f --- /dev/null +++ b/VIServer/TCPClient/TCPClient/push_options.hpp @@ -0,0 +1,127 @@ +// +// detail/push_options.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +// No header guard + +#if defined(__COMO__) + +// Comeau C++ + +#elif defined(__DMC__) + +// Digital Mars C++ + +#elif defined(__INTEL_COMPILER) || defined(__ICL) \ + || defined(__ICC) || defined(__ECC) + +// Intel C++ + +#elif defined(__GNUC__) + +// GNU C++ + +# if defined(__MINGW32__) || defined(__CYGWIN__) +# pragma pack (push, 8) +# endif + +# if defined(__OBJC__) +# if !defined(__APPLE_CC__) || (__APPLE_CC__ <= 1) +# if !defined(STDNET_DISABLE_OBJC_WORKAROUND) +# if !defined(Protocol) && !defined(id) +# define Protocol cpp_Protocol +# define id cpp_id +# define STDNET_OBJC_WORKAROUND +# endif +# endif +# endif +# endif + +#elif defined(__KCC) + +// Kai C++ + +#elif defined(__sgi) + +// SGI MIPSpro C++ + +#elif defined(__DECCXX) + +// Compaq Tru64 Unix cxx + +#elif defined(__ghs) + +// Greenhills C++ + +#elif defined(__BORLANDC__) + +// Borland C++ + +# pragma option push -a8 -b -Ve- -Vx- -w-inl -vi- +# pragma nopushoptwarn +# pragma nopackwarning +# if !defined(__MT__) +# error Multithreaded RTL must be selected. +# endif // !defined(__MT__) + +#elif defined(__MWERKS__) + +// Metrowerks CodeWarrior + +#elif defined(__SUNPRO_CC) + +// Sun Workshop Compiler C++ + +#elif defined(__HP_aCC) + +// HP aCC + +#elif defined(__MRC__) || defined(__SC__) + +// MPW MrCpp or SCpp + +#elif defined(__IBMCPP__) + +// IBM Visual Age + +#elif defined(_MSC_VER) + +// Microsoft Visual C++ +// +// Must remain the last #elif since some other vendors (Metrowerks, for example) +// also #define _MSC_VER + +# pragma warning (disable:4103) +# pragma warning (push) +# pragma warning (disable:4127) +# pragma warning (disable:4180) +# pragma warning (disable:4244) +# pragma warning (disable:4355) +# pragma warning (disable:4512) +# pragma warning (disable:4675) +# if defined(_M_IX86) && defined(_Wp64) +// The /Wp64 option is broken. If you want to check 64 bit portability, use a +// 64 bit compiler! +# pragma warning (disable:4311) +# pragma warning (disable:4312) +# endif // defined(_M_IX86) && defined(_Wp64) +# pragma pack (push, 8) +// Note that if the /Og optimisation flag is enabled with MSVC6, the compiler +// has a tendency to incorrectly optimise away some calls to member template +// functions, even though those functions contain code that should not be +// optimised away! Therefore we will always disable this optimisation option +// for the MSVC6 compiler. +# if (_MSC_VER < 1300) +# pragma optimize ("g", off) +# endif +# if !defined(_MT) +# error Multithreaded RTL must be selected. +# endif // !defined(_MT) + +#endif diff --git a/VIServer/TCPClient/TCPClient/socket_types.hpp b/VIServer/TCPClient/TCPClient/socket_types.hpp new file mode 100644 index 0000000000..7f06f86b68 --- /dev/null +++ b/VIServer/TCPClient/TCPClient/socket_types.hpp @@ -0,0 +1,186 @@ +// +// detail/socket_types.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef STDNET_DETAIL_SOCKET_TYPES_HPP +#define STDNET_DETAIL_SOCKET_TYPES_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "config.hpp" + +#if defined(STDNET_WINDOWS) || defined(__CYGWIN__) +# if defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_) +# error WinSock.h has already been included +# endif // defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_) +# if defined(__BORLANDC__) +# include // Needed for __errno +# if !defined(_WSPIAPI_H_) +# define _WSPIAPI_H_ +# define STDNET_WSPIAPI_H_DEFINED +# endif // !defined(_WSPIAPI_H_) +# endif // defined(__BORLANDC__) +# include +# include +# include +# if defined(STDNET_WSPIAPI_H_DEFINED) +# undef _WSPIAPI_H_ +# undef STDNET_WSPIAPI_H_DEFINED +# endif // defined(STDNET_WSPIAPI_H_DEFINED) +# if !defined(STDNET_NO_DEFAULT_LINKED_LIBS) +# if defined(UNDER_CE) +# pragma comment(lib, "ws2.lib") +# elif defined(_MSC_VER) || defined(__BORLANDC__) +# pragma comment(lib, "ws2_32.lib") +# pragma comment(lib, "mswsock.lib") +# endif // defined(_MSC_VER) || defined(__BORLANDC__) +# endif // !defined(STDNET_NO_DEFAULT_LINKED_LIBS) +# include "old_win_sdk_compat.hpp" +#else +# include +# if !defined(__SYMBIAN32__) +# include +# endif +# include +# include +# include +# if defined(__hpux) +# include +# endif +# if !defined(__hpux) || defined(__SELECT) +# include +# endif +# include +# include +# include +# include +# if !defined(__SYMBIAN32__) +# include +# endif +# include +# include +# include +# include +# if defined(__sun) +# include +# include +# endif +#endif + +#include "push_options.hpp" + +namespace std { +namespace experimental { +namespace net { +namespace detail { + +#if defined(STDNET_WINDOWS) || defined(__CYGWIN__) +typedef SOCKET socket_type; +const SOCKET invalid_socket = INVALID_SOCKET; +const int socket_error_retval = SOCKET_ERROR; +const int max_addr_v4_str_len = 256; +const int max_addr_v6_str_len = 256; +typedef sockaddr socket_addr_type; +typedef in_addr in4_addr_type; +typedef ip_mreq in4_mreq_type; +typedef sockaddr_in sockaddr_in4_type; +# if defined(STDNET_HAS_OLD_WIN_SDK) +typedef in6_addr_emulation in6_addr_type; +typedef ipv6_mreq_emulation in6_mreq_type; +typedef sockaddr_in6_emulation sockaddr_in6_type; +typedef sockaddr_storage_emulation sockaddr_storage_type; +typedef addrinfo_emulation addrinfo_type; +# else +typedef in6_addr in6_addr_type; +typedef ipv6_mreq in6_mreq_type; +typedef sockaddr_in6 sockaddr_in6_type; +typedef sockaddr_storage sockaddr_storage_type; +typedef addrinfo addrinfo_type; +# endif +typedef unsigned long ioctl_arg_type; +typedef u_long u_long_type; +typedef u_short u_short_type; +typedef int signed_size_type; +const int shutdown_receive = SD_RECEIVE; +const int shutdown_send = SD_SEND; +const int shutdown_both = SD_BOTH; +const int message_peek = MSG_PEEK; +const int message_out_of_band = MSG_OOB; +const int message_do_not_route = MSG_DONTROUTE; +const int message_end_of_record = 0; // Not supported on Windows. +# if defined (_WIN32_WINNT) +const int max_iov_len = 64; +# else +const int max_iov_len = 16; +# endif +#else +typedef int socket_type; +const int invalid_socket = -1; +const int socket_error_retval = -1; +const int max_addr_v4_str_len = INET_ADDRSTRLEN; +#if defined(INET6_ADDRSTRLEN) +const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE; +#else // defined(INET6_ADDRSTRLEN) +const int max_addr_v6_str_len = 256; +#endif // defined(INET6_ADDRSTRLEN) +typedef sockaddr socket_addr_type; +typedef in_addr in4_addr_type; +# if defined(__hpux) +// HP-UX doesn't provide ip_mreq when _XOPEN_SOURCE_EXTENDED is defined. +struct in4_mreq_type +{ + struct in_addr imr_multiaddr; + struct in_addr imr_interface; +}; +# else +typedef ip_mreq in4_mreq_type; +# endif +typedef sockaddr_in sockaddr_in4_type; +typedef in6_addr in6_addr_type; +typedef ipv6_mreq in6_mreq_type; +typedef sockaddr_in6 sockaddr_in6_type; +typedef sockaddr_storage sockaddr_storage_type; +typedef sockaddr_un sockaddr_un_type; +typedef addrinfo addrinfo_type; +typedef int ioctl_arg_type; +typedef uint32_t u_long_type; +typedef uint16_t u_short_type; +#if defined(STDNET_HAS_SSIZE_T) +typedef ssize_t signed_size_type; +#else // defined(STDNET_HAS_SSIZE_T) +typedef int signed_size_type; +#endif // defined(STDNET_HAS_SSIZE_T) +const int shutdown_receive = SHUT_RD; +const int shutdown_send = SHUT_WR; +const int shutdown_both = SHUT_RDWR; +const int message_peek = MSG_PEEK; +const int message_out_of_band = MSG_OOB; +const int message_do_not_route = MSG_DONTROUTE; +const int message_end_of_record = MSG_EOR; +# if defined(IOV_MAX) +const int max_iov_len = IOV_MAX; +# else +// POSIX platforms are not required to define IOV_MAX. +const int max_iov_len = 16; +# endif +#endif +const int custom_socket_option_level = 0xA5100000; +const int enable_connection_aborted_option = 1; +const int always_fail_option = 2; + +} // namespace detail +} // namespace net +} // namespace experimental +} // namespace std + +#include "pop_options.hpp" + +#endif // STDNET_DETAIL_SOCKET_TYPES_HPP diff --git a/VIServer/TCPClient/TCPClient/winsock_init.hpp b/VIServer/TCPClient/TCPClient/winsock_init.hpp new file mode 100644 index 0000000000..1dbe8e0ed8 --- /dev/null +++ b/VIServer/TCPClient/TCPClient/winsock_init.hpp @@ -0,0 +1,86 @@ +// +// detail/winsock_init.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef STDNET_DETAIL_WINSOCK_INIT_HPP +#define STDNET_DETAIL_WINSOCK_INIT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "config.hpp" + +#if defined(STDNET_WINDOWS) || defined(__CYGWIN__) + +#include "push_options.hpp" + + +class winsock_init_base +{ +protected: + // Structure to track result of initialisation and number of uses. POD is used + // to ensure that the values are zero-initialised prior to any code being run. + struct data + { + long init_count_; + long result_; + }; + + STDNET_DECL static void startup(data& d, + unsigned char major, unsigned char minor); + + STDNET_DECL static void cleanup(data& d); + + STDNET_DECL static void throw_on_error(data& d); +}; + +template +class winsock_init : private winsock_init_base +{ +public: + winsock_init(bool allow_throw = true) + { + startup(data_, Major, Minor); + if (allow_throw) + throw_on_error(data_); + } + + winsock_init(const winsock_init&) + { + startup(data_, Major, Minor); + throw_on_error(data_); + } + + ~winsock_init() + { + cleanup(data_); + } + +private: + static data data_; +}; + +template +winsock_init_base::data winsock_init::data_; + +// Static variable to ensure that winsock is initialised before main, and +// therefore before any other threads can get started. +static const winsock_init<>& winsock_init_instance = winsock_init<>(false); + + +#include "pop_options.hpp" + +#if defined(STDNET_HEADER_ONLY) +# include "winsock_init.ipp" +#endif // defined(STDNET_HEADER_ONLY) + +#endif // defined(STDNET_WINDOWS) || defined(__CYGWIN__) + +#endif // STDNET_DETAIL_WINSOCK_INIT_HPP diff --git a/VIServer/TCPClient/TCPClient/winsock_init.ipp b/VIServer/TCPClient/TCPClient/winsock_init.ipp new file mode 100644 index 0000000000..7f923e7def --- /dev/null +++ b/VIServer/TCPClient/TCPClient/winsock_init.ipp @@ -0,0 +1,59 @@ +// +// detail/impl/winsock_init.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef STDNET_DETAIL_IMPL_WINSOCK_INIT_IPP +#define STDNET_DETAIL_IMPL_WINSOCK_INIT_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "config.hpp" + +#if defined(STDNET_WINDOWS) || defined(__CYGWIN__) + +#include "socket_types.hpp" +#include "winsock_init.hpp" +#include "push_options.hpp" + + +void winsock_init_base::startup(data& d, + unsigned char major, unsigned char minor) +{ + if (::InterlockedIncrement(&d.init_count_) == 1) + { + WSADATA wsa_data; + long result = ::WSAStartup(MAKEWORD(major, minor), &wsa_data); + ::InterlockedExchange(&d.result_, result); + } +} + +void winsock_init_base::cleanup(data& d) +{ + if (::InterlockedDecrement(&d.init_count_) == 0) + { + ::WSACleanup(); + } +} + +void winsock_init_base::throw_on_error(data& d) +{ + long result = ::InterlockedExchangeAdd(&d.result_, 0); + if (result != 0) + { + + } +} + +#include "pop_options.hpp" + +#endif // defined(STDNET_WINDOWS) || defined(__CYGWIN__) + +#endif // STDNET_DETAIL_IMPL_WINSOCK_INIT_IPP diff --git a/VIServer/VIServer.sln b/VIServer/VIServer.sln new file mode 100644 index 0000000000..c36af032ca --- /dev/null +++ b/VIServer/VIServer.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.40629.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VIServer", "VIServer\VIServer.vcxproj", "{472B1E39-7F8A-4E48-B840-1009C7705F63}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {472B1E39-7F8A-4E48-B840-1009C7705F63}.Debug|Win32.ActiveCfg = Debug|Win32 + {472B1E39-7F8A-4E48-B840-1009C7705F63}.Debug|Win32.Build.0 = Debug|Win32 + {472B1E39-7F8A-4E48-B840-1009C7705F63}.Release|Win32.ActiveCfg = Release|Win32 + {472B1E39-7F8A-4E48-B840-1009C7705F63}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/VIServer/VIServer/Generic.props b/VIServer/VIServer/Generic.props new file mode 100644 index 0000000000..9e9ab1f78f --- /dev/null +++ b/VIServer/VIServer/Generic.props @@ -0,0 +1,26 @@ + + + + + $(ProjectDir)../Classes/ + + + $(SolutionDir)publish/Temp/$(Configuration)\ + $(SolutionDir)publish/$(Configuration)\ + + + + WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + $(SOURCE_ROOT);$(SOURCE_ROOT)Networking/IPAddress/;$(SOURCE_ROOT)FoundationKit/Platform/windows/system;$(SOURCE_ROOT)FoundationKit/external/unzip;$(SOURCE_ROOT)FoundationKit/external/zlib;%(AdditionalIncludeDirectories) + + + libzlib.lib;%(AdditionalDependencies) + $(SOURCE_ROOT)FoundationKit/external/zlib;%(AdditionalLibraryDirectories) + + + + + $(SOURCE_ROOT) + + + \ No newline at end of file diff --git a/VIServer/VIServer/VIServer.vcxproj b/VIServer/VIServer/VIServer.vcxproj new file mode 100644 index 0000000000..eeb0425407 --- /dev/null +++ b/VIServer/VIServer/VIServer.vcxproj @@ -0,0 +1,184 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {472B1E39-7F8A-4E48-B840-1009C7705F63} + Win32Proj + VIServer + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + true + + + Console + true + + + if not exist "$(OutDir)" mkdir "$(OutDir)" +xcopy /Y /Q "$(ProjectDir)..\Classes\FoundationKit\external\zlib\*.dll" "$(OutDir)" +xcopy /Y /Q "$(ProjectDir)..\Classes\FoundationKit\external\zlib\*.lib" "$(OutDir)" + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + if not exist "$(OutDir)" mkdir "$(OutDir)" +xcopy /Y /Q "$(ProjectDir)..\Classes\FoundationKit\external\zlib\*.dll" "$(OutDir)" +xcopy /Y /Q "$(ProjectDir)..\Classes\FoundationKit\external\zlib\*.lib" "$(OutDir)" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/VIServer/VIServer/VIServer.vcxproj.filters b/VIServer/VIServer/VIServer.vcxproj.filters new file mode 100644 index 0000000000..ad857d1c94 --- /dev/null +++ b/VIServer/VIServer/VIServer.vcxproj.filters @@ -0,0 +1,305 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {a35a63cd-77a8-4a40-ae75-2c2e158f35f6} + + + {9a198d4a-0aa9-4f91-8b59-a0639eb55d4f} + + + {11660fbf-0eee-41aa-9527-1bcc0bd9f403} + + + {7263a859-6b0c-47a9-a92e-ea4064decffb} + + + {31557a42-31fe-409c-96a8-8b934acbfb82} + + + {c9dc7a92-6656-4e10-9353-46d381de1497} + + + {42bf4d3c-2016-4c7c-9deb-c7091a87621e} + + + {6aa2c1b0-22e2-4999-b03a-95fc5f7eab87} + + + {e24ee0fd-ef6c-4993-b352-7fbe64f657a7} + + + {9be781a1-5cb6-4aa8-982c-8fc1ca68ca37} + + + {ec8ffae8-f1f6-4eb9-b3fd-9d00b337789d} + + + + + Classes\Networking + + + Classes\Networking + + + Classes\FoundationKit + + + Classes\FoundationKit\Foundation + + + Classes\FoundationKit\external\ConvertUTF + + + Classes\FoundationKit\external\ConvertUTF + + + Classes\FoundationKit\Base + + + Classes\FoundationKit\Base + + + Classes\FoundationKit\Foundation + + + Classes\FoundationKit\Base + + + Classes\FoundationKit\Platform + + + Classes\FoundationKit\Platform + + + Classes\FoundationKit\Platform\windows + + + Classes\FoundationKit\Platform\windows + + + Classes\FoundationKit\Platform\windows + + + Classes\FoundationKit\Platform\windows + + + Classes\FoundationKit\Crypto + + + Classes\FoundationKit\Crypto + + + Classes + + + Classes\FoundationKit\Foundation + + + Classes\FoundationKit\Base + + + Classes\FoundationKit\external\unzip + + + Classes\FoundationKit\external\unzip + + + Classes\FoundationKit\external\unzip + + + Classes + + + Classes\FoundationKit\Base + + + Classes\Networking + + + Classes\Networking + + + Classes\FoundationKit\Base + + + Classes + + + Classes + + + Classes\FoundationKit\Foundation + + + + + Classes\Networking + + + Classes\Networking + + + Classes\FoundationKit + + + Classes\FoundationKit\Base + + + Classes\FoundationKit\Foundation + + + Classes\FoundationKit\external\ConvertUTF + + + Classes\FoundationKit\Base + + + Classes\FoundationKit\Base + + + Classes\FoundationKit\Base + + + Classes\FoundationKit\Foundation + + + Classes\FoundationKit\Foundation + + + Classes\FoundationKit\Base + + + Classes\FoundationKit\Base + + + Classes\FoundationKit\Platform + + + Classes\FoundationKit\Platform + + + Classes\FoundationKit\Platform + + + Classes\FoundationKit\Platform + + + Classes\FoundationKit\Platform\windows + + + Classes\FoundationKit\Platform\windows + + + Classes\FoundationKit\Crypto + + + Classes\FoundationKit\Crypto + + + Classes\FoundationKit\Crypto + + + Classes\FoundationKit\Crypto + + + Classes\Networking + + + Classes\Networking + + + Classes\Networking + + + Classes\Networking + + + Classes\Networking + + + Classes\Networking + + + Classes\Networking + + + Classes\Networking + + + Classes\Networking + + + Classes\FoundationKit\Foundation + + + Classes\Networking + + + Classes\FoundationKit\Foundation + + + Classes\FoundationKit\Base + + + Classes\FoundationKit\external\unzip + + + Classes\FoundationKit\external\unzip + + + Classes\FoundationKit\external\unzip + + + Classes + + + Classes\FoundationKit\Base + + + Classes\FoundationKit\Foundation + + + Classes\Networking + + + Classes\Networking + + + Classes\FoundationKit\Base + + + Classes + + + Classes + + + Classes + + + Classes + + + Classes\FoundationKit\Base + + + + + Classes\Networking + + + \ No newline at end of file diff --git a/VIServer/config b/VIServer/config new file mode 100644 index 0000000000..3b1ef1dc8e --- /dev/null +++ b/VIServer/config @@ -0,0 +1,13 @@ +[core] + repositoryformatversion = 0 + filemode = false + bare = false + logallrefupdates = true + symlinks = false + ignorecase = true +[remote "origin"] + url = https://github.com/losemymind/VIServer.git + fetch = +refs/heads/*:refs/remotes/origin/* +[branch "master"] + remote = origin + merge = refs/heads/master diff --git a/WIN32/ALL_BUILD.vcxproj b/WIN32/ALL_BUILD.vcxproj new file mode 100644 index 0000000000..0b045203b0 --- /dev/null +++ b/WIN32/ALL_BUILD.vcxproj @@ -0,0 +1,284 @@ + + + + x64 + + + + Debug + Win32 + + + Release + Win32 + + + MinSizeRel + Win32 + + + RelWithDebInfo + Win32 + + + + {E6C3FF0A-B39E-3D38-A718-D638CC0CAEEE} + 10.0.17763.0 + Win32Proj + Win32 + ALL_BUILD + NoUpgrade + + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + + + + %(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + %(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + %(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + %(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + Building Custom Rule E:/netttttt/http/zhangbincpprestsdk/CMakeLists.txt + setlocal +"D:\Program Files\CMake\bin\cmake.exe" -SE:/netttttt/http/zhangbincpprestsdk -BE:/netttttt/http/zhangbincpprestsdk/WIN32 --check-stamp-file E:/netttttt/http/zhangbincpprestsdk/WIN32/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + E:/netttttt/http/zhangbincpprestsdk/CMakeLists.txt;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeGenericSystem.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeInitializeConfigs.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeSystemSpecificInformation.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeSystemSpecificInitialize.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Platform\Windows.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Platform\WindowsPaths.cmake;E:\netttttt\http\zhangbincpprestsdk\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\3.14.0\CMakeSystem.cmake;E:\netttttt\http\zhangbincpprestsdk\CMakeLists.txt;%(AdditionalInputs) + E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\generate.stamp + false + Building Custom Rule E:/netttttt/http/zhangbincpprestsdk/CMakeLists.txt + setlocal +"D:\Program Files\CMake\bin\cmake.exe" -SE:/netttttt/http/zhangbincpprestsdk -BE:/netttttt/http/zhangbincpprestsdk/WIN32 --check-stamp-file E:/netttttt/http/zhangbincpprestsdk/WIN32/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + E:/netttttt/http/zhangbincpprestsdk/CMakeLists.txt;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeGenericSystem.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeInitializeConfigs.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeSystemSpecificInformation.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeSystemSpecificInitialize.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Platform\Windows.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Platform\WindowsPaths.cmake;E:\netttttt\http\zhangbincpprestsdk\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\3.14.0\CMakeSystem.cmake;E:\netttttt\http\zhangbincpprestsdk\CMakeLists.txt;%(AdditionalInputs) + E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\generate.stamp + false + Building Custom Rule E:/netttttt/http/zhangbincpprestsdk/CMakeLists.txt + setlocal +"D:\Program Files\CMake\bin\cmake.exe" -SE:/netttttt/http/zhangbincpprestsdk -BE:/netttttt/http/zhangbincpprestsdk/WIN32 --check-stamp-file E:/netttttt/http/zhangbincpprestsdk/WIN32/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + E:/netttttt/http/zhangbincpprestsdk/CMakeLists.txt;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeGenericSystem.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeInitializeConfigs.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeSystemSpecificInformation.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeSystemSpecificInitialize.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Platform\Windows.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Platform\WindowsPaths.cmake;E:\netttttt\http\zhangbincpprestsdk\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\3.14.0\CMakeSystem.cmake;E:\netttttt\http\zhangbincpprestsdk\CMakeLists.txt;%(AdditionalInputs) + E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\generate.stamp + false + Building Custom Rule E:/netttttt/http/zhangbincpprestsdk/CMakeLists.txt + setlocal +"D:\Program Files\CMake\bin\cmake.exe" -SE:/netttttt/http/zhangbincpprestsdk -BE:/netttttt/http/zhangbincpprestsdk/WIN32 --check-stamp-file E:/netttttt/http/zhangbincpprestsdk/WIN32/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + E:/netttttt/http/zhangbincpprestsdk/CMakeLists.txt;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeGenericSystem.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeInitializeConfigs.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeSystemSpecificInformation.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeSystemSpecificInitialize.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Platform\Windows.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Platform\WindowsPaths.cmake;E:\netttttt\http\zhangbincpprestsdk\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\3.14.0\CMakeSystem.cmake;E:\netttttt\http\zhangbincpprestsdk\CMakeLists.txt;%(AdditionalInputs) + E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\generate.stamp + false + + + + + + + {A176657F-0AA3-398F-8CF1-46712FD79F2B} + ZERO_CHECK + false + Never + + + {DFC1F0B0-A588-3F9B-9CAD-11938C1F32AC} + BingRequest + false + Never + + + {FB3CB569-9342-31EE-A902-DEEA05F1B7D5} + SearchFile + false + Never + + + {71D26AC8-A3F9-325F-A3B8-3AF09DCFE994} + blackjackclient + false + Never + + + {E5C90FD6-9338-3971-BDBE-8C0DD7E28A01} + blackjackserver + false + Never + + + {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A} + common_utilities + false + Never + + + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} + cpprest + false + Never + + + {42513BC6-0B70-3C14-B3C5-4BC7E1BC0650} + httpclient_test + false + Never + + + {4362448C-BE8F-36A3-9B0E-50611BD41CF1} + httplistener_test + false + Never + + + {5E524D44-C5BF-336D-B812-E13DBC6B94B6} + httptest_utilities + false + Never + + + {1C9DD759-1582-3F76-91A7-E2E93ED3EDA7} + json_test + false + Never + + + {F998D6CB-C9D6-3B52-85BF-503E8965DD7E} + oauth1client + false + Never + + + {922B451B-BAFA-3F9B-803B-54138CE39381} + oauth2client + false + Never + + + {D6297D20-59AF-3E27-83CC-DE1EA62B27CE} + pplx_test + false + Never + + + {04AA7FE2-B767-3EE0-9607-97CE5A999562} + streams_test + false + Never + + + {8EF7FEFB-B31C-3709-B1A3-1FCAB22D3D51} + test_runner + false + Never + + + {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF} + unittestpp + false + Never + + + {25A5C8EB-A739-30EA-AE01-4DDC56266398} + uri_test + false + Never + + + {7BFCA077-2FEF-34D5-8A79-1F8F4D3022E4} + utils_test + false + Never + + + + + + \ No newline at end of file diff --git a/WIN32/ALL_BUILD.vcxproj.filters b/WIN32/ALL_BUILD.vcxproj.filters new file mode 100644 index 0000000000..a2f624dc3c --- /dev/null +++ b/WIN32/ALL_BUILD.vcxproj.filters @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/WIN32/ALL_BUILD.vcxproj.user b/WIN32/ALL_BUILD.vcxproj.user new file mode 100644 index 0000000000..88a550947e --- /dev/null +++ b/WIN32/ALL_BUILD.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/WIN32/CMakeCache.txt b/WIN32/CMakeCache.txt new file mode 100644 index 0000000000..4a0dbd9c05 --- /dev/null +++ b/WIN32/CMakeCache.txt @@ -0,0 +1,588 @@ +# This is the CMakeCache file. +# For build in directory: e:/netttttt/http/zhangbincpprestsdk/WIN32 +# It was generated by CMake: D:/Program Files/CMake/bin/cmake.exe +# You can edit this file to change values found and used by cmake. +# If you do not want to change any of the values, simply exit the editor. +# If you do want to change a value, simply edit, save, and exit the editor. +# The syntax for the file is as follows: +# KEY:TYPE=VALUE +# KEY is the name of a variable in the cache. +# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. +# VALUE is the current value for the KEY. + +######################## +# EXTERNAL cache entries +######################## + +BOOST_LIBRARYDIR:PATH=E:/edu100dev/100protosdkPC/eduprotosdk/depends/dw3rd/zlib2015-1.2.5/lib/release + +BOOST_ROOT:PATH=E:/edu100dev/100protosdkPC/eduprotosdk/depends/dw3rd/boost2015-1.66.0.140 + +//Build sample applications. +BUILD_SAMPLES:BOOL=ON + +//Build shared libraries +BUILD_SHARED_LIBS:BOOL=ON + +//Build tests. +BUILD_TESTS:BOOL=ON + +//Boost date_time library (debug) +Boost_DATE_TIME_LIBRARY_DEBUG:FILEPATH=Boost_DATE_TIME_LIBRARY_DEBUG-NOTFOUND + +//Boost date_time library (release) +Boost_DATE_TIME_LIBRARY_RELEASE:FILEPATH=Boost_DATE_TIME_LIBRARY_RELEASE-NOTFOUND + +//The directory containing a CMake configuration file for Boost. +Boost_DIR:PATH=Boost_DIR-NOTFOUND + +//Path to a file. +Boost_INCLUDE_DIR:PATH=E:/edu100dev/100protosdkPC/eduprotosdk/depends/dw3rd/boost2015-1.66.0.140/include + +//Boost regex library (debug) +Boost_REGEX_LIBRARY_DEBUG:FILEPATH=Boost_REGEX_LIBRARY_DEBUG-NOTFOUND + +//Boost regex library (release) +Boost_REGEX_LIBRARY_RELEASE:FILEPATH=Boost_REGEX_LIBRARY_RELEASE-NOTFOUND + +//Boost system library (debug) +Boost_SYSTEM_LIBRARY_DEBUG:FILEPATH=Boost_SYSTEM_LIBRARY_DEBUG-NOTFOUND + +//Boost system library (release) +Boost_SYSTEM_LIBRARY_RELEASE:FILEPATH=Boost_SYSTEM_LIBRARY_RELEASE-NOTFOUND + +//Link against boost statically. +Boost_USE_STATIC_LIBS:BOOL=OFF + +//Semicolon separated list of supported configuration types, only +// supports Debug, Release, MinSizeRel, and RelWithDebInfo, anything +// else will be ignored. +CMAKE_CONFIGURATION_TYPES:STRING=Debug;Release;MinSizeRel;RelWithDebInfo + +//Flags used by the CXX compiler during all build types. +CMAKE_CXX_FLAGS:STRING=/DWIN32 /D_WINDOWS /W3 /GR /EHsc + +//Flags used by the CXX compiler during DEBUG builds. +CMAKE_CXX_FLAGS_DEBUG:STRING=/MDd /Zi /Ob0 /Od /RTC1 + +//Flags used by the CXX compiler during MINSIZEREL builds. +CMAKE_CXX_FLAGS_MINSIZEREL:STRING=/MD /O1 /Ob1 /DNDEBUG + +//Flags used by the CXX compiler during RELEASE builds. +CMAKE_CXX_FLAGS_RELEASE:STRING=/MD /O2 /Ob2 /DNDEBUG + +//Flags used by the CXX compiler during RELWITHDEBINFO builds. +CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=/MD /Zi /O2 /Ob1 /DNDEBUG + +//Libraries linked by default with all C++ applications. +CMAKE_CXX_STANDARD_LIBRARIES:STRING=kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib + +//Default filename postfix for libraries under configuration DEBUG +CMAKE_DEBUG_POSTFIX:STRING=d + +//Flags used by the linker during all build types. +CMAKE_EXE_LINKER_FLAGS:STRING=/machine:X86 + +//Flags used by the linker during DEBUG builds. +CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING=/debug /INCREMENTAL + +//Flags used by the linker during MINSIZEREL builds. +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO + +//Flags used by the linker during RELEASE builds. +CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO + +//Flags used by the linker during RELWITHDEBINFO builds. +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING=/debug /INCREMENTAL + +//User executables (bin) +CMAKE_INSTALL_BINDIR:PATH=bin + +//Read-only architecture-independent data (DATAROOTDIR) +CMAKE_INSTALL_DATADIR:PATH= + +//Read-only architecture-independent data root (share) +CMAKE_INSTALL_DATAROOTDIR:PATH=share + +//Documentation root (DATAROOTDIR/doc/PROJECT_NAME) +CMAKE_INSTALL_DOCDIR:PATH= + +//C header files (include) +CMAKE_INSTALL_INCLUDEDIR:PATH=include + +//Info documentation (DATAROOTDIR/info) +CMAKE_INSTALL_INFODIR:PATH= + +//Object code libraries (lib) +CMAKE_INSTALL_LIBDIR:PATH=lib + +//Program executables (libexec) +CMAKE_INSTALL_LIBEXECDIR:PATH=libexec + +//Locale-dependent data (DATAROOTDIR/locale) +CMAKE_INSTALL_LOCALEDIR:PATH= + +//Modifiable single-machine data (var) +CMAKE_INSTALL_LOCALSTATEDIR:PATH=var + +//Man documentation (DATAROOTDIR/man) +CMAKE_INSTALL_MANDIR:PATH= + +//C header files for non-gcc (/usr/include) +CMAKE_INSTALL_OLDINCLUDEDIR:PATH=/usr/include + +//Install path prefix, prepended onto install directories. +CMAKE_INSTALL_PREFIX:PATH=E:/netttttt/http/zhangbincpprestsdk/cpprestsdk-root + +//Run-time variable data (LOCALSTATEDIR/run) +CMAKE_INSTALL_RUNSTATEDIR:PATH= + +//System admin executables (sbin) +CMAKE_INSTALL_SBINDIR:PATH=sbin + +//Modifiable architecture-independent data (com) +CMAKE_INSTALL_SHAREDSTATEDIR:PATH=com + +//Read-only single-machine data (etc) +CMAKE_INSTALL_SYSCONFDIR:PATH=etc + +//Path to a program. +CMAKE_LINKER:FILEPATH=C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64_x86/link.exe + +//Flags used by the linker during the creation of modules during +// all build types. +CMAKE_MODULE_LINKER_FLAGS:STRING=/machine:X86 + +//Flags used by the linker during the creation of modules during +// DEBUG builds. +CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING=/debug /INCREMENTAL + +//Flags used by the linker during the creation of modules during +// MINSIZEREL builds. +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO + +//Flags used by the linker during the creation of modules during +// RELEASE builds. +CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO + +//Flags used by the linker during the creation of modules during +// RELWITHDEBINFO builds. +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING=/debug /INCREMENTAL + +//Path to a program. +CMAKE_MT:FILEPATH=CMAKE_MT-NOTFOUND + +//Value Computed by CMake +CMAKE_PROJECT_DESCRIPTION:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_HOMEPAGE_URL:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_NAME:STATIC=cpprestsdk-root + +//RC compiler +CMAKE_RC_COMPILER:FILEPATH=rc + +//Flags for Windows Resource Compiler during all build types. +CMAKE_RC_FLAGS:STRING=/DWIN32 + +//Flags for Windows Resource Compiler during DEBUG builds. +CMAKE_RC_FLAGS_DEBUG:STRING=/D_DEBUG + +//Flags for Windows Resource Compiler during MINSIZEREL builds. +CMAKE_RC_FLAGS_MINSIZEREL:STRING= + +//Flags for Windows Resource Compiler during RELEASE builds. +CMAKE_RC_FLAGS_RELEASE:STRING= + +//Flags for Windows Resource Compiler during RELWITHDEBINFO builds. +CMAKE_RC_FLAGS_RELWITHDEBINFO:STRING= + +//Flags used by the linker during the creation of shared libraries +// during all build types. +CMAKE_SHARED_LINKER_FLAGS:STRING=/machine:X86 + +//Flags used by the linker during the creation of shared libraries +// during DEBUG builds. +CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING=/debug /INCREMENTAL + +//Flags used by the linker during the creation of shared libraries +// during MINSIZEREL builds. +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO + +//Flags used by the linker during the creation of shared libraries +// during RELEASE builds. +CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO + +//Flags used by the linker during the creation of shared libraries +// during RELWITHDEBINFO builds. +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING=/debug /INCREMENTAL + +//If set, runtime paths are not added when installing shared libraries, +// but are added when building. +CMAKE_SKIP_INSTALL_RPATH:BOOL=OFF + +//If set, runtime paths are not added when using shared libraries. +CMAKE_SKIP_RPATH:BOOL=OFF + +//Flags used by the linker during the creation of static libraries +// during all build types. +CMAKE_STATIC_LINKER_FLAGS:STRING=/machine:X86 + +//Flags used by the linker during the creation of static libraries +// during DEBUG builds. +CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of static libraries +// during MINSIZEREL builds. +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELEASE builds. +CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELWITHDEBINFO builds. +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//If this value is on, makefiles will be generated without the +// .SILENT directive, and all commands will be echoed to the console +// during the make. This is useful for debugging only. With Visual +// Studio IDE projects all commands are done without /nologo. +CMAKE_VERBOSE_MAKEFILE:BOOL=OFF + +//Postfix tag for the cpprest abi +CPPREST_ABI_TAG:STRING=140_2_10 + +//Exclude Brotli compression functionality. +CPPREST_EXCLUDE_BROTLI:BOOL=ON + +//Exclude compression functionality. +CPPREST_EXCLUDE_COMPRESSION:BOOL=OFF + +//Exclude websockets functionality. +CPPREST_EXCLUDE_WEBSOCKETS:BOOL=ON + +//Directory to install CMake config files. +CPPREST_EXPORT_DIR:STRING=cpprestsdk + +//Internal use. +CPPREST_FILEIO_IMPL:STRING=win32 + +//Internal use. +CPPREST_HTTP_CLIENT_IMPL:STRING=winhttp + +//Internal use. +CPPREST_HTTP_LISTENER_IMPL:STRING=httpsys + +//Add install commands. +CPPREST_INSTALL:BOOL=ON + +//Install header files. +CPPREST_INSTALL_HEADERS:BOOL=ON + +//Internal use. +CPPREST_PPLX_IMPL:STRING=win + +//Internal use. +CPPREST_WEBSOCKETS_IMPL:STRING=wspp + +//Path to a library. +LIB_EAY_DEBUG:FILEPATH=E:/edu100dev/100protosdkPC/eduprotosdk/depends/dw3rd/openssl2015-1.0.0d_vs2015/lib/debug + +//Path to a library. +LIB_EAY_LIBRARY_DEBUG:FILEPATH=LIB_EAY_LIBRARY_DEBUG-NOTFOUND + +//Path to a library. +LIB_EAY_LIBRARY_RELEASE:FILEPATH=LIB_EAY_LIBRARY_RELEASE-NOTFOUND + +//Path to a library. +LIB_EAY_RELEASE:FILEPATH=E:\edu100dev\100protosdkPC\eduprotosdk\depends\dw3rd\openssl2015-1.0.0d_vs2015\lib\release + +//Path to a file. +OPENSSL_INCLUDE_DIR:PATH=E:\edu100dev\100protosdkPC\eduprotosdk\depends\dw3rd\openssl2015-1.0.0d_vs2015\include + +//Path to a library. +SSL_EAY_DEBUG:FILEPATH=E:\edu100dev\100protosdkPC\eduprotosdk\depends\dw3rd\openssl2015-1.0.0d_vs2015\lib\debug + +//Path to a library. +SSL_EAY_LIBRARY_DEBUG:FILEPATH=SSL_EAY_LIBRARY_DEBUG-NOTFOUND + +//Path to a library. +SSL_EAY_LIBRARY_RELEASE:FILEPATH=SSL_EAY_LIBRARY_RELEASE-NOTFOUND + +//Path to a library. +SSL_EAY_RELEASE:FILEPATH=E:\edu100dev\100protosdkPC\eduprotosdk\depends\dw3rd\openssl2015-1.0.0d_vs2015\lib\release + +//Treat Warnings as Errors. +WERROR:BOOL=ON + +//Path to a file. +ZLIB_INCLUDE_DIR:PATH=C:/Strawberry/c/include + +ZLIB_LIBRARY:PATH=E:/edu100dev/100protosdkPC/eduprotosdk/depends/dw3rd/zlib2015-1.2.5/lib/release + +//Path to a library. +ZLIB_LIBRARY_DEBUG:FILEPATH=ZLIB_LIBRARY_DEBUG-NOTFOUND + +//Path to a library. +ZLIB_LIBRARY_RELEASE:FILEPATH=ZLIB_LIBRARY_RELEASE-NOTFOUND + +ZLIB_ROOT:PATH=E:/edu100dev/100protosdkPC/eduprotosdk/depends/dw3rd/zlib2015-1.2.5 + +//Dependencies for the target +common_utilities_LIB_DEPENDS:STATIC=general;cpprest;general;unittestpp; + +//Dependencies for the target +cpprest_LIB_DEPENDS:STATIC=general;cpprestsdk_boost_internal;general;cpprestsdk_zlib_internal;general;httpapi.lib;general;Winhttp.lib;general;bcrypt.lib;general;crypt32.lib; + +//Value Computed by CMake +cpprestsdk-root_BINARY_DIR:STATIC=E:/netttttt/http/zhangbincpprestsdk/WIN32 + +//Value Computed by CMake +cpprestsdk-root_SOURCE_DIR:STATIC=E:/netttttt/http/zhangbincpprestsdk + +//Value Computed by CMake +cpprestsdk_BINARY_DIR:STATIC=E:/netttttt/http/zhangbincpprestsdk/WIN32/Release + +//Value Computed by CMake +cpprestsdk_SOURCE_DIR:STATIC=E:/netttttt/http/zhangbincpprestsdk/Release + +//Dependencies for the target +httpclient_test_LIB_DEPENDS:STATIC=general;cpprest;general;common_utilities;general;unittestpp;general;httptest_utilities; + +//Dependencies for the target +httplistener_test_LIB_DEPENDS:STATIC=general;cpprest;general;common_utilities;general;unittestpp;general;httptest_utilities; + +//Dependencies for the target +httptest_utilities_LIB_DEPENDS:STATIC=general;cpprest;general;unittestpp;general;common_utilities; + +//Dependencies for the target +json_test_LIB_DEPENDS:STATIC=general;cpprest;general;common_utilities;general;unittestpp; + +//Dependencies for the target +pplx_test_LIB_DEPENDS:STATIC=general;cpprest;general;common_utilities;general;unittestpp; + +//Dependencies for the target +streams_test_LIB_DEPENDS:STATIC=general;cpprest;general;common_utilities;general;unittestpp; + +//Dependencies for the target +unittestpp_LIB_DEPENDS:STATIC=general;cpprest; + +//Dependencies for the target +uri_test_LIB_DEPENDS:STATIC=general;cpprest;general;common_utilities;general;unittestpp; + +//Dependencies for the target +utils_test_LIB_DEPENDS:STATIC=general;cpprest;general;common_utilities;general;unittestpp; + + +######################## +# INTERNAL cache entries +######################## + +//ADVANCED property for variable: BOOST_LIBRARYDIR +BOOST_LIBRARYDIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: BOOST_ROOT +BOOST_ROOT-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: Boost_DATE_TIME_LIBRARY_DEBUG +Boost_DATE_TIME_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: Boost_DATE_TIME_LIBRARY_RELEASE +Boost_DATE_TIME_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: Boost_DIR +Boost_DIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: Boost_INCLUDE_DIR +Boost_INCLUDE_DIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: Boost_REGEX_LIBRARY_DEBUG +Boost_REGEX_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: Boost_REGEX_LIBRARY_RELEASE +Boost_REGEX_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: Boost_SYSTEM_LIBRARY_DEBUG +Boost_SYSTEM_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: Boost_SYSTEM_LIBRARY_RELEASE +Boost_SYSTEM_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 +//This is the directory where this CMakeCache.txt was created +CMAKE_CACHEFILE_DIR:INTERNAL=e:/netttttt/http/zhangbincpprestsdk/WIN32 +//Major version of cmake used to create the current loaded cache +CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 +//Minor version of cmake used to create the current loaded cache +CMAKE_CACHE_MINOR_VERSION:INTERNAL=14 +//Patch version of cmake used to create the current loaded cache +CMAKE_CACHE_PATCH_VERSION:INTERNAL=0 +//Path to CMake executable. +CMAKE_COMMAND:INTERNAL=D:/Program Files/CMake/bin/cmake.exe +//Path to cpack program executable. +CMAKE_CPACK_COMMAND:INTERNAL=D:/Program Files/CMake/bin/cpack.exe +//Path to ctest program executable. +CMAKE_CTEST_COMMAND:INTERNAL=D:/Program Files/CMake/bin/ctest.exe +//ADVANCED property for variable: CMAKE_CXX_FLAGS +CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG +CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL +CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE +CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO +CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_STANDARD_LIBRARIES +CMAKE_CXX_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 +//Executable file format +CMAKE_EXECUTABLE_FORMAT:INTERNAL=Unknown +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS +CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG +CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE +CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//Name of external makefile project generator. +CMAKE_EXTRA_GENERATOR:INTERNAL= +//Name of generator. +CMAKE_GENERATOR:INTERNAL=Visual Studio 16 2019 +//Generator instance identifier. +CMAKE_GENERATOR_INSTANCE:INTERNAL=C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise +//Name of generator platform. +CMAKE_GENERATOR_PLATFORM:INTERNAL=Win32 +//Name of generator toolset. +CMAKE_GENERATOR_TOOLSET:INTERNAL=v140 +//Have include pthread.h +CMAKE_HAVE_PTHREAD_H:INTERNAL= +//Source directory with the top level CMakeLists.txt file for this +// project +CMAKE_HOME_DIRECTORY:INTERNAL=E:/netttttt/http/zhangbincpprestsdk +//ADVANCED property for variable: CMAKE_INSTALL_BINDIR +CMAKE_INSTALL_BINDIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_DATADIR +CMAKE_INSTALL_DATADIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_DATAROOTDIR +CMAKE_INSTALL_DATAROOTDIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_DOCDIR +CMAKE_INSTALL_DOCDIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_INCLUDEDIR +CMAKE_INSTALL_INCLUDEDIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_INFODIR +CMAKE_INSTALL_INFODIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_LIBDIR +CMAKE_INSTALL_LIBDIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_LIBEXECDIR +CMAKE_INSTALL_LIBEXECDIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_LOCALEDIR +CMAKE_INSTALL_LOCALEDIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_LOCALSTATEDIR +CMAKE_INSTALL_LOCALSTATEDIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_MANDIR +CMAKE_INSTALL_MANDIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_OLDINCLUDEDIR +CMAKE_INSTALL_OLDINCLUDEDIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_RUNSTATEDIR +CMAKE_INSTALL_RUNSTATEDIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_SBINDIR +CMAKE_INSTALL_SBINDIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_SHAREDSTATEDIR +CMAKE_INSTALL_SHAREDSTATEDIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_SYSCONFDIR +CMAKE_INSTALL_SYSCONFDIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_LINKER +CMAKE_LINKER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS +CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG +CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE +CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MT +CMAKE_MT-ADVANCED:INTERNAL=1 +//number of local generators +CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=28 +//Platform information initialized +CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RC_COMPILER +CMAKE_RC_COMPILER-ADVANCED:INTERNAL=1 +CMAKE_RC_COMPILER_WORKS:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RC_FLAGS +CMAKE_RC_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RC_FLAGS_DEBUG +CMAKE_RC_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RC_FLAGS_MINSIZEREL +CMAKE_RC_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RC_FLAGS_RELEASE +CMAKE_RC_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RC_FLAGS_RELWITHDEBINFO +CMAKE_RC_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//Path to CMake installation. +CMAKE_ROOT:INTERNAL=D:/Program Files/CMake/share/cmake-3.14 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS +CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG +CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE +CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH +CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_RPATH +CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS +CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG +CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE +CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE +CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 +//Details about finding OpenSSL +FIND_PACKAGE_MESSAGE_DETAILS_OpenSSL:INTERNAL=[optimized;E:\edu100dev\100protosdkPC\eduprotosdk\depends\dw3rd\openssl2015-1.0.0d_vs2015\lib\release;debug;E:/edu100dev/100protosdkPC/eduprotosdk/depends/dw3rd/openssl2015-1.0.0d_vs2015/lib/debug][E:\edu100dev\100protosdkPC\eduprotosdk\depends\dw3rd\openssl2015-1.0.0d_vs2015\include][c ][v1.0.0d(1.0.0)] +//Details about finding Threads +FIND_PACKAGE_MESSAGE_DETAILS_Threads:INTERNAL=[TRUE][v()] +//Details about finding ZLIB +FIND_PACKAGE_MESSAGE_DETAILS_ZLIB:INTERNAL=[E:/edu100dev/100protosdkPC/eduprotosdk/depends/dw3rd/zlib2015-1.2.5/lib/release][C:/Strawberry/c/include][v1.2.8()] +//ADVANCED property for variable: LIB_EAY_LIBRARY_DEBUG +LIB_EAY_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: LIB_EAY_LIBRARY_RELEASE +LIB_EAY_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: OPENSSL_INCLUDE_DIR +OPENSSL_INCLUDE_DIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: SSL_EAY_LIBRARY_DEBUG +SSL_EAY_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: SSL_EAY_LIBRARY_RELEASE +SSL_EAY_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: ZLIB_INCLUDE_DIR +ZLIB_INCLUDE_DIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: ZLIB_LIBRARY_DEBUG +ZLIB_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: ZLIB_LIBRARY_RELEASE +ZLIB_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 +//Last used BOOST_LIBRARYDIR value. +_BOOST_LIBRARYDIR_LAST:INTERNAL=E:/edu100dev/100protosdkPC/eduprotosdk/depends/dw3rd/zlib2015-1.2.5/lib/release +//Last used BOOST_ROOT value. +_BOOST_ROOT_LAST:INTERNAL=E:/edu100dev/100protosdkPC/eduprotosdk/depends/dw3rd/boost2015-1.66.0.140 +//Components requested for this build tree. +_Boost_COMPONENTS_SEARCHED:INTERNAL=date_time;regex;system +//Last used Boost_INCLUDE_DIR value. +_Boost_INCLUDE_DIR_LAST:INTERNAL=E:/edu100dev/100protosdkPC/eduprotosdk/depends/dw3rd/boost2015-1.66.0.140/include +//Last used Boost_NAMESPACE value. +_Boost_NAMESPACE_LAST:INTERNAL=boost +//Last used Boost_USE_MULTITHREADED value. +_Boost_USE_MULTITHREADED_LAST:INTERNAL=TRUE +//Last used Boost_USE_STATIC_LIBS value. +_Boost_USE_STATIC_LIBS_LAST:INTERNAL=OFF +//CMAKE_INSTALL_PREFIX during last run +_GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX:INTERNAL=E:/netttttt/http/zhangbincpprestsdk/cpprestsdk-root +//Result of TRY_COMPILE +_SSL_LEAK_SUPPRESS_AVAILABLE:INTERNAL=FALSE + diff --git a/WIN32/CTestTestfile.cmake b/WIN32/CTestTestfile.cmake new file mode 100644 index 0000000000..6463e62c75 --- /dev/null +++ b/WIN32/CTestTestfile.cmake @@ -0,0 +1,7 @@ +# CMake generated Testfile for +# Source directory: E:/netttttt/http/zhangbincpprestsdk +# Build directory: E:/netttttt/http/zhangbincpprestsdk/WIN32 +# +# This file includes the relevant testing commands required for +# testing this directory and lists subdirectories to be tested as well. +subdirs("Release") diff --git a/WIN32/INSTALL.vcxproj b/WIN32/INSTALL.vcxproj new file mode 100644 index 0000000000..e1b9f85714 --- /dev/null +++ b/WIN32/INSTALL.vcxproj @@ -0,0 +1,228 @@ + + + + x64 + + + + Debug + Win32 + + + Release + Win32 + + + MinSizeRel + Win32 + + + RelWithDebInfo + Win32 + + + + {E46A4ACB-1E02-341D-9BBF-64284E64F708} + 10.0.17763.0 + Win32Proj + Win32 + INSTALL + NoUpgrade + + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + + + + %(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"D:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + %(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"D:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + %(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"D:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + %(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"D:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + E:/netttttt/http/zhangbincpprestsdk/WIN32/CMakeFiles/c169eeec3ed84cd70538e7841fd07709/INSTALL_force.rule;%(AdditionalInputs) + E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + E:/netttttt/http/zhangbincpprestsdk/WIN32/CMakeFiles/c169eeec3ed84cd70538e7841fd07709/INSTALL_force.rule;%(AdditionalInputs) + E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + E:/netttttt/http/zhangbincpprestsdk/WIN32/CMakeFiles/c169eeec3ed84cd70538e7841fd07709/INSTALL_force.rule;%(AdditionalInputs) + E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + E:/netttttt/http/zhangbincpprestsdk/WIN32/CMakeFiles/c169eeec3ed84cd70538e7841fd07709/INSTALL_force.rule;%(AdditionalInputs) + E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\INSTALL_force + false + + + + + {A176657F-0AA3-398F-8CF1-46712FD79F2B} + ZERO_CHECK + false + Never + + + {E6C3FF0A-B39E-3D38-A718-D638CC0CAEEE} + ALL_BUILD + false + Never + + + + + + \ No newline at end of file diff --git a/WIN32/INSTALL.vcxproj.filters b/WIN32/INSTALL.vcxproj.filters new file mode 100644 index 0000000000..9714cc02ac --- /dev/null +++ b/WIN32/INSTALL.vcxproj.filters @@ -0,0 +1,13 @@ + + + + + CMake Rules + + + + + {49EE7268-01FC-3FF9-ADDD-C33D31A02CF8} + + + diff --git a/WIN32/RUN_TESTS.vcxproj b/WIN32/RUN_TESTS.vcxproj new file mode 100644 index 0000000000..554727e065 --- /dev/null +++ b/WIN32/RUN_TESTS.vcxproj @@ -0,0 +1,222 @@ + + + + x64 + + + + Debug + Win32 + + + Release + Win32 + + + MinSizeRel + Win32 + + + RelWithDebInfo + Win32 + + + + {3F617CE3-B640-3E99-B533-B23FE4975692} + 10.0.17763.0 + Win32Proj + Win32 + RUN_TESTS + NoUpgrade + + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + + + + %(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"D:\Program Files\CMake\bin\ctest.exe" --force-new-ctest-process -C $(Configuration) +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + %(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"D:\Program Files\CMake\bin\ctest.exe" --force-new-ctest-process -C $(Configuration) +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + %(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"D:\Program Files\CMake\bin\ctest.exe" --force-new-ctest-process -C $(Configuration) +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + %(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"D:\Program Files\CMake\bin\ctest.exe" --force-new-ctest-process -C $(Configuration) +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + E:/netttttt/http/zhangbincpprestsdk/WIN32/CMakeFiles/c169eeec3ed84cd70538e7841fd07709/RUN_TESTS_force.rule;%(AdditionalInputs) + E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\RUN_TESTS_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + E:/netttttt/http/zhangbincpprestsdk/WIN32/CMakeFiles/c169eeec3ed84cd70538e7841fd07709/RUN_TESTS_force.rule;%(AdditionalInputs) + E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\RUN_TESTS_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + E:/netttttt/http/zhangbincpprestsdk/WIN32/CMakeFiles/c169eeec3ed84cd70538e7841fd07709/RUN_TESTS_force.rule;%(AdditionalInputs) + E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\RUN_TESTS_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + E:/netttttt/http/zhangbincpprestsdk/WIN32/CMakeFiles/c169eeec3ed84cd70538e7841fd07709/RUN_TESTS_force.rule;%(AdditionalInputs) + E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\RUN_TESTS_force + false + + + + + {A176657F-0AA3-398F-8CF1-46712FD79F2B} + ZERO_CHECK + false + Never + + + + + + \ No newline at end of file diff --git a/WIN32/RUN_TESTS.vcxproj.filters b/WIN32/RUN_TESTS.vcxproj.filters new file mode 100644 index 0000000000..3e5fc1e0da --- /dev/null +++ b/WIN32/RUN_TESTS.vcxproj.filters @@ -0,0 +1,13 @@ + + + + + CMake Rules + + + + + {49EE7268-01FC-3FF9-ADDD-C33D31A02CF8} + + + diff --git a/WIN32/Win32/Release/ZERO_CHECK/ZERO_CHECK.vcxproj.FileListAbsolute.txt b/WIN32/Win32/Release/ZERO_CHECK/ZERO_CHECK.vcxproj.FileListAbsolute.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/WIN32/ZERO_CHECK.vcxproj b/WIN32/ZERO_CHECK.vcxproj new file mode 100644 index 0000000000..0b333b0792 --- /dev/null +++ b/WIN32/ZERO_CHECK.vcxproj @@ -0,0 +1,170 @@ + + + + x64 + + + + Debug + Win32 + + + Release + Win32 + + + MinSizeRel + Win32 + + + RelWithDebInfo + Win32 + + + + {A176657F-0AA3-398F-8CF1-46712FD79F2B} + 10.0.17763.0 + Win32Proj + Win32 + ZERO_CHECK + NoUpgrade + + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + Utility + MultiByte + v140 + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + + + + %(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + %(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + %(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + %(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + Checking Build System + setlocal +"D:\Program Files\CMake\bin\cmake.exe" -SE:/netttttt/http/zhangbincpprestsdk -BE:/netttttt/http/zhangbincpprestsdk/WIN32 --check-stamp-list CMakeFiles/generate.stamp.list --vs-solution-file E:/netttttt/http/zhangbincpprestsdk/WIN32/cpprestsdk-root.sln +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + E:/netttttt/http/zhangbincpprestsdk/WIN32/CMakeFiles/c169eeec3ed84cd70538e7841fd07709/generate.stamp.rule;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeCXXInformation.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeCommonLanguageInclude.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeGenericSystem.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeInitializeConfigs.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeLanguageInformation.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeRCInformation.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeSystemSpecificInformation.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeSystemSpecificInitialize.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CheckCXXSourceCompiles.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CheckIncludeFileCXX.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CheckIncludeFiles.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CheckLibraryExists.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CheckSymbolExists.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Compiler\CMakeCommonCompilerMacros.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Compiler\MSVC-CXX.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\FindOpenSSL.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\FindPackageHandleStandardArgs.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\FindPackageMessage.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\FindThreads.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\GNUInstallDirs.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Platform\Windows-MSVC-CXX.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Platform\Windows-MSVC.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Platform\Windows.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Platform\WindowsPaths.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\SelectLibraryConfigurations.cmake;E:\netttttt\http\zhangbincpprestsdk\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\cmake\cpprest_find_boost.cmake;E:\netttttt\http\zhangbincpprestsdk\Release\cmake\cpprest_find_openssl.cmake;E:\netttttt\http\zhangbincpprestsdk\Release\cmake\cpprest_find_zlib.cmake;E:\netttttt\http\zhangbincpprestsdk\Release\cmake\cpprestsdk-config.in.cmake;E:\netttttt\http\zhangbincpprestsdk\Release\samples\BingRequest\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\samples\BlackJack\BlackJack_Client\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\samples\BlackJack\BlackJack_Server\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\samples\BlackJack\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\samples\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\samples\Oauth1Client\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\samples\Oauth2Client\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\samples\SearchFile\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\src\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\common\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\common\TestRunner\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\common\UnitTestpp\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\common\utilities\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\http\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\http\client\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\http\listener\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\http\utilities\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\json\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\pplx\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\pplx\pplx_test\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\streams\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\uri\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\utils\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\websockets\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\3.14.0\CMakeCXXCompiler.cmake;E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\3.14.0\CMakeRCCompiler.cmake;E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\3.14.0\CMakeSystem.cmake;%(AdditionalInputs) + E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\src\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\common\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\common\utilities\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\common\UnitTestpp\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\common\TestRunner\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\http\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\http\utilities\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\http\client\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\http\listener\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\json\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\pplx\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\pplx\pplx_test\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\streams\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\uri\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\utils\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\websockets\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\SearchFile\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\BingRequest\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\BlackJack\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\BlackJack\BlackJack_Server\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\BlackJack\BlackJack_Client\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\Oauth1Client\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\Oauth2Client\CMakeFiles\generate.stamp + false + Checking Build System + setlocal +"D:\Program Files\CMake\bin\cmake.exe" -SE:/netttttt/http/zhangbincpprestsdk -BE:/netttttt/http/zhangbincpprestsdk/WIN32 --check-stamp-list CMakeFiles/generate.stamp.list --vs-solution-file E:/netttttt/http/zhangbincpprestsdk/WIN32/cpprestsdk-root.sln +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + E:/netttttt/http/zhangbincpprestsdk/WIN32/CMakeFiles/c169eeec3ed84cd70538e7841fd07709/generate.stamp.rule;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeCXXInformation.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeCommonLanguageInclude.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeGenericSystem.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeInitializeConfigs.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeLanguageInformation.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeRCInformation.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeSystemSpecificInformation.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeSystemSpecificInitialize.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CheckCXXSourceCompiles.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CheckIncludeFileCXX.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CheckIncludeFiles.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CheckLibraryExists.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CheckSymbolExists.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Compiler\CMakeCommonCompilerMacros.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Compiler\MSVC-CXX.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\FindOpenSSL.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\FindPackageHandleStandardArgs.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\FindPackageMessage.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\FindThreads.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\GNUInstallDirs.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Platform\Windows-MSVC-CXX.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Platform\Windows-MSVC.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Platform\Windows.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Platform\WindowsPaths.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\SelectLibraryConfigurations.cmake;E:\netttttt\http\zhangbincpprestsdk\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\cmake\cpprest_find_boost.cmake;E:\netttttt\http\zhangbincpprestsdk\Release\cmake\cpprest_find_openssl.cmake;E:\netttttt\http\zhangbincpprestsdk\Release\cmake\cpprest_find_zlib.cmake;E:\netttttt\http\zhangbincpprestsdk\Release\cmake\cpprestsdk-config.in.cmake;E:\netttttt\http\zhangbincpprestsdk\Release\samples\BingRequest\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\samples\BlackJack\BlackJack_Client\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\samples\BlackJack\BlackJack_Server\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\samples\BlackJack\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\samples\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\samples\Oauth1Client\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\samples\Oauth2Client\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\samples\SearchFile\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\src\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\common\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\common\TestRunner\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\common\UnitTestpp\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\common\utilities\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\http\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\http\client\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\http\listener\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\http\utilities\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\json\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\pplx\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\pplx\pplx_test\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\streams\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\uri\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\utils\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\websockets\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\3.14.0\CMakeCXXCompiler.cmake;E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\3.14.0\CMakeRCCompiler.cmake;E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\3.14.0\CMakeSystem.cmake;%(AdditionalInputs) + E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\src\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\common\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\common\utilities\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\common\UnitTestpp\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\common\TestRunner\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\http\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\http\utilities\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\http\client\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\http\listener\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\json\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\pplx\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\pplx\pplx_test\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\streams\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\uri\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\utils\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\websockets\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\SearchFile\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\BingRequest\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\BlackJack\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\BlackJack\BlackJack_Server\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\BlackJack\BlackJack_Client\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\Oauth1Client\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\Oauth2Client\CMakeFiles\generate.stamp + false + Checking Build System + setlocal +"D:\Program Files\CMake\bin\cmake.exe" -SE:/netttttt/http/zhangbincpprestsdk -BE:/netttttt/http/zhangbincpprestsdk/WIN32 --check-stamp-list CMakeFiles/generate.stamp.list --vs-solution-file E:/netttttt/http/zhangbincpprestsdk/WIN32/cpprestsdk-root.sln +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + E:/netttttt/http/zhangbincpprestsdk/WIN32/CMakeFiles/c169eeec3ed84cd70538e7841fd07709/generate.stamp.rule;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeCXXInformation.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeCommonLanguageInclude.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeGenericSystem.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeInitializeConfigs.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeLanguageInformation.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeRCInformation.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeSystemSpecificInformation.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeSystemSpecificInitialize.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CheckCXXSourceCompiles.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CheckIncludeFileCXX.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CheckIncludeFiles.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CheckLibraryExists.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CheckSymbolExists.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Compiler\CMakeCommonCompilerMacros.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Compiler\MSVC-CXX.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\FindOpenSSL.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\FindPackageHandleStandardArgs.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\FindPackageMessage.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\FindThreads.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\GNUInstallDirs.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Platform\Windows-MSVC-CXX.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Platform\Windows-MSVC.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Platform\Windows.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Platform\WindowsPaths.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\SelectLibraryConfigurations.cmake;E:\netttttt\http\zhangbincpprestsdk\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\cmake\cpprest_find_boost.cmake;E:\netttttt\http\zhangbincpprestsdk\Release\cmake\cpprest_find_openssl.cmake;E:\netttttt\http\zhangbincpprestsdk\Release\cmake\cpprest_find_zlib.cmake;E:\netttttt\http\zhangbincpprestsdk\Release\cmake\cpprestsdk-config.in.cmake;E:\netttttt\http\zhangbincpprestsdk\Release\samples\BingRequest\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\samples\BlackJack\BlackJack_Client\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\samples\BlackJack\BlackJack_Server\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\samples\BlackJack\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\samples\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\samples\Oauth1Client\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\samples\Oauth2Client\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\samples\SearchFile\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\src\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\common\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\common\TestRunner\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\common\UnitTestpp\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\common\utilities\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\http\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\http\client\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\http\listener\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\http\utilities\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\json\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\pplx\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\pplx\pplx_test\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\streams\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\uri\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\utils\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\websockets\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\3.14.0\CMakeCXXCompiler.cmake;E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\3.14.0\CMakeRCCompiler.cmake;E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\3.14.0\CMakeSystem.cmake;%(AdditionalInputs) + E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\src\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\common\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\common\utilities\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\common\UnitTestpp\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\common\TestRunner\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\http\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\http\utilities\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\http\client\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\http\listener\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\json\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\pplx\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\pplx\pplx_test\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\streams\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\uri\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\utils\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\websockets\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\SearchFile\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\BingRequest\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\BlackJack\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\BlackJack\BlackJack_Server\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\BlackJack\BlackJack_Client\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\Oauth1Client\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\Oauth2Client\CMakeFiles\generate.stamp + false + Checking Build System + setlocal +"D:\Program Files\CMake\bin\cmake.exe" -SE:/netttttt/http/zhangbincpprestsdk -BE:/netttttt/http/zhangbincpprestsdk/WIN32 --check-stamp-list CMakeFiles/generate.stamp.list --vs-solution-file E:/netttttt/http/zhangbincpprestsdk/WIN32/cpprestsdk-root.sln +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + E:/netttttt/http/zhangbincpprestsdk/WIN32/CMakeFiles/c169eeec3ed84cd70538e7841fd07709/generate.stamp.rule;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeCXXInformation.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeCommonLanguageInclude.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeGenericSystem.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeInitializeConfigs.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeLanguageInformation.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeRCInformation.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeSystemSpecificInformation.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CMakeSystemSpecificInitialize.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CheckCXXSourceCompiles.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CheckIncludeFileCXX.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CheckIncludeFiles.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CheckLibraryExists.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\CheckSymbolExists.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Compiler\CMakeCommonCompilerMacros.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Compiler\MSVC-CXX.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\FindOpenSSL.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\FindPackageHandleStandardArgs.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\FindPackageMessage.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\FindThreads.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\GNUInstallDirs.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Platform\Windows-MSVC-CXX.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Platform\Windows-MSVC.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Platform\Windows.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\Platform\WindowsPaths.cmake;D:\Program Files\CMake\share\cmake-3.14\Modules\SelectLibraryConfigurations.cmake;E:\netttttt\http\zhangbincpprestsdk\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\cmake\cpprest_find_boost.cmake;E:\netttttt\http\zhangbincpprestsdk\Release\cmake\cpprest_find_openssl.cmake;E:\netttttt\http\zhangbincpprestsdk\Release\cmake\cpprest_find_zlib.cmake;E:\netttttt\http\zhangbincpprestsdk\Release\cmake\cpprestsdk-config.in.cmake;E:\netttttt\http\zhangbincpprestsdk\Release\samples\BingRequest\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\samples\BlackJack\BlackJack_Client\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\samples\BlackJack\BlackJack_Server\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\samples\BlackJack\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\samples\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\samples\Oauth1Client\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\samples\Oauth2Client\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\samples\SearchFile\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\src\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\common\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\common\TestRunner\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\common\UnitTestpp\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\common\utilities\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\http\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\http\client\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\http\listener\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\http\utilities\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\json\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\pplx\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\pplx\pplx_test\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\streams\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\uri\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\utils\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\Release\tests\functional\websockets\CMakeLists.txt;E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\3.14.0\CMakeCXXCompiler.cmake;E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\3.14.0\CMakeRCCompiler.cmake;E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\3.14.0\CMakeSystem.cmake;%(AdditionalInputs) + E:\netttttt\http\zhangbincpprestsdk\WIN32\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\src\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\common\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\common\utilities\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\common\UnitTestpp\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\common\TestRunner\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\http\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\http\utilities\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\http\client\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\http\listener\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\json\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\pplx\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\pplx\pplx_test\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\streams\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\uri\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\utils\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\tests\functional\websockets\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\SearchFile\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\BingRequest\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\BlackJack\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\BlackJack\BlackJack_Server\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\BlackJack\BlackJack_Client\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\Oauth1Client\CMakeFiles\generate.stamp;E:\netttttt\http\zhangbincpprestsdk\WIN32\Release\samples\Oauth2Client\CMakeFiles\generate.stamp + false + + + + + + + + + + \ No newline at end of file diff --git a/WIN32/ZERO_CHECK.vcxproj.filters b/WIN32/ZERO_CHECK.vcxproj.filters new file mode 100644 index 0000000000..deebe7dafa --- /dev/null +++ b/WIN32/ZERO_CHECK.vcxproj.filters @@ -0,0 +1,13 @@ + + + + + CMake Rules + + + + + {49EE7268-01FC-3FF9-ADDD-C33D31A02CF8} + + + diff --git a/WIN32/cmake_install.cmake b/WIN32/cmake_install.cmake new file mode 100644 index 0000000000..ad23077aa8 --- /dev/null +++ b/WIN32/cmake_install.cmake @@ -0,0 +1,50 @@ +# Install script for directory: E:/netttttt/http/zhangbincpprestsdk + +# Set the install prefix +if(NOT DEFINED CMAKE_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX "E:/netttttt/http/zhangbincpprestsdk/cpprestsdk-root") +endif() +string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + if(BUILD_TYPE) + string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + else() + set(CMAKE_INSTALL_CONFIG_NAME "Release") + endif() + message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +endif() + +# Set the component getting installed. +if(NOT CMAKE_INSTALL_COMPONENT) + if(COMPONENT) + message(STATUS "Install component: \"${COMPONENT}\"") + set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + else() + set(CMAKE_INSTALL_COMPONENT) + endif() +endif() + +# Is this installation the result of a crosscompile? +if(NOT DEFINED CMAKE_CROSSCOMPILING) + set(CMAKE_CROSSCOMPILING "FALSE") +endif() + +if(NOT CMAKE_INSTALL_LOCAL_ONLY) + # Include the install script for each subdirectory. + include("E:/netttttt/http/zhangbincpprestsdk/WIN32/Release/cmake_install.cmake") + +endif() + +if(CMAKE_INSTALL_COMPONENT) + set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") +else() + set(CMAKE_INSTALL_MANIFEST "install_manifest.txt") +endif() + +string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT + "${CMAKE_INSTALL_MANIFEST_FILES}") +file(WRITE "E:/netttttt/http/zhangbincpprestsdk/WIN32/${CMAKE_INSTALL_MANIFEST}" + "${CMAKE_INSTALL_MANIFEST_CONTENT}") diff --git a/WIN32/cpprestsdk-root.sln b/WIN32/cpprestsdk-root.sln new file mode 100644 index 0000000000..ecf4ae0005 --- /dev/null +++ b/WIN32/cpprestsdk-root.sln @@ -0,0 +1,570 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.28922.388 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ALL_BUILD", "ALL_BUILD.vcxproj", "{E6C3FF0A-B39E-3D38-A718-D638CC0CAEEE}" + ProjectSection(ProjectDependencies) = postProject + {DFC1F0B0-A588-3F9B-9CAD-11938C1F32AC} = {DFC1F0B0-A588-3F9B-9CAD-11938C1F32AC} + {FB3CB569-9342-31EE-A902-DEEA05F1B7D5} = {FB3CB569-9342-31EE-A902-DEEA05F1B7D5} + {A176657F-0AA3-398F-8CF1-46712FD79F2B} = {A176657F-0AA3-398F-8CF1-46712FD79F2B} + {71D26AC8-A3F9-325F-A3B8-3AF09DCFE994} = {71D26AC8-A3F9-325F-A3B8-3AF09DCFE994} + {E5C90FD6-9338-3971-BDBE-8C0DD7E28A01} = {E5C90FD6-9338-3971-BDBE-8C0DD7E28A01} + {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A} = {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A} + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} = {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} + {42513BC6-0B70-3C14-B3C5-4BC7E1BC0650} = {42513BC6-0B70-3C14-B3C5-4BC7E1BC0650} + {4362448C-BE8F-36A3-9B0E-50611BD41CF1} = {4362448C-BE8F-36A3-9B0E-50611BD41CF1} + {5E524D44-C5BF-336D-B812-E13DBC6B94B6} = {5E524D44-C5BF-336D-B812-E13DBC6B94B6} + {1C9DD759-1582-3F76-91A7-E2E93ED3EDA7} = {1C9DD759-1582-3F76-91A7-E2E93ED3EDA7} + {F998D6CB-C9D6-3B52-85BF-503E8965DD7E} = {F998D6CB-C9D6-3B52-85BF-503E8965DD7E} + {922B451B-BAFA-3F9B-803B-54138CE39381} = {922B451B-BAFA-3F9B-803B-54138CE39381} + {D6297D20-59AF-3E27-83CC-DE1EA62B27CE} = {D6297D20-59AF-3E27-83CC-DE1EA62B27CE} + {04AA7FE2-B767-3EE0-9607-97CE5A999562} = {04AA7FE2-B767-3EE0-9607-97CE5A999562} + {8EF7FEFB-B31C-3709-B1A3-1FCAB22D3D51} = {8EF7FEFB-B31C-3709-B1A3-1FCAB22D3D51} + {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF} = {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF} + {25A5C8EB-A739-30EA-AE01-4DDC56266398} = {25A5C8EB-A739-30EA-AE01-4DDC56266398} + {7BFCA077-2FEF-34D5-8A79-1F8F4D3022E4} = {7BFCA077-2FEF-34D5-8A79-1F8F4D3022E4} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BingRequest", "Release\samples\BingRequest\BingRequest.vcxproj", "{DFC1F0B0-A588-3F9B-9CAD-11938C1F32AC}" + ProjectSection(ProjectDependencies) = postProject + {A176657F-0AA3-398F-8CF1-46712FD79F2B} = {A176657F-0AA3-398F-8CF1-46712FD79F2B} + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} = {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "INSTALL", "INSTALL.vcxproj", "{E46A4ACB-1E02-341D-9BBF-64284E64F708}" + ProjectSection(ProjectDependencies) = postProject + {E6C3FF0A-B39E-3D38-A718-D638CC0CAEEE} = {E6C3FF0A-B39E-3D38-A718-D638CC0CAEEE} + {A176657F-0AA3-398F-8CF1-46712FD79F2B} = {A176657F-0AA3-398F-8CF1-46712FD79F2B} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RUN_TESTS", "RUN_TESTS.vcxproj", "{3F617CE3-B640-3E99-B533-B23FE4975692}" + ProjectSection(ProjectDependencies) = postProject + {A176657F-0AA3-398F-8CF1-46712FD79F2B} = {A176657F-0AA3-398F-8CF1-46712FD79F2B} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SearchFile", "Release\samples\SearchFile\SearchFile.vcxproj", "{FB3CB569-9342-31EE-A902-DEEA05F1B7D5}" + ProjectSection(ProjectDependencies) = postProject + {A176657F-0AA3-398F-8CF1-46712FD79F2B} = {A176657F-0AA3-398F-8CF1-46712FD79F2B} + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} = {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZERO_CHECK", "ZERO_CHECK.vcxproj", "{A176657F-0AA3-398F-8CF1-46712FD79F2B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "blackjackclient", "Release\samples\BlackJack\BlackJack_Client\blackjackclient.vcxproj", "{71D26AC8-A3F9-325F-A3B8-3AF09DCFE994}" + ProjectSection(ProjectDependencies) = postProject + {A176657F-0AA3-398F-8CF1-46712FD79F2B} = {A176657F-0AA3-398F-8CF1-46712FD79F2B} + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} = {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "blackjackserver", "Release\samples\BlackJack\BlackJack_Server\blackjackserver.vcxproj", "{E5C90FD6-9338-3971-BDBE-8C0DD7E28A01}" + ProjectSection(ProjectDependencies) = postProject + {A176657F-0AA3-398F-8CF1-46712FD79F2B} = {A176657F-0AA3-398F-8CF1-46712FD79F2B} + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} = {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common_utilities", "Release\tests\common\utilities\common_utilities.vcxproj", "{2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A}" + ProjectSection(ProjectDependencies) = postProject + {A176657F-0AA3-398F-8CF1-46712FD79F2B} = {A176657F-0AA3-398F-8CF1-46712FD79F2B} + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} = {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} + {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF} = {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprest", "Release\src\cpprest.vcxproj", "{E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A}" + ProjectSection(ProjectDependencies) = postProject + {A176657F-0AA3-398F-8CF1-46712FD79F2B} = {A176657F-0AA3-398F-8CF1-46712FD79F2B} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "httpclient_test", "Release\tests\functional\http\client\httpclient_test.vcxproj", "{42513BC6-0B70-3C14-B3C5-4BC7E1BC0650}" + ProjectSection(ProjectDependencies) = postProject + {A176657F-0AA3-398F-8CF1-46712FD79F2B} = {A176657F-0AA3-398F-8CF1-46712FD79F2B} + {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A} = {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A} + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} = {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} + {5E524D44-C5BF-336D-B812-E13DBC6B94B6} = {5E524D44-C5BF-336D-B812-E13DBC6B94B6} + {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF} = {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "httplistener_test", "Release\tests\functional\http\listener\httplistener_test.vcxproj", "{4362448C-BE8F-36A3-9B0E-50611BD41CF1}" + ProjectSection(ProjectDependencies) = postProject + {A176657F-0AA3-398F-8CF1-46712FD79F2B} = {A176657F-0AA3-398F-8CF1-46712FD79F2B} + {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A} = {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A} + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} = {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} + {5E524D44-C5BF-336D-B812-E13DBC6B94B6} = {5E524D44-C5BF-336D-B812-E13DBC6B94B6} + {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF} = {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "httptest_utilities", "Release\tests\functional\http\utilities\httptest_utilities.vcxproj", "{5E524D44-C5BF-336D-B812-E13DBC6B94B6}" + ProjectSection(ProjectDependencies) = postProject + {A176657F-0AA3-398F-8CF1-46712FD79F2B} = {A176657F-0AA3-398F-8CF1-46712FD79F2B} + {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A} = {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A} + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} = {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} + {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF} = {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "json_test", "Release\tests\functional\json\json_test.vcxproj", "{1C9DD759-1582-3F76-91A7-E2E93ED3EDA7}" + ProjectSection(ProjectDependencies) = postProject + {A176657F-0AA3-398F-8CF1-46712FD79F2B} = {A176657F-0AA3-398F-8CF1-46712FD79F2B} + {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A} = {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A} + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} = {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} + {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF} = {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "oauth1client", "Release\samples\Oauth1Client\oauth1client.vcxproj", "{F998D6CB-C9D6-3B52-85BF-503E8965DD7E}" + ProjectSection(ProjectDependencies) = postProject + {A176657F-0AA3-398F-8CF1-46712FD79F2B} = {A176657F-0AA3-398F-8CF1-46712FD79F2B} + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} = {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "oauth2client", "Release\samples\Oauth2Client\oauth2client.vcxproj", "{922B451B-BAFA-3F9B-803B-54138CE39381}" + ProjectSection(ProjectDependencies) = postProject + {A176657F-0AA3-398F-8CF1-46712FD79F2B} = {A176657F-0AA3-398F-8CF1-46712FD79F2B} + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} = {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pplx_test", "Release\tests\functional\pplx\pplx_test\pplx_test.vcxproj", "{D6297D20-59AF-3E27-83CC-DE1EA62B27CE}" + ProjectSection(ProjectDependencies) = postProject + {A176657F-0AA3-398F-8CF1-46712FD79F2B} = {A176657F-0AA3-398F-8CF1-46712FD79F2B} + {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A} = {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A} + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} = {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} + {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF} = {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "samples", "Release\samples\samples.vcxproj", "{F85883CC-3DE4-3DA8-8A67-735428E10BF4}" + ProjectSection(ProjectDependencies) = postProject + {DFC1F0B0-A588-3F9B-9CAD-11938C1F32AC} = {DFC1F0B0-A588-3F9B-9CAD-11938C1F32AC} + {FB3CB569-9342-31EE-A902-DEEA05F1B7D5} = {FB3CB569-9342-31EE-A902-DEEA05F1B7D5} + {A176657F-0AA3-398F-8CF1-46712FD79F2B} = {A176657F-0AA3-398F-8CF1-46712FD79F2B} + {71D26AC8-A3F9-325F-A3B8-3AF09DCFE994} = {71D26AC8-A3F9-325F-A3B8-3AF09DCFE994} + {E5C90FD6-9338-3971-BDBE-8C0DD7E28A01} = {E5C90FD6-9338-3971-BDBE-8C0DD7E28A01} + {F998D6CB-C9D6-3B52-85BF-503E8965DD7E} = {F998D6CB-C9D6-3B52-85BF-503E8965DD7E} + {922B451B-BAFA-3F9B-803B-54138CE39381} = {922B451B-BAFA-3F9B-803B-54138CE39381} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "streams_test", "Release\tests\functional\streams\streams_test.vcxproj", "{04AA7FE2-B767-3EE0-9607-97CE5A999562}" + ProjectSection(ProjectDependencies) = postProject + {A176657F-0AA3-398F-8CF1-46712FD79F2B} = {A176657F-0AA3-398F-8CF1-46712FD79F2B} + {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A} = {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A} + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} = {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} + {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF} = {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_runner", "Release\tests\common\TestRunner\test_runner.vcxproj", "{8EF7FEFB-B31C-3709-B1A3-1FCAB22D3D51}" + ProjectSection(ProjectDependencies) = postProject + {A176657F-0AA3-398F-8CF1-46712FD79F2B} = {A176657F-0AA3-398F-8CF1-46712FD79F2B} + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} = {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} + {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF} = {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unittestpp", "Release\tests\common\UnitTestpp\unittestpp.vcxproj", "{6BE9891D-D655-30ED-9EB9-B9BA3C219DDF}" + ProjectSection(ProjectDependencies) = postProject + {A176657F-0AA3-398F-8CF1-46712FD79F2B} = {A176657F-0AA3-398F-8CF1-46712FD79F2B} + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} = {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "uri_test", "Release\tests\functional\uri\uri_test.vcxproj", "{25A5C8EB-A739-30EA-AE01-4DDC56266398}" + ProjectSection(ProjectDependencies) = postProject + {A176657F-0AA3-398F-8CF1-46712FD79F2B} = {A176657F-0AA3-398F-8CF1-46712FD79F2B} + {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A} = {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A} + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} = {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} + {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF} = {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "utils_test", "Release\tests\functional\utils\utils_test.vcxproj", "{7BFCA077-2FEF-34D5-8A79-1F8F4D3022E4}" + ProjectSection(ProjectDependencies) = postProject + {A176657F-0AA3-398F-8CF1-46712FD79F2B} = {A176657F-0AA3-398F-8CF1-46712FD79F2B} + {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A} = {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A} + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} = {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A} + {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF} = {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HTTP_CLIENT_GET_PICTURE", "..\HTTP_CLIENT_GET_PICTURE\HTTP_CLIENT_GET_PICTURE.vcxproj", "{5A72CAB6-2338-4984-9FE5-AED77A2824F8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HTTP_SIMPLE_SERVER", "..\HTTP_SIMPLE_SERVER\HTTP_SIMPLE_SERVER.vcxproj", "{BB0FB695-74B7-473B-B034-68F9FF0F3ED0}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HTTP_SIMPLE_CLIENT", "..\HTTP_SIMPLE_CLIENT\HTTP_SIMPLE_CLIENT.vcxproj", "{05071389-F9F3-4C44-B155-A15E43CA3FFD}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "simple_web", "..\simple_web\simple_web.vcxproj", "{363DCB11-CFEF-4E12-BE70-CE3C2D695ECA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JSON", "..\JSON\JSON\JSON.vcxproj", "{BE66C1CF-258B-4BD1-9ED5-7BD4235342D1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SYSINFO", "..\get\get.vcxproj", "{2A5089E9-EF05-48A2-B5A6-22723BAF9E78}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + MinSizeRel|Win32 = MinSizeRel|Win32 + MinSizeRel|x64 = MinSizeRel|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + RelWithDebInfo|Win32 = RelWithDebInfo|Win32 + RelWithDebInfo|x64 = RelWithDebInfo|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E6C3FF0A-B39E-3D38-A718-D638CC0CAEEE}.Debug|Win32.ActiveCfg = Debug|Win32 + {E6C3FF0A-B39E-3D38-A718-D638CC0CAEEE}.Debug|Win32.Build.0 = Debug|Win32 + {E6C3FF0A-B39E-3D38-A718-D638CC0CAEEE}.Debug|x64.ActiveCfg = Debug|Win32 + {E6C3FF0A-B39E-3D38-A718-D638CC0CAEEE}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {E6C3FF0A-B39E-3D38-A718-D638CC0CAEEE}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {E6C3FF0A-B39E-3D38-A718-D638CC0CAEEE}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {E6C3FF0A-B39E-3D38-A718-D638CC0CAEEE}.Release|Win32.ActiveCfg = Release|Win32 + {E6C3FF0A-B39E-3D38-A718-D638CC0CAEEE}.Release|Win32.Build.0 = Release|Win32 + {E6C3FF0A-B39E-3D38-A718-D638CC0CAEEE}.Release|x64.ActiveCfg = Release|Win32 + {E6C3FF0A-B39E-3D38-A718-D638CC0CAEEE}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {E6C3FF0A-B39E-3D38-A718-D638CC0CAEEE}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {E6C3FF0A-B39E-3D38-A718-D638CC0CAEEE}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 + {DFC1F0B0-A588-3F9B-9CAD-11938C1F32AC}.Debug|Win32.ActiveCfg = Debug|Win32 + {DFC1F0B0-A588-3F9B-9CAD-11938C1F32AC}.Debug|Win32.Build.0 = Debug|Win32 + {DFC1F0B0-A588-3F9B-9CAD-11938C1F32AC}.Debug|x64.ActiveCfg = Debug|Win32 + {DFC1F0B0-A588-3F9B-9CAD-11938C1F32AC}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {DFC1F0B0-A588-3F9B-9CAD-11938C1F32AC}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {DFC1F0B0-A588-3F9B-9CAD-11938C1F32AC}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {DFC1F0B0-A588-3F9B-9CAD-11938C1F32AC}.Release|Win32.ActiveCfg = Release|Win32 + {DFC1F0B0-A588-3F9B-9CAD-11938C1F32AC}.Release|Win32.Build.0 = Release|Win32 + {DFC1F0B0-A588-3F9B-9CAD-11938C1F32AC}.Release|x64.ActiveCfg = Release|Win32 + {DFC1F0B0-A588-3F9B-9CAD-11938C1F32AC}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {DFC1F0B0-A588-3F9B-9CAD-11938C1F32AC}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {DFC1F0B0-A588-3F9B-9CAD-11938C1F32AC}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 + {E46A4ACB-1E02-341D-9BBF-64284E64F708}.Debug|Win32.ActiveCfg = Debug|Win32 + {E46A4ACB-1E02-341D-9BBF-64284E64F708}.Debug|x64.ActiveCfg = Debug|Win32 + {E46A4ACB-1E02-341D-9BBF-64284E64F708}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {E46A4ACB-1E02-341D-9BBF-64284E64F708}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {E46A4ACB-1E02-341D-9BBF-64284E64F708}.Release|Win32.ActiveCfg = Release|Win32 + {E46A4ACB-1E02-341D-9BBF-64284E64F708}.Release|x64.ActiveCfg = Release|Win32 + {E46A4ACB-1E02-341D-9BBF-64284E64F708}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {E46A4ACB-1E02-341D-9BBF-64284E64F708}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 + {3F617CE3-B640-3E99-B533-B23FE4975692}.Debug|Win32.ActiveCfg = Debug|Win32 + {3F617CE3-B640-3E99-B533-B23FE4975692}.Debug|x64.ActiveCfg = Debug|Win32 + {3F617CE3-B640-3E99-B533-B23FE4975692}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {3F617CE3-B640-3E99-B533-B23FE4975692}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {3F617CE3-B640-3E99-B533-B23FE4975692}.Release|Win32.ActiveCfg = Release|Win32 + {3F617CE3-B640-3E99-B533-B23FE4975692}.Release|x64.ActiveCfg = Release|Win32 + {3F617CE3-B640-3E99-B533-B23FE4975692}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {3F617CE3-B640-3E99-B533-B23FE4975692}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 + {FB3CB569-9342-31EE-A902-DEEA05F1B7D5}.Debug|Win32.ActiveCfg = Debug|Win32 + {FB3CB569-9342-31EE-A902-DEEA05F1B7D5}.Debug|Win32.Build.0 = Debug|Win32 + {FB3CB569-9342-31EE-A902-DEEA05F1B7D5}.Debug|x64.ActiveCfg = Debug|Win32 + {FB3CB569-9342-31EE-A902-DEEA05F1B7D5}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {FB3CB569-9342-31EE-A902-DEEA05F1B7D5}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {FB3CB569-9342-31EE-A902-DEEA05F1B7D5}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {FB3CB569-9342-31EE-A902-DEEA05F1B7D5}.Release|Win32.ActiveCfg = Release|Win32 + {FB3CB569-9342-31EE-A902-DEEA05F1B7D5}.Release|Win32.Build.0 = Release|Win32 + {FB3CB569-9342-31EE-A902-DEEA05F1B7D5}.Release|x64.ActiveCfg = Release|Win32 + {FB3CB569-9342-31EE-A902-DEEA05F1B7D5}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {FB3CB569-9342-31EE-A902-DEEA05F1B7D5}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {FB3CB569-9342-31EE-A902-DEEA05F1B7D5}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 + {A176657F-0AA3-398F-8CF1-46712FD79F2B}.Debug|Win32.ActiveCfg = Debug|Win32 + {A176657F-0AA3-398F-8CF1-46712FD79F2B}.Debug|Win32.Build.0 = Debug|Win32 + {A176657F-0AA3-398F-8CF1-46712FD79F2B}.Debug|x64.ActiveCfg = Debug|Win32 + {A176657F-0AA3-398F-8CF1-46712FD79F2B}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {A176657F-0AA3-398F-8CF1-46712FD79F2B}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {A176657F-0AA3-398F-8CF1-46712FD79F2B}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {A176657F-0AA3-398F-8CF1-46712FD79F2B}.Release|Win32.ActiveCfg = Release|Win32 + {A176657F-0AA3-398F-8CF1-46712FD79F2B}.Release|Win32.Build.0 = Release|Win32 + {A176657F-0AA3-398F-8CF1-46712FD79F2B}.Release|x64.ActiveCfg = Release|Win32 + {A176657F-0AA3-398F-8CF1-46712FD79F2B}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {A176657F-0AA3-398F-8CF1-46712FD79F2B}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {A176657F-0AA3-398F-8CF1-46712FD79F2B}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 + {71D26AC8-A3F9-325F-A3B8-3AF09DCFE994}.Debug|Win32.ActiveCfg = Debug|Win32 + {71D26AC8-A3F9-325F-A3B8-3AF09DCFE994}.Debug|Win32.Build.0 = Debug|Win32 + {71D26AC8-A3F9-325F-A3B8-3AF09DCFE994}.Debug|x64.ActiveCfg = Debug|Win32 + {71D26AC8-A3F9-325F-A3B8-3AF09DCFE994}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {71D26AC8-A3F9-325F-A3B8-3AF09DCFE994}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {71D26AC8-A3F9-325F-A3B8-3AF09DCFE994}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {71D26AC8-A3F9-325F-A3B8-3AF09DCFE994}.Release|Win32.ActiveCfg = Release|Win32 + {71D26AC8-A3F9-325F-A3B8-3AF09DCFE994}.Release|Win32.Build.0 = Release|Win32 + {71D26AC8-A3F9-325F-A3B8-3AF09DCFE994}.Release|x64.ActiveCfg = Release|Win32 + {71D26AC8-A3F9-325F-A3B8-3AF09DCFE994}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {71D26AC8-A3F9-325F-A3B8-3AF09DCFE994}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {71D26AC8-A3F9-325F-A3B8-3AF09DCFE994}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 + {E5C90FD6-9338-3971-BDBE-8C0DD7E28A01}.Debug|Win32.ActiveCfg = Debug|Win32 + {E5C90FD6-9338-3971-BDBE-8C0DD7E28A01}.Debug|Win32.Build.0 = Debug|Win32 + {E5C90FD6-9338-3971-BDBE-8C0DD7E28A01}.Debug|x64.ActiveCfg = Debug|Win32 + {E5C90FD6-9338-3971-BDBE-8C0DD7E28A01}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {E5C90FD6-9338-3971-BDBE-8C0DD7E28A01}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {E5C90FD6-9338-3971-BDBE-8C0DD7E28A01}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {E5C90FD6-9338-3971-BDBE-8C0DD7E28A01}.Release|Win32.ActiveCfg = Release|Win32 + {E5C90FD6-9338-3971-BDBE-8C0DD7E28A01}.Release|Win32.Build.0 = Release|Win32 + {E5C90FD6-9338-3971-BDBE-8C0DD7E28A01}.Release|x64.ActiveCfg = Release|Win32 + {E5C90FD6-9338-3971-BDBE-8C0DD7E28A01}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {E5C90FD6-9338-3971-BDBE-8C0DD7E28A01}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {E5C90FD6-9338-3971-BDBE-8C0DD7E28A01}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 + {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A}.Debug|Win32.ActiveCfg = Debug|Win32 + {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A}.Debug|Win32.Build.0 = Debug|Win32 + {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A}.Debug|x64.ActiveCfg = Debug|Win32 + {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A}.Release|Win32.ActiveCfg = Release|Win32 + {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A}.Release|Win32.Build.0 = Release|Win32 + {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A}.Release|x64.ActiveCfg = Release|Win32 + {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {2956FD8C-FBAD-3A7D-A1AA-EA1C660A129A}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A}.Debug|Win32.ActiveCfg = Debug|Win32 + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A}.Debug|Win32.Build.0 = Debug|Win32 + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A}.Debug|x64.ActiveCfg = Debug|Win32 + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A}.Release|Win32.ActiveCfg = Release|Win32 + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A}.Release|Win32.Build.0 = Release|Win32 + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A}.Release|x64.ActiveCfg = Release|Win32 + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {E2EDCFD5-C98B-3EFE-9EDF-9B69F8F1379A}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 + {42513BC6-0B70-3C14-B3C5-4BC7E1BC0650}.Debug|Win32.ActiveCfg = Debug|Win32 + {42513BC6-0B70-3C14-B3C5-4BC7E1BC0650}.Debug|Win32.Build.0 = Debug|Win32 + {42513BC6-0B70-3C14-B3C5-4BC7E1BC0650}.Debug|x64.ActiveCfg = Debug|Win32 + {42513BC6-0B70-3C14-B3C5-4BC7E1BC0650}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {42513BC6-0B70-3C14-B3C5-4BC7E1BC0650}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {42513BC6-0B70-3C14-B3C5-4BC7E1BC0650}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {42513BC6-0B70-3C14-B3C5-4BC7E1BC0650}.Release|Win32.ActiveCfg = Release|Win32 + {42513BC6-0B70-3C14-B3C5-4BC7E1BC0650}.Release|Win32.Build.0 = Release|Win32 + {42513BC6-0B70-3C14-B3C5-4BC7E1BC0650}.Release|x64.ActiveCfg = Release|Win32 + {42513BC6-0B70-3C14-B3C5-4BC7E1BC0650}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {42513BC6-0B70-3C14-B3C5-4BC7E1BC0650}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {42513BC6-0B70-3C14-B3C5-4BC7E1BC0650}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 + {4362448C-BE8F-36A3-9B0E-50611BD41CF1}.Debug|Win32.ActiveCfg = Debug|Win32 + {4362448C-BE8F-36A3-9B0E-50611BD41CF1}.Debug|Win32.Build.0 = Debug|Win32 + {4362448C-BE8F-36A3-9B0E-50611BD41CF1}.Debug|x64.ActiveCfg = Debug|Win32 + {4362448C-BE8F-36A3-9B0E-50611BD41CF1}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {4362448C-BE8F-36A3-9B0E-50611BD41CF1}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {4362448C-BE8F-36A3-9B0E-50611BD41CF1}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {4362448C-BE8F-36A3-9B0E-50611BD41CF1}.Release|Win32.ActiveCfg = Release|Win32 + {4362448C-BE8F-36A3-9B0E-50611BD41CF1}.Release|Win32.Build.0 = Release|Win32 + {4362448C-BE8F-36A3-9B0E-50611BD41CF1}.Release|x64.ActiveCfg = Release|Win32 + {4362448C-BE8F-36A3-9B0E-50611BD41CF1}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {4362448C-BE8F-36A3-9B0E-50611BD41CF1}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {4362448C-BE8F-36A3-9B0E-50611BD41CF1}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 + {5E524D44-C5BF-336D-B812-E13DBC6B94B6}.Debug|Win32.ActiveCfg = Debug|Win32 + {5E524D44-C5BF-336D-B812-E13DBC6B94B6}.Debug|Win32.Build.0 = Debug|Win32 + {5E524D44-C5BF-336D-B812-E13DBC6B94B6}.Debug|x64.ActiveCfg = Debug|Win32 + {5E524D44-C5BF-336D-B812-E13DBC6B94B6}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {5E524D44-C5BF-336D-B812-E13DBC6B94B6}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {5E524D44-C5BF-336D-B812-E13DBC6B94B6}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {5E524D44-C5BF-336D-B812-E13DBC6B94B6}.Release|Win32.ActiveCfg = Release|Win32 + {5E524D44-C5BF-336D-B812-E13DBC6B94B6}.Release|Win32.Build.0 = Release|Win32 + {5E524D44-C5BF-336D-B812-E13DBC6B94B6}.Release|x64.ActiveCfg = Release|Win32 + {5E524D44-C5BF-336D-B812-E13DBC6B94B6}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {5E524D44-C5BF-336D-B812-E13DBC6B94B6}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {5E524D44-C5BF-336D-B812-E13DBC6B94B6}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 + {1C9DD759-1582-3F76-91A7-E2E93ED3EDA7}.Debug|Win32.ActiveCfg = Debug|Win32 + {1C9DD759-1582-3F76-91A7-E2E93ED3EDA7}.Debug|Win32.Build.0 = Debug|Win32 + {1C9DD759-1582-3F76-91A7-E2E93ED3EDA7}.Debug|x64.ActiveCfg = Debug|Win32 + {1C9DD759-1582-3F76-91A7-E2E93ED3EDA7}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {1C9DD759-1582-3F76-91A7-E2E93ED3EDA7}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {1C9DD759-1582-3F76-91A7-E2E93ED3EDA7}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {1C9DD759-1582-3F76-91A7-E2E93ED3EDA7}.Release|Win32.ActiveCfg = Release|Win32 + {1C9DD759-1582-3F76-91A7-E2E93ED3EDA7}.Release|Win32.Build.0 = Release|Win32 + {1C9DD759-1582-3F76-91A7-E2E93ED3EDA7}.Release|x64.ActiveCfg = Release|Win32 + {1C9DD759-1582-3F76-91A7-E2E93ED3EDA7}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {1C9DD759-1582-3F76-91A7-E2E93ED3EDA7}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {1C9DD759-1582-3F76-91A7-E2E93ED3EDA7}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 + {F998D6CB-C9D6-3B52-85BF-503E8965DD7E}.Debug|Win32.ActiveCfg = Debug|Win32 + {F998D6CB-C9D6-3B52-85BF-503E8965DD7E}.Debug|Win32.Build.0 = Debug|Win32 + {F998D6CB-C9D6-3B52-85BF-503E8965DD7E}.Debug|x64.ActiveCfg = Debug|Win32 + {F998D6CB-C9D6-3B52-85BF-503E8965DD7E}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {F998D6CB-C9D6-3B52-85BF-503E8965DD7E}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {F998D6CB-C9D6-3B52-85BF-503E8965DD7E}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {F998D6CB-C9D6-3B52-85BF-503E8965DD7E}.Release|Win32.ActiveCfg = Release|Win32 + {F998D6CB-C9D6-3B52-85BF-503E8965DD7E}.Release|Win32.Build.0 = Release|Win32 + {F998D6CB-C9D6-3B52-85BF-503E8965DD7E}.Release|x64.ActiveCfg = Release|Win32 + {F998D6CB-C9D6-3B52-85BF-503E8965DD7E}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {F998D6CB-C9D6-3B52-85BF-503E8965DD7E}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {F998D6CB-C9D6-3B52-85BF-503E8965DD7E}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 + {922B451B-BAFA-3F9B-803B-54138CE39381}.Debug|Win32.ActiveCfg = Debug|Win32 + {922B451B-BAFA-3F9B-803B-54138CE39381}.Debug|Win32.Build.0 = Debug|Win32 + {922B451B-BAFA-3F9B-803B-54138CE39381}.Debug|x64.ActiveCfg = Debug|Win32 + {922B451B-BAFA-3F9B-803B-54138CE39381}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {922B451B-BAFA-3F9B-803B-54138CE39381}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {922B451B-BAFA-3F9B-803B-54138CE39381}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {922B451B-BAFA-3F9B-803B-54138CE39381}.Release|Win32.ActiveCfg = Release|Win32 + {922B451B-BAFA-3F9B-803B-54138CE39381}.Release|Win32.Build.0 = Release|Win32 + {922B451B-BAFA-3F9B-803B-54138CE39381}.Release|x64.ActiveCfg = Release|Win32 + {922B451B-BAFA-3F9B-803B-54138CE39381}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {922B451B-BAFA-3F9B-803B-54138CE39381}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {922B451B-BAFA-3F9B-803B-54138CE39381}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 + {D6297D20-59AF-3E27-83CC-DE1EA62B27CE}.Debug|Win32.ActiveCfg = Debug|Win32 + {D6297D20-59AF-3E27-83CC-DE1EA62B27CE}.Debug|Win32.Build.0 = Debug|Win32 + {D6297D20-59AF-3E27-83CC-DE1EA62B27CE}.Debug|x64.ActiveCfg = Debug|Win32 + {D6297D20-59AF-3E27-83CC-DE1EA62B27CE}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {D6297D20-59AF-3E27-83CC-DE1EA62B27CE}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {D6297D20-59AF-3E27-83CC-DE1EA62B27CE}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {D6297D20-59AF-3E27-83CC-DE1EA62B27CE}.Release|Win32.ActiveCfg = Release|Win32 + {D6297D20-59AF-3E27-83CC-DE1EA62B27CE}.Release|Win32.Build.0 = Release|Win32 + {D6297D20-59AF-3E27-83CC-DE1EA62B27CE}.Release|x64.ActiveCfg = Release|Win32 + {D6297D20-59AF-3E27-83CC-DE1EA62B27CE}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {D6297D20-59AF-3E27-83CC-DE1EA62B27CE}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {D6297D20-59AF-3E27-83CC-DE1EA62B27CE}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 + {F85883CC-3DE4-3DA8-8A67-735428E10BF4}.Debug|Win32.ActiveCfg = Debug|Win32 + {F85883CC-3DE4-3DA8-8A67-735428E10BF4}.Debug|x64.ActiveCfg = Debug|Win32 + {F85883CC-3DE4-3DA8-8A67-735428E10BF4}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {F85883CC-3DE4-3DA8-8A67-735428E10BF4}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {F85883CC-3DE4-3DA8-8A67-735428E10BF4}.Release|Win32.ActiveCfg = Release|Win32 + {F85883CC-3DE4-3DA8-8A67-735428E10BF4}.Release|x64.ActiveCfg = Release|Win32 + {F85883CC-3DE4-3DA8-8A67-735428E10BF4}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {F85883CC-3DE4-3DA8-8A67-735428E10BF4}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 + {04AA7FE2-B767-3EE0-9607-97CE5A999562}.Debug|Win32.ActiveCfg = Debug|Win32 + {04AA7FE2-B767-3EE0-9607-97CE5A999562}.Debug|Win32.Build.0 = Debug|Win32 + {04AA7FE2-B767-3EE0-9607-97CE5A999562}.Debug|x64.ActiveCfg = Debug|Win32 + {04AA7FE2-B767-3EE0-9607-97CE5A999562}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {04AA7FE2-B767-3EE0-9607-97CE5A999562}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {04AA7FE2-B767-3EE0-9607-97CE5A999562}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {04AA7FE2-B767-3EE0-9607-97CE5A999562}.Release|Win32.ActiveCfg = Release|Win32 + {04AA7FE2-B767-3EE0-9607-97CE5A999562}.Release|Win32.Build.0 = Release|Win32 + {04AA7FE2-B767-3EE0-9607-97CE5A999562}.Release|x64.ActiveCfg = Release|Win32 + {04AA7FE2-B767-3EE0-9607-97CE5A999562}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {04AA7FE2-B767-3EE0-9607-97CE5A999562}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {04AA7FE2-B767-3EE0-9607-97CE5A999562}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 + {8EF7FEFB-B31C-3709-B1A3-1FCAB22D3D51}.Debug|Win32.ActiveCfg = Debug|Win32 + {8EF7FEFB-B31C-3709-B1A3-1FCAB22D3D51}.Debug|Win32.Build.0 = Debug|Win32 + {8EF7FEFB-B31C-3709-B1A3-1FCAB22D3D51}.Debug|x64.ActiveCfg = Debug|Win32 + {8EF7FEFB-B31C-3709-B1A3-1FCAB22D3D51}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {8EF7FEFB-B31C-3709-B1A3-1FCAB22D3D51}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {8EF7FEFB-B31C-3709-B1A3-1FCAB22D3D51}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {8EF7FEFB-B31C-3709-B1A3-1FCAB22D3D51}.Release|Win32.ActiveCfg = Release|Win32 + {8EF7FEFB-B31C-3709-B1A3-1FCAB22D3D51}.Release|Win32.Build.0 = Release|Win32 + {8EF7FEFB-B31C-3709-B1A3-1FCAB22D3D51}.Release|x64.ActiveCfg = Release|Win32 + {8EF7FEFB-B31C-3709-B1A3-1FCAB22D3D51}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {8EF7FEFB-B31C-3709-B1A3-1FCAB22D3D51}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {8EF7FEFB-B31C-3709-B1A3-1FCAB22D3D51}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 + {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF}.Debug|Win32.ActiveCfg = Debug|Win32 + {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF}.Debug|Win32.Build.0 = Debug|Win32 + {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF}.Debug|x64.ActiveCfg = Debug|Win32 + {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF}.Release|Win32.ActiveCfg = Release|Win32 + {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF}.Release|Win32.Build.0 = Release|Win32 + {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF}.Release|x64.ActiveCfg = Release|Win32 + {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {6BE9891D-D655-30ED-9EB9-B9BA3C219DDF}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 + {25A5C8EB-A739-30EA-AE01-4DDC56266398}.Debug|Win32.ActiveCfg = Debug|Win32 + {25A5C8EB-A739-30EA-AE01-4DDC56266398}.Debug|Win32.Build.0 = Debug|Win32 + {25A5C8EB-A739-30EA-AE01-4DDC56266398}.Debug|x64.ActiveCfg = Debug|Win32 + {25A5C8EB-A739-30EA-AE01-4DDC56266398}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {25A5C8EB-A739-30EA-AE01-4DDC56266398}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {25A5C8EB-A739-30EA-AE01-4DDC56266398}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {25A5C8EB-A739-30EA-AE01-4DDC56266398}.Release|Win32.ActiveCfg = Release|Win32 + {25A5C8EB-A739-30EA-AE01-4DDC56266398}.Release|Win32.Build.0 = Release|Win32 + {25A5C8EB-A739-30EA-AE01-4DDC56266398}.Release|x64.ActiveCfg = Release|Win32 + {25A5C8EB-A739-30EA-AE01-4DDC56266398}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {25A5C8EB-A739-30EA-AE01-4DDC56266398}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {25A5C8EB-A739-30EA-AE01-4DDC56266398}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 + {7BFCA077-2FEF-34D5-8A79-1F8F4D3022E4}.Debug|Win32.ActiveCfg = Debug|Win32 + {7BFCA077-2FEF-34D5-8A79-1F8F4D3022E4}.Debug|Win32.Build.0 = Debug|Win32 + {7BFCA077-2FEF-34D5-8A79-1F8F4D3022E4}.Debug|x64.ActiveCfg = Debug|Win32 + {7BFCA077-2FEF-34D5-8A79-1F8F4D3022E4}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {7BFCA077-2FEF-34D5-8A79-1F8F4D3022E4}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {7BFCA077-2FEF-34D5-8A79-1F8F4D3022E4}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {7BFCA077-2FEF-34D5-8A79-1F8F4D3022E4}.Release|Win32.ActiveCfg = Release|Win32 + {7BFCA077-2FEF-34D5-8A79-1F8F4D3022E4}.Release|Win32.Build.0 = Release|Win32 + {7BFCA077-2FEF-34D5-8A79-1F8F4D3022E4}.Release|x64.ActiveCfg = Release|Win32 + {7BFCA077-2FEF-34D5-8A79-1F8F4D3022E4}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {7BFCA077-2FEF-34D5-8A79-1F8F4D3022E4}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {7BFCA077-2FEF-34D5-8A79-1F8F4D3022E4}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 + {5A72CAB6-2338-4984-9FE5-AED77A2824F8}.Debug|Win32.ActiveCfg = Debug|Win32 + {5A72CAB6-2338-4984-9FE5-AED77A2824F8}.Debug|Win32.Build.0 = Debug|Win32 + {5A72CAB6-2338-4984-9FE5-AED77A2824F8}.Debug|x64.ActiveCfg = Debug|x64 + {5A72CAB6-2338-4984-9FE5-AED77A2824F8}.Debug|x64.Build.0 = Debug|x64 + {5A72CAB6-2338-4984-9FE5-AED77A2824F8}.MinSizeRel|Win32.ActiveCfg = Release|Win32 + {5A72CAB6-2338-4984-9FE5-AED77A2824F8}.MinSizeRel|Win32.Build.0 = Release|Win32 + {5A72CAB6-2338-4984-9FE5-AED77A2824F8}.MinSizeRel|x64.ActiveCfg = Release|x64 + {5A72CAB6-2338-4984-9FE5-AED77A2824F8}.MinSizeRel|x64.Build.0 = Release|x64 + {5A72CAB6-2338-4984-9FE5-AED77A2824F8}.Release|Win32.ActiveCfg = Release|Win32 + {5A72CAB6-2338-4984-9FE5-AED77A2824F8}.Release|Win32.Build.0 = Release|Win32 + {5A72CAB6-2338-4984-9FE5-AED77A2824F8}.Release|x64.ActiveCfg = Release|x64 + {5A72CAB6-2338-4984-9FE5-AED77A2824F8}.Release|x64.Build.0 = Release|x64 + {5A72CAB6-2338-4984-9FE5-AED77A2824F8}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 + {5A72CAB6-2338-4984-9FE5-AED77A2824F8}.RelWithDebInfo|Win32.Build.0 = Release|Win32 + {5A72CAB6-2338-4984-9FE5-AED77A2824F8}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {5A72CAB6-2338-4984-9FE5-AED77A2824F8}.RelWithDebInfo|x64.Build.0 = Release|x64 + {BB0FB695-74B7-473B-B034-68F9FF0F3ED0}.Debug|Win32.ActiveCfg = Debug|Win32 + {BB0FB695-74B7-473B-B034-68F9FF0F3ED0}.Debug|Win32.Build.0 = Debug|Win32 + {BB0FB695-74B7-473B-B034-68F9FF0F3ED0}.Debug|x64.ActiveCfg = Debug|x64 + {BB0FB695-74B7-473B-B034-68F9FF0F3ED0}.Debug|x64.Build.0 = Debug|x64 + {BB0FB695-74B7-473B-B034-68F9FF0F3ED0}.MinSizeRel|Win32.ActiveCfg = Release|Win32 + {BB0FB695-74B7-473B-B034-68F9FF0F3ED0}.MinSizeRel|Win32.Build.0 = Release|Win32 + {BB0FB695-74B7-473B-B034-68F9FF0F3ED0}.MinSizeRel|x64.ActiveCfg = Release|x64 + {BB0FB695-74B7-473B-B034-68F9FF0F3ED0}.MinSizeRel|x64.Build.0 = Release|x64 + {BB0FB695-74B7-473B-B034-68F9FF0F3ED0}.Release|Win32.ActiveCfg = Release|Win32 + {BB0FB695-74B7-473B-B034-68F9FF0F3ED0}.Release|Win32.Build.0 = Release|Win32 + {BB0FB695-74B7-473B-B034-68F9FF0F3ED0}.Release|x64.ActiveCfg = Release|x64 + {BB0FB695-74B7-473B-B034-68F9FF0F3ED0}.Release|x64.Build.0 = Release|x64 + {BB0FB695-74B7-473B-B034-68F9FF0F3ED0}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 + {BB0FB695-74B7-473B-B034-68F9FF0F3ED0}.RelWithDebInfo|Win32.Build.0 = Release|Win32 + {BB0FB695-74B7-473B-B034-68F9FF0F3ED0}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {BB0FB695-74B7-473B-B034-68F9FF0F3ED0}.RelWithDebInfo|x64.Build.0 = Release|x64 + {05071389-F9F3-4C44-B155-A15E43CA3FFD}.Debug|Win32.ActiveCfg = Debug|Win32 + {05071389-F9F3-4C44-B155-A15E43CA3FFD}.Debug|Win32.Build.0 = Debug|Win32 + {05071389-F9F3-4C44-B155-A15E43CA3FFD}.Debug|x64.ActiveCfg = Debug|x64 + {05071389-F9F3-4C44-B155-A15E43CA3FFD}.Debug|x64.Build.0 = Debug|x64 + {05071389-F9F3-4C44-B155-A15E43CA3FFD}.MinSizeRel|Win32.ActiveCfg = Release|Win32 + {05071389-F9F3-4C44-B155-A15E43CA3FFD}.MinSizeRel|Win32.Build.0 = Release|Win32 + {05071389-F9F3-4C44-B155-A15E43CA3FFD}.MinSizeRel|x64.ActiveCfg = Release|x64 + {05071389-F9F3-4C44-B155-A15E43CA3FFD}.MinSizeRel|x64.Build.0 = Release|x64 + {05071389-F9F3-4C44-B155-A15E43CA3FFD}.Release|Win32.ActiveCfg = Release|Win32 + {05071389-F9F3-4C44-B155-A15E43CA3FFD}.Release|Win32.Build.0 = Release|Win32 + {05071389-F9F3-4C44-B155-A15E43CA3FFD}.Release|x64.ActiveCfg = Release|x64 + {05071389-F9F3-4C44-B155-A15E43CA3FFD}.Release|x64.Build.0 = Release|x64 + {05071389-F9F3-4C44-B155-A15E43CA3FFD}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 + {05071389-F9F3-4C44-B155-A15E43CA3FFD}.RelWithDebInfo|Win32.Build.0 = Release|Win32 + {05071389-F9F3-4C44-B155-A15E43CA3FFD}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {05071389-F9F3-4C44-B155-A15E43CA3FFD}.RelWithDebInfo|x64.Build.0 = Release|x64 + {363DCB11-CFEF-4E12-BE70-CE3C2D695ECA}.Debug|Win32.ActiveCfg = Debug|Win32 + {363DCB11-CFEF-4E12-BE70-CE3C2D695ECA}.Debug|Win32.Build.0 = Debug|Win32 + {363DCB11-CFEF-4E12-BE70-CE3C2D695ECA}.Debug|x64.ActiveCfg = Debug|x64 + {363DCB11-CFEF-4E12-BE70-CE3C2D695ECA}.Debug|x64.Build.0 = Debug|x64 + {363DCB11-CFEF-4E12-BE70-CE3C2D695ECA}.MinSizeRel|Win32.ActiveCfg = Release|Win32 + {363DCB11-CFEF-4E12-BE70-CE3C2D695ECA}.MinSizeRel|Win32.Build.0 = Release|Win32 + {363DCB11-CFEF-4E12-BE70-CE3C2D695ECA}.MinSizeRel|x64.ActiveCfg = Release|x64 + {363DCB11-CFEF-4E12-BE70-CE3C2D695ECA}.MinSizeRel|x64.Build.0 = Release|x64 + {363DCB11-CFEF-4E12-BE70-CE3C2D695ECA}.Release|Win32.ActiveCfg = Release|Win32 + {363DCB11-CFEF-4E12-BE70-CE3C2D695ECA}.Release|Win32.Build.0 = Release|Win32 + {363DCB11-CFEF-4E12-BE70-CE3C2D695ECA}.Release|x64.ActiveCfg = Release|x64 + {363DCB11-CFEF-4E12-BE70-CE3C2D695ECA}.Release|x64.Build.0 = Release|x64 + {363DCB11-CFEF-4E12-BE70-CE3C2D695ECA}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 + {363DCB11-CFEF-4E12-BE70-CE3C2D695ECA}.RelWithDebInfo|Win32.Build.0 = Release|Win32 + {363DCB11-CFEF-4E12-BE70-CE3C2D695ECA}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {363DCB11-CFEF-4E12-BE70-CE3C2D695ECA}.RelWithDebInfo|x64.Build.0 = Release|x64 + {BE66C1CF-258B-4BD1-9ED5-7BD4235342D1}.Debug|Win32.ActiveCfg = Debug|Win32 + {BE66C1CF-258B-4BD1-9ED5-7BD4235342D1}.Debug|Win32.Build.0 = Debug|Win32 + {BE66C1CF-258B-4BD1-9ED5-7BD4235342D1}.Debug|x64.ActiveCfg = Debug|x64 + {BE66C1CF-258B-4BD1-9ED5-7BD4235342D1}.Debug|x64.Build.0 = Debug|x64 + {BE66C1CF-258B-4BD1-9ED5-7BD4235342D1}.MinSizeRel|Win32.ActiveCfg = Release|Win32 + {BE66C1CF-258B-4BD1-9ED5-7BD4235342D1}.MinSizeRel|Win32.Build.0 = Release|Win32 + {BE66C1CF-258B-4BD1-9ED5-7BD4235342D1}.MinSizeRel|x64.ActiveCfg = Release|x64 + {BE66C1CF-258B-4BD1-9ED5-7BD4235342D1}.MinSizeRel|x64.Build.0 = Release|x64 + {BE66C1CF-258B-4BD1-9ED5-7BD4235342D1}.Release|Win32.ActiveCfg = Release|Win32 + {BE66C1CF-258B-4BD1-9ED5-7BD4235342D1}.Release|Win32.Build.0 = Release|Win32 + {BE66C1CF-258B-4BD1-9ED5-7BD4235342D1}.Release|x64.ActiveCfg = Release|x64 + {BE66C1CF-258B-4BD1-9ED5-7BD4235342D1}.Release|x64.Build.0 = Release|x64 + {BE66C1CF-258B-4BD1-9ED5-7BD4235342D1}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 + {BE66C1CF-258B-4BD1-9ED5-7BD4235342D1}.RelWithDebInfo|Win32.Build.0 = Release|Win32 + {BE66C1CF-258B-4BD1-9ED5-7BD4235342D1}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {BE66C1CF-258B-4BD1-9ED5-7BD4235342D1}.RelWithDebInfo|x64.Build.0 = Release|x64 + {2A5089E9-EF05-48A2-B5A6-22723BAF9E78}.Debug|Win32.ActiveCfg = Debug|Win32 + {2A5089E9-EF05-48A2-B5A6-22723BAF9E78}.Debug|Win32.Build.0 = Debug|Win32 + {2A5089E9-EF05-48A2-B5A6-22723BAF9E78}.Debug|x64.ActiveCfg = Debug|x64 + {2A5089E9-EF05-48A2-B5A6-22723BAF9E78}.Debug|x64.Build.0 = Debug|x64 + {2A5089E9-EF05-48A2-B5A6-22723BAF9E78}.MinSizeRel|Win32.ActiveCfg = Release|Win32 + {2A5089E9-EF05-48A2-B5A6-22723BAF9E78}.MinSizeRel|Win32.Build.0 = Release|Win32 + {2A5089E9-EF05-48A2-B5A6-22723BAF9E78}.MinSizeRel|x64.ActiveCfg = Release|x64 + {2A5089E9-EF05-48A2-B5A6-22723BAF9E78}.MinSizeRel|x64.Build.0 = Release|x64 + {2A5089E9-EF05-48A2-B5A6-22723BAF9E78}.Release|Win32.ActiveCfg = Release|Win32 + {2A5089E9-EF05-48A2-B5A6-22723BAF9E78}.Release|Win32.Build.0 = Release|Win32 + {2A5089E9-EF05-48A2-B5A6-22723BAF9E78}.Release|x64.ActiveCfg = Release|x64 + {2A5089E9-EF05-48A2-B5A6-22723BAF9E78}.Release|x64.Build.0 = Release|x64 + {2A5089E9-EF05-48A2-B5A6-22723BAF9E78}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 + {2A5089E9-EF05-48A2-B5A6-22723BAF9E78}.RelWithDebInfo|Win32.Build.0 = Release|Win32 + {2A5089E9-EF05-48A2-B5A6-22723BAF9E78}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {2A5089E9-EF05-48A2-B5A6-22723BAF9E78}.RelWithDebInfo|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {7C828009-CA58-3FF8-A565-EE3F72B20006} + EndGlobalSection +EndGlobal diff --git a/get/ConvertUTF/ConvertUTF.c b/get/ConvertUTF/ConvertUTF.c new file mode 100644 index 0000000000..0abde66fb4 --- /dev/null +++ b/get/ConvertUTF/ConvertUTF.c @@ -0,0 +1,589 @@ +/*===--- ConvertUTF.c - Universal Character Names conversions ---------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===------------------------------------------------------------------------=*/ +/* + * Copyright 2001-2004 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + +/* --------------------------------------------------------------------- + + Conversions between UTF32, UTF-16, and UTF-8. Source code file. + Author: Mark E. Davis, 1994. + Rev History: Rick McGowan, fixes & updates May 2001. + Sept 2001: fixed const & error conditions per + mods suggested by S. Parent & A. Lillich. + June 2002: Tim Dodd added detection and handling of incomplete + source sequences, enhanced error detection, added casts + to eliminate compiler warnings. + July 2003: slight mods to back out aggressive FFFE detection. + Jan 2004: updated switches in from-UTF8 conversions. + Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions. + + See the header file "ConvertUTF.h" for complete documentation. + +------------------------------------------------------------------------ */ + + +#include "ConvertUTF.h" +#ifdef CVTUTF_DEBUG +#include +#endif + +#include + +static const int halfShift = 10; /* used for shifting by 10 bits */ + +static const UTF32 halfBase = 0x0010000UL; +static const UTF32 halfMask = 0x3FFUL; + +#define UNI_SUR_HIGH_START (UTF32)0xD800 +#define UNI_SUR_HIGH_END (UTF32)0xDBFF +#define UNI_SUR_LOW_START (UTF32)0xDC00 +#define UNI_SUR_LOW_END (UTF32)0xDFFF +#define false 0 +#define true 1 + +/* --------------------------------------------------------------------- */ + +/* + * Index into the table below with the first byte of a UTF-8 sequence to + * get the number of trailing bytes that are supposed to follow it. + * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is + * left as-is for anyone who may want to do such conversion, which was + * allowed in earlier algorithms. + */ +static const char trailingBytesForUTF8[256] = { + 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, + 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, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 +}; + +/* + * Magic values subtracted from a buffer value during UTF8 conversion. + * This table contains as many values as there might be trailing bytes + * in a UTF-8 sequence. + */ +static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, + 0x03C82080UL, 0xFA082080UL, 0x82082080UL }; + +/* + * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed + * into the first byte, depending on how many bytes follow. There are + * as many entries in this table as there are UTF-8 sequence types. + * (I.e., one byte sequence, two byte... etc.). Remember that sequencs + * for *legal* UTF-8 will be 4 or fewer bytes total. + */ +static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + +/* --------------------------------------------------------------------- */ + +/* The interface converts a whole buffer to avoid function-call overhead. + * Constants have been gathered. Loops & conditionals have been removed as + * much as possible for efficiency, in favor of drop-through switches. + * (See "Note A" at the bottom of the file for equivalent code.) + * If your compiler supports it, the "isLegalUTF8" call can be turned + * into an inline function. + */ + + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF32toUTF16 ( + const UTF32** sourceStart, const UTF32* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF32* source = *sourceStart; + UTF16* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch; + if (target >= targetEnd) { + result = targetExhausted; break; + } + ch = *source++; + if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ + /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + if (flags == strictConversion) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + *target++ = (UTF16)ch; /* normal case */ + } + } else if (ch > UNI_MAX_LEGAL_UTF32) { + if (flags == strictConversion) { + result = sourceIllegal; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + /* target is a character in range 0xFFFF - 0x10FFFF. */ + if (target + 1 >= targetEnd) { + --source; /* Back up source pointer! */ + result = targetExhausted; break; + } + ch -= halfBase; + *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); + *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); + } + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF16toUTF32 ( + const UTF16** sourceStart, const UTF16* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF16* source = *sourceStart; + UTF32* target = *targetStart; + UTF32 ch, ch2; + while (source < sourceEnd) { + const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ + ch = *source++; + /* If we have a surrogate pair, convert to UTF32 first. */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { + /* If the 16 bits following the high surrogate are in the source buffer... */ + if (source < sourceEnd) { + ch2 = *source; + /* If it's a low surrogate, convert to UTF32. */ + if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { + ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + + (ch2 - UNI_SUR_LOW_START) + halfBase; + ++source; + } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } else { /* We don't have the 16 bits following the high surrogate. */ + --source; /* return to the high surrogate */ + result = sourceExhausted; + break; + } + } else if (flags == strictConversion) { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + if (target >= targetEnd) { + source = oldSource; /* Back up source pointer! */ + result = targetExhausted; break; + } + *target++ = ch; + } + *sourceStart = source; + *targetStart = target; +#ifdef CVTUTF_DEBUG +if (result == sourceIllegal) { + fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2); + fflush(stderr); +} +#endif + return result; +} +ConversionResult ConvertUTF16toUTF8 ( + const UTF16** sourceStart, const UTF16* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF16* source = *sourceStart; + UTF8* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch; + unsigned short bytesToWrite = 0; + const UTF32 byteMask = 0xBF; + const UTF32 byteMark = 0x80; + const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ + ch = *source++; + /* If we have a surrogate pair, convert to UTF32 first. */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { + /* If the 16 bits following the high surrogate are in the source buffer... */ + if (source < sourceEnd) { + UTF32 ch2 = *source; + /* If it's a low surrogate, convert to UTF32. */ + if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { + ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + + (ch2 - UNI_SUR_LOW_START) + halfBase; + ++source; + } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } else { /* We don't have the 16 bits following the high surrogate. */ + --source; /* return to the high surrogate */ + result = sourceExhausted; + break; + } + } else if (flags == strictConversion) { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + /* Figure out how many bytes the result will require */ + if (ch < (UTF32)0x80) { bytesToWrite = 1; + } else if (ch < (UTF32)0x800) { bytesToWrite = 2; + } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; + } else if (ch < (UTF32)0x110000) { bytesToWrite = 4; + } else { bytesToWrite = 3; + ch = UNI_REPLACEMENT_CHAR; + } + + target += bytesToWrite; + if (target > targetEnd) { + source = oldSource; /* Back up source pointer! */ + target -= bytesToWrite; result = targetExhausted; break; + } + switch (bytesToWrite) { /* note: everything falls through. */ + case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]); + } + target += bytesToWrite; + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF32toUTF8 ( + const UTF32** sourceStart, const UTF32* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF32* source = *sourceStart; + UTF8* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch; + unsigned short bytesToWrite = 0; + const UTF32 byteMask = 0xBF; + const UTF32 byteMark = 0x80; + ch = *source++; + if (flags == strictConversion ) { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + /* + * Figure out how many bytes the result will require. Turn any + * illegally large UTF32 things (> Plane 17) into replacement chars. + */ + if (ch < (UTF32)0x80) { bytesToWrite = 1; + } else if (ch < (UTF32)0x800) { bytesToWrite = 2; + } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; + } else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4; + } else { bytesToWrite = 3; + ch = UNI_REPLACEMENT_CHAR; + result = sourceIllegal; + } + + target += bytesToWrite; + if (target > targetEnd) { + --source; /* Back up source pointer! */ + target -= bytesToWrite; result = targetExhausted; break; + } + switch (bytesToWrite) { /* note: everything falls through. */ + case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]); + } + target += bytesToWrite; + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +/* + * Utility routine to tell whether a sequence of bytes is legal UTF-8. + * This must be called with the length pre-determined by the first byte. + * If not calling this from ConvertUTF8to*, then the length can be set by: + * length = trailingBytesForUTF8[*source]+1; + * and the sequence is illegal right away if there aren't that many bytes + * available. + * If presented with a length > 4, this returns false. The Unicode + * definition of UTF-8 goes up to 4-byte sequences. + */ + +static Boolean isLegalUTF8(const UTF8 *source, int length) { + UTF8 a; + const UTF8 *srcptr = source+length; + switch (length) { + default: return false; + /* Everything else falls through when "true"... */ + case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + case 2: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + + switch (*source) { + /* no fall-through in this inner switch */ + case 0xE0: if (a < 0xA0) return false; break; + case 0xED: if (a > 0x9F) return false; break; + case 0xF0: if (a < 0x90) return false; break; + case 0xF4: if (a > 0x8F) return false; break; + default: if (a < 0x80) return false; + } + + case 1: if (*source >= 0x80 && *source < 0xC2) return false; + } + if (*source > 0xF4) return false; + return true; +} + +/* --------------------------------------------------------------------- */ + +/* + * Exported function to return whether a UTF-8 sequence is legal or not. + * This is not used here; it's just exported. + */ +Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) { + int length = trailingBytesForUTF8[*source]+1; + if (length > sourceEnd - source) { + return false; + } + return isLegalUTF8(source, length); +} + +/* --------------------------------------------------------------------- */ + +/* + * Exported function to return the total number of bytes in a codepoint + * represented in UTF-8, given the value of the first byte. + */ +unsigned getNumBytesForUTF8(UTF8 first) { + return trailingBytesForUTF8[first] + 1; +} + +int getUTF8StringLength(const UTF8* utf8) +{ + const UTF8** source = &utf8; + const UTF8* sourceEnd = utf8 + strlen((const char*)utf8); + int ret = 0; + while (*source != sourceEnd) { + int length = trailingBytesForUTF8[**source] + 1; + if (length > sourceEnd - *source || !isLegalUTF8(*source, length)) + return 0; + *source += length; + ++ret; + } + return ret; +} + + +/* --------------------------------------------------------------------- */ + +/* + * Exported function to return whether a UTF-8 string is legal or not. + * This is not used here; it's just exported. + */ +Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd) { + while (*source != sourceEnd) { + int length = trailingBytesForUTF8[**source] + 1; + if (length > sourceEnd - *source || !isLegalUTF8(*source, length)) + return false; + *source += length; + } + return true; +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF8toUTF16 ( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF8* source = *sourceStart; + UTF16* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch = 0; + unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; + if (extraBytesToRead >= sourceEnd - source) { + result = sourceExhausted; break; + } + /* Do this check whether lenient or strict */ + if (!isLegalUTF8(source, extraBytesToRead+1)) { + result = sourceIllegal; + break; + } + /* + * The cases all fall through. See "Note A" below. + */ + switch (extraBytesToRead) { + case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ + case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ + case 3: ch += *source++; ch <<= 6; + case 2: ch += *source++; ch <<= 6; + case 1: ch += *source++; ch <<= 6; + case 0: ch += *source++; + } + ch -= offsetsFromUTF8[extraBytesToRead]; + + if (target >= targetEnd) { + source -= (extraBytesToRead+1); /* Back up source pointer! */ + result = targetExhausted; break; + } + if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + if (flags == strictConversion) { + source -= (extraBytesToRead+1); /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + *target++ = (UTF16)ch; /* normal case */ + } + } else if (ch > UNI_MAX_UTF16) { + if (flags == strictConversion) { + result = sourceIllegal; + source -= (extraBytesToRead+1); /* return to the start */ + break; /* Bail out; shouldn't continue */ + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + /* target is a character in range 0xFFFF - 0x10FFFF. */ + if (target + 1 >= targetEnd) { + source -= (extraBytesToRead+1); /* Back up source pointer! */ + result = targetExhausted; break; + } + ch -= halfBase; + *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); + *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); + } + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF8toUTF32 ( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF8* source = *sourceStart; + UTF32* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch = 0; + unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; + if (extraBytesToRead >= sourceEnd - source) { + result = sourceExhausted; break; + } + /* Do this check whether lenient or strict */ + if (!isLegalUTF8(source, extraBytesToRead+1)) { + result = sourceIllegal; + break; + } + /* + * The cases all fall through. See "Note A" below. + */ + switch (extraBytesToRead) { + case 5: ch += *source++; ch <<= 6; + case 4: ch += *source++; ch <<= 6; + case 3: ch += *source++; ch <<= 6; + case 2: ch += *source++; ch <<= 6; + case 1: ch += *source++; ch <<= 6; + case 0: ch += *source++; + } + ch -= offsetsFromUTF8[extraBytesToRead]; + + if (target >= targetEnd) { + source -= (extraBytesToRead+1); /* Back up the source pointer! */ + result = targetExhausted; break; + } + if (ch <= UNI_MAX_LEGAL_UTF32) { + /* + * UTF-16 surrogate values are illegal in UTF-32, and anything + * over Plane 17 (> 0x10FFFF) is illegal. + */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + if (flags == strictConversion) { + source -= (extraBytesToRead+1); /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + *target++ = ch; + } + } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */ + result = sourceIllegal; + *target++ = UNI_REPLACEMENT_CHAR; + } + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- + + Note A. + The fall-through switches in UTF-8 reading code save a + temp variable, some decrements & conditionals. The switches + are equivalent to the following loop: + { + int tmpBytesToRead = extraBytesToRead+1; + do { + ch += *source++; + --tmpBytesToRead; + if (tmpBytesToRead) ch <<= 6; + } while (tmpBytesToRead > 0); + } + In UTF-8 writing code, the switches on "bytesToWrite" are + similarly unrolled loops. + + --------------------------------------------------------------------- */ diff --git a/get/ConvertUTF/ConvertUTF.h b/get/ConvertUTF/ConvertUTF.h new file mode 100644 index 0000000000..3ef4ca14b7 --- /dev/null +++ b/get/ConvertUTF/ConvertUTF.h @@ -0,0 +1,253 @@ +/*===--- ConvertUTF.h - Universal Character Names conversions ---------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *==------------------------------------------------------------------------==*/ +/* + * Copyright 2001-2004 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + +/* --------------------------------------------------------------------- + + Conversions between UTF32, UTF-16, and UTF-8. Header file. + + Several funtions are included here, forming a complete set of + conversions between the three formats. UTF-7 is not included + here, but is handled in a separate source file. + + Each of these routines takes pointers to input buffers and output + buffers. The input buffers are const. + + Each routine converts the text between *sourceStart and sourceEnd, + putting the result into the buffer between *targetStart and + targetEnd. Note: the end pointers are *after* the last item: e.g. + *(sourceEnd - 1) is the last item. + + The return result indicates whether the conversion was successful, + and if not, whether the problem was in the source or target buffers. + (Only the first encountered problem is indicated.) + + After the conversion, *sourceStart and *targetStart are both + updated to point to the end of last text successfully converted in + the respective buffers. + + Input parameters: + sourceStart - pointer to a pointer to the source buffer. + The contents of this are modified on return so that + it points at the next thing to be converted. + targetStart - similarly, pointer to pointer to the target buffer. + sourceEnd, targetEnd - respectively pointers to the ends of the + two buffers, for overflow checking only. + + These conversion functions take a ConversionFlags argument. When this + flag is set to strict, both irregular sequences and isolated surrogates + will cause an error. When the flag is set to lenient, both irregular + sequences and isolated surrogates are converted. + + Whether the flag is strict or lenient, all illegal sequences will cause + an error return. This includes sequences such as: , , + or in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code + must check for illegal sequences. + + When the flag is set to lenient, characters over 0x10FFFF are converted + to the replacement character; otherwise (when the flag is set to strict) + they constitute an error. + + Output parameters: + The value "sourceIllegal" is returned from some routines if the input + sequence is malformed. When "sourceIllegal" is returned, the source + value will point to the illegal value that caused the problem. E.g., + in UTF-8 when a sequence is malformed, it points to the start of the + malformed sequence. + + Author: Mark E. Davis, 1994. + Rev History: Rick McGowan, fixes & updates May 2001. + Fixes & updates, Sept 2001. + +------------------------------------------------------------------------ */ + +#ifndef LLVM_SUPPORT_CONVERTUTF_H +#define LLVM_SUPPORT_CONVERTUTF_H + +#include /* ptrdiff_t */ +/* --------------------------------------------------------------------- + The following 4 definitions are compiler-specific. + The C standard does not guarantee that wchar_t has at least + 16 bits, so wchar_t is no less portable than unsigned short! + All should be unsigned values to avoid sign extension during + bit mask & shift operations. +------------------------------------------------------------------------ */ + +typedef unsigned int UTF32; /* at least 32 bits */ +typedef unsigned short UTF16; /* at least 16 bits */ +typedef unsigned char UTF8; /* typically 8 bits */ +typedef unsigned char Boolean; /* 0 or 1 */ + +/* Some fundamental constants */ +#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD +#define UNI_MAX_BMP (UTF32)0x0000FFFF +#define UNI_MAX_UTF16 (UTF32)0x0010FFFF +#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF +#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF + +#define UNI_MAX_UTF8_BYTES_PER_CODE_POINT 4 + +#define UNI_UTF16_BYTE_ORDER_MARK_NATIVE 0xFEFF +#define UNI_UTF16_BYTE_ORDER_MARK_SWAPPED 0xFFFE + +typedef enum { + conversionOK, /* conversion successful */ + sourceExhausted, /* partial character in source, but hit end */ + targetExhausted, /* insuff. room in target for conversion */ + sourceIllegal /* source sequence is illegal/malformed */ +} ConversionResult; + +typedef enum { + strictConversion = 0, + lenientConversion +} ConversionFlags; + +/* This is for C++ and does no harm in C */ +#ifdef __cplusplus +extern "C" { +#endif + +ConversionResult ConvertUTF8toUTF16 ( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF8toUTF32 ( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF16toUTF8 ( + const UTF16** sourceStart, const UTF16* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF32toUTF8 ( + const UTF32** sourceStart, const UTF32* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF16toUTF32 ( + const UTF16** sourceStart, const UTF16* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF32toUTF16 ( + const UTF32** sourceStart, const UTF32* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); + +Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd); + +Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd); + +unsigned getNumBytesForUTF8(UTF8 firstByte); + +int getUTF8StringLength(const UTF8* utf8); + +#ifdef __cplusplus +} + +/*************************************************************************/ +/* Below are LLVM-specific wrappers of the functions above. */ + +//#include "llvm/ADT/ArrayRef.h" +//#include "llvm/ADT/StringRef.h" + +#include +#include +namespace llvm { + +/** + * Convert an UTF8 StringRef to UTF8, UTF16, or UTF32 depending on + * WideCharWidth. The converted data is written to ResultPtr, which needs to + * point to at least WideCharWidth * (Source.Size() + 1) bytes. On success, + * ResultPtr will point one after the end of the copied string. On failure, + * ResultPtr will not be changed, and ErrorPtr will be set to the location of + * the first character which could not be converted. + * \return true on success. + */ +bool ConvertUTF8toWide(unsigned WideCharWidth, const std::string& Source, + char *&ResultPtr, const UTF8 *&ErrorPtr); + +/** + * Convert an Unicode code point to UTF8 sequence. + * + * \param Source a Unicode code point. + * \param [in,out] ResultPtr pointer to the output buffer, needs to be at least + * \c UNI_MAX_UTF8_BYTES_PER_CODE_POINT bytes. On success \c ResultPtr is + * updated one past end of the converted sequence. + * + * \returns true on success. + */ +bool ConvertCodePointToUTF8(unsigned Source, char *&ResultPtr); + +/** + * Convert the first UTF8 sequence in the given source buffer to a UTF32 + * code point. + * + * \param [in,out] source A pointer to the source buffer. If the conversion + * succeeds, this pointer will be updated to point to the byte just past the + * end of the converted sequence. + * \param sourceEnd A pointer just past the end of the source buffer. + * \param [out] target The converted code + * \param flags Whether the conversion is strict or lenient. + * + * \returns conversionOK on success + * + * \sa ConvertUTF8toUTF32 + */ +static inline ConversionResult convertUTF8Sequence(const UTF8 **source, + const UTF8 *sourceEnd, + UTF32 *target, + ConversionFlags flags) { + if (*source == sourceEnd) + return sourceExhausted; + unsigned size = getNumBytesForUTF8(**source); + if ((ptrdiff_t)size > sourceEnd - *source) + return sourceExhausted; + return ConvertUTF8toUTF32(source, *source + size, &target, target + 1, flags); +} + +/** + * Returns true if a blob of text starts with a UTF-16 big or little endian byte + * order mark. + */ +bool hasUTF16ByteOrderMark(const char* SrcBytes, size_t len); + +/** + * Converts a stream of raw bytes assumed to be UTF16 into a UTF8 std::string. + * + * \param [in] SrcBytes A buffer of what is assumed to be UTF-16 encoded text. + * \param [out] Out Converted UTF-8 is stored here on success. + * \returns true on success + */ +bool convertUTF16ToUTF8String(const std::u16string& utf16, std::string &Out); + +} /* end namespace llvm */ + +#endif + +/* --------------------------------------------------------------------- */ + +#endif diff --git a/get/ConvertUTF/ConvertUTFWrapper.cpp b/get/ConvertUTF/ConvertUTFWrapper.cpp new file mode 100644 index 0000000000..278bdd4897 --- /dev/null +++ b/get/ConvertUTF/ConvertUTFWrapper.cpp @@ -0,0 +1,144 @@ +//===-- ConvertUTFWrapper.cpp - Wrap ConvertUTF.h with clang data types -----=== +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ConvertUTF.h" +//#include "llvm/Support/SwapByteOrder.h" +#include +#include +#include // uint16_t +#include +#include + +namespace llvm { + +bool ConvertUTF8toWide(unsigned WideCharWidth, const std::string& Source, + char *&ResultPtr, const UTF8 *&ErrorPtr) { + assert(WideCharWidth == 1 || WideCharWidth == 2 || WideCharWidth == 4); + ConversionResult result = conversionOK; + // Copy the character span over. + if (WideCharWidth == 1) { + const UTF8 *Pos = reinterpret_cast(Source.data()); + if (!isLegalUTF8String(&Pos, reinterpret_cast(Source.data() + Source.length()))) { + result = sourceIllegal; + ErrorPtr = Pos; + } else { + memcpy(ResultPtr, Source.data(), Source.size()); + ResultPtr += Source.size(); + } + } else if (WideCharWidth == 2) { + const UTF8 *sourceStart = (const UTF8*)Source.data(); + // FIXME: Make the type of the result buffer correct instead of + // using reinterpret_cast. + UTF16 *targetStart = reinterpret_cast(ResultPtr); + ConversionFlags flags = strictConversion; + result = ConvertUTF8toUTF16( + &sourceStart, sourceStart + Source.size(), + &targetStart, targetStart + 2*Source.size(), flags); + if (result == conversionOK) + ResultPtr = reinterpret_cast(targetStart); + else + ErrorPtr = sourceStart; + } else if (WideCharWidth == 4) { + const UTF8 *sourceStart = (const UTF8*)Source.data(); + // FIXME: Make the type of the result buffer correct instead of + // using reinterpret_cast. + UTF32 *targetStart = reinterpret_cast(ResultPtr); + ConversionFlags flags = strictConversion; + result = ConvertUTF8toUTF32( + &sourceStart, sourceStart + Source.size(), + &targetStart, targetStart + 4*Source.size(), flags); + if (result == conversionOK) + ResultPtr = reinterpret_cast(targetStart); + else + ErrorPtr = sourceStart; + } + assert((result != targetExhausted) + && "ConvertUTF8toUTFXX exhausted target buffer"); + return result == conversionOK; +} + +bool ConvertCodePointToUTF8(unsigned Source, char *&ResultPtr) { + const UTF32 *SourceStart = &Source; + const UTF32 *SourceEnd = SourceStart + 1; + UTF8 *TargetStart = reinterpret_cast(ResultPtr); + UTF8 *TargetEnd = TargetStart + 4; + ConversionResult CR = ConvertUTF32toUTF8(&SourceStart, SourceEnd, + &TargetStart, TargetEnd, + strictConversion); + if (CR != conversionOK) + return false; + + ResultPtr = reinterpret_cast(TargetStart); + return true; +} + +bool hasUTF16ByteOrderMark(const char* S, size_t len) { + return (len >= 2 && + ((S[0] == '\xff' && S[1] == '\xfe') || + (S[0] == '\xfe' && S[1] == '\xff'))); +} + +/// SwapByteOrder_16 - This function returns a byte-swapped representation of +/// the 16-bit argument. +inline uint16_t SwapByteOrder_16(uint16_t value) { +#if defined(_MSC_VER) && !defined(_DEBUG) + // The DLL version of the runtime lacks these functions (bug!?), but in a + // release build they're replaced with BSWAP instructions anyway. + return _byteswap_ushort(value); +#else + uint16_t Hi = value << 8; + uint16_t Lo = value >> 8; + return Hi | Lo; +#endif +} + +bool convertUTF16ToUTF8String(const std::u16string& utf16, std::string &Out) { + assert(Out.empty()); + + // Avoid OOB by returning early on empty input. + if (utf16.empty()) + return true; + + const UTF16 *Src = reinterpret_cast(utf16.data()); + const UTF16 *SrcEnd = reinterpret_cast(utf16.data() + utf16.length()); + + // Byteswap if necessary. + std::vector ByteSwapped; + if (Src[0] == UNI_UTF16_BYTE_ORDER_MARK_SWAPPED) { + ByteSwapped.insert(ByteSwapped.end(), Src, SrcEnd); + for (size_t I = 0, E = ByteSwapped.size(); I != E; ++I) + ByteSwapped[I] = SwapByteOrder_16(ByteSwapped[I]); + Src = &ByteSwapped[0]; + SrcEnd = &ByteSwapped[ByteSwapped.size() - 1] + 1; + } + + // Skip the BOM for conversion. + if (Src[0] == UNI_UTF16_BYTE_ORDER_MARK_NATIVE) + Src++; + + // Just allocate enough space up front. We'll shrink it later. + Out.resize(utf16.length() * UNI_MAX_UTF8_BYTES_PER_CODE_POINT + 1); + UTF8 *Dst = reinterpret_cast(&Out[0]); + UTF8 *DstEnd = Dst + Out.size(); + + ConversionResult CR = + ConvertUTF16toUTF8(&Src, SrcEnd, &Dst, DstEnd, strictConversion); + assert(CR != targetExhausted); + + if (CR != conversionOK) { + Out.clear(); + return false; + } + + Out.resize(reinterpret_cast(Dst) - &Out[0]); + return true; +} + +} // end namespace llvm + diff --git a/get/Environment.h b/get/Environment.h new file mode 100644 index 0000000000..6b9c77165d --- /dev/null +++ b/get/Environment.h @@ -0,0 +1,32 @@ +/**************************************************************************** + Copyright (c) 2016 libo All rights reserved. + + losemymind.libo@gmail.com + + ****************************************************************************/ +#ifndef LOSEMYMIND_ENVIRONMENT_H +#define LOSEMYMIND_ENVIRONMENT_H +#pragma once +#include +#include +#include "GenericPlatformMacros.h" + +NS_FK_BEGIN + +class Environment +{ +public: + static std::string GetEnvironmentVariable(const std::string& variable); + static bool HasEnvironmentVariable(const std::string& variable); + static void SetEnvironmentVariable(const std::string& variable, const std::string& value); + static std::string GetMachineName(); + static std::string GetOSVersion(); +}; + + +NS_FK_END + + +#endif // LOSEMYMIND_ENVIRONMENT_H + + diff --git a/get/EnvironmentWindows.cpp b/get/EnvironmentWindows.cpp new file mode 100644 index 0000000000..5ed9e9a27a --- /dev/null +++ b/get/EnvironmentWindows.cpp @@ -0,0 +1,113 @@ + +#include +#include +#include "Environment.h" +//#include "Exception.h" +//#include "ion/Logger.h" + +NS_FK_BEGIN + +std::string Environment::GetEnvironmentVariable(const std::string& variable) +{ + DWORD len = GetEnvironmentVariableA(variable.c_str(), 0, 0); + if (len == 0) return ""; //throw NotFoundException(variable); + char* buffer = new char[len]; + GetEnvironmentVariableA(variable.c_str(), buffer, len); + std::string result(buffer); + delete[] buffer; + return result; +} + +bool Environment::HasEnvironmentVariable(const std::string& variable) +{ + DWORD len = GetEnvironmentVariableA(variable.c_str(), 0, 0); + return len > 0; +} + +void Environment::SetEnvironmentVariable(const std::string& variable, const std::string& value) +{ + if (SetEnvironmentVariableA(variable.c_str(), value.c_str()) == 0) + { + std::string msg = "cannot set environment variable: "; + msg.append(variable); + // throw SystemException(msg); + } +} + +typedef LONG(NTAPI* fnRtlGetVersion)(PRTL_OSVERSIONINFOW lpVersionInformation); +std::string Environment::GetMachineName() +{ + RTL_OSVERSIONINFOEXW verInfo = { 0 }; + verInfo.dwOSVersionInfoSize = sizeof(verInfo); + static auto RtlGetVersion = (fnRtlGetVersion)GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlGetVersion"); + if (RtlGetVersion != 0) + RtlGetVersion((PRTL_OSVERSIONINFOW)&verInfo); + + switch (verInfo.dwMajorVersion) + { + case 10: + switch (verInfo.dwMinorVersion) + { + case 0: + return verInfo.wProductType == VER_NT_WORKSTATION ? "Windows 10" : "Windows Server 2016"; + } + case 6: + switch (verInfo.dwMinorVersion) + { + case 0: + return verInfo.wProductType == VER_NT_WORKSTATION ? "Windows Vista" : "Windows Server 2008"; + case 1: + return verInfo.wProductType == VER_NT_WORKSTATION ? "Windows 7" : "Windows Server 2008 R2"; + case 2: + return verInfo.wProductType == VER_NT_WORKSTATION ? "Windows 8" : "Windows Server 2012"; + case 3: + return verInfo.wProductType == VER_NT_WORKSTATION ? "Windows 8.1" : "Windows Server 2012 R2"; + default: + return "Unknown"; + } + case 5: + switch (verInfo.dwMinorVersion) + { + case 0: + return "Windows 2000"; + case 1: + return "Windows XP"; + case 2: + return "Windows Server 2003/Windows Server 2003 R2"; + default: + return "Unknown"; + } + default: + return "Unknown"; + } +} + +std::string Environment::GetOSVersion() +{ + RTL_OSVERSIONINFOEXW verInfo = { 0 }; + verInfo.dwOSVersionInfoSize = sizeof(verInfo); + static auto RtlGetVersion = (fnRtlGetVersion)GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlGetVersion"); + if (RtlGetVersion != 0 && RtlGetVersion((PRTL_OSVERSIONINFOW)&verInfo) == 0) + { + std::ostringstream str; + str << verInfo.dwMajorVersion << "." << verInfo.dwMinorVersion << " (Build " << (verInfo.dwBuildNumber & 0xFFFF); + if (verInfo.szCSDVersion[0]) str << ": " << verInfo.szCSDVersion; + str << ")"; + return str.str(); + } + else + { + //throw SystemException("Cannot get OS version information"); + // LOG_ERROR + std::cout << ("***** Cannot get OS version information.") << std::endl; + } + return ""; +} + + + +NS_FK_END + + + + diff --git a/get/GenericPlatformMacros.cpp b/get/GenericPlatformMacros.cpp new file mode 100644 index 0000000000..b78c1813d9 --- /dev/null +++ b/get/GenericPlatformMacros.cpp @@ -0,0 +1,89 @@ + +#if 0 +#include "GenericPlatformMacros.h" +#include "StringUtils.h" +#include +#include +#if (TARGET_PLATFORM == PLATFORM_ANDROID) +#include +#elif (TARGET_PLATFORM == PLATFORM_WIN32) +#include +#endif +USING_NS_FK; + + +void __fail__(const char* expr, const char* file, int line) +{ +#if (DEBUG_MODE==1) + +# if defined(EMSCRIPTEN) && EMSCRIPTEN + __assert_fail(expr, file, line, ""); +# elif defined __native_client__ + __assert(expr, line, file); // WHY. +# elif defined __ANDROID__ + __assert(file, line, expr); +# elif defined __clang__ || defined __GNU_LIBRARY__ || (defined __GNUC__ && defined __APPLE__) + __assert(expr, file, line); +# elif defined __GNUC__ + _assert(expr, file, line); +# elif defined _MSC_VER + _CrtDbgReport(_CRT_ASSERT, file, line, expr, ""); +# else +# error UNSUPPORTED COMPILER +# endif +#endif // (DEBUG_MODE==1) + +} + +void __log__(const char* file, int line, const char* message, ...) +{ + static const size_t MAX_LOG_LENGTH = 1024; + // Declare a moderately sized buffer on the stack that should be + // large enough to accommodate most log requests. + int size = MAX_LOG_LENGTH; + //char stackBuffer[MAX_LOG_LENGTH] = { 0 }; + std::vector dynamicBuffer(MAX_LOG_LENGTH); + char* str = &dynamicBuffer[0]; + std::string logMessage; + logMessage += file ? file : ""; + logMessage += ":"; + logMessage += StringUtils::to_string(line); + va_list args; + for (;;) + { + va_start(args, message); + // Pass one less than size to leave room for NULL terminator + int needed = vsnprintf(str, size - 1, message, args); + va_end(args); + // NOTE: Some platforms return -1 when vsnprintf runs out of room, while others return + // the number of characters actually needed to fill the buffer. + if (needed >= 0 && needed < size) + { + // Successfully wrote buffer. Added a NULL terminator in case it wasn't written. + str[needed] = '\0'; + break; + } + size = needed > 0 ? (needed + 1) : (size * 2); + dynamicBuffer.resize(size); + str = &dynamicBuffer[0]; + } + logMessage += str; + +#if (TARGET_PLATFORM == PLATFORM_ANDROID) + __android_log_print(ANDROID_LOG_INFO, "LoseMyMind", "%s", logMessage.c_str()); +#elif TARGET_PLATFORM == PLATFORM_WIN32 + std::wstring wstr = StringUtils::string2UTF8wstring(logMessage.c_str()); + OutputDebugStringW(wstr.c_str()); + printf("%s", logMessage.c_str()); + fflush(stdout); +#else + // Linux, Mac, iOS, etc + fprintf(stdout, "%s", logMessage.c_str()); + fflush(stdout); +#endif +} +#endif + + + + diff --git a/get/GenericPlatformMacros.h b/get/GenericPlatformMacros.h new file mode 100644 index 0000000000..18d8d04e52 --- /dev/null +++ b/get/GenericPlatformMacros.h @@ -0,0 +1,220 @@ + +#ifndef LOSEMYMIND_GENERICPLATFORMMACROS_H +#define LOSEMYMIND_GENERICPLATFORMMACROS_H +#pragma once +#include +// namespace FoundationKit {} +#ifdef __cplusplus + #define NS_FK_BEGIN namespace FoundationKit { + #define NS_FK_END } + #define USING_NS_FK using namespace FoundationKit +#else + #define NS_FK_BEGIN + #define NS_FK_END + #define USING_NS_FK +#endif + +#if __cplusplus < 201103L +#define constexpr +#define noexcept +#endif + +// see https://sourceforge.net/p/predef/wiki/Compilers/ +// or boost\config\select_platform_config.hpp +// define supported target platform macro which to uses. +#define PLATFORM_UNKNOWN 0 +#define PLATFORM_IOS 1 +#define PLATFORM_ANDROID 2 +#define PLATFORM_WIN32 3 +#define PLATFORM_LINUX 4 +#define PLATFORM_MAC 5 + +#define TARGET_PLATFORM PLATFORM_UNKNOWN + +#if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) +// TARGET_OS_IPHONE inlcudes TARGET_OS_IOS TARGET_OS_TV and TARGET_OS_WATCH. see TargetConditionals.h +#include +#endif + +#if (TARGET_OS_IOS ) + #undef TARGET_PLATFORM + #define TARGET_PLATFORM PLATFORM_IOS + /** + * Macro for marking up deprecated code, functions and types. + * + * Features that are marked as deprecated are scheduled to be removed from the code base + * in a future release. If you are using a deprecated feature in your code, you should + * replace it before upgrading to the next release. See the Upgrade Notes in the release + * notes for the release in which the feature was marked deprecated. + * + * Sample usage (note the slightly different syntax for classes and structures): + * + * DEPRECATED(4.6, "Message") + * void Function(); + * + * struct DEPRECATED(4.6, "Message") MODULE_API MyStruct + * { + * // StructImplementation + * }; + * class DEPRECATED(4.6, "Message") MODULE_API MyClass + * { + * // ClassImplementation + * }; + * + * @param VERSION The release number in which the feature was marked deprecated. + * @param MESSAGE A message containing upgrade notes. + */ + #define DEPRECATED(VERSION, MESSAGE) __attribute__((deprecated(MESSAGE " Please update your code to the new API before upgrading to the next release, otherwise your project will no longer compile."))) + // Symbol export and import definitions + #define SYMBOL_EXPORT + #define SYMBOL_IMPORT + // Alignment. + #define ATTRIBUTE_PACK(n) __attribute__((packed,aligned(n))) + #define ATTRIBUTE_ALIGN(n) __attribute__((aligned(n))) + #define ATTRIBUTE_UNUSED __attribute__((unused))//__attribute__((__unused__)) ? + #define FORCEINLINE inline __attribute__ ((always_inline)) /* Force code to be inline */ + #define FORCENOINLINE __attribute__((noinline)) /* Force code to NOT be inline */ + #define THREAD_LOCAL __thread + #define FILEPATH_MAX MAX_PATH + + +#elif defined(__ANDROID__) || defined(ANDROID) + #undef TARGET_PLATFORM + #define TARGET_PLATFORM PLATFORM_ANDROID + #define DEPRECATED(VERSION, MESSAGE) __attribute__((deprecated(MESSAGE " Please update your code to the new API before upgrading to the next release, otherwise your project will no longer compile."))) + // Symbol export and import definitions + #define SYMBOL_EXPORT __attribute__((visibility("default"))) + #define SYMBOL_IMPORT __attribute__((visibility("default"))) + // Alignment. + #define ATTRIBUTE_PACK(n) __attribute__((packed,aligned(n))) + #define ATTRIBUTE_ALIGN(n) __attribute__((aligned(n))) + #define ATTRIBUTE_UNUSED __attribute__((unused))//__attribute__((__unused__)) ? + #define FORCEINLINE inline __attribute__ ((always_inline)) /* Force code to be inline */ + #define FORCENOINLINE __attribute__((noinline)) /* Force code to NOT be inline */ + #define THREAD_LOCAL __thread + #define FILEPATH_MAX PATH_MAX + + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) + #undef TARGET_PLATFORM + #define TARGET_PLATFORM PLATFORM_WIN32 + #define DEPRECATED(VERSION, MESSAGE) __declspec(deprecated(MESSAGE " Please update your code to the new API before upgrading to the next release, otherwise your project will no longer compile.")) + // Symbol export and import definitions + #define SYMBOL_EXPORT __declspec(dllexport) + #define SYMBOL_IMPORT __declspec(dllimport) + // Alignment. + #define ATTRIBUTE_PACK(n) + #define ATTRIBUTE_ALIGN(n) __declspec(align(n)) + #define ATTRIBUTE_UNUSED + #define FORCEINLINE __forceinline /* Force code to be inline */ + #define FORCENOINLINE __declspec(noinline) /* Force code to NOT be inline */ + #define THREAD_LOCAL __declspec(thread) + #define FILEPATH_MAX MAX_PATH + +#elif (defined(linux) || defined(__linux) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__)) && !defined(_CRAYC) + #undef TARGET_PLATFORM + #define TARGET_PLATFORM PLATFORM_LINUX + #define DEPRECATED(VERSION, MESSAGE) __attribute__((deprecated(MESSAGE " Please update your code to the new API before upgrading to the next release, otherwise your project will no longer compile."))) + // Symbol export and import definitions + #define SYMBOL_EXPORT __attribute__((visibility("default"))) + #define SYMBOL_IMPORT __attribute__((visibility("default"))) + // Alignment. + #define ATTRIBUTE_PACK(n) __attribute__((packed,aligned(n))) + #define ATTRIBUTE_ALIGN(n) __attribute__((aligned(n))) + #define ATTRIBUTE_UNUSED __attribute__((unused))//__attribute__((__unused__)) ? + #define FORCEINLINE inline __attribute__ ((always_inline)) /* Force code to be inline */ + #define FORCENOINLINE __attribute__((noinline)) /* Force code to NOT be inline */ + #define THREAD_LOCAL __thread + #define FILEPATH_MAX PATH_MAX + +#elif(TARGET_OS_MAC) + #undef TARGET_PLATFORM + #define TARGET_PLATFORM PLATFORM_MAC + #define DEPRECATED(VERSION, MESSAGE) __attribute__((deprecated(MESSAGE " Please update your code to the new API before upgrading to the next release, otherwise your project will no longer compile."))) + // Symbol export and import definitions + #define SYMBOL_EXPORT + #define SYMBOL_IMPORT + // Alignment. + #define ATTRIBUTE_PACK(n) __attribute__((packed,aligned(n))) + #define ATTRIBUTE_ALIGN(n) __attribute__((aligned(n))) + #define ATTRIBUTE_UNUSED __attribute__((unused)) //__attribute__((__unused__)) ? + #define FORCEINLINE inline __attribute__ ((always_inline)) /* Force code to be inline */ + #define FORCENOINLINE __attribute__((noinline)) /* Force code to NOT be inline */ + #define THREAD_LOCAL __thread + #define FILEPATH_MAX MAX_PATH + +#else + #error Unknown platform +#endif + +#define UNUSED_ARG(arg) do{(void)(arg);}while(0) + +#define SAFE_DELETE(p) do { delete (p); (p) = nullptr; } while(0) +#define SAFE_DELETE_ARRAY(p) do { if(p) { delete[] (p); (p) = nullptr; } } while(0) +#define SAFE_FREE(p) do { if(p) { free(p); (p) = nullptr; } } while(0) +#define SAFE_RELEASE(p) do { if(p) { (p)->release(); } } while(0) +#define SAFE_RELEASE_NULL(p) do { if(p) { (p)->release(); (p) = nullptr; } } while(0) +#define SAFE_RETAIN(p) do { if(p) { (p)->retain(); } } while(0) +#define BREAK_IF(cond) if(cond) break + +// Make a string to Wide string +#define TEXT_HELPER(a,b) a ## b +#define MAKE_TEXT(s) TEXT_HELPER(L, s) + +// Helper macro STRINGIZE: +// Converts the parameter X to a string after macro replacement +// on X has been performed. +#define STRINGIZE_HELPER(X) #X +#define STRINGIZE(X) STRINGIZE_HELPER(X) + +//#pragma message(COMPILE_MSG "Show compile message") +#define COMPILE_MSG __FILE__ "(" STRINGIZE(__LINE__) "):Warning:" + +extern void __fail__(const char* expr, const char* file, int line); +extern void __log__(const char* file, int line, const char* message, ...); +#if defined(_DEBUG) || defined(DEBUG) + #define ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : (__fail__(#CHECK, __FILE__, __LINE__), (EXPR))) + #define LOG_ASSERT(cond, msg,...) do{if (!(cond)){ __log__(__FILE__, __LINE__, msg, ##__VA_ARGS__);assert(cond);}} while (false) + #define DEBUG_MODE 1 +#else + #define ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR) + #define LOG_ASSERT(cond, msg,...) do{}while(false) + #define DEBUG_MODE 0 +#endif +#define LOG_CONDITION(cond,msg,...) do{if ((cond)){ __log__(__FILE__, __LINE__, msg, ##__VA_ARGS__);}} while (false) + +//=============================================================================================== +// Platform Pre-Setup +//=============================================================================================== +#if (TARGET_PLATFORM == PLATFORM_WIN32) +__pragma (warning(disable:4127)) +#define _XKEYCHECK_H // disable windows xkeycheck.h + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN 1 +#endif + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS 1 +#endif + +#ifndef _SCL_SECURE_NO_WARNINGS +#define _SCL_SECURE_NO_WARNINGS 1 +#endif + +#include + +#endif //(TARGET_PLATFORM == PLATFORM_WIN32) + +// IOS,ANDROID,MAC platform must be defined USE_FILE32API +//#ifndef USE_FILE32API +//#define USE_FILE32API 1 +//#endif + + +#endif // #ifndef LOSEMYMIND_GENERICPLATFORMMACROS_H + diff --git a/get/StringUtils.cpp b/get/StringUtils.cpp new file mode 100644 index 0000000000..332544a9e3 --- /dev/null +++ b/get/StringUtils.cpp @@ -0,0 +1,243 @@ +/**************************************************************************** + Copyright (c) 2015 libo All rights reserved. + + losemymind.libo@gmail.com + +****************************************************************************/ +#include +#include +#include +#include +#include +#include +//#include +#include "StringUtils.h" +#include "ConvertUTF/ConvertUTF.h" + +NS_FK_BEGIN + +std::string StringUtils::tolower( const std::string& str ) +{ + std::string ret; + for (auto ch : str) + { + if (ch >= 'A' && ch <= 'Z') + ret += ch | 32; + else + ret += ch; + } + return ret; +} + +std::string StringUtils::toupper( const std::string& str ) +{ + std::string ret; + for (auto ch : str) + { + if (ch >= 'a' && ch <= 'z') + ret += ch ^ 32; + else + ret += ch; + } + return ret; +} + +std::string StringUtils::format( const char* format, ... ) +{ + const static unsigned int MAX_STRING_LENGTH = 64; + va_list arglist; + int size = MAX_STRING_LENGTH; + std::vector dynamicBuffer(MAX_STRING_LENGTH); + char* str = &dynamicBuffer[0]; + for (;;) + { + va_start(arglist, format); + // Pass one less than size to leave room for NULL terminator + int needed = vsnprintf(str, size - 1, format, arglist); + va_end(arglist); + + // NOTE: Some platforms return -1 when vsnprintf runs out of room, while others return + // the number of characters actually needed to fill the buffer. + if (needed >= 0 && needed < size) + { + // Successfully wrote buffer. Added a NULL terminator in case it wasn't written. + str[needed] = '\0'; + break; + } + size = needed > 0 ? (needed + 1) : (size * 2); + dynamicBuffer.resize(size); + str = &dynamicBuffer[0]; + } + return str; +} + +std::string & StringUtils::ltrim( std::string &s ) +{ + s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); + return s; +} + +std::string & StringUtils::rtrim( std::string &s ) +{ + s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), s.end()); + return s; +} + +std::string & StringUtils::trim( std::string &s ) +{ + return ltrim(rtrim(s)); +} + +std::vector & StringUtils::split( const std::string &s, char delim, std::vector &elems ) +{ + std::stringstream ss(s); + std::string item; + while (std::getline(ss, item, delim)) + { + elems.push_back(item); + } + return elems; +} + +std::vector StringUtils::split( const std::string &s, char delim ) +{ + std::vector elems; + split(s, delim, elems); + return elems; +} + +std::string StringUtils::join(std::string delim, std::vector values) +{ + std::string ret; + size_t index = 0; + size_t valuesSize = values.size(); + for (auto& str : values) + { + ++index; + ret.append(str); + if (index < valuesSize) + { + ret.append(delim); + } + } + return ret; +} + +bool StringUtils::isNumber( const std::string& val ) +{ + std::stringstream str(val); + float tst; + str >> tst; + return !str.fail() && str.eof(); +} + + +// Other impl see:http://blog.poxiao.me/p/unicode-character-encoding-conversion-in-cpp11/ + +std::string StringUtils::wstring2UTF8string(const std::wstring &input) +{ + std::locale old_loc = std::locale::global(std::locale("")); + const wchar_t* src_wstr = input.c_str(); + size_t buffer_size = input.size() * 4 + 1; + char* dst_str = new char[buffer_size]; + memset(dst_str, 0, buffer_size); + wcstombs(dst_str, src_wstr, buffer_size); + std::string result = dst_str; + delete[]dst_str; + std::locale::global(old_loc); + return result; +} + +std::wstring StringUtils::string2UTF8wstring(const std::string &input) +{ + std::locale old_loc = std::locale::global(std::locale("")); + const char* src_str = input.c_str(); + const size_t buffer_size = input.size() + 1; + wchar_t* dst_wstr = new wchar_t[buffer_size]; + wmemset(dst_wstr, 0, buffer_size); + mbstowcs(dst_wstr, src_str, buffer_size); + std::wstring result = dst_wstr; + delete[]dst_wstr; + std::locale::global(old_loc); + return result; +} + + +bool StringUtils::UTF8ToUTF16(const std::string& utf8, std::u16string& outUtf16) +{ + if (utf8.empty()) + { + outUtf16.clear(); + return true; + } + + bool ret = false; + + const size_t utf16Bytes = (utf8.length() + 1) * sizeof(char16_t); + char16_t* utf16 = (char16_t*)malloc(utf16Bytes); + memset(utf16, 0, utf16Bytes); + + char* utf16ptr = reinterpret_cast(utf16); + const UTF8* error = nullptr; + + if (llvm::ConvertUTF8toWide(2, utf8, utf16ptr, error)) + { + outUtf16 = utf16; + ret = true; + } + free(utf16); + return ret; +} + +bool StringUtils::UTF16ToUTF8(const std::u16string& utf16, std::string& outUtf8) +{ + if (utf16.empty()) + { + outUtf8.clear(); + return true; + } + + return llvm::convertUTF16ToUTF8String(utf16, outUtf8); +} + +/* +std::u16string StringUtils::UTF8ToUTF16(const std::string &s) +{ + std::wstring_convert, char16_t> conv; + return conv.from_bytes(s); +} + +std::u32string StringUtils::UTF8ToUTF32(const std::string &s) +{ + std::wstring_convert, char32_t> conv; + return conv.from_bytes(s); +} + +std::string StringUtils::UTF16ToUTF8(const std::u16string &s) +{ + std::wstring_convert, char16_t> conv; + return conv.to_bytes(s); +} + +std::u32string StringUtils::UTF16ToUTF32(const std::u16string &s) +{ + const char16_t *pData = s.c_str(); + std::wstring_convert, char32_t> conv; + return conv.from_bytes(reinterpret_cast(pData), reinterpret_cast(pData + s.length())); +} + +std::string StringUtils::UTF32ToUTF8(const std::u32string &s) +{ + std::wstring_convert, char32_t> conv; + return conv.to_bytes(s); +} + + +std::u16string StringUtils::UTF32ToUTF16(const std::u32string &s) +{ + std::wstring_convert, char32_t> conv; + std::string bytes = conv.to_bytes(s); + return std::u16string(reinterpret_cast(bytes.c_str()), bytes.length() / sizeof(char16_t)); +} +*/ +NS_FK_END diff --git a/get/StringUtils.h b/get/StringUtils.h new file mode 100644 index 0000000000..7b89e3a3bb --- /dev/null +++ b/get/StringUtils.h @@ -0,0 +1,153 @@ +/**************************************************************************** + Copyright (c) 2015 libo All rights reserved. + + losemymind.libo@gmail.com + +****************************************************************************/ +#ifndef LOSEMYMIND_STRINGUTILS_H +#define LOSEMYMIND_STRINGUTILS_H + +#pragma once +#include +#include +#include +#include +#include "GenericPlatformMacros.h" + +NS_FK_BEGIN + +class StringUtils +{ +public: + static std::string tolower(const std::string& str); + + static std::string toupper(const std::string& str); + + static std::string format(const char* format, ...); + + // trim from start + static std::string <rim(std::string &s); + + // trim from end + static std::string &rtrim(std::string &s); + + // trim from both ends + static std::string &trim(std::string &s); + + static std::vector &split(const std::string &s, char delim, std::vector &elems); + + static std::vector split(const std::string &s, char delim); + + static std::string join(std::string delim, std::vector values); + + /** + * @brief Converts basic numeric types to strings. + * @param[in] val The basic numeric. + * @param[in] percision Number of precision. + * @usage tostring(val); + */ + template + static std::string to_string(_Val val,int precision = 2) + { + std::ostringstream oss; + oss << std::fixed << std::setprecision(precision) << val; + return oss.str(); + } + + /** + * @brief Converts boolean types to strings. + * @usage tostring(val); + */ + static std::string to_string(bool val) + { + return val ? "true" : "false"; + } + + static bool isNumber(const std::string& val); + + /** + * Convert std::wstring to std::string, the string code page is UTF-8. + */ + static std::string wstring2UTF8string(const std::wstring &input); + + /** + * Convert std::string to std::wstring, the string code page is UTF-8. + */ + static std::wstring string2UTF8wstring(const std::string &input); + + + static std::wstring string2wstring(std::string s) + { + std::wstring ws; + ws.assign(s.begin(), s.end()); + return ws; + } + + static std::string wstring2string(std::wstring ws) + { + std::string s; + s.assign(ws.begin(), ws.end()); + return s; + } + + static unsigned char* to_unsigned(char* p) + { + return reinterpret_cast(p); + } + + static unsigned char* to_unsigned(std::string& str) + { + return reinterpret_cast(&*str.begin()); + } + + + /** + * @brief Converts utf8 string to utf16 string. + * @param utf8 The utf8 string to be converted. + * @param outUtf16 The output utf16 string. + * @return True if succeed, otherwise false. + * @note Please check the return value before using \p outUtf16 + * e.g. + * @code + * std::u16string utf16; + * bool ret = StringUtils::UTF8ToUTF16("hello", utf16); + * if (ret) { + * do_some_thing_with_utf16(utf16); + * } + * @endcode + */ + static bool UTF8ToUTF16(const std::string& utf8, std::u16string& outUtf16); + + /** + * @brief Converts utf16 string to utf8 string. + * @param utf16 The utf16 string to be converted. + * @param outUtf8 The output utf8 string. + * @return True if succeed, otherwise false. + * @note Please check the return value before using \p outUtf8 + * e.g. + * @code + * std::string utf8; + * bool ret = StringUtils::UTF16ToUTF8(u"\u4f60\u597d", utf16); + * if (ret) { + * do_some_thing_with_utf8(utf8); + * } + * @endcode + */ + static bool UTF16ToUTF8(const std::u16string& utf16, std::string& outUtf8); + + /** + static std::u16string UTF8ToUTF16(const std::string &s); + static std::u32string UTF8ToUTF32(const std::string &s); + static std::string UTF16ToUTF8(const std::u16string &s); + static std::u32string UTF16ToUTF32(const std::u16string &s); + static std::string UTF32ToUTF8(const std::u32string &s); + static std::u16string UTF32ToUTF16(const std::u32string &s); + */ + + +}; + +NS_FK_END +#endif // LOSEMYMIND_STRINGUTILS_H + + diff --git "a/get/app.manifest - \345\211\257\346\234\254.xml" "b/get/app.manifest - \345\211\257\346\234\254.xml" new file mode 100644 index 0000000000..b851b235af --- /dev/null +++ "b/get/app.manifest - \345\211\257\346\234\254.xml" @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/get/app.manifest.xml b/get/app.manifest.xml new file mode 100644 index 0000000000..b387ab0a8e --- /dev/null +++ b/get/app.manifest.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/get/constructormagic.h b/get/constructormagic.h new file mode 100644 index 0000000000..6b6e83cb47 --- /dev/null +++ b/get/constructormagic.h @@ -0,0 +1,34 @@ +/* + * Copyright 2004 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef RTC_BASE_CONSTRUCTORMAGIC_H_ +#define RTC_BASE_CONSTRUCTORMAGIC_H_ + +// Put this in the declarations for a class to be unassignable. +#define RTC_DISALLOW_ASSIGN(TypeName) \ + TypeName& operator=(const TypeName&) = delete + +// A macro to disallow the copy constructor and operator= functions. This should +// be used in the declarations for a class. +#define RTC_DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&) = delete; \ + RTC_DISALLOW_ASSIGN(TypeName) + +// A macro to disallow all the implicit constructors, namely the default +// constructor, copy constructor and operator= functions. +// +// This should be used in the declarations for a class that wants to prevent +// anyone from instantiating it. This is especially useful for classes +// containing only static methods. +#define RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ + TypeName() = delete; \ + RTC_DISALLOW_COPY_AND_ASSIGN(TypeName) + +#endif // RTC_BASE_CONSTRUCTORMAGIC_H_ diff --git a/get/get.cpp b/get/get.cpp new file mode 100644 index 0000000000..2aacff02fa --- /dev/null +++ b/get/get.cpp @@ -0,0 +1,91 @@ +// get.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 +// +//https://social.msdn.microsoft.com/Forums/windows/en-US/6f22c643-7a33-4581-9fbb-5462c1602f8b/windows-10-getversionex?forum=windowssdk +#include + +//通过peb方式获得系统版本信息 +#include +#include + +#include + +#if 0 + +DWORD Major; +DWORD Minor; +DWORD Build; + +typedef NTSTATUS(WINAPI* _NtQueryInformationProcess)(_In_ HANDLE ProcessHandle, + _In_ PROCESSINFOCLASS ProcessInformationClass, + _Out_ PVOID ProcessInformation, + _In_ ULONG ProcessInformationLength, + _Out_opt_ PULONG ReturnLength); +_NtQueryInformationProcess NtQueryInformationProcess_; + +DWORD GetProcessPEBAddress(HANDLE hProc) +{ + PROCESS_BASIC_INFORMATION peb; + DWORD tmp; + NtQueryInformationProcess_ = + (_NtQueryInformationProcess)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQueryInformationProcess"); + NtQueryInformationProcess_(hProc, ProcessBasicInformation, &peb, sizeof(PROCESS_BASIC_INFORMATION), &tmp); + return (DWORD)peb.PebBaseAddress; +} + +void OSVersion(HANDLE handle) +{ + DWORD pebAddress = GetProcessPEBAddress(handle); + DWORD OSMajorVersionAddress = pebAddress + 0x0a4; + DWORD OSMinorVersionAddress = pebAddress + 0x0a8; + DWORD OSBuildNumberAddress = pebAddress + 0x0ac; + ReadProcessMemory(handle, (void*)OSMajorVersionAddress, &Major, sizeof(Major), 0); + ReadProcessMemory(handle, (void*)OSMinorVersionAddress, &Minor, sizeof(Minor), 0); + ReadProcessMemory(handle, (void*)OSBuildNumberAddress, &Build, sizeof(Build), 0); +} + +int main() +{ + HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId()); + OSVersion(handle); + + printf("OS version - %d.%d.%d", Major, Minor, Build); + + getchar(); + return 0; +} + +//通过RtlGetVersion api获得系统信息 + +LONG(WINAPI* pfnRtlGetVersion)(RTL_OSVERSIONINFOEXW*); +(FARPROC&)pfnRtlGetVersion = GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "RtlGetVersion"); +if (pfnRtlGetVersion) +{ + RTL_OSVERSIONINFOEXW ver = {0}; + ver.dwOSVersionInfoSize = sizeof(ver); + + if (pfnRtlGetVersion(&ver) == 0) + { + // Success, read results in `ver` + } + else + { + // RtlGetVersion failed + } +} +else +{ + // RtlGetVersion was not found... +} + +// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单 +// 调试程序: F5 或调试 >“开始调试”菜单 + +// 入门使用技巧: +// 1. 使用解决方案资源管理器窗口添加/管理文件 +// 2. 使用团队资源管理器窗口连接到源代码管理 +// 3. 使用输出窗口查看生成输出和其他消息 +// 4. 使用错误列表窗口查看错误 +// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目 +// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件 + +#endif \ No newline at end of file diff --git a/get/get.vcxproj b/get/get.vcxproj new file mode 100644 index 0000000000..11341ed9fa --- /dev/null +++ b/get/get.vcxproj @@ -0,0 +1,179 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {2A5089E9-EF05-48A2-B5A6-22723BAF9E78} + Win32Proj + get + 10.0.10586.0 + SYSINFO + + + + Application + true + v142 + Unicode + + + Application + false + v140 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + false + + + true + + + true + + + false + + + + + + Level3 + MaxSpeed + true + true + false + WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + + Level3 + Disabled + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + + + Level3 + Disabled + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + + + Level3 + MaxSpeed + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/get/get.vcxproj.filters b/get/get.vcxproj.filters new file mode 100644 index 0000000000..fa5459cd7c --- /dev/null +++ b/get/get.vcxproj.filters @@ -0,0 +1,63 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + \ No newline at end of file diff --git a/get/main.cpp b/get/main.cpp new file mode 100644 index 0000000000..c762688832 --- /dev/null +++ b/get/main.cpp @@ -0,0 +1,111 @@ +//_CRT_SECURE_NO_WARNINGS //: error C4996: 'GetVersionExW': Ϊѷ +// 1.Project Properties > Configuration Properties > C/C++ > General > SDL checksص +#include "windows_version.h" +//./app.manifest.xml +#include +#include +int testrtc_main() +{ + std::string ver = rtc::rtc_win::getosver(); + std::cout << ver << std::endl; + getchar(); + return 0; +} +// https://github.com/uemuraj/tanzaku/blob/63ea6637d7a3ab987659a63f08e39f504c7a6c21/windows-load-proc/maincpp.cpp +#define _WIN32_WINNT _WIN32_WINNT_WIN8 +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#include + +// +// DLL vӵĤä뤿Υإ +// +template +class ProcAddress +{ + typedef ReturnType(__stdcall* ADDRESS)(ArgumentTypes...); + + HMODULE m_module; + ADDRESS m_address; + +public: + ProcAddress(LPCSTR lib, LPCSTR proc) + { + m_module = ::LoadLibraryA(lib); + m_address = (ADDRESS)::GetProcAddress(m_module, proc); + } + + // ԩ`ֹΤ¤ delete ָ뤬... + ProcAddress(const ProcAddress& ref) = delete; + ProcAddress& operator=(const ProcAddress&) = delete; + + // Υ󥹥ȥ饯 delete ָǤʤgHˤʹʤƤ⥳ѥ륨`ȤʤäƤޤ + ProcAddress(ProcAddress&& ref) { static_assert(false); } + + ~ProcAddress() { ::FreeLibrary(m_module); } + + operator bool() { return m_address != nullptr; } + + ReturnType operator()(ArgumentTypes... args) { return (*m_address)(args...); } +}; + +// +// DLL vӵĤä뤿Υإ +// +template +ProcAddress LoadProcAddress(LPCSTR lib, LPCSTR proc) +{ + return ProcAddress(lib, proc); +} + + +int whatmain() +{ + auto RtlGetVersion = LoadProcAddress("ntdll", "RtlGetVersion"); + + if (RtlGetVersion) + { + OSVERSIONINFOEXW info = {sizeof info}; + + return RtlGetVersion(&info); + } + + return 1; +} + + +#include "Environment.h" + +std::string getwintime() +{ + SYSTEMTIME st = {0}; + GetLocalTime(&st); //ȡǰʱ ɾȷms + char buffer[80] = {0}; + int len = sprintf_s(buffer, + 80, + "%d-%02d-%02d %02d:%02d:%02d.%03d\n", + st.wYear, + st.wMonth, + st.wDay, + st.wHour, + st.wMinute, + st.wSecond, + st.wMilliseconds); + if (-1 == len) + { + return std::string(); + } + return std::move(std::string(buffer)); +} +int main() +{ + FoundationKit::Environment ev; + std::string os = ev.GetOSVersion(); + auto name = ev.GetMachineName(); + std::cout << os << std::endl; + std::cout << name << std::endl; + std::cout << getwintime() << std::endl; + + getchar(); + return 0; +} diff --git a/get/windows_version.cc b/get/windows_version.cc new file mode 100644 index 0000000000..d5e71800bc --- /dev/null +++ b/get/windows_version.cc @@ -0,0 +1,421 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "windows_version.h" + +#include +#include +#include + +#define alloca _alloca +//#include "rtc_base/stringutils.h" + +//#if !defined(__clang__) && _MSC_FULL_VER < 191125507 +//#error VS 2017 Update 3.2 or higher is required +//#endif +namespace rtc +{ +#define STACK_ARRAY(TYPE, LEN) \ + static_cast(::alloca((LEN) * sizeof(TYPE))) + + + inline std::string ToUtf8(const wchar_t* wide, size_t len) { + int len8 = ::WideCharToMultiByte(CP_UTF8, 0, wide, static_cast(len), + nullptr, 0, nullptr, nullptr); + char* ns = STACK_ARRAY(char, len8); + ::WideCharToMultiByte(CP_UTF8, 0, wide, static_cast(len), ns, len8, + nullptr, nullptr); + return std::string(ns, len8); + } + + inline std::string ToUtf8(const wchar_t* wide) { + return ToUtf8(wide, wcslen(wide)); + } + + inline std::string ToUtf8(const std::wstring& wstr) { + return ToUtf8(wstr.data(), wstr.length()); + } +} +namespace { + +typedef BOOL(WINAPI* GetProductInfoPtr)(DWORD, DWORD, DWORD, DWORD, PDWORD); + +// Mask to pull WOW64 access flags out of REGSAM access. +const REGSAM kWow64AccessMask = KEY_WOW64_32KEY | KEY_WOW64_64KEY; + +// Utility class to read, write and manipulate the Windows Registry. +// Registry vocabulary primer: a "key" is like a folder, in which there +// are "values", which are pairs, with an associated data type. +// Based on base::win::RegKey but only implements a small fraction of it. +class RegKey { + public: + RegKey() : key_(nullptr), wow64access_(0) {} + + RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access) + : key_(nullptr), wow64access_(0) { + if (rootkey) { + if (access & (KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_CREATE_LINK)) + Create(rootkey, subkey, access); + else + Open(rootkey, subkey, access); + } else { + //RTC_DCHECK(!subkey); + wow64access_ = access & kWow64AccessMask; + } + } + + ~RegKey() { Close(); } + + LONG Create(HKEY rootkey, const wchar_t* subkey, REGSAM access) { + DWORD disposition_value; + return CreateWithDisposition(rootkey, subkey, &disposition_value, access); + } + + LONG CreateWithDisposition(HKEY rootkey, + const wchar_t* subkey, + DWORD* disposition, + REGSAM access) { + //RTC_DCHECK(rootkey && subkey && access && disposition); + HKEY subhkey = NULL; + LONG result = + ::RegCreateKeyEx(rootkey, subkey, 0, NULL, REG_OPTION_NON_VOLATILE, + access, NULL, &subhkey, disposition); + if (result == ERROR_SUCCESS) { + Close(); + key_ = subhkey; + wow64access_ = access & kWow64AccessMask; + } + + return result; + } + + // Opens an existing reg key. + LONG Open(HKEY rootkey, const wchar_t* subkey, REGSAM access) { + //RTC_DCHECK(rootkey && subkey && access); + HKEY subhkey = NULL; + + LONG result = ::RegOpenKeyEx(rootkey, subkey, 0, access, &subhkey); + if (result == ERROR_SUCCESS) { + Close(); + key_ = subhkey; + wow64access_ = access & kWow64AccessMask; + } + + return result; + } + + // Closes this reg key. + void Close() { + if (key_) { + ::RegCloseKey(key_); + key_ = nullptr; + } + } + + // Reads a REG_DWORD (uint32_t) into |out_value|. If |name| is null or empty, + // reads the key's default value, if any. + LONG ReadValueDW(const wchar_t* name, DWORD* out_value) const { + //RTC_DCHECK(out_value); + DWORD type = REG_DWORD; + DWORD size = sizeof(DWORD); + DWORD local_value = 0; + LONG result = ReadValue(name, &local_value, &size, &type); + if (result == ERROR_SUCCESS) { + if ((type == REG_DWORD || type == REG_BINARY) && size == sizeof(DWORD)) + *out_value = local_value; + else + result = ERROR_CANTREAD; + } + + return result; + } + + // Reads a string into |out_value|. If |name| is null or empty, reads + // the key's default value, if any. + LONG ReadValue(const wchar_t* name, std::wstring* out_value) const { + //RTC_DCHECK(out_value); + const size_t kMaxStringLength = 1024; // This is after expansion. + // Use the one of the other forms of ReadValue if 1024 is too small for you. + wchar_t raw_value[kMaxStringLength]; + DWORD type = REG_SZ, size = sizeof(raw_value); + LONG result = ReadValue(name, raw_value, &size, &type); + if (result == ERROR_SUCCESS) { + if (type == REG_SZ) { + *out_value = raw_value; + } else if (type == REG_EXPAND_SZ) { + wchar_t expanded[kMaxStringLength]; + size = + ::ExpandEnvironmentStrings(raw_value, expanded, kMaxStringLength); + // Success: returns the number of wchar_t's copied + // Fail: buffer too small, returns the size required + // Fail: other, returns 0 + if (size == 0 || size > kMaxStringLength) { + result = ERROR_MORE_DATA; + } else { + *out_value = expanded; + } + } else { + // Not a string. Oops. + result = ERROR_CANTREAD; + } + } + + return result; + } + + LONG ReadValue(const wchar_t* name, + void* data, + DWORD* dsize, + DWORD* dtype) const { + LONG result = RegQueryValueEx(key_, name, 0, dtype, + reinterpret_cast(data), dsize); + return result; + } + + private: + HKEY key_; + REGSAM wow64access_; +}; + +} // namespace + +namespace rtc { +namespace rtc_win { +namespace { + +// Helper to map a major.minor.x.build version (e.g. 6.1) to a Windows release. +Version MajorMinorBuildToVersion(int major, int minor, int build) { + if ((major == 5) && (minor > 0)) { + // Treat XP Pro x64, Home Server, and Server 2003 R2 as Server 2003. + return (minor == 1) ? VERSION_XP : VERSION_SERVER_2003; + } else if (major == 6) { + switch (minor) { + case 0: + // Treat Windows Server 2008 the same as Windows Vista. + return VERSION_VISTA; + case 1: + // Treat Windows Server 2008 R2 the same as Windows 7. + return VERSION_WIN7; + case 2: + // Treat Windows Server 2012 the same as Windows 8. + return VERSION_WIN8; + default: + // RTC_DCHECK_EQ(minor, 3); + return VERSION_WIN8_1; + } + } else if (major == 10) { + if (build < 10586) { + return VERSION_WIN10; + } else if (build < 14393) { + return VERSION_WIN10_TH2; + } else if (build < 15063) { + return VERSION_WIN10_RS1; + } else if (build < 16299) { + return VERSION_WIN10_RS2; + } else if (build < 17134) { + return VERSION_WIN10_RS3; + } else { + return VERSION_WIN10_RS4; + } + } else if (major > 6) { + // RTC_NOTREACHED(); + return VERSION_WIN_LAST; + } + + return VERSION_PRE_XP; +} + +// Returns the the "UBR" value from the registry. Introduced in Windows 10, +// this undocumented value appears to be similar to a patch number. +// Returns 0 if the value does not exist or it could not be read. +int GetUBR() { + // The values under the CurrentVersion registry hive are mirrored under + // the corresponding Wow6432 hive. + static constexpr wchar_t kRegKeyWindowsNTCurrentVersion[] = + L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"; + + RegKey key; + if (key.Open(HKEY_LOCAL_MACHINE, kRegKeyWindowsNTCurrentVersion, + KEY_QUERY_VALUE) != ERROR_SUCCESS) { + return 0; + } + + DWORD ubr = 0; + key.ReadValueDW(L"UBR", &ubr); + + return static_cast(ubr); +} + +} // namespace + +// static +OSInfo* OSInfo::GetInstance() { + // Note: we don't use the Singleton class because it depends on AtExitManager, + // and it's convenient for other modules to use this class without it. This + // pattern is copied from gurl.cc. + static OSInfo* info; + if (!info) { + OSInfo* new_info = new OSInfo(); + if (InterlockedCompareExchangePointer(reinterpret_cast(&info), + new_info, NULL)) { + delete new_info; + } + } + return info; +} + +OSInfo::OSInfo() + : version_(VERSION_PRE_XP), + architecture_(OTHER_ARCHITECTURE), + wow64_status_(GetWOW64StatusForProcess(GetCurrentProcess())) { + OSVERSIONINFOEX version_info = {sizeof version_info}; + // Applications not manifested for Windows 8.1 or Windows 10 will return the + // Windows 8 OS version value (6.2). Once an application is manifested for a + // given operating system version, GetVersionEx() will always return the + // version that the application is manifested for in future releases. + // https://docs.microsoft.com/en-us/windows/desktop/SysInfo/targeting-your-application-at-windows-8-1. + // https://www.codeproject.com/Articles/678606/Part-Overcoming-Windows-s-deprecation-of-GetVe. + ::GetVersionEx(reinterpret_cast(&version_info)); + version_number_.major = version_info.dwMajorVersion; + version_number_.minor = version_info.dwMinorVersion; + version_number_.build = version_info.dwBuildNumber; + version_number_.patch = GetUBR(); + version_ = MajorMinorBuildToVersion( + version_number_.major, version_number_.minor, version_number_.build); + service_pack_.major = version_info.wServicePackMajor; + service_pack_.minor = version_info.wServicePackMinor; + service_pack_str_ = rtc::ToUtf8(version_info.szCSDVersion); + + SYSTEM_INFO system_info = {}; + ::GetNativeSystemInfo(&system_info); + switch (system_info.wProcessorArchitecture) { + case PROCESSOR_ARCHITECTURE_INTEL: + architecture_ = X86_ARCHITECTURE; + break; + case PROCESSOR_ARCHITECTURE_AMD64: + architecture_ = X64_ARCHITECTURE; + break; + case PROCESSOR_ARCHITECTURE_IA64: + architecture_ = IA64_ARCHITECTURE; + break; + } + processors_ = system_info.dwNumberOfProcessors; + allocation_granularity_ = system_info.dwAllocationGranularity; + + GetProductInfoPtr get_product_info; + DWORD os_type; + + if (version_info.dwMajorVersion == 6 || version_info.dwMajorVersion == 10) { + // Only present on Vista+. + get_product_info = reinterpret_cast( + ::GetProcAddress(::GetModuleHandle(L"kernel32.dll"), "GetProductInfo")); + + get_product_info(version_info.dwMajorVersion, version_info.dwMinorVersion, + 0, 0, &os_type); + switch (os_type) { + case PRODUCT_CLUSTER_SERVER: + case PRODUCT_DATACENTER_SERVER: + case PRODUCT_DATACENTER_SERVER_CORE: + case PRODUCT_ENTERPRISE_SERVER: + case PRODUCT_ENTERPRISE_SERVER_CORE: + case PRODUCT_ENTERPRISE_SERVER_IA64: + case PRODUCT_SMALLBUSINESS_SERVER: + case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM: + case PRODUCT_STANDARD_SERVER: + case PRODUCT_STANDARD_SERVER_CORE: + case PRODUCT_WEB_SERVER: + version_type_ = SUITE_SERVER; + break; + case PRODUCT_PROFESSIONAL: + case PRODUCT_ULTIMATE: + version_type_ = SUITE_PROFESSIONAL; + break; + case PRODUCT_ENTERPRISE: + case PRODUCT_ENTERPRISE_E: + case PRODUCT_ENTERPRISE_EVALUATION: + case PRODUCT_ENTERPRISE_N: + case PRODUCT_ENTERPRISE_N_EVALUATION: + case PRODUCT_ENTERPRISE_S: + case PRODUCT_ENTERPRISE_S_EVALUATION: + case PRODUCT_ENTERPRISE_S_N: + case PRODUCT_ENTERPRISE_S_N_EVALUATION: + case PRODUCT_BUSINESS: + case PRODUCT_BUSINESS_N: + version_type_ = SUITE_ENTERPRISE; + break; + case PRODUCT_EDUCATION: + case PRODUCT_EDUCATION_N: + version_type_ = SUITE_EDUCATION; + break; + case PRODUCT_HOME_BASIC: + case PRODUCT_HOME_PREMIUM: + case PRODUCT_STARTER: + default: + version_type_ = SUITE_HOME; + break; + } + } else if (version_info.dwMajorVersion == 5 && + version_info.dwMinorVersion == 2) { + if (version_info.wProductType == VER_NT_WORKSTATION && + system_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) { + version_type_ = SUITE_PROFESSIONAL; + } else if (version_info.wSuiteMask & VER_SUITE_WH_SERVER) { + version_type_ = SUITE_HOME; + } else { + version_type_ = SUITE_SERVER; + } + } else if (version_info.dwMajorVersion == 5 && + version_info.dwMinorVersion == 1) { + if (version_info.wSuiteMask & VER_SUITE_PERSONAL) + version_type_ = SUITE_HOME; + else + version_type_ = SUITE_PROFESSIONAL; + } else { + // Windows is pre XP so we don't care but pick a safe default. + version_type_ = SUITE_HOME; + } +} + +OSInfo::~OSInfo() {} + +std::string OSInfo::processor_model_name() { + if (processor_model_name_.empty()) { + const wchar_t kProcessorNameString[] = + L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"; + RegKey key(HKEY_LOCAL_MACHINE, kProcessorNameString, KEY_READ); + std::wstring value; + key.ReadValue(L"ProcessorNameString", &value); + processor_model_name_ = rtc::ToUtf8(value); + } + return processor_model_name_; +} + +// static +OSInfo::WOW64Status OSInfo::GetWOW64StatusForProcess(HANDLE process_handle) { + typedef BOOL(WINAPI * IsWow64ProcessFunc)(HANDLE, PBOOL); + IsWow64ProcessFunc is_wow64_process = reinterpret_cast( + GetProcAddress(GetModuleHandle(L"kernel32.dll"), "IsWow64Process")); + if (!is_wow64_process) + return WOW64_DISABLED; + BOOL is_wow64 = FALSE; + if (!(*is_wow64_process)(process_handle, &is_wow64)) + return WOW64_UNKNOWN; + return is_wow64 ? WOW64_ENABLED : WOW64_DISABLED; +} + +Version GetVersion() { + return OSInfo::GetInstance()->version(); +} +std::string getosver() +{ + return std::move(std::string(VersionStr[GetVersion()].desc)); +} +} // namespace rtc_win +} // namespace rtc diff --git a/get/windows_version.h b/get/windows_version.h new file mode 100644 index 0000000000..25fd181d87 --- /dev/null +++ b/get/windows_version.h @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef RTC_BASE_WIN_WINDOWS_VERSION_H_ +#define RTC_BASE_WIN_WINDOWS_VERSION_H_ + +#include +#include + +#include "constructormagic.h" + +typedef void* HANDLE; + +namespace rtc { +namespace rtc_win { + +// The running version of Windows. This is declared outside OSInfo for +// syntactic sugar reasons; see the declaration of GetVersion() below. +// NOTE: Keep these in order so callers can do things like +// "if (rtc_win::GetVersion() >= rtc_win::VERSION_VISTA) ...". +// +// This enum is used in metrics histograms, so they shouldn't be reordered or +// removed. New values can be added before VERSION_WIN_LAST. +enum Version { + VERSION_PRE_XP = 0, // Not supported. + VERSION_XP = 1, + VERSION_SERVER_2003 = 2, // Also includes XP Pro x64 and Server 2003 R2. + VERSION_VISTA = 3, // Also includes Windows Server 2008. + VERSION_WIN7 = 4, // Also includes Windows Server 2008 R2. + VERSION_WIN8 = 5, // Also includes Windows Server 2012. + VERSION_WIN8_1 = 6, // Also includes Windows Server 2012 R2. + VERSION_WIN10 = 7, // Threshold 1: Version 1507, Build 10240. + VERSION_WIN10_TH2 = 8, // Threshold 2: Version 1511, Build 10586. + VERSION_WIN10_RS1 = 9, // Redstone 1: Version 1607, Build 14393. + VERSION_WIN10_RS2 = 10, // Redstone 2: Version 1703, Build 15063. + VERSION_WIN10_RS3 = 11, // Redstone 3: Version 1709, Build 16299. + VERSION_WIN10_RS4 = 12, // Redstone 4: Version 1803, Build 17134. + // On edit, update tools\metrics\histograms\enums.xml "WindowsVersion" and + // "GpuBlacklistFeatureTestResultsWindows2". + VERSION_WIN_LAST, // Indicates error condition. +}; +//using VersionStr = std::map; +static const struct T_VersionStr +{ + Version v; + const char* desc; +}VersionStr[] = +{ + { Version::VERSION_PRE_XP, "PRE_XP" }, + { Version::VERSION_XP ,"xp" }, + { Version::VERSION_SERVER_2003, "XP Pro x64 and Server 2003 R2"}, + { Version::VERSION_VISTA , "VISTA , Windows Server 2008" }, + { Version::VERSION_WIN7 , "WIN7 ,Windows Server 2008 R2" }, + { Version::VERSION_WIN8 , "WIN8, Windows Server 2012" }, + {Version::VERSION_WIN8_1 , "WIN8.1, Windows Server 2012 R2"}, + {Version::VERSION_WIN10 , "WIN10, Threshold 1: Version 1507, Build 10240"}, + {Version::VERSION_WIN10_TH2 , "WIN10, Threshold 2: Version 1511, Build 10586" }, + {Version::VERSION_WIN10_RS1 , "WIN10 Redstone 1: Version 1607, Build 14393"}, + { Version::VERSION_WIN10_RS2 , "WIN10 Redstone 2: Version 1703, Build 15063"}, + {Version::VERSION_WIN10_RS3, "WIN10 Redstone 3: Version 1709, Build 16299"}, + {Version::VERSION_WIN10_RS4 , "WIN10 Redstone 4: Version 1803, Build 17134."}, + // On edit, update tools\metrics\histograms\enums.xml "WindowsVersion" and + // "GpuBlacklistFeatureTestResultsWindows2". + {Version::VERSION_WIN_LAST,"Indicates error condition."} +}; + +// A rough bucketing of the available types of versions of Windows. This is used +// to distinguish enterprise enabled versions from home versions and potentially +// server versions. Keep these values in the same order, since they are used as +// is for metrics histogram ids. +enum VersionType { + SUITE_HOME = 0, + SUITE_PROFESSIONAL, + SUITE_SERVER, + SUITE_ENTERPRISE, + SUITE_EDUCATION, + SUITE_LAST, +}; + +// A singleton that can be used to query various pieces of information about the +// OS and process state. Note that this doesn't use the base Singleton class, so +// it can be used without an AtExitManager. +class OSInfo { + public: + struct VersionNumber { + int major; + int minor; + int build; + int patch; + }; + + struct ServicePack { + int major; + int minor; + }; + + // The processor architecture this copy of Windows natively uses. For + // example, given an x64-capable processor, we have three possibilities: + // 32-bit Chrome running on 32-bit Windows: X86_ARCHITECTURE + // 32-bit Chrome running on 64-bit Windows via WOW64: X64_ARCHITECTURE + // 64-bit Chrome running on 64-bit Windows: X64_ARCHITECTURE + enum WindowsArchitecture { + X86_ARCHITECTURE, + X64_ARCHITECTURE, + IA64_ARCHITECTURE, + OTHER_ARCHITECTURE, + }; + + // Whether a process is running under WOW64 (the wrapper that allows 32-bit + // processes to run on 64-bit versions of Windows). This will return + // WOW64_DISABLED for both "32-bit Chrome on 32-bit Windows" and "64-bit + // Chrome on 64-bit Windows". WOW64_UNKNOWN means "an error occurred", e.g. + // the process does not have sufficient access rights to determine this. + enum WOW64Status { + WOW64_DISABLED, + WOW64_ENABLED, + WOW64_UNKNOWN, + }; + + static OSInfo* GetInstance(); + + Version version() const { return version_; } + VersionNumber version_number() const { return version_number_; } + VersionType version_type() const { return version_type_; } + ServicePack service_pack() const { return service_pack_; } + std::string service_pack_str() const { return service_pack_str_; } + WindowsArchitecture architecture() const { return architecture_; } + int processors() const { return processors_; } + size_t allocation_granularity() const { return allocation_granularity_; } + WOW64Status wow64_status() const { return wow64_status_; } + std::string processor_model_name(); + + // Like wow64_status(), but for the supplied handle instead of the current + // process. This doesn't touch member state, so you can bypass the singleton. + static WOW64Status GetWOW64StatusForProcess(HANDLE process_handle); + + private: + OSInfo(); + ~OSInfo(); + + Version version_; + VersionNumber version_number_; + VersionType version_type_; + ServicePack service_pack_; + + // A string, such as "Service Pack 3", that indicates the latest Service Pack + // installed on the system. If no Service Pack has been installed, the string + // is empty. + std::string service_pack_str_; + WindowsArchitecture architecture_; + int processors_; + size_t allocation_granularity_; + WOW64Status wow64_status_; + std::string processor_model_name_; + + //RTC_DISALLOW_COPY_AND_ASSIGN(OSInfo); +}; + +// Because this is by far the most commonly-requested value from the above +// singleton, we add a global-scope accessor here as syntactic sugar. +Version GetVersion(); +__declspec(dllexport) std::string getosver(); +} // namespace rtc_win +} // namespace rtc + +#endif // RTC_BASE_WIN_WINDOWS_VERSION_H_ diff --git a/nlohmann/adl_serializer.hpp b/nlohmann/adl_serializer.hpp new file mode 100644 index 0000000000..eeaa142574 --- /dev/null +++ b/nlohmann/adl_serializer.hpp @@ -0,0 +1,49 @@ +#pragma once + +#include + +#include +#include + +namespace nlohmann +{ + +template +struct adl_serializer +{ + /*! + @brief convert a JSON value to any value type + + This function is usually called by the `get()` function of the + @ref basic_json class (either explicit or via conversion operators). + + @param[in] j JSON value to read from + @param[in,out] val value to write to + */ + template + static auto from_json(BasicJsonType&& j, ValueType& val) noexcept( + noexcept(::nlohmann::from_json(std::forward(j), val))) + -> decltype(::nlohmann::from_json(std::forward(j), val), void()) + { + ::nlohmann::from_json(std::forward(j), val); + } + + /*! + @brief convert any value type to a JSON value + + This function is usually called by the constructors of the @ref basic_json + class. + + @param[in,out] j JSON value to write to + @param[in] val value to read from + */ + template + static auto to_json(BasicJsonType& j, ValueType&& val) noexcept( + noexcept(::nlohmann::to_json(j, std::forward(val)))) + -> decltype(::nlohmann::to_json(j, std::forward(val)), void()) + { + ::nlohmann::to_json(j, std::forward(val)); + } +}; + +} // namespace nlohmann diff --git a/nlohmann/detail/conversions/from_json.hpp b/nlohmann/detail/conversions/from_json.hpp new file mode 100644 index 0000000000..8f8162ff94 --- /dev/null +++ b/nlohmann/detail/conversions/from_json.hpp @@ -0,0 +1,370 @@ +#pragma once + +#include // transform +#include // array +#include // and, not +#include // forward_list +#include // inserter, front_inserter, end +#include // map +#include // string +#include // tuple, make_tuple +#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible +#include // unordered_map +#include // pair, declval +#include // valarray + +#include +#include +#include +#include +#include + +namespace nlohmann +{ +namespace detail +{ +template +void from_json(const BasicJsonType& j, typename std::nullptr_t& n) +{ + if (JSON_UNLIKELY(not j.is_null())) + { + JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name()))); + } + n = nullptr; +} + +// overloads for basic_json template parameters +template::value and + not std::is_same::value, + int> = 0> +void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) +{ + switch (static_cast(j)) + { + case value_t::number_unsigned: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_integer: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_float: + { + val = static_cast(*j.template get_ptr()); + break; + } + + default: + JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()))); + } +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) +{ + if (JSON_UNLIKELY(not j.is_boolean())) + { + JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()))); + } + b = *j.template get_ptr(); +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) +{ + if (JSON_UNLIKELY(not j.is_string())) + { + JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()))); + } + s = *j.template get_ptr(); +} + +template < + typename BasicJsonType, typename ConstructibleStringType, + enable_if_t < + is_constructible_string_type::value and + not std::is_same::value, + int > = 0 > +void from_json(const BasicJsonType& j, ConstructibleStringType& s) +{ + if (JSON_UNLIKELY(not j.is_string())) + { + JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()))); + } + + s = *j.template get_ptr(); +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) +{ + get_arithmetic_value(j, val); +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) +{ + get_arithmetic_value(j, val); +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) +{ + get_arithmetic_value(j, val); +} + +template::value, int> = 0> +void from_json(const BasicJsonType& j, EnumType& e) +{ + typename std::underlying_type::type val; + get_arithmetic_value(j, val); + e = static_cast(val); +} + +// forward_list doesn't have an insert method +template::value, int> = 0> +void from_json(const BasicJsonType& j, std::forward_list& l) +{ + if (JSON_UNLIKELY(not j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); + } + std::transform(j.rbegin(), j.rend(), + std::front_inserter(l), [](const BasicJsonType & i) + { + return i.template get(); + }); +} + +// valarray doesn't have an insert method +template::value, int> = 0> +void from_json(const BasicJsonType& j, std::valarray& l) +{ + if (JSON_UNLIKELY(not j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); + } + l.resize(j.size()); + std::copy(j.m_value.array->begin(), j.m_value.array->end(), std::begin(l)); +} + +template +void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) +{ + arr = *j.template get_ptr(); +} + +template +auto from_json_array_impl(const BasicJsonType& j, std::array& arr, + priority_tag<2> /*unused*/) +-> decltype(j.template get(), void()) +{ + for (std::size_t i = 0; i < N; ++i) + { + arr[i] = j.at(i).template get(); + } +} + +template +auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/) +-> decltype( + arr.reserve(std::declval()), + j.template get(), + void()) +{ + using std::end; + + arr.reserve(j.size()); + std::transform(j.begin(), j.end(), + std::inserter(arr, end(arr)), [](const BasicJsonType & i) + { + // get() returns *this, this won't call a from_json + // method when value_type is BasicJsonType + return i.template get(); + }); +} + +template +void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, + priority_tag<0> /*unused*/) +{ + using std::end; + + std::transform( + j.begin(), j.end(), std::inserter(arr, end(arr)), + [](const BasicJsonType & i) + { + // get() returns *this, this won't call a from_json + // method when value_type is BasicJsonType + return i.template get(); + }); +} + +template ::value and + not is_constructible_object_type::value and + not is_constructible_string_type::value and + not is_basic_json::value, + int > = 0 > + +auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr) +-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}), +j.template get(), +void()) +{ + if (JSON_UNLIKELY(not j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + + std::string(j.type_name()))); + } + + from_json_array_impl(j, arr, priority_tag<3> {}); +} + +template::value, int> = 0> +void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) +{ + if (JSON_UNLIKELY(not j.is_object())) + { + JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()))); + } + + auto inner_object = j.template get_ptr(); + using value_type = typename ConstructibleObjectType::value_type; + std::transform( + inner_object->begin(), inner_object->end(), + std::inserter(obj, obj.begin()), + [](typename BasicJsonType::object_t::value_type const & p) + { + return value_type(p.first, p.second.template get()); + }); +} + +// overload for arithmetic types, not chosen for basic_json template arguments +// (BooleanType, etc..); note: Is it really necessary to provide explicit +// overloads for boolean_t etc. in case of a custom BooleanType which is not +// an arithmetic type? +template::value and + not std::is_same::value and + not std::is_same::value and + not std::is_same::value and + not std::is_same::value, + int> = 0> +void from_json(const BasicJsonType& j, ArithmeticType& val) +{ + switch (static_cast(j)) + { + case value_t::number_unsigned: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_integer: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_float: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::boolean: + { + val = static_cast(*j.template get_ptr()); + break; + } + + default: + JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()))); + } +} + +template +void from_json(const BasicJsonType& j, std::pair& p) +{ + p = {j.at(0).template get(), j.at(1).template get()}; +} + +template +void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence /*unused*/) +{ + t = std::make_tuple(j.at(Idx).template get::type>()...); +} + +template +void from_json(const BasicJsonType& j, std::tuple& t) +{ + from_json_tuple_impl(j, t, index_sequence_for {}); +} + +template ::value>> +void from_json(const BasicJsonType& j, std::map& m) +{ + if (JSON_UNLIKELY(not j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); + } + for (const auto& p : j) + { + if (JSON_UNLIKELY(not p.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()))); + } + m.emplace(p.at(0).template get(), p.at(1).template get()); + } +} + +template ::value>> +void from_json(const BasicJsonType& j, std::unordered_map& m) +{ + if (JSON_UNLIKELY(not j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); + } + for (const auto& p : j) + { + if (JSON_UNLIKELY(not p.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()))); + } + m.emplace(p.at(0).template get(), p.at(1).template get()); + } +} + +struct from_json_fn +{ + template + auto operator()(const BasicJsonType& j, T& val) const + noexcept(noexcept(from_json(j, val))) + -> decltype(from_json(j, val), void()) + { + return from_json(j, val); + } +}; +} // namespace detail + +/// namespace to hold default `from_json` function +/// to see why this is required: +/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html +namespace +{ +constexpr const auto& from_json = detail::static_const::value; +} // namespace +} // namespace nlohmann diff --git a/nlohmann/detail/conversions/to_chars.hpp b/nlohmann/detail/conversions/to_chars.hpp new file mode 100644 index 0000000000..2a264a8775 --- /dev/null +++ b/nlohmann/detail/conversions/to_chars.hpp @@ -0,0 +1,1097 @@ +#pragma once + +#include // array +#include // assert +#include // or, and, not +#include // signbit, isfinite +#include // intN_t, uintN_t +#include // memcpy, memmove +#include // numeric_limits +#include // conditional + +namespace nlohmann +{ +namespace detail +{ + +/*! +@brief implements the Grisu2 algorithm for binary to decimal floating-point +conversion. + +This implementation is a slightly modified version of the reference +implementation which may be obtained from +http://florian.loitsch.com/publications (bench.tar.gz). + +The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch. + +For a detailed description of the algorithm see: + +[1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with + Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming + Language Design and Implementation, PLDI 2010 +[2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately", + Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language + Design and Implementation, PLDI 1996 +*/ +namespace dtoa_impl +{ + +template +Target reinterpret_bits(const Source source) +{ + static_assert(sizeof(Target) == sizeof(Source), "size mismatch"); + + Target target; + std::memcpy(&target, &source, sizeof(Source)); + return target; +} + +struct diyfp // f * 2^e +{ + static constexpr int kPrecision = 64; // = q + + std::uint64_t f = 0; + int e = 0; + + constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {} + + /*! + @brief returns x - y + @pre x.e == y.e and x.f >= y.f + */ + static diyfp sub(const diyfp& x, const diyfp& y) noexcept + { + assert(x.e == y.e); + assert(x.f >= y.f); + + return {x.f - y.f, x.e}; + } + + /*! + @brief returns x * y + @note The result is rounded. (Only the upper q bits are returned.) + */ + static diyfp mul(const diyfp& x, const diyfp& y) noexcept + { + static_assert(kPrecision == 64, "internal error"); + + // Computes: + // f = round((x.f * y.f) / 2^q) + // e = x.e + y.e + q + + // Emulate the 64-bit * 64-bit multiplication: + // + // p = u * v + // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi) + // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi ) + // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 ) + // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 ) + // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3) + // = (p0_lo ) + 2^32 (Q ) + 2^64 (H ) + // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H ) + // + // (Since Q might be larger than 2^32 - 1) + // + // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H) + // + // (Q_hi + H does not overflow a 64-bit int) + // + // = p_lo + 2^64 p_hi + + const std::uint64_t u_lo = x.f & 0xFFFFFFFFu; + const std::uint64_t u_hi = x.f >> 32u; + const std::uint64_t v_lo = y.f & 0xFFFFFFFFu; + const std::uint64_t v_hi = y.f >> 32u; + + const std::uint64_t p0 = u_lo * v_lo; + const std::uint64_t p1 = u_lo * v_hi; + const std::uint64_t p2 = u_hi * v_lo; + const std::uint64_t p3 = u_hi * v_hi; + + const std::uint64_t p0_hi = p0 >> 32u; + const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu; + const std::uint64_t p1_hi = p1 >> 32u; + const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu; + const std::uint64_t p2_hi = p2 >> 32u; + + std::uint64_t Q = p0_hi + p1_lo + p2_lo; + + // The full product might now be computed as + // + // p_hi = p3 + p2_hi + p1_hi + (Q >> 32) + // p_lo = p0_lo + (Q << 32) + // + // But in this particular case here, the full p_lo is not required. + // Effectively we only need to add the highest bit in p_lo to p_hi (and + // Q_hi + 1 does not overflow). + + Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up + + const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u); + + return {h, x.e + y.e + 64}; + } + + /*! + @brief normalize x such that the significand is >= 2^(q-1) + @pre x.f != 0 + */ + static diyfp normalize(diyfp x) noexcept + { + assert(x.f != 0); + + while ((x.f >> 63u) == 0) + { + x.f <<= 1u; + x.e--; + } + + return x; + } + + /*! + @brief normalize x such that the result has the exponent E + @pre e >= x.e and the upper e - x.e bits of x.f must be zero. + */ + static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept + { + const int delta = x.e - target_exponent; + + assert(delta >= 0); + assert(((x.f << delta) >> delta) == x.f); + + return {x.f << delta, target_exponent}; + } +}; + +struct boundaries +{ + diyfp w; + diyfp minus; + diyfp plus; +}; + +/*! +Compute the (normalized) diyfp representing the input number 'value' and its +boundaries. + +@pre value must be finite and positive +*/ +template +boundaries compute_boundaries(FloatType value) +{ + assert(std::isfinite(value)); + assert(value > 0); + + // Convert the IEEE representation into a diyfp. + // + // If v is denormal: + // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1)) + // If v is normalized: + // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1)) + + static_assert(std::numeric_limits::is_iec559, + "internal error: dtoa_short requires an IEEE-754 floating-point implementation"); + + constexpr int kPrecision = std::numeric_limits::digits; // = p (includes the hidden bit) + constexpr int kBias = std::numeric_limits::max_exponent - 1 + (kPrecision - 1); + constexpr int kMinExp = 1 - kBias; + constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1) + + using bits_type = typename std::conditional::type; + + const std::uint64_t bits = reinterpret_bits(value); + const std::uint64_t E = bits >> (kPrecision - 1); + const std::uint64_t F = bits & (kHiddenBit - 1); + + const bool is_denormal = E == 0; + const diyfp v = is_denormal + ? diyfp(F, kMinExp) + : diyfp(F + kHiddenBit, static_cast(E) - kBias); + + // Compute the boundaries m- and m+ of the floating-point value + // v = f * 2^e. + // + // Determine v- and v+, the floating-point predecessor and successor if v, + // respectively. + // + // v- = v - 2^e if f != 2^(p-1) or e == e_min (A) + // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B) + // + // v+ = v + 2^e + // + // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_ + // between m- and m+ round to v, regardless of how the input rounding + // algorithm breaks ties. + // + // ---+-------------+-------------+-------------+-------------+--- (A) + // v- m- v m+ v+ + // + // -----------------+------+------+-------------+-------------+--- (B) + // v- m- v m+ v+ + + const bool lower_boundary_is_closer = F == 0 and E > 1; + const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1); + const diyfp m_minus = lower_boundary_is_closer + ? diyfp(4 * v.f - 1, v.e - 2) // (B) + : diyfp(2 * v.f - 1, v.e - 1); // (A) + + // Determine the normalized w+ = m+. + const diyfp w_plus = diyfp::normalize(m_plus); + + // Determine w- = m- such that e_(w-) = e_(w+). + const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e); + + return {diyfp::normalize(v), w_minus, w_plus}; +} + +// Given normalized diyfp w, Grisu needs to find a (normalized) cached +// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies +// within a certain range [alpha, gamma] (Definition 3.2 from [1]) +// +// alpha <= e = e_c + e_w + q <= gamma +// +// or +// +// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q +// <= f_c * f_w * 2^gamma +// +// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies +// +// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma +// +// or +// +// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma) +// +// The choice of (alpha,gamma) determines the size of the table and the form of +// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well +// in practice: +// +// The idea is to cut the number c * w = f * 2^e into two parts, which can be +// processed independently: An integral part p1, and a fractional part p2: +// +// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e +// = (f div 2^-e) + (f mod 2^-e) * 2^e +// = p1 + p2 * 2^e +// +// The conversion of p1 into decimal form requires a series of divisions and +// modulos by (a power of) 10. These operations are faster for 32-bit than for +// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be +// achieved by choosing +// +// -e >= 32 or e <= -32 := gamma +// +// In order to convert the fractional part +// +// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ... +// +// into decimal form, the fraction is repeatedly multiplied by 10 and the digits +// d[-i] are extracted in order: +// +// (10 * p2) div 2^-e = d[-1] +// (10 * p2) mod 2^-e = d[-2] / 10^1 + ... +// +// The multiplication by 10 must not overflow. It is sufficient to choose +// +// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64. +// +// Since p2 = f mod 2^-e < 2^-e, +// +// -e <= 60 or e >= -60 := alpha + +constexpr int kAlpha = -60; +constexpr int kGamma = -32; + +struct cached_power // c = f * 2^e ~= 10^k +{ + std::uint64_t f; + int e; + int k; +}; + +/*! +For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached +power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c +satisfies (Definition 3.2 from [1]) + + alpha <= e_c + e + q <= gamma. +*/ +inline cached_power get_cached_power_for_binary_exponent(int e) +{ + // Now + // + // alpha <= e_c + e + q <= gamma (1) + // ==> f_c * 2^alpha <= c * 2^e * 2^q + // + // and since the c's are normalized, 2^(q-1) <= f_c, + // + // ==> 2^(q - 1 + alpha) <= c * 2^(e + q) + // ==> 2^(alpha - e - 1) <= c + // + // If c were an exakt power of ten, i.e. c = 10^k, one may determine k as + // + // k = ceil( log_10( 2^(alpha - e - 1) ) ) + // = ceil( (alpha - e - 1) * log_10(2) ) + // + // From the paper: + // "In theory the result of the procedure could be wrong since c is rounded, + // and the computation itself is approximated [...]. In practice, however, + // this simple function is sufficient." + // + // For IEEE double precision floating-point numbers converted into + // normalized diyfp's w = f * 2^e, with q = 64, + // + // e >= -1022 (min IEEE exponent) + // -52 (p - 1) + // -52 (p - 1, possibly normalize denormal IEEE numbers) + // -11 (normalize the diyfp) + // = -1137 + // + // and + // + // e <= +1023 (max IEEE exponent) + // -52 (p - 1) + // -11 (normalize the diyfp) + // = 960 + // + // This binary exponent range [-1137,960] results in a decimal exponent + // range [-307,324]. One does not need to store a cached power for each + // k in this range. For each such k it suffices to find a cached power + // such that the exponent of the product lies in [alpha,gamma]. + // This implies that the difference of the decimal exponents of adjacent + // table entries must be less than or equal to + // + // floor( (gamma - alpha) * log_10(2) ) = 8. + // + // (A smaller distance gamma-alpha would require a larger table.) + + // NB: + // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34. + + constexpr int kCachedPowersMinDecExp = -300; + constexpr int kCachedPowersDecStep = 8; + + static constexpr std::array kCachedPowers = + { + { + { 0xAB70FE17C79AC6CA, -1060, -300 }, + { 0xFF77B1FCBEBCDC4F, -1034, -292 }, + { 0xBE5691EF416BD60C, -1007, -284 }, + { 0x8DD01FAD907FFC3C, -980, -276 }, + { 0xD3515C2831559A83, -954, -268 }, + { 0x9D71AC8FADA6C9B5, -927, -260 }, + { 0xEA9C227723EE8BCB, -901, -252 }, + { 0xAECC49914078536D, -874, -244 }, + { 0x823C12795DB6CE57, -847, -236 }, + { 0xC21094364DFB5637, -821, -228 }, + { 0x9096EA6F3848984F, -794, -220 }, + { 0xD77485CB25823AC7, -768, -212 }, + { 0xA086CFCD97BF97F4, -741, -204 }, + { 0xEF340A98172AACE5, -715, -196 }, + { 0xB23867FB2A35B28E, -688, -188 }, + { 0x84C8D4DFD2C63F3B, -661, -180 }, + { 0xC5DD44271AD3CDBA, -635, -172 }, + { 0x936B9FCEBB25C996, -608, -164 }, + { 0xDBAC6C247D62A584, -582, -156 }, + { 0xA3AB66580D5FDAF6, -555, -148 }, + { 0xF3E2F893DEC3F126, -529, -140 }, + { 0xB5B5ADA8AAFF80B8, -502, -132 }, + { 0x87625F056C7C4A8B, -475, -124 }, + { 0xC9BCFF6034C13053, -449, -116 }, + { 0x964E858C91BA2655, -422, -108 }, + { 0xDFF9772470297EBD, -396, -100 }, + { 0xA6DFBD9FB8E5B88F, -369, -92 }, + { 0xF8A95FCF88747D94, -343, -84 }, + { 0xB94470938FA89BCF, -316, -76 }, + { 0x8A08F0F8BF0F156B, -289, -68 }, + { 0xCDB02555653131B6, -263, -60 }, + { 0x993FE2C6D07B7FAC, -236, -52 }, + { 0xE45C10C42A2B3B06, -210, -44 }, + { 0xAA242499697392D3, -183, -36 }, + { 0xFD87B5F28300CA0E, -157, -28 }, + { 0xBCE5086492111AEB, -130, -20 }, + { 0x8CBCCC096F5088CC, -103, -12 }, + { 0xD1B71758E219652C, -77, -4 }, + { 0x9C40000000000000, -50, 4 }, + { 0xE8D4A51000000000, -24, 12 }, + { 0xAD78EBC5AC620000, 3, 20 }, + { 0x813F3978F8940984, 30, 28 }, + { 0xC097CE7BC90715B3, 56, 36 }, + { 0x8F7E32CE7BEA5C70, 83, 44 }, + { 0xD5D238A4ABE98068, 109, 52 }, + { 0x9F4F2726179A2245, 136, 60 }, + { 0xED63A231D4C4FB27, 162, 68 }, + { 0xB0DE65388CC8ADA8, 189, 76 }, + { 0x83C7088E1AAB65DB, 216, 84 }, + { 0xC45D1DF942711D9A, 242, 92 }, + { 0x924D692CA61BE758, 269, 100 }, + { 0xDA01EE641A708DEA, 295, 108 }, + { 0xA26DA3999AEF774A, 322, 116 }, + { 0xF209787BB47D6B85, 348, 124 }, + { 0xB454E4A179DD1877, 375, 132 }, + { 0x865B86925B9BC5C2, 402, 140 }, + { 0xC83553C5C8965D3D, 428, 148 }, + { 0x952AB45CFA97A0B3, 455, 156 }, + { 0xDE469FBD99A05FE3, 481, 164 }, + { 0xA59BC234DB398C25, 508, 172 }, + { 0xF6C69A72A3989F5C, 534, 180 }, + { 0xB7DCBF5354E9BECE, 561, 188 }, + { 0x88FCF317F22241E2, 588, 196 }, + { 0xCC20CE9BD35C78A5, 614, 204 }, + { 0x98165AF37B2153DF, 641, 212 }, + { 0xE2A0B5DC971F303A, 667, 220 }, + { 0xA8D9D1535CE3B396, 694, 228 }, + { 0xFB9B7CD9A4A7443C, 720, 236 }, + { 0xBB764C4CA7A44410, 747, 244 }, + { 0x8BAB8EEFB6409C1A, 774, 252 }, + { 0xD01FEF10A657842C, 800, 260 }, + { 0x9B10A4E5E9913129, 827, 268 }, + { 0xE7109BFBA19C0C9D, 853, 276 }, + { 0xAC2820D9623BF429, 880, 284 }, + { 0x80444B5E7AA7CF85, 907, 292 }, + { 0xBF21E44003ACDD2D, 933, 300 }, + { 0x8E679C2F5E44FF8F, 960, 308 }, + { 0xD433179D9C8CB841, 986, 316 }, + { 0x9E19DB92B4E31BA9, 1013, 324 }, + } + }; + + // This computation gives exactly the same results for k as + // k = ceil((kAlpha - e - 1) * 0.30102999566398114) + // for |e| <= 1500, but doesn't require floating-point operations. + // NB: log_10(2) ~= 78913 / 2^18 + assert(e >= -1500); + assert(e <= 1500); + const int f = kAlpha - e - 1; + const int k = (f * 78913) / (1 << 18) + static_cast(f > 0); + + const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep; + assert(index >= 0); + assert(static_cast(index) < kCachedPowers.size()); + + const cached_power cached = kCachedPowers[static_cast(index)]; + assert(kAlpha <= cached.e + e + 64); + assert(kGamma >= cached.e + e + 64); + + return cached; +} + +/*! +For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k. +For n == 0, returns 1 and sets pow10 := 1. +*/ +inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10) +{ + // LCOV_EXCL_START + if (n >= 1000000000) + { + pow10 = 1000000000; + return 10; + } + // LCOV_EXCL_STOP + else if (n >= 100000000) + { + pow10 = 100000000; + return 9; + } + else if (n >= 10000000) + { + pow10 = 10000000; + return 8; + } + else if (n >= 1000000) + { + pow10 = 1000000; + return 7; + } + else if (n >= 100000) + { + pow10 = 100000; + return 6; + } + else if (n >= 10000) + { + pow10 = 10000; + return 5; + } + else if (n >= 1000) + { + pow10 = 1000; + return 4; + } + else if (n >= 100) + { + pow10 = 100; + return 3; + } + else if (n >= 10) + { + pow10 = 10; + return 2; + } + else + { + pow10 = 1; + return 1; + } +} + +inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta, + std::uint64_t rest, std::uint64_t ten_k) +{ + assert(len >= 1); + assert(dist <= delta); + assert(rest <= delta); + assert(ten_k > 0); + + // <--------------------------- delta ----> + // <---- dist ---------> + // --------------[------------------+-------------------]-------------- + // M- w M+ + // + // ten_k + // <------> + // <---- rest ----> + // --------------[------------------+----+--------------]-------------- + // w V + // = buf * 10^k + // + // ten_k represents a unit-in-the-last-place in the decimal representation + // stored in buf. + // Decrement buf by ten_k while this takes buf closer to w. + + // The tests are written in this order to avoid overflow in unsigned + // integer arithmetic. + + while (rest < dist + and delta - rest >= ten_k + and (rest + ten_k < dist or dist - rest > rest + ten_k - dist)) + { + assert(buf[len - 1] != '0'); + buf[len - 1]--; + rest += ten_k; + } +} + +/*! +Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+. +M- and M+ must be normalized and share the same exponent -60 <= e <= -32. +*/ +inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, + diyfp M_minus, diyfp w, diyfp M_plus) +{ + static_assert(kAlpha >= -60, "internal error"); + static_assert(kGamma <= -32, "internal error"); + + // Generates the digits (and the exponent) of a decimal floating-point + // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's + // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma. + // + // <--------------------------- delta ----> + // <---- dist ---------> + // --------------[------------------+-------------------]-------------- + // M- w M+ + // + // Grisu2 generates the digits of M+ from left to right and stops as soon as + // V is in [M-,M+]. + + assert(M_plus.e >= kAlpha); + assert(M_plus.e <= kGamma); + + std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e) + std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e) + + // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0): + // + // M+ = f * 2^e + // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e + // = ((p1 ) * 2^-e + (p2 )) * 2^e + // = p1 + p2 * 2^e + + const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e); + + auto p1 = static_cast(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.) + std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e + + // 1) + // + // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0] + + assert(p1 > 0); + + std::uint32_t pow10; + const int k = find_largest_pow10(p1, pow10); + + // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1) + // + // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1)) + // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1)) + // + // M+ = p1 + p2 * 2^e + // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e + // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e + // = d[k-1] * 10^(k-1) + ( rest) * 2^e + // + // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0) + // + // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0] + // + // but stop as soon as + // + // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e + + int n = k; + while (n > 0) + { + // Invariants: + // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k) + // pow10 = 10^(n-1) <= p1 < 10^n + // + const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1) + const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1) + // + // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e + // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e) + // + assert(d <= 9); + buffer[length++] = static_cast('0' + d); // buffer := buffer * 10 + d + // + // M+ = buffer * 10^(n-1) + (r + p2 * 2^e) + // + p1 = r; + n--; + // + // M+ = buffer * 10^n + (p1 + p2 * 2^e) + // pow10 = 10^n + // + + // Now check if enough digits have been generated. + // Compute + // + // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e + // + // Note: + // Since rest and delta share the same exponent e, it suffices to + // compare the significands. + const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2; + if (rest <= delta) + { + // V = buffer * 10^n, with M- <= V <= M+. + + decimal_exponent += n; + + // We may now just stop. But instead look if the buffer could be + // decremented to bring V closer to w. + // + // pow10 = 10^n is now 1 ulp in the decimal representation V. + // The rounding procedure works with diyfp's with an implicit + // exponent of e. + // + // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e + // + const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e; + grisu2_round(buffer, length, dist, delta, rest, ten_n); + + return; + } + + pow10 /= 10; + // + // pow10 = 10^(n-1) <= p1 < 10^n + // Invariants restored. + } + + // 2) + // + // The digits of the integral part have been generated: + // + // M+ = d[k-1]...d[1]d[0] + p2 * 2^e + // = buffer + p2 * 2^e + // + // Now generate the digits of the fractional part p2 * 2^e. + // + // Note: + // No decimal point is generated: the exponent is adjusted instead. + // + // p2 actually represents the fraction + // + // p2 * 2^e + // = p2 / 2^-e + // = d[-1] / 10^1 + d[-2] / 10^2 + ... + // + // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...) + // + // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m + // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...) + // + // using + // + // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e) + // = ( d) * 2^-e + ( r) + // + // or + // 10^m * p2 * 2^e = d + r * 2^e + // + // i.e. + // + // M+ = buffer + p2 * 2^e + // = buffer + 10^-m * (d + r * 2^e) + // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e + // + // and stop as soon as 10^-m * r * 2^e <= delta * 2^e + + assert(p2 > delta); + + int m = 0; + for (;;) + { + // Invariant: + // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e + // = buffer * 10^-m + 10^-m * (p2 ) * 2^e + // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e + // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e + // + assert(p2 <= (std::numeric_limits::max)() / 10); + p2 *= 10; + const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e + const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e + // + // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e + // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e)) + // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e + // + assert(d <= 9); + buffer[length++] = static_cast('0' + d); // buffer := buffer * 10 + d + // + // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e + // + p2 = r; + m++; + // + // M+ = buffer * 10^-m + 10^-m * p2 * 2^e + // Invariant restored. + + // Check if enough digits have been generated. + // + // 10^-m * p2 * 2^e <= delta * 2^e + // p2 * 2^e <= 10^m * delta * 2^e + // p2 <= 10^m * delta + delta *= 10; + dist *= 10; + if (p2 <= delta) + { + break; + } + } + + // V = buffer * 10^-m, with M- <= V <= M+. + + decimal_exponent -= m; + + // 1 ulp in the decimal representation is now 10^-m. + // Since delta and dist are now scaled by 10^m, we need to do the + // same with ulp in order to keep the units in sync. + // + // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e + // + const std::uint64_t ten_m = one.f; + grisu2_round(buffer, length, dist, delta, p2, ten_m); + + // By construction this algorithm generates the shortest possible decimal + // number (Loitsch, Theorem 6.2) which rounds back to w. + // For an input number of precision p, at least + // + // N = 1 + ceil(p * log_10(2)) + // + // decimal digits are sufficient to identify all binary floating-point + // numbers (Matula, "In-and-Out conversions"). + // This implies that the algorithm does not produce more than N decimal + // digits. + // + // N = 17 for p = 53 (IEEE double precision) + // N = 9 for p = 24 (IEEE single precision) +} + +/*! +v = buf * 10^decimal_exponent +len is the length of the buffer (number of decimal digits) +The buffer must be large enough, i.e. >= max_digits10. +*/ +inline void grisu2(char* buf, int& len, int& decimal_exponent, + diyfp m_minus, diyfp v, diyfp m_plus) +{ + assert(m_plus.e == m_minus.e); + assert(m_plus.e == v.e); + + // --------(-----------------------+-----------------------)-------- (A) + // m- v m+ + // + // --------------------(-----------+-----------------------)-------- (B) + // m- v m+ + // + // First scale v (and m- and m+) such that the exponent is in the range + // [alpha, gamma]. + + const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e); + + const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k + + // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma] + const diyfp w = diyfp::mul(v, c_minus_k); + const diyfp w_minus = diyfp::mul(m_minus, c_minus_k); + const diyfp w_plus = diyfp::mul(m_plus, c_minus_k); + + // ----(---+---)---------------(---+---)---------------(---+---)---- + // w- w w+ + // = c*m- = c*v = c*m+ + // + // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and + // w+ are now off by a small amount. + // In fact: + // + // w - v * 10^k < 1 ulp + // + // To account for this inaccuracy, add resp. subtract 1 ulp. + // + // --------+---[---------------(---+---)---------------]---+-------- + // w- M- w M+ w+ + // + // Now any number in [M-, M+] (bounds included) will round to w when input, + // regardless of how the input rounding algorithm breaks ties. + // + // And digit_gen generates the shortest possible such number in [M-, M+]. + // Note that this does not mean that Grisu2 always generates the shortest + // possible number in the interval (m-, m+). + const diyfp M_minus(w_minus.f + 1, w_minus.e); + const diyfp M_plus (w_plus.f - 1, w_plus.e ); + + decimal_exponent = -cached.k; // = -(-k) = k + + grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus); +} + +/*! +v = buf * 10^decimal_exponent +len is the length of the buffer (number of decimal digits) +The buffer must be large enough, i.e. >= max_digits10. +*/ +template +void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value) +{ + static_assert(diyfp::kPrecision >= std::numeric_limits::digits + 3, + "internal error: not enough precision"); + + assert(std::isfinite(value)); + assert(value > 0); + + // If the neighbors (and boundaries) of 'value' are always computed for double-precision + // numbers, all float's can be recovered using strtod (and strtof). However, the resulting + // decimal representations are not exactly "short". + // + // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars) + // says "value is converted to a string as if by std::sprintf in the default ("C") locale" + // and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars' + // does. + // On the other hand, the documentation for 'std::to_chars' requires that "parsing the + // representation using the corresponding std::from_chars function recovers value exactly". That + // indicates that single precision floating-point numbers should be recovered using + // 'std::strtof'. + // + // NB: If the neighbors are computed for single-precision numbers, there is a single float + // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision + // value is off by 1 ulp. +#if 0 + const boundaries w = compute_boundaries(static_cast(value)); +#else + const boundaries w = compute_boundaries(value); +#endif + + grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus); +} + +/*! +@brief appends a decimal representation of e to buf +@return a pointer to the element following the exponent. +@pre -1000 < e < 1000 +*/ +inline char* append_exponent(char* buf, int e) +{ + assert(e > -1000); + assert(e < 1000); + + if (e < 0) + { + e = -e; + *buf++ = '-'; + } + else + { + *buf++ = '+'; + } + + auto k = static_cast(e); + if (k < 10) + { + // Always print at least two digits in the exponent. + // This is for compatibility with printf("%g"). + *buf++ = '0'; + *buf++ = static_cast('0' + k); + } + else if (k < 100) + { + *buf++ = static_cast('0' + k / 10); + k %= 10; + *buf++ = static_cast('0' + k); + } + else + { + *buf++ = static_cast('0' + k / 100); + k %= 100; + *buf++ = static_cast('0' + k / 10); + k %= 10; + *buf++ = static_cast('0' + k); + } + + return buf; +} + +/*! +@brief prettify v = buf * 10^decimal_exponent + +If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point +notation. Otherwise it will be printed in exponential notation. + +@pre min_exp < 0 +@pre max_exp > 0 +*/ +inline char* format_buffer(char* buf, int len, int decimal_exponent, + int min_exp, int max_exp) +{ + assert(min_exp < 0); + assert(max_exp > 0); + + const int k = len; + const int n = len + decimal_exponent; + + // v = buf * 10^(n-k) + // k is the length of the buffer (number of decimal digits) + // n is the position of the decimal point relative to the start of the buffer. + + if (k <= n and n <= max_exp) + { + // digits[000] + // len <= max_exp + 2 + + std::memset(buf + k, '0', static_cast(n - k)); + // Make it look like a floating-point number (#362, #378) + buf[n + 0] = '.'; + buf[n + 1] = '0'; + return buf + (n + 2); + } + + if (0 < n and n <= max_exp) + { + // dig.its + // len <= max_digits10 + 1 + + assert(k > n); + + std::memmove(buf + (n + 1), buf + n, static_cast(k - n)); + buf[n] = '.'; + return buf + (k + 1); + } + + if (min_exp < n and n <= 0) + { + // 0.[000]digits + // len <= 2 + (-min_exp - 1) + max_digits10 + + std::memmove(buf + (2 + -n), buf, static_cast(k)); + buf[0] = '0'; + buf[1] = '.'; + std::memset(buf + 2, '0', static_cast(-n)); + return buf + (2 + (-n) + k); + } + + if (k == 1) + { + // dE+123 + // len <= 1 + 5 + + buf += 1; + } + else + { + // d.igitsE+123 + // len <= max_digits10 + 1 + 5 + + std::memmove(buf + 2, buf + 1, static_cast(k - 1)); + buf[1] = '.'; + buf += 1 + k; + } + + *buf++ = 'e'; + return append_exponent(buf, n - 1); +} + +} // namespace dtoa_impl + +/*! +@brief generates a decimal representation of the floating-point number value in [first, last). + +The format of the resulting decimal representation is similar to printf's %g +format. Returns an iterator pointing past-the-end of the decimal representation. + +@note The input number must be finite, i.e. NaN's and Inf's are not supported. +@note The buffer must be large enough. +@note The result is NOT null-terminated. +*/ +template +char* to_chars(char* first, const char* last, FloatType value) +{ + static_cast(last); // maybe unused - fix warning + assert(std::isfinite(value)); + + // Use signbit(value) instead of (value < 0) since signbit works for -0. + if (std::signbit(value)) + { + value = -value; + *first++ = '-'; + } + + if (value == 0) // +-0 + { + *first++ = '0'; + // Make it look like a floating-point number (#362, #378) + *first++ = '.'; + *first++ = '0'; + return first; + } + + assert(last - first >= std::numeric_limits::max_digits10); + + // Compute v = buffer * 10^decimal_exponent. + // The decimal digits are stored in the buffer, which needs to be interpreted + // as an unsigned decimal integer. + // len is the length of the buffer, i.e. the number of decimal digits. + int len = 0; + int decimal_exponent = 0; + dtoa_impl::grisu2(first, len, decimal_exponent, value); + + assert(len <= std::numeric_limits::max_digits10); + + // Format the buffer like printf("%.*g", prec, value) + constexpr int kMinExp = -4; + // Use digits10 here to increase compatibility with version 2. + constexpr int kMaxExp = std::numeric_limits::digits10; + + assert(last - first >= kMaxExp + 2); + assert(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits::max_digits10); + assert(last - first >= std::numeric_limits::max_digits10 + 6); + + return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp); +} + +} // namespace detail +} // namespace nlohmann diff --git a/nlohmann/detail/conversions/to_json.hpp b/nlohmann/detail/conversions/to_json.hpp new file mode 100644 index 0000000000..227d745526 --- /dev/null +++ b/nlohmann/detail/conversions/to_json.hpp @@ -0,0 +1,344 @@ +#pragma once + +#include // copy +#include // or, and, not +#include // begin, end +#include // string +#include // tuple, get +#include // is_same, is_constructible, is_floating_point, is_enum, underlying_type +#include // move, forward, declval, pair +#include // valarray +#include // vector + +#include +#include +#include +#include + +namespace nlohmann +{ +namespace detail +{ +////////////////// +// constructors // +////////////////// + +template struct external_constructor; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept + { + j.m_type = value_t::boolean; + j.m_value = b; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) + { + j.m_type = value_t::string; + j.m_value = s; + j.assert_invariant(); + } + + template + static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s) + { + j.m_type = value_t::string; + j.m_value = std::move(s); + j.assert_invariant(); + } + + template::value, + int> = 0> + static void construct(BasicJsonType& j, const CompatibleStringType& str) + { + j.m_type = value_t::string; + j.m_value.string = j.template create(str); + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept + { + j.m_type = value_t::number_float; + j.m_value = val; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept + { + j.m_type = value_t::number_unsigned; + j.m_value = val; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept + { + j.m_type = value_t::number_integer; + j.m_value = val; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) + { + j.m_type = value_t::array; + j.m_value = arr; + j.assert_invariant(); + } + + template + static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr) + { + j.m_type = value_t::array; + j.m_value = std::move(arr); + j.assert_invariant(); + } + + template::value, + int> = 0> + static void construct(BasicJsonType& j, const CompatibleArrayType& arr) + { + using std::begin; + using std::end; + j.m_type = value_t::array; + j.m_value.array = j.template create(begin(arr), end(arr)); + j.assert_invariant(); + } + + template + static void construct(BasicJsonType& j, const std::vector& arr) + { + j.m_type = value_t::array; + j.m_value = value_t::array; + j.m_value.array->reserve(arr.size()); + for (const bool x : arr) + { + j.m_value.array->push_back(x); + } + j.assert_invariant(); + } + + template::value, int> = 0> + static void construct(BasicJsonType& j, const std::valarray& arr) + { + j.m_type = value_t::array; + j.m_value = value_t::array; + j.m_value.array->resize(arr.size()); + std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin()); + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) + { + j.m_type = value_t::object; + j.m_value = obj; + j.assert_invariant(); + } + + template + static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj) + { + j.m_type = value_t::object; + j.m_value = std::move(obj); + j.assert_invariant(); + } + + template::value, int> = 0> + static void construct(BasicJsonType& j, const CompatibleObjectType& obj) + { + using std::begin; + using std::end; + + j.m_type = value_t::object; + j.m_value.object = j.template create(begin(obj), end(obj)); + j.assert_invariant(); + } +}; + +///////////// +// to_json // +///////////// + +template::value, int> = 0> +void to_json(BasicJsonType& j, T b) noexcept +{ + external_constructor::construct(j, b); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, const CompatibleString& s) +{ + external_constructor::construct(j, s); +} + +template +void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s) +{ + external_constructor::construct(j, std::move(s)); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, FloatType val) noexcept +{ + external_constructor::construct(j, static_cast(val)); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept +{ + external_constructor::construct(j, static_cast(val)); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept +{ + external_constructor::construct(j, static_cast(val)); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, EnumType e) noexcept +{ + using underlying_type = typename std::underlying_type::type; + external_constructor::construct(j, static_cast(e)); +} + +template +void to_json(BasicJsonType& j, const std::vector& e) +{ + external_constructor::construct(j, e); +} + +template ::value and + not is_compatible_object_type< + BasicJsonType, CompatibleArrayType>::value and + not is_compatible_string_type::value and + not is_basic_json::value, + int> = 0> +void to_json(BasicJsonType& j, const CompatibleArrayType& arr) +{ + external_constructor::construct(j, arr); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, const std::valarray& arr) +{ + external_constructor::construct(j, std::move(arr)); +} + +template +void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) +{ + external_constructor::construct(j, std::move(arr)); +} + +template::value and not is_basic_json::value, int> = 0> +void to_json(BasicJsonType& j, const CompatibleObjectType& obj) +{ + external_constructor::construct(j, obj); +} + +template +void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) +{ + external_constructor::construct(j, std::move(obj)); +} + +template < + typename BasicJsonType, typename T, std::size_t N, + enable_if_t::value, + int> = 0 > +void to_json(BasicJsonType& j, const T(&arr)[N]) +{ + external_constructor::construct(j, arr); +} + +template +void to_json(BasicJsonType& j, const std::pair& p) +{ + j = { p.first, p.second }; +} + +// for https://github.com/nlohmann/json/pull/1134 +template < typename BasicJsonType, typename T, + enable_if_t>::value, int> = 0> +void to_json(BasicJsonType& j, const T& b) +{ + j = { {b.key(), b.value()} }; +} + +template +void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence /*unused*/) +{ + j = { std::get(t)... }; +} + +template +void to_json(BasicJsonType& j, const std::tuple& t) +{ + to_json_tuple_impl(j, t, index_sequence_for {}); +} + +struct to_json_fn +{ + template + auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward(val)))) + -> decltype(to_json(j, std::forward(val)), void()) + { + return to_json(j, std::forward(val)); + } +}; +} // namespace detail + +/// namespace to hold default `to_json` function +namespace +{ +constexpr const auto& to_json = detail::static_const::value; +} // namespace +} // namespace nlohmann diff --git a/nlohmann/detail/exceptions.hpp b/nlohmann/detail/exceptions.hpp new file mode 100644 index 0000000000..519a597549 --- /dev/null +++ b/nlohmann/detail/exceptions.hpp @@ -0,0 +1,349 @@ +#pragma once + +#include // exception +#include // runtime_error +#include // to_string + +#include + +namespace nlohmann +{ +namespace detail +{ +//////////////// +// exceptions // +//////////////// + +/*! +@brief general exception of the @ref basic_json class + +This class is an extension of `std::exception` objects with a member @a id for +exception ids. It is used as the base class for all exceptions thrown by the +@ref basic_json class. This class can hence be used as "wildcard" to catch +exceptions. + +Subclasses: +- @ref parse_error for exceptions indicating a parse error +- @ref invalid_iterator for exceptions indicating errors with iterators +- @ref type_error for exceptions indicating executing a member function with + a wrong type +- @ref out_of_range for exceptions indicating access out of the defined range +- @ref other_error for exceptions indicating other library errors + +@internal +@note To have nothrow-copy-constructible exceptions, we internally use + `std::runtime_error` which can cope with arbitrary-length error messages. + Intermediate strings are built with static functions and then passed to + the actual constructor. +@endinternal + +@liveexample{The following code shows how arbitrary library exceptions can be +caught.,exception} + +@since version 3.0.0 +*/ +class exception : public std::exception +{ + public: + /// returns the explanatory string + const char* what() const noexcept override + { + return m.what(); + } + + /// the id of the exception + const int id; + + protected: + exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} + + static std::string name(const std::string& ename, int id_) + { + return "[json.exception." + ename + "." + std::to_string(id_) + "] "; + } + + private: + /// an exception object as storage for error messages + std::runtime_error m; +}; + +/*! +@brief exception indicating a parse error + +This exception is thrown by the library when a parse error occurs. Parse errors +can occur during the deserialization of JSON text, CBOR, MessagePack, as well +as when using JSON Patch. + +Member @a byte holds the byte index of the last read character in the input +file. + +Exceptions have ids 1xx. + +name / id | example message | description +------------------------------ | --------------- | ------------------------- +json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position. +json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point. +json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid. +json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects. +json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors. +json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`. +json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character. +json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences. +json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number. +json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read. +json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read. +json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read. +json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet). + +@note For an input with n bytes, 1 is the index of the first character and n+1 + is the index of the terminating null byte or the end of file. This also + holds true when reading a byte vector (CBOR or MessagePack). + +@liveexample{The following code shows how a `parse_error` exception can be +caught.,parse_error} + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref invalid_iterator for exceptions indicating errors with iterators +@sa - @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa - @ref out_of_range for exceptions indicating access out of the defined range +@sa - @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class parse_error : public exception +{ + public: + /*! + @brief create a parse error exception + @param[in] id_ the id of the exception + @param[in] pos the position where the error occurred (or with + chars_read_total=0 if the position cannot be + determined) + @param[in] what_arg the explanatory string + @return parse_error object + */ + static parse_error create(int id_, const position_t& pos, const std::string& what_arg) + { + std::string w = exception::name("parse_error", id_) + "parse error" + + position_string(pos) + ": " + what_arg; + return parse_error(id_, pos.chars_read_total, w.c_str()); + } + + static parse_error create(int id_, std::size_t byte_, const std::string& what_arg) + { + std::string w = exception::name("parse_error", id_) + "parse error" + + (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + + ": " + what_arg; + return parse_error(id_, byte_, w.c_str()); + } + + /*! + @brief byte index of the parse error + + The byte index of the last read character in the input file. + + @note For an input with n bytes, 1 is the index of the first character and + n+1 is the index of the terminating null byte or the end of file. + This also holds true when reading a byte vector (CBOR or MessagePack). + */ + const std::size_t byte; + + private: + parse_error(int id_, std::size_t byte_, const char* what_arg) + : exception(id_, what_arg), byte(byte_) {} + + static std::string position_string(const position_t& pos) + { + return " at line " + std::to_string(pos.lines_read + 1) + + ", column " + std::to_string(pos.chars_read_current_line); + } +}; + +/*! +@brief exception indicating errors with iterators + +This exception is thrown if iterators passed to a library function do not match +the expected semantics. + +Exceptions have ids 2xx. + +name / id | example message | description +----------------------------------- | --------------- | ------------------------- +json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. +json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion. +json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from. +json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid. +json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid. +json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range. +json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key. +json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. +json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. +json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. +json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to. +json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container. +json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered. +json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin(). + +@liveexample{The following code shows how an `invalid_iterator` exception can be +caught.,invalid_iterator} + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref parse_error for exceptions indicating a parse error +@sa - @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa - @ref out_of_range for exceptions indicating access out of the defined range +@sa - @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class invalid_iterator : public exception +{ + public: + static invalid_iterator create(int id_, const std::string& what_arg) + { + std::string w = exception::name("invalid_iterator", id_) + what_arg; + return invalid_iterator(id_, w.c_str()); + } + + private: + invalid_iterator(int id_, const char* what_arg) + : exception(id_, what_arg) {} +}; + +/*! +@brief exception indicating executing a member function with a wrong type + +This exception is thrown in case of a type error; that is, a library function is +executed on a JSON value whose type does not match the expected semantics. + +Exceptions have ids 3xx. + +name / id | example message | description +----------------------------- | --------------- | ------------------------- +json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead. +json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types. +json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t &. +json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types. +json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types. +json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types. +json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types. +json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types. +json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types. +json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types. +json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types. +json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types. +json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined. +json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers. +json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive. +json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. | +json.exception.type_error.317 | JSON value cannot be serialized to requested format | The dynamic type of the object cannot be represented in the requested serialization format (e.g. a raw `true` or `null` JSON object cannot be serialized to BSON) | + +@liveexample{The following code shows how a `type_error` exception can be +caught.,type_error} + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref parse_error for exceptions indicating a parse error +@sa - @ref invalid_iterator for exceptions indicating errors with iterators +@sa - @ref out_of_range for exceptions indicating access out of the defined range +@sa - @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class type_error : public exception +{ + public: + static type_error create(int id_, const std::string& what_arg) + { + std::string w = exception::name("type_error", id_) + what_arg; + return type_error(id_, w.c_str()); + } + + private: + type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; + +/*! +@brief exception indicating access out of the defined range + +This exception is thrown in case a library function is called on an input +parameter that exceeds the expected range, for instance in case of array +indices or nonexisting object keys. + +Exceptions have ids 4xx. + +name / id | example message | description +------------------------------- | --------------- | ------------------------- +json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1. +json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it. +json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object. +json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved. +json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value. +json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF. +json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. | +json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. | +json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string | + +@liveexample{The following code shows how an `out_of_range` exception can be +caught.,out_of_range} + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref parse_error for exceptions indicating a parse error +@sa - @ref invalid_iterator for exceptions indicating errors with iterators +@sa - @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa - @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class out_of_range : public exception +{ + public: + static out_of_range create(int id_, const std::string& what_arg) + { + std::string w = exception::name("out_of_range", id_) + what_arg; + return out_of_range(id_, w.c_str()); + } + + private: + out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; + +/*! +@brief exception indicating other library errors + +This exception is thrown in case of errors that cannot be classified with the +other exception types. + +Exceptions have ids 5xx. + +name / id | example message | description +------------------------------ | --------------- | ------------------------- +json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed. + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref parse_error for exceptions indicating a parse error +@sa - @ref invalid_iterator for exceptions indicating errors with iterators +@sa - @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa - @ref out_of_range for exceptions indicating access out of the defined range + +@liveexample{The following code shows how an `other_error` exception can be +caught.,other_error} + +@since version 3.0.0 +*/ +class other_error : public exception +{ + public: + static other_error create(int id_, const std::string& what_arg) + { + std::string w = exception::name("other_error", id_) + what_arg; + return other_error(id_, w.c_str()); + } + + private: + other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; +} // namespace detail +} // namespace nlohmann diff --git a/nlohmann/detail/input/binary_reader.hpp b/nlohmann/detail/input/binary_reader.hpp new file mode 100644 index 0000000000..42976d70f6 --- /dev/null +++ b/nlohmann/detail/input/binary_reader.hpp @@ -0,0 +1,1986 @@ +#pragma once + +#include // generate_n +#include // array +#include // assert +#include // ldexp +#include // size_t +#include // uint8_t, uint16_t, uint32_t, uint64_t +#include // snprintf +#include // memcpy +#include // back_inserter +#include // numeric_limits +#include // char_traits, string +#include // make_pair, move + +#include +#include +#include +#include +#include +#include + +namespace nlohmann +{ +namespace detail +{ +/////////////////// +// binary reader // +/////////////////// + +/*! +@brief deserialization of CBOR, MessagePack, and UBJSON values +*/ +template> +class binary_reader +{ + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using json_sax_t = SAX; + + public: + /*! + @brief create a binary reader + + @param[in] adapter input adapter to read from + */ + explicit binary_reader(input_adapter_t adapter) : ia(std::move(adapter)) + { + (void)detail::is_sax_static_asserts {}; + assert(ia); + } + + // make class move-only + binary_reader(const binary_reader&) = delete; + binary_reader(binary_reader&&) = default; + binary_reader& operator=(const binary_reader&) = delete; + binary_reader& operator=(binary_reader&&) = default; + ~binary_reader() = default; + + /*! + @param[in] format the binary format to parse + @param[in] sax_ a SAX event processor + @param[in] strict whether to expect the input to be consumed completed + + @return + */ + bool sax_parse(const input_format_t format, + json_sax_t* sax_, + const bool strict = true) + { + sax = sax_; + bool result = false; + + switch (format) + { + case input_format_t::bson: + result = parse_bson_internal(); + break; + + case input_format_t::cbor: + result = parse_cbor_internal(); + break; + + case input_format_t::msgpack: + result = parse_msgpack_internal(); + break; + + case input_format_t::ubjson: + result = parse_ubjson_internal(); + break; + + default: // LCOV_EXCL_LINE + assert(false); // LCOV_EXCL_LINE + } + + // strict mode: next byte must be EOF + if (result and strict) + { + if (format == input_format_t::ubjson) + { + get_ignore_noop(); + } + else + { + get(); + } + + if (JSON_UNLIKELY(current != std::char_traits::eof())) + { + return sax->parse_error(chars_read, get_token_string(), + parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value"))); + } + } + + return result; + } + + /*! + @brief determine system byte order + + @return true if and only if system's byte order is little endian + + @note from http://stackoverflow.com/a/1001328/266378 + */ + static constexpr bool little_endianess(int num = 1) noexcept + { + return *reinterpret_cast(&num) == 1; + } + + private: + ////////// + // BSON // + ////////// + + /*! + @brief Reads in a BSON-object and passes it to the SAX-parser. + @return whether a valid BSON-value was passed to the SAX parser + */ + bool parse_bson_internal() + { + std::int32_t document_size; + get_number(input_format_t::bson, document_size); + + if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1)))) + { + return false; + } + + if (JSON_UNLIKELY(not parse_bson_element_list(/*is_array*/false))) + { + return false; + } + + return sax->end_object(); + } + + /*! + @brief Parses a C-style string from the BSON input. + @param[in, out] result A reference to the string variable where the read + string is to be stored. + @return `true` if the \x00-byte indicating the end of the string was + encountered before the EOF; false` indicates an unexpected EOF. + */ + bool get_bson_cstr(string_t& result) + { + auto out = std::back_inserter(result); + while (true) + { + get(); + if (JSON_UNLIKELY(not unexpect_eof(input_format_t::bson, "cstring"))) + { + return false; + } + if (current == 0x00) + { + return true; + } + *out++ = static_cast(current); + } + + return true; + } + + /*! + @brief Parses a zero-terminated string of length @a len from the BSON + input. + @param[in] len The length (including the zero-byte at the end) of the + string to be read. + @param[in, out] result A reference to the string variable where the read + string is to be stored. + @tparam NumberType The type of the length @a len + @pre len >= 1 + @return `true` if the string was successfully parsed + */ + template + bool get_bson_string(const NumberType len, string_t& result) + { + if (JSON_UNLIKELY(len < 1)) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string"))); + } + + return get_string(input_format_t::bson, len - static_cast(1), result) and get() != std::char_traits::eof(); + } + + /*! + @brief Read a BSON document element of the given @a element_type. + @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html + @param[in] element_type_parse_position The position in the input stream, + where the `element_type` was read. + @warning Not all BSON element types are supported yet. An unsupported + @a element_type will give rise to a parse_error.114: + Unsupported BSON record type 0x... + @return whether a valid BSON-object/array was passed to the SAX parser + */ + bool parse_bson_element_internal(const int element_type, + const std::size_t element_type_parse_position) + { + switch (element_type) + { + case 0x01: // double + { + double number; + return get_number(input_format_t::bson, number) and sax->number_float(static_cast(number), ""); + } + + case 0x02: // string + { + std::int32_t len; + string_t value; + return get_number(input_format_t::bson, len) and get_bson_string(len, value) and sax->string(value); + } + + case 0x03: // object + { + return parse_bson_internal(); + } + + case 0x04: // array + { + return parse_bson_array(); + } + + case 0x08: // boolean + { + return sax->boolean(get() != 0); + } + + case 0x0A: // null + { + return sax->null(); + } + + case 0x10: // int32 + { + std::int32_t value; + return get_number(input_format_t::bson, value) and sax->number_integer(value); + } + + case 0x12: // int64 + { + std::int64_t value; + return get_number(input_format_t::bson, value) and sax->number_integer(value); + } + + default: // anything else not supported (yet) + { + std::array cr{{}}; + (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast(element_type)); + return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data()))); + } + } + } + + /*! + @brief Read a BSON element list (as specified in the BSON-spec) + + The same binary layout is used for objects and arrays, hence it must be + indicated with the argument @a is_array which one is expected + (true --> array, false --> object). + + @param[in] is_array Determines if the element list being read is to be + treated as an object (@a is_array == false), or as an + array (@a is_array == true). + @return whether a valid BSON-object/array was passed to the SAX parser + */ + bool parse_bson_element_list(const bool is_array) + { + string_t key; + while (int element_type = get()) + { + if (JSON_UNLIKELY(not unexpect_eof(input_format_t::bson, "element list"))) + { + return false; + } + + const std::size_t element_type_parse_position = chars_read; + if (JSON_UNLIKELY(not get_bson_cstr(key))) + { + return false; + } + + if (not is_array and not sax->key(key)) + { + return false; + } + + if (JSON_UNLIKELY(not parse_bson_element_internal(element_type, element_type_parse_position))) + { + return false; + } + + // get_bson_cstr only appends + key.clear(); + } + + return true; + } + + /*! + @brief Reads an array from the BSON input and passes it to the SAX-parser. + @return whether a valid BSON-array was passed to the SAX parser + */ + bool parse_bson_array() + { + std::int32_t document_size; + get_number(input_format_t::bson, document_size); + + if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1)))) + { + return false; + } + + if (JSON_UNLIKELY(not parse_bson_element_list(/*is_array*/true))) + { + return false; + } + + return sax->end_array(); + } + + ////////// + // CBOR // + ////////// + + /*! + @param[in] get_char whether a new character should be retrieved from the + input (true, default) or whether the last read + character should be considered instead + + @return whether a valid CBOR value was passed to the SAX parser + */ + bool parse_cbor_internal(const bool get_char = true) + { + switch (get_char ? get() : current) + { + // EOF + case std::char_traits::eof(): + return unexpect_eof(input_format_t::cbor, "value"); + + // Integer 0x00..0x17 (0..23) + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + return sax->number_unsigned(static_cast(current)); + + case 0x18: // Unsigned integer (one-byte uint8_t follows) + { + std::uint8_t number; + return get_number(input_format_t::cbor, number) and sax->number_unsigned(number); + } + + case 0x19: // Unsigned integer (two-byte uint16_t follows) + { + std::uint16_t number; + return get_number(input_format_t::cbor, number) and sax->number_unsigned(number); + } + + case 0x1A: // Unsigned integer (four-byte uint32_t follows) + { + std::uint32_t number; + return get_number(input_format_t::cbor, number) and sax->number_unsigned(number); + } + + case 0x1B: // Unsigned integer (eight-byte uint64_t follows) + { + std::uint64_t number; + return get_number(input_format_t::cbor, number) and sax->number_unsigned(number); + } + + // Negative integer -1-0x00..-1-0x17 (-1..-24) + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + return sax->number_integer(static_cast(0x20 - 1 - current)); + + case 0x38: // Negative integer (one-byte uint8_t follows) + { + std::uint8_t number; + return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast(-1) - number); + } + + case 0x39: // Negative integer -1-n (two-byte uint16_t follows) + { + std::uint16_t number; + return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast(-1) - number); + } + + case 0x3A: // Negative integer -1-n (four-byte uint32_t follows) + { + std::uint32_t number; + return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast(-1) - number); + } + + case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows) + { + std::uint64_t number; + return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast(-1) + - static_cast(number)); + } + + // UTF-8 string (0x00..0x17 bytes follow) + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: // UTF-8 string (one-byte uint8_t for n follows) + case 0x79: // UTF-8 string (two-byte uint16_t for n follow) + case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) + case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) + case 0x7F: // UTF-8 string (indefinite length) + { + string_t s; + return get_cbor_string(s) and sax->string(s); + } + + // array (0x00..0x17 data items follow) + case 0x80: + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + case 0x86: + case 0x87: + case 0x88: + case 0x89: + case 0x8A: + case 0x8B: + case 0x8C: + case 0x8D: + case 0x8E: + case 0x8F: + case 0x90: + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + return get_cbor_array(static_cast(static_cast(current) & 0x1Fu)); + + case 0x98: // array (one-byte uint8_t for n follows) + { + std::uint8_t len; + return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast(len)); + } + + case 0x99: // array (two-byte uint16_t for n follow) + { + std::uint16_t len; + return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast(len)); + } + + case 0x9A: // array (four-byte uint32_t for n follow) + { + std::uint32_t len; + return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast(len)); + } + + case 0x9B: // array (eight-byte uint64_t for n follow) + { + std::uint64_t len; + return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast(len)); + } + + case 0x9F: // array (indefinite length) + return get_cbor_array(std::size_t(-1)); + + // map (0x00..0x17 pairs of data items follow) + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + return get_cbor_object(static_cast(static_cast(current) & 0x1Fu)); + + case 0xB8: // map (one-byte uint8_t for n follows) + { + std::uint8_t len; + return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast(len)); + } + + case 0xB9: // map (two-byte uint16_t for n follow) + { + std::uint16_t len; + return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast(len)); + } + + case 0xBA: // map (four-byte uint32_t for n follow) + { + std::uint32_t len; + return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast(len)); + } + + case 0xBB: // map (eight-byte uint64_t for n follow) + { + std::uint64_t len; + return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast(len)); + } + + case 0xBF: // map (indefinite length) + return get_cbor_object(std::size_t(-1)); + + case 0xF4: // false + return sax->boolean(false); + + case 0xF5: // true + return sax->boolean(true); + + case 0xF6: // null + return sax->null(); + + case 0xF9: // Half-Precision Float (two-byte IEEE 754) + { + const int byte1_raw = get(); + if (JSON_UNLIKELY(not unexpect_eof(input_format_t::cbor, "number"))) + { + return false; + } + const int byte2_raw = get(); + if (JSON_UNLIKELY(not unexpect_eof(input_format_t::cbor, "number"))) + { + return false; + } + + const auto byte1 = static_cast(byte1_raw); + const auto byte2 = static_cast(byte2_raw); + + // code from RFC 7049, Appendix D, Figure 3: + // As half-precision floating-point numbers were only added + // to IEEE 754 in 2008, today's programming platforms often + // still only have limited support for them. It is very + // easy to include at least decoding support for them even + // without such support. An example of a small decoder for + // half-precision floating-point numbers in the C language + // is shown in Fig. 3. + const auto half = static_cast((byte1 << 8u) + byte2); + const double val = [&half] + { + const int exp = (half >> 10u) & 0x1Fu; + const unsigned int mant = half & 0x3FFu; + assert(0 <= exp and exp <= 32); + assert(0 <= mant and mant <= 1024); + switch (exp) + { + case 0: + return std::ldexp(mant, -24); + case 31: + return (mant == 0) + ? std::numeric_limits::infinity() + : std::numeric_limits::quiet_NaN(); + default: + return std::ldexp(mant + 1024, exp - 25); + } + }(); + return sax->number_float((half & 0x8000u) != 0 + ? static_cast(-val) + : static_cast(val), ""); + } + + case 0xFA: // Single-Precision Float (four-byte IEEE 754) + { + float number; + return get_number(input_format_t::cbor, number) and sax->number_float(static_cast(number), ""); + } + + case 0xFB: // Double-Precision Float (eight-byte IEEE 754) + { + double number; + return get_number(input_format_t::cbor, number) and sax->number_float(static_cast(number), ""); + } + + default: // anything else (0xFF is handled inside the other types) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"))); + } + } + } + + /*! + @brief reads a CBOR string + + This function first reads starting bytes to determine the expected + string length and then copies this number of bytes into a string. + Additionally, CBOR's strings with indefinite lengths are supported. + + @param[out] result created string + + @return whether string creation completed + */ + bool get_cbor_string(string_t& result) + { + if (JSON_UNLIKELY(not unexpect_eof(input_format_t::cbor, "string"))) + { + return false; + } + + switch (current) + { + // UTF-8 string (0x00..0x17 bytes follow) + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + { + return get_string(input_format_t::cbor, static_cast(current) & 0x1Fu, result); + } + + case 0x78: // UTF-8 string (one-byte uint8_t for n follows) + { + std::uint8_t len; + return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result); + } + + case 0x79: // UTF-8 string (two-byte uint16_t for n follow) + { + std::uint16_t len; + return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result); + } + + case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) + { + std::uint32_t len; + return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result); + } + + case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) + { + std::uint64_t len; + return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result); + } + + case 0x7F: // UTF-8 string (indefinite length) + { + while (get() != 0xFF) + { + string_t chunk; + if (not get_cbor_string(chunk)) + { + return false; + } + result.append(chunk); + } + return true; + } + + default: + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string"))); + } + } + } + + /*! + @param[in] len the length of the array or std::size_t(-1) for an + array of indefinite size + @return whether array creation completed + */ + bool get_cbor_array(const std::size_t len) + { + if (JSON_UNLIKELY(not sax->start_array(len))) + { + return false; + } + + if (len != std::size_t(-1)) + { + for (std::size_t i = 0; i < len; ++i) + { + if (JSON_UNLIKELY(not parse_cbor_internal())) + { + return false; + } + } + } + else + { + while (get() != 0xFF) + { + if (JSON_UNLIKELY(not parse_cbor_internal(false))) + { + return false; + } + } + } + + return sax->end_array(); + } + + /*! + @param[in] len the length of the object or std::size_t(-1) for an + object of indefinite size + @return whether object creation completed + */ + bool get_cbor_object(const std::size_t len) + { + if (JSON_UNLIKELY(not sax->start_object(len))) + { + return false; + } + + string_t key; + if (len != std::size_t(-1)) + { + for (std::size_t i = 0; i < len; ++i) + { + get(); + if (JSON_UNLIKELY(not get_cbor_string(key) or not sax->key(key))) + { + return false; + } + + if (JSON_UNLIKELY(not parse_cbor_internal())) + { + return false; + } + key.clear(); + } + } + else + { + while (get() != 0xFF) + { + if (JSON_UNLIKELY(not get_cbor_string(key) or not sax->key(key))) + { + return false; + } + + if (JSON_UNLIKELY(not parse_cbor_internal())) + { + return false; + } + key.clear(); + } + } + + return sax->end_object(); + } + + ///////////// + // MsgPack // + ///////////// + + /*! + @return whether a valid MessagePack value was passed to the SAX parser + */ + bool parse_msgpack_internal() + { + switch (get()) + { + // EOF + case std::char_traits::eof(): + return unexpect_eof(input_format_t::msgpack, "value"); + + // positive fixint + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x18: + case 0x19: + case 0x1A: + case 0x1B: + case 0x1C: + case 0x1D: + case 0x1E: + case 0x1F: + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3A: + case 0x3B: + case 0x3C: + case 0x3D: + case 0x3E: + case 0x3F: + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: + case 0x59: + case 0x5A: + case 0x5B: + case 0x5C: + case 0x5D: + case 0x5E: + case 0x5F: + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: + case 0x79: + case 0x7A: + case 0x7B: + case 0x7C: + case 0x7D: + case 0x7E: + case 0x7F: + return sax->number_unsigned(static_cast(current)); + + // fixmap + case 0x80: + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + case 0x86: + case 0x87: + case 0x88: + case 0x89: + case 0x8A: + case 0x8B: + case 0x8C: + case 0x8D: + case 0x8E: + case 0x8F: + return get_msgpack_object(static_cast(static_cast(current) & 0x0Fu)); + + // fixarray + case 0x90: + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + case 0x98: + case 0x99: + case 0x9A: + case 0x9B: + case 0x9C: + case 0x9D: + case 0x9E: + case 0x9F: + return get_msgpack_array(static_cast(static_cast(current) & 0x0Fu)); + + // fixstr + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: + { + string_t s; + return get_msgpack_string(s) and sax->string(s); + } + + case 0xC0: // nil + return sax->null(); + + case 0xC2: // false + return sax->boolean(false); + + case 0xC3: // true + return sax->boolean(true); + + case 0xCA: // float 32 + { + float number; + return get_number(input_format_t::msgpack, number) and sax->number_float(static_cast(number), ""); + } + + case 0xCB: // float 64 + { + double number; + return get_number(input_format_t::msgpack, number) and sax->number_float(static_cast(number), ""); + } + + case 0xCC: // uint 8 + { + std::uint8_t number; + return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number); + } + + case 0xCD: // uint 16 + { + std::uint16_t number; + return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number); + } + + case 0xCE: // uint 32 + { + std::uint32_t number; + return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number); + } + + case 0xCF: // uint 64 + { + std::uint64_t number; + return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number); + } + + case 0xD0: // int 8 + { + std::int8_t number; + return get_number(input_format_t::msgpack, number) and sax->number_integer(number); + } + + case 0xD1: // int 16 + { + std::int16_t number; + return get_number(input_format_t::msgpack, number) and sax->number_integer(number); + } + + case 0xD2: // int 32 + { + std::int32_t number; + return get_number(input_format_t::msgpack, number) and sax->number_integer(number); + } + + case 0xD3: // int 64 + { + std::int64_t number; + return get_number(input_format_t::msgpack, number) and sax->number_integer(number); + } + + case 0xD9: // str 8 + case 0xDA: // str 16 + case 0xDB: // str 32 + { + string_t s; + return get_msgpack_string(s) and sax->string(s); + } + + case 0xDC: // array 16 + { + std::uint16_t len; + return get_number(input_format_t::msgpack, len) and get_msgpack_array(static_cast(len)); + } + + case 0xDD: // array 32 + { + std::uint32_t len; + return get_number(input_format_t::msgpack, len) and get_msgpack_array(static_cast(len)); + } + + case 0xDE: // map 16 + { + std::uint16_t len; + return get_number(input_format_t::msgpack, len) and get_msgpack_object(static_cast(len)); + } + + case 0xDF: // map 32 + { + std::uint32_t len; + return get_number(input_format_t::msgpack, len) and get_msgpack_object(static_cast(len)); + } + + // negative fixint + case 0xE0: + case 0xE1: + case 0xE2: + case 0xE3: + case 0xE4: + case 0xE5: + case 0xE6: + case 0xE7: + case 0xE8: + case 0xE9: + case 0xEA: + case 0xEB: + case 0xEC: + case 0xED: + case 0xEE: + case 0xEF: + case 0xF0: + case 0xF1: + case 0xF2: + case 0xF3: + case 0xF4: + case 0xF5: + case 0xF6: + case 0xF7: + case 0xF8: + case 0xF9: + case 0xFA: + case 0xFB: + case 0xFC: + case 0xFD: + case 0xFE: + case 0xFF: + return sax->number_integer(static_cast(current)); + + default: // anything else + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value"))); + } + } + } + + /*! + @brief reads a MessagePack string + + This function first reads starting bytes to determine the expected + string length and then copies this number of bytes into a string. + + @param[out] result created string + + @return whether string creation completed + */ + bool get_msgpack_string(string_t& result) + { + if (JSON_UNLIKELY(not unexpect_eof(input_format_t::msgpack, "string"))) + { + return false; + } + + switch (current) + { + // fixstr + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: + { + return get_string(input_format_t::msgpack, static_cast(current) & 0x1Fu, result); + } + + case 0xD9: // str 8 + { + std::uint8_t len; + return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result); + } + + case 0xDA: // str 16 + { + std::uint16_t len; + return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result); + } + + case 0xDB: // str 32 + { + std::uint32_t len; + return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result); + } + + default: + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string"))); + } + } + } + + /*! + @param[in] len the length of the array + @return whether array creation completed + */ + bool get_msgpack_array(const std::size_t len) + { + if (JSON_UNLIKELY(not sax->start_array(len))) + { + return false; + } + + for (std::size_t i = 0; i < len; ++i) + { + if (JSON_UNLIKELY(not parse_msgpack_internal())) + { + return false; + } + } + + return sax->end_array(); + } + + /*! + @param[in] len the length of the object + @return whether object creation completed + */ + bool get_msgpack_object(const std::size_t len) + { + if (JSON_UNLIKELY(not sax->start_object(len))) + { + return false; + } + + string_t key; + for (std::size_t i = 0; i < len; ++i) + { + get(); + if (JSON_UNLIKELY(not get_msgpack_string(key) or not sax->key(key))) + { + return false; + } + + if (JSON_UNLIKELY(not parse_msgpack_internal())) + { + return false; + } + key.clear(); + } + + return sax->end_object(); + } + + //////////// + // UBJSON // + //////////// + + /*! + @param[in] get_char whether a new character should be retrieved from the + input (true, default) or whether the last read + character should be considered instead + + @return whether a valid UBJSON value was passed to the SAX parser + */ + bool parse_ubjson_internal(const bool get_char = true) + { + return get_ubjson_value(get_char ? get_ignore_noop() : current); + } + + /*! + @brief reads a UBJSON string + + This function is either called after reading the 'S' byte explicitly + indicating a string, or in case of an object key where the 'S' byte can be + left out. + + @param[out] result created string + @param[in] get_char whether a new character should be retrieved from the + input (true, default) or whether the last read + character should be considered instead + + @return whether string creation completed + */ + bool get_ubjson_string(string_t& result, const bool get_char = true) + { + if (get_char) + { + get(); // TODO(niels): may we ignore N here? + } + + if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "value"))) + { + return false; + } + + switch (current) + { + case 'U': + { + std::uint8_t len; + return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result); + } + + case 'i': + { + std::int8_t len; + return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result); + } + + case 'I': + { + std::int16_t len; + return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result); + } + + case 'l': + { + std::int32_t len; + return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result); + } + + case 'L': + { + std::int64_t len; + return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result); + } + + default: + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string"))); + } + } + + /*! + @param[out] result determined size + @return whether size determination completed + */ + bool get_ubjson_size_value(std::size_t& result) + { + switch (get_ignore_noop()) + { + case 'U': + { + std::uint8_t number; + if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number))) + { + return false; + } + result = static_cast(number); + return true; + } + + case 'i': + { + std::int8_t number; + if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number))) + { + return false; + } + result = static_cast(number); + return true; + } + + case 'I': + { + std::int16_t number; + if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number))) + { + return false; + } + result = static_cast(number); + return true; + } + + case 'l': + { + std::int32_t number; + if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number))) + { + return false; + } + result = static_cast(number); + return true; + } + + case 'L': + { + std::int64_t number; + if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number))) + { + return false; + } + result = static_cast(number); + return true; + } + + default: + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size"))); + } + } + } + + /*! + @brief determine the type and size for a container + + In the optimized UBJSON format, a type and a size can be provided to allow + for a more compact representation. + + @param[out] result pair of the size and the type + + @return whether pair creation completed + */ + bool get_ubjson_size_type(std::pair& result) + { + result.first = string_t::npos; // size + result.second = 0; // type + + get_ignore_noop(); + + if (current == '$') + { + result.second = get(); // must not ignore 'N', because 'N' maybe the type + if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "type"))) + { + return false; + } + + get_ignore_noop(); + if (JSON_UNLIKELY(current != '#')) + { + if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "value"))) + { + return false; + } + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size"))); + } + + return get_ubjson_size_value(result.first); + } + + if (current == '#') + { + return get_ubjson_size_value(result.first); + } + + return true; + } + + /*! + @param prefix the previously read or set type prefix + @return whether value creation completed + */ + bool get_ubjson_value(const int prefix) + { + switch (prefix) + { + case std::char_traits::eof(): // EOF + return unexpect_eof(input_format_t::ubjson, "value"); + + case 'T': // true + return sax->boolean(true); + case 'F': // false + return sax->boolean(false); + + case 'Z': // null + return sax->null(); + + case 'U': + { + std::uint8_t number; + return get_number(input_format_t::ubjson, number) and sax->number_unsigned(number); + } + + case 'i': + { + std::int8_t number; + return get_number(input_format_t::ubjson, number) and sax->number_integer(number); + } + + case 'I': + { + std::int16_t number; + return get_number(input_format_t::ubjson, number) and sax->number_integer(number); + } + + case 'l': + { + std::int32_t number; + return get_number(input_format_t::ubjson, number) and sax->number_integer(number); + } + + case 'L': + { + std::int64_t number; + return get_number(input_format_t::ubjson, number) and sax->number_integer(number); + } + + case 'd': + { + float number; + return get_number(input_format_t::ubjson, number) and sax->number_float(static_cast(number), ""); + } + + case 'D': + { + double number; + return get_number(input_format_t::ubjson, number) and sax->number_float(static_cast(number), ""); + } + + case 'C': // char + { + get(); + if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "char"))) + { + return false; + } + if (JSON_UNLIKELY(current > 127)) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char"))); + } + string_t s(1, static_cast(current)); + return sax->string(s); + } + + case 'S': // string + { + string_t s; + return get_ubjson_string(s) and sax->string(s); + } + + case '[': // array + return get_ubjson_array(); + + case '{': // object + return get_ubjson_object(); + + default: // anything else + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value"))); + } + } + } + + /*! + @return whether array creation completed + */ + bool get_ubjson_array() + { + std::pair size_and_type; + if (JSON_UNLIKELY(not get_ubjson_size_type(size_and_type))) + { + return false; + } + + if (size_and_type.first != string_t::npos) + { + if (JSON_UNLIKELY(not sax->start_array(size_and_type.first))) + { + return false; + } + + if (size_and_type.second != 0) + { + if (size_and_type.second != 'N') + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_UNLIKELY(not get_ubjson_value(size_and_type.second))) + { + return false; + } + } + } + } + else + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_UNLIKELY(not parse_ubjson_internal())) + { + return false; + } + } + } + } + else + { + if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1)))) + { + return false; + } + + while (current != ']') + { + if (JSON_UNLIKELY(not parse_ubjson_internal(false))) + { + return false; + } + get_ignore_noop(); + } + } + + return sax->end_array(); + } + + /*! + @return whether object creation completed + */ + bool get_ubjson_object() + { + std::pair size_and_type; + if (JSON_UNLIKELY(not get_ubjson_size_type(size_and_type))) + { + return false; + } + + string_t key; + if (size_and_type.first != string_t::npos) + { + if (JSON_UNLIKELY(not sax->start_object(size_and_type.first))) + { + return false; + } + + if (size_and_type.second != 0) + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_UNLIKELY(not get_ubjson_string(key) or not sax->key(key))) + { + return false; + } + if (JSON_UNLIKELY(not get_ubjson_value(size_and_type.second))) + { + return false; + } + key.clear(); + } + } + else + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_UNLIKELY(not get_ubjson_string(key) or not sax->key(key))) + { + return false; + } + if (JSON_UNLIKELY(not parse_ubjson_internal())) + { + return false; + } + key.clear(); + } + } + } + else + { + if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1)))) + { + return false; + } + + while (current != '}') + { + if (JSON_UNLIKELY(not get_ubjson_string(key, false) or not sax->key(key))) + { + return false; + } + if (JSON_UNLIKELY(not parse_ubjson_internal())) + { + return false; + } + get_ignore_noop(); + key.clear(); + } + } + + return sax->end_object(); + } + + /////////////////////// + // Utility functions // + /////////////////////// + + /*! + @brief get next character from the input + + This function provides the interface to the used input adapter. It does + not throw in case the input reached EOF, but returns a -'ve valued + `std::char_traits::eof()` in that case. + + @return character read from the input + */ + int get() + { + ++chars_read; + return current = ia->get_character(); + } + + /*! + @return character read from the input after ignoring all 'N' entries + */ + int get_ignore_noop() + { + do + { + get(); + } + while (current == 'N'); + + return current; + } + + /* + @brief read a number from the input + + @tparam NumberType the type of the number + @param[in] format the current format (for diagnostics) + @param[out] result number of type @a NumberType + + @return whether conversion completed + + @note This function needs to respect the system's endianess, because + bytes in CBOR, MessagePack, and UBJSON are stored in network order + (big endian) and therefore need reordering on little endian systems. + */ + template + bool get_number(const input_format_t format, NumberType& result) + { + // step 1: read input into array with system's byte order + std::array vec; + for (std::size_t i = 0; i < sizeof(NumberType); ++i) + { + get(); + if (JSON_UNLIKELY(not unexpect_eof(format, "number"))) + { + return false; + } + + // reverse byte order prior to conversion if necessary + if (is_little_endian != InputIsLittleEndian) + { + vec[sizeof(NumberType) - i - 1] = static_cast(current); + } + else + { + vec[i] = static_cast(current); // LCOV_EXCL_LINE + } + } + + // step 2: convert array into number of type T and return + std::memcpy(&result, vec.data(), sizeof(NumberType)); + return true; + } + + /*! + @brief create a string by reading characters from the input + + @tparam NumberType the type of the number + @param[in] format the current format (for diagnostics) + @param[in] len number of characters to read + @param[out] result string created by reading @a len bytes + + @return whether string creation completed + + @note We can not reserve @a len bytes for the result, because @a len + may be too large. Usually, @ref unexpect_eof() detects the end of + the input before we run out of string memory. + */ + template + bool get_string(const input_format_t format, + const NumberType len, + string_t& result) + { + bool success = true; + std::generate_n(std::back_inserter(result), len, [this, &success, &format]() + { + get(); + if (JSON_UNLIKELY(not unexpect_eof(format, "string"))) + { + success = false; + } + return static_cast(current); + }); + return success; + } + + /*! + @param[in] format the current format (for diagnostics) + @param[in] context further context information (for diagnostics) + @return whether the last read character is not EOF + */ + bool unexpect_eof(const input_format_t format, const char* context) const + { + if (JSON_UNLIKELY(current == std::char_traits::eof())) + { + return sax->parse_error(chars_read, "", + parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context))); + } + return true; + } + + /*! + @return a string representation of the last read byte + */ + std::string get_token_string() const + { + std::array cr{{}}; + (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast(current)); + return std::string{cr.data()}; + } + + /*! + @param[in] format the current format + @param[in] detail a detailed error message + @param[in] context further contect information + @return a message string to use in the parse_error exceptions + */ + std::string exception_message(const input_format_t format, + const std::string& detail, + const std::string& context) const + { + std::string error_msg = "syntax error while parsing "; + + switch (format) + { + case input_format_t::cbor: + error_msg += "CBOR"; + break; + + case input_format_t::msgpack: + error_msg += "MessagePack"; + break; + + case input_format_t::ubjson: + error_msg += "UBJSON"; + break; + + case input_format_t::bson: + error_msg += "BSON"; + break; + + default: // LCOV_EXCL_LINE + assert(false); // LCOV_EXCL_LINE + } + + return error_msg + " " + context + ": " + detail; + } + + private: + /// input adapter + input_adapter_t ia = nullptr; + + /// the current character + int current = std::char_traits::eof(); + + /// the number of characters read + std::size_t chars_read = 0; + + /// whether we can assume little endianess + const bool is_little_endian = little_endianess(); + + /// the SAX parser + json_sax_t* sax = nullptr; +}; +} // namespace detail +} // namespace nlohmann diff --git a/nlohmann/detail/input/input_adapters.hpp b/nlohmann/detail/input/input_adapters.hpp new file mode 100644 index 0000000000..5d9e200e38 --- /dev/null +++ b/nlohmann/detail/input/input_adapters.hpp @@ -0,0 +1,439 @@ +#pragma once + +#include // array +#include // assert +#include // size_t +#include //FILE * +#include // strlen +#include // istream +#include // begin, end, iterator_traits, random_access_iterator_tag, distance, next +#include // shared_ptr, make_shared, addressof +#include // accumulate +#include // string, char_traits +#include // enable_if, is_base_of, is_pointer, is_integral, remove_pointer +#include // pair, declval + +#include +#include + +namespace nlohmann +{ +namespace detail +{ +/// the supported input formats +enum class input_format_t { json, cbor, msgpack, ubjson, bson }; + +//////////////////// +// input adapters // +//////////////////// + +/*! +@brief abstract input adapter interface + +Produces a stream of std::char_traits::int_type characters from a +std::istream, a buffer, or some other input type. Accepts the return of +exactly one non-EOF character for future input. The int_type characters +returned consist of all valid char values as positive values (typically +unsigned char), plus an EOF value outside that range, specified by the value +of the function std::char_traits::eof(). This value is typically -1, but +could be any arbitrary value which is not a valid char value. +*/ +struct input_adapter_protocol +{ + /// get a character [0,255] or std::char_traits::eof(). + virtual std::char_traits::int_type get_character() = 0; + virtual ~input_adapter_protocol() = default; +}; + +/// a type to simplify interfaces +using input_adapter_t = std::shared_ptr; + +/*! +Input adapter for stdio file access. This adapter read only 1 byte and do not use any + buffer. This adapter is a very low level adapter. +*/ +class file_input_adapter : public input_adapter_protocol +{ + public: + explicit file_input_adapter(std::FILE* f) noexcept + : m_file(f) + {} + + // make class move-only + file_input_adapter(const file_input_adapter&) = delete; + file_input_adapter(file_input_adapter&&) = default; + file_input_adapter& operator=(const file_input_adapter&) = delete; + file_input_adapter& operator=(file_input_adapter&&) = default; + ~file_input_adapter() override = default; + + std::char_traits::int_type get_character() noexcept override + { + return std::fgetc(m_file); + } + + private: + /// the file pointer to read from + std::FILE* m_file; +}; + + +/*! +Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at +beginning of input. Does not support changing the underlying std::streambuf +in mid-input. Maintains underlying std::istream and std::streambuf to support +subsequent use of standard std::istream operations to process any input +characters following those used in parsing the JSON input. Clears the +std::istream flags; any input errors (e.g., EOF) will be detected by the first +subsequent call for input from the std::istream. +*/ +class input_stream_adapter : public input_adapter_protocol +{ + public: + ~input_stream_adapter() override + { + // clear stream flags; we use underlying streambuf I/O, do not + // maintain ifstream flags, except eof + is.clear(is.rdstate() & std::ios::eofbit); + } + + explicit input_stream_adapter(std::istream& i) + : is(i), sb(*i.rdbuf()) + {} + + // delete because of pointer members + input_stream_adapter(const input_stream_adapter&) = delete; + input_stream_adapter& operator=(input_stream_adapter&) = delete; + input_stream_adapter(input_stream_adapter&&) = delete; + input_stream_adapter& operator=(input_stream_adapter&&) = delete; + + // std::istream/std::streambuf use std::char_traits::to_int_type, to + // ensure that std::char_traits::eof() and the character 0xFF do not + // end up as the same value, eg. 0xFFFFFFFF. + std::char_traits::int_type get_character() override + { + auto res = sb.sbumpc(); + // set eof manually, as we don't use the istream interface. + if (res == EOF) + { + is.clear(is.rdstate() | std::ios::eofbit); + } + return res; + } + + private: + /// the associated input stream + std::istream& is; + std::streambuf& sb; +}; + +/// input adapter for buffer input +class input_buffer_adapter : public input_adapter_protocol +{ + public: + input_buffer_adapter(const char* b, const std::size_t l) noexcept + : cursor(b), limit(b + l) + {} + + // delete because of pointer members + input_buffer_adapter(const input_buffer_adapter&) = delete; + input_buffer_adapter& operator=(input_buffer_adapter&) = delete; + input_buffer_adapter(input_buffer_adapter&&) = delete; + input_buffer_adapter& operator=(input_buffer_adapter&&) = delete; + ~input_buffer_adapter() override = default; + + std::char_traits::int_type get_character() noexcept override + { + if (JSON_LIKELY(cursor < limit)) + { + return std::char_traits::to_int_type(*(cursor++)); + } + + return std::char_traits::eof(); + } + + private: + /// pointer to the current character + const char* cursor; + /// pointer past the last character + const char* const limit; +}; + +template +struct wide_string_input_helper +{ + // UTF-32 + static void fill_buffer(const WideStringType& str, + size_t& current_wchar, + std::array::int_type, 4>& utf8_bytes, + size_t& utf8_bytes_index, + size_t& utf8_bytes_filled) + { + utf8_bytes_index = 0; + + if (current_wchar == str.size()) + { + utf8_bytes[0] = std::char_traits::eof(); + utf8_bytes_filled = 1; + } + else + { + // get the current character + const auto wc = static_cast(str[current_wchar++]); + + // UTF-32 to UTF-8 encoding + if (wc < 0x80) + { + utf8_bytes[0] = static_cast::int_type>(wc); + utf8_bytes_filled = 1; + } + else if (wc <= 0x7FF) + { + utf8_bytes[0] = static_cast::int_type>(0xC0u | ((wc >> 6u) & 0x1Fu)); + utf8_bytes[1] = static_cast::int_type>(0x80u | (wc & 0x3Fu)); + utf8_bytes_filled = 2; + } + else if (wc <= 0xFFFF) + { + utf8_bytes[0] = static_cast::int_type>(0xE0u | ((wc >> 12u) & 0x0Fu)); + utf8_bytes[1] = static_cast::int_type>(0x80u | ((wc >> 6u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>(0x80u | (wc & 0x3Fu)); + utf8_bytes_filled = 3; + } + else if (wc <= 0x10FFFF) + { + utf8_bytes[0] = static_cast::int_type>(0xF0u | ((wc >> 18u) & 0x07u)); + utf8_bytes[1] = static_cast::int_type>(0x80u | ((wc >> 12u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>(0x80u | ((wc >> 6u) & 0x3Fu)); + utf8_bytes[3] = static_cast::int_type>(0x80u | (wc & 0x3Fu)); + utf8_bytes_filled = 4; + } + else + { + // unknown character + utf8_bytes[0] = static_cast::int_type>(wc); + utf8_bytes_filled = 1; + } + } + } +}; + +template +struct wide_string_input_helper +{ + // UTF-16 + static void fill_buffer(const WideStringType& str, + size_t& current_wchar, + std::array::int_type, 4>& utf8_bytes, + size_t& utf8_bytes_index, + size_t& utf8_bytes_filled) + { + utf8_bytes_index = 0; + + if (current_wchar == str.size()) + { + utf8_bytes[0] = std::char_traits::eof(); + utf8_bytes_filled = 1; + } + else + { + // get the current character + const auto wc = static_cast(str[current_wchar++]); + + // UTF-16 to UTF-8 encoding + if (wc < 0x80) + { + utf8_bytes[0] = static_cast::int_type>(wc); + utf8_bytes_filled = 1; + } + else if (wc <= 0x7FF) + { + utf8_bytes[0] = static_cast::int_type>(0xC0u | ((wc >> 6u))); + utf8_bytes[1] = static_cast::int_type>(0x80u | (wc & 0x3Fu)); + utf8_bytes_filled = 2; + } + else if (0xD800 > wc or wc >= 0xE000) + { + utf8_bytes[0] = static_cast::int_type>(0xE0u | ((wc >> 12u))); + utf8_bytes[1] = static_cast::int_type>(0x80u | ((wc >> 6u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>(0x80u | (wc & 0x3Fu)); + utf8_bytes_filled = 3; + } + else + { + if (current_wchar < str.size()) + { + const auto wc2 = static_cast(str[current_wchar++]); + const auto charcode = 0x10000u + (((wc & 0x3FFu) << 10u) | (wc2 & 0x3FFu)); + utf8_bytes[0] = static_cast::int_type>(0xF0u | (charcode >> 18u)); + utf8_bytes[1] = static_cast::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu)); + utf8_bytes[3] = static_cast::int_type>(0x80u | (charcode & 0x3Fu)); + utf8_bytes_filled = 4; + } + else + { + // unknown character + ++current_wchar; + utf8_bytes[0] = static_cast::int_type>(wc); + utf8_bytes_filled = 1; + } + } + } + } +}; + +template +class wide_string_input_adapter : public input_adapter_protocol +{ + public: + explicit wide_string_input_adapter(const WideStringType& w) noexcept + : str(w) + {} + + std::char_traits::int_type get_character() noexcept override + { + // check if buffer needs to be filled + if (utf8_bytes_index == utf8_bytes_filled) + { + fill_buffer(); + + assert(utf8_bytes_filled > 0); + assert(utf8_bytes_index == 0); + } + + // use buffer + assert(utf8_bytes_filled > 0); + assert(utf8_bytes_index < utf8_bytes_filled); + return utf8_bytes[utf8_bytes_index++]; + } + + private: + template + void fill_buffer() + { + wide_string_input_helper::fill_buffer(str, current_wchar, utf8_bytes, utf8_bytes_index, utf8_bytes_filled); + } + + /// the wstring to process + const WideStringType& str; + + /// index of the current wchar in str + std::size_t current_wchar = 0; + + /// a buffer for UTF-8 bytes + std::array::int_type, 4> utf8_bytes = {{0, 0, 0, 0}}; + + /// index to the utf8_codes array for the next valid byte + std::size_t utf8_bytes_index = 0; + /// number of valid bytes in the utf8_codes array + std::size_t utf8_bytes_filled = 0; +}; + +class input_adapter +{ + public: + // native support + input_adapter(std::FILE* file) + : ia(std::make_shared(file)) {} + /// input adapter for input stream + input_adapter(std::istream& i) + : ia(std::make_shared(i)) {} + + /// input adapter for input stream + input_adapter(std::istream&& i) + : ia(std::make_shared(i)) {} + + input_adapter(const std::wstring& ws) + : ia(std::make_shared>(ws)) {} + + input_adapter(const std::u16string& ws) + : ia(std::make_shared>(ws)) {} + + input_adapter(const std::u32string& ws) + : ia(std::make_shared>(ws)) {} + + /// input adapter for buffer + template::value and + std::is_integral::type>::value and + sizeof(typename std::remove_pointer::type) == 1, + int>::type = 0> + input_adapter(CharT b, std::size_t l) + : ia(std::make_shared(reinterpret_cast(b), l)) {} + + // derived support + + /// input adapter for string literal + template::value and + std::is_integral::type>::value and + sizeof(typename std::remove_pointer::type) == 1, + int>::type = 0> + input_adapter(CharT b) + : input_adapter(reinterpret_cast(b), + std::strlen(reinterpret_cast(b))) {} + + /// input adapter for iterator range with contiguous storage + template::iterator_category, std::random_access_iterator_tag>::value, + int>::type = 0> + input_adapter(IteratorType first, IteratorType last) + { +#ifndef NDEBUG + // assertion to check that the iterator range is indeed contiguous, + // see http://stackoverflow.com/a/35008842/266378 for more discussion + const auto is_contiguous = std::accumulate( + first, last, std::pair(true, 0), + [&first](std::pair res, decltype(*first) val) + { + res.first &= (val == *(std::next(std::addressof(*first), res.second++))); + return res; + }).first; + assert(is_contiguous); +#endif + + // assertion to check that each element is 1 byte long + static_assert( + sizeof(typename iterator_traits::value_type) == 1, + "each element in the iterator range must have the size of 1 byte"); + + const auto len = static_cast(std::distance(first, last)); + if (JSON_LIKELY(len > 0)) + { + // there is at least one element: use the address of first + ia = std::make_shared(reinterpret_cast(&(*first)), len); + } + else + { + // the address of first cannot be used: use nullptr + ia = std::make_shared(nullptr, len); + } + } + + /// input adapter for array + template + input_adapter(T (&array)[N]) + : input_adapter(std::begin(array), std::end(array)) {} + + /// input adapter for contiguous container + template::value and + std::is_base_of()))>::iterator_category>::value, + int>::type = 0> + input_adapter(const ContiguousContainer& c) + : input_adapter(std::begin(c), std::end(c)) {} + + operator input_adapter_t() + { + return ia; + } + + private: + /// the actual adapter + input_adapter_t ia = nullptr; +}; +} // namespace detail +} // namespace nlohmann diff --git a/nlohmann/detail/input/json_sax.hpp b/nlohmann/detail/input/json_sax.hpp new file mode 100644 index 0000000000..66651a90bb --- /dev/null +++ b/nlohmann/detail/input/json_sax.hpp @@ -0,0 +1,700 @@ +#pragma once + +#include // assert +#include +#include // string +#include // move +#include // vector + +#include +#include + +namespace nlohmann +{ + +/*! +@brief SAX interface + +This class describes the SAX interface used by @ref nlohmann::json::sax_parse. +Each function is called in different situations while the input is parsed. The +boolean return value informs the parser whether to continue processing the +input. +*/ +template +struct json_sax +{ + /// type for (signed) integers + using number_integer_t = typename BasicJsonType::number_integer_t; + /// type for unsigned integers + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + /// type for floating-point numbers + using number_float_t = typename BasicJsonType::number_float_t; + /// type for strings + using string_t = typename BasicJsonType::string_t; + + /*! + @brief a null value was read + @return whether parsing should proceed + */ + virtual bool null() = 0; + + /*! + @brief a boolean value was read + @param[in] val boolean value + @return whether parsing should proceed + */ + virtual bool boolean(bool val) = 0; + + /*! + @brief an integer number was read + @param[in] val integer value + @return whether parsing should proceed + */ + virtual bool number_integer(number_integer_t val) = 0; + + /*! + @brief an unsigned integer number was read + @param[in] val unsigned integer value + @return whether parsing should proceed + */ + virtual bool number_unsigned(number_unsigned_t val) = 0; + + /*! + @brief an floating-point number was read + @param[in] val floating-point value + @param[in] s raw token value + @return whether parsing should proceed + */ + virtual bool number_float(number_float_t val, const string_t& s) = 0; + + /*! + @brief a string was read + @param[in] val string value + @return whether parsing should proceed + @note It is safe to move the passed string. + */ + virtual bool string(string_t& val) = 0; + + /*! + @brief the beginning of an object was read + @param[in] elements number of object elements or -1 if unknown + @return whether parsing should proceed + @note binary formats may report the number of elements + */ + virtual bool start_object(std::size_t elements) = 0; + + /*! + @brief an object key was read + @param[in] val object key + @return whether parsing should proceed + @note It is safe to move the passed string. + */ + virtual bool key(string_t& val) = 0; + + /*! + @brief the end of an object was read + @return whether parsing should proceed + */ + virtual bool end_object() = 0; + + /*! + @brief the beginning of an array was read + @param[in] elements number of array elements or -1 if unknown + @return whether parsing should proceed + @note binary formats may report the number of elements + */ + virtual bool start_array(std::size_t elements) = 0; + + /*! + @brief the end of an array was read + @return whether parsing should proceed + */ + virtual bool end_array() = 0; + + /*! + @brief a parse error occurred + @param[in] position the position in the input where the error occurs + @param[in] last_token the last read token + @param[in] ex an exception object describing the error + @return whether parsing should proceed (must return false) + */ + virtual bool parse_error(std::size_t position, + const std::string& last_token, + const detail::exception& ex) = 0; + + virtual ~json_sax() = default; +}; + + +namespace detail +{ +/*! +@brief SAX implementation to create a JSON value from SAX events + +This class implements the @ref json_sax interface and processes the SAX events +to create a JSON value which makes it basically a DOM parser. The structure or +hierarchy of the JSON value is managed by the stack `ref_stack` which contains +a pointer to the respective array or object for each recursion depth. + +After successful parsing, the value that is passed by reference to the +constructor contains the parsed value. + +@tparam BasicJsonType the JSON type +*/ +template +class json_sax_dom_parser +{ + public: + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + + /*! + @param[in, out] r reference to a JSON value that is manipulated while + parsing + @param[in] allow_exceptions_ whether parse errors yield exceptions + */ + explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true) + : root(r), allow_exceptions(allow_exceptions_) + {} + + // make class move-only + json_sax_dom_parser(const json_sax_dom_parser&) = delete; + json_sax_dom_parser(json_sax_dom_parser&&) = default; + json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete; + json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; + ~json_sax_dom_parser() = default; + + bool null() + { + handle_value(nullptr); + return true; + } + + bool boolean(bool val) + { + handle_value(val); + return true; + } + + bool number_integer(number_integer_t val) + { + handle_value(val); + return true; + } + + bool number_unsigned(number_unsigned_t val) + { + handle_value(val); + return true; + } + + bool number_float(number_float_t val, const string_t& /*unused*/) + { + handle_value(val); + return true; + } + + bool string(string_t& val) + { + handle_value(val); + return true; + } + + bool start_object(std::size_t len) + { + ref_stack.push_back(handle_value(BasicJsonType::value_t::object)); + + if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, + "excessive object size: " + std::to_string(len))); + } + + return true; + } + + bool key(string_t& val) + { + // add null at given key and store the reference for later + object_element = &(ref_stack.back()->m_value.object->operator[](val)); + return true; + } + + bool end_object() + { + ref_stack.pop_back(); + return true; + } + + bool start_array(std::size_t len) + { + ref_stack.push_back(handle_value(BasicJsonType::value_t::array)); + + if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, + "excessive array size: " + std::to_string(len))); + } + + return true; + } + + bool end_array() + { + ref_stack.pop_back(); + return true; + } + + bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, + const detail::exception& ex) + { + errored = true; + if (allow_exceptions) + { + // determine the proper exception type from the id + switch ((ex.id / 100) % 100) + { + case 1: + JSON_THROW(*static_cast(&ex)); + case 4: + JSON_THROW(*static_cast(&ex)); + // LCOV_EXCL_START + case 2: + JSON_THROW(*static_cast(&ex)); + case 3: + JSON_THROW(*static_cast(&ex)); + case 5: + JSON_THROW(*static_cast(&ex)); + default: + assert(false); + // LCOV_EXCL_STOP + } + } + return false; + } + + constexpr bool is_errored() const + { + return errored; + } + + private: + /*! + @invariant If the ref stack is empty, then the passed value will be the new + root. + @invariant If the ref stack contains a value, then it is an array or an + object to which we can add elements + */ + template + BasicJsonType* handle_value(Value&& v) + { + if (ref_stack.empty()) + { + root = BasicJsonType(std::forward(v)); + return &root; + } + + assert(ref_stack.back()->is_array() or ref_stack.back()->is_object()); + + if (ref_stack.back()->is_array()) + { + ref_stack.back()->m_value.array->emplace_back(std::forward(v)); + return &(ref_stack.back()->m_value.array->back()); + } + + assert(ref_stack.back()->is_object()); + assert(object_element); + *object_element = BasicJsonType(std::forward(v)); + return object_element; + } + + /// the parsed JSON value + BasicJsonType& root; + /// stack to model hierarchy of values + std::vector ref_stack {}; + /// helper to hold the reference for the next object element + BasicJsonType* object_element = nullptr; + /// whether a syntax error occurred + bool errored = false; + /// whether to throw exceptions in case of errors + const bool allow_exceptions = true; +}; + +template +class json_sax_dom_callback_parser +{ + public: + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using parser_callback_t = typename BasicJsonType::parser_callback_t; + using parse_event_t = typename BasicJsonType::parse_event_t; + + json_sax_dom_callback_parser(BasicJsonType& r, + const parser_callback_t cb, + const bool allow_exceptions_ = true) + : root(r), callback(cb), allow_exceptions(allow_exceptions_) + { + keep_stack.push_back(true); + } + + // make class move-only + json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete; + json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; + json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete; + json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; + ~json_sax_dom_callback_parser() = default; + + bool null() + { + handle_value(nullptr); + return true; + } + + bool boolean(bool val) + { + handle_value(val); + return true; + } + + bool number_integer(number_integer_t val) + { + handle_value(val); + return true; + } + + bool number_unsigned(number_unsigned_t val) + { + handle_value(val); + return true; + } + + bool number_float(number_float_t val, const string_t& /*unused*/) + { + handle_value(val); + return true; + } + + bool string(string_t& val) + { + handle_value(val); + return true; + } + + bool start_object(std::size_t len) + { + // check callback for object start + const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::object_start, discarded); + keep_stack.push_back(keep); + + auto val = handle_value(BasicJsonType::value_t::object, true); + ref_stack.push_back(val.second); + + // check object limit + if (ref_stack.back() and JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len))); + } + + return true; + } + + bool key(string_t& val) + { + BasicJsonType k = BasicJsonType(val); + + // check callback for key + const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::key, k); + key_keep_stack.push_back(keep); + + // add discarded value at given key and store the reference for later + if (keep and ref_stack.back()) + { + object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded); + } + + return true; + } + + bool end_object() + { + if (ref_stack.back() and not callback(static_cast(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back())) + { + // discard object + *ref_stack.back() = discarded; + } + + assert(not ref_stack.empty()); + assert(not keep_stack.empty()); + ref_stack.pop_back(); + keep_stack.pop_back(); + + if (not ref_stack.empty() and ref_stack.back() and ref_stack.back()->is_object()) + { + // remove discarded value + for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it) + { + if (it->is_discarded()) + { + ref_stack.back()->erase(it); + break; + } + } + } + + return true; + } + + bool start_array(std::size_t len) + { + const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::array_start, discarded); + keep_stack.push_back(keep); + + auto val = handle_value(BasicJsonType::value_t::array, true); + ref_stack.push_back(val.second); + + // check array limit + if (ref_stack.back() and JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len))); + } + + return true; + } + + bool end_array() + { + bool keep = true; + + if (ref_stack.back()) + { + keep = callback(static_cast(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back()); + if (not keep) + { + // discard array + *ref_stack.back() = discarded; + } + } + + assert(not ref_stack.empty()); + assert(not keep_stack.empty()); + ref_stack.pop_back(); + keep_stack.pop_back(); + + // remove discarded value + if (not keep and not ref_stack.empty() and ref_stack.back()->is_array()) + { + ref_stack.back()->m_value.array->pop_back(); + } + + return true; + } + + bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, + const detail::exception& ex) + { + errored = true; + if (allow_exceptions) + { + // determine the proper exception type from the id + switch ((ex.id / 100) % 100) + { + case 1: + JSON_THROW(*static_cast(&ex)); + case 4: + JSON_THROW(*static_cast(&ex)); + // LCOV_EXCL_START + case 2: + JSON_THROW(*static_cast(&ex)); + case 3: + JSON_THROW(*static_cast(&ex)); + case 5: + JSON_THROW(*static_cast(&ex)); + default: + assert(false); + // LCOV_EXCL_STOP + } + } + return false; + } + + constexpr bool is_errored() const + { + return errored; + } + + private: + /*! + @param[in] v value to add to the JSON value we build during parsing + @param[in] skip_callback whether we should skip calling the callback + function; this is required after start_array() and + start_object() SAX events, because otherwise we would call the + callback function with an empty array or object, respectively. + + @invariant If the ref stack is empty, then the passed value will be the new + root. + @invariant If the ref stack contains a value, then it is an array or an + object to which we can add elements + + @return pair of boolean (whether value should be kept) and pointer (to the + passed value in the ref_stack hierarchy; nullptr if not kept) + */ + template + std::pair handle_value(Value&& v, const bool skip_callback = false) + { + assert(not keep_stack.empty()); + + // do not handle this value if we know it would be added to a discarded + // container + if (not keep_stack.back()) + { + return {false, nullptr}; + } + + // create value + auto value = BasicJsonType(std::forward(v)); + + // check callback + const bool keep = skip_callback or callback(static_cast(ref_stack.size()), parse_event_t::value, value); + + // do not handle this value if we just learnt it shall be discarded + if (not keep) + { + return {false, nullptr}; + } + + if (ref_stack.empty()) + { + root = std::move(value); + return {true, &root}; + } + + // skip this value if we already decided to skip the parent + // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360) + if (not ref_stack.back()) + { + return {false, nullptr}; + } + + // we now only expect arrays and objects + assert(ref_stack.back()->is_array() or ref_stack.back()->is_object()); + + // array + if (ref_stack.back()->is_array()) + { + ref_stack.back()->m_value.array->push_back(std::move(value)); + return {true, &(ref_stack.back()->m_value.array->back())}; + } + + // object + assert(ref_stack.back()->is_object()); + // check if we should store an element for the current key + assert(not key_keep_stack.empty()); + const bool store_element = key_keep_stack.back(); + key_keep_stack.pop_back(); + + if (not store_element) + { + return {false, nullptr}; + } + + assert(object_element); + *object_element = std::move(value); + return {true, object_element}; + } + + /// the parsed JSON value + BasicJsonType& root; + /// stack to model hierarchy of values + std::vector ref_stack {}; + /// stack to manage which values to keep + std::vector keep_stack {}; + /// stack to manage which object keys to keep + std::vector key_keep_stack {}; + /// helper to hold the reference for the next object element + BasicJsonType* object_element = nullptr; + /// whether a syntax error occurred + bool errored = false; + /// callback function + const parser_callback_t callback = nullptr; + /// whether to throw exceptions in case of errors + const bool allow_exceptions = true; + /// a discarded value for the callback + BasicJsonType discarded = BasicJsonType::value_t::discarded; +}; + +template +class json_sax_acceptor +{ + public: + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + + bool null() + { + return true; + } + + bool boolean(bool /*unused*/) + { + return true; + } + + bool number_integer(number_integer_t /*unused*/) + { + return true; + } + + bool number_unsigned(number_unsigned_t /*unused*/) + { + return true; + } + + bool number_float(number_float_t /*unused*/, const string_t& /*unused*/) + { + return true; + } + + bool string(string_t& /*unused*/) + { + return true; + } + + bool start_object(std::size_t /*unused*/ = std::size_t(-1)) + { + return true; + } + + bool key(string_t& /*unused*/) + { + return true; + } + + bool end_object() + { + return true; + } + + bool start_array(std::size_t /*unused*/ = std::size_t(-1)) + { + return true; + } + + bool end_array() + { + return true; + } + + bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/) + { + return false; + } +}; +} // namespace detail + +} // namespace nlohmann diff --git a/nlohmann/detail/input/lexer.hpp b/nlohmann/detail/input/lexer.hpp new file mode 100644 index 0000000000..c135420f22 --- /dev/null +++ b/nlohmann/detail/input/lexer.hpp @@ -0,0 +1,1504 @@ +#pragma once + +#include // array +#include // localeconv +#include // size_t +#include // snprintf +#include // strtof, strtod, strtold, strtoll, strtoull +#include // initializer_list +#include // char_traits, string +#include // move +#include // vector + +#include +#include +#include + +namespace nlohmann +{ +namespace detail +{ +/////////// +// lexer // +/////////// + +/*! +@brief lexical analysis + +This class organizes the lexical analysis during JSON deserialization. +*/ +template +class lexer +{ + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + + public: + /// token types for the parser + enum class token_type + { + uninitialized, ///< indicating the scanner is uninitialized + literal_true, ///< the `true` literal + literal_false, ///< the `false` literal + literal_null, ///< the `null` literal + value_string, ///< a string -- use get_string() for actual value + value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value + value_integer, ///< a signed integer -- use get_number_integer() for actual value + value_float, ///< an floating point number -- use get_number_float() for actual value + begin_array, ///< the character for array begin `[` + begin_object, ///< the character for object begin `{` + end_array, ///< the character for array end `]` + end_object, ///< the character for object end `}` + name_separator, ///< the name separator `:` + value_separator, ///< the value separator `,` + parse_error, ///< indicating a parse error + end_of_input, ///< indicating the end of the input buffer + literal_or_value ///< a literal or the begin of a value (only for diagnostics) + }; + + /// return name of values of type token_type (only used for errors) + static const char* token_type_name(const token_type t) noexcept + { + switch (t) + { + case token_type::uninitialized: + return ""; + case token_type::literal_true: + return "true literal"; + case token_type::literal_false: + return "false literal"; + case token_type::literal_null: + return "null literal"; + case token_type::value_string: + return "string literal"; + case lexer::token_type::value_unsigned: + case lexer::token_type::value_integer: + case lexer::token_type::value_float: + return "number literal"; + case token_type::begin_array: + return "'['"; + case token_type::begin_object: + return "'{'"; + case token_type::end_array: + return "']'"; + case token_type::end_object: + return "'}'"; + case token_type::name_separator: + return "':'"; + case token_type::value_separator: + return "','"; + case token_type::parse_error: + return ""; + case token_type::end_of_input: + return "end of input"; + case token_type::literal_or_value: + return "'[', '{', or a literal"; + // LCOV_EXCL_START + default: // catch non-enum values + return "unknown token"; + // LCOV_EXCL_STOP + } + } + + explicit lexer(detail::input_adapter_t&& adapter) + : ia(std::move(adapter)), decimal_point_char(get_decimal_point()) {} + + // delete because of pointer members + lexer(const lexer&) = delete; + lexer(lexer&&) = delete; + lexer& operator=(lexer&) = delete; + lexer& operator=(lexer&&) = delete; + ~lexer() = default; + + private: + ///////////////////// + // locales + ///////////////////// + + /// return the locale-dependent decimal point + static char get_decimal_point() noexcept + { + const auto loc = localeconv(); + assert(loc != nullptr); + return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point); + } + + ///////////////////// + // scan functions + ///////////////////// + + /*! + @brief get codepoint from 4 hex characters following `\u` + + For input "\u c1 c2 c3 c4" the codepoint is: + (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4 + = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0) + + Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f' + must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The + conversion is done by subtracting the offset (0x30, 0x37, and 0x57) + between the ASCII value of the character and the desired integer value. + + @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or + non-hex character) + */ + int get_codepoint() + { + // this function only makes sense after reading `\u` + assert(current == 'u'); + int codepoint = 0; + + const auto factors = { 12u, 8u, 4u, 0u }; + for (const auto factor : factors) + { + get(); + + if (current >= '0' and current <= '9') + { + codepoint += static_cast((static_cast(current) - 0x30u) << factor); + } + else if (current >= 'A' and current <= 'F') + { + codepoint += static_cast((static_cast(current) - 0x37u) << factor); + } + else if (current >= 'a' and current <= 'f') + { + codepoint += static_cast((static_cast(current) - 0x57u) << factor); + } + else + { + return -1; + } + } + + assert(0x0000 <= codepoint and codepoint <= 0xFFFF); + return codepoint; + } + + /*! + @brief check if the next byte(s) are inside a given range + + Adds the current byte and, for each passed range, reads a new byte and + checks if it is inside the range. If a violation was detected, set up an + error message and return false. Otherwise, return true. + + @param[in] ranges list of integers; interpreted as list of pairs of + inclusive lower and upper bound, respectively + + @pre The passed list @a ranges must have 2, 4, or 6 elements; that is, + 1, 2, or 3 pairs. This precondition is enforced by an assertion. + + @return true if and only if no range violation was detected + */ + bool next_byte_in_range(std::initializer_list ranges) + { + assert(ranges.size() == 2 or ranges.size() == 4 or ranges.size() == 6); + add(current); + + for (auto range = ranges.begin(); range != ranges.end(); ++range) + { + get(); + if (JSON_LIKELY(*range <= current and current <= *(++range))) + { + add(current); + } + else + { + error_message = "invalid string: ill-formed UTF-8 byte"; + return false; + } + } + + return true; + } + + /*! + @brief scan a string literal + + This function scans a string according to Sect. 7 of RFC 7159. While + scanning, bytes are escaped and copied into buffer token_buffer. Then the + function returns successfully, token_buffer is *not* null-terminated (as it + may contain \0 bytes), and token_buffer.size() is the number of bytes in the + string. + + @return token_type::value_string if string could be successfully scanned, + token_type::parse_error otherwise + + @note In case of errors, variable error_message contains a textual + description. + */ + token_type scan_string() + { + // reset token_buffer (ignore opening quote) + reset(); + + // we entered the function by reading an open quote + assert(current == '\"'); + + while (true) + { + // get next character + switch (get()) + { + // end of file while parsing string + case std::char_traits::eof(): + { + error_message = "invalid string: missing closing quote"; + return token_type::parse_error; + } + + // closing quote + case '\"': + { + return token_type::value_string; + } + + // escapes + case '\\': + { + switch (get()) + { + // quotation mark + case '\"': + add('\"'); + break; + // reverse solidus + case '\\': + add('\\'); + break; + // solidus + case '/': + add('/'); + break; + // backspace + case 'b': + add('\b'); + break; + // form feed + case 'f': + add('\f'); + break; + // line feed + case 'n': + add('\n'); + break; + // carriage return + case 'r': + add('\r'); + break; + // tab + case 't': + add('\t'); + break; + + // unicode escapes + case 'u': + { + const int codepoint1 = get_codepoint(); + int codepoint = codepoint1; // start with codepoint1 + + if (JSON_UNLIKELY(codepoint1 == -1)) + { + error_message = "invalid string: '\\u' must be followed by 4 hex digits"; + return token_type::parse_error; + } + + // check if code point is a high surrogate + if (0xD800 <= codepoint1 and codepoint1 <= 0xDBFF) + { + // expect next \uxxxx entry + if (JSON_LIKELY(get() == '\\' and get() == 'u')) + { + const int codepoint2 = get_codepoint(); + + if (JSON_UNLIKELY(codepoint2 == -1)) + { + error_message = "invalid string: '\\u' must be followed by 4 hex digits"; + return token_type::parse_error; + } + + // check if codepoint2 is a low surrogate + if (JSON_LIKELY(0xDC00 <= codepoint2 and codepoint2 <= 0xDFFF)) + { + // overwrite codepoint + codepoint = static_cast( + // high surrogate occupies the most significant 22 bits + (static_cast(codepoint1) << 10u) + // low surrogate occupies the least significant 15 bits + + static_cast(codepoint2) + // there is still the 0xD800, 0xDC00 and 0x10000 noise + // in the result so we have to subtract with: + // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00 + - 0x35FDC00u); + } + else + { + error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF"; + return token_type::parse_error; + } + } + else + { + error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF"; + return token_type::parse_error; + } + } + else + { + if (JSON_UNLIKELY(0xDC00 <= codepoint1 and codepoint1 <= 0xDFFF)) + { + error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF"; + return token_type::parse_error; + } + } + + // result of the above calculation yields a proper codepoint + assert(0x00 <= codepoint and codepoint <= 0x10FFFF); + + // translate codepoint into bytes + if (codepoint < 0x80) + { + // 1-byte characters: 0xxxxxxx (ASCII) + add(codepoint); + } + else if (codepoint <= 0x7FF) + { + // 2-byte characters: 110xxxxx 10xxxxxx + add(static_cast(0xC0u | (static_cast(codepoint) >> 6u))); + add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); + } + else if (codepoint <= 0xFFFF) + { + // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx + add(static_cast(0xE0u | (static_cast(codepoint) >> 12u))); + add(static_cast(0x80u | ((static_cast(codepoint) >> 6u) & 0x3Fu))); + add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); + } + else + { + // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + add(static_cast(0xF0u | (static_cast(codepoint) >> 18u))); + add(static_cast(0x80u | ((static_cast(codepoint) >> 12u) & 0x3Fu))); + add(static_cast(0x80u | ((static_cast(codepoint) >> 6u) & 0x3Fu))); + add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); + } + + break; + } + + // other characters after escape + default: + error_message = "invalid string: forbidden character after backslash"; + return token_type::parse_error; + } + + break; + } + + // invalid control characters + case 0x00: + { + error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000"; + return token_type::parse_error; + } + + case 0x01: + { + error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001"; + return token_type::parse_error; + } + + case 0x02: + { + error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002"; + return token_type::parse_error; + } + + case 0x03: + { + error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003"; + return token_type::parse_error; + } + + case 0x04: + { + error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004"; + return token_type::parse_error; + } + + case 0x05: + { + error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005"; + return token_type::parse_error; + } + + case 0x06: + { + error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006"; + return token_type::parse_error; + } + + case 0x07: + { + error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007"; + return token_type::parse_error; + } + + case 0x08: + { + error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b"; + return token_type::parse_error; + } + + case 0x09: + { + error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t"; + return token_type::parse_error; + } + + case 0x0A: + { + error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n"; + return token_type::parse_error; + } + + case 0x0B: + { + error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B"; + return token_type::parse_error; + } + + case 0x0C: + { + error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f"; + return token_type::parse_error; + } + + case 0x0D: + { + error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r"; + return token_type::parse_error; + } + + case 0x0E: + { + error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E"; + return token_type::parse_error; + } + + case 0x0F: + { + error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F"; + return token_type::parse_error; + } + + case 0x10: + { + error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010"; + return token_type::parse_error; + } + + case 0x11: + { + error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011"; + return token_type::parse_error; + } + + case 0x12: + { + error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012"; + return token_type::parse_error; + } + + case 0x13: + { + error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013"; + return token_type::parse_error; + } + + case 0x14: + { + error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014"; + return token_type::parse_error; + } + + case 0x15: + { + error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015"; + return token_type::parse_error; + } + + case 0x16: + { + error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016"; + return token_type::parse_error; + } + + case 0x17: + { + error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017"; + return token_type::parse_error; + } + + case 0x18: + { + error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018"; + return token_type::parse_error; + } + + case 0x19: + { + error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019"; + return token_type::parse_error; + } + + case 0x1A: + { + error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A"; + return token_type::parse_error; + } + + case 0x1B: + { + error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B"; + return token_type::parse_error; + } + + case 0x1C: + { + error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C"; + return token_type::parse_error; + } + + case 0x1D: + { + error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D"; + return token_type::parse_error; + } + + case 0x1E: + { + error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E"; + return token_type::parse_error; + } + + case 0x1F: + { + error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F"; + return token_type::parse_error; + } + + // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace)) + case 0x20: + case 0x21: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3A: + case 0x3B: + case 0x3C: + case 0x3D: + case 0x3E: + case 0x3F: + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: + case 0x59: + case 0x5A: + case 0x5B: + case 0x5D: + case 0x5E: + case 0x5F: + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: + case 0x79: + case 0x7A: + case 0x7B: + case 0x7C: + case 0x7D: + case 0x7E: + case 0x7F: + { + add(current); + break; + } + + // U+0080..U+07FF: bytes C2..DF 80..BF + case 0xC2: + case 0xC3: + case 0xC4: + case 0xC5: + case 0xC6: + case 0xC7: + case 0xC8: + case 0xC9: + case 0xCA: + case 0xCB: + case 0xCC: + case 0xCD: + case 0xCE: + case 0xCF: + case 0xD0: + case 0xD1: + case 0xD2: + case 0xD3: + case 0xD4: + case 0xD5: + case 0xD6: + case 0xD7: + case 0xD8: + case 0xD9: + case 0xDA: + case 0xDB: + case 0xDC: + case 0xDD: + case 0xDE: + case 0xDF: + { + if (JSON_UNLIKELY(not next_byte_in_range({0x80, 0xBF}))) + { + return token_type::parse_error; + } + break; + } + + // U+0800..U+0FFF: bytes E0 A0..BF 80..BF + case 0xE0: + { + if (JSON_UNLIKELY(not (next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF + // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF + case 0xE1: + case 0xE2: + case 0xE3: + case 0xE4: + case 0xE5: + case 0xE6: + case 0xE7: + case 0xE8: + case 0xE9: + case 0xEA: + case 0xEB: + case 0xEC: + case 0xEE: + case 0xEF: + { + if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+D000..U+D7FF: bytes ED 80..9F 80..BF + case 0xED: + { + if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0x9F, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF + case 0xF0: + { + if (JSON_UNLIKELY(not (next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF + case 0xF1: + case 0xF2: + case 0xF3: + { + if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF + case 0xF4: + { + if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // remaining bytes (80..C1 and F5..FF) are ill-formed + default: + { + error_message = "invalid string: ill-formed UTF-8 byte"; + return token_type::parse_error; + } + } + } + } + + static void strtof(float& f, const char* str, char** endptr) noexcept + { + f = std::strtof(str, endptr); + } + + static void strtof(double& f, const char* str, char** endptr) noexcept + { + f = std::strtod(str, endptr); + } + + static void strtof(long double& f, const char* str, char** endptr) noexcept + { + f = std::strtold(str, endptr); + } + + /*! + @brief scan a number literal + + This function scans a string according to Sect. 6 of RFC 7159. + + The function is realized with a deterministic finite state machine derived + from the grammar described in RFC 7159. Starting in state "init", the + input is read and used to determined the next state. Only state "done" + accepts the number. State "error" is a trap state to model errors. In the + table below, "anything" means any character but the ones listed before. + + state | 0 | 1-9 | e E | + | - | . | anything + ---------|----------|----------|----------|---------|---------|----------|----------- + init | zero | any1 | [error] | [error] | minus | [error] | [error] + minus | zero | any1 | [error] | [error] | [error] | [error] | [error] + zero | done | done | exponent | done | done | decimal1 | done + any1 | any1 | any1 | exponent | done | done | decimal1 | done + decimal1 | decimal2 | [error] | [error] | [error] | [error] | [error] | [error] + decimal2 | decimal2 | decimal2 | exponent | done | done | done | done + exponent | any2 | any2 | [error] | sign | sign | [error] | [error] + sign | any2 | any2 | [error] | [error] | [error] | [error] | [error] + any2 | any2 | any2 | done | done | done | done | done + + The state machine is realized with one label per state (prefixed with + "scan_number_") and `goto` statements between them. The state machine + contains cycles, but any cycle can be left when EOF is read. Therefore, + the function is guaranteed to terminate. + + During scanning, the read bytes are stored in token_buffer. This string is + then converted to a signed integer, an unsigned integer, or a + floating-point number. + + @return token_type::value_unsigned, token_type::value_integer, or + token_type::value_float if number could be successfully scanned, + token_type::parse_error otherwise + + @note The scanner is independent of the current locale. Internally, the + locale's decimal point is used instead of `.` to work with the + locale-dependent converters. + */ + token_type scan_number() // lgtm [cpp/use-of-goto] + { + // reset token_buffer to store the number's bytes + reset(); + + // the type of the parsed number; initially set to unsigned; will be + // changed if minus sign, decimal point or exponent is read + token_type number_type = token_type::value_unsigned; + + // state (init): we just found out we need to scan a number + switch (current) + { + case '-': + { + add(current); + goto scan_number_minus; + } + + case '0': + { + add(current); + goto scan_number_zero; + } + + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any1; + } + + // all other characters are rejected outside scan_number() + default: // LCOV_EXCL_LINE + assert(false); // LCOV_EXCL_LINE + } + +scan_number_minus: + // state: we just parsed a leading minus sign + number_type = token_type::value_integer; + switch (get()) + { + case '0': + { + add(current); + goto scan_number_zero; + } + + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any1; + } + + default: + { + error_message = "invalid number; expected digit after '-'"; + return token_type::parse_error; + } + } + +scan_number_zero: + // state: we just parse a zero (maybe with a leading minus sign) + switch (get()) + { + case '.': + { + add(decimal_point_char); + goto scan_number_decimal1; + } + + case 'e': + case 'E': + { + add(current); + goto scan_number_exponent; + } + + default: + goto scan_number_done; + } + +scan_number_any1: + // state: we just parsed a number 0-9 (maybe with a leading minus sign) + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any1; + } + + case '.': + { + add(decimal_point_char); + goto scan_number_decimal1; + } + + case 'e': + case 'E': + { + add(current); + goto scan_number_exponent; + } + + default: + goto scan_number_done; + } + +scan_number_decimal1: + // state: we just parsed a decimal point + number_type = token_type::value_float; + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_decimal2; + } + + default: + { + error_message = "invalid number; expected digit after '.'"; + return token_type::parse_error; + } + } + +scan_number_decimal2: + // we just parsed at least one number after a decimal point + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_decimal2; + } + + case 'e': + case 'E': + { + add(current); + goto scan_number_exponent; + } + + default: + goto scan_number_done; + } + +scan_number_exponent: + // we just parsed an exponent + number_type = token_type::value_float; + switch (get()) + { + case '+': + case '-': + { + add(current); + goto scan_number_sign; + } + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any2; + } + + default: + { + error_message = + "invalid number; expected '+', '-', or digit after exponent"; + return token_type::parse_error; + } + } + +scan_number_sign: + // we just parsed an exponent sign + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any2; + } + + default: + { + error_message = "invalid number; expected digit after exponent sign"; + return token_type::parse_error; + } + } + +scan_number_any2: + // we just parsed a number after the exponent or exponent sign + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any2; + } + + default: + goto scan_number_done; + } + +scan_number_done: + // unget the character after the number (we only read it to know that + // we are done scanning a number) + unget(); + + char* endptr = nullptr; + errno = 0; + + // try to parse integers first and fall back to floats + if (number_type == token_type::value_unsigned) + { + const auto x = std::strtoull(token_buffer.data(), &endptr, 10); + + // we checked the number format before + assert(endptr == token_buffer.data() + token_buffer.size()); + + if (errno == 0) + { + value_unsigned = static_cast(x); + if (value_unsigned == x) + { + return token_type::value_unsigned; + } + } + } + else if (number_type == token_type::value_integer) + { + const auto x = std::strtoll(token_buffer.data(), &endptr, 10); + + // we checked the number format before + assert(endptr == token_buffer.data() + token_buffer.size()); + + if (errno == 0) + { + value_integer = static_cast(x); + if (value_integer == x) + { + return token_type::value_integer; + } + } + } + + // this code is reached if we parse a floating-point number or if an + // integer conversion above failed + strtof(value_float, token_buffer.data(), &endptr); + + // we checked the number format before + assert(endptr == token_buffer.data() + token_buffer.size()); + + return token_type::value_float; + } + + /*! + @param[in] literal_text the literal text to expect + @param[in] length the length of the passed literal text + @param[in] return_type the token type to return on success + */ + token_type scan_literal(const char* literal_text, const std::size_t length, + token_type return_type) + { + assert(current == literal_text[0]); + for (std::size_t i = 1; i < length; ++i) + { + if (JSON_UNLIKELY(get() != literal_text[i])) + { + error_message = "invalid literal"; + return token_type::parse_error; + } + } + return return_type; + } + + ///////////////////// + // input management + ///////////////////// + + /// reset token_buffer; current character is beginning of token + void reset() noexcept + { + token_buffer.clear(); + token_string.clear(); + token_string.push_back(std::char_traits::to_char_type(current)); + } + + /* + @brief get next character from the input + + This function provides the interface to the used input adapter. It does + not throw in case the input reached EOF, but returns a + `std::char_traits::eof()` in that case. Stores the scanned characters + for use in error messages. + + @return character read from the input + */ + std::char_traits::int_type get() + { + ++position.chars_read_total; + ++position.chars_read_current_line; + + if (next_unget) + { + // just reset the next_unget variable and work with current + next_unget = false; + } + else + { + current = ia->get_character(); + } + + if (JSON_LIKELY(current != std::char_traits::eof())) + { + token_string.push_back(std::char_traits::to_char_type(current)); + } + + if (current == '\n') + { + ++position.lines_read; + position.chars_read_current_line = 0; + } + + return current; + } + + /*! + @brief unget current character (read it again on next get) + + We implement unget by setting variable next_unget to true. The input is not + changed - we just simulate ungetting by modifying chars_read_total, + chars_read_current_line, and token_string. The next call to get() will + behave as if the unget character is read again. + */ + void unget() + { + next_unget = true; + + --position.chars_read_total; + + // in case we "unget" a newline, we have to also decrement the lines_read + if (position.chars_read_current_line == 0) + { + if (position.lines_read > 0) + { + --position.lines_read; + } + } + else + { + --position.chars_read_current_line; + } + + if (JSON_LIKELY(current != std::char_traits::eof())) + { + assert(not token_string.empty()); + token_string.pop_back(); + } + } + + /// add a character to token_buffer + void add(int c) + { + token_buffer.push_back(std::char_traits::to_char_type(c)); + } + + public: + ///////////////////// + // value getters + ///////////////////// + + /// return integer value + constexpr number_integer_t get_number_integer() const noexcept + { + return value_integer; + } + + /// return unsigned integer value + constexpr number_unsigned_t get_number_unsigned() const noexcept + { + return value_unsigned; + } + + /// return floating-point value + constexpr number_float_t get_number_float() const noexcept + { + return value_float; + } + + /// return current string value (implicitly resets the token; useful only once) + string_t& get_string() + { + return token_buffer; + } + + ///////////////////// + // diagnostics + ///////////////////// + + /// return position of last read token + constexpr position_t get_position() const noexcept + { + return position; + } + + /// return the last read token (for errors only). Will never contain EOF + /// (an arbitrary value that is not a valid char value, often -1), because + /// 255 may legitimately occur. May contain NUL, which should be escaped. + std::string get_token_string() const + { + // escape control characters + std::string result; + for (const auto c : token_string) + { + if ('\x00' <= c and c <= '\x1F') + { + // escape control characters + std::array cs{{}}; + (std::snprintf)(cs.data(), cs.size(), "", static_cast(c)); + result += cs.data(); + } + else + { + // add character as is + result.push_back(c); + } + } + + return result; + } + + /// return syntax error message + constexpr const char* get_error_message() const noexcept + { + return error_message; + } + + ///////////////////// + // actual scanner + ///////////////////// + + /*! + @brief skip the UTF-8 byte order mark + @return true iff there is no BOM or the correct BOM has been skipped + */ + bool skip_bom() + { + if (get() == 0xEF) + { + // check if we completely parse the BOM + return get() == 0xBB and get() == 0xBF; + } + + // the first character is not the beginning of the BOM; unget it to + // process is later + unget(); + return true; + } + + token_type scan() + { + // initially, skip the BOM + if (position.chars_read_total == 0 and not skip_bom()) + { + error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given"; + return token_type::parse_error; + } + + // read next character and ignore whitespace + do + { + get(); + } + while (current == ' ' or current == '\t' or current == '\n' or current == '\r'); + + switch (current) + { + // structural characters + case '[': + return token_type::begin_array; + case ']': + return token_type::end_array; + case '{': + return token_type::begin_object; + case '}': + return token_type::end_object; + case ':': + return token_type::name_separator; + case ',': + return token_type::value_separator; + + // literals + case 't': + return scan_literal("true", 4, token_type::literal_true); + case 'f': + return scan_literal("false", 5, token_type::literal_false); + case 'n': + return scan_literal("null", 4, token_type::literal_null); + + // string + case '\"': + return scan_string(); + + // number + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return scan_number(); + + // end of input (the null byte is needed when parsing from + // string literals) + case '\0': + case std::char_traits::eof(): + return token_type::end_of_input; + + // error + default: + error_message = "invalid literal"; + return token_type::parse_error; + } + } + + private: + /// input adapter + detail::input_adapter_t ia = nullptr; + + /// the current character + std::char_traits::int_type current = std::char_traits::eof(); + + /// whether the next get() call should just return current + bool next_unget = false; + + /// the start position of the current token + position_t position {}; + + /// raw input token string (for error messages) + std::vector token_string {}; + + /// buffer for variable-length tokens (numbers, strings) + string_t token_buffer {}; + + /// a description of occurred lexer errors + const char* error_message = ""; + + // number values + number_integer_t value_integer = 0; + number_unsigned_t value_unsigned = 0; + number_float_t value_float = 0; + + /// the decimal point + const char decimal_point_char = '.'; +}; +} // namespace detail +} // namespace nlohmann diff --git a/nlohmann/detail/input/parser.hpp b/nlohmann/detail/input/parser.hpp new file mode 100644 index 0000000000..6c03181e68 --- /dev/null +++ b/nlohmann/detail/input/parser.hpp @@ -0,0 +1,496 @@ +#pragma once + +#include // assert +#include // isfinite +#include // uint8_t +#include // function +#include // string +#include // move +#include // vector + +#include +#include +#include +#include +#include +#include +#include + +namespace nlohmann +{ +namespace detail +{ +//////////// +// parser // +//////////// + +/*! +@brief syntax analysis + +This class implements a recursive decent parser. +*/ +template +class parser +{ + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using lexer_t = lexer; + using token_type = typename lexer_t::token_type; + + public: + enum class parse_event_t : uint8_t + { + /// the parser read `{` and started to process a JSON object + object_start, + /// the parser read `}` and finished processing a JSON object + object_end, + /// the parser read `[` and started to process a JSON array + array_start, + /// the parser read `]` and finished processing a JSON array + array_end, + /// the parser read a key of a value in an object + key, + /// the parser finished reading a JSON value + value + }; + + using parser_callback_t = + std::function; + + /// a parser reading from an input adapter + explicit parser(detail::input_adapter_t&& adapter, + const parser_callback_t cb = nullptr, + const bool allow_exceptions_ = true) + : callback(cb), m_lexer(std::move(adapter)), allow_exceptions(allow_exceptions_) + { + // read first token + get_token(); + } + + /*! + @brief public parser interface + + @param[in] strict whether to expect the last token to be EOF + @param[in,out] result parsed JSON value + + @throw parse_error.101 in case of an unexpected token + @throw parse_error.102 if to_unicode fails or surrogate error + @throw parse_error.103 if to_unicode fails + */ + void parse(const bool strict, BasicJsonType& result) + { + if (callback) + { + json_sax_dom_callback_parser sdp(result, callback, allow_exceptions); + sax_parse_internal(&sdp); + result.assert_invariant(); + + // in strict mode, input must be completely read + if (strict and (get_token() != token_type::end_of_input)) + { + sdp.parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_of_input, "value"))); + } + + // in case of an error, return discarded value + if (sdp.is_errored()) + { + result = value_t::discarded; + return; + } + + // set top-level value to null if it was discarded by the callback + // function + if (result.is_discarded()) + { + result = nullptr; + } + } + else + { + json_sax_dom_parser sdp(result, allow_exceptions); + sax_parse_internal(&sdp); + result.assert_invariant(); + + // in strict mode, input must be completely read + if (strict and (get_token() != token_type::end_of_input)) + { + sdp.parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_of_input, "value"))); + } + + // in case of an error, return discarded value + if (sdp.is_errored()) + { + result = value_t::discarded; + return; + } + } + } + + /*! + @brief public accept interface + + @param[in] strict whether to expect the last token to be EOF + @return whether the input is a proper JSON text + */ + bool accept(const bool strict = true) + { + json_sax_acceptor sax_acceptor; + return sax_parse(&sax_acceptor, strict); + } + + template + bool sax_parse(SAX* sax, const bool strict = true) + { + (void)detail::is_sax_static_asserts {}; + const bool result = sax_parse_internal(sax); + + // strict mode: next byte must be EOF + if (result and strict and (get_token() != token_type::end_of_input)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_of_input, "value"))); + } + + return result; + } + + private: + template + bool sax_parse_internal(SAX* sax) + { + // stack to remember the hierarchy of structured values we are parsing + // true = array; false = object + std::vector states; + // value to avoid a goto (see comment where set to true) + bool skip_to_state_evaluation = false; + + while (true) + { + if (not skip_to_state_evaluation) + { + // invariant: get_token() was called before each iteration + switch (last_token) + { + case token_type::begin_object: + { + if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1)))) + { + return false; + } + + // closing } -> we are done + if (get_token() == token_type::end_object) + { + if (JSON_UNLIKELY(not sax->end_object())) + { + return false; + } + break; + } + + // parse key + if (JSON_UNLIKELY(last_token != token_type::value_string)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::value_string, "object key"))); + } + if (JSON_UNLIKELY(not sax->key(m_lexer.get_string()))) + { + return false; + } + + // parse separator (:) + if (JSON_UNLIKELY(get_token() != token_type::name_separator)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::name_separator, "object separator"))); + } + + // remember we are now inside an object + states.push_back(false); + + // parse values + get_token(); + continue; + } + + case token_type::begin_array: + { + if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1)))) + { + return false; + } + + // closing ] -> we are done + if (get_token() == token_type::end_array) + { + if (JSON_UNLIKELY(not sax->end_array())) + { + return false; + } + break; + } + + // remember we are now inside an array + states.push_back(true); + + // parse values (no need to call get_token) + continue; + } + + case token_type::value_float: + { + const auto res = m_lexer.get_number_float(); + + if (JSON_UNLIKELY(not std::isfinite(res))) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'")); + } + + if (JSON_UNLIKELY(not sax->number_float(res, m_lexer.get_string()))) + { + return false; + } + + break; + } + + case token_type::literal_false: + { + if (JSON_UNLIKELY(not sax->boolean(false))) + { + return false; + } + break; + } + + case token_type::literal_null: + { + if (JSON_UNLIKELY(not sax->null())) + { + return false; + } + break; + } + + case token_type::literal_true: + { + if (JSON_UNLIKELY(not sax->boolean(true))) + { + return false; + } + break; + } + + case token_type::value_integer: + { + if (JSON_UNLIKELY(not sax->number_integer(m_lexer.get_number_integer()))) + { + return false; + } + break; + } + + case token_type::value_string: + { + if (JSON_UNLIKELY(not sax->string(m_lexer.get_string()))) + { + return false; + } + break; + } + + case token_type::value_unsigned: + { + if (JSON_UNLIKELY(not sax->number_unsigned(m_lexer.get_number_unsigned()))) + { + return false; + } + break; + } + + case token_type::parse_error: + { + // using "uninitialized" to avoid "expected" message + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::uninitialized, "value"))); + } + + default: // the last token was unexpected + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::literal_or_value, "value"))); + } + } + } + else + { + skip_to_state_evaluation = false; + } + + // we reached this line after we successfully parsed a value + if (states.empty()) + { + // empty stack: we reached the end of the hierarchy: done + return true; + } + + if (states.back()) // array + { + // comma -> next value + if (get_token() == token_type::value_separator) + { + // parse a new value + get_token(); + continue; + } + + // closing ] + if (JSON_LIKELY(last_token == token_type::end_array)) + { + if (JSON_UNLIKELY(not sax->end_array())) + { + return false; + } + + // We are done with this array. Before we can parse a + // new value, we need to evaluate the new state first. + // By setting skip_to_state_evaluation to false, we + // are effectively jumping to the beginning of this if. + assert(not states.empty()); + states.pop_back(); + skip_to_state_evaluation = true; + continue; + } + + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_array, "array"))); + } + else // object + { + // comma -> next value + if (get_token() == token_type::value_separator) + { + // parse key + if (JSON_UNLIKELY(get_token() != token_type::value_string)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::value_string, "object key"))); + } + + if (JSON_UNLIKELY(not sax->key(m_lexer.get_string()))) + { + return false; + } + + // parse separator (:) + if (JSON_UNLIKELY(get_token() != token_type::name_separator)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::name_separator, "object separator"))); + } + + // parse values + get_token(); + continue; + } + + // closing } + if (JSON_LIKELY(last_token == token_type::end_object)) + { + if (JSON_UNLIKELY(not sax->end_object())) + { + return false; + } + + // We are done with this object. Before we can parse a + // new value, we need to evaluate the new state first. + // By setting skip_to_state_evaluation to false, we + // are effectively jumping to the beginning of this if. + assert(not states.empty()); + states.pop_back(); + skip_to_state_evaluation = true; + continue; + } + + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_object, "object"))); + } + } + } + + /// get next token from lexer + token_type get_token() + { + return last_token = m_lexer.scan(); + } + + std::string exception_message(const token_type expected, const std::string& context) + { + std::string error_msg = "syntax error "; + + if (not context.empty()) + { + error_msg += "while parsing " + context + " "; + } + + error_msg += "- "; + + if (last_token == token_type::parse_error) + { + error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" + + m_lexer.get_token_string() + "'"; + } + else + { + error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token)); + } + + if (expected != token_type::uninitialized) + { + error_msg += "; expected " + std::string(lexer_t::token_type_name(expected)); + } + + return error_msg; + } + + private: + /// callback function + const parser_callback_t callback = nullptr; + /// the type of the last read token + token_type last_token = token_type::uninitialized; + /// the lexer + lexer_t m_lexer; + /// whether to throw exceptions in case of errors + const bool allow_exceptions = true; +}; +} // namespace detail +} // namespace nlohmann diff --git a/nlohmann/detail/input/position_t.hpp b/nlohmann/detail/input/position_t.hpp new file mode 100644 index 0000000000..14e9649fb2 --- /dev/null +++ b/nlohmann/detail/input/position_t.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include // size_t + +namespace nlohmann +{ +namespace detail +{ +/// struct to capture the start position of the current token +struct position_t +{ + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; + + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const + { + return chars_read_total; + } +}; + +} // namespace detail +} // namespace nlohmann diff --git a/nlohmann/detail/iterators/internal_iterator.hpp b/nlohmann/detail/iterators/internal_iterator.hpp new file mode 100644 index 0000000000..2c81f723fd --- /dev/null +++ b/nlohmann/detail/iterators/internal_iterator.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include + +namespace nlohmann +{ +namespace detail +{ +/*! +@brief an iterator value + +@note This structure could easily be a union, but MSVC currently does not allow +unions members with complex constructors, see https://github.com/nlohmann/json/pull/105. +*/ +template struct internal_iterator +{ + /// iterator for JSON objects + typename BasicJsonType::object_t::iterator object_iterator {}; + /// iterator for JSON arrays + typename BasicJsonType::array_t::iterator array_iterator {}; + /// generic iterator for all other types + primitive_iterator_t primitive_iterator {}; +}; +} // namespace detail +} // namespace nlohmann diff --git a/nlohmann/detail/iterators/iter_impl.hpp b/nlohmann/detail/iterators/iter_impl.hpp new file mode 100644 index 0000000000..0b0282c296 --- /dev/null +++ b/nlohmann/detail/iterators/iter_impl.hpp @@ -0,0 +1,613 @@ +#pragma once + +#include // not +#include // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next +#include // conditional, is_const, remove_const + +#include +#include +#include +#include +#include +#include +#include + +namespace nlohmann +{ +namespace detail +{ +// forward declare, to be able to friend it later on +template class iteration_proxy; +template class iteration_proxy_value; + +/*! +@brief a template for a bidirectional iterator for the @ref basic_json class +This class implements a both iterators (iterator and const_iterator) for the +@ref basic_json class. +@note An iterator is called *initialized* when a pointer to a JSON value has + been set (e.g., by a constructor or a copy assignment). If the iterator is + default-constructed, it is *uninitialized* and most methods are undefined. + **The library uses assertions to detect calls on uninitialized iterators.** +@requirement The class satisfies the following concept requirements: +- +[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): + The iterator that can be moved can be moved in both directions (i.e. + incremented and decremented). +@since version 1.0.0, simplified in version 2.0.9, change to bidirectional + iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593) +*/ +template +class iter_impl +{ + /// allow basic_json to access private members + friend iter_impl::value, typename std::remove_const::type, const BasicJsonType>::type>; + friend BasicJsonType; + friend iteration_proxy; + friend iteration_proxy_value; + + using object_t = typename BasicJsonType::object_t; + using array_t = typename BasicJsonType::array_t; + // make sure BasicJsonType is basic_json or const basic_json + static_assert(is_basic_json::type>::value, + "iter_impl only accepts (const) basic_json"); + + public: + + /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17. + /// The C++ Standard has never required user-defined iterators to derive from std::iterator. + /// A user-defined iterator should provide publicly accessible typedefs named + /// iterator_category, value_type, difference_type, pointer, and reference. + /// Note that value_type is required to be non-const, even for constant iterators. + using iterator_category = std::bidirectional_iterator_tag; + + /// the type of the values when the iterator is dereferenced + using value_type = typename BasicJsonType::value_type; + /// a type to represent differences between iterators + using difference_type = typename BasicJsonType::difference_type; + /// defines a pointer to the type iterated over (value_type) + using pointer = typename std::conditional::value, + typename BasicJsonType::const_pointer, + typename BasicJsonType::pointer>::type; + /// defines a reference to the type iterated over (value_type) + using reference = + typename std::conditional::value, + typename BasicJsonType::const_reference, + typename BasicJsonType::reference>::type; + + /// default constructor + iter_impl() = default; + + /*! + @brief constructor for a given JSON instance + @param[in] object pointer to a JSON object for this iterator + @pre object != nullptr + @post The iterator is initialized; i.e. `m_object != nullptr`. + */ + explicit iter_impl(pointer object) noexcept : m_object(object) + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + m_it.object_iterator = typename object_t::iterator(); + break; + } + + case value_t::array: + { + m_it.array_iterator = typename array_t::iterator(); + break; + } + + default: + { + m_it.primitive_iterator = primitive_iterator_t(); + break; + } + } + } + + /*! + @note The conventional copy constructor and copy assignment are implicitly + defined. Combined with the following converting constructor and + assignment, they support: (1) copy from iterator to iterator, (2) + copy from const iterator to const iterator, and (3) conversion from + iterator to const iterator. However conversion from const iterator + to iterator is not defined. + */ + + /*! + @brief converting constructor + @param[in] other non-const iterator to copy from + @note It is not checked whether @a other is initialized. + */ + iter_impl(const iter_impl::type>& other) noexcept + : m_object(other.m_object), m_it(other.m_it) {} + + /*! + @brief converting assignment + @param[in,out] other non-const iterator to copy from + @return const/non-const iterator + @note It is not checked whether @a other is initialized. + */ + iter_impl& operator=(const iter_impl::type>& other) noexcept + { + m_object = other.m_object; + m_it = other.m_it; + return *this; + } + + private: + /*! + @brief set the iterator to the first value + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + void set_begin() noexcept + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + m_it.object_iterator = m_object->m_value.object->begin(); + break; + } + + case value_t::array: + { + m_it.array_iterator = m_object->m_value.array->begin(); + break; + } + + case value_t::null: + { + // set to end so begin()==end() is true: null is empty + m_it.primitive_iterator.set_end(); + break; + } + + default: + { + m_it.primitive_iterator.set_begin(); + break; + } + } + } + + /*! + @brief set the iterator past the last value + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + void set_end() noexcept + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + m_it.object_iterator = m_object->m_value.object->end(); + break; + } + + case value_t::array: + { + m_it.array_iterator = m_object->m_value.array->end(); + break; + } + + default: + { + m_it.primitive_iterator.set_end(); + break; + } + } + } + + public: + /*! + @brief return a reference to the value pointed to by the iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + reference operator*() const + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + assert(m_it.object_iterator != m_object->m_value.object->end()); + return m_it.object_iterator->second; + } + + case value_t::array: + { + assert(m_it.array_iterator != m_object->m_value.array->end()); + return *m_it.array_iterator; + } + + case value_t::null: + JSON_THROW(invalid_iterator::create(214, "cannot get value")); + + default: + { + if (JSON_LIKELY(m_it.primitive_iterator.is_begin())) + { + return *m_object; + } + + JSON_THROW(invalid_iterator::create(214, "cannot get value")); + } + } + } + + /*! + @brief dereference the iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + pointer operator->() const + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + assert(m_it.object_iterator != m_object->m_value.object->end()); + return &(m_it.object_iterator->second); + } + + case value_t::array: + { + assert(m_it.array_iterator != m_object->m_value.array->end()); + return &*m_it.array_iterator; + } + + default: + { + if (JSON_LIKELY(m_it.primitive_iterator.is_begin())) + { + return m_object; + } + + JSON_THROW(invalid_iterator::create(214, "cannot get value")); + } + } + } + + /*! + @brief post-increment (it++) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl const operator++(int) + { + auto result = *this; + ++(*this); + return result; + } + + /*! + @brief pre-increment (++it) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator++() + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + std::advance(m_it.object_iterator, 1); + break; + } + + case value_t::array: + { + std::advance(m_it.array_iterator, 1); + break; + } + + default: + { + ++m_it.primitive_iterator; + break; + } + } + + return *this; + } + + /*! + @brief post-decrement (it--) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl const operator--(int) + { + auto result = *this; + --(*this); + return result; + } + + /*! + @brief pre-decrement (--it) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator--() + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + std::advance(m_it.object_iterator, -1); + break; + } + + case value_t::array: + { + std::advance(m_it.array_iterator, -1); + break; + } + + default: + { + --m_it.primitive_iterator; + break; + } + } + + return *this; + } + + /*! + @brief comparison: equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator==(const iter_impl& other) const + { + // if objects are not the same, the comparison is undefined + if (JSON_UNLIKELY(m_object != other.m_object)) + { + JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers")); + } + + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + return (m_it.object_iterator == other.m_it.object_iterator); + + case value_t::array: + return (m_it.array_iterator == other.m_it.array_iterator); + + default: + return (m_it.primitive_iterator == other.m_it.primitive_iterator); + } + } + + /*! + @brief comparison: not equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator!=(const iter_impl& other) const + { + return not operator==(other); + } + + /*! + @brief comparison: smaller + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator<(const iter_impl& other) const + { + // if objects are not the same, the comparison is undefined + if (JSON_UNLIKELY(m_object != other.m_object)) + { + JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers")); + } + + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators")); + + case value_t::array: + return (m_it.array_iterator < other.m_it.array_iterator); + + default: + return (m_it.primitive_iterator < other.m_it.primitive_iterator); + } + } + + /*! + @brief comparison: less than or equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator<=(const iter_impl& other) const + { + return not other.operator < (*this); + } + + /*! + @brief comparison: greater than + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator>(const iter_impl& other) const + { + return not operator<=(other); + } + + /*! + @brief comparison: greater than or equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator>=(const iter_impl& other) const + { + return not operator<(other); + } + + /*! + @brief add to iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator+=(difference_type i) + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); + + case value_t::array: + { + std::advance(m_it.array_iterator, i); + break; + } + + default: + { + m_it.primitive_iterator += i; + break; + } + } + + return *this; + } + + /*! + @brief subtract from iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator-=(difference_type i) + { + return operator+=(-i); + } + + /*! + @brief add to iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl operator+(difference_type i) const + { + auto result = *this; + result += i; + return result; + } + + /*! + @brief addition of distance and iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + friend iter_impl operator+(difference_type i, const iter_impl& it) + { + auto result = it; + result += i; + return result; + } + + /*! + @brief subtract from iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl operator-(difference_type i) const + { + auto result = *this; + result -= i; + return result; + } + + /*! + @brief return difference + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + difference_type operator-(const iter_impl& other) const + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); + + case value_t::array: + return m_it.array_iterator - other.m_it.array_iterator; + + default: + return m_it.primitive_iterator - other.m_it.primitive_iterator; + } + } + + /*! + @brief access to successor + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + reference operator[](difference_type n) const + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators")); + + case value_t::array: + return *std::next(m_it.array_iterator, n); + + case value_t::null: + JSON_THROW(invalid_iterator::create(214, "cannot get value")); + + default: + { + if (JSON_LIKELY(m_it.primitive_iterator.get_value() == -n)) + { + return *m_object; + } + + JSON_THROW(invalid_iterator::create(214, "cannot get value")); + } + } + } + + /*! + @brief return the key of an object iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + const typename object_t::key_type& key() const + { + assert(m_object != nullptr); + + if (JSON_LIKELY(m_object->is_object())) + { + return m_it.object_iterator->first; + } + + JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators")); + } + + /*! + @brief return the value of an iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + reference value() const + { + return operator*(); + } + + private: + /// associated JSON instance + pointer m_object = nullptr; + /// the actual iterator of the associated instance + internal_iterator::type> m_it {}; +}; +} // namespace detail +} // namespace nlohmann diff --git a/nlohmann/detail/iterators/iteration_proxy.hpp b/nlohmann/detail/iterators/iteration_proxy.hpp new file mode 100644 index 0000000000..da2e32b42e --- /dev/null +++ b/nlohmann/detail/iterators/iteration_proxy.hpp @@ -0,0 +1,170 @@ +#pragma once + +#include // size_t +#include // input_iterator_tag +#include // string, to_string +#include // tuple_size, get, tuple_element + +#include +#include + +namespace nlohmann +{ +namespace detail +{ +template class iteration_proxy_value +{ + public: + using difference_type = std::ptrdiff_t; + using value_type = iteration_proxy_value; + using pointer = value_type * ; + using reference = value_type & ; + using iterator_category = std::input_iterator_tag; + + private: + /// the iterator + IteratorType anchor; + /// an index for arrays (used to create key names) + std::size_t array_index = 0; + /// last stringified array index + mutable std::size_t array_index_last = 0; + /// a string representation of the array index + mutable std::string array_index_str = "0"; + /// an empty string (to return a reference for primitive values) + const std::string empty_str = ""; + + public: + explicit iteration_proxy_value(IteratorType it) noexcept : anchor(it) {} + + /// dereference operator (needed for range-based for) + iteration_proxy_value& operator*() + { + return *this; + } + + /// increment operator (needed for range-based for) + iteration_proxy_value& operator++() + { + ++anchor; + ++array_index; + + return *this; + } + + /// equality operator (needed for InputIterator) + bool operator==(const iteration_proxy_value& o) const + { + return anchor == o.anchor; + } + + /// inequality operator (needed for range-based for) + bool operator!=(const iteration_proxy_value& o) const + { + return anchor != o.anchor; + } + + /// return key of the iterator + const std::string& key() const + { + assert(anchor.m_object != nullptr); + + switch (anchor.m_object->type()) + { + // use integer array index as key + case value_t::array: + { + if (array_index != array_index_last) + { + array_index_str = std::to_string(array_index); + array_index_last = array_index; + } + return array_index_str; + } + + // use key from the object + case value_t::object: + return anchor.key(); + + // use an empty key for all primitive types + default: + return empty_str; + } + } + + /// return value of the iterator + typename IteratorType::reference value() const + { + return anchor.value(); + } +}; + +/// proxy class for the items() function +template class iteration_proxy +{ + private: + /// the container to iterate + typename IteratorType::reference container; + + public: + /// construct iteration proxy from a container + explicit iteration_proxy(typename IteratorType::reference cont) noexcept + : container(cont) {} + + /// return iterator begin (needed for range-based for) + iteration_proxy_value begin() noexcept + { + return iteration_proxy_value(container.begin()); + } + + /// return iterator end (needed for range-based for) + iteration_proxy_value end() noexcept + { + return iteration_proxy_value(container.end()); + } +}; +// Structured Bindings Support +// For further reference see https://blog.tartanllama.xyz/structured-bindings/ +// And see https://github.com/nlohmann/json/pull/1391 +template = 0> +auto get(const nlohmann::detail::iteration_proxy_value& i) -> decltype(i.key()) +{ + return i.key(); +} +// Structured Bindings Support +// For further reference see https://blog.tartanllama.xyz/structured-bindings/ +// And see https://github.com/nlohmann/json/pull/1391 +template = 0> +auto get(const nlohmann::detail::iteration_proxy_value& i) -> decltype(i.value()) +{ + return i.value(); +} +} // namespace detail +} // namespace nlohmann + +// The Addition to the STD Namespace is required to add +// Structured Bindings Support to the iteration_proxy_value class +// For further reference see https://blog.tartanllama.xyz/structured-bindings/ +// And see https://github.com/nlohmann/json/pull/1391 +namespace std +{ +#if defined(__clang__) + // Fix: https://github.com/nlohmann/json/issues/1401 + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wmismatched-tags" +#endif +template +class tuple_size<::nlohmann::detail::iteration_proxy_value> + : public std::integral_constant {}; + +template +class tuple_element> +{ + public: + using type = decltype( + get(std::declval < + ::nlohmann::detail::iteration_proxy_value> ())); +}; +#if defined(__clang__) + #pragma clang diagnostic pop +#endif +} // namespace std diff --git a/nlohmann/detail/iterators/iterator_traits.hpp b/nlohmann/detail/iterators/iterator_traits.hpp new file mode 100644 index 0000000000..9806be8c89 --- /dev/null +++ b/nlohmann/detail/iterators/iterator_traits.hpp @@ -0,0 +1,49 @@ +#pragma once + +#include // random_access_iterator_tag + +#include +#include + +namespace nlohmann +{ +namespace detail +{ +template +struct iterator_types {}; + +template +struct iterator_types< + It, + void_t> { + using difference_type = typename It::difference_type; + using value_type = typename It::value_type; + using pointer = typename It::pointer; + using reference = typename It::reference; + using iterator_category = typename It::iterator_category; +}; + +// This is required as some compilers implement std::iterator_traits in a way that +// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. +template +struct iterator_traits +{ +}; + +template +struct iterator_traits::value>> + : iterator_types +{ +}; + +template +struct iterator_traits::value>> { + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using difference_type = ptrdiff_t; + using pointer = T*; + using reference = T&; +}; +} // namespace detail +} // namespace nlohmann diff --git a/nlohmann/detail/iterators/json_reverse_iterator.hpp b/nlohmann/detail/iterators/json_reverse_iterator.hpp new file mode 100644 index 0000000000..f3b5b5db6b --- /dev/null +++ b/nlohmann/detail/iterators/json_reverse_iterator.hpp @@ -0,0 +1,119 @@ +#pragma once + +#include // ptrdiff_t +#include // reverse_iterator +#include // declval + +namespace nlohmann +{ +namespace detail +{ +////////////////////// +// reverse_iterator // +////////////////////// + +/*! +@brief a template for a reverse iterator class + +@tparam Base the base iterator type to reverse. Valid types are @ref +iterator (to create @ref reverse_iterator) and @ref const_iterator (to +create @ref const_reverse_iterator). + +@requirement The class satisfies the following concept requirements: +- +[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): + The iterator that can be moved can be moved in both directions (i.e. + incremented and decremented). +- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator): + It is possible to write to the pointed-to element (only if @a Base is + @ref iterator). + +@since version 1.0.0 +*/ +template +class json_reverse_iterator : public std::reverse_iterator +{ + public: + using difference_type = std::ptrdiff_t; + /// shortcut to the reverse iterator adapter + using base_iterator = std::reverse_iterator; + /// the reference type for the pointed-to element + using reference = typename Base::reference; + + /// create reverse iterator from iterator + explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept + : base_iterator(it) {} + + /// create reverse iterator from base class + explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {} + + /// post-increment (it++) + json_reverse_iterator const operator++(int) + { + return static_cast(base_iterator::operator++(1)); + } + + /// pre-increment (++it) + json_reverse_iterator& operator++() + { + return static_cast(base_iterator::operator++()); + } + + /// post-decrement (it--) + json_reverse_iterator const operator--(int) + { + return static_cast(base_iterator::operator--(1)); + } + + /// pre-decrement (--it) + json_reverse_iterator& operator--() + { + return static_cast(base_iterator::operator--()); + } + + /// add to iterator + json_reverse_iterator& operator+=(difference_type i) + { + return static_cast(base_iterator::operator+=(i)); + } + + /// add to iterator + json_reverse_iterator operator+(difference_type i) const + { + return static_cast(base_iterator::operator+(i)); + } + + /// subtract from iterator + json_reverse_iterator operator-(difference_type i) const + { + return static_cast(base_iterator::operator-(i)); + } + + /// return difference + difference_type operator-(const json_reverse_iterator& other) const + { + return base_iterator(*this) - base_iterator(other); + } + + /// access to successor + reference operator[](difference_type n) const + { + return *(this->operator+(n)); + } + + /// return the key of an object iterator + auto key() const -> decltype(std::declval().key()) + { + auto it = --this->base(); + return it.key(); + } + + /// return the value of an iterator + reference value() const + { + auto it = --this->base(); + return it.operator * (); + } +}; +} // namespace detail +} // namespace nlohmann diff --git a/nlohmann/detail/iterators/primitive_iterator.hpp b/nlohmann/detail/iterators/primitive_iterator.hpp new file mode 100644 index 0000000000..28d6f1a65d --- /dev/null +++ b/nlohmann/detail/iterators/primitive_iterator.hpp @@ -0,0 +1,120 @@ +#pragma once + +#include // ptrdiff_t +#include // numeric_limits + +namespace nlohmann +{ +namespace detail +{ +/* +@brief an iterator for primitive JSON types + +This class models an iterator for primitive JSON types (boolean, number, +string). It's only purpose is to allow the iterator/const_iterator classes +to "iterate" over primitive values. Internally, the iterator is modeled by +a `difference_type` variable. Value begin_value (`0`) models the begin, +end_value (`1`) models past the end. +*/ +class primitive_iterator_t +{ + private: + using difference_type = std::ptrdiff_t; + static constexpr difference_type begin_value = 0; + static constexpr difference_type end_value = begin_value + 1; + + /// iterator as signed integer type + difference_type m_it = (std::numeric_limits::min)(); + + public: + constexpr difference_type get_value() const noexcept + { + return m_it; + } + + /// set iterator to a defined beginning + void set_begin() noexcept + { + m_it = begin_value; + } + + /// set iterator to a defined past the end + void set_end() noexcept + { + m_it = end_value; + } + + /// return whether the iterator can be dereferenced + constexpr bool is_begin() const noexcept + { + return m_it == begin_value; + } + + /// return whether the iterator is at end + constexpr bool is_end() const noexcept + { + return m_it == end_value; + } + + friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + { + return lhs.m_it == rhs.m_it; + } + + friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + { + return lhs.m_it < rhs.m_it; + } + + primitive_iterator_t operator+(difference_type n) noexcept + { + auto result = *this; + result += n; + return result; + } + + friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + { + return lhs.m_it - rhs.m_it; + } + + primitive_iterator_t& operator++() noexcept + { + ++m_it; + return *this; + } + + primitive_iterator_t const operator++(int) noexcept + { + auto result = *this; + ++m_it; + return result; + } + + primitive_iterator_t& operator--() noexcept + { + --m_it; + return *this; + } + + primitive_iterator_t const operator--(int) noexcept + { + auto result = *this; + --m_it; + return result; + } + + primitive_iterator_t& operator+=(difference_type n) noexcept + { + m_it += n; + return *this; + } + + primitive_iterator_t& operator-=(difference_type n) noexcept + { + m_it -= n; + return *this; + } +}; +} // namespace detail +} // namespace nlohmann diff --git a/nlohmann/detail/json_pointer.hpp b/nlohmann/detail/json_pointer.hpp new file mode 100644 index 0000000000..465e51658e --- /dev/null +++ b/nlohmann/detail/json_pointer.hpp @@ -0,0 +1,939 @@ +#pragma once + +#include // all_of +#include // assert +#include // accumulate +#include // string +#include // move +#include // vector + +#include +#include +#include + +namespace nlohmann +{ +template +class json_pointer +{ + // allow basic_json to access private members + NLOHMANN_BASIC_JSON_TPL_DECLARATION + friend class basic_json; + + public: + /*! + @brief create JSON pointer + + Create a JSON pointer according to the syntax described in + [Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3). + + @param[in] s string representing the JSON pointer; if omitted, the empty + string is assumed which references the whole JSON value + + @throw parse_error.107 if the given JSON pointer @a s is nonempty and does + not begin with a slash (`/`); see example below + + @throw parse_error.108 if a tilde (`~`) in the given JSON pointer @a s is + not followed by `0` (representing `~`) or `1` (representing `/`); see + example below + + @liveexample{The example shows the construction several valid JSON pointers + as well as the exceptional behavior.,json_pointer} + + @since version 2.0.0 + */ + explicit json_pointer(const std::string& s = "") + : reference_tokens(split(s)) + {} + + /*! + @brief return a string representation of the JSON pointer + + @invariant For each JSON pointer `ptr`, it holds: + @code {.cpp} + ptr == json_pointer(ptr.to_string()); + @endcode + + @return a string representation of the JSON pointer + + @liveexample{The example shows the result of `to_string`.,json_pointer__to_string} + + @since version 2.0.0 + */ + std::string to_string() const + { + return std::accumulate(reference_tokens.begin(), reference_tokens.end(), + std::string{}, + [](const std::string & a, const std::string & b) + { + return a + "/" + escape(b); + }); + } + + /// @copydoc to_string() + operator std::string() const + { + return to_string(); + } + + /*! + @brief append another JSON pointer at the end of this JSON pointer + + @param[in] ptr JSON pointer to append + @return JSON pointer with @a ptr appended + + @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add} + + @complexity Linear in the length of @a ptr. + + @sa @ref operator/=(std::string) to append a reference token + @sa @ref operator/=(std::size_t) to append an array index + @sa @ref operator/(const json_pointer&, const json_pointer&) for a binary operator + + @since version 3.6.0 + */ + json_pointer& operator/=(const json_pointer& ptr) + { + reference_tokens.insert(reference_tokens.end(), + ptr.reference_tokens.begin(), + ptr.reference_tokens.end()); + return *this; + } + + /*! + @brief append an unescaped reference token at the end of this JSON pointer + + @param[in] token reference token to append + @return JSON pointer with @a token appended without escaping @a token + + @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add} + + @complexity Amortized constant. + + @sa @ref operator/=(const json_pointer&) to append a JSON pointer + @sa @ref operator/=(std::size_t) to append an array index + @sa @ref operator/(const json_pointer&, std::size_t) for a binary operator + + @since version 3.6.0 + */ + json_pointer& operator/=(std::string token) + { + push_back(std::move(token)); + return *this; + } + + /*! + @brief append an array index at the end of this JSON pointer + + @param[in] array_index array index ot append + @return JSON pointer with @a array_index appended + + @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add} + + @complexity Amortized constant. + + @sa @ref operator/=(const json_pointer&) to append a JSON pointer + @sa @ref operator/=(std::string) to append a reference token + @sa @ref operator/(const json_pointer&, std::string) for a binary operator + + @since version 3.6.0 + */ + json_pointer& operator/=(std::size_t array_index) + { + return *this /= std::to_string(array_index); + } + + /*! + @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer + + @param[in] lhs JSON pointer + @param[in] rhs JSON pointer + @return a new JSON pointer with @a rhs appended to @a lhs + + @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary} + + @complexity Linear in the length of @a lhs and @a rhs. + + @sa @ref operator/=(const json_pointer&) to append a JSON pointer + + @since version 3.6.0 + */ + friend json_pointer operator/(const json_pointer& lhs, + const json_pointer& rhs) + { + return json_pointer(lhs) /= rhs; + } + + /*! + @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer + + @param[in] ptr JSON pointer + @param[in] token reference token + @return a new JSON pointer with unescaped @a token appended to @a ptr + + @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary} + + @complexity Linear in the length of @a ptr. + + @sa @ref operator/=(std::string) to append a reference token + + @since version 3.6.0 + */ + friend json_pointer operator/(const json_pointer& ptr, std::string token) + { + return json_pointer(ptr) /= std::move(token); + } + + /*! + @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer + + @param[in] ptr JSON pointer + @param[in] array_index array index + @return a new JSON pointer with @a array_index appended to @a ptr + + @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary} + + @complexity Linear in the length of @a ptr. + + @sa @ref operator/=(std::size_t) to append an array index + + @since version 3.6.0 + */ + friend json_pointer operator/(const json_pointer& ptr, std::size_t array_index) + { + return json_pointer(ptr) /= array_index; + } + + /*! + @brief returns the parent of this JSON pointer + + @return parent of this JSON pointer; in case this JSON pointer is the root, + the root itself is returned + + @complexity Linear in the length of the JSON pointer. + + @liveexample{The example shows the result of `parent_pointer` for different + JSON Pointers.,json_pointer__parent_pointer} + + @since version 3.6.0 + */ + json_pointer parent_pointer() const + { + if (empty()) + { + return *this; + } + + json_pointer res = *this; + res.pop_back(); + return res; + } + + /*! + @brief remove last reference token + + @pre not `empty()` + + @liveexample{The example shows the usage of `pop_back`.,json_pointer__pop_back} + + @complexity Constant. + + @throw out_of_range.405 if JSON pointer has no parent + + @since version 3.6.0 + */ + void pop_back() + { + if (JSON_UNLIKELY(empty())) + { + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); + } + + reference_tokens.pop_back(); + } + + /*! + @brief return last reference token + + @pre not `empty()` + @return last reference token + + @liveexample{The example shows the usage of `back`.,json_pointer__back} + + @complexity Constant. + + @throw out_of_range.405 if JSON pointer has no parent + + @since version 3.6.0 + */ + const std::string& back() + { + if (JSON_UNLIKELY(empty())) + { + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); + } + + return reference_tokens.back(); + } + + /*! + @brief append an unescaped token at the end of the reference pointer + + @param[in] token token to add + + @complexity Amortized constant. + + @liveexample{The example shows the result of `push_back` for different + JSON Pointers.,json_pointer__push_back} + + @since version 3.6.0 + */ + void push_back(const std::string& token) + { + reference_tokens.push_back(token); + } + + /// @copydoc push_back(const std::string&) + void push_back(std::string&& token) + { + reference_tokens.push_back(std::move(token)); + } + + /*! + @brief return whether pointer points to the root document + + @return true iff the JSON pointer points to the root document + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + + @liveexample{The example shows the result of `empty` for different JSON + Pointers.,json_pointer__empty} + + @since version 3.6.0 + */ + bool empty() const noexcept + { + return reference_tokens.empty(); + } + + private: + /*! + @param[in] s reference token to be converted into an array index + + @return integer representation of @a s + + @throw out_of_range.404 if string @a s could not be converted to an integer + */ + static int array_index(const std::string& s) + { + std::size_t processed_chars = 0; + const int res = std::stoi(s, &processed_chars); + + // check if the string was completely read + if (JSON_UNLIKELY(processed_chars != s.size())) + { + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'")); + } + + return res; + } + + json_pointer top() const + { + if (JSON_UNLIKELY(empty())) + { + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); + } + + json_pointer result = *this; + result.reference_tokens = {reference_tokens[0]}; + return result; + } + + /*! + @brief create and return a reference to the pointed to value + + @complexity Linear in the number of reference tokens. + + @throw parse_error.109 if array index is not a number + @throw type_error.313 if value cannot be unflattened + */ + BasicJsonType& get_and_create(BasicJsonType& j) const + { + using size_type = typename BasicJsonType::size_type; + auto result = &j; + + // in case no reference tokens exist, return a reference to the JSON value + // j which will be overwritten by a primitive value + for (const auto& reference_token : reference_tokens) + { + switch (result->m_type) + { + case detail::value_t::null: + { + if (reference_token == "0") + { + // start a new array if reference token is 0 + result = &result->operator[](0); + } + else + { + // start a new object otherwise + result = &result->operator[](reference_token); + } + break; + } + + case detail::value_t::object: + { + // create an entry in the object + result = &result->operator[](reference_token); + break; + } + + case detail::value_t::array: + { + // create an entry in the array + JSON_TRY + { + result = &result->operator[](static_cast(array_index(reference_token))); + } + JSON_CATCH(std::invalid_argument&) + { + JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); + } + break; + } + + /* + The following code is only reached if there exists a reference + token _and_ the current value is primitive. In this case, we have + an error situation, because primitive values may only occur as + single value; that is, with an empty list of reference tokens. + */ + default: + JSON_THROW(detail::type_error::create(313, "invalid value to unflatten")); + } + } + + return *result; + } + + /*! + @brief return a reference to the pointed to value + + @note This version does not throw if a value is not present, but tries to + create nested values instead. For instance, calling this function + with pointer `"/this/that"` on a null value is equivalent to calling + `operator[]("this").operator[]("that")` on that value, effectively + changing the null value to an object. + + @param[in] ptr a JSON value + + @return reference to the JSON value pointed to by the JSON pointer + + @complexity Linear in the length of the JSON pointer. + + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + BasicJsonType& get_unchecked(BasicJsonType* ptr) const + { + using size_type = typename BasicJsonType::size_type; + for (const auto& reference_token : reference_tokens) + { + // convert null values to arrays or objects before continuing + if (ptr->m_type == detail::value_t::null) + { + // check if reference token is a number + const bool nums = + std::all_of(reference_token.begin(), reference_token.end(), + [](const char x) + { + return x >= '0' and x <= '9'; + }); + + // change value to array for numbers or "-" or to object otherwise + *ptr = (nums or reference_token == "-") + ? detail::value_t::array + : detail::value_t::object; + } + + switch (ptr->m_type) + { + case detail::value_t::object: + { + // use unchecked object access + ptr = &ptr->operator[](reference_token); + break; + } + + case detail::value_t::array: + { + // error condition (cf. RFC 6901, Sect. 4) + if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0')) + { + JSON_THROW(detail::parse_error::create(106, 0, + "array index '" + reference_token + + "' must not begin with '0'")); + } + + if (reference_token == "-") + { + // explicitly treat "-" as index beyond the end + ptr = &ptr->operator[](ptr->m_value.array->size()); + } + else + { + // convert array index to number; unchecked access + JSON_TRY + { + ptr = &ptr->operator[]( + static_cast(array_index(reference_token))); + } + JSON_CATCH(std::invalid_argument&) + { + JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); + } + } + break; + } + + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); + } + } + + return *ptr; + } + + /*! + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.402 if the array index '-' is used + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + BasicJsonType& get_checked(BasicJsonType* ptr) const + { + using size_type = typename BasicJsonType::size_type; + for (const auto& reference_token : reference_tokens) + { + switch (ptr->m_type) + { + case detail::value_t::object: + { + // note: at performs range check + ptr = &ptr->at(reference_token); + break; + } + + case detail::value_t::array: + { + if (JSON_UNLIKELY(reference_token == "-")) + { + // "-" always fails the range check + JSON_THROW(detail::out_of_range::create(402, + "array index '-' (" + std::to_string(ptr->m_value.array->size()) + + ") is out of range")); + } + + // error condition (cf. RFC 6901, Sect. 4) + if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0')) + { + JSON_THROW(detail::parse_error::create(106, 0, + "array index '" + reference_token + + "' must not begin with '0'")); + } + + // note: at performs range check + JSON_TRY + { + ptr = &ptr->at(static_cast(array_index(reference_token))); + } + JSON_CATCH(std::invalid_argument&) + { + JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); + } + break; + } + + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); + } + } + + return *ptr; + } + + /*! + @brief return a const reference to the pointed to value + + @param[in] ptr a JSON value + + @return const reference to the JSON value pointed to by the JSON + pointer + + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.402 if the array index '-' is used + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const + { + using size_type = typename BasicJsonType::size_type; + for (const auto& reference_token : reference_tokens) + { + switch (ptr->m_type) + { + case detail::value_t::object: + { + // use unchecked object access + ptr = &ptr->operator[](reference_token); + break; + } + + case detail::value_t::array: + { + if (JSON_UNLIKELY(reference_token == "-")) + { + // "-" cannot be used for const access + JSON_THROW(detail::out_of_range::create(402, + "array index '-' (" + std::to_string(ptr->m_value.array->size()) + + ") is out of range")); + } + + // error condition (cf. RFC 6901, Sect. 4) + if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0')) + { + JSON_THROW(detail::parse_error::create(106, 0, + "array index '" + reference_token + + "' must not begin with '0'")); + } + + // use unchecked array access + JSON_TRY + { + ptr = &ptr->operator[]( + static_cast(array_index(reference_token))); + } + JSON_CATCH(std::invalid_argument&) + { + JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); + } + break; + } + + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); + } + } + + return *ptr; + } + + /*! + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.402 if the array index '-' is used + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + const BasicJsonType& get_checked(const BasicJsonType* ptr) const + { + using size_type = typename BasicJsonType::size_type; + for (const auto& reference_token : reference_tokens) + { + switch (ptr->m_type) + { + case detail::value_t::object: + { + // note: at performs range check + ptr = &ptr->at(reference_token); + break; + } + + case detail::value_t::array: + { + if (JSON_UNLIKELY(reference_token == "-")) + { + // "-" always fails the range check + JSON_THROW(detail::out_of_range::create(402, + "array index '-' (" + std::to_string(ptr->m_value.array->size()) + + ") is out of range")); + } + + // error condition (cf. RFC 6901, Sect. 4) + if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0')) + { + JSON_THROW(detail::parse_error::create(106, 0, + "array index '" + reference_token + + "' must not begin with '0'")); + } + + // note: at performs range check + JSON_TRY + { + ptr = &ptr->at(static_cast(array_index(reference_token))); + } + JSON_CATCH(std::invalid_argument&) + { + JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); + } + break; + } + + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); + } + } + + return *ptr; + } + + /*! + @brief split the string input to reference tokens + + @note This function is only called by the json_pointer constructor. + All exceptions below are documented there. + + @throw parse_error.107 if the pointer is not empty or begins with '/' + @throw parse_error.108 if character '~' is not followed by '0' or '1' + */ + static std::vector split(const std::string& reference_string) + { + std::vector result; + + // special case: empty reference string -> no reference tokens + if (reference_string.empty()) + { + return result; + } + + // check if nonempty reference string begins with slash + if (JSON_UNLIKELY(reference_string[0] != '/')) + { + JSON_THROW(detail::parse_error::create(107, 1, + "JSON pointer must be empty or begin with '/' - was: '" + + reference_string + "'")); + } + + // extract the reference tokens: + // - slash: position of the last read slash (or end of string) + // - start: position after the previous slash + for ( + // search for the first slash after the first character + std::size_t slash = reference_string.find_first_of('/', 1), + // set the beginning of the first reference token + start = 1; + // we can stop if start == 0 (if slash == std::string::npos) + start != 0; + // set the beginning of the next reference token + // (will eventually be 0 if slash == std::string::npos) + start = (slash == std::string::npos) ? 0 : slash + 1, + // find next slash + slash = reference_string.find_first_of('/', start)) + { + // use the text between the beginning of the reference token + // (start) and the last slash (slash). + auto reference_token = reference_string.substr(start, slash - start); + + // check reference tokens are properly escaped + for (std::size_t pos = reference_token.find_first_of('~'); + pos != std::string::npos; + pos = reference_token.find_first_of('~', pos + 1)) + { + assert(reference_token[pos] == '~'); + + // ~ must be followed by 0 or 1 + if (JSON_UNLIKELY(pos == reference_token.size() - 1 or + (reference_token[pos + 1] != '0' and + reference_token[pos + 1] != '1'))) + { + JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'")); + } + } + + // finally, store the reference token + unescape(reference_token); + result.push_back(reference_token); + } + + return result; + } + + /*! + @brief replace all occurrences of a substring by another string + + @param[in,out] s the string to manipulate; changed so that all + occurrences of @a f are replaced with @a t + @param[in] f the substring to replace with @a t + @param[in] t the string to replace @a f + + @pre The search string @a f must not be empty. **This precondition is + enforced with an assertion.** + + @since version 2.0.0 + */ + static void replace_substring(std::string& s, const std::string& f, + const std::string& t) + { + assert(not f.empty()); + for (auto pos = s.find(f); // find first occurrence of f + pos != std::string::npos; // make sure f was found + s.replace(pos, f.size(), t), // replace with t, and + pos = s.find(f, pos + t.size())) // find next occurrence of f + {} + } + + /// escape "~" to "~0" and "/" to "~1" + static std::string escape(std::string s) + { + replace_substring(s, "~", "~0"); + replace_substring(s, "/", "~1"); + return s; + } + + /// unescape "~1" to tilde and "~0" to slash (order is important!) + static void unescape(std::string& s) + { + replace_substring(s, "~1", "/"); + replace_substring(s, "~0", "~"); + } + + /*! + @param[in] reference_string the reference string to the current value + @param[in] value the value to consider + @param[in,out] result the result object to insert values to + + @note Empty objects or arrays are flattened to `null`. + */ + static void flatten(const std::string& reference_string, + const BasicJsonType& value, + BasicJsonType& result) + { + switch (value.m_type) + { + case detail::value_t::array: + { + if (value.m_value.array->empty()) + { + // flatten empty array as null + result[reference_string] = nullptr; + } + else + { + // iterate array and use index as reference string + for (std::size_t i = 0; i < value.m_value.array->size(); ++i) + { + flatten(reference_string + "/" + std::to_string(i), + value.m_value.array->operator[](i), result); + } + } + break; + } + + case detail::value_t::object: + { + if (value.m_value.object->empty()) + { + // flatten empty object as null + result[reference_string] = nullptr; + } + else + { + // iterate object and use keys as reference string + for (const auto& element : *value.m_value.object) + { + flatten(reference_string + "/" + escape(element.first), element.second, result); + } + } + break; + } + + default: + { + // add primitive value with its reference string + result[reference_string] = value; + break; + } + } + } + + /*! + @param[in] value flattened JSON + + @return unflattened JSON + + @throw parse_error.109 if array index is not a number + @throw type_error.314 if value is not an object + @throw type_error.315 if object values are not primitive + @throw type_error.313 if value cannot be unflattened + */ + static BasicJsonType + unflatten(const BasicJsonType& value) + { + if (JSON_UNLIKELY(not value.is_object())) + { + JSON_THROW(detail::type_error::create(314, "only objects can be unflattened")); + } + + BasicJsonType result; + + // iterate the JSON object values + for (const auto& element : *value.m_value.object) + { + if (JSON_UNLIKELY(not element.second.is_primitive())) + { + JSON_THROW(detail::type_error::create(315, "values in object must be primitive")); + } + + // assign value to reference pointed to by JSON pointer; Note that if + // the JSON pointer is "" (i.e., points to the whole value), function + // get_and_create returns a reference to result itself. An assignment + // will then create a primitive value. + json_pointer(element.first).get_and_create(result) = element.second; + } + + return result; + } + + /*! + @brief compares two JSON pointers for equality + + @param[in] lhs JSON pointer to compare + @param[in] rhs JSON pointer to compare + @return whether @a lhs is equal to @a rhs + + @complexity Linear in the length of the JSON pointer + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + */ + friend bool operator==(json_pointer const& lhs, + json_pointer const& rhs) noexcept + { + return lhs.reference_tokens == rhs.reference_tokens; + } + + /*! + @brief compares two JSON pointers for inequality + + @param[in] lhs JSON pointer to compare + @param[in] rhs JSON pointer to compare + @return whether @a lhs is not equal @a rhs + + @complexity Linear in the length of the JSON pointer + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + */ + friend bool operator!=(json_pointer const& lhs, + json_pointer const& rhs) noexcept + { + return not (lhs == rhs); + } + + /// the reference tokens + std::vector reference_tokens; +}; +} // namespace nlohmann diff --git a/nlohmann/detail/json_ref.hpp b/nlohmann/detail/json_ref.hpp new file mode 100644 index 0000000000..c8dec7330f --- /dev/null +++ b/nlohmann/detail/json_ref.hpp @@ -0,0 +1,69 @@ +#pragma once + +#include +#include + +#include + +namespace nlohmann +{ +namespace detail +{ +template +class json_ref +{ + public: + using value_type = BasicJsonType; + + json_ref(value_type&& value) + : owned_value(std::move(value)), value_ref(&owned_value), is_rvalue(true) + {} + + json_ref(const value_type& value) + : value_ref(const_cast(&value)), is_rvalue(false) + {} + + json_ref(std::initializer_list init) + : owned_value(init), value_ref(&owned_value), is_rvalue(true) + {} + + template < + class... Args, + enable_if_t::value, int> = 0 > + json_ref(Args && ... args) + : owned_value(std::forward(args)...), value_ref(&owned_value), + is_rvalue(true) {} + + // class should be movable only + json_ref(json_ref&&) = default; + json_ref(const json_ref&) = delete; + json_ref& operator=(const json_ref&) = delete; + json_ref& operator=(json_ref&&) = delete; + ~json_ref() = default; + + value_type moved_or_copied() const + { + if (is_rvalue) + { + return std::move(*value_ref); + } + return *value_ref; + } + + value_type const& operator*() const + { + return *static_cast(value_ref); + } + + value_type const* operator->() const + { + return static_cast(value_ref); + } + + private: + mutable value_type owned_value = nullptr; + value_type* value_ref = nullptr; + const bool is_rvalue; +}; +} // namespace detail +} // namespace nlohmann diff --git a/nlohmann/detail/macro_scope.hpp b/nlohmann/detail/macro_scope.hpp new file mode 100644 index 0000000000..ef13810044 --- /dev/null +++ b/nlohmann/detail/macro_scope.hpp @@ -0,0 +1,151 @@ +#pragma once + +#include // pair + +// This file contains all internal macro definitions +// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them + +// exclude unsupported compilers +#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) + #if defined(__clang__) + #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 + #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 + #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #endif +#endif + +// disable float-equal warnings on GCC/clang +#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + +// disable documentation warnings on clang +#if defined(__clang__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdocumentation" +#endif + +// allow for portable deprecation warnings +#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) + #define JSON_DEPRECATED __attribute__((deprecated)) +#elif defined(_MSC_VER) + #define JSON_DEPRECATED __declspec(deprecated) +#else + #define JSON_DEPRECATED +#endif + +// allow for portable nodiscard warnings +#if defined(__has_cpp_attribute) + #if __has_cpp_attribute(nodiscard) + #define JSON_NODISCARD [[nodiscard]] + #elif __has_cpp_attribute(gnu::warn_unused_result) + #define JSON_NODISCARD [[gnu::warn_unused_result]] + #else + #define JSON_NODISCARD + #endif +#else + #define JSON_NODISCARD +#endif + +// allow to disable exceptions +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) + #define JSON_THROW(exception) throw exception + #define JSON_TRY try + #define JSON_CATCH(exception) catch(exception) + #define JSON_INTERNAL_CATCH(exception) catch(exception) +#else + #include + #define JSON_THROW(exception) std::abort() + #define JSON_TRY if(true) + #define JSON_CATCH(exception) if(false) + #define JSON_INTERNAL_CATCH(exception) if(false) +#endif + +// override exception macros +#if defined(JSON_THROW_USER) + #undef JSON_THROW + #define JSON_THROW JSON_THROW_USER +#endif +#if defined(JSON_TRY_USER) + #undef JSON_TRY + #define JSON_TRY JSON_TRY_USER +#endif +#if defined(JSON_CATCH_USER) + #undef JSON_CATCH + #define JSON_CATCH JSON_CATCH_USER + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_CATCH_USER +#endif +#if defined(JSON_INTERNAL_CATCH_USER) + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER +#endif + +// manual branch prediction +#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) + #define JSON_LIKELY(x) __builtin_expect(x, 1) + #define JSON_UNLIKELY(x) __builtin_expect(x, 0) +#else + #define JSON_LIKELY(x) x + #define JSON_UNLIKELY(x) x +#endif + +// C++ language standard detection +#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 +#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 +#endif + +/*! +@brief macro to briefly define a mapping between an enum and JSON +@def NLOHMANN_JSON_SERIALIZE_ENUM +@since version 3.4.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + j = ((it != std::end(m)) ? it : std::begin(m))->second; \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + e = ((it != std::end(m)) ? it : std::begin(m))->first; \ + } + +// Ugly macros to avoid uglier copy-paste when specializing basic_json. They +// may be removed in the future once the class is split. + +#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ + template class ObjectType, \ + template class ArrayType, \ + class StringType, class BooleanType, class NumberIntegerType, \ + class NumberUnsignedType, class NumberFloatType, \ + template class AllocatorType, \ + template class JSONSerializer> + +#define NLOHMANN_BASIC_JSON_TPL \ + basic_json diff --git a/nlohmann/detail/macro_unscope.hpp b/nlohmann/detail/macro_unscope.hpp new file mode 100644 index 0000000000..592debf7ec --- /dev/null +++ b/nlohmann/detail/macro_unscope.hpp @@ -0,0 +1,23 @@ +#pragma once + +// restore GCC/clang diagnostic settings +#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) + #pragma GCC diagnostic pop +#endif +#if defined(__clang__) + #pragma GCC diagnostic pop +#endif + +// clean up +#undef JSON_INTERNAL_CATCH +#undef JSON_CATCH +#undef JSON_THROW +#undef JSON_TRY +#undef JSON_LIKELY +#undef JSON_UNLIKELY +#undef JSON_DEPRECATED +#undef JSON_NODISCARD +#undef JSON_HAS_CPP_14 +#undef JSON_HAS_CPP_17 +#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION +#undef NLOHMANN_BASIC_JSON_TPL diff --git a/nlohmann/detail/meta/cpp_future.hpp b/nlohmann/detail/meta/cpp_future.hpp new file mode 100644 index 0000000000..948cd4fb0c --- /dev/null +++ b/nlohmann/detail/meta/cpp_future.hpp @@ -0,0 +1,63 @@ +#pragma once + +#include // not +#include // size_t +#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type + +namespace nlohmann +{ +namespace detail +{ +// alias templates to reduce boilerplate +template +using enable_if_t = typename std::enable_if::type; + +template +using uncvref_t = typename std::remove_cv::type>::type; + +// implementation of C++14 index_sequence and affiliates +// source: https://stackoverflow.com/a/32223343 +template +struct index_sequence +{ + using type = index_sequence; + using value_type = std::size_t; + static constexpr std::size_t size() noexcept + { + return sizeof...(Ints); + } +}; + +template +struct merge_and_renumber; + +template +struct merge_and_renumber, index_sequence> + : index_sequence < I1..., (sizeof...(I1) + I2)... > {}; + +template +struct make_index_sequence + : merge_and_renumber < typename make_index_sequence < N / 2 >::type, + typename make_index_sequence < N - N / 2 >::type > {}; + +template<> struct make_index_sequence<0> : index_sequence<> {}; +template<> struct make_index_sequence<1> : index_sequence<0> {}; + +template +using index_sequence_for = make_index_sequence; + +// dispatch utility (taken from ranges-v3) +template struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; + +// taken from ranges-v3 +template +struct static_const +{ + static constexpr T value{}; +}; + +template +constexpr T static_const::value; +} // namespace detail +} // namespace nlohmann diff --git a/nlohmann/detail/meta/detected.hpp b/nlohmann/detail/meta/detected.hpp new file mode 100644 index 0000000000..5b52460acf --- /dev/null +++ b/nlohmann/detail/meta/detected.hpp @@ -0,0 +1,58 @@ +#pragma once + +#include + +#include + +// http://en.cppreference.com/w/cpp/experimental/is_detected +namespace nlohmann +{ +namespace detail +{ +struct nonesuch +{ + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + nonesuch(nonesuch const&&) = delete; + void operator=(nonesuch const&) = delete; + void operator=(nonesuch&&) = delete; +}; + +template class Op, + class... Args> +struct detector +{ + using value_t = std::false_type; + using type = Default; +}; + +template class Op, class... Args> +struct detector>, Op, Args...> +{ + using value_t = std::true_type; + using type = Op; +}; + +template