├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── LICENSE ├── README.md ├── appveyor.yml ├── hprose ├── Any.h ├── Ref.h ├── Uri.cpp ├── Uri.h ├── Variant-inl.h ├── Variant.cpp ├── Variant.h ├── http │ ├── Client.cpp │ ├── Client.h │ ├── Cookie.cpp │ ├── Cookie.h │ ├── CookieJar.h │ ├── Header.h │ ├── Method.h │ ├── Request.cpp │ ├── Request.h │ ├── Response.h │ ├── Status.h │ ├── Transport.h │ └── asio │ │ ├── Client.h │ │ ├── Transport.cpp │ │ └── Transport.h ├── io │ ├── ByteReader.cpp │ ├── ByteReader.h │ ├── ClassManager.h │ ├── Formatter.h │ ├── RawReader.cpp │ ├── RawReader.h │ ├── Reader-inl.h │ ├── Reader.cpp │ ├── Reader.h │ ├── Tags.h │ ├── Writer-inl.h │ ├── Writer.h │ ├── decoders │ │ ├── BoolDecoder.cpp │ │ ├── BoolDecoder.h │ │ ├── ComplexDecoder-inl.h │ │ ├── ComplexDecoder.h │ │ ├── FloatDecoder-inl.h │ │ ├── FloatDecoder.h │ │ ├── IntDecoder.cpp │ │ ├── IntDecoder.h │ │ ├── ListDecoder-inl.h │ │ ├── ListDecoder.h │ │ ├── MapDecoder-inl.h │ │ ├── MapDecoder.h │ │ ├── ObjectDecoder-inl.h │ │ ├── ObjectDecoder.h │ │ ├── StringDecoder.cpp │ │ └── StringDecoder.h │ └── test │ │ ├── ReaderTest.cpp │ │ └── WriterTest.cpp ├── rpc │ ├── Client.cpp │ ├── Client.h │ ├── Context.h │ ├── Filter.h │ └── asio │ │ ├── HttpClient.cpp │ │ ├── HttpClient.h │ │ └── test │ │ └── HttpClientTest.cpp ├── test │ └── VariantTest.cpp └── util │ ├── Config.h │ ├── PreProcessor.h │ ├── Util.cpp │ └── Util.h └── travis.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | *.smod 19 | 20 | # Compiled Static libraries 21 | *.lai 22 | *.la 23 | *.a 24 | *.lib 25 | 26 | # Executables 27 | *.exe 28 | *.out 29 | *.app 30 | 31 | # IDEA workspace 32 | .idea 33 | 34 | # VSCode workspace 35 | .vscode 36 | 37 | # CMake files 38 | CMakeFiles 39 | CMakeCache.txt 40 | Makefile 41 | cmake_install.cmake -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: generic 2 | os: osx 3 | before_install: 4 | - curl -sSLo googletest-release-1.8.0.tar.gz https://github.com/google/googletest/archive/release-1.8.0.tar.gz 5 | - tar xzf googletest-release-1.8.0.tar.gz 6 | - cd googletest-release-1.8.0/googletest && cmake . && make && cd .. && cd .. 7 | - curl -sSLo asio-1.10.8.tar.gz https://superb-sea2.dl.sourceforge.net/project/asio/asio/1.10.8%20%28Stable%29/asio-1.10.8.tar.gz 8 | - tar xzf asio-1.10.8.tar.gz 9 | - cd asio-1.10.8 && ./configure --without-boost && make && make install && cd .. 10 | matrix: 11 | include: 12 | - os: linux 13 | dist: precise 14 | env: COMPILER_NAME=gcc CXX=g++-5 CC=gcc-5 15 | addons: 16 | apt: 17 | packages: 18 | - g++-5 19 | sources: &sources 20 | - ubuntu-toolchain-r-test 21 | before_install: 22 | - sudo apt-get autoremove cmake 23 | - sudo apt-get autoremove emacsen-common 24 | - sudo apt-get install software-properties-common 25 | - sudo add-apt-repository -y ppa:george-edison55/precise-backports 26 | - sudo apt-get update 27 | - sudo apt-get install cmake 28 | - curl -sSLo googletest-release-1.8.0.tar.gz https://github.com/google/googletest/archive/release-1.8.0.tar.gz 29 | - tar xzf googletest-release-1.8.0.tar.gz 30 | - cd googletest-release-1.8.0/googletest && cmake . && make && cd .. && cd .. 31 | - curl -sSLo asio-1.10.8.tar.gz https://superb-sea2.dl.sourceforge.net/project/asio/asio/1.10.8%20%28Stable%29/asio-1.10.8.tar.gz 32 | - tar xzf asio-1.10.8.tar.gz 33 | - cd asio-1.10.8 && ./configure --without-boost && make && sudo make install && cd .. 34 | - os: linux 35 | dist: precise 36 | env: COMPILER_NAME=gcc CXX=g++-4.9 CC=gcc-4.9 37 | addons: 38 | apt: 39 | packages: 40 | - g++-4.9 41 | sources: &sources 42 | - ubuntu-toolchain-r-test 43 | before_install: 44 | - sudo apt-get autoremove cmake 45 | - sudo apt-get autoremove emacsen-common 46 | - sudo apt-get install software-properties-common 47 | - sudo add-apt-repository -y ppa:george-edison55/precise-backports 48 | - sudo apt-get update 49 | - sudo apt-get install cmake 50 | - curl -sSLo googletest-release-1.8.0.tar.gz https://github.com/google/googletest/archive/release-1.8.0.tar.gz 51 | - tar xzf googletest-release-1.8.0.tar.gz 52 | - cd googletest-release-1.8.0/googletest && cmake . && make && cd .. && cd .. 53 | - curl -sSLo asio-1.10.8.tar.gz https://superb-sea2.dl.sourceforge.net/project/asio/asio/1.10.8%20%28Stable%29/asio-1.10.8.tar.gz 54 | - tar xzf asio-1.10.8.tar.gz 55 | - cd asio-1.10.8 && ./configure --without-boost && make && sudo make install && cd .. 56 | - os: linux 57 | dist: precise 58 | env: COMPILER_NAME=gcc CXX=g++-4.8 CC=gcc-4.8 59 | addons: 60 | apt: 61 | packages: 62 | - g++-4.8 63 | sources: &sources 64 | - ubuntu-toolchain-r-test 65 | before_install: 66 | - sudo apt-get autoremove cmake 67 | - sudo apt-get autoremove emacsen-common 68 | - sudo apt-get install software-properties-common 69 | - sudo add-apt-repository -y ppa:george-edison55/precise-backports 70 | - sudo apt-get update 71 | - sudo apt-get install cmake 72 | - curl -sSLo googletest-release-1.8.0.tar.gz https://github.com/google/googletest/archive/release-1.8.0.tar.gz 73 | - tar xzf googletest-release-1.8.0.tar.gz 74 | - cd googletest-release-1.8.0/googletest && cmake . && make && cd .. && cd .. 75 | - curl -sSLo asio-1.10.8.tar.gz https://superb-sea2.dl.sourceforge.net/project/asio/asio/1.10.8%20%28Stable%29/asio-1.10.8.tar.gz 76 | - tar xzf asio-1.10.8.tar.gz 77 | - cd asio-1.10.8 && ./configure --without-boost && make && sudo make install && cd .. 78 | - os: linux 79 | dist: precise 80 | env: COMPILER_NAME=gcc CXX=g++-4.7 CC=gcc-4.7 81 | addons: 82 | apt: 83 | packages: 84 | - g++-4.7 85 | sources: &sources 86 | - ubuntu-toolchain-r-test 87 | before_install: 88 | - sudo apt-get autoremove cmake 89 | - sudo apt-get autoremove emacsen-common 90 | - sudo apt-get install software-properties-common 91 | - sudo add-apt-repository -y ppa:george-edison55/precise-backports 92 | - sudo apt-get update 93 | - sudo apt-get install cmake 94 | - curl -sSLo googletest-release-1.8.0.tar.gz https://github.com/google/googletest/archive/release-1.8.0.tar.gz 95 | - tar xzf googletest-release-1.8.0.tar.gz 96 | - cd googletest-release-1.8.0/googletest && cmake . && make && cd .. && cd .. 97 | - curl -sSLo asio-1.10.8.tar.gz https://superb-sea2.dl.sourceforge.net/project/asio/asio/1.10.8%20%28Stable%29/asio-1.10.8.tar.gz 98 | - tar xzf asio-1.10.8.tar.gz 99 | - cd asio-1.10.8 && ./configure --without-boost && make && sudo make install && cd .. 100 | - os: linux 101 | dist: precise 102 | env: COMPILER_NAME=gcc CXX=g++-4.6 CC=gcc-4.6 103 | before_install: 104 | - sudo apt-get autoremove cmake 105 | - sudo apt-get autoremove emacsen-common 106 | - sudo apt-get install software-properties-common 107 | - sudo add-apt-repository -y ppa:george-edison55/precise-backports 108 | - sudo apt-get update 109 | - sudo apt-get install cmake 110 | - curl -sSLo googletest-release-1.8.0.tar.gz https://github.com/google/googletest/archive/release-1.8.0.tar.gz 111 | - tar xzf googletest-release-1.8.0.tar.gz 112 | - cd googletest-release-1.8.0/googletest && cmake . && make && cd .. && cd .. 113 | - curl -sSLo asio-1.10.8.tar.gz https://superb-sea2.dl.sourceforge.net/project/asio/asio/1.10.8%20%28Stable%29/asio-1.10.8.tar.gz 114 | - tar xzf asio-1.10.8.tar.gz 115 | - cd asio-1.10.8 && sudo cp -a include/asio.hpp /usr/local/include && sudo cp -a include/asio /usr/local/include && cd .. 116 | - os: linux 117 | dist: precise 118 | env: COMPILER_NAME=clang CXX=clang++-4.0 CC=clang-4.0 119 | addons: 120 | apt: 121 | packages: 122 | - g++-5 123 | sources: &sources 124 | - ubuntu-toolchain-r-test 125 | before_install: 126 | - sudo sh -c "echo 'deb http://apt.llvm.org/precise/ llvm-toolchain-precise-4.0 main' >> /etc/apt/sources.list" 127 | - sudo sh -c "echo 'deb-src http://apt.llvm.org/precise/ llvm-toolchain-precise-4.0 main' >> /etc/apt/sources.list" 128 | - wget -O - http://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - 129 | - sudo apt-get autoremove cmake 130 | - sudo apt-get autoremove emacsen-common 131 | - sudo apt-get install software-properties-common 132 | - sudo add-apt-repository -y ppa:george-edison55/precise-backports 133 | - sudo apt-get update 134 | - sudo apt-get install -y cmake clang-4.0 135 | - curl -sSLo googletest-release-1.8.0.tar.gz https://github.com/google/googletest/archive/release-1.8.0.tar.gz 136 | - tar xzf googletest-release-1.8.0.tar.gz 137 | - cd googletest-release-1.8.0/googletest && cmake . && make && cd .. && cd .. 138 | - curl -sSLo asio-1.10.8.tar.gz https://superb-sea2.dl.sourceforge.net/project/asio/asio/1.10.8%20%28Stable%29/asio-1.10.8.tar.gz 139 | - tar xzf asio-1.10.8.tar.gz 140 | - cd asio-1.10.8 && ./configure --without-boost && make && sudo make install && cd .. 141 | script: sh ./travis.sh 142 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.2) 2 | project(hprose) 3 | 4 | find_package(Threads REQUIRED) 5 | 6 | if (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") 7 | #gcc 8 | set(CMAKE_CXX_FLAGS "-g -Wall -Wextra -Werror") 9 | execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion 10 | OUTPUT_VARIABLE COMPILER_VERSION) 11 | if (COMPILER_VERSION VERSION_GREATER 4.7 OR COMPILER_VERSION VERSION_EQUAL 4.7) 12 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 13 | else() 14 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") 15 | endif() 16 | elseif (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") 17 | #Clang and AppleClang 18 | set(CMAKE_CXX_FLAGS "-g -Wall -Wextra -Werror -Wno-error=deprecated-declarations") 19 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 20 | elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") 21 | # using Visual Studio C++ 22 | # -D_WIN32_WINNT=0x0501 to shut up asio warning 23 | # /EHsc to shut up C++ exception handling was used but /EHsc was not selected. 24 | set(CMAKE_CXX_FLAGS "-D_WIN32_WINNT=0x0501 /EHsc /utf-8") 25 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 26 | else () 27 | # default 28 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 29 | endif () 30 | 31 | set(SOURCE_FILES 32 | hprose/io/Reader.cpp 33 | hprose/io/ByteReader.cpp 34 | hprose/io/RawReader.cpp 35 | hprose/io/decoders/BoolDecoder.cpp 36 | hprose/io/decoders/IntDecoder.cpp 37 | hprose/io/decoders/StringDecoder.cpp 38 | hprose/rpc/Client.cpp 39 | hprose/rpc/asio/HttpClient.cpp 40 | hprose/http/Cookie.cpp 41 | hprose/http/Request.cpp 42 | hprose/http/Client.cpp 43 | hprose/http/asio/Transport.cpp 44 | hprose/util/Util.cpp 45 | hprose/Uri.cpp 46 | hprose/Variant.cpp) 47 | 48 | include_directories("/usr/local/include" ".") 49 | link_directories(${GTEST_DIR}) 50 | 51 | add_definitions(-DASIO_STANDALONE) 52 | add_library(hprose STATIC ${SOURCE_FILES}) 53 | 54 | set(TEST_FILES 55 | hprose/test/VariantTest.cpp 56 | hprose/io/test/WriterTest.cpp 57 | hprose/io/test/ReaderTest.cpp 58 | hprose/rpc/asio/test/HttpClientTest.cpp) 59 | 60 | add_executable(IOTest.out ${TEST_FILES}) 61 | target_include_directories(IOTest.out PUBLIC "${GTEST_DIR}/include") 62 | target_link_libraries(IOTest.out hprose ${CMAKE_THREAD_LIBS_INIT} gtest) 63 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Hprose 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hprose for C++ 1x 2 | 3 | [![Build Status](https://travis-ci.org/hprose/hprose-cpp1x.svg?branch=master)](https://travis-ci.org/hprose/hprose-cpp1x) 4 | 5 | *Hprose* is a High Performance Remote Object Service Engine. 6 | 7 | It is a modern, lightweight, cross-language, cross-platform, object-oriented, high performance, remote dynamic communication middleware. It is not only easy to use, but powerful. You just need a little time to learn, then you can use it to easily construct cross language cross platform distributed application system. 8 | 9 | *Hprose* supports many programming languages, for example: 10 | 11 | * AAuto Quicker 12 | * ActionScript 13 | * ASP 14 | * C++ 15 | * Dart 16 | * Delphi/Free Pascal 17 | * dotNET(C#, Visual Basic...) 18 | * Golang 19 | * Java 20 | * JavaScript 21 | * Node.js 22 | * Objective-C 23 | * Perl 24 | * PHP 25 | * Python 26 | * Ruby 27 | * ... 28 | 29 | Through *Hprose*, You can conveniently and efficiently intercommunicate between those programming languages. 30 | 31 | This project is the implementation of Hprose for C++ 1x. 32 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # Notes: 2 | # - Minimal appveyor.yml file is an empty file. All sections are optional. 3 | # - Indent each level of configuration with 2 spaces. Do not use tabs! 4 | # - All section names are case-sensitive. 5 | # - Section names should be unique on each level. 6 | 7 | #---------------------------------# 8 | # general configuration # 9 | #---------------------------------# 10 | 11 | # version format 12 | version: 1.0.{build} 13 | 14 | # Do not build on tags (GitHub and BitBucket) 15 | skip_tags: true 16 | configuration: Release 17 | 18 | # Build worker image (VM template) 19 | image: Visual Studio 2015 20 | 21 | install: 22 | - curl -sSLo googletest-release-1.8.0.zip https://github.com/google/googletest/archive/release-1.8.0.zip 23 | - 7z x googletest-release-1.8.0.zip 24 | - cd googletest-release-1.8.0\googletest && cmake -G "Visual Studio 14 2015" -DBUILD_SHARED_LIBS=on . && cmake --build . && copy /y Debug\gtest.dll . && cd .. && cd .. 25 | - curl -sSLo asio-asio-1-10-8.zip https://github.com/chriskohlhoff/asio/archive/asio-1-10-8.zip 26 | - 7z x asio-asio-1-10-8.zip 27 | - move asio-asio-1-10-8\asio\include\asio.hpp . && move asio-asio-1-10-8\asio\include\asio . 28 | build_script: 29 | - cmake -G "Visual Studio 14 2015" -DGTEST_DIR=googletest-release-1.8.0\googletest 30 | - cmake --build . && copy /y googletest-release-1.8.0\googletest\gtest.dll Debug\ && Debug\IOTest.out 31 | -------------------------------------------------------------------------------- /hprose/Any.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/Any.h * 13 | * * 14 | * any type for cpp, ported from boost::any. * 15 | * * 16 | * LastModified: Dec 4, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | namespace hprose { 28 | 29 | class Any { 30 | public: 31 | Any() noexcept 32 | : content(0) { 33 | } 34 | 35 | template 36 | Any(const T &value) 37 | : content(new holder::type>::type>(value)) { 38 | } 39 | 40 | Any(const Any &other) 41 | : content(other.content ? other.content->clone() : 0) { 42 | } 43 | 44 | Any(Any &&other) noexcept 45 | : content(other.content) { 46 | other.content = 0; 47 | } 48 | 49 | // template 50 | // Any(T &&value 51 | // , typename std::disable_if >::type * = 0 52 | // , typename std::disable_if >::type * = 0) 53 | // : content(new holder::type>(static_cast(value))) { 54 | // } 55 | 56 | ~Any() noexcept { 57 | delete content; 58 | } 59 | 60 | public: 61 | Any &swap(Any &rhs) { 62 | std::swap(content, rhs.content); 63 | return *this; 64 | } 65 | 66 | template 67 | Any &operator=(const T &rhs) { 68 | Any(rhs).swap(*this); 69 | return *this; 70 | } 71 | 72 | Any &operator=(Any &&rhs) noexcept { 73 | rhs.swap(*this); 74 | Any().swap(rhs); 75 | return *this; 76 | } 77 | 78 | template 79 | Any &operator=(ValueType &&rhs) { 80 | Any(static_cast(rhs)).swap(*this); 81 | return *this; 82 | } 83 | 84 | public: 85 | bool empty() const noexcept { 86 | return !content; 87 | } 88 | 89 | void clear() noexcept { 90 | Any().swap(*this); 91 | } 92 | 93 | const std::type_info &type() const noexcept { 94 | return content ? content->type() : typeid(void); 95 | } 96 | 97 | private: 98 | 99 | class placeholder { 100 | public: 101 | 102 | virtual ~placeholder() { 103 | } 104 | 105 | public: 106 | 107 | virtual const std::type_info &type() const = 0; 108 | 109 | virtual placeholder *clone() const = 0; 110 | }; 111 | 112 | template 113 | class holder : public placeholder { 114 | public: 115 | 116 | holder(const T &value) 117 | : held(value) { 118 | } 119 | 120 | holder(T &&value) 121 | : held(static_cast(value)) { 122 | } 123 | 124 | public: 125 | 126 | virtual const std::type_info &type() const { 127 | return typeid(T); 128 | } 129 | 130 | virtual placeholder *clone() const { 131 | return new holder(held); 132 | } 133 | 134 | public: 135 | 136 | T held; 137 | 138 | private: 139 | 140 | holder &operator=(const holder &); 141 | 142 | }; 143 | 144 | public: 145 | 146 | template 147 | static T *cast(Any *operand) { 148 | return operand && 149 | operand->type() == typeid(T) 150 | ? &static_cast *>(operand->content)->held 151 | : 0; 152 | } 153 | 154 | template 155 | inline static const T *cast(const Any *operand) { 156 | return cast(const_cast(operand)); 157 | } 158 | 159 | template 160 | static T cast(Any &operand) { 161 | typedef typename std::remove_reference::type nonref; 162 | nonref *result = cast(&operand); 163 | if (!result) { 164 | throw std::runtime_error("failed conversion using hprose::Any::cast"); 165 | } 166 | return *result; 167 | } 168 | 169 | template 170 | inline static T cast(const Any &operand) { 171 | typedef typename std::remove_reference::type nonref; 172 | return cast(const_cast(operand)); 173 | } 174 | 175 | template 176 | inline static T *unsafe_cast(Any *operand) { 177 | return &static_cast * > (operand->content)->held; 178 | } 179 | 180 | template 181 | inline static const T *unsafe_cast(const Any *operand) { 182 | return unsafe_cast(const_cast(operand)); 183 | } 184 | 185 | private: 186 | 187 | placeholder *content; 188 | 189 | }; 190 | 191 | 192 | } //hprose 193 | -------------------------------------------------------------------------------- /hprose/Ref.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/Ref.h * 13 | * * 14 | * ref type for cpp. * 15 | * * 16 | * LastModified: Dec 26, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | 26 | namespace hprose { 27 | 28 | struct Ref { 29 | template 30 | Ref(const T &v) 31 | : ptr(&v), type(&typeid(v)) { 32 | } 33 | 34 | const void *ptr; 35 | const std::type_info *type; 36 | }; 37 | 38 | } // hprose 39 | 40 | namespace std { 41 | 42 | template<> 43 | struct hash { 44 | typedef hprose::Ref argument_type; 45 | typedef std::size_t result_type; 46 | 47 | result_type operator()(const argument_type &ref) const { 48 | const result_type h1(std::hash{}(ref.ptr)); 49 | const result_type h2(std::hash{}(ref.type)); 50 | return h1 ^ (h2 << 1); 51 | } 52 | }; 53 | 54 | template<> 55 | struct equal_to { 56 | typedef bool result_type; 57 | typedef hprose::Ref first_argument_type; 58 | typedef hprose::Ref second_argument_type; 59 | 60 | result_type operator()(const first_argument_type &left, const second_argument_type &right) const { 61 | return left.ptr == right.ptr && left.type == right.type; 62 | } 63 | }; 64 | 65 | } // std 66 | -------------------------------------------------------------------------------- /hprose/Uri.cpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/Uri.cpp * 13 | * * 14 | * URI for cpp. * 15 | * * 16 | * LastModified: Dec 15, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #include 22 | #include 23 | 24 | #include 25 | #ifdef HPROSE_HAS_REGEX 26 | #include 27 | #else // HPROSE_HAS_REGEX 28 | #include 29 | #include 30 | #include 31 | #endif // HPROSE_HAS_REGEX 32 | #include 33 | 34 | namespace hprose { 35 | 36 | #ifdef HPROSE_HAS_REGEX 37 | std::string submatch(const std::smatch &m, size_t idx) { 38 | auto &sub = m[idx]; 39 | return std::string(sub.first, sub.second); 40 | } 41 | 42 | void Uri::setUri(const std::string &str) { 43 | static const std::regex uriRegex( 44 | "([a-zA-Z][a-zA-Z0-9+.-]*):" // scheme: 45 | "([^?#]*)" // authority and path 46 | "(?:\\?([^#]*))?" // ?query 47 | "(?:#(.*))?"); // #fragment 48 | 49 | static const std::regex authorityAndPathRegex("//([^/]*)(/.*)?"); 50 | 51 | std::smatch match; 52 | if (!std::regex_match(str.begin(), str.end(), match, uriRegex)) { 53 | throw std::invalid_argument(std::string("invalid URI ") + str); 54 | } 55 | 56 | scheme = submatch(match, 1); 57 | std::transform(scheme.begin(), scheme.end(), scheme.begin(), tolower); 58 | 59 | const std::string authorityAndPath(match[2].first, match[2].second); 60 | std::smatch authorityAndPathMatch; 61 | if (!std::regex_match(authorityAndPath.begin(), 62 | authorityAndPath.end(), 63 | authorityAndPathMatch, 64 | authorityAndPathRegex)) { 65 | // Does not start with //, doesn't have authority 66 | path = authorityAndPath; 67 | } else { 68 | static const std::regex authorityRegex( 69 | "(?:([^@:]*)(?::([^@]*))?@)?" // username, password 70 | "(\\[[^\\]]*\\]|[^\\[:]*)" // host (IP-literal (e.g. '['+IPv6+']', 71 | // dotted-IPv4, or named host) 72 | "(?::(\\d*))?"); // port 73 | 74 | auto authority = authorityAndPathMatch[1]; 75 | std::smatch authorityMatch; 76 | if (!std::regex_match(authority.first, 77 | authority.second, 78 | authorityMatch, 79 | authorityRegex)) { 80 | throw std::invalid_argument( 81 | std::string("invalid URI authority ") + std::string(authority.first, authority.second)); 82 | } 83 | 84 | const std::string port(authorityMatch[4].first, authorityMatch[4].second); 85 | if (!port.empty()) { 86 | this->port = static_cast(std::stoi(port)); 87 | } 88 | 89 | username = submatch(authorityMatch, 1); 90 | password = submatch(authorityMatch, 2); 91 | host = submatch(authorityMatch, 3); 92 | path = submatch(authorityAndPathMatch, 2); 93 | } 94 | 95 | query = submatch(match, 3); 96 | fragment = submatch(match, 4); 97 | } 98 | 99 | #else // HPROSE_HAS_REGEX 100 | 101 | static std::string getLeftStr(std::string &str, const char sep) { 102 | std::string ret; 103 | std::string::size_type pos = str.find(sep); 104 | if (pos != std::string::npos) { 105 | ret = str.substr(0, pos); 106 | str.erase(0, pos + 1); 107 | } 108 | return ret; 109 | } 110 | 111 | static std::string getRightStr(std::string &str, const char sep) { 112 | std::string ret; 113 | std::string::size_type pos = str.find(sep); 114 | if (pos != std::string::npos) { 115 | ret = str.substr(pos + 1); 116 | str.erase(pos); 117 | } 118 | return ret; 119 | } 120 | 121 | void Uri::setUri(const std::string &str) { 122 | //scheme:[//[user[:password]@]host[:port]][/path][?query][#fragment] 123 | path = str; 124 | scheme = getLeftStr(path, ':'); 125 | if (!scheme.empty()) { 126 | std::transform(scheme.begin(), scheme.end(), scheme.begin(), tolower); 127 | } 128 | 129 | fragment = getRightStr(path, '#'); 130 | query = getRightStr(path, '?'); 131 | 132 | std::string::size_type pos = path.find("//"); 133 | if (pos != std::string::npos) { 134 | path.erase(0, 2); 135 | pos = path.find("/"); 136 | host = path; 137 | path = getRightStr(host, '/'); 138 | if (pos != std::string::npos) { 139 | path.insert(0, 1, '/'); 140 | } 141 | if (!host.empty()) { 142 | username = getLeftStr(host, '@'); 143 | if (!username.empty()) { 144 | password = getRightStr(username, ':'); 145 | } 146 | std::string strPort = getRightStr(host, ':'); 147 | if (!strPort.empty()) { 148 | port = static_cast(std::stoi(strPort)); 149 | } 150 | } 151 | } 152 | } 153 | #endif // HPROSE_HAS_REGEX 154 | 155 | Uri::Uri(const std::string &str) 156 | : port(0) { 157 | setUri(str); 158 | } 159 | 160 | Uri::Uri() 161 | : port(0) { 162 | } 163 | 164 | Uri::~Uri() { 165 | } 166 | 167 | std::string Uri::getHostname() const { 168 | if (host.size() > 0 && host[0] == '[') { 169 | return host.substr(1, host.size() - 2); 170 | } 171 | return host; 172 | } 173 | 174 | std::string Uri::getAuthority() const { 175 | std::ostringstream ss; 176 | if (!username.empty() || !password.empty()) { 177 | ss << username; 178 | if (!password.empty()) { 179 | ss << ':' << password; 180 | } 181 | ss << '@'; 182 | } 183 | ss << host; 184 | if (port != 0) { 185 | ss << ':' << port; 186 | } 187 | return ss.str(); 188 | } 189 | 190 | std::string Uri::str() const { 191 | std::ostringstream ss; 192 | auto authority = getAuthority(); 193 | if (!authority.empty()) { 194 | ss << scheme << "://" << authority; 195 | } else { 196 | ss << scheme << ':'; 197 | } 198 | ss << path; 199 | if (!query.empty()) { 200 | ss << '?' << query; 201 | } 202 | if (!fragment.empty()) { 203 | ss << '#' << fragment; 204 | } 205 | return ss.str(); 206 | } 207 | 208 | } // hprose 209 | -------------------------------------------------------------------------------- /hprose/Uri.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/Uri.h * 13 | * * 14 | * URI for cpp. * 15 | * * 16 | * LastModified: Dec 9, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | namespace hprose { 26 | 27 | class Uri { 28 | public: 29 | explicit Uri(const std::string &str); 30 | Uri(); 31 | ~Uri(); 32 | 33 | void setUri(const std::string &str); 34 | 35 | const std::string &getScheme() const { return scheme; } 36 | 37 | const std::string &getUsername() const { return username; } 38 | 39 | const std::string &getPassword() const { return password; } 40 | 41 | const std::string &getHost() const { return host; } 42 | 43 | uint16_t getPort() const { return port; } 44 | 45 | void setPort(uint16_t port) { this->port = port; }; 46 | 47 | const std::string &getPath() const { return path; } 48 | 49 | const std::string &getQuery() const { return query; } 50 | 51 | const std::string &getFragment() const { return fragment; } 52 | 53 | std::string getHostname() const; 54 | 55 | std::string getAuthority() const; 56 | 57 | std::string str() const; 58 | 59 | private: 60 | std::string scheme; 61 | std::string username; 62 | std::string password; 63 | std::string host; 64 | uint16_t port; 65 | std::string path; 66 | std::string query; 67 | std::string fragment; 68 | }; 69 | 70 | } // hprose 71 | -------------------------------------------------------------------------------- /hprose/Variant-inl.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/Variant.h * 13 | * * 14 | * variant type for cpp. * 15 | * * 16 | * LastModified: Dec 26, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | namespace hprose { 24 | 25 | namespace detail { 26 | 27 | struct Destroy { 28 | template 29 | static void destroy(T *t) { t->~T(); } 30 | }; 31 | 32 | } // hprose::detail 33 | 34 | #ifdef HPROSE_HAS_DELEGATING_CONSTRUCTORS 35 | inline Variant::Variant() : Variant(nullptr) {} 36 | #else // HPROSE_HAS_DELEGATING_CONSTRUCTORS 37 | inline Variant::Variant() : type(Null) {} 38 | #endif // HPROSE_HAS_DELEGATING_CONSTRUCTORS 39 | 40 | inline Variant::Variant(std::nullptr_t) : type(Null) {} 41 | 42 | #ifdef HPROSE_HAS_DELEGATING_CONSTRUCTORS 43 | inline Variant::Variant(const char *v) : Variant(std::string(v)) {} 44 | #else // HPROSE_HAS_DELEGATING_CONSTRUCTORS 45 | inline Variant::Variant(const char *v) : type(String) { 46 | new (&data.vString) std::shared_ptr(new std::string(v)); 47 | } 48 | #endif // HPROSE_HAS_DELEGATING_CONSTRUCTORS 49 | 50 | inline Variant::Variant(std::string v) : type(String) { 51 | new (&data.vString) std::shared_ptr(new std::string(std::move(v))); 52 | } 53 | 54 | inline Variant::Variant(std::tm v) : type(Time) { 55 | new (&data.vTime) std::shared_ptr(new std::tm(std::move(v))); 56 | } 57 | 58 | inline Variant::Variant(Ref ref) : type(Reference) { 59 | new (&data.vRef) Ref(ref); 60 | } 61 | 62 | template 63 | Variant::Variant(const T &v) : type(Other) { 64 | new (&data.vOther) std::shared_ptr(new Any(v)); 65 | } 66 | 67 | inline Variant::Variant(const Variant &o) : type(Null) { 68 | *this = o; 69 | } 70 | 71 | inline Variant::Variant(Variant &&o) noexcept : type(Null) { 72 | *this = std::move(o); 73 | } 74 | 75 | inline Variant::~Variant() noexcept { 76 | destroy(); 77 | } 78 | 79 | inline bool Variant::isNull() const { return type == Null; } 80 | inline bool Variant::isBool() const { return type == Bool; } 81 | inline bool Variant::isInt64() const { return type == Int64; } 82 | inline bool Variant::isDouble() const { return type == Double; } 83 | inline bool Variant::isString() const { return type == String; } 84 | inline bool Variant::isTime() const { return type == Time; } 85 | inline bool Variant::isRef() const { return type == Reference; } 86 | inline bool Variant::isOther() const { return type == Other; } 87 | 88 | #ifdef HPROSE_HAS_REF_QUALIFIER 89 | inline const std::string &Variant::getString() const & { 90 | return *data.vString; 91 | } 92 | 93 | inline const std::tm &Variant::getTime() const & { 94 | return *data.vTime; 95 | } 96 | 97 | inline const Ref &Variant::getRef() const & { 98 | return data.vRef; 99 | } 100 | 101 | inline const Any &Variant::getOther() const & { 102 | return *data.vOther; 103 | } 104 | #else // HPROSE_HAS_REF_QUALIFIER 105 | inline const std::string &Variant::getString() const { 106 | return *data.vString; 107 | } 108 | 109 | inline const std::tm &Variant::getTime() const { 110 | return *data.vTime; 111 | } 112 | 113 | inline const Ref &Variant::getRef() const { 114 | return data.vRef; 115 | } 116 | 117 | inline const Any &Variant::getOther() const { 118 | return *data.vOther; 119 | } 120 | #endif // HPROSE_HAS_REF_QUALIFIER 121 | 122 | template 123 | T *Variant::getAddress() noexcept { 124 | return GetAddrImpl::get(data); 125 | } 126 | 127 | template 128 | T const *Variant::getAddress() const noexcept { 129 | return const_cast(this)->getAddress(); 130 | } 131 | 132 | template 133 | struct Variant::GetAddrImpl { 134 | }; 135 | 136 | template<> 137 | struct Variant::GetAddrImpl { 138 | static void **get(Data &d) noexcept { return &d.vNull; } 139 | }; 140 | 141 | template<> 142 | struct Variant::GetAddrImpl > { 143 | static std::shared_ptr *get(Data &d) noexcept { return &d.vString; } 144 | }; 145 | 146 | template<> 147 | struct Variant::GetAddrImpl> { 148 | static std::shared_ptr *get(Data &d) noexcept { return &d.vTime; } 149 | }; 150 | 151 | template<> 152 | struct Variant::GetAddrImpl { 153 | static Ref *get(Data &d) noexcept { return &d.vRef; } 154 | }; 155 | 156 | template<> 157 | struct Variant::GetAddrImpl> { 158 | static std::shared_ptr *get(Data &d) noexcept { return &d.vOther; } 159 | }; 160 | 161 | } // hprose 162 | -------------------------------------------------------------------------------- /hprose/Variant.cpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/Variant.h * 13 | * * 14 | * variant type for cpp. * 15 | * * 16 | * LastModified: Dec 26, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #include 22 | 23 | namespace hprose { 24 | 25 | #define HP_DYNAMIC_APPLY(type, apply) \ 26 | do { \ 27 | switch ((type)) { \ 28 | case Null: \ 29 | apply(void*); \ 30 | break; \ 31 | case String: \ 32 | apply(std::shared_ptr); \ 33 | break; \ 34 | case Time: \ 35 | apply(std::shared_ptr); \ 36 | break; \ 37 | case Reference: \ 38 | apply(Ref); \ 39 | break; \ 40 | case Other: \ 41 | apply(std::shared_ptr); \ 42 | break; \ 43 | default: \ 44 | abort(); \ 45 | } \ 46 | } while (0) 47 | 48 | const char *Variant::typeName() const { 49 | switch (type) { 50 | case Null: 51 | return "void *"; 52 | case String: 53 | return "std::string"; 54 | case Time: 55 | return "std::tm"; 56 | case Reference: 57 | return "Ref"; 58 | case Other: 59 | return "Any"; 60 | default: 61 | abort(); 62 | } 63 | } 64 | 65 | Variant &Variant::operator=(const Variant &o) { 66 | if (&o != this) { 67 | if (type == o.type) { 68 | #define HP_X(T) *getAddress() = *o.getAddress() 69 | HP_DYNAMIC_APPLY(type, HP_X); 70 | #undef HP_X 71 | } else { 72 | destroy(); 73 | #define HP_X(T) new (getAddress()) T(*o.getAddress()) 74 | HP_DYNAMIC_APPLY(o.type, HP_X); 75 | #undef HP_X 76 | type = o.type; 77 | } 78 | } 79 | return *this; 80 | } 81 | 82 | Variant &Variant::operator=(Variant &&o) noexcept { 83 | if (&o != this) { 84 | if (type == o.type) { 85 | #define HP_X(T) *getAddress() = std::move(*o.getAddress()) 86 | HP_DYNAMIC_APPLY(type, HP_X); 87 | #undef HP_X 88 | } else { 89 | destroy(); 90 | #define HP_X(T) new (getAddress()) T(std::move(*o.getAddress())) 91 | HP_DYNAMIC_APPLY(o.type, HP_X); 92 | #undef HP_X 93 | type = o.type; 94 | } 95 | } 96 | return *this; 97 | } 98 | 99 | void Variant::destroy() noexcept { 100 | if (type == Null) return; 101 | #define HP_X(T) detail::Destroy::destroy(getAddress()) 102 | HP_DYNAMIC_APPLY(type, HP_X); 103 | #undef HP_X 104 | type = Null; 105 | data.vNull = nullptr; 106 | } 107 | 108 | } // hprose 109 | -------------------------------------------------------------------------------- /hprose/Variant.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/Variant.h * 13 | * * 14 | * variant type for cpp. * 15 | * * 16 | * LastModified: Dec 26, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | namespace hprose { 36 | 37 | class Variant { 38 | public: 39 | enum Type { 40 | Null, 41 | Bool, 42 | Int64, 43 | Double, 44 | String, 45 | Bytes, 46 | Time, 47 | Array, 48 | Reference, 49 | Other 50 | }; 51 | 52 | Variant(); 53 | Variant(std::nullptr_t); 54 | 55 | Variant(const char *v); 56 | Variant(std::string v); 57 | 58 | Variant(std::tm v); 59 | 60 | Variant(Ref ref); 61 | 62 | template 63 | Variant(const T &v); 64 | 65 | Variant(const Variant &o); 66 | Variant(Variant &&o) noexcept; 67 | ~Variant() noexcept; 68 | 69 | Variant &operator=(const Variant &o); 70 | Variant &operator=(Variant &&o) noexcept; 71 | 72 | bool isNull() const; 73 | bool isBool() const; 74 | bool isInt64() const; 75 | bool isDouble() const; 76 | bool isString() const; 77 | bool isTime() const; 78 | bool isRef() const; 79 | bool isOther() const; 80 | 81 | const char *typeName() const; 82 | 83 | #ifdef HPROSE_HAS_REF_QUALIFIER 84 | const std::string &getString() const &; 85 | const std::tm &getTime() const &; 86 | const Ref &getRef() const &; 87 | const Any &getOther() const &; 88 | #else // HPROSE_HAS_REF_QUALIFIER 89 | const std::string &getString() const; 90 | const std::tm &getTime() const; 91 | const Ref &getRef() const; 92 | const Any &getOther() const; 93 | #endif // HPROSE_HAS_REF_QUALIFIER 94 | 95 | private: 96 | template struct GetAddrImpl; 97 | 98 | template T *getAddress() noexcept; 99 | template T const *getAddress() const noexcept; 100 | 101 | void destroy() noexcept; 102 | 103 | Type type; 104 | 105 | union Data { 106 | explicit Data() : vNull(nullptr) {} 107 | ~Data() {} 108 | 109 | void *vNull; 110 | bool vBool; 111 | int64_t vInt64; 112 | double vDouble; 113 | std::shared_ptr vString; 114 | std::shared_ptr vTime; 115 | std::shared_ptr > vArray; 116 | Ref vRef; 117 | std::shared_ptr vOther; 118 | } data; 119 | }; 120 | 121 | } // hprose 122 | 123 | #include 124 | -------------------------------------------------------------------------------- /hprose/http/Client.cpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/http/Client.h * 13 | * * 14 | * hprose http client for cpp. * 15 | * * 16 | * LastModified: May 17, 2018 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #include 22 | #include 23 | 24 | namespace hprose { 25 | namespace http { 26 | 27 | namespace internal { 28 | 29 | bool shouldRedirectGet(int statusCode) { 30 | switch (statusCode) { 31 | case StatusMovedPermanently: 32 | case StatusFound: 33 | case StatusSeeOther: 34 | case StatusTemporaryRedirect: 35 | return true; 36 | default: 37 | return false; 38 | } 39 | } 40 | 41 | 42 | bool shouldRedirectPost(int statusCode) { 43 | switch (statusCode) { 44 | case StatusFound: 45 | case StatusSeeOther: 46 | return true; 47 | default: 48 | return false; 49 | } 50 | } 51 | 52 | } // internal 53 | 54 | } 55 | } // hprose::http 56 | -------------------------------------------------------------------------------- /hprose/http/Client.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/http/Client.h * 13 | * * 14 | * hprose http client for cpp. * 15 | * * 16 | * LastModified: Dec 3, 2017 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | 30 | namespace hprose { 31 | namespace http { 32 | 33 | namespace internal { 34 | 35 | bool shouldRedirectGet(int statusCode); 36 | 37 | bool shouldRedirectPost(int statusCode); 38 | 39 | } // internal 40 | 41 | template 42 | class Client { 43 | public: 44 | Client() 45 | : cookieJar(nullptr), timeout(0) { 46 | } 47 | 48 | Transport &getTransport() { return transport; } 49 | 50 | std::shared_ptr getCookieJar() { return cookieJar; } 51 | 52 | void setCookieJar(std::shared_ptr cookieJar) { this->cookieJar = cookieJar; } 53 | 54 | int getTimeout() { return timeout; } 55 | 56 | void setTimeout(int timeout) { this->timeout = timeout; } 57 | 58 | Response execute(const Request &req) { 59 | std::string method = req.method.empty() ? "GET" : req.method; 60 | if (method == "GET" || method == "HEAD") { 61 | return doFollowingRedirects(req, internal::shouldRedirectGet); 62 | } 63 | if (method == "POST" || method == "PUT") { 64 | return doFollowingRedirects(req, internal::shouldRedirectPost); 65 | } 66 | return send(req, deadline()); 67 | } 68 | 69 | inline Response get(std::string url) { 70 | Request req("GET", url); 71 | return doFollowingRedirects(req, internal::shouldRedirectGet); 72 | } 73 | 74 | inline Response post(std::string url, std::string bodyType, std::string body) { 75 | Request req("POST", url, body); 76 | req.header.set("Content-Type", bodyType); 77 | return doFollowingRedirects(req, internal::shouldRedirectPost); 78 | } 79 | 80 | inline Response head(std::string url) { 81 | Request req("HEAD", url); 82 | return doFollowingRedirects(req, internal::shouldRedirectGet); 83 | } 84 | 85 | private: 86 | Response doFollowingRedirects(const Request &req, bool shouldRedirect(int)) { 87 | auto deadline = this->deadline(); 88 | std::vector reqs; 89 | Response resp; 90 | while (true) { 91 | if (!reqs.empty()) { 92 | auto loc = resp.header.get("Location"); 93 | if (loc.empty()) { 94 | throw std::runtime_error(std::to_string(resp.statusCode) + " response missing Location header"); 95 | } 96 | } 97 | reqs.push_back(req); 98 | resp = send(req, deadline); 99 | if (!shouldRedirect(resp.statusCode)) { 100 | return resp; 101 | } 102 | } 103 | } 104 | 105 | Response send(const Request &req, time_t deadline) { 106 | return transport.sendRequest(req, deadline); 107 | } 108 | 109 | time_t deadline() { 110 | if (timeout > 0) { 111 | return time(0) + timeout; 112 | } 113 | return time_t(); 114 | } 115 | 116 | Transport transport; 117 | std::shared_ptr cookieJar; 118 | int timeout; 119 | }; 120 | 121 | } 122 | } // hprose::http 123 | -------------------------------------------------------------------------------- /hprose/http/Cookie.cpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/http/Cookie.h * 13 | * * 14 | * hprose http cookie for cpp. * 15 | * * 16 | * LastModified: Dec 3, 2017 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #include 22 | 23 | #include 24 | 25 | namespace hprose { 26 | namespace http { 27 | 28 | bool isCookieNameValid(const std::string &name) { 29 | if (name.empty()) { 30 | return false; 31 | } 32 | return true; 33 | } 34 | 35 | 36 | std::string Cookie::str() const { 37 | if (!isCookieNameValid(name)) { 38 | return ""; 39 | } 40 | std::ostringstream stream; 41 | stream << name << "=" << value; 42 | return stream.str(); 43 | } 44 | 45 | } 46 | } // hprose::http 47 | -------------------------------------------------------------------------------- /hprose/http/Cookie.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/http/Cookie.h * 13 | * * 14 | * hprose http cookie for cpp. * 15 | * * 16 | * LastModified: Dec 3, 2017 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | 26 | namespace hprose { 27 | namespace http { 28 | 29 | class Cookie { 30 | public: 31 | Cookie(std::string name, std::string value) 32 | : name(name), value(value), expires(0), maxAge(-1), secure(false), httpOnly(false) { 33 | } 34 | 35 | std::string getName() const { return name; } 36 | 37 | void setName(const std::string &name) { this->name = name; }; 38 | 39 | std::string getValue() const { return value; } 40 | 41 | void setValue(const std::string &value) { this->value = value; }; 42 | 43 | std::string getDomain() const { return domain; } 44 | 45 | void setDomain(const std::string &domain) { this->domain = domain; }; 46 | 47 | std::string getPath() const { return path; } 48 | 49 | void setPath(const std::string &path) { this->path = path; }; 50 | 51 | std::time_t getExpires() const { return expires; } 52 | 53 | void setExpires(std::time_t expires) { this->expires = expires; }; 54 | 55 | int getMaxAge() const { return maxAge; } 56 | 57 | void setMaxAge(int maxAge) { this->maxAge = maxAge; }; 58 | 59 | bool isSecure() const { return secure; } 60 | 61 | void setSecure(bool secure) { this->secure = secure; }; 62 | 63 | bool isHttpOnly() const { return httpOnly; } 64 | 65 | void setHttpOnly(bool httpOnly) { this->httpOnly = httpOnly; }; 66 | 67 | std::string str() const; 68 | 69 | private: 70 | std::string name; 71 | std::string value; 72 | std::string domain; 73 | std::string path; 74 | std::time_t expires; 75 | int maxAge; 76 | bool secure; 77 | bool httpOnly; 78 | }; 79 | 80 | } 81 | } // hprose::http 82 | -------------------------------------------------------------------------------- /hprose/http/CookieJar.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/http/CookieJar.h * 13 | * * 14 | * hprose http cookie jar for cpp. * 15 | * * 16 | * LastModified: Nov 29, 2017 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | namespace hprose { 29 | namespace http { 30 | 31 | class CookieJar { 32 | public: 33 | virtual std::vector getCookies(const Uri &uri) = 0; 34 | 35 | virtual void setCookies(const Uri &uri, const std::vector &cookies) = 0; 36 | }; 37 | 38 | } 39 | } // hprose::http 40 | -------------------------------------------------------------------------------- /hprose/http/Header.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/http/Header.h * 13 | * * 14 | * hprose http header for cpp. * 15 | * * 16 | * LastModified: Nov 27, 2017 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | namespace hprose { 32 | namespace http { 33 | 34 | namespace internal { 35 | 36 | struct UniHash { 37 | size_t operator()(const std::string &str) const { 38 | std::string lowerStr(str.size(), 0); 39 | std::transform(str.begin(), str.end(), lowerStr.begin(), tolower); 40 | std::hash hash; 41 | return hash(lowerStr); 42 | } 43 | }; 44 | 45 | struct UniEqual { 46 | bool operator()(const std::string &left, const std::string &right) const { 47 | return left.size() == right.size() 48 | && std::equal(left.begin(), left.end(), right.begin(), 49 | [](char a, char b) { 50 | return tolower(a) == tolower(b); 51 | } 52 | ); 53 | } 54 | }; 55 | 56 | } // internal 57 | 58 | class Header 59 | : public std::unordered_map, internal::UniHash, internal::UniEqual> { 60 | public: 61 | void add(std::string key, std::string value) { 62 | auto search = find(key); 63 | if (search != end()) { 64 | search->second.push_back(value); 65 | } else { 66 | set(key, value); 67 | } 68 | } 69 | 70 | inline void set(std::string key, std::string value) { 71 | (*this)[key] = {value}; 72 | } 73 | 74 | std::string get(std::string key) const { 75 | auto search = find(key); 76 | if (search != end()) { 77 | auto value = search->second; 78 | if (value.size()) { 79 | return value[0]; 80 | } 81 | } 82 | return ""; 83 | } 84 | 85 | inline void del(std::string key) { 86 | erase(key); 87 | } 88 | 89 | void writeSubset(std::ostream &ostream, const std::set &exclude) const { 90 | for (auto iter = cbegin(); iter != cend(); iter++) { 91 | if (exclude.find(iter->first) == exclude.end()) { 92 | ostream << iter->first << ": " << iter->second[0] << "\r\n"; 93 | } 94 | } 95 | } 96 | 97 | }; 98 | 99 | } 100 | } // hprose::http 101 | -------------------------------------------------------------------------------- /hprose/http/Method.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/http/Method.h * 13 | * * 14 | * hprose http common methods for cpp. * 15 | * * 16 | * LastModified: Dec 12, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | namespace hprose { 24 | namespace http { 25 | 26 | const char *MethodGet = "GET"; 27 | const char *MethodHead = "HEAD"; 28 | const char *MethodPost = "POST"; 29 | const char *MethodPut = "PUT"; 30 | const char *MethodPatch = "PATCH"; 31 | const char *MethodDelete = "DELETE"; 32 | const char *MethodConnect = "CONNECT"; 33 | const char *MethodOptions = "OPTIONS"; 34 | const char *MethodTrace = "TRACE"; 35 | 36 | } 37 | } // hprose::http 38 | -------------------------------------------------------------------------------- /hprose/http/Request.cpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/http/Request.cpp * 13 | * * 14 | * hprose http request for cpp. * 15 | * * 16 | * LastModified: Dec 3, 2017 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #include 22 | 23 | namespace hprose { 24 | namespace http { 25 | 26 | const char *DefaultUserAgent = "Hprose-http-client/1.1"; 27 | 28 | const std::set ReqWriteExcludeHeader = {"Host", "User-Agent", "Content-Length", "Transfer-Encoding", "Trailer"}; 29 | 30 | inline bool chunked(const std::vector &transferEncoding) { 31 | return !transferEncoding.empty() && transferEncoding[0] == "chunked"; 32 | } 33 | 34 | inline bool isIdentity(const std::vector &transferEncoding) { 35 | return transferEncoding.size() == 1 && transferEncoding[0] == "identity"; 36 | } 37 | 38 | void Request::addCookie(const Cookie &cookie) { 39 | std::string raw = cookie.str(); 40 | std::string cookieValue = header.get("Cookie"); 41 | if (!cookieValue.empty()) { 42 | header.set("Cookie", cookieValue + "; " + raw); 43 | } else { 44 | header.set("Cookie", raw); 45 | } 46 | } 47 | 48 | void Request::write(std::ostream &ostream) const { 49 | std::string host = uri.getHost(); 50 | if (uri.getPort() > 0) { 51 | host += ":" + std::to_string(uri.getPort()); 52 | } 53 | 54 | ostream << method << " " << uri.getPath() << " " << proto << "\r\n"; 55 | 56 | ostream << "Host: " << host << "\r\n"; 57 | 58 | std::string userAgent = DefaultUserAgent; 59 | if (header.find("User-Agent") != header.end()) { 60 | userAgent = header.get("User-Agent"); 61 | } 62 | if (userAgent != "") { 63 | ostream << "User-Agent: " << host << "\r\n"; 64 | } 65 | 66 | if (close) { 67 | ostream << "Connection: close\r\n"; 68 | } 69 | if (shouldSendContentLength()) { 70 | ostream << "Content-Length: " << contentLength << "\r\n"; 71 | } else if (chunked(transferEncoding)) { 72 | ostream << "Transfer-Encoding: chunked\r\n"; 73 | } 74 | 75 | header.writeSubset(ostream, ReqWriteExcludeHeader); 76 | 77 | ostream << "\r\n"; 78 | } 79 | 80 | bool Request::shouldSendContentLength() const { 81 | if (chunked(transferEncoding)) { 82 | return false; 83 | } 84 | if (contentLength > 0) { 85 | return true; 86 | } 87 | if (contentLength < 0) { 88 | return false; 89 | } 90 | if (method == "POST" || method == "PUT") { 91 | return true; 92 | } 93 | if (contentLength == 0 && isIdentity(transferEncoding)) { 94 | if (method == "GET" || method == "HEAD") { 95 | return false; 96 | } 97 | return true; 98 | } 99 | return false; 100 | } 101 | 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /hprose/http/Request.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/http/Request.h * 13 | * * 14 | * hprose http request for cpp. * 15 | * * 16 | * LastModified: Nov 29, 2017 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | 30 | namespace hprose { 31 | namespace http { 32 | 33 | struct Request { 34 | explicit Request(const std::string &uri) 35 | : method("GET"), uri(Uri(uri)), proto("HTTP/1.1"), contentLength(0), close(false) { 36 | } 37 | 38 | explicit Request(std::string method, const std::string &uri) 39 | : method(std::move(method)), uri(Uri(uri)), proto("HTTP/1.1"), contentLength(0), close(false) { 40 | } 41 | 42 | explicit Request(std::string method, const std::string &uri, std::string body) 43 | : method(std::move(method)), uri(Uri(uri)), proto("HTTP/1.1"), body(std::move(body)), 44 | contentLength(this->body.size()), close(false) { 45 | } 46 | 47 | void addCookie(const Cookie &cookie); 48 | 49 | void write(std::ostream &ostream) const; 50 | 51 | std::string method; 52 | Uri uri; 53 | std::string proto; 54 | Header header; 55 | std::string body; 56 | int64_t contentLength; 57 | std::vector transferEncoding; 58 | bool close; 59 | 60 | private: 61 | bool shouldSendContentLength() const; 62 | }; 63 | 64 | } 65 | } // hprose::http 66 | -------------------------------------------------------------------------------- /hprose/http/Response.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/http/Response.h * 13 | * * 14 | * hprose http response for cpp. * 15 | * * 16 | * LastModified: Dec 13, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | namespace hprose { 26 | namespace http { 27 | 28 | struct Response { 29 | std::string status; 30 | int statusCode; 31 | std::string proto; 32 | Header header; 33 | std::string body; 34 | int64_t contentLength; 35 | }; 36 | 37 | } 38 | } // hprose::http 39 | -------------------------------------------------------------------------------- /hprose/http/Status.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/http/Status.h * 13 | * * 14 | * hprose http status for cpp. * 15 | * * 16 | * LastModified: Dec 12, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | namespace hprose { 24 | namespace http { 25 | 26 | const int StatusContinue = 100; 27 | const int StatusSwitchingProtocols = 101; 28 | const int StatusProcessing = 102; 29 | 30 | const int StatusOK = 200; 31 | const int StatusCreated = 201; 32 | const int StatusAccepted = 202; 33 | const int StatusNonAuthoritativeInfo = 203; 34 | const int StatusNoContent = 204; 35 | const int StatusResetContent = 205; 36 | const int StatusPartialContent = 206; 37 | const int StatusMultiStatus = 207; 38 | const int StatusAlreadyReported = 208; 39 | const int StatusIMUsed = 226; 40 | 41 | const int StatusMultipleChoices = 300; 42 | const int StatusMovedPermanently = 301; 43 | const int StatusFound = 302; 44 | const int StatusSeeOther = 303; 45 | const int StatusNotModified = 304; 46 | const int StatusUseProxy = 305; 47 | const int StatusTemporaryRedirect = 307; 48 | const int StatusPermanentRedirect = 308; 49 | 50 | const int StatusBadRequest = 400; 51 | const int StatusUnauthorized = 401; 52 | const int StatusPaymentRequired = 402; 53 | const int StatusForbidden = 403; 54 | const int StatusNotFound = 404; 55 | const int StatusMethodNotAllowed = 405; 56 | const int StatusNotAcceptable = 406; 57 | const int StatusProxyAuthRequired = 407; 58 | const int StatusRequestTimeout = 408; 59 | const int StatusConflict = 409; 60 | const int StatusGone = 410; 61 | const int StatusLengthRequired = 411; 62 | const int StatusPreconditionFailed = 412; 63 | const int StatusRequestEntityTooLarge = 413; 64 | const int StatusRequestURITooLong = 414; 65 | const int StatusUnsupportedMediaType = 415; 66 | const int StatusRequestedRangeNotSatisfiable = 416; 67 | const int StatusExpectationFailed = 417; 68 | const int StatusTeapot = 418; 69 | const int StatusUnprocessableEntity = 422; 70 | const int StatusLocked = 423; 71 | const int StatusFailedDependency = 424; 72 | const int StatusUpgradeRequired = 426; 73 | const int StatusPreconditionRequired = 428; 74 | const int StatusTooManyRequests = 429; 75 | const int StatusRequestHeaderFieldsTooLarge = 431; 76 | const int StatusUnavailableForLegalReasons = 451; 77 | 78 | const int StatusInternalServerError = 500; 79 | const int StatusNotImplemented = 501; 80 | const int StatusBadGateway = 502; 81 | const int StatusServiceUnavailable = 503; 82 | const int StatusGatewayTimeout = 504; 83 | const int StatusHTTPVersionNotSupported = 505; 84 | const int StatusVariantAlsoNegotiates = 506; 85 | const int StatusInsufficientStorage = 507; 86 | const int StatusLoopDetected = 508; 87 | const int StatusNotExtended = 510; 88 | const int StatusNetworkAuthenticationRequired = 511; 89 | 90 | } 91 | } // hprose::http 92 | -------------------------------------------------------------------------------- /hprose/http/Transport.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/http/Transport.h * 13 | * * 14 | * hprose http transport for cpp. * 15 | * * 16 | * LastModified: Nov 28, 2017 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | 26 | namespace hprose { 27 | namespace http { 28 | 29 | class Transport { 30 | public: 31 | Transport() 32 | : keepAlive(true), compression(false) { 33 | } 34 | 35 | virtual Response sendRequest(const Request &req, time_t deadline) = 0; 36 | 37 | bool keepAlive; 38 | 39 | bool compression; 40 | }; 41 | 42 | } 43 | } // hprose::http 44 | -------------------------------------------------------------------------------- /hprose/http/asio/Client.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/http/asio/Client.h * 13 | * * 14 | * hprose http asio client for cpp. * 15 | * * 16 | * LastModified: Dec 3, 2017 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | 26 | namespace hprose { 27 | namespace http { 28 | namespace asio { 29 | 30 | typedef Client Client; 31 | 32 | } 33 | } 34 | } // hprose::http::asio 35 | -------------------------------------------------------------------------------- /hprose/http/asio/Transport.cpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/http/asio/Transport.cpp * 13 | * * 14 | * hprose http asio transport for cpp. * 15 | * * 16 | * LastModified: Nov 28, 2017 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #include 22 | #include 23 | 24 | namespace hprose { 25 | namespace http { 26 | namespace asio { 27 | 28 | using ::asio::ip::tcp; 29 | 30 | Response Transport::sendRequest(const Request &req, time_t deadline) { 31 | (void)deadline; 32 | tcp::socket socket = getConnection(req); 33 | writeRequest(req, socket); 34 | return readResponse(socket); 35 | } 36 | 37 | tcp::socket Transport::getConnection(const Request &req) { 38 | tcp::socket socket(ios); 39 | tcp::resolver resolver(ios); 40 | uint16_t port = req.uri.getPort(); 41 | tcp::resolver::query query(req.uri.getHost(), port ? std::to_string(port) : req.uri.getScheme()); 42 | ::asio::error_code error; 43 | ::asio::connect(socket, resolver.resolve(query), error); 44 | return socket; 45 | } 46 | 47 | void Transport::writeRequest(const Request &req, tcp::socket &socket) { 48 | ::asio::streambuf request; 49 | std::ostream requestStream(&request); 50 | req.write(requestStream); 51 | if (req.contentLength >= 64 * 1024) { 52 | ::asio::write(socket, request); 53 | ::asio::write(socket, ::asio::buffer(req.body)); 54 | } else { 55 | requestStream << req.body; 56 | ::asio::write(socket, request); 57 | } 58 | } 59 | 60 | Response Transport::readResponse(tcp::socket &socket) { 61 | Response resp; 62 | 63 | ::asio::streambuf response; 64 | ::asio::read_until(socket, response, "\r\n"); 65 | 66 | std::istream response_stream(&response); 67 | response_stream >> resp.proto >> resp.statusCode >> resp.status; 68 | response.consume(2); 69 | 70 | size_t bytes = 0, len = 0; 71 | bool chunked = false; 72 | 73 | ::asio::read_until(socket, response, "\r\n\r\n"); 74 | std::string header; 75 | internal::UniEqual uniEqual; 76 | while (std::getline(response_stream, header) && header != "\r") { 77 | auto index = header.find_first_of(":"); 78 | if (index != std::string::npos) { 79 | auto key = header.substr(0, index); 80 | auto value = header.substr(index + 2, header.size() - index - 3); 81 | if (uniEqual(key, "Content-Length")) { 82 | len = std::stoul(value); 83 | resp.contentLength = len; 84 | } else if (uniEqual(key, "Transfer-Encoding")) { 85 | chunked = uniEqual(value, "chunked"); 86 | } else { 87 | resp.header.set(key, value); 88 | } 89 | } 90 | } 91 | 92 | std::ostringstream responseStream; 93 | if (chunked) { 94 | while (true) { 95 | size_t chunk_size = 0; 96 | ::asio::read_until(socket, response, "\r\n"); 97 | response_stream >> std::hex >> chunk_size >> std::dec; 98 | response.consume(2); 99 | if (chunk_size) { 100 | bytes = 0; 101 | while (true) { 102 | bytes += ::asio::read_until(socket, response, "\r\n"); 103 | if (bytes > chunk_size) { 104 | for (size_t i = 0; i < chunk_size; i++) { 105 | responseStream << (char) response_stream.get(); 106 | }; 107 | response.consume(2); 108 | break; 109 | } 110 | } 111 | } else { 112 | response.consume(2); 113 | break; 114 | } 115 | } 116 | } else { 117 | bool nosize = !len; 118 | size_t n = std::min(len, header.size()); 119 | for (size_t i = 0; i < n; ++i, --len) { 120 | responseStream << (char) response_stream.get(); 121 | }; 122 | if (nosize) { 123 | len = (std::numeric_limits::max)(); 124 | } 125 | if (len) { 126 | char buf[1024]; 127 | ::asio::error_code error; 128 | while (len) { 129 | auto n = socket.read_some(::asio::buffer(buf), error); 130 | if (error) break; 131 | responseStream.write(buf, n); 132 | len -= n; 133 | } 134 | } 135 | } 136 | socket.close(); 137 | 138 | resp.body = responseStream.str(); 139 | return resp; 140 | } 141 | 142 | } 143 | } 144 | } // hprose::http::asio 145 | -------------------------------------------------------------------------------- /hprose/http/asio/Transport.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/http/asio/Transport.h * 13 | * * 14 | * hprose http asio transport for cpp. * 15 | * * 16 | * LastModified: Nov 28, 2017 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | #include 26 | 27 | namespace hprose { 28 | namespace http { 29 | namespace asio { 30 | 31 | using ::asio::ip::tcp; 32 | 33 | class Transport : public http::Transport { 34 | public: 35 | Response sendRequest(const Request &req, time_t deadline); 36 | 37 | private: 38 | tcp::socket getConnection(const Request &req); 39 | 40 | void writeRequest(const Request &req, tcp::socket &socket); 41 | 42 | Response readResponse(tcp::socket &socket); 43 | 44 | ::asio::io_service ios; 45 | }; 46 | 47 | } 48 | } 49 | } // hprose::http::asio 50 | -------------------------------------------------------------------------------- /hprose/io/ByteReader.cpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/io/ByteReader.h * 13 | * * 14 | * hprose byte reader for cpp. * 15 | * * 16 | * LastModified: Dec 15, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #include 22 | 23 | #include 24 | 25 | namespace hprose { 26 | namespace io { 27 | 28 | std::string ByteReader::read(size_t count) { 29 | std::string str; 30 | str.resize(count); 31 | stream.read(const_cast(str.data()), count); 32 | if (static_cast(stream.gcount()) != count) { 33 | throw std::runtime_error("unexpected end of stream"); 34 | } 35 | return str; 36 | } 37 | 38 | std::string ByteReader::readUTF8String(int length) { 39 | if (length == 0) { 40 | return ""; 41 | } 42 | std::ostringstream ss; 43 | for (auto i = 0; i < length; i++) { 44 | auto c = stream.get(); 45 | switch (c >> 4) { 46 | case 0: 47 | case 1: 48 | case 2: 49 | case 3: 50 | case 4: 51 | case 5: 52 | case 6: 53 | case 7: { 54 | ss << static_cast(c); 55 | break; 56 | } 57 | case 12: 58 | case 13: { 59 | ss << static_cast(c); 60 | ss << static_cast(stream.get()); 61 | break; 62 | } 63 | case 14: { 64 | ss << static_cast(c); 65 | ss << static_cast(stream.get()); 66 | ss << static_cast(stream.get()); 67 | break; 68 | } 69 | case 15: { 70 | if ((c & 8) == 8) { 71 | throw std::runtime_error("bad utf-8 encode"); 72 | } 73 | ss << static_cast(c); 74 | ss << static_cast(stream.get()); 75 | ss << static_cast(stream.get()); 76 | ss << static_cast(stream.get()); 77 | i++; 78 | break; 79 | } 80 | default: 81 | throw std::runtime_error("bad utf-8 encode"); 82 | }; 83 | } 84 | return ss.str(); 85 | } 86 | 87 | } 88 | } // hprose::io 89 | -------------------------------------------------------------------------------- /hprose/io/ByteReader.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/io/ByteReader.h * 13 | * * 14 | * hprose byte reader for cpp. * 15 | * * 16 | * LastModified: May 17, 2018 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | namespace hprose { 33 | namespace io { 34 | 35 | class ByteReader { 36 | public: 37 | explicit ByteReader(std::istream &stream) 38 | : stream(stream) { 39 | } 40 | 41 | int read2Digit() { 42 | auto n = stream.get() - '0'; 43 | return n * 10 + (stream.get() - '0'); 44 | } 45 | 46 | int read4Digit() { 47 | auto n = stream.get() - '0'; 48 | n = n * 10 + (stream.get() - '0'); 49 | n = n * 10 + (stream.get() - '0'); 50 | return n * 10 + (stream.get() - '0'); 51 | } 52 | 53 | template 54 | typename std::enable_if< 55 | std::is_arithmetic::value, 56 | T 57 | >::type 58 | readArithmetic(char tag) { 59 | auto b = stream.get(); 60 | if (b == tag) { 61 | return 0; 62 | } 63 | T i = 0; 64 | auto neg = false; 65 | switch (b) { 66 | case '-': 67 | neg = true; 68 | case '+': 69 | b = stream.get(); 70 | default: 71 | break; 72 | } 73 | if (neg) { 74 | while (b != tag) { 75 | i = i * 10 - (b - '0'); 76 | b = stream.get(); 77 | } 78 | } else { 79 | while (b != tag) { 80 | i = i * 10 + (b - '0'); 81 | b = stream.get(); 82 | } 83 | } 84 | return i; 85 | } 86 | 87 | inline int readInt() { 88 | return readArithmetic(TagSemicolon); 89 | } 90 | 91 | inline int readLength() { 92 | return readArithmetic(TagQuote); 93 | } 94 | 95 | template 96 | typename std::enable_if< 97 | std::is_floating_point::value, 98 | T 99 | >::type 100 | readInfinity() { 101 | return stream.get() == TagPos ? std::numeric_limits::infinity() : -std::numeric_limits::infinity(); 102 | } 103 | 104 | template 105 | typename std::enable_if< 106 | std::is_floating_point::value, 107 | T 108 | >::type 109 | readFloat() { 110 | return util::StringToFloat(readUntil(TagSemicolon)); 111 | } 112 | 113 | std::string read(size_t count); 114 | 115 | std::string readUntil(char tag) { 116 | std::string s; 117 | std::getline(stream, s, tag); 118 | return s; 119 | } 120 | 121 | std::string readUTF8String(int length); 122 | 123 | inline std::string readString() { 124 | std::string s = readUTF8String(readLength()); 125 | stream.get(); 126 | return s; 127 | } 128 | 129 | std::istream &stream; 130 | }; 131 | 132 | } 133 | } // hprose::io 134 | -------------------------------------------------------------------------------- /hprose/io/ClassManager.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/io/ClassManager.h * 13 | * * 14 | * hprose class manager for cpp. * 15 | * * 16 | * LastModified: Dec 18, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #define HPROSE_REG_CLASS_1(Class, Body) HPROSE_REG_CLASS_2(Class, #Class, Body) 31 | #define HPROSE_REG_CLASS_2(Class, Alias, Body) \ 32 | namespace hprose { namespace io { \ 33 | \ 34 | template<> \ 35 | std::vector getClassFields() { \ 36 | typedef const Class * ConstClassPointer; \ 37 | typedef Class * ClassPointer; \ 38 | std::vector fields; \ 39 | Body \ 40 | return fields; \ 41 | } \ 42 | \ 43 | template<> \ 44 | void initClassCache(ClassCache &classCache) { \ 45 | auto fields = getClassFields(); \ 46 | auto count = fields.size(); \ 47 | std::ostringstream stream; \ 48 | stream << TagClass; \ 49 | util::WriteInt(stream, util::UTF16Length(Alias)); \ 50 | stream << TagQuote << Alias << TagQuote; \ 51 | if (count > 0) util::WriteInt(stream, count); \ 52 | stream << TagOpenbrace; \ 53 | for (auto &&field : fields) { \ 54 | classCache.fieldMap[field.alias] = field; \ 55 | stream << TagString; \ 56 | util::WriteInt(stream, util::UTF16Length(field.alias)); \ 57 | stream << TagQuote << field.alias << TagQuote; \ 58 | } \ 59 | stream << TagClosebrace; \ 60 | classCache.alias = Alias; \ 61 | classCache.fields = std::move(fields); \ 62 | classCache.data = stream.str(); \ 63 | } \ 64 | \ 65 | inline void encode(const Class &v, Writer &writer) { \ 66 | writer.writeObject(v); \ 67 | } \ 68 | \ 69 | inline void decode(Class &v, Reader &reader) { \ 70 | reader.readObject(v); \ 71 | } \ 72 | \ 73 | } } // hprose::io 74 | 75 | #define HPROSE_REG_FIELD_1(Field) HPROSE_REG_FIELD_2(Field, #Field) 76 | #define HPROSE_REG_FIELD_2(Field, Alias) { \ 77 | FieldCache fieldCache; \ 78 | fieldCache.alias = Alias; \ 79 | fieldCache.encode = [](const void *obj, Writer &writer) { \ 80 | writer.writeValue(static_cast(obj)->Field); \ 81 | }; \ 82 | fieldCache.decode = [](void *obj, Reader &reader) { \ 83 | reader.readValue(static_cast(obj)->Field); \ 84 | }; \ 85 | fields.push_back(std::move(fieldCache)); \ 86 | } 87 | 88 | #ifndef _MSC_VER 89 | #define HPROSE_REG_CLASS(Class, ...) HPROSE_PP_OVERLOAD(HPROSE_REG_CLASS_,__VA_ARGS__)(Class, __VA_ARGS__) 90 | #define HPROSE_REG_FIELD(...) HPROSE_PP_OVERLOAD(HPROSE_REG_FIELD_, __VA_ARGS__)(__VA_ARGS__) 91 | #else // _MSC_VER 92 | #define HPROSE_REG_CLASS(Class, ...) HPROSE_PP_CAT(HPROSE_PP_OVERLOAD(HPROSE_REG_CLASS_,__VA_ARGS__)(Class, __VA_ARGS__),) 93 | #define HPROSE_REG_FIELD(...) HPROSE_PP_CAT(HPROSE_PP_OVERLOAD(HPROSE_REG_FIELD_, __VA_ARGS__)(__VA_ARGS__),) 94 | #endif // _MSC_VER 95 | 96 | namespace hprose { 97 | namespace io { 98 | 99 | class Writer; 100 | 101 | class Reader; 102 | 103 | struct FieldCache { 104 | std::string alias; 105 | std::function encode; 106 | std::function decode; 107 | }; 108 | 109 | struct ClassCache { 110 | std::string alias; 111 | std::vector fields; 112 | std::unordered_map fieldMap; 113 | std::string data; 114 | }; 115 | 116 | template 117 | std::vector getClassFields(); 118 | 119 | template 120 | void initClassCache(ClassCache &classCache); 121 | 122 | class ClassManager { 123 | public: 124 | static ClassManager &SharedInstance() { 125 | static ClassManager classManager; 126 | return classManager; 127 | } 128 | 129 | template 130 | void registerClass() { 131 | auto type = std::type_index(typeid(T)); 132 | ClassCache classCache; 133 | initClassCache(classCache); 134 | cache[type] = classCache; 135 | types[classCache.alias] = &typeid(T); 136 | } 137 | 138 | template 139 | const ClassCache &getClassCache() { 140 | auto type = std::type_index(typeid(T)); 141 | auto iter = cache.find(type); 142 | if (iter == cache.end()) { 143 | registerClass(); 144 | return cache[type]; 145 | } else { 146 | return iter->second; 147 | } 148 | } 149 | 150 | inline const ClassCache &getClassCache(const std::type_info &type) { 151 | return cache[std::type_index(type)]; 152 | } 153 | 154 | inline const std::type_info *getClassType(const std::string &alias) { 155 | return types[alias]; 156 | } 157 | 158 | private: 159 | std::unordered_map cache; 160 | std::unordered_map types; 161 | }; 162 | 163 | } 164 | } // hprose::io 165 | -------------------------------------------------------------------------------- /hprose/io/Formatter.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/io/Formatter.h * 13 | * * 14 | * hprose formatter for cpp. * 15 | * * 16 | * LastModified: Dec 15, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | 26 | namespace hprose { 27 | namespace io { 28 | 29 | template 30 | inline std::string serialize(const T &v, bool simple = false) { 31 | std::ostringstream stream; 32 | Writer(stream, simple).writeValue(v); 33 | return stream.str(); 34 | } 35 | 36 | template 37 | inline T unserialize(const std::istream &stream, bool simple = false) { 38 | return Reader(stream, simple).unserialize(); 39 | } 40 | 41 | template 42 | inline T unserialize(const std::string &data, bool simple = false) { 43 | std::istringstream stream(data); 44 | return Reader(stream, simple).unserialize(); 45 | } 46 | 47 | template 48 | inline void &unserialize(const std::istream &stream, T &v, bool simple = false) { 49 | Reader(stream, simple).readValue(v); 50 | } 51 | 52 | template 53 | inline void &unserialize(const std::string &data, T &v, bool simple = false) { 54 | std::istringstream stream(data); 55 | Reader(stream, simple).readValue(v); 56 | } 57 | 58 | } 59 | } // hprose::io 60 | -------------------------------------------------------------------------------- /hprose/io/RawReader.cpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/io/RawReader.cpp * 13 | * * 14 | * hprose raw reader for cpp. * 15 | * * 16 | * LastModified: Dec 15, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #include 22 | 23 | namespace hprose { 24 | namespace io { 25 | 26 | void RawReader::readRaw(std::ostream &ostream, char tag) { 27 | ostream << tag; 28 | switch (tag) { 29 | case '0': 30 | case '1': 31 | case '2': 32 | case '3': 33 | case '4': 34 | case '5': 35 | case '6': 36 | case '7': 37 | case '8': 38 | case '9': 39 | case TagNull: 40 | case TagEmpty: 41 | case TagFalse: 42 | case TagTrue: 43 | case TagNaN: break; 44 | case TagInfinity: ostream << stream.get(); break; 45 | case TagInteger: 46 | case TagLong: 47 | case TagDouble: 48 | case TagRef: readNumberRaw(ostream); break; 49 | case TagDate: 50 | case TagTime: readDateTimeRaw(ostream); break; 51 | case TagUTF8Char: readUTF8CharRaw(ostream); break; 52 | case TagString: readStringRaw(ostream); break; 53 | case TagBytes: readBytesRaw(ostream); break; 54 | case TagGUID: readGUIDRaw(ostream); break; 55 | case TagList: 56 | case TagMap: 57 | case TagObject: readComplexRaw(ostream); break; 58 | case TagClass: readComplexRaw(ostream); readRawTo(ostream); break; 59 | case TagError: readRawTo(ostream); break; 60 | default: throw UnexpectedTag(tag); 61 | } 62 | } 63 | 64 | void RawReader::readNumberRaw(std::ostream &ostream) { 65 | while (!stream.eof()) { 66 | auto tag = static_cast(stream.get()); 67 | ostream << tag; 68 | if (tag == TagSemicolon) break; 69 | } 70 | } 71 | 72 | void RawReader::readDateTimeRaw(std::ostream &ostream) { 73 | while (!stream.eof()) { 74 | auto tag = static_cast(stream.get()); 75 | ostream << tag; 76 | if (tag == TagSemicolon || tag == TagUTC) break; 77 | } 78 | } 79 | 80 | void RawReader::readUTF8CharRaw(std::ostream &ostream) { 81 | ostream << readUTF8String(1); 82 | } 83 | 84 | void RawReader::readStringRaw(std::ostream &ostream) { 85 | auto count = 0; 86 | char tag = '0'; 87 | while (!stream.eof()) { 88 | count *= 10; 89 | count += (tag - '0'); 90 | tag = static_cast(stream.get()); 91 | ostream << tag; 92 | if (tag == TagQuote) { 93 | ostream << readUTF8String(count + 1); 94 | break; 95 | } 96 | } 97 | } 98 | 99 | void RawReader::readBytesRaw(std::ostream &ostream) { 100 | auto count = 0; 101 | char tag = '0'; 102 | while (!stream.eof()) { 103 | count *= 10; 104 | count += (tag - '0'); 105 | tag = static_cast(stream.get()); 106 | ostream << tag; 107 | if (tag == TagQuote) { 108 | ostream << read(count + 1); 109 | break; 110 | } 111 | } 112 | } 113 | 114 | void RawReader::readGUIDRaw(std::ostream &ostream) { 115 | ostream << read(38); 116 | } 117 | 118 | void RawReader::readComplexRaw(std::ostream &ostream) { 119 | char tag = 0; 120 | while (!stream.eof()) { 121 | tag = static_cast(stream.get()); 122 | ostream << tag; 123 | if (tag == TagOpenbrace) break; 124 | } 125 | while (!stream.eof()) { 126 | tag = static_cast(stream.get()); 127 | if (tag == TagClosebrace) { 128 | ostream << tag; 129 | break; 130 | } 131 | readRaw(ostream, tag); 132 | } 133 | } 134 | 135 | } 136 | } // hprose::io 137 | -------------------------------------------------------------------------------- /hprose/io/RawReader.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/io/RawReader.h * 13 | * * 14 | * hprose raw reader for cpp. * 15 | * * 16 | * LastModified: May 17, 2018 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | #include 26 | 27 | namespace hprose { 28 | namespace io { 29 | 30 | struct UnexpectedTag : std::runtime_error { 31 | explicit UnexpectedTag(char tag) 32 | : std::runtime_error(tag == -1 ? 33 | "no byte found in stream" : 34 | std::string("unexpected serialize tag '") + tag + "' in stream") { 35 | } 36 | }; 37 | 38 | class RawReader : public ByteReader { 39 | public: 40 | explicit RawReader(std::istream &stream) 41 | : ByteReader(stream) { 42 | } 43 | 44 | inline std::string readRaw() { 45 | std::ostringstream stream; 46 | readRawTo(stream); 47 | return stream.str(); 48 | } 49 | 50 | inline void readRawTo(std::ostream &ostream) { 51 | readRaw(ostream, static_cast(stream.get())); 52 | } 53 | 54 | private: 55 | void readRaw(std::ostream &ostream, char tag); 56 | 57 | void readNumberRaw(std::ostream &ostream); 58 | 59 | void readDateTimeRaw(std::ostream &ostream); 60 | 61 | void readUTF8CharRaw(std::ostream &ostream); 62 | 63 | void readStringRaw(std::ostream &ostream); 64 | 65 | void readBytesRaw(std::ostream &ostream); 66 | 67 | void readGUIDRaw(std::ostream &ostream); 68 | 69 | void readComplexRaw(std::ostream &ostream); 70 | }; 71 | 72 | } 73 | } // hprose::io 74 | -------------------------------------------------------------------------------- /hprose/io/Reader-inl.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/io/Reader-inl.h * 13 | * * 14 | * hprose decode funtions for cpp. * 15 | * * 16 | * LastModified: Dec 30, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | namespace hprose { 29 | namespace io { 30 | 31 | inline void decode(bool &b, Reader &reader) { 32 | b = reader.readBool(); 33 | } 34 | 35 | template 36 | inline typename std::enable_if< 37 | std::is_integral::value && 38 | !std::is_same::value 39 | >::type 40 | decode(T &v, Reader &reader) { 41 | v = reader.readInteger(); 42 | } 43 | 44 | template 45 | inline typename std::enable_if< 46 | std::is_enum::value 47 | >::type 48 | decode(T &v, Reader &reader) { 49 | #ifdef HPROSE_HAS_UNDERLYING_TYPE 50 | v = static_cast(reader.readInteger::type>()); 51 | #else // HPROSE_HAS_UNDERLYING_TYPE 52 | v = static_cast(reader.readInteger()); 53 | #endif // HPROSE_HAS_UNDERLYING_TYPE 54 | } 55 | 56 | template 57 | inline typename std::enable_if< 58 | std::is_floating_point::value 59 | >::type 60 | decode(T &v, Reader &reader) { 61 | v = reader.readFloat(); 62 | } 63 | 64 | template 65 | inline void decode(std::complex &v, Reader &reader) { 66 | reader.readComplex(v); 67 | } 68 | 69 | template 70 | inline typename std::enable_if< 71 | std::is_same::value || 72 | std::is_same::value || 73 | std::is_same::value || 74 | std::is_same::value 75 | >::type 76 | decode(T *&v, Reader &reader) { 77 | char tag = static_cast(reader.stream.peek()); 78 | if (tag == TagNull) { 79 | v = nullptr; 80 | } else { 81 | auto str = reader.readString>(); 82 | v = static_cast(malloc((str.size() + 1) * sizeof(T))); 83 | std::copy(str.begin(), str.end(), v); 84 | *(v + str.size()) = 0; 85 | } 86 | } 87 | 88 | template 89 | inline void decode(std::basic_string &v, Reader &reader) { 90 | v = reader.readString>(); 91 | } 92 | 93 | template 94 | inline typename std::enable_if< 95 | std::is_pointer::value 96 | >::type 97 | decode(T &v, Reader &reader) { 98 | char tag = static_cast(reader.stream.peek()); 99 | if (tag == TagNull) { 100 | v = nullptr; 101 | } else if (tag == TagRef) { 102 | reader.readValue(*v); 103 | } else { 104 | v = new typename std::remove_pointer::type(); 105 | reader.readValue(*v); 106 | } 107 | } 108 | 109 | template 110 | inline void decode(std::unique_ptr &v, Reader &reader) { 111 | char tag = static_cast(reader.stream.peek()); 112 | if (tag == TagNull) { 113 | v = nullptr; 114 | } else { 115 | v.reset(new T()); 116 | reader.readValue(*v); 117 | } 118 | } 119 | 120 | template 121 | inline void decode(std::shared_ptr &v, Reader &reader) { 122 | char tag = static_cast(reader.stream.peek()); 123 | if (tag == TagNull) { 124 | v = nullptr; 125 | } else { 126 | v.reset(new T()); 127 | reader.readValue(*v); 128 | } 129 | } 130 | 131 | template 132 | inline void decode(std::weak_ptr &, Reader &) { 133 | throw std::runtime_error("the weak pointer cannot be unserialized"); 134 | } 135 | 136 | template 137 | inline typename std::enable_if< 138 | std::is_array::value 139 | >::type 140 | decode(T &v, Reader &reader) { 141 | reader.readList(v); 142 | } 143 | 144 | template 145 | inline void decode(std::array &v, Reader &reader) { 146 | reader.readList(v); 147 | } 148 | 149 | template 150 | inline void decode(std::vector &v, Reader &reader) { 151 | reader.readList(v); 152 | } 153 | 154 | template 155 | inline void decode(std::deque &v, Reader &reader) { 156 | reader.readList(v); 157 | } 158 | 159 | template 160 | inline void decode(std::forward_list &v, Reader &reader) { 161 | reader.readList(v); 162 | } 163 | 164 | template 165 | inline void decode(std::list &v, Reader &reader) { 166 | reader.readList(v); 167 | } 168 | 169 | template 170 | inline void decode(std::set &v, Reader &reader) { 171 | reader.readList(v); 172 | } 173 | 174 | template 175 | inline void decode(std::multiset &v, Reader &reader) { 176 | reader.readList(v); 177 | } 178 | 179 | template 180 | inline void decode(std::unordered_set &v, Reader &reader) { 181 | reader.readList(v); 182 | } 183 | 184 | template 185 | inline void decode(std::unordered_multiset &v, Reader &reader) { 186 | reader.readList(v); 187 | } 188 | 189 | template 190 | inline void decode(std::bitset &v, Reader &reader) { 191 | reader.readList(v); 192 | }; 193 | 194 | template 195 | inline void decode(std::tuple &v, Reader &reader) { 196 | reader.readList(v); 197 | }; 198 | 199 | template 200 | inline void decode(std::map &v, Reader &reader) { 201 | reader.readMap(v); 202 | } 203 | 204 | template 205 | inline void decode(std::multimap &v, Reader &reader) { 206 | reader.readMap(v); 207 | } 208 | 209 | template 210 | inline void decode(std::unordered_map &v, Reader &reader) { 211 | reader.readMap(v); 212 | } 213 | 214 | template 215 | inline void decode(std::unordered_multimap &v, Reader &reader) { 216 | reader.readMap(v); 217 | } 218 | 219 | } 220 | } // hprose::io 221 | -------------------------------------------------------------------------------- /hprose/io/Reader.cpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/io/Reader.cpp * 13 | * * 14 | * hprose reader unit for cpp. * 15 | * * 16 | * LastModified: Dec 15, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #include 22 | 23 | namespace hprose { 24 | namespace io { 25 | 26 | namespace internal { 27 | 28 | std::string TagToString(char tag) { 29 | switch (tag) { 30 | case '0': 31 | case '1': 32 | case '2': 33 | case '3': 34 | case '4': 35 | case '5': 36 | case '6': 37 | case '7': 38 | case '8': 39 | case '9': 40 | case TagInteger: return "int"; 41 | case TagLong: return "long long"; 42 | case TagDouble: return "double"; 43 | case TagNull: return "null"; 44 | case TagEmpty: return "empty string"; 45 | case TagTrue: return "true"; 46 | case TagFalse: return "false"; 47 | case TagNaN: return "nan"; 48 | case TagInfinity: return "infinity"; 49 | case TagDate: 50 | case TagTime: return "time"; 51 | case TagBytes: return "bytes"; 52 | case TagUTF8Char: 53 | case TagString: return "string"; 54 | case TagGUID: return "uuid"; 55 | case TagList: return "list"; 56 | case TagMap: return "map"; 57 | case TagClass: return "class"; 58 | case TagObject: return "object"; 59 | case TagRef: return "reference"; 60 | default: throw UnexpectedTag(tag); 61 | } 62 | 63 | } 64 | 65 | } // internal 66 | 67 | } 68 | } // hprose::io 69 | -------------------------------------------------------------------------------- /hprose/io/Tags.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/io/Tags.h * 13 | * * 14 | * hprose tags constants for cpp. * 15 | * * 16 | * LastModified: Dec 12, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | namespace hprose { 24 | namespace io { 25 | 26 | /* Serialize Tags */ 27 | const char TagInteger = 'i'; 28 | const char TagLong = 'l'; 29 | const char TagDouble = 'd'; 30 | const char TagNull = 'n'; 31 | const char TagEmpty = 'e'; 32 | const char TagTrue = 't'; 33 | const char TagFalse = 'f'; 34 | const char TagNaN = 'N'; 35 | const char TagInfinity = 'I'; 36 | const char TagDate = 'D'; 37 | const char TagTime = 'T'; 38 | const char TagUTC = 'Z'; 39 | const char TagBytes = 'b'; 40 | const char TagUTF8Char = 'u'; 41 | const char TagString = 's'; 42 | const char TagGUID = 'g'; 43 | const char TagList = 'a'; 44 | const char TagMap = 'm'; 45 | const char TagClass = 'c'; 46 | const char TagObject = 'o'; 47 | const char TagRef = 'r'; 48 | /* Serialize Marks */ 49 | const char TagPos = '+'; 50 | const char TagNeg = '-'; 51 | const char TagSemicolon = ';'; 52 | const char TagOpenbrace = '{'; 53 | const char TagClosebrace = '}'; 54 | const char TagQuote = '"'; 55 | const char TagPoint = '.'; 56 | /* Protocol Tags */ 57 | const char TagFunctions = 'F'; 58 | const char TagCall = 'C'; 59 | const char TagResult = 'R'; 60 | const char TagArgument = 'A'; 61 | const char TagError = 'E'; 62 | const char TagEnd = 'z'; 63 | 64 | } 65 | } // hprose::io 66 | -------------------------------------------------------------------------------- /hprose/io/Writer-inl.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/io/Writer-inl.h * 13 | * * 14 | * hprose encode funtions for cpp. * 15 | * * 16 | * LastModified: Dec 15, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | namespace hprose { 31 | namespace io { 32 | 33 | inline void encode(std::nullptr_t, Writer &writer) { 34 | writer.writeNull(); 35 | } 36 | 37 | inline void encode(bool v, Writer &writer) { 38 | writer.writeBool(v); 39 | } 40 | 41 | template 42 | inline typename std::enable_if< 43 | std::is_integral::value && 44 | !std::is_same::value 45 | >::type 46 | encode(T v, Writer &writer) { 47 | writer.writeInteger(v); 48 | } 49 | 50 | template 51 | inline typename std::enable_if< 52 | std::is_enum::value 53 | >::type 54 | encode(T v, Writer &writer) { 55 | #ifdef HPROSE_HAS_UNDERLYING_TYPE 56 | writer.writeInteger(static_cast::type>(v)); 57 | #else // HPROSE_HAS_UNDERLYING_TYPE 58 | writer.writeInteger(static_cast(v)); 59 | #endif // HPROSE_HAS_UNDERLYING_TYPE 60 | } 61 | 62 | template 63 | inline typename std::enable_if< 64 | std::is_floating_point::value 65 | >::type 66 | encode(T v, Writer &writer) { 67 | writer.writeFloat(v); 68 | } 69 | 70 | template 71 | inline void encode(const std::complex &v, Writer &writer) { 72 | writer.writeComplex(v); 73 | } 74 | 75 | template 76 | inline void encode(const std::ratio &v, Writer &writer) { 77 | writer.writeRatio(v); 78 | } 79 | 80 | template 81 | inline typename std::enable_if< 82 | std::is_same::value || 83 | std::is_same::value || 84 | std::is_same::value || 85 | std::is_same::value 86 | >::type 87 | encode(const T *v, Writer &writer) { 88 | if (v) { 89 | writer.writeString(v); 90 | } else { 91 | writer.writeNull(); 92 | } 93 | } 94 | 95 | template 96 | inline void encode(const std::basic_string &v, Writer &writer) { 97 | writer.writeString(v); 98 | } 99 | 100 | inline void encode(const std::tm &v, Writer &writer) { 101 | writer.writeTime(v); 102 | } 103 | 104 | template 105 | inline void encode(const std::chrono::time_point &v, Writer &writer) { 106 | writer.writeTime(v); 107 | } 108 | 109 | template 110 | inline typename std::enable_if< 111 | std::is_pointer::value 112 | >::type 113 | encode(const T &v, Writer &writer) { 114 | if (v) { 115 | writer.writeValue(*v); 116 | } else { 117 | writer.writeNull(); 118 | } 119 | } 120 | 121 | template 122 | inline void encode(const std::unique_ptr &v, Writer &writer) { 123 | if (v) { 124 | writer.writeValue(*v); 125 | } else { 126 | writer.writeNull(); 127 | } 128 | } 129 | 130 | template 131 | inline void encode(const std::shared_ptr &v, Writer &writer) { 132 | if (v) { 133 | writer.writeValue(*v); 134 | } else { 135 | writer.writeNull(); 136 | } 137 | } 138 | 139 | template 140 | inline void encode(const std::weak_ptr &v, Writer &writer) { 141 | if (auto spt = v.lock()) { 142 | writer.writeValue(*spt); 143 | } else { 144 | throw std::runtime_error("the weak pointer has expired"); 145 | } 146 | } 147 | 148 | template 149 | inline typename std::enable_if< 150 | std::is_array::value 151 | >::type 152 | encode(const T &v, Writer &writer) { 153 | writer.writeList(v); 154 | } 155 | 156 | template 157 | inline void encode(const std::array &v, Writer &writer) { 158 | writer.writeList(v); 159 | } 160 | 161 | template 162 | inline void encode(const std::vector &v, Writer &writer) { 163 | writer.writeList(v); 164 | } 165 | 166 | template 167 | inline void encode(const std::deque &v, Writer &writer) { 168 | writer.writeList(v); 169 | } 170 | 171 | template 172 | inline void encode(const std::forward_list &v, Writer &writer) { 173 | writer.writeList(v); 174 | } 175 | 176 | template 177 | inline void encode(const std::list &v, Writer &writer) { 178 | writer.writeList(v); 179 | } 180 | 181 | template 182 | inline void encode(const std::set &v, Writer &writer) { 183 | writer.writeList(v); 184 | } 185 | 186 | template 187 | inline void encode(const std::multiset &v, Writer &writer) { 188 | writer.writeList(v); 189 | } 190 | 191 | template 192 | inline void encode(const std::unordered_set &v, Writer &writer) { 193 | writer.writeList(v); 194 | } 195 | 196 | template 197 | inline void encode(const std::unordered_multiset &v, Writer &writer) { 198 | writer.writeList(v); 199 | } 200 | 201 | template 202 | inline void encode(const std::bitset &v, Writer &writer) { 203 | writer.writeList(v); 204 | }; 205 | 206 | template 207 | inline void encode(const std::tuple &v, Writer &writer) { 208 | writer.writeList(v); 209 | }; 210 | 211 | template 212 | inline void encode(const std::map &v, Writer &writer) { 213 | writer.writeMap(v); 214 | } 215 | 216 | template 217 | inline void encode(const std::multimap &v, Writer &writer) { 218 | writer.writeMap(v); 219 | } 220 | 221 | template 222 | inline void encode(const std::unordered_map &v, Writer &writer) { 223 | writer.writeMap(v); 224 | } 225 | 226 | template 227 | inline void encode(const std::unordered_multimap &v, Writer &writer) { 228 | writer.writeMap(v); 229 | } 230 | 231 | } 232 | } // hprose::io 233 | -------------------------------------------------------------------------------- /hprose/io/decoders/BoolDecoder.cpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | * * 3 | * hprose/io/decoders/BoolDecoder.cpp * 4 | * * 5 | * hprose bool decoder for cpp. * 6 | * * 7 | * LastModified: Dec 12, 2016 * 8 | * Author: Chen fei * 9 | * * 10 | \**********************************************************/ 11 | 12 | #include 13 | #include 14 | 15 | namespace hprose { 16 | namespace io { 17 | namespace decoders { 18 | 19 | bool parseBool(const std::string &s) { 20 | if (s == "1" || s == "t" || s == "T" || s == "true" || s == "TRUE" || s == "True") { 21 | return true; 22 | } 23 | if (s == "0" || s == "f" || s == "F" || s == "false" || s == "FALSE" || s == "False") { 24 | return false; 25 | } 26 | throw std::runtime_error("parse bool failed"); 27 | } 28 | 29 | bool readNumberAsBool(Reader &reader) { 30 | std::string str = reader.readUntil(TagSemicolon); 31 | if (str.length() == 1) { 32 | return str.at(0) != '0'; 33 | } else { 34 | return true; 35 | } 36 | } 37 | 38 | inline bool readInfinityAsBool(Reader &reader) { 39 | reader.stream.ignore(); 40 | return true; 41 | } 42 | 43 | inline bool readUTF8CharAsBool(Reader &reader) { 44 | return parseBool(reader.readUTF8String(1)); 45 | } 46 | 47 | inline bool readStringAsBool(Reader &reader) { 48 | return parseBool(reader.readStringWithoutTag()); 49 | } 50 | 51 | bool readRefAsBool(Reader &reader) { 52 | const auto &var = reader.readRef(); 53 | if (var.isString()) { 54 | return parseBool(var.getString()); 55 | } 56 | throw std::runtime_error(std::string("value of type ") + var.typeName() + " cannot be converted to type bool"); 57 | } 58 | 59 | bool BoolDecode(Reader &reader, char tag) { 60 | switch (tag) { 61 | case '0': 62 | case TagNull: 63 | case TagEmpty: 64 | case TagFalse: return false; 65 | case '1': 66 | case '2': 67 | case '3': 68 | case '4': 69 | case '5': 70 | case '6': 71 | case '7': 72 | case '8': 73 | case '9': 74 | case TagTrue: 75 | case TagNaN: return true; 76 | case TagInteger: 77 | case TagLong: 78 | case TagDouble: return readNumberAsBool(reader); 79 | case TagInfinity: return readInfinityAsBool(reader); 80 | case TagUTF8Char: return readUTF8CharAsBool(reader); 81 | case TagString: return readStringAsBool(reader); 82 | case TagRef: return readRefAsBool(reader); 83 | default: throw CastError(tag); 84 | } 85 | } 86 | 87 | } 88 | } 89 | } // hprose::io::decoders 90 | -------------------------------------------------------------------------------- /hprose/io/decoders/BoolDecoder.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/io/decoders/BoolDecoder.h * 13 | * * 14 | * hprose bool decoder for cpp. * 15 | * * 16 | * LastModified: Oct 22, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | namespace hprose { 24 | namespace io { 25 | 26 | class Reader; 27 | 28 | namespace decoders { 29 | 30 | bool BoolDecode(Reader &reader, char tag); 31 | 32 | } 33 | } 34 | } // hprose::io::decoders 35 | -------------------------------------------------------------------------------- /hprose/io/decoders/ComplexDecoder-inl.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/io/decoders/ComplexDecoder-inl.h * 13 | * * 14 | * hprose complex decoder for cpp. * 15 | * * 16 | * LastModified: Dec 30, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | namespace hprose { 26 | namespace io { 27 | namespace decoders { 28 | 29 | template 30 | void readLongAsComplex(std::complex &v, Reader &reader) { 31 | v = std::complex(reader.readArithmetic(TagSemicolon)); 32 | } 33 | 34 | template 35 | void readUTF8CharAsComplex(std::complex &v, Reader &reader) { 36 | v = std::complex(util::StringToFloat(reader.readUTF8String(1))); 37 | } 38 | 39 | template 40 | void readStringAsComplex(std::complex &v, Reader &reader) { 41 | v = std::complex(util::StringToFloat(reader.readStringWithoutTag())); 42 | } 43 | 44 | void checkSize(size_t actual, int expected); 45 | 46 | template 47 | void readListAsComplex(std::complex &v, Reader &reader) { 48 | auto count = reader.readCount(); 49 | checkSize(count, 2); 50 | reader.setRef(Ref(v)); 51 | T value; 52 | reader.readValue(value); 53 | v.real(value); 54 | reader.readValue(value); 55 | v.imag(value); 56 | reader.stream.ignore(); 57 | } 58 | 59 | template 60 | void readRefAsComplex(std::complex &v, Reader &reader) { 61 | const auto &var = reader.readRef(); 62 | if (var.isString()) { 63 | v = std::complex(util::StringToFloat(var.getString())); 64 | return; 65 | } 66 | if (var.isRef()) { 67 | const Ref &ref = var.getRef(); 68 | if (typeid(std::complex) == *ref.type) { 69 | v = *static_cast *>(ref.ptr); 70 | return; 71 | } 72 | throw std::runtime_error(std::string("value of type ") + ref.type->name() + " cannot be converted to type " + typeid(T).name()); 73 | } 74 | throw std::runtime_error(std::string("value of type ") + var.typeName() + " cannot be converted to type complex"); 75 | } 76 | 77 | template 78 | void ComplexDecode(std::complex &v, Reader &reader, char tag) { 79 | switch (tag) { 80 | case '0': 81 | case TagNull: 82 | case TagEmpty: 83 | case TagFalse: v = std::complex(); break; 84 | case '1': 85 | case TagTrue: v = std::complex(1); break; 86 | case '2': v = std::complex(2); break; 87 | case '3': v = std::complex(3); break; 88 | case '4': v = std::complex(4); break; 89 | case '5': v = std::complex(5); break; 90 | case '6': v = std::complex(6); break; 91 | case '7': v = std::complex(7); break; 92 | case '8': v = std::complex(8); break; 93 | case '9': v = std::complex(9); break; 94 | case TagNaN: v = std::complex(std::numeric_limits::quiet_NaN()); break; 95 | case TagInfinity: v = std::complex(reader.readInfinity()); break; 96 | case TagInteger: 97 | case TagLong: readLongAsComplex(v, reader); break; 98 | case TagDouble: v = std::complex(reader.ByteReader::readFloat()); break; 99 | case TagUTF8Char: readUTF8CharAsComplex(v, reader); break; 100 | case TagString: readStringAsComplex(v, reader); break; 101 | case TagList: readListAsComplex(v, reader); break; 102 | case TagRef: readRefAsComplex(v, reader); break; 103 | default: throw CastError(tag); 104 | } 105 | } 106 | 107 | } 108 | } 109 | } // hprose::io::decoders 110 | -------------------------------------------------------------------------------- /hprose/io/decoders/ComplexDecoder.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/io/decoders/ComplexDecoder.h * 13 | * * 14 | * hprose complex decoder for cpp. * 15 | * * 16 | * LastModified: Dec 30, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | namespace hprose { 26 | namespace io { 27 | 28 | class Reader; 29 | 30 | namespace decoders { 31 | 32 | template 33 | void ComplexDecode(std::complex &v, Reader &reader, char tag); 34 | 35 | } 36 | } 37 | } // hprose::io::decoders 38 | -------------------------------------------------------------------------------- /hprose/io/decoders/FloatDecoder-inl.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/io/decoders/FloatDecoder-inl.h * 13 | * * 14 | * hprose float decoder for cpp. * 15 | * * 16 | * LastModified: Dec 12, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | namespace hprose { 26 | namespace io { 27 | namespace decoders { 28 | 29 | template 30 | inline typename std::enable_if< 31 | std::is_floating_point::value, 32 | T 33 | >::type 34 | readLongAsFloat(Reader &reader) { 35 | return reader.readArithmetic(TagSemicolon); 36 | } 37 | 38 | template 39 | inline typename std::enable_if< 40 | std::is_floating_point::value, 41 | T 42 | >::type 43 | readUTF8CharAsFloat(Reader &reader) { 44 | return util::StringToFloat(reader.readUTF8String(1)); 45 | } 46 | 47 | template 48 | inline typename std::enable_if< 49 | std::is_floating_point::value, 50 | T 51 | >::type 52 | readStringAsFloat(Reader &reader) { 53 | return util::StringToFloat(reader.readStringWithoutTag()); 54 | } 55 | 56 | template 57 | typename std::enable_if< 58 | std::is_floating_point::value, 59 | T 60 | >::type 61 | readDateTimeAsFloat(Reader &reader) { 62 | auto tm = reader.readDateTimeWithoutTag(); 63 | return mktime(&tm); 64 | } 65 | 66 | template 67 | typename std::enable_if< 68 | std::is_floating_point::value, 69 | T 70 | >::type 71 | readTimeAsFloat(Reader &reader) { 72 | auto tm = reader.readTimeWithoutTag(); 73 | return mktime(&tm); 74 | } 75 | 76 | template 77 | typename std::enable_if< 78 | std::is_floating_point::value, 79 | T 80 | >::type 81 | readRefAsFloat(Reader &reader) { 82 | const auto &var = reader.readRef(); 83 | if (var.isString()) { 84 | return util::StringToFloat(var.getString()); 85 | } 86 | if (var.isTime()) { 87 | auto tm = var.getTime(); 88 | return mktime(&tm); 89 | } 90 | throw std::runtime_error(std::string("value of type ") + var.typeName() + " cannot be converted to type float"); 91 | } 92 | 93 | template 94 | typename std::enable_if< 95 | std::is_floating_point::value, 96 | T 97 | >::type 98 | FloatDecode(Reader &reader, char tag) { 99 | switch (tag) { 100 | case '0': 101 | case TagNull: 102 | case TagEmpty: 103 | case TagFalse: return 0; 104 | case '1': 105 | case TagTrue: return 1; 106 | case '2': return 2; 107 | case '3': return 3; 108 | case '4': return 4; 109 | case '5': return 5; 110 | case '6': return 6; 111 | case '7': return 7; 112 | case '8': return 8; 113 | case '9': return 9; 114 | case TagNaN: return std::numeric_limits::quiet_NaN(); 115 | case TagInfinity: return reader.readInfinity(); 116 | case TagInteger: 117 | case TagLong: return readLongAsFloat(reader); 118 | case TagDouble: return reader.ByteReader::readFloat(); 119 | case TagUTF8Char: return readUTF8CharAsFloat(reader); 120 | case TagString: return readStringAsFloat(reader); 121 | case TagDate: return readDateTimeAsFloat(reader); 122 | case TagTime: return readTimeAsFloat(reader); 123 | case TagRef: return readRefAsFloat(reader); 124 | default: throw CastError(tag); 125 | } 126 | } 127 | 128 | } 129 | } 130 | } // hprose::io::decoders 131 | -------------------------------------------------------------------------------- /hprose/io/decoders/FloatDecoder.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/io/decoders/FloatDecoder.h * 13 | * * 14 | * hprose float decoder for cpp. * 15 | * * 16 | * LastModified: Oct 27, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | namespace hprose { 26 | namespace io { 27 | 28 | class Reader; 29 | 30 | namespace decoders { 31 | 32 | template 33 | typename std::enable_if< 34 | std::is_floating_point::value, 35 | T 36 | >::type 37 | FloatDecode(Reader &reader, char tag); 38 | 39 | } 40 | } 41 | } // hprose::io::decoders 42 | -------------------------------------------------------------------------------- /hprose/io/decoders/IntDecoder.cpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | * * 3 | * hprose/io/decoders/IntDecoder.cpp * 4 | * * 5 | * hprose int decoder for cpp. * 6 | * * 7 | * LastModified: Dec 12, 2016 * 8 | * Author: Chen fei * 9 | * * 10 | \**********************************************************/ 11 | 12 | #include 13 | #include 14 | 15 | namespace hprose { 16 | namespace io { 17 | namespace decoders { 18 | 19 | inline int64_t readInt64(Reader &reader) { 20 | return reader.readArithmetic(TagSemicolon); 21 | } 22 | 23 | inline int64_t readDoubleAsInt(Reader &reader) { 24 | return static_cast(reader.ByteReader::readFloat()); 25 | } 26 | 27 | inline int64_t readUTF8CharAsInt(Reader &reader) { 28 | return std::stoll(reader.readUTF8String(1)); 29 | } 30 | 31 | inline int64_t readStringAsInt(Reader &reader) { 32 | return std::stoll(reader.readStringWithoutTag()); 33 | } 34 | 35 | int64_t readDateTimeAsInt(Reader &reader) { 36 | auto tm = reader.readDateTimeWithoutTag(); 37 | return mktime(&tm); 38 | } 39 | 40 | int64_t readTimeAsInt(Reader &reader) { 41 | auto tm = reader.readTimeWithoutTag(); 42 | return mktime(&tm); 43 | } 44 | 45 | int64_t readRefAsInt(Reader &reader) { 46 | const auto &var = reader.readRef(); 47 | if (var.isString()) { 48 | return std::stoll(var.getString()); 49 | } 50 | if (var.isTime()) { 51 | auto tm = var.getTime(); 52 | return mktime(&tm); 53 | } 54 | throw std::runtime_error(std::string("value of type ") + var.typeName() + " cannot be converted to type int"); 55 | } 56 | 57 | int64_t IntDecode(Reader &reader, char tag) { 58 | switch (tag) { 59 | case '0': 60 | case TagNull: 61 | case TagEmpty: 62 | case TagFalse: return 0; 63 | case '1': 64 | case TagTrue: return 1; 65 | case '2': return 2; 66 | case '3': return 3; 67 | case '4': return 4; 68 | case '5': return 5; 69 | case '6': return 6; 70 | case '7': return 7; 71 | case '8': return 8; 72 | case '9': return 9; 73 | case TagInteger: 74 | case TagLong: return readInt64(reader); 75 | case TagDouble: return readDoubleAsInt(reader); 76 | case TagUTF8Char: return readUTF8CharAsInt(reader); 77 | case TagString: return readStringAsInt(reader); 78 | case TagDate: return readDateTimeAsInt(reader); 79 | case TagTime: return readTimeAsInt(reader); 80 | case TagRef: return readRefAsInt(reader); 81 | default: throw CastError(tag); 82 | } 83 | } 84 | 85 | } 86 | } 87 | } // hprose::io::decoders 88 | -------------------------------------------------------------------------------- /hprose/io/decoders/IntDecoder.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/io/decoders/IntDecoder.h * 13 | * * 14 | * hprose int decoder for cpp. * 15 | * * 16 | * LastModified: Oct 25, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | namespace hprose { 26 | namespace io { 27 | 28 | class Reader; 29 | 30 | namespace decoders { 31 | 32 | int64_t IntDecode(Reader &reader, char tag); 33 | 34 | } 35 | } 36 | } // hprose::io::decoders 37 | -------------------------------------------------------------------------------- /hprose/io/decoders/ListDecoder-inl.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/io/decoders/ListDecoder-inl.h * 13 | * * 14 | * hprose list decoder for cpp. * 15 | * * 16 | * LastModified: Dec 26, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | namespace hprose { 32 | namespace io { 33 | namespace decoders { 34 | 35 | inline void checkSize(size_t actual, int expected) { 36 | if (static_cast(expected) != actual) 37 | throw std::runtime_error("expected array size " + std::to_string(expected) 38 | + ", actual size " + std::to_string(expected)); 39 | } 40 | 41 | template 42 | inline void makeSize(T &v, int count) { 43 | v.resize(count); 44 | } 45 | 46 | template 47 | inline void makeSize(T (&v)[N], int count) { 48 | (void)v; 49 | checkSize(N, count); 50 | } 51 | 52 | template 53 | inline void makeSize(std::array &, int count) { 54 | checkSize(N, count); 55 | } 56 | 57 | template 58 | void readBytes(T &v, Reader &reader) { 59 | auto len = reader.readLength(); 60 | auto str = reader.read(len); 61 | makeSize(v, len); 62 | std::copy(str.cbegin(), str.cend(), &v[0]); // Todo: avoid copy 63 | reader.stream.ignore(); 64 | } 65 | 66 | template 67 | void readList(T &v, Reader &reader) { 68 | auto count = reader.readCount(); 69 | makeSize(v, count); 70 | reader.setRef(Ref(v)); 71 | for(auto &e : v) { 72 | reader.readValue(e); 73 | } 74 | reader.stream.ignore(); 75 | } 76 | 77 | template 78 | void readListAsSet(T &v, Reader &reader) { 79 | auto count = reader.readCount(); 80 | for(auto i = 0; i < count; ++i) { 81 | typename T::key_type key; 82 | reader.readValue(key); 83 | v.insert(std::move(key)); 84 | } 85 | reader.stream.ignore(); 86 | } 87 | 88 | template 89 | inline void readList(std::set &v, Reader &reader) { 90 | readListAsSet(v, reader); 91 | } 92 | 93 | template 94 | inline void readList(std::multiset &v, Reader &reader) { 95 | readListAsSet(v, reader); 96 | } 97 | 98 | template 99 | inline void readList(std::unordered_set &v, Reader &reader) { 100 | readListAsSet(v, reader); 101 | } 102 | 103 | template 104 | inline void readList(std::unordered_multiset &v, Reader &reader) { 105 | readListAsSet(v, reader); 106 | } 107 | 108 | template 109 | inline void readList(std::bitset &v, Reader &reader) { 110 | auto count = reader.readCount(); 111 | checkSize(N, count); 112 | for(auto i = 0; i < count; ++i) { 113 | v.set(i, reader.unserialize()); 114 | } 115 | reader.stream.ignore(); 116 | }; 117 | 118 | template 119 | inline typename std::enable_if< 120 | Index == sizeof...(Tuple) 121 | >::type 122 | readTupleElement(std::tuple &, Reader &) { 123 | } 124 | 125 | template 126 | inline typename std::enable_if< 127 | Index < sizeof...(Tuple) 128 | >::type 129 | readTupleElement(std::tuple &tuple, Reader &reader) { 130 | reader.readValue(std::get(tuple)); 131 | readTupleElement(tuple, reader); 132 | } 133 | 134 | template 135 | void readList(std::tuple &lst, Reader &reader) { 136 | auto count = reader.readCount(); 137 | checkSize(std::tuple_size >::value, count); 138 | readTupleElement(lst, reader); 139 | reader.stream.ignore(); 140 | } 141 | 142 | template 143 | void readRefAsList(T &v, Reader &reader) { 144 | const auto &var = reader.readRef(); 145 | if (var.isRef()) { 146 | const Ref &ref = var.getRef(); 147 | if (typeid(T) == *ref.type) { 148 | v = *static_cast(ref.ptr); 149 | return; 150 | } 151 | throw std::runtime_error(std::string("value of type ") + ref.type->name() + " cannot be converted to type " + typeid(T).name()); 152 | } 153 | throw std::runtime_error(std::string("value of type ") + var.typeName() + " cannot be converted to type list"); 154 | } 155 | 156 | namespace detail { 157 | 158 | template 159 | void ListDecode(T &v, Reader &reader, char tag) { 160 | switch (tag) { 161 | case TagList: readList(v, reader); break; 162 | case TagRef: readRefAsList(v, reader); break; 163 | default: throw CastError(tag); 164 | } 165 | } 166 | 167 | template 168 | void ListDecode(T (&v)[N], Reader &reader, char tag) { 169 | switch (tag) { 170 | case TagList: readList(v, reader); break; 171 | default: throw CastError(tag); 172 | } 173 | } 174 | 175 | template 176 | void ListDecode(uint8_t (&v)[N], Reader &reader, char tag) { 177 | switch (tag) { 178 | case TagBytes: readBytes(v, reader); break; 179 | case TagList: readList(v, reader); break; 180 | default: throw CastError(tag); 181 | } 182 | } 183 | 184 | template 185 | void ListDecode(std::array &v, Reader &reader, char tag) { 186 | switch (tag) { 187 | case TagBytes: readBytes(v, reader); break; 188 | case TagList: readList(v, reader); break; 189 | case TagRef: readRefAsList(v, reader); break; 190 | default: throw CastError >(tag); 191 | } 192 | } 193 | 194 | template 195 | void ListDecode(std::vector &v, Reader &reader, char tag) { 196 | switch (tag) { 197 | case TagBytes: readBytes(v, reader); break; 198 | case TagList: readList(v, reader); break; 199 | case TagRef: readRefAsList(v, reader); break; 200 | default: throw CastError >(tag); 201 | } 202 | } 203 | 204 | } // detail 205 | 206 | template 207 | inline void ListDecode(T &v, Reader &reader, char tag) { 208 | detail::ListDecode(v, reader, tag); 209 | } 210 | 211 | } 212 | } 213 | } // hprose::io::decoders 214 | -------------------------------------------------------------------------------- /hprose/io/decoders/ListDecoder.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/io/decoders/ListDecoder.h * 13 | * * 14 | * hprose list decoder for cpp. * 15 | * * 16 | * LastModified: Nov 14, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | namespace hprose { 24 | namespace io { 25 | 26 | class Reader; 27 | 28 | namespace decoders { 29 | 30 | template 31 | void ListDecode(T &v, Reader &reader, char tag); 32 | 33 | } 34 | } 35 | } // hprose::io::decoders 36 | -------------------------------------------------------------------------------- /hprose/io/decoders/MapDecoder-inl.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/io/decoders/MapDecoder-inl.h * 13 | * * 14 | * hprose map decoder for cpp. * 15 | * * 16 | * LastModified: Dec 26, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | namespace hprose { 24 | namespace io { 25 | namespace decoders { 26 | 27 | template 28 | inline void setIntKey(T &, int) { 29 | throw std::runtime_error(std::string("cannot convert int to type ") + typeid(T).name()); 30 | } 31 | 32 | template 33 | inline typename std::enable_if< 34 | std::is_integral::value && 35 | !std::is_same::value 36 | >::type 37 | setIntKey(T &v, int i) { 38 | v = i; 39 | } 40 | 41 | inline void setIntKey(std::string &str, int i) { 42 | str = std::to_string(i); 43 | } 44 | 45 | template 46 | void readListAsMap(T &v, Reader &reader) { 47 | auto count = reader.readCount(); 48 | reader.setRef(Ref(v)); 49 | for (auto i = 0; i < count; ++i) { 50 | typename T::key_type key; 51 | setIntKey(key, i); 52 | typename T::mapped_type value; 53 | reader.readValue(value); 54 | v.insert({key, value}); 55 | } 56 | reader.stream.ignore(); 57 | } 58 | 59 | template 60 | void readMap(T &v, Reader &reader) { 61 | auto count = reader.readCount(); 62 | reader.setRef(Ref(v)); 63 | for (auto i = 0; i < count; ++i) { 64 | typename T::key_type key; 65 | reader.readValue(key); 66 | typename T::mapped_type value; 67 | reader.readValue(value); 68 | v.insert({key, value}); 69 | } 70 | reader.stream.ignore(); 71 | } 72 | 73 | template 74 | void readClass(T &v, Reader &reader) { 75 | auto className = reader.ByteReader::readString(); 76 | auto classManager = ClassManager::SharedInstance(); 77 | auto classType = classManager.getClassType(className); 78 | if (!classType) { 79 | throw std::runtime_error("cannot convert " + className + " to type " + typeid(T).name()); 80 | } 81 | const auto &classCache = classManager.getClassCache(*classType); 82 | auto fieldMap = classCache.fieldMap; 83 | auto count = reader.readCount(); 84 | std::vector fields; 85 | for (auto i = 0; i < count; ++i) { 86 | auto fieldName = reader.readString(); 87 | fields.push_back(fieldMap[fieldName]); 88 | } 89 | reader.fieldsRef.push_back(fields); 90 | reader.stream.ignore(); 91 | reader.readValue(v); 92 | } 93 | 94 | template 95 | void readObjectAsMap(T &v, Reader &reader) { 96 | auto index = reader.readCount(); 97 | auto fields = reader.fieldsRef[index]; 98 | reader.setRef(Ref(v)); 99 | for (auto &field : fields) { 100 | v[field.alias] = reader.unserialize(); 101 | } 102 | reader.stream.ignore(); 103 | } 104 | 105 | template 106 | void readRefAsMap(T &v, Reader &reader) { 107 | const auto &var = reader.readRef(); 108 | if (var.isRef()) { 109 | const Ref &ref = var.getRef(); 110 | if (typeid(T) == *ref.type) { 111 | v = *static_cast(ref.ptr); 112 | return; 113 | } 114 | throw std::runtime_error(std::string("value of type ") + ref.type->name() + " cannot be converted to type " + typeid(T).name()); 115 | } 116 | throw std::runtime_error(std::string("value of type ") + var.typeName() + " cannot be converted to type map"); 117 | } 118 | 119 | template 120 | inline void MapDecode(T &v, Reader &reader, char tag) { 121 | switch (tag) { 122 | case TagList: readListAsMap(v, reader); break; 123 | case TagMap: readMap(v, reader); break; 124 | case TagClass: readClass(v, reader); break; 125 | case TagObject: readObjectAsMap(v, reader); break; 126 | case TagRef: readRefAsList(v, reader); break; 127 | default: throw CastError(tag); 128 | } 129 | } 130 | 131 | } 132 | } 133 | } // hprose::io::decoders 134 | -------------------------------------------------------------------------------- /hprose/io/decoders/MapDecoder.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/io/decoders/MapDecoder.h * 13 | * * 14 | * hprose map decoder for cpp. * 15 | * * 16 | * LastModified: Nov 14, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | namespace hprose { 24 | namespace io { 25 | 26 | class Reader; 27 | 28 | namespace decoders { 29 | 30 | template 31 | void MapDecode(T &v, Reader &reader, char tag); 32 | 33 | } 34 | } 35 | } // hprose::io::decoders 36 | -------------------------------------------------------------------------------- /hprose/io/decoders/ObjectDecoder-inl.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/io/decoders/ObjectDecoder-inl.h * 13 | * * 14 | * hprose object decoder for cpp. * 15 | * * 16 | * LastModified: Dec 26, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | namespace hprose { 24 | namespace io { 25 | namespace decoders { 26 | 27 | template 28 | void readMapAsObject(T &, Reader &) { 29 | } 30 | 31 | template 32 | void readObject(T &v, Reader &reader) { 33 | auto index = reader.readCount(); 34 | auto fields = reader.fieldsRef[index]; 35 | reader.setRef(Ref(v)); 36 | for (auto &field : fields) { 37 | field.decode(&v, reader); 38 | } 39 | reader.stream.ignore(); 40 | } 41 | 42 | template 43 | void readRefAsObject(T &v, Reader &reader) { 44 | const auto &var = reader.readRef(); 45 | if (var.isRef()) { 46 | const Ref &ref = var.getRef(); 47 | if (typeid(T) == *ref.type) { 48 | v = *static_cast(ref.ptr); 49 | return; 50 | } 51 | throw std::runtime_error(std::string("value of type ") + ref.type->name() + " cannot be converted to type " + typeid(T).name()); 52 | } 53 | throw std::runtime_error(std::string("value of type ") + var.typeName() + " cannot be converted to type " + typeid(T).name()); 54 | } 55 | 56 | template 57 | inline void ObjectDecode(T &v, Reader &reader, char tag) { 58 | switch (tag) { 59 | case TagMap: readMapAsObject(v, reader); break; 60 | case TagClass: readClass(v, reader); break; 61 | case TagObject: readObject(v, reader); break; 62 | case TagRef: readRefAsObject(v, reader); break; 63 | default: throw CastError(tag); 64 | } 65 | } 66 | 67 | } 68 | } 69 | } // hprose::io::decoders 70 | -------------------------------------------------------------------------------- /hprose/io/decoders/ObjectDecoder.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/io/decoders/ObjectDecoder.h * 13 | * * 14 | * hprose object decoder for cpp. * 15 | * * 16 | * LastModified: Dec 18, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | namespace hprose { 24 | namespace io { 25 | 26 | class Reader; 27 | 28 | namespace decoders { 29 | 30 | template 31 | void ObjectDecode(T &v, Reader &reader, char tag); 32 | 33 | } 34 | } 35 | } // hprose::io::decoders 36 | -------------------------------------------------------------------------------- /hprose/io/decoders/StringDecoder.cpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/io/decoders/StringDecoder.cpp * 13 | * * 14 | * hprose string decoder for cpp. * 15 | * * 16 | * LastModified: Dec 12, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #include 22 | #include 23 | 24 | namespace hprose { 25 | namespace io { 26 | namespace decoders { 27 | 28 | inline std::string readInfAsString(Reader &reader) { 29 | return reader.stream.get() == TagPos ? "+Inf" : "-Inf"; 30 | } 31 | 32 | inline std::string readNumberAsString(Reader &reader) { 33 | return reader.readUntil(TagSemicolon); 34 | } 35 | 36 | inline std::string readUTF8CharAsString(Reader &reader) { 37 | return reader.readUTF8String(1); 38 | } 39 | 40 | std::string readBytesAsString(Reader &reader) { 41 | auto len = reader.readLength(); 42 | auto s = reader.read(len); 43 | reader.setRef(s); 44 | return s; 45 | } 46 | 47 | std::string readGUIDAsString(Reader &reader) { 48 | reader.stream.ignore(); 49 | auto s = reader.read(36); 50 | reader.stream.ignore(); 51 | reader.setRef(s); 52 | return s; 53 | } 54 | 55 | inline std::string readDateTimeAsString(Reader &reader) { 56 | auto tm = reader.readDateTimeWithoutTag(); 57 | return std::asctime(&tm); 58 | } 59 | 60 | inline std::string readTimeAsString(Reader &reader) { 61 | auto tm = reader.readTimeWithoutTag(); 62 | return std::asctime(&tm); 63 | } 64 | 65 | std::string readRefAsString(Reader &reader) { 66 | const auto &var = reader.readRef(); 67 | if (var.isString()) { 68 | return var.getString(); 69 | } 70 | if (var.isTime()) { 71 | auto tm = var.getTime(); 72 | return std::asctime(&tm); 73 | } 74 | throw std::runtime_error(std::string("value of type ") + var.typeName() + " cannot be converted to type string"); 75 | } 76 | 77 | std::string StringDecode(Reader &reader, char tag) { 78 | switch (tag) { 79 | case '0': return "0"; 80 | case '1': return "1"; 81 | case '2': return "2"; 82 | case '3': return "3"; 83 | case '4': return "4"; 84 | case '5': return "5"; 85 | case '6': return "6"; 86 | case '7': return "7"; 87 | case '8': return "8"; 88 | case '9': return "9"; 89 | case TagNull: 90 | case TagEmpty: return ""; 91 | case TagFalse: return "false"; 92 | case TagTrue: return "true"; 93 | case TagInfinity: return readInfAsString(reader); 94 | case TagInteger: 95 | case TagLong: 96 | case TagDouble: return readNumberAsString(reader); 97 | case TagUTF8Char: return readUTF8CharAsString(reader); 98 | case TagString: return reader.readStringWithoutTag(); 99 | case TagBytes: return readBytesAsString(reader); 100 | case TagGUID: return readGUIDAsString(reader); 101 | case TagDate: return readDateTimeAsString(reader); 102 | case TagTime: return readTimeAsString(reader); 103 | case TagRef: return readRefAsString(reader); 104 | default: throw CastError(tag); 105 | } 106 | } 107 | 108 | } 109 | } 110 | } // hprose::io::decoders 111 | -------------------------------------------------------------------------------- /hprose/io/decoders/StringDecoder.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/io/decoders/StringDecoder.h * 13 | * * 14 | * hprose string decoder for cpp. * 15 | * * 16 | * LastModified: Nov 9, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | namespace hprose { 26 | namespace io { 27 | 28 | class Reader; 29 | 30 | namespace decoders { 31 | 32 | std::string StringDecode(Reader &reader, char tag); 33 | 34 | } 35 | } 36 | } // hprose::io::decoders 37 | -------------------------------------------------------------------------------- /hprose/rpc/Client.cpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/rpc/Client.cpp * 13 | * * 14 | * hprose rpc client for cpp. * 15 | * * 16 | * LastModified: Dec 8, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #include 22 | 23 | namespace hprose { 24 | namespace rpc { 25 | 26 | ClientContext Client::getContext(const InvokeSettings *settings) { 27 | auto context = ClientContext(*this); 28 | if (settings) { 29 | context.settings = *settings; 30 | if (settings->retry <= 0) { 31 | context.settings.retry = retry; 32 | } 33 | if (settings->timeout <= 0) { 34 | context.settings.timeout = timeout; 35 | } 36 | } else { 37 | context.settings.retry = retry; 38 | context.settings.timeout = timeout; 39 | } 40 | return context; 41 | } 42 | 43 | std::string Client::sendRequest(const std::string &request, const ClientContext &context) { 44 | return sendAndReceive(request, context); 45 | } 46 | 47 | } 48 | } // hprose::rpc 49 | -------------------------------------------------------------------------------- /hprose/rpc/Client.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/rpc/Client.h * 13 | * * 14 | * hprose rpc client header for cpp. * 15 | * * 16 | * LastModified: Dec 16, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | namespace hprose { 36 | namespace rpc { 37 | 38 | template 39 | struct is_future : std::false_type { 40 | }; 41 | 42 | template 43 | struct is_future> : std::true_type { 44 | }; 45 | 46 | template 47 | struct result_of_future { 48 | }; 49 | 50 | template 51 | struct result_of_future> { 52 | typedef T type; 53 | }; 54 | 55 | class Client; 56 | 57 | enum ResultMode { 58 | Normal, 59 | Serialized, 60 | Raw, 61 | RawWithEndTag 62 | }; 63 | 64 | struct InvokeSettings { 65 | ResultMode mode; 66 | bool async; 67 | bool byref; 68 | bool simple; 69 | bool idempotent; 70 | bool failswitch; 71 | bool oneway; 72 | int retry; 73 | int timeout; 74 | }; 75 | 76 | class ClientContext : Context { 77 | public: 78 | ClientContext(const Client &client) 79 | : retried(0), settings(InvokeSettings()), client(client) { 80 | } 81 | 82 | const Client &getClient() { 83 | return client; 84 | } 85 | 86 | int retried; 87 | InvokeSettings settings; 88 | 89 | private: 90 | const Client &client; 91 | }; 92 | 93 | class Client { 94 | public: 95 | inline const std::string &getUri() const { 96 | return uri; 97 | } 98 | 99 | inline void setUri(const std::string &uri) { 100 | setUriList({uri}); 101 | } 102 | 103 | inline const std::vector &getUriList() const { 104 | return uriList; 105 | } 106 | 107 | void setUriList(std::vector uriList) { 108 | if (uriList.size() > 1) { 109 | std::random_device rd; 110 | std::mt19937 g(rd()); 111 | std::shuffle(uriList.begin(), uriList.end(), g); 112 | } 113 | index = 0; 114 | failround = 0; 115 | uri = uriList[0]; 116 | this->uriList = std::move(uriList); 117 | } 118 | 119 | inline int getFailround() const { 120 | return failround; 121 | } 122 | 123 | template 124 | typename std::enable_if< 125 | !std::is_void::value && 126 | !is_future::value, 127 | R 128 | >::type 129 | invoke(const std::string &name, const std::vector &args, const InvokeSettings *settings = nullptr) { 130 | auto context = getContext(settings); 131 | if (context.settings.oneway) { 132 | throw std::runtime_error("oneway must return void type"); 133 | } 134 | auto request = encode(name, args, context); 135 | auto response = sendRequest(request, context); 136 | return decode(response, args, context); 137 | } 138 | 139 | template 140 | typename std::enable_if< 141 | std::is_void::value 142 | >::type 143 | invoke(const std::string &name, const std::vector &args, const InvokeSettings *settings = nullptr) { 144 | auto context = getContext(settings); 145 | auto request = encode(name, args, context); 146 | sendRequest(request, context); 147 | } 148 | 149 | template 150 | typename std::enable_if< 151 | is_future::value, 152 | R 153 | >::type 154 | invoke(const std::string &name, const std::vector &args, const InvokeSettings *settings = nullptr) { 155 | #ifdef HPROSE_HAS_LAMBDA_CAPTURE 156 | return std::async(std::launch::async, [=] { 157 | #else // HPROSE_HAS_LAMBDA_CAPTURE 158 | return std::async(std::launch::async, [this, name, args, settings]() { 159 | #endif // HPROSE_HAS_LAMBDA_CAPTURE 160 | return invoke::type>(name, args, settings); 161 | }); 162 | } 163 | 164 | int retry; 165 | int timeout; 166 | 167 | protected: 168 | Client(const std::string &uri) 169 | : retry(10), timeout(30) { 170 | setUri(uri); 171 | } 172 | 173 | Client(const std::vector &uriList) 174 | : retry(10), timeout(30) { 175 | setUriList(uriList); 176 | } 177 | 178 | virtual std::string sendAndReceive(const std::string &request, const ClientContext &context) = 0; 179 | 180 | std::string uri; 181 | std::vector uriList; 182 | std::vector filters; 183 | 184 | private: 185 | ClientContext getContext(const InvokeSettings *settings); 186 | 187 | std::string sendRequest(const std::string &request, const ClientContext &context); 188 | 189 | template 190 | std::string encode(const std::string &name, const std::vector &args, const ClientContext &context) { 191 | std::ostringstream stream; 192 | io::Writer writer(stream, context.settings.simple); 193 | stream << io::TagCall; 194 | writer.writeString(name); 195 | if (!args.empty() || context.settings.byref) { 196 | writer.reset(); 197 | writer.writeList(args); 198 | if (context.settings.byref) { 199 | writer.writeBool(true); 200 | } 201 | } 202 | stream << io::TagEnd; 203 | return stream.str(); 204 | } 205 | 206 | template 207 | typename std::enable_if< 208 | !std::is_same::value, 209 | R 210 | >::type 211 | decode(const std::string &data, const std::vector &args, const ClientContext &context) { 212 | (void)args; 213 | checkData(data); 214 | if (context.settings.mode != Normal) { 215 | throw std::runtime_error("only normal mode can return non string type"); 216 | } 217 | 218 | R result; 219 | std::istringstream stream(data); 220 | io::Reader reader(stream); 221 | auto tag = reader.stream.get(); 222 | if (tag == io::TagResult) { 223 | reader.unserialize(result); 224 | tag = reader.stream.get(); 225 | if (tag == io::TagArgument) { 226 | 227 | } 228 | } else if (tag == io::TagError) { 229 | throw std::runtime_error(reader.readString()); 230 | } 231 | if (tag != io::TagEnd) { 232 | throw std::runtime_error("wrong response: \r\n" + data); 233 | } 234 | return result; 235 | } 236 | 237 | template 238 | typename std::enable_if< 239 | std::is_same::value, 240 | std::string 241 | >::type 242 | decode(const std::string &data, const std::vector &args, const ClientContext &context) { 243 | (void)args; 244 | checkData(data); 245 | if (context.settings.mode == RawWithEndTag) { 246 | return data; 247 | } else if (context.settings.mode == Raw) { 248 | return data.substr(0, data.size() - 1); 249 | } 250 | 251 | std::string result; 252 | std::istringstream stream(data); 253 | io::Reader reader(stream); 254 | auto tag = reader.stream.get(); 255 | if (tag == io::TagResult) { 256 | if (context.settings.mode == Normal) { 257 | reader.unserialize(result); 258 | } else if (context.settings.mode == Serialized) { 259 | result = reader.readRaw(); 260 | } 261 | tag = reader.stream.get(); 262 | if (tag == io::TagArgument) { 263 | 264 | } 265 | } else if (tag == io::TagError) { 266 | throw std::runtime_error(reader.readString()); 267 | } 268 | if (tag != io::TagEnd) { 269 | throw std::runtime_error("wrong response: \r\n" + data); 270 | } 271 | return result; 272 | } 273 | 274 | void checkData(const std::string &data) { 275 | if (data.empty()) { 276 | throw std::runtime_error("unexpected eof"); 277 | } 278 | if (data[data.size() - 1] != io::TagEnd) { 279 | throw std::runtime_error("wrong response: \r\n" + data); 280 | } 281 | } 282 | 283 | int index; 284 | int failround; 285 | }; 286 | 287 | } 288 | } // hprose::rpc 289 | -------------------------------------------------------------------------------- /hprose/rpc/Context.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/rpc/Context.h * 13 | * * 14 | * hprose rpc context for cpp. * 15 | * * 16 | * LastModified: Dec 8, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | namespace hprose { 24 | namespace rpc { 25 | 26 | class Context { 27 | 28 | }; 29 | 30 | } 31 | } // hprose::rpc 32 | -------------------------------------------------------------------------------- /hprose/rpc/Filter.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/rpc/Filter.h * 13 | * * 14 | * hprose rpc filter for cpp. * 15 | * * 16 | * LastModified: Dec 14, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | namespace hprose { 24 | namespace rpc { 25 | 26 | class Filter { 27 | virtual std::string inputFilter(const std::string &data, const Context &context) = 0; 28 | 29 | virtual std::string outputFilter(const std::string &data, const Context &context) = 0; 30 | }; 31 | 32 | } 33 | } // hprose::rpc 34 | -------------------------------------------------------------------------------- /hprose/rpc/asio/HttpClient.cpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/rpc/asio/HttpClient.cpp * 13 | * * 14 | * hprose asio http client for cpp. * 15 | * * 16 | * LastModified: Nov 29, 2017 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #include 22 | 23 | namespace hprose { 24 | namespace rpc { 25 | namespace asio { 26 | 27 | std::string HttpClient::sendAndReceive(const std::string &data, const ClientContext &context) { 28 | http::Request req("POST", uri, data); 29 | req.header.insert(header.begin(), header.end()); 30 | req.header.set("Content-Type", "application/hprose"); 31 | client.setTimeout(context.settings.timeout); 32 | auto response = client.execute(req); 33 | return response.body; 34 | } 35 | 36 | } 37 | } 38 | } // hprose::rpc::asio 39 | -------------------------------------------------------------------------------- /hprose/rpc/asio/HttpClient.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/rpc/asio/HttpClient.h * 13 | * * 14 | * hprose asio http client for cpp. * 15 | * * 16 | * LastModified: Dec 3, 2017 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | 29 | namespace hprose { 30 | namespace rpc { 31 | namespace asio { 32 | 33 | class HttpClient : public Client { 34 | public: 35 | HttpClient(const std::string &uri) 36 | : Client(uri) { 37 | } 38 | 39 | HttpClient(const std::vector &uriList) 40 | : Client(uriList) { 41 | } 42 | 43 | inline bool getKeepAlive() { 44 | return client.getTransport().keepAlive; 45 | } 46 | 47 | inline void setKeepAlive(bool enable) { 48 | client.getTransport().keepAlive = enable; 49 | } 50 | 51 | inline bool getCompression() { 52 | return client.getTransport().compression; 53 | } 54 | 55 | inline void setCompression(bool enable) { 56 | client.getTransport().compression = enable; 57 | } 58 | 59 | http::Header header; 60 | 61 | protected: 62 | std::string sendAndReceive(const std::string &data, const ClientContext &context); 63 | 64 | private: 65 | http::asio::Client client; 66 | }; 67 | 68 | } 69 | } 70 | } // hprose::rpc::asio 71 | -------------------------------------------------------------------------------- /hprose/rpc/asio/test/HttpClientTest.cpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * HttpClientTest.cpp * 13 | * * 14 | * hprose asio http client test for cpp. * 15 | * * 16 | * LastModified: Dec 9, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #include 22 | 23 | #include 24 | 25 | using hprose::rpc::InvokeSettings; 26 | using hprose::rpc::asio::HttpClient; 27 | 28 | TEST(HttpClient, Basic) { 29 | HttpClient client("http://hprose.com/example/"); 30 | auto result = client.invoke("hello", std::vector({"world"})); 31 | EXPECT_EQ(result, "Hello world"); 32 | } 33 | 34 | TEST(HttpClient, Async) { 35 | HttpClient client("http://hprose.com/example/"); 36 | auto result = client.invoke >("hello", std::vector({"world"})); 37 | EXPECT_EQ(result.get(), "Hello world"); 38 | } 39 | -------------------------------------------------------------------------------- /hprose/test/VariantTest.cpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * VariantTest.cpp * 13 | * * 14 | * hprose variant test for cpp. * 15 | * * 16 | * LastModified: Nov 10, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #include 22 | 23 | #include 24 | 25 | TEST(Variant, Default) { 26 | hprose::Variant var; 27 | EXPECT_TRUE(var.isNull()); 28 | } -------------------------------------------------------------------------------- /hprose/util/Config.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/util/Config.h * 13 | * * 14 | * some compiler config for cpp. * 15 | * * 16 | * LastModified: May 22, 2017 * 17 | * Author: xiaoyur347 * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | // compiler macros 24 | #if defined(__GNUC__) 25 | #include // for _GLIBCXX_USE_C99 26 | #if defined(__clang__) || __GNUC__ > 5 || defined(_GLIBCXX_USE_C99) 27 | #define HPROSE_HAS_STOX 28 | #endif 29 | #else 30 | #define HPROSE_HAS_STOX 31 | #endif 32 | 33 | #if defined(__GNUC__) 34 | #if defined(__clang__) || __GNUC__ > 4 35 | #define HPROSE_HAS_CODECVT 36 | #endif 37 | #elif defined(_MSC_VER) 38 | #define HPROSE_HAS_CODECVT 39 | //this is a bug of Visual Studio 40 | //https://social.msdn.microsoft.com/Forums/en-US/8f40dcd8-c67f-4eba-9134-a19b9178e481/vs-2015-rc-linker-stdcodecvt-error?forum=vcgeneral 41 | #define HPROSE_HAS_CODECVT_BUG 42 | #else 43 | #define HPROSE_HAS_CODECVT 44 | #endif 45 | 46 | #if defined(__GNUC__) 47 | #if defined(__clang__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 8) 48 | #define HPROSE_HAS_REGEX 49 | #endif 50 | #else 51 | #define HPROSE_HAS_REGEX 52 | #endif 53 | 54 | #if defined(__GNUC__) 55 | #if defined(__clang__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 7) 56 | #define HPROSE_HAS_REF_QUALIFIER 57 | #endif 58 | #else 59 | #define HPROSE_HAS_REF_QUALIFIER 60 | #endif 61 | 62 | #if defined(__GNUC__) 63 | #if defined(__clang__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 7) 64 | #define HPROSE_HAS_ARRAY_INITIALIZER_LIST 65 | #endif 66 | #elif defined(_MSC_VER) 67 | //#define HPROSE_HAS_ARRAY_INITIALIZER_LIST 68 | #else 69 | #define HPROSE_HAS_ARRAY_INITIALIZER_LIST 70 | #endif 71 | 72 | #if defined(__GNUC__) 73 | #if defined(__clang__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6) 74 | #define HPROSE_HAS_DELEGATING_CONSTRUCTORS 75 | #endif 76 | #else 77 | #define HPROSE_HAS_DELEGATING_CONSTRUCTORS 78 | #endif 79 | 80 | #if defined(__GNUC__) 81 | #if defined(__clang__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6) 82 | #define HPROSE_HAS_UNDERLYING_TYPE 83 | #endif 84 | #else 85 | #define HPROSE_HAS_UNDERLYING_TYPE 86 | #endif 87 | 88 | #if defined(__GNUC__) 89 | #if defined(__clang__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6) 90 | #define HPROSE_HAS_LAMBDA_CAPTURE 91 | #endif 92 | #else 93 | #define HPROSE_HAS_LAMBDA_CAPTURE 94 | #endif -------------------------------------------------------------------------------- /hprose/util/PreProcessor.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/util/PreProcessor.h * 13 | * * 14 | * some preprocessor util for cpp. * 15 | * * 16 | * LastModified: May 22, 2017 * 17 | * Author: xiaoyur347 * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | //original https://github.com/boostorg/preprocessor/blob/develop/include/boost/preprocessor/cat.hpp 24 | #define HPROSE_PP_CAT(a, b) HPROSE_PP_CAT_I(a, b) 25 | #ifndef _MSC_VER 26 | #define HPROSE_PP_CAT_I(a, b) a ## b 27 | #else // _MSC_VER 28 | #define HPROSE_PP_CAT_I(a, b) HPROSE_PP_CAT_II(~, a ## b) 29 | #define HPROSE_PP_CAT_II(p, res) res 30 | #endif // _MSC_VER 31 | 32 | //original https://github.com/boostorg/preprocessor/tree/develop/include/boost/preprocessor/variadic 33 | #ifndef _MSC_VER 34 | #define HPROSE_PP_VARIADIC_SIZE(...) HPROSE_PP_VARIADIC_SIZE_I(__VA_ARGS__, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,) 35 | #else // _MSC_VER 36 | #define HPROSE_PP_VARIADIC_SIZE(...) HPROSE_PP_CAT(HPROSE_PP_VARIADIC_SIZE_I(__VA_ARGS__, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,),) 37 | #endif // _MSC_VER 38 | #define HPROSE_PP_VARIADIC_SIZE_I(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63, size, ...) size 39 | 40 | //custom macros 41 | #define HPROSE_PP_OVERLOAD(prefix, ...) HPROSE_PP_CAT(prefix, HPROSE_PP_VARIADIC_SIZE(__VA_ARGS__)) 42 | -------------------------------------------------------------------------------- /hprose/util/Util.cpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/util/Util.cpp * 13 | * * 14 | * some util for cpp. * 15 | * * 16 | * LastModified: Oct 27, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #include 22 | 23 | #include 24 | 25 | namespace hprose { 26 | namespace util { 27 | 28 | const char digits[] = 29 | "0123456789"; 30 | 31 | const char digit2[] = 32 | "0001020304050607080910111213141516171819" 33 | "2021222324252627282930313233343536373839" 34 | "4041424344454647484950515253545556575859" 35 | "6061626364656667686970717273747576777879" 36 | "8081828384858687888990919293949596979899"; 37 | 38 | const char digit3[] = 39 | "000001002003004005006007008009010011012013014015016017018019" 40 | "020021022023024025026027028029030031032033034035036037038039" 41 | "040041042043044045046047048049050051052053054055056057058059" 42 | "060061062063064065066067068069070071072073074075076077078079" 43 | "080081082083084085086087088089090091092093094095096097098099" 44 | "100101102103104105106107108109110111112113114115116117118119" 45 | "120121122123124125126127128129130131132133134135136137138139" 46 | "140141142143144145146147148149150151152153154155156157158159" 47 | "160161162163164165166167168169170171172173174175176177178179" 48 | "180181182183184185186187188189190191192193194195196197198199" 49 | "200201202203204205206207208209210211212213214215216217218219" 50 | "220221222223224225226227228229230231232233234235236237238239" 51 | "240241242243244245246247248249250251252253254255256257258259" 52 | "260261262263264265266267268269270271272273274275276277278279" 53 | "280281282283284285286287288289290291292293294295296297298299" 54 | "300301302303304305306307308309310311312313314315316317318319" 55 | "320321322323324325326327328329330331332333334335336337338339" 56 | "340341342343344345346347348349350351352353354355356357358359" 57 | "360361362363364365366367368369370371372373374375376377378379" 58 | "380381382383384385386387388389390391392393394395396397398399" 59 | "400401402403404405406407408409410411412413414415416417418419" 60 | "420421422423424425426427428429430431432433434435436437438439" 61 | "440441442443444445446447448449450451452453454455456457458459" 62 | "460461462463464465466467468469470471472473474475476477478479" 63 | "480481482483484485486487488489490491492493494495496497498499" 64 | "500501502503504505506507508509510511512513514515516517518519" 65 | "520521522523524525526527528529530531532533534535536537538539" 66 | "540541542543544545546547548549550551552553554555556557558559" 67 | "560561562563564565566567568569570571572573574575576577578579" 68 | "580581582583584585586587588589590591592593594595596597598599" 69 | "600601602603604605606607608609610611612613614615616617618619" 70 | "620621622623624625626627628629630631632633634635636637638639" 71 | "640641642643644645646647648649650651652653654655656657658659" 72 | "660661662663664665666667668669670671672673674675676677678679" 73 | "680681682683684685686687688689690691692693694695696697698699" 74 | "700701702703704705706707708709710711712713714715716717718719" 75 | "720721722723724725726727728729730731732733734735736737738739" 76 | "740741742743744745746747748749750751752753754755756757758759" 77 | "760761762763764765766767768769770771772773774775776777778779" 78 | "780781782783784785786787788789790791792793794795796797798799" 79 | "800801802803804805806807808809810811812813814815816817818819" 80 | "820821822823824825826827828829830831832833834835836837838839" 81 | "840841842843844845846847848849850851852853854855856857858859" 82 | "860861862863864865866867868869870871872873874875876877878879" 83 | "880881882883884885886887888889890891892893894895896897898899" 84 | "900901902903904905906907908909910911912913914915916917918919" 85 | "920921922923924925926927928929930931932933934935936937938939" 86 | "940941942943944945946947948949950951952953954955956957958959" 87 | "960961962963964965966967968969970971972973974975976977978979" 88 | "980981982983984985986987988989990991992993994995996997998999"; 89 | 90 | void WriteInt(std::ostream &stream, int64_t i) { 91 | if (i == 0) { 92 | stream << '0'; 93 | return; 94 | } 95 | if (i == std::numeric_limits::min()) { 96 | stream << "-9223372036854775808"; 97 | return; 98 | } 99 | char sign = '+'; 100 | if (i < 0) { 101 | sign = '-'; 102 | i = -i; 103 | } 104 | char buf[20]; 105 | int off = 20; 106 | int64_t q, p; 107 | while (i >= 100) { 108 | q = i / 1000; 109 | p = (i - (q * 1000)) * 3; 110 | i = q; 111 | off -= 3; 112 | buf[off] = digit3[p]; 113 | buf[off + 1] = digit3[p + 1]; 114 | buf[off + 2] = digit3[p + 2]; 115 | } 116 | if (i >= 10) { 117 | q = i / 100; 118 | p = (i - (q * 100)) * 2; 119 | i = q; 120 | off -= 2; 121 | buf[off] = digit2[p]; 122 | buf[off + 1] = digit2[p + 1]; 123 | } 124 | if (i > 0) { 125 | off--; 126 | buf[off] = digits[i]; 127 | } 128 | if (sign == '-') { 129 | off--; 130 | buf[off] = sign; 131 | } 132 | stream.write(&buf[off], 20 - off); 133 | } 134 | 135 | void WriteUint(std::ostream &stream, uint64_t u) { 136 | if (u == 0) { 137 | stream << '0'; 138 | return; 139 | } 140 | char buf[20]; 141 | int off = 20; 142 | uint64_t q, p; 143 | while (u >= 100) { 144 | q = u / 1000; 145 | p = (u - (q * 1000)) * 3; 146 | u = q; 147 | off -= 3; 148 | buf[off] = digit3[p]; 149 | buf[off + 1] = digit3[p + 1]; 150 | buf[off + 2] = digit3[p + 2]; 151 | } 152 | if (u >= 10) { 153 | q = u / 100; 154 | p = (u - (q * 100)) * 2; 155 | u = q; 156 | off -= 2; 157 | buf[off] = digit2[p]; 158 | buf[off + 1] = digit2[p + 1]; 159 | } 160 | if (u > 0) { 161 | off--; 162 | buf[off] = digits[u]; 163 | } 164 | stream.write(&buf[off], 20 - off); 165 | } 166 | 167 | void WriteDate(std::ostream &stream, int year, int month, int day) { 168 | int q = year / 100; 169 | int p = q << 1; 170 | stream << digit2[p] << digit2[p + 1]; 171 | p = (year - q * 100) << 1; 172 | stream << digit2[p] << digit2[p + 1]; 173 | p = month << 1; 174 | stream << digit2[p] << digit2[p + 1]; 175 | p = day << 1; 176 | stream << digit2[p] << digit2[p + 1]; 177 | } 178 | 179 | void WriteTime(std::ostream &stream, int hour, int min, int sec) { 180 | int p = hour << 1; 181 | stream << digit2[p] << digit2[p + 1]; 182 | p = min << 1; 183 | stream << digit2[p] << digit2[p + 1]; 184 | p = sec << 1; 185 | stream << digit2[p] << digit2[p + 1]; 186 | } 187 | 188 | int UTF16Length(const std::string &str) { 189 | int length = str.length(); 190 | int n = length; 191 | int p = 0; 192 | while (p < length) { 193 | char a = str.at(p); 194 | switch (static_cast(a) >> 4) { 195 | case 0: 196 | case 1: 197 | case 2: 198 | case 3: 199 | case 4: 200 | case 5: 201 | case 6: 202 | case 7: 203 | p++; 204 | break; 205 | case 12: 206 | case 13: 207 | p += 2; 208 | n--; 209 | break; 210 | case 14: 211 | p += 3; 212 | n -= 2; 213 | break; 214 | case 15: 215 | if ((a & 8) == 8) { 216 | return -1; 217 | } 218 | p += 4; 219 | n -= 2; 220 | break; 221 | default: 222 | return -1; 223 | } 224 | } 225 | return n; 226 | } 227 | 228 | } 229 | } // hprose::util 230 | -------------------------------------------------------------------------------- /hprose/util/Util.h: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/util/Util.h * 13 | * * 14 | * some util for cpp. * 15 | * * 16 | * LastModified: Oct 27, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #ifndef HPROSE_HAS_STOX 29 | #include 30 | #include 31 | namespace std { 32 | inline int stoi(const std::string &str, std::size_t* pos = 0, int base = 10) { 33 | char *ptr; 34 | auto ret = strtol(str.c_str(), &ptr, base); 35 | if (pos != 0) { 36 | *pos = ptr - str.c_str(); 37 | } 38 | return ret; 39 | } 40 | inline unsigned long stoul(const std::string &str, std::size_t* pos = 0, int base = 10) { 41 | char *ptr; 42 | auto ret = strtoul(str.c_str(), &ptr, base); 43 | if (pos != 0) { 44 | *pos = ptr - str.c_str(); 45 | } 46 | return ret; 47 | } 48 | inline long long stoll(const std::string &str, std::size_t* pos = 0, int base = 10) { 49 | char *ptr; 50 | auto ret = strtoll(str.c_str(), &ptr, base); 51 | if (pos != 0) { 52 | *pos = ptr - str.c_str(); 53 | } 54 | return ret; 55 | } 56 | inline float stof(const std::string &str, std::size_t* pos = 0) { 57 | char *ptr; 58 | auto ret = strtof(str.c_str(), &ptr); 59 | if (pos != 0) { 60 | *pos = ptr - str.c_str(); 61 | } 62 | return ret; 63 | } 64 | inline double stod(const std::string &str, std::size_t* pos = 0) { 65 | char *ptr; 66 | auto ret = strtod(str.c_str(), &ptr); 67 | if (pos != 0) { 68 | *pos = ptr - str.c_str(); 69 | } 70 | return ret; 71 | } 72 | inline long double stold(const std::string &str, std::size_t* pos = 0) { 73 | char *ptr; 74 | auto ret = strtold(str.c_str(), &ptr); 75 | if (pos != 0) { 76 | *pos = ptr - str.c_str(); 77 | } 78 | return ret; 79 | } 80 | 81 | inline std::string to_string(int value) { 82 | char szBuf[4 * sizeof(int)]; 83 | const int nRet = snprintf(szBuf, sizeof(szBuf), "%d", value); 84 | return std::string(szBuf, nRet); 85 | } 86 | 87 | inline std::string to_string(long value) { 88 | char szBuf[4 * sizeof(long)]; 89 | const int nRet = snprintf(szBuf, sizeof(szBuf), "%ld", value); 90 | return std::string(szBuf, nRet); 91 | } 92 | 93 | inline std::string to_string(long long value) { 94 | char szBuf[4 * sizeof(long long)]; 95 | const int nRet = snprintf(szBuf, sizeof(szBuf), "%lld", value); 96 | return std::string(szBuf, nRet); 97 | } 98 | 99 | inline std::string to_string(unsigned value) { 100 | char szBuf[4 * sizeof(unsigned)]; 101 | const int nRet = snprintf(szBuf, sizeof(szBuf), "%u", value); 102 | return std::string(szBuf, nRet); 103 | } 104 | 105 | inline std::string to_string(unsigned long value) { 106 | char szBuf[4 * sizeof(unsigned long)]; 107 | const int nRet = snprintf(szBuf, sizeof(szBuf), "%lu", value); 108 | return std::string(szBuf, nRet); 109 | } 110 | 111 | inline std::string to_string(unsigned long long value) { 112 | char szBuf[4 * sizeof(unsigned long long)]; 113 | const int nRet = snprintf(szBuf, sizeof(szBuf), "%llu", value); 114 | return std::string(szBuf, nRet); 115 | } 116 | 117 | inline std::string to_string(float value) { 118 | char szBuf[__FLT_MAX_10_EXP__ + 20]; 119 | const int nRet = snprintf(szBuf, sizeof(szBuf), "%f", value); 120 | return std::string(szBuf, nRet); 121 | } 122 | 123 | inline std::string to_string(double value) { 124 | char szBuf[__DBL_MAX_10_EXP__ + 20]; 125 | const int nRet = snprintf(szBuf, sizeof(szBuf), "%f", value); 126 | return std::string(szBuf, nRet); 127 | } 128 | } // namespace std 129 | #endif // HPROSE_HAS_STOX 130 | 131 | namespace hprose { 132 | namespace util { 133 | 134 | void WriteInt(std::ostream &stream, int64_t i); 135 | 136 | void WriteUint(std::ostream &stream, uint64_t u); 137 | 138 | void WriteDate(std::ostream &stream, int year, int month, int day); 139 | 140 | void WriteTime(std::ostream &stream, int hour, int min, int sec); 141 | 142 | // UTF16Length return the UTF16 length of str. 143 | // str must be an UTF8 encode string, otherwise return -1. 144 | int UTF16Length(const std::string &str); 145 | 146 | template 147 | inline typename std::enable_if< 148 | std::is_same::value, 149 | T 150 | >::type 151 | StringToFloat(const std::string &s) { 152 | return std::stof(s); 153 | } 154 | 155 | template 156 | inline typename std::enable_if< 157 | std::is_same::value, 158 | T 159 | >::type 160 | StringToFloat(const std::string &s) { 161 | return std::stod(s); 162 | } 163 | 164 | template 165 | inline typename std::enable_if< 166 | std::is_same::value, 167 | T 168 | >::type 169 | StringToFloat(const std::string &s) { 170 | return std::stold(s); 171 | } 172 | 173 | } 174 | } // hprose::util 175 | -------------------------------------------------------------------------------- /travis.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | cmake -DGTEST_DIR=`pwd`/googletest-release-1.8.0/googletest && make && ./IOTest.out 4 | --------------------------------------------------------------------------------