Browse Source

[C++] Add new paozhu (#8705)

* [C++] add new paozhu

* [C++] add new paozhu

* [C++] add new paozhu

* [C++] add new paozhu

* [C++] add new paozhu

* [C++] add new paozhu

* [C++] add new paozhu

* [C++] add new paozhu

* [C++] add new paozhu

* [C++] add new paozhu

* [C++] add new paozhu

* [C++] add new paozhu

* [C++] add new paozhu

* [C++] add new paozhu

* [C++] add new paozhu

* [C++] add new paozhu

* [C++] add new paozhu

* [C++] add new paozhu

* [C++] add new paozhu

* [C++] add new paozhu

* [C++] add new paozhu

* [C++] add new paozhu

* [C++] add new paozhu

* update benchmark to v1.5.8

* update benchmark to v1.5.8

* Add benchmark files

* Add benchmark files

* use local file

* use git clone

* add conf

* add conf

* add conf

* add conf

* add conf

* use local files

* use local files

* use local files

* use local files

* Remove files

* Fix files
Huang ziquan 1 year ago
parent
commit
61b1acbcfd

+ 40 - 0
frameworks/C++/paozhu/README.md

@@ -0,0 +1,40 @@
+# paozhu Benchmarking Test
+
+This is the [Paozhu](https://github.com/hggq/paozhu) 
+
+This Benchmarking Test code from https://github.com/hggq/paozhu/releases/tag/v1.5.8
+
+### Test Type Implementation Source Code
+
+* [Benchmark code](controller/src/techempower.cpp)
+* [ORM config](conf/orm.conf) 
+* [Server config](conf/server.conf) 
+
+## Test URLs
+### JSON
+
+http://localhost:8888/json
+
+### PLAINTEXT
+
+http://localhost:8888/plaintext
+
+
+### Single Database Query
+
+http://localhost:8888/db
+
+### Fortune
+
+http://localhost:8888/fortunes
+
+### Multiple Database Queries
+
+http://localhost:8888/queries?queries=10
+
+### Database Updates
+
+http://localhost:8888/updates?queries=10
+
+### Cache
+http://localhost:8888/cached-queries?count=20

+ 31 - 0
frameworks/C++/paozhu/benchmark_config.json

@@ -0,0 +1,31 @@
+{
+  "framework": "paozhu",
+  "tests": [
+    {
+      "default": {
+        "json_url": "/json",
+        "plaintext_url": "/plaintext",
+        "db_url": "/db",
+        "fortune_url": "/fortunes",
+        "query_url": "/queries?queries=",
+        "update_url": "/updates?queries=",
+        "cached_query_url": "/cached-queries?count=",
+        "port": 8888,
+        "approach": "Realistic",
+        "classification": "Fullstack",
+        "database": "MySQL",
+        "framework": "paozhu",
+        "language": "C++",
+        "flavor": "None",
+        "orm": "Micro",
+        "platform": "None",
+        "webserver": "None",
+        "os": "Linux",
+        "database_os": "Linux",
+        "display_name": "paozhu",
+        "notes": "",
+        "versus": "None"
+      }
+    }
+  ]
+}

+ 22 - 0
frameworks/C++/paozhu/config.toml

@@ -0,0 +1,22 @@
+[framework]
+name = "paozhu"
+authors = ["Huang ziquan <[email protected]>"]
+github = "https://github.com/hggq/paozhu"
+
+[main]
+urls.plaintext = "/plaintext"
+urls.json = "/json"
+urls.db = "/db"
+urls.query = "/queries?queries="
+urls.update = "/updates?queries="
+urls.fortune = "/fortunes"
+urls.cached_query = "/cached-queries?count="
+approach = "Realistic"
+classification = "Fullstack"
+database = "MySQL"
+database_os = "Linux"
+os = "Linux"
+orm = "Micro"
+platform = "None"
+webserver = "None"
+versus = "None"

+ 41 - 0
frameworks/C++/paozhu/paozhu.dockerfile

@@ -0,0 +1,41 @@
+FROM ubuntu:22.04
+RUN apt-get update -yqq && apt-get install -yqq apt-utils software-properties-common wget unzip cmake git
+RUN apt-get install -yqq gcc g++ openssl libssl-dev zlib1g-dev build-essential locales
+
+RUN apt-get -y install brotli libbrotli-dev 
+RUN apt-get -y install libreadline-dev 
+RUN apt-get -y install mysql-client
+RUN apt-get -y install libmysqlclient-dev
+
+RUN locale-gen en_US.UTF-8
+ENV LANG en_US.UTF-8
+ENV LANGUAGE en_US:en
+ENV LC_ALL en_US.UTF-8
+
+COPY ./ ./
+WORKDIR /
+
+# RUN wget https://github.com/hggq/paozhu/releases/download/v1.5.8/benchmark.zip
+RUN git clone https://github.com/hggq/paozhu
+# RUN unzip benchmark.zip
+RUN rm -Rf ./paozhu/controller
+ 
+COPY ./paozhu_benchmark/controller ./paozhu/
+COPY ./paozhu_benchmark/common/autocontrolmethod.hpp ./paozhu/common/
+COPY ./paozhu_benchmark/common/reghttpmethod_pre.hpp ./paozhu/common/
+COPY ./paozhu_benchmark/common/reghttpmethod.hpp ./paozhu/common/
+
+COPY ./paozhu_benchmark/conf/server.conf ./paozhu/conf/server.conf
+COPY ./paozhu_benchmark/conf/orm.conf ./paozhu/conf/orm.conf
+COPY ./paozhu_benchmark/CMakeLists.txt ./paozhu/CMakeLists.txt
+
+WORKDIR /paozhu
+RUN unzip asio.zip
+
+RUN cmake . -B build -DCMAKE_BUILD_TYPE=Release 
+RUN cmake --build build
+
+
+EXPOSE 8888
+
+CMD ./bin/paozhu 

+ 508 - 0
frameworks/C++/paozhu/paozhu_benchmark/CMakeLists.txt

@@ -0,0 +1,508 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 3.20)
+
+cmake_policy(SET CMP0048 NEW)
+
+set(ENABLE_VCPKG OFF CACHE BOOL "choose ON to enable")
+set(ENABLE_BOOST OFF CACHE BOOL "choose ON to enable")
+set(ENABLE_GD OFF CACHE BOOL "choose ON to enable")
+set(ENABLE_WIN_VCPKG OFF CACHE BOOL "choose ON to enable")
+
+if (ENABLE_GD STREQUAL "ON")
+    list(FIND VCPKG_MANIFEST_FEATURES "gd" index)
+    if (index EQUAL -1)
+        message(STATUS "Auto append features: gd")
+        list(APPEND VCPKG_MANIFEST_FEATURES "gd")
+    endif ()
+endif ()
+
+if (ENABLE_BOOST STREQUAL "ON")
+    list(FIND VCPKG_MANIFEST_FEATURES "boost" index)
+    if (index EQUAL -1)
+        message(STATUS "Auto append features: boost")
+        list(APPEND VCPKG_MANIFEST_FEATURES "boost")
+    endif ()
+endif ()
+
+PROJECT(Paozhu_web_framework)
+set(CMAKE_CXX_STANDARD 20)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+set(mode "CMAKE_BUILD_TYPE")
+
+set(BOOST_OPEN "  ")
+set(GD_OPEN " ")
+
+if(ENABLE_BOOST STREQUAL "ON")
+  message("ENABLE_BOOST")
+  set(BOOST_OPEN " -DENABLE_BOOST ")
+endif()
+
+if(ENABLE_GD STREQUAL "ON")
+    message("ENABLE_GD")
+    set(GD_OPEN " -DENABLE_GD ")
+endif()
+
+set(sys_so_path "/usr/lib64")
+
+if (IS_DIRECTORY "/usr/lib/x86_64-linux-gnu")
+  set(sys_so_path "/usr/lib/x86_64-linux-gnu")
+endif()
+
+if (CMAKE_SYSTEM_NAME MATCHES "Windows")
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_WIN32_WINNT=0x0601")
+endif()
+
+if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /utf-8 /EHsc")
+endif ()
+
+if(${mode} AND (CMAKE_BUILD_TYPE STREQUAL "Debug"))
+
+    if(CMAKE_SYSTEM_NAME MATCHES "Windows")
+        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DASIO_STANDALONE -DDEBUG ${BOOST_OPEN} ${GD_OPEN}")
+        if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+            set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address")
+        elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+            set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pthread -g")
+        endif ()
+    else()
+        set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Wextra")
+        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pthread -g -fsanitize=address -DASIO_STANDALONE -DDEBUG ${BOOST_OPEN} ${GD_OPEN} -I/usr/local/include -I/usr/local/mysql/include   -I/usr/include -I/usr/include/mysql " )
+    endif ()
+    message("Debug mode:${CMAKE_CXX_FLAGS_DEBUG}")
+
+elseif(${mode} AND (CMAKE_BUILD_TYPE STREQUAL "Release"))
+
+    if (CMAKE_SYSTEM_NAME MATCHES "Windows")
+        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DASIO_STANDALONE ${BOOST_OPEN} ${GD_OPEN} -O3")
+        if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+            set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pthread")
+        endif ()
+    else ()
+        set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wall -Wextra -O3")
+        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread  -DASIO_STANDALONE ${BOOST_OPEN} ${GD_OPEN}  -I/usr/local/include -I/usr/local/mysql/include -I/usr/include -I/usr/include/mysql  " )
+        file(MAKE_DIRECTORY /usr/local/etc/paozhu)
+        file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/conf/ DESTINATION /usr/local/etc/paozhu/)
+    endif ()
+    message("Release mode:${CMAKE_CXX_FLAGS_RELEASE}")
+
+else()
+    set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Wextra")
+    message("Debug mode:${CMAKE_CXX_FLAGS_DEBUG}")
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pthread  -g -fsanitize=address  -DASIO_STANDALONE -DDEBUG ${BOOST_OPEN} ${GD_OPEN} -I/usr/local/include -I/usr/local/mysql/include   -I/usr/include  -I/usr/include/mysql  " )
+
+    if(NOT CMAKE_SYSTEM_NAME MATCHES "Windows")
+        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
+    endif ()
+endif()
+
+
+
+file(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/temp)
+file(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/log)
+set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/bin)
+set(USE_STANDALONE_ASIO ON)
+set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
+
+message(STATUS "SOURCE dir ${CMAKE_CURRENT_SOURCE_DIR}")
+
+
+set(CMAKE_BUILD_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/build)
+set(CMAKE_CACHEFILE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/build)
+set(CMAKE_CURRENT_BINARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/build)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/common)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/controller)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/vendor/httpcli)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/viewsrc/include)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/websockets/include)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
+
+if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/bin/paozhu_empty)
+  file(REMOVE_RECURSE ${CMAKE_CURRENT_SOURCE_DIR}/bin/paozhu_empty)
+endif ()
+#EXECUTE_PROCESS(COMMAND rm ${CMAKE_CURRENT_SOURCE_DIR}/bin/paozhu_empty)
+set(PAOZHU_PRE paozhu_pre)
+add_executable(${PAOZHU_PRE} ${CMAKE_CURRENT_SOURCE_DIR}/vendor/httpcli/autopickmethod.cpp ${CMAKE_CURRENT_SOURCE_DIR}/vendor/httpserver/src/md5.cpp)
+add_executable(paozhu_empty ${CMAKE_CURRENT_SOURCE_DIR}/vendor/httpcli/autoemptymethod.cpp)
+
+
+
+file(GLOB_RECURSE orm_list ${CMAKE_CURRENT_SOURCE_DIR}/orm/*.cpp)
+file(GLOB_RECURSE source_list ${CMAKE_CURRENT_SOURCE_DIR}/models/*.cpp)
+file(GLOB_RECURSE FRAMEWORK_CPP_PATH ${CMAKE_CURRENT_SOURCE_DIR}/vendor/httpserver/*.cpp)
+file(GLOB_RECURSE common_list ${CMAKE_CURRENT_SOURCE_DIR}/common/*.cpp)
+file(GLOB_RECURSE controller_list ${CMAKE_CURRENT_SOURCE_DIR}/controller/src/*.cpp)
+file(GLOB_RECURSE viewsrc_list ${CMAKE_CURRENT_SOURCE_DIR}/viewsrc/view/*.cpp)
+file(GLOB_RECURSE reflect_list ${CMAKE_CURRENT_SOURCE_DIR}/libs/*.cpp)
+file(GLOB_RECURSE src_list ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
+
+foreach(cppfile IN LISTS controller_list)
+  string(REGEX REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/controller/src/" "" cppfilename ${cppfile})
+  string(REGEX REPLACE ".cpp" "" cppbasename ${cppfilename})
+#  message(${cppbasename})
+  if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/controller/include/${cppbasename}.h")
+  else()
+      file(TOUCH "${CMAKE_CURRENT_SOURCE_DIR}/controller/include/${cppbasename}.h")
+  endif()
+endforeach()
+
+function(include_sub_directories_recursively root_dir)
+    if (IS_DIRECTORY ${root_dir})               # 当前路径是一个目录吗,是的话就加入到包含目录
+        #        if (${root_dir} MATCHES "include")
+        message("include dir: " ${root_dir})
+        include_directories(${root_dir})
+        #        endif()
+    endif()
+
+    file(GLOB ALL_SUB RELATIVE ${root_dir} ${root_dir}/*) # 获得当前目录下的所有文件,让如ALL_SUB列表中
+
+    foreach(sub ${ALL_SUB})
+        if (IS_DIRECTORY ${root_dir}/${sub})
+            include_sub_directories_recursively(${root_dir}/${sub}) # 对子目录递归调用,包含
+        endif()
+    endforeach()
+endfunction()
+
+include_sub_directories_recursively(${CMAKE_CURRENT_SOURCE_DIR}/vendor/httpserver)
+include_sub_directories_recursively(${CMAKE_CURRENT_SOURCE_DIR}/orm)
+include_sub_directories_recursively(${CMAKE_CURRENT_SOURCE_DIR}/models)
+include_sub_directories_recursively(${CMAKE_CURRENT_SOURCE_DIR}/controller/include)
+include_sub_directories_recursively(${CMAKE_CURRENT_SOURCE_DIR}/libs)
+include_sub_directories_recursively(${CMAKE_CURRENT_SOURCE_DIR}/include)
+
+add_executable(paozhu_cli ${CMAKE_CURRENT_SOURCE_DIR}/vendor/httpcli/http_cli.cpp)
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin)
+
+
+if(${mode} AND (CMAKE_BUILD_TYPE STREQUAL "Release"))
+  add_executable(paozhu ${CMAKE_CURRENT_SOURCE_DIR}/test/testbenchmark.cpp ${common_list} ${viewsrc_list} ${FRAMEWORK_CPP_PATH} ${orm_list} ${reflect_list} ${src_list} ${source_list} ${controller_list})
+else()
+  add_executable(paozhu ${CMAKE_CURRENT_SOURCE_DIR}/test/test.cpp ${common_list} ${viewsrc_list} ${FRAMEWORK_CPP_PATH} ${orm_list} ${reflect_list} ${src_list} ${source_list} ${controller_list})
+endif()
+
+if (ENABLE_WIN_VCPKG STREQUAL "ON")
+else ()
+add_custom_command(
+    TARGET paozhu_empty paozhu
+    DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/bin/paozhu_pre
+    PRE_BUILD
+    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
+    COMMAND echo "-- controls method --"
+    COMMAND ${PAOZHU_PRE} ${CMAKE_CURRENT_SOURCE_DIR}/
+    COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_CURRENT_SOURCE_DIR}/bin/paozhu_empty
+    )
+endif()
+
+if (ENABLE_VCPKG)
+    add_compile_definitions(ENABLE_VCPKG)
+    find_package(asio CONFIG REQUIRED)
+    target_link_libraries(paozhu asio::asio)
+
+    if (ENABLE_BOOST)
+        add_compile_definitions(ENABLE_BOOST)
+        set(Boost_NO_WARN_NEW_VERSIONS ON)
+        find_package(Boost REQUIRED COMPONENTS filesystem coroutine)
+        target_link_libraries(paozhu Boost::boost Boost::filesystem Boost::coroutine)
+    endif ()
+
+    find_package(OpenSSL REQUIRED)
+    target_link_libraries(paozhu OpenSSL::Crypto OpenSSL::SSL)
+
+    find_package(ZLIB REQUIRED)
+    target_link_libraries(paozhu ZLIB::ZLIB)
+
+    # find_package(libmysql REQUIRED)
+    find_package(unofficial-libmariadb CONFIG REQUIRED)
+    find_path(MYSQL_ROOT_DIR mysql)
+    # target_link_libraries(paozhu ${MYSQL_LIBRARIES})
+    # target_link_libraries(paozhu_cli ${MYSQL_LIBRARIES})
+    target_link_libraries(paozhu unofficial::libmariadb)
+    target_link_libraries(paozhu_cli unofficial::libmariadb)
+    target_include_directories(paozhu PUBLIC ${MYSQL_ROOT_DIR}/mysql)
+    target_include_directories(paozhu_cli PUBLIC ${MYSQL_ROOT_DIR}/mysql)
+
+    if (ENABLE_GD STREQUAL "ON")
+        find_package(PkgConfig)
+        pkg_check_modules(LIBGD REQUIRED IMPORTED_TARGET gdlib)
+        target_link_libraries(paozhu PkgConfig::LIBGD)
+
+        find_path(QRENCODE_INCLUDE_DIR NAMES qrencode.h)
+        find_library(QRENCODE_LIBRARY_RELEASE qrencode)
+        # find_library(QRENCODE_LIBRARY_DEBUG qrencoded)
+        # set(QRENCODE_LIBRARIES optimized ${QRENCODE_LIBRARY_RELEASE} debug ${QRENCODE_LIBRARY_DEBUG})
+        target_include_directories(paozhu PRIVATE ${QRENCODE_INCLUDE_DIR})
+        target_link_libraries(paozhu ${QRENCODE_LIBRARY_RELEASE})
+        # MESSAGE(STATUS ${QRENCODE_LIBRARY_RELEASE})
+
+        # warning: Fixed an issue where ports/libqrencode would not automatically
+        #          copy dll files to the bin directory
+        if (CMAKE_SYSTEM_NAME MATCHES "Windows")
+            set(PATH_TO_QRENCODE_DLL "")
+            if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+                set(PATH_TO_QRENCODE_DLL "${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin/qrencode.dll")
+            elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+                set(PATH_TO_QRENCODE_DLL "${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/lib/libqrencode.dll")
+            endif ()
+            message(STATUS "Selected libqrencode.dll: ${PATH_TO_QRENCODE_DLL}")
+
+            add_custom_command(
+                    TARGET paozhu POST_BUILD
+                    COMMAND ${CMAKE_COMMAND} -E copy_if_different
+                    ${PATH_TO_QRENCODE_DLL} ${CMAKE_CURRENT_SOURCE_DIR}/bin/
+            )
+        endif ()
+
+        find_package(PNG REQUIRED)
+        target_link_libraries(paozhu PNG::PNG)
+
+        find_package(Freetype REQUIRED)
+        target_link_libraries(paozhu Freetype::Freetype)
+    endif ()
+
+    find_package(unofficial-brotli CONFIG REQUIRED)
+    target_link_libraries(paozhu unofficial::brotli::brotlidec unofficial::brotli::brotlienc)
+else ()
+
+if(USE_STANDALONE_ASIO)
+if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
+set(ASIO_PATH "/usr/local/opt/asio/include" "/usr/local/include")
+else()
+set(ASIO_PATH ${CMAKE_CURRENT_SOURCE_DIR}/asio "/usr/include")
+endif()
+
+    target_compile_definitions(paozhu INTERFACE ASIO_STANDALONE)
+    find_path(ASIO_PATH asio.hpp)
+    message(state " Standalone Asio found: " ${ASIO_PATH})
+    if(NOT ASIO_PATH)
+        message(FATAL_ERROR "Standalone Asio not found")
+    else()
+        target_include_directories(paozhu INTERFACE ${ASIO_PATH})
+    endif()
+
+    include_directories(${ASIO_PATH})
+
+endif()
+
+
+if(ENABLE_BOOST STREQUAL "ON")
+message("---ENABLE_BOOST-----")
+find_package(Boost REQUIRED
+             COMPONENTS system filesystem)
+if(Boost_FOUND)
+    add_compile_definitions(ENABLE_BOOST)
+    include_directories("${Boost_INCLUDE_DIRS}/boost")
+
+    MESSAGE( STATUS "Boost_INCLUDE_DIRS = ${Boost_INCLUDE_DIRS}")
+    MESSAGE( STATUS "Boost_LIBRARIES = ${Boost_LIBRARY_DIRS}")
+    MESSAGE( STATUS "Boost_LIB_VERSION = ${Boost_LIB_VERSION}")
+    link_directories(${Boost_LIBRARY_DIRS})
+    target_link_libraries (paozhu ${Boost_LIBRARIES})
+endif()
+
+endif()
+
+
+find_package(OpenSSL REQUIRED)
+
+if(OPENSSL_FOUND)
+
+  message(STATUS "OPENSSL_VERSION = ${OPENSSL_VERSION}")
+  message(STATUS "OPENSSL_SSL_LIBRARY = ${OPENSSL_SSL_LIBRARY}")
+  message(STATUS "OPENSSL_CRYPTO_LIBRARY = ${OPENSSL_CRYPTO_LIBRARY}")
+  message(STATUS "OPENSSL_INCLUDE_DIR = ${OPENSSL_INCLUDE_DIR}")
+  INCLUDE_DIRECTORIES("${OPENSSL_INCLUDE_DIR}")
+  target_link_libraries (paozhu ${OPENSSL_SSL_LIBRARY})
+  target_link_libraries (paozhu ${OPENSSL_CRYPTO_LIBRARY})
+endif()
+
+
+find_package(ZLIB REQUIRED)
+if(ZLIB_FOUND)
+  message(STATUS "Zlib Found! ${ZLIB_LIBRARIES}")
+  include_directories(${ZLIB_INCLUDE_DIR})
+  set(zlib_library ${ZLIB_LIBRARIES})
+  target_link_libraries(paozhu z)
+endif()
+
+find_path(MYSQL_ROOT_DIR mysql)
+MESSAGE( STATUS "MYSQL_ROOT_DIR = ${MYSQL_ROOT_DIR} ")
+find_package_handle_standard_args(mysql REQUIRED_VARS MYSQL_ROOT_DIR)
+
+FIND_PATH(MYSQL_INCLUDE_DIR mysql.h
+  /usr/local/include/mysql
+  /usr/include/mysql
+  /usr/local/mysql/include
+)
+SET(MYSQL_NAMES mysqlclient)
+FIND_LIBRARY(MYSQL_LIBRARY
+  NAMES ${MYSQL_NAMES}
+  PATHS /usr/lib /usr/local/lib /usr/local/mysql/lib
+  PATH_SUFFIXES mysql
+)
+
+IF (MYSQL_INCLUDE_DIR AND MYSQL_LIBRARY)
+  SET(MYSQL_FOUND TRUE)
+  SET( MYSQL_LIBRARIES ${MYSQL_LIBRARY} )
+ELSE (MYSQL_INCLUDE_DIR AND MYSQL_LIBRARY)
+  SET(MYSQL_FOUND FALSE)
+  SET( MYSQL_LIBRARIES )
+ENDIF (MYSQL_INCLUDE_DIR AND MYSQL_LIBRARY)
+
+IF (MYSQL_FOUND)
+  IF (NOT MYSQL_FIND_QUIETLY)
+    MESSAGE(STATUS "Found MySQL: ${MYSQL_LIBRARY}")
+  ENDIF (NOT MYSQL_FIND_QUIETLY)
+ELSE (MYSQL_FOUND)
+  IF (MYSQL_FIND_REQUIRED)
+    MESSAGE(STATUS "Looked for MySQL libraries named ${MYSQL_NAMES}.")
+    MESSAGE(FATAL_ERROR "Could NOT find MySQL library")
+  ENDIF (MYSQL_FIND_REQUIRED)
+ENDIF (MYSQL_FOUND)
+
+target_include_directories(paozhu PUBLIC ${MYSQL_INCLUDE_DIR})
+target_link_libraries(paozhu ${MYSQL_LIBRARY})
+
+target_include_directories(paozhu_cli PUBLIC ${MYSQL_INCLUDE_DIR})
+target_link_libraries(paozhu_cli ${MYSQL_LIBRARY})
+
+
+
+if(ENABLE_GD STREQUAL "ON")
+message("---ENABLE_GD-----")
+
+if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
+  set(GD_ROOT_DIR "/usr/local/opt/gd/lib")
+else()
+  set(GD_ROOT_DIR "${sys_so_path}")
+endif()
+
+set(find_gdname gd)
+
+find_library(GD_LIB_DIR
+  NAMES ${find_gdname}
+  PATHS "${GD_ROOT_DIR}"
+  NO_DEFAULT_PATH
+)
+
+if(NOT GD_LIB_DIR)
+message(FATAL_ERROR
+"GD Graphics Library NOT FOUND! please install . "
+)
+endif()
+
+message(STATUS "GD Graphics Library  at: ${GD_LIB_DIR}")
+
+if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
+set(QR_ROOT_DIR "/usr/local/opt/qrencode/lib")
+else()
+set(QR_ROOT_DIR "${sys_so_path}")
+endif()
+
+set(find_qrname qrencode)
+
+find_library(QR_LIB_DIR
+  NAMES ${find_qrname}
+  PATHS "${QR_ROOT_DIR}"
+  NO_DEFAULT_PATH
+)
+
+if(NOT QR_LIB_DIR)
+message(FATAL_ERROR
+"qrencode Library  NOT FOUND! please install . "
+)
+endif()
+
+message(STATUS "qrencode at: ${QR_LIB_DIR}")
+
+INCLUDE_DIRECTORIES("${GD_ROOT_DIR}/include")
+INCLUDE_DIRECTORIES("${QR_ROOT_DIR}/include")
+link_directories("${QR_ROOT_DIR}/lib")
+link_directories("${GD_ROOT_DIR}/lib")
+target_link_libraries(paozhu ${GD_LIB_DIR})
+target_link_libraries(paozhu ${QR_LIB_DIR})
+
+if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
+set(PNG_ROOT_DIR "/usr/local/opt/libpng/lib")
+else()
+set(PNG_ROOT_DIR "${sys_so_path}")
+endif()
+
+find_library(PNG_LIB_DIR
+  NAMES png
+  PATHS "${PNG_ROOT_DIR}"
+  NO_DEFAULT_PATH
+)
+target_link_libraries(paozhu ${PNG_LIB_DIR})
+
+if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
+  set(FREETYPE_ROOT_DIR "/usr/local/opt/freetype/lib")
+else()
+  set(FREETYPE_ROOT_DIR "${sys_so_path}")
+endif()
+
+find_library(FREETYPE_LIB_DIR
+  NAMES freetype
+  PATHS "${FREETYPE_ROOT_DIR}"
+  NO_DEFAULT_PATH
+)
+target_link_libraries(paozhu ${FREETYPE_LIB_DIR})
+#end ENABLE_GD
+endif()
+
+if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
+  set(BROTLI_ROOT_DIR "/usr/local/opt/brotli/lib")
+else()
+  set(BROTLI_ROOT_DIR "${sys_so_path}")
+endif()
+
+
+
+#find_package(Brotli COMPONENTS encoder decoder common REQUIRED)
+
+message(STATUS "Brotli at: ${BROTLI_ROOT_DIR}")
+
+set(find_brname brotlienc)
+set(find_brdename brotlidec)
+find_library(BR_LIB_DIR
+  NAMES ${find_brname}
+  PATHS "${BROTLI_ROOT_DIR}"
+  NO_DEFAULT_PATH
+)
+find_library(BRDEC_LIB_DIR
+  NAMES ${find_brdename}
+  PATHS "${BROTLI_ROOT_DIR}"
+  NO_DEFAULT_PATH
+)
+INCLUDE_DIRECTORIES("${BROTLI_ROOT_DIR}/include")
+link_directories("${BROTLI_ROOT_DIR}/lib")
+
+if(NOT BR_LIB_DIR)
+message(FATAL_ERROR
+"Brotli Library  NOT FOUND! please install . "
+)
+endif()
+
+message(STATUS "Brotli at: ${BR_LIB_DIR}")
+target_link_libraries(paozhu ${BR_LIB_DIR})
+
+
+if(NOT BRDEC_LIB_DIR)
+message(FATAL_ERROR
+"Brotli Library  NOT FOUND! please install . "
+)
+endif()
+
+message(STATUS "Brotli at: ${BRDEC_LIB_DIR}")
+target_link_libraries(paozhu ${BRDEC_LIB_DIR})
+
+
+message("Compile framework mode")
+
+target_link_libraries(paozhu  m  dl)
+
+endif ()
+
+if (CMAKE_SYSTEM_NAME MATCHES "Windows")
+   target_link_libraries(paozhu ws2_32)
+   target_link_libraries(paozhu_cli ws2_32)
+endif ()

+ 51 - 0
frameworks/C++/paozhu/paozhu_benchmark/common/autocontrolmethod.hpp

@@ -0,0 +1,51 @@
+
+#ifndef __HTTP_AUTO_REG_CONTROL_HTTPMETHOD_HPP
+#define __HTTP_AUTO_REG_CONTROL_HTTPMETHOD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+#pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "httppeer.h" 
+
+#include "techempower.h"
+
+
+namespace http
+{
+  void _initauto_control_httpmethodregto(std::map<std::string, regmethold_t> &methodcallback)
+  {
+    struct regmethold_t temp;
+
+		temp.pre = nullptr;
+		temp.regfun = techempowerplaintext;
+		methodcallback.emplace("plaintext",temp);
+		temp.pre = nullptr;
+		temp.regfun = techempowerjson;
+		methodcallback.emplace("json",temp);
+		temp.pre = nullptr;
+		temp.regfun = techempowerdb;
+		methodcallback.emplace("db",temp);
+		temp.pre = nullptr;
+		temp.regfun = techempowerqueries;
+		methodcallback.emplace("queries",temp);
+		temp.pre = nullptr;
+		temp.regfun = techempowerfortunes;
+		methodcallback.emplace("fortunes",temp);
+		temp.pre = nullptr;
+		temp.regfun = techempowerupdates;
+		methodcallback.emplace("updates",temp);
+		temp.pre = nullptr;
+		temp.regfun = techempowercached_queries;
+		methodcallback.emplace("cached-queries",temp);
+		temp.pre = nullptr;
+		temp.regfun = techempowercached_db;
+		methodcallback.emplace("cached-db",temp);
+
+
+    }
+}
+
+#endif
+
+    

+ 32 - 0
frameworks/C++/paozhu/paozhu_benchmark/common/json_reflect_headers.h

@@ -0,0 +1,32 @@
+#pragma once
+#include <sstream>
+#include <string>
+#include <vector>
+#include <map>
+
+#include "types/techempower_json.h"
+#include "unicode.h"
+
+template <typename JSON_REF_OBJ_TEMP>
+std::string json_encode([[maybe_unused]] const JSON_REF_OBJ_TEMP &json_reflectobj) { return ""; }
+
+template <typename JSON_REF_OBJ_TEMP>
+std::string json_encode([[maybe_unused]] const std::vector<JSON_REF_OBJ_TEMP> &json_reflectobj) { return ""; }
+
+template <typename JSON_REF_OBJ_TEMP>
+unsigned int json_decode([[maybe_unused]] JSON_REF_OBJ_TEMP &json_reflectobj, [[maybe_unused]] const std::string &_json_data, [[maybe_unused]] unsigned int _offset) { return 0; }
+
+template <typename JSON_REF_OBJ_TEMP>
+unsigned int json_decode([[maybe_unused]] std::vector<JSON_REF_OBJ_TEMP> &json_reflectobj, [[maybe_unused]] const std::string &_json_data, [[maybe_unused]] unsigned int _offset) { return 0; }
+
+namespace http
+{
+
+std::string json_encode(const techempower_outjson_t &json_reflectobj);
+
+std::string json_encode(const std::vector<techempower_outjson_t> &json_reflectobj);
+
+unsigned int json_decode(techempower_outjson_t &json_reflectobj, const std::string &_json_data, unsigned int _offset = 0);
+
+unsigned int json_decode(std::vector<techempower_outjson_t> &json_reflectobj, const std::string &_json_data, unsigned int _offset = 0);
+}// namespace http

+ 16 - 0
frameworks/C++/paozhu/paozhu_benchmark/common/reghttpmethod.hpp

@@ -0,0 +1,16 @@
+#ifndef __HTTP_REGHTTPMETHOD_HPP
+#define __HTTP_REGHTTPMETHOD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+#pragma once
+#endif// defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "httppeer.h"
+namespace http
+{
+void _inithttpmethodregto(std::map<std::string, regmethold_t> &methodcallback)
+{
+}
+
+}// namespace http
+#endif

+ 20 - 0
frameworks/C++/paozhu/paozhu_benchmark/common/reghttpmethod_pre.hpp

@@ -0,0 +1,20 @@
+#ifndef __HTTP_REGHTTPMETHOD_PRE_HPP
+#define __HTTP_REGHTTPMETHOD_PRE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+#pragma once
+#endif// defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "httppeer.h"
+namespace http
+{
+void _inithttpmethodregto_pre(std::map<std::string, regmethold_t> &methodcallback)
+{
+    struct regmethold_t temp;
+    //temp.pre = adminlogin;
+    //temp.regfun = adminmar;
+    //methodcallback.emplace("adminmar", temp);
+}
+
+}// namespace http
+#endif

+ 20 - 0
frameworks/C++/paozhu/paozhu_benchmark/conf/orm.conf

@@ -0,0 +1,20 @@
+[default]
+type=main
+host=tfb-database
+port=3306
+dbname=hello_world
+user=benchmarkdbuser
+password=benchmarkdbpass
+pretable=
+maxpool=5
+dbtype=mysql
+
+type=second
+host=tfb-database
+port=3306
+dbname=hello_world
+user=benchmarkdbuser
+password=benchmarkdbpass
+pretable=
+maxpool=20
+dbtype=mysql

+ 42 - 0
frameworks/C++/paozhu/paozhu_benchmark/conf/server.conf

@@ -0,0 +1,42 @@
+[default]
+threadmax=1024
+threadmin=5
+httpport=8888
+httpsport=4430
+cothreadnum=8 ;Coroutines run on thread num
+
+http2_enable=0
+debug_enable=1
+deamon_enable=0
+mainhost=localhost
+certificate_chain_file=localhost.pem
+private_key_file=localhost.key
+tmp_dh_file=dh4096.pem
+reboot_password=e10adc3949ba59abbe56e057f20f883e ;md5(md5("123456")+"rand_char"+md5("123456"))
+session_type=1 ;session save type 0.file 1.memory 2.redis 3.memcache 4.reserve
+static_file_compress_cache=1 ;1 enable, Cache static file compress(gzip,br) content to cache directory 
+modelspath=/root/benchmark/models
+serverpath=/root/benchmark
+viewpath=/root/benchmark/view
+viewsopath=/root/benchmark/module/view
+
+controlpath=/root/benchmark/controller
+controlsopath=/root/benchmark/module/controller
+
+temppath=/root/benchmark/temp
+logpath=/root/benchmark/log
+wwwpath=/root/benchmark/www/default
+pluginspath=/root/benchmark/plugins
+libspath=/root/benchmark/libs
+directorylist=0
+index=index.html
+;usehtmlcache=1
+;usehtmlcachetime=3600
+rewrite_404=0   ;1 file 2 action url path
+rewrite_404_action=index.html
+method_pre=
+method_after=
+show_visitinfo=0
+upload_max_size=16777216
+
+

+ 19 - 0
frameworks/C++/paozhu/paozhu_benchmark/controller/include/techempower.h

@@ -0,0 +1,19 @@
+
+#pragma once
+#include <chrono>
+#include <thread>
+#include "httppeer.h"
+
+namespace http
+{
+
+            
+	std::string techempowerplaintext(std::shared_ptr<httppeer> peer);
+	std::string techempowerjson(std::shared_ptr<httppeer> peer);
+	std::string techempowerdb(std::shared_ptr<httppeer> peer);
+	std::string techempowerqueries(std::shared_ptr<httppeer> peer);
+	std::string techempowerfortunes(std::shared_ptr<httppeer> peer);
+	std::string techempowerupdates(std::shared_ptr<httppeer> peer);
+	std::string techempowercached_queries(std::shared_ptr<httppeer> peer);
+	std::string techempowercached_db(std::shared_ptr<httppeer> peer);
+}

+ 241 - 0
frameworks/C++/paozhu/paozhu_benchmark/controller/src/techempower.cpp

@@ -0,0 +1,241 @@
+#include "orm.h"
+#include <chrono>
+#include <thread>
+#include <algorithm>
+#include <random>
+#include <chrono>
+#include "httppeer.h"
+#include "techempower.h"
+#include "techempower_json.h"
+#include "datetime.h"
+#include "func.h"
+#include "pzcache.h"
+#include "json_reflect_headers.h"
+namespace http
+{
+//@urlpath(null,plaintext)
+std::string techempowerplaintext(std::shared_ptr<httppeer> peer)
+{
+    peer->type("text/plain; charset=UTF-8");
+    peer->set_header("Date", get_gmttime());
+    peer->output = "Hello, World!";
+    return "";
+}
+
+//@urlpath(null,json)
+std::string techempowerjson(std::shared_ptr<httppeer> peer)
+{
+    peer->type("application/json; charset=UTF-8");
+    peer->set_header("Date", get_gmttime());
+    struct techempower_outjson_t a;
+    a.message    = "Hello, World!";
+    peer->output = json_encode(a);
+    return "";
+}
+
+//@urlpath(null,db)
+std::string techempowerdb(std::shared_ptr<httppeer> peer)
+{
+    peer->type("application/json; charset=UTF-8");
+    peer->set_header("Date", get_gmttime());
+    auto myworld        = orm::World();
+    unsigned int rd_num = rand_range(1, 10000);
+    myworld.get_one(rd_num);
+
+    peer->output = myworld.data_tojson();
+    return "";
+}
+
+//@urlpath(null,queries)
+std::string techempowerqueries(std::shared_ptr<httppeer> peer)
+{
+    peer->type("application/json; charset=UTF-8");
+    peer->set_header("Date", get_gmttime());
+
+    unsigned int get_num = peer->get["queries"].to_int();
+    if (get_num == 0)
+    {
+        get_num = 1;
+    }
+    else if (get_num > 500)
+    {
+        get_num = 500;
+    }
+    auto myworld = orm::World();
+    myworld.record.reserve(get_num);
+    for (unsigned int i = 0; i < get_num; i++)
+    {
+        myworld.wheresql.clear();
+        unsigned int rd_num = rand_range(1, 10000);
+        myworld.where("id", rd_num).fetch_append();
+    }
+
+    peer->output = myworld.to_json();
+    return "";
+}
+
+//@urlpath(null,fortunes)
+std::string techempowerfortunes(std::shared_ptr<httppeer> peer)
+{
+    peer->type("text/html; charset=UTF-8");
+    peer->set_header("Date", get_gmttime());
+
+    auto myfortune = orm::Fortune();
+    myfortune.fetch();
+    myfortune.data.id      = 0;
+    myfortune.data.message = "Additional fortune added at request time.";
+    myfortune.record.push_back(myfortune.data);
+
+    std::sort(myfortune.record.begin(), myfortune.record.end(), [](const auto &lhs, const auto &rhs)
+              { return lhs.message < rhs.message; });
+    peer->val["list"].set_array();
+    OBJ_ARRAY item;
+    for (unsigned int i = 0; i < myfortune.record.size(); i++)
+    {
+        item["id"]      = myfortune.record[i].id;
+        item["message"] = html_encode(myfortune.record[i].message);
+        peer->val["list"].push(item);
+    }
+
+    peer->view("techempower/fortunes");
+    return "";
+}
+
+//@urlpath(null,updates)
+std::string techempowerupdates(std::shared_ptr<httppeer> peer)
+{
+    peer->type("application/json; charset=UTF-8");
+    peer->set_header("Date", get_gmttime());
+    unsigned int get_num = peer->get["queries"].to_int();
+
+    if (get_num == 0)
+    {
+        get_num = 1;
+    }
+    else if (get_num > 500)
+    {
+        get_num = 500;
+    }
+    auto myworld = orm::World();
+    myworld.record.clear();
+    myworld.record.reserve(get_num);
+    for (unsigned int i = 0; i < get_num; i++)
+    {
+        myworld.wheresql.clear();
+        myworld.where("id", rand_range(1, 10000)).fetch_append();
+        if (myworld.effect() > 0)
+        {
+            unsigned int j                 = myworld.record.size() - 1;
+            myworld.data.randomnumber      = rand_range(1, 10000);
+            myworld.record[j].randomnumber = myworld.data.randomnumber;
+            myworld.update("randomnumber");
+        }
+    }
+    peer->output = myworld.to_json();
+    return "";
+}
+
+//@urlpath(null,cached-queries)
+std::string techempowercached_queries(std::shared_ptr<httppeer> peer)
+{
+    peer->type("application/json; charset=UTF-8");
+    peer->set_header("Date", get_gmttime());
+
+    unsigned int get_num = peer->get["count"].to_int();
+    if (get_num == 0)
+    {
+        get_num = 1;
+    }
+    else if (get_num > 500)
+    {
+        get_num = 500;
+    }
+    auto myworld          = orm::World();
+    std::string mycacheid = "alldatacache";
+
+    pzcache<std::vector<orm::worldbase::meta>> &temp_cache = pzcache<std::vector<orm::worldbase::meta>>::conn();
+
+    std::vector<orm::worldbase::meta> allcachedata_array;
+    allcachedata_array.reserve(10000);
+    //create rand data to cache
+    if (temp_cache.check(mycacheid) > -1)
+    {
+        allcachedata_array = temp_cache.get(mycacheid);
+    }
+    else
+    {
+        allcachedata_array.resize(10000);
+        for (unsigned int i = 0; i < 10000; i++)
+        {
+            allcachedata_array[i].id           = i + 1;
+            allcachedata_array[i].randomnumber = rand_range(1, 10000);
+        }
+        temp_cache.save(mycacheid, allcachedata_array, 120);
+    }
+    //get rand data from cache
+    mycacheid = "my" + std::to_string(get_num);
+    myworld.record.reserve(get_num);
+    if (temp_cache.check(mycacheid) > -1)
+    {
+        myworld.record = temp_cache.get(mycacheid);
+    }
+    else
+    {
+        if (allcachedata_array.size() == 10000)
+        {
+            for (unsigned int i = 0; i < get_num; i++)
+            {
+                unsigned int temp_rid = rand_range(0, 9999);
+                myworld.record.push_back(allcachedata_array[temp_rid]);
+            }
+        }
+        temp_cache.save(mycacheid, myworld.record, 120);
+    }
+
+    peer->output = myworld.to_json();
+    return "";
+}
+
+//@urlpath(null,cached-db)
+std::string techempowercached_db(std::shared_ptr<httppeer> peer)
+{
+    peer->type("application/json; charset=UTF-8");
+    peer->set_header("Date", get_gmttime());
+    //this test from database to cache
+    unsigned int get_num = peer->get["count"].to_int();
+    if (get_num == 0)
+    {
+        get_num = 1;
+    }
+    else if (get_num > 500)
+    {
+        get_num = 500;
+    }
+    auto myworld          = orm::World();
+    std::string mycacheid = "my" + std::to_string(get_num);
+
+    pzcache<std::vector<orm::worldbase::meta>> &temp_cache = pzcache<std::vector<orm::worldbase::meta>>::conn();
+
+    myworld.record.reserve(get_num);
+    if (temp_cache.check(mycacheid) > -1)
+    {
+        myworld.record = temp_cache.get(mycacheid);
+    }
+    else
+    {
+        std::vector<unsigned int> cacheid;
+        for (unsigned int i = 0; i < get_num; i++)
+        {
+            cacheid.push_back(rand_range(1, 10000));
+        }
+
+        std::string sqlstr = array_to_sql(cacheid);
+        myworld.whereIn("id", sqlstr).fetch();
+        temp_cache.save(mycacheid, myworld.record, 120);
+    }
+
+    peer->output = myworld.to_json();
+    return "";
+}
+
+}// namespace http

+ 15 - 0
frameworks/C++/paozhu/paozhu_benchmark/libs/types/techempower_json.h

@@ -0,0 +1,15 @@
+#ifndef LIBS_TYPES_TECHEMPOWER_TYPE_H
+#define LIBS_TYPES_TECHEMPOWER_TYPE_H
+#include <string>
+#include <sstream>
+
+namespace http
+{
+//@reflect json to_json from_json
+struct techempower_outjson_t
+{
+    std::string message;
+};
+
+}// namespace http
+#endif

+ 290 - 0
frameworks/C++/paozhu/paozhu_benchmark/libs/types/techempower_json_jsonreflect.cpp

@@ -0,0 +1,290 @@
+#include <sstream>
+#include <string>
+#include <vector>
+#include <map>
+#include "types/techempower_json.h"
+#include "json_reflect_headers.h"
+#include "unicode.h"
+#include "func.h"
+
+namespace http
+{
+
+
+std::string json_encode(const techempower_outjson_t &json_reflectobj)
+	{
+ 
+    std::stringstream _stream;
+    _stream << "{"; 
+    _stream << "\"message\":\"" << http::utf8_to_jsonstring(json_reflectobj.message)<< "\"";
+                
+    _stream << "}";
+
+    return _stream.str();
+            
+	}
+
+
+std::string json_encode(const std::vector<techempower_outjson_t> &json_reflectobj)
+        {
+        std::stringstream _stream;
+        _stream << "["; 
+    
+            for(unsigned int i=0;i<json_reflectobj.size();i++) 
+            {
+                if(i>0)
+                {
+                    _stream <<",";
+                }
+                _stream <<json_encode(json_reflectobj[i]);
+            }
+    
+        _stream << "]";
+
+        return _stream.str();
+        }
+              
+     unsigned int json_decode(techempower_outjson_t &json_reflectobj,const std::string &_json_data,unsigned int _offset)
+     {           
+             bool _isarray=false;
+        for(;_offset<_json_data.size();_offset++)
+        {
+            if(_json_data[_offset]=='{')
+            {
+                break;
+            }
+            if(_json_data[_offset]=='[')
+            {
+                _isarray=true;
+                break;
+            }
+        }
+
+        if(_isarray)
+        {
+            for(;_offset<_json_data.size();_offset++)
+            {
+                if(_json_data[_offset]=='{')
+                {
+                    _isarray=false;
+                    break;
+                }   
+            }
+        }
+
+        if(_isarray==false)
+        {
+            if(_json_data[_offset]=='{')
+            {
+                _offset++;
+            }
+            std::string _json_key_name,_json_value_name;
+            for(;_offset<_json_data.size();_offset++)
+            {
+
+                //去除空格
+                _offset=http::json_string_trim(_json_data,_offset);
+                //如果是右侧括号表示这个对象已经结束
+                if(_json_data[_offset]==0x7D)
+                {
+                    return _offset;
+                }
+                //直到引号
+                if(_json_data[_offset]==0x22)
+                {
+                    unsigned int temp_offset=_offset;
+                    _json_value_name.clear();
+                    _json_key_name=http::jsonstring_to_utf8(&_json_data[_offset],_json_data.size()-_offset,temp_offset);
+
+                    _offset=temp_offset;
+                    if(_offset < _json_data.size() &&_json_data[_offset]==0x22)
+                    {
+                        _offset+=1;
+                    }
+                    //键名 后就是键值类型 循环去除空格
+                    _offset=http::json_string_trim(_json_data,_offset);
+                    if(_offset < _json_data.size() &&_json_data[_offset]!=':')
+                    {
+                        return _offset; 
+                    }
+                    _offset++;
+                    _offset=http::json_string_trim(_json_data,_offset);
+                    
+                    if(_offset < _json_data.size() &&_json_data[_offset]=='{')
+                    {   //还是一个对象,表示有嵌套对象
+                        //1 内置 struct map<std::string,*>
+                        //递归代码
+                    
+                            _offset++;
+                            for ( ; _offset < _json_data.size(); _offset++)
+                            {
+                                if (_json_data[_offset] == '}')
+                                {
+                                    //offset++;
+                                    break;
+                                }
+                                if (_json_data[_offset] == '"')
+                                {
+                                    _offset++;
+                                    for ( ; _offset < _json_data.size(); _offset++)
+                                    {
+                                        if (_json_data[_offset] == '"'&&_json_data[_offset-1]!=0x5C)
+                                        {
+                                            break;
+                                        }
+                                    }
+                                }
+                            }
+                                                
+
+                        if(_offset < _json_data.size() && (_json_data[_offset]==']'||_json_data[_offset]=='}'))
+                        {
+                            _offset-=1;
+                        }
+                        //直接下一个,不用处理键值
+                        continue;   
+                    }
+                    else if(_json_data[_offset]=='[')
+                    {   //表示有数组 
+                        //////////////////////////////////////////////////////////////////////
+                        //begin level1 []
+                        //vector<std::string> vector<std::pair<std::string,*>>   vector<vector<int|long|float|double>>
+                        //如果是非内置类型 直接使用json_decode<>
+
+                        //递归代码     
+
+                    
+                            _offset++;
+                            for ( ; _offset < _json_data.size(); _offset++)
+                            {
+                                if (_json_data[_offset] == ']')
+                                {
+                                    //offset++;
+                                    break;
+                                }
+                                if (_json_data[_offset] == '"')
+                                {
+                                    _offset++;
+                                    for ( ; _offset < _json_data.size(); _offset++)
+                                    {
+                                        if (_json_data[_offset] == '"'&&_json_data[_offset-1]!=0x5C)
+                                        {
+                                            break;
+                                        }
+                                    }
+                                }
+                            }
+                        
+                        //直接下一个,不用处理键值
+                        if(_offset < _json_data.size() && (_json_data[_offset]==']'||_json_data[_offset]=='}'))
+                        {
+                            _offset-=1;
+                        }
+                        continue;    
+                        //end level1[]
+                        ////////////////////////////////////////////////////////////////////
+                    }
+                    else if(_json_data[_offset]==0x22)
+                    {
+                        //如果键值也是字符串
+                        temp_offset=_offset;
+                        _json_value_name=http::jsonstring_to_utf8(&_json_data[_offset],_json_data.size()-_offset,temp_offset);
+                        _offset=temp_offset;
+                        if(_json_data[_offset]==0x22)
+                        {
+                            if((_offset+1)<_json_data.size())
+                            {
+                                if(_json_data[_offset+1]!=']'&&_json_data[_offset+1]!='}')
+                                {
+                                    _offset+=1;
+                                }
+                            }
+                        }
+                    }
+                    else
+                    {
+                        //表示是数字 bool NULL
+                        for(;_offset<_json_data.size();_offset++)
+                        {
+                            //结束条件
+                            if(_json_data[_offset]==','||_json_data[_offset]==']'||_json_data[_offset]=='}'||_json_data[_offset]==0x20||_json_data[_offset]==0x0A||_json_data[_offset]==0x0D||_json_data[_offset]=='\t')
+                            {
+                                break;
+                            }
+                            _json_value_name.push_back(_json_data[_offset]);
+                        }
+                        //让前面循环退出或返回
+                        if(_offset < _json_data.size() && _json_data[_offset]=='}')
+                        {
+                            _offset-=1;
+                        }
+                    }
+                    ////////////////////////////////////////////////////////
+                    // level1
+                    //处理对象赋值
+                    if (http::str_casecmp(_json_key_name, "message"))
+                            {
+
+                                json_reflectobj.message=_json_value_name;     
+                            }
+                            
+                    ////////////////////////////////////////////////////////
+                    //继续循环下一个键值
+                    continue;
+                }
+            }
+        }
+        return _offset;
+    }
+  
+unsigned int json_decode(std::vector<techempower_outjson_t> &json_reflectobj,const std::string &_json_data,unsigned int _offset)
+      {          
+             bool _isarray=false;
+        for(;_offset<_json_data.size();_offset++)
+        {
+            if(_json_data[_offset]=='{')
+            {
+                break;
+            }
+            if(_json_data[_offset]=='[')
+            {
+                _isarray=true;
+                break;
+            }
+        }
+
+        if(_isarray)
+        {
+            if(_json_data[_offset]=='[')
+            {
+                _offset+=1;
+            }
+            for(;_offset<_json_data.size();_offset++)
+            {
+                _offset=http::json_string_trim(_json_data,_offset);
+                //直接返回,这样可以防插入空的对象
+                if(_json_data[_offset]==0x5D)
+                {
+                    return _offset;
+                }else if(_json_data[_offset]=='{')
+                {
+                    techempower_outjson_t temp;
+                    _offset=json_decode(temp,_json_data,_offset);
+                    json_reflectobj.push_back(temp);
+                }
+
+            }
+            
+        }
+        else
+        {
+            techempower_outjson_t temp;
+            _offset=json_decode(temp,_json_data,_offset);
+            json_reflectobj.push_back(temp);
+            
+        }
+
+        return _offset; 
+    }
+         
+}