├── .clang-format ├── .github └── workflows │ ├── clang-format.yml │ ├── code-coverage.yml │ ├── linux-clang.yml │ ├── linux-gcc.yml │ ├── mac.yml │ └── windows.yml ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── benchmark ├── json_benchmark.cpp ├── json_benchmark.h ├── pb_benchmark.cpp ├── xml_bench.hpp ├── xml_benchmark.cpp ├── yaml_benchmark.cpp └── yaml_benchmark.hpp ├── data ├── apache_builds.json ├── appveyor.yml ├── bench_num.xml ├── canada.json ├── citm_catalog.json ├── github_events.json ├── gsoc-2018.json ├── instruments.json ├── marine_ik.json ├── mesh.json ├── mesh.pretty.json ├── numbers.json ├── random.json ├── rpm_filelists.xml ├── sample_rss.xml ├── travis.yml ├── twitter.json ├── twitterescaped.json └── update-center.json ├── example ├── example.cpp ├── json_example.cpp ├── xml_example.cpp └── yaml_example.cpp ├── frozen ├── CMakeLists.txt ├── algorithm.h ├── bits │ ├── algorithms.h │ ├── basic_types.h │ ├── constexpr_assert.h │ ├── defines.h │ ├── elsa.h │ ├── elsa_std.h │ ├── exceptions.h │ ├── hash_string.h │ ├── pmh.h │ └── version.h ├── map.h ├── random.h ├── set.h ├── string.h ├── unordered_map.h └── unordered_set.h ├── iguana ├── common.hpp ├── define.h ├── detail │ ├── charconv.h │ ├── dragonbox.h │ ├── dragonbox_to_chars.h │ ├── fast_float.h │ ├── itoa.hpp │ ├── pb_type.hpp │ ├── string_resize.hpp │ ├── string_stream.hpp │ ├── traits.hpp │ └── utf.hpp ├── dynamic.hpp ├── error_code.h ├── field_reflection.hpp ├── iguana.hpp ├── json_reader.hpp ├── json_util.hpp ├── json_writer.hpp ├── pb_reader.hpp ├── pb_util.hpp ├── pb_writer.hpp ├── prettify.hpp ├── util.hpp ├── value.hpp ├── version.hpp ├── xml_reader.hpp ├── xml_util.hpp ├── xml_writer.hpp ├── yaml_reader.hpp ├── yaml_util.hpp ├── yaml_writer.hpp └── ylt │ ├── reflection │ ├── internal │ │ ├── arg_list_macro.hpp │ │ ├── common_macro.hpp │ │ └── generate │ │ │ ├── arg_list_macro_gen.hpp │ │ │ └── member_macro.hpp │ ├── member_count.hpp │ ├── member_names.hpp │ ├── member_ptr.hpp │ ├── member_value.hpp │ ├── private_visitor.hpp │ ├── template_string.hpp │ ├── template_switch.hpp │ └── user_reflect_macro.hpp │ └── util │ └── expected.hpp ├── lang ├── iguana 使用文档.md ├── reflection.png ├── reflection_introduction.md └── struct_pb_intro.md ├── rapidxml ├── rapidxml.hpp └── rapidxml_print.hpp ├── scripts ├── automatic_macro_generator.py └── test_macro_generator.cpp ├── test ├── doctest.h ├── proto │ ├── data_def.proto │ ├── unittest_proto3.h │ └── unittest_proto3.proto ├── test_cpp20.cpp ├── test_headers.h ├── test_json_files.cpp ├── test_pb.cpp ├── test_proto3.cpp ├── test_reflection.cpp ├── test_some.cpp ├── test_util.cpp ├── test_xml.cpp ├── test_xml_nothrow.cpp ├── test_yaml.cpp ├── test_yaml_bech.cpp ├── test_yaml_nothrow.cpp └── unit_test.cpp └── tool ├── CMakeLists.txt ├── README.md ├── proto_to_struct.cpp ├── struct_code_generator.hpp └── struct_token.hpp /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | BasedOnStyle: Google 4 | # Should be declared this way: 5 | BreakBeforeBraces: Custom 6 | BraceWrapping: 7 | BeforeElse: true 8 | AllowShortLambdasOnASingleLine: None 9 | AllowShortIfStatementsOnASingleLine: Never 10 | --- 11 | Language: JavaScript 12 | DisableFormat: true 13 | --- 14 | Language: Proto 15 | DisableFormat: true -------------------------------------------------------------------------------- /.github/workflows/clang-format.yml: -------------------------------------------------------------------------------- 1 | name: Clang Format Diff 2 | 3 | on: 4 | push: 5 | branches: [ master, struct_pb ] 6 | pull_request: 7 | branches: [ master, struct_pb ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-22.04 13 | 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v3 17 | with: 18 | fetch-depth: 0 19 | - name: install clang-format 20 | run: sudo apt install clang-format 21 | - name: check-diff 22 | run : | 23 | diff=`git-clang-format --diff HEAD^` 24 | if ! [[ "$diff" = "no modified files to format" || "$diff" = "clang-format did not modify any files" ]]; then 25 | echo "The diff you sent is not formatted correctly." 26 | echo "the suggested format is" 27 | echo "$diff" 28 | exit 1 29 | fi 30 | -------------------------------------------------------------------------------- /.github/workflows/code-coverage.yml: -------------------------------------------------------------------------------- 1 | name: Upload CodeCov Report 2 | 3 | on: [ push, pull_request ] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - name: check out 12 | uses: actions/checkout@v3 13 | 14 | - name: Configure cmake 15 | run: cmake -B${{github.workspace}}/build -DCOVERAGE_TEST=ON -DCMAKE_BUILD_TYPE=Debug 16 | 17 | - name: Build 18 | run: cmake --build ${{github.workspace}}/build --config Debug 19 | 20 | - name: Test 21 | working-directory: ${{github.workspace}}/build 22 | env: 23 | CTEST_OUTPUT_ON_FAILURE: 1 24 | run: ctest -C ${{ matrix.configuration }} -j 1 -V 25 | 26 | - name: Upload coverage to Codecov 27 | uses: codecov/codecov-action@v1 28 | -------------------------------------------------------------------------------- /.github/workflows/linux-clang.yml: -------------------------------------------------------------------------------- 1 | name: Ubuntu (clang) 2 | 3 | on: 4 | push: 5 | branches: [ master, struct_pb ] 6 | pull_request: 7 | branches: [ master, struct_pb ] 8 | 9 | jobs: 10 | build: 11 | strategy: 12 | matrix: 13 | mode: [ Debug, Release ] 14 | cpp_version: [17, 20] 15 | runs-on: ubuntu-22.04 16 | 17 | steps: 18 | - name: check out 19 | uses: actions/checkout@v3 20 | 21 | - name: configure cmake 22 | run: CXX=clang++ CC=clang cmake -B ${{ github.workspace }}/build -DCMAKE_BUILD_TYPE=${{ matrix.mode }} -DCMAKE_CXX_STANDARD=${{ matrix.cpp_version }} -DLINKLIBC++=ON 23 | 24 | - name: build project 25 | run: cmake --build ${{ github.workspace }}/build --config ${{ matrix.mode }} 26 | 27 | - name: test 28 | working-directory: ${{ github.workspace }}/build 29 | run: ctest -C ${{ matrix.mode }} -j 1 -V 30 | 31 | -------------------------------------------------------------------------------- /.github/workflows/linux-gcc.yml: -------------------------------------------------------------------------------- 1 | name: Ubuntu (gcc) 2 | 3 | on: 4 | push: 5 | branches: [ master, struct_pb ] 6 | pull_request: 7 | branches: [ master, struct_pb ] 8 | 9 | jobs: 10 | ubuntu_gcc: 11 | strategy: 12 | matrix: 13 | mode: [ Debug, Release ] 14 | cpp_version: [20] 15 | runs-on: ubuntu-22.04 16 | 17 | steps: 18 | - name: check out 19 | uses: actions/checkout@v3 20 | 21 | - name: checkout gcc version 22 | run: gcc --version 23 | 24 | - name: Install Protobuf and Dev Package 25 | run: sudo apt-get update && sudo apt-get install -y protobuf-compiler libprotobuf-dev 26 | 27 | - name: configure cmake 28 | run: CXX=g++ CC=gcc cmake -B ${{ github.workspace }}/build -DCMAKE_BUILD_TYPE=${{ matrix.mode }} -DCMAKE_CXX_STANDARD=${{ matrix.cpp_version }} 29 | 30 | - name: build project 31 | run: cmake --build ${{ github.workspace }}/build --config ${{ matrix.mode }} 32 | 33 | - name: test 34 | working-directory: ${{ github.workspace }}/build 35 | run: ctest -C ${{ matrix.mode }} -j 1 -V 36 | 37 | ubuntu_gcc9: 38 | strategy: 39 | matrix: 40 | mode: [ Debug, Release ] 41 | cpp_version: [17] 42 | runs-on: ubuntu-22.04 43 | 44 | steps: 45 | - name: check out 46 | uses: actions/checkout@v3 47 | 48 | - name: checkout gcc version 49 | run: gcc --version 50 | 51 | - name: configure cmake 52 | run: CXX=g++ CC=gcc cmake -B ${{ github.workspace }}/build -DCMAKE_BUILD_TYPE=${{ matrix.mode }} -DCMAKE_CXX_STANDARD=${{ matrix.cpp_version }} 53 | 54 | - name: build project 55 | run: cmake --build ${{ github.workspace }}/build --config ${{ matrix.mode }} 56 | 57 | - name: test 58 | working-directory: ${{ github.workspace }}/build 59 | run: ctest -C ${{ matrix.mode }} -j 1 -V 60 | 61 | # ubuntu_gcc8: 62 | # strategy: 63 | # matrix: 64 | # mode: [ Debug, Release ] 65 | # cpp_version: [17] 66 | # runs-on: ubuntu-20.04 67 | 68 | # steps: 69 | # - name: check out 70 | # uses: actions/checkout@v3 71 | 72 | # - name: Install GCC8 73 | # run: | 74 | # sudo apt update 75 | # sudo apt install gcc-8 g++-8 76 | 77 | # - name: checkout gcc version 78 | # run: gcc-8 --version 79 | 80 | # - name: configure cmake 81 | # run: CXX=g++-8 CC=gcc-8 cmake -B ${{ github.workspace }}/build -DCMAKE_BUILD_TYPE=${{ matrix.mode }} -DCMAKE_CXX_STANDARD=${{ matrix.cpp_version }} 82 | 83 | # - name: build project 84 | # run: cmake --build ${{ github.workspace }}/build --config ${{ matrix.mode }} 85 | 86 | # - name: test 87 | # working-directory: ${{ github.workspace }}/build 88 | # run: ctest -C ${{ matrix.mode }} -j 1 -V -------------------------------------------------------------------------------- /.github/workflows/mac.yml: -------------------------------------------------------------------------------- 1 | name: macOS Monterey latest 2 | 3 | on: 4 | push: 5 | branches: [ master, struct_pb ] 6 | pull_request: 7 | branches: [ master, struct_pb ] 8 | 9 | jobs: 10 | build: 11 | strategy: 12 | matrix: 13 | mode: [ Debug, Release ] 14 | cpp_version: [17, 20] 15 | 16 | runs-on: macos-latest 17 | 18 | steps: 19 | - name: check out 20 | uses: actions/checkout@v3 21 | 22 | - name: configure cmake 23 | run: CXX=clang++ CC=clang cmake -B ${{ github.workspace }}/build -DCMAKE_BUILD_TYPE=${{ matrix.mode }} -DCMAKE_CXX_STANDARD=${{ matrix.cpp_version }} 24 | 25 | - name: build project 26 | run: cmake --build ${{ github.workspace }}/build --config ${{ matrix.mode }} 27 | 28 | - name: test 29 | working-directory: ${{ github.workspace }}/build 30 | run: ctest -C ${{ matrix.mode }} -j 1 -V 31 | -------------------------------------------------------------------------------- /.github/workflows/windows.yml: -------------------------------------------------------------------------------- 1 | name: Windows Server 2022 2 | 3 | on: 4 | push: 5 | branches: [ master, struct_pb ] 6 | pull_request: 7 | branches: [ master, struct_pb ] 8 | 9 | jobs: 10 | build: 11 | runs-on: windows-latest 12 | 13 | strategy: 14 | matrix: 15 | mode: [Debug, Release] 16 | cpp_version: [17, 20] 17 | arch: [x64] 18 | 19 | env: 20 | CXX: cl.exe 21 | CC: cl.exe 22 | 23 | steps: 24 | - name: check out 25 | uses: actions/checkout@v3 26 | 27 | - name: generate project 28 | run: cmake -B ${{ github.workspace }}\build -DCMAKE_BUILD_TYPE=${{ matrix.mode }} -A${{ matrix.arch }} -DCMAKE_CXX_STANDARD=${{ matrix.cpp_version }} 29 | 30 | - name: build iguana 31 | run: cmake --build ${{ github.workspace }}\build --config ${{ matrix.mode }} 32 | 33 | - name: test 34 | working-directory: ${{github.workspace}}\build 35 | run: ctest -C ${{matrix.mode}} -j 1 -V 36 | 37 | -------------------------------------------------------------------------------- /.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 | build 32 | .vscode 33 | .idea 34 | cmake-* 35 | .cache 36 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.15) 2 | project(iguana) 3 | 4 | message(STATUS "C++ Compiler Version: ${CMAKE_CXX_COMPILER_VERSION}") 5 | 6 | if(MSVC) 7 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17") 8 | add_compile_options(/utf-8) 9 | ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS) 10 | add_compile_options("$<$:/bigobj>") 11 | add_compile_options("$<$:/Zc:__cplusplus>") 12 | else() 13 | 14 | if(NOT LINKLIBC++) 15 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pthread -g ") 16 | message(STATUS "link libstdc++") 17 | else() 18 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pthread -g -stdlib=libc++") 19 | message(STATUS "link libc++") 20 | endif() 21 | 22 | set(CMAKE_CXX_FLAGS_RELEASE "-O3") 23 | endif(MSVC) 24 | set(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} -ldl") 25 | set(IGUANA_DIR ${CMAKE_CURRENT_SOURCE_DIR}) 26 | 27 | if(NOT CMAKE_CXX_STANDARD) 28 | set(CMAKE_CXX_STANDARD 17) 29 | endif() 30 | 31 | if(NOT CMAKE_BUILD_TYPE) 32 | set(CMAKE_BUILD_TYPE Release) 33 | endif() 34 | 35 | message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") 36 | message(STATUS "C++ standard: ${CMAKE_CXX_STANDARD}") 37 | 38 | add_definitions(-DTHROW_UNKNOWN_KEY) 39 | 40 | add_compile_options("$<$:/bigobj>") 41 | 42 | option(ENABLE_SEQUENTIAL_PARSE "parse json sequential more efficient if the json fields sequences are the same with struct fields" OFF) 43 | if (${ENABLE_SEQUENTIAL_PARSE}) 44 | ADD_DEFINITIONS(-DSEQUENTIAL_PARSE) 45 | endif () 46 | 47 | option(HAS_RAPIDJSON "import rapidjson" OFF) 48 | if (${HAS_RAPIDJSON}) 49 | add_definitions(-DHAS_RAPIDJSON) 50 | include_directories(../rapidjson/include) 51 | ADD_DEFINITIONS(-DRAPIDJSON_HAS_STDSTRING) 52 | endif() 53 | 54 | option(HAS_RAPIDYAML "import rapidyaml" OFF) 55 | if (${HAS_RAPIDYAML}) 56 | add_definitions(-DHAS_RAPIDYAML) 57 | endif() 58 | 59 | include_directories( 60 | ${IGUANA_DIR} 61 | ) 62 | 63 | if(CMAKE_COMPILER_IS_GNUCXX) 64 | link_libraries(stdc++fs) 65 | endif() 66 | 67 | set(JSON_EXAMPLE 68 | example/json_example.cpp 69 | ) 70 | 71 | set(XML_EXAMPLE 72 | example/xml_example.cpp 73 | ) 74 | set(YAML_EXAMPLE 75 | example/yaml_example.cpp 76 | ) 77 | 78 | set(TEST_SOME test/test_some.cpp) 79 | set(TEST_UT test/unit_test.cpp) 80 | set(TEST_JSON_FILES test/test_json_files.cpp) 81 | set(TEST_XML test/test_xml.cpp) 82 | set(JSONBENCHMARK benchmark/json_benchmark.cpp) 83 | set(XMLBENCH benchmark/xml_benchmark.cpp) 84 | set(TEST_YAML test/test_yaml.cpp test/test_yaml_bech.cpp) 85 | set(YAMLBENCH benchmark/yaml_benchmark.cpp) 86 | set(TEST_NOTHROW test/test_yaml_nothrow.cpp) 87 | set(TEST_UTIL test/test_util.cpp) 88 | set(TEST_XMLNOTHROW test/test_xml_nothrow.cpp) 89 | set(TEST_PB test/test_pb.cpp) 90 | set(TEST_PROTO test/test_proto3.cpp) 91 | set(TEST_CPP20 test/test_cpp20.cpp) 92 | set(PB_BENCHMARK benchmark/pb_benchmark.cpp) 93 | 94 | add_executable(json_example ${JSON_EXAMPLE}) 95 | add_executable(json_benchmark ${JSONBENCHMARK}) 96 | add_executable(test_some ${TEST_SOME}) 97 | add_executable(test_ut ${TEST_UT}) 98 | add_executable(test_json_files ${TEST_JSON_FILES}) 99 | add_executable(xml_example ${XML_EXAMPLE}) 100 | add_executable(test_xml ${TEST_XML}) 101 | add_executable(xml_benchmark ${XMLBENCH}) 102 | add_executable(test_xml_nothrow ${TEST_XMLNOTHROW}) 103 | add_executable(yaml_example ${YAML_EXAMPLE}) 104 | add_executable(test_yaml ${TEST_YAML}) 105 | add_executable(yaml_benchmark ${YAMLBENCH}) 106 | add_executable(test_nothrow ${TEST_NOTHROW}) 107 | add_executable(test_util ${TEST_UTIL}) 108 | add_executable(test_pb ${TEST_PB}) 109 | add_executable(test_cpp20 ${TEST_CPP20}) 110 | 111 | if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 112 | if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 9) 113 | message(STATUS "GCC version ${CMAKE_CXX_COMPILER_VERSION}") 114 | add_executable(test_reflection test/test_reflection.cpp) 115 | endif() 116 | else() 117 | add_executable(test_reflection test/test_reflection.cpp) 118 | endif() 119 | 120 | 121 | find_package(Protobuf QUIET) 122 | if(Protobuf_FOUND) 123 | add_definitions(-DSTRUCT_PB_WITH_PROTO) 124 | find_package(Protobuf REQUIRED) 125 | if(Protobuf_FOUND) 126 | message(STATUS "Found Protobuf: ${Protobuf_VERSION}") 127 | else() 128 | message(STATUS "Protobuf not found") 129 | endif() 130 | 131 | include_directories(${Protobuf_INCLUDE_DIRS}) 132 | include_directories(${CMAKE_CURRENT_BINARY_DIR}) 133 | set(PROTO_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/test/proto) 134 | file(GLOB PROTO_FILES ${PROTO_SRC_DIR}/*.proto) 135 | 136 | protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS ${PROTO_FILES}) 137 | message(STATUS "Proto source files: ${PROTO_SRCS}") 138 | message(STATUS "Proto header files: ${PROTO_HDRS}") 139 | 140 | add_executable(pb_benchmark ${PB_BENCHMARK} ${PROTO_SRCS}) 141 | target_link_libraries(pb_benchmark ${Protobuf_LIBRARIES}) 142 | add_executable(test_proto ${PROTO_SRCS} ${TEST_PROTO}) 143 | target_link_libraries(test_proto ${Protobuf_LIBRARIES}) 144 | add_test(NAME test_proto COMMAND test_proto) 145 | endif() 146 | 147 | # unit test 148 | option(BUILD_UNIT_TESTS "Build unit tests" ON) 149 | if (BUILD_UNIT_TESTS) 150 | enable_testing() 151 | endif () 152 | 153 | # coverage test 154 | option(COVERAGE_TEST "Build with unit test coverage" OFF) 155 | if(COVERAGE_TEST) 156 | if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 157 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage --coverage") 158 | else() 159 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-instr-generate -fcoverage-mapping") 160 | endif() 161 | endif() 162 | 163 | add_test(NAME test_some COMMAND test_some) 164 | add_test(NAME test_ut COMMAND test_ut) 165 | add_test(NAME test_json_files COMMAND test_json_files) 166 | add_test(NAME test_xml COMMAND test_xml) 167 | add_test(NAME test_yaml COMMAND test_yaml) 168 | add_test(NAME test_nothrow COMMAND test_nothrow) 169 | add_test(NAME test_util COMMAND test_util) 170 | add_test(NAME test_xml_nothrow COMMAND test_xml_nothrow) 171 | add_test(NAME test_pb COMMAND test_pb) 172 | add_test(NAME test_cpp20 COMMAND test_cpp20) 173 | -------------------------------------------------------------------------------- /benchmark/xml_bench.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "iguana/xml_reader.hpp" 13 | #include "iguana/xml_writer.hpp" 14 | 15 | // ************ struct for filelists.xml **************** 16 | 17 | struct package_t { 18 | std::optional version; 19 | std::vector file; 20 | }; 21 | YLT_REFL(package_t, version, file); 22 | 23 | struct filelists_t { 24 | std::vector package; 25 | }; 26 | YLT_REFL(filelists_t, package); 27 | // ************ struct for sample_rss.xml **************** 28 | 29 | struct skip_t { 30 | std::string_view skip; 31 | }; 32 | YLT_REFL(skip_t, skip); 33 | struct item_t { 34 | std::string_view title; 35 | std::string_view link; 36 | skip_t description; 37 | std::string_view pubDate; 38 | std::optional enclosure; 39 | std::string_view guid; 40 | std::string_view itunes_author; 41 | std::string_view itunes_subtitle; 42 | skip_t itunes_summary; 43 | std::string_view itunes_explicit; 44 | std::string_view itunes_duration; 45 | std::string_view dc_creator; 46 | std::optional media_thumbnail; 47 | std::string_view author; 48 | std::optional media_content; 49 | std::string_view itunes_keywords; 50 | }; 51 | YLT_REFL(item_t, title, link, description, pubDate, enclosure, guid, 52 | itunes_author, itunes_subtitle, itunes_summary, itunes_explicit, 53 | itunes_duration, dc_creator, media_thumbnail, author, media_content, 54 | itunes_keywords); 55 | 56 | struct image_t { 57 | std::string_view link; 58 | std::string_view url; 59 | std::string_view title; 60 | }; 61 | YLT_REFL(image_t, link, url, title); 62 | 63 | struct channel_t { 64 | std::string_view title; 65 | std::string_view link; 66 | std::string_view description; 67 | std::string_view generator; 68 | std::string_view docs; 69 | std::string_view language; 70 | std::string_view pubDate; 71 | std::string_view lastBuildDate; 72 | image_t image; 73 | std::string_view itunes_author; 74 | std::string_view itunes_subtitle; 75 | std::string_view itunes_keywords; 76 | std::optional itunes_image; 77 | std::string_view itunes_explicit; 78 | std::string_view itunes_block; 79 | std::vector item; 80 | std::string_view media_credit; 81 | std::string_view media_rating; 82 | std::string_view media_description; 83 | }; 84 | YLT_REFL(channel_t, title, link, description, generator, docs, language, 85 | pubDate, lastBuildDate, image, itunes_author, itunes_subtitle, 86 | itunes_keywords, itunes_image, itunes_explicit, itunes_block, item, 87 | media_credit, media_rating, media_description); 88 | 89 | struct rss_t { 90 | channel_t channel; 91 | }; 92 | YLT_REFL(rss_t, channel); 93 | 94 | // ************ struct for bench_num.xml **************** 95 | 96 | struct goods_t { 97 | std::string_view id; 98 | std::string_view sales; 99 | std::string_view inventory; 100 | std::string_view weight; 101 | std::string_view price; 102 | std::string_view rating; 103 | std::string_view discount; 104 | }; 105 | YLT_REFL(goods_t, id, sales, inventory, weight, price, rating, discount); 106 | struct storeowner_t { 107 | std::string_view name; 108 | std::string_view telephone; 109 | }; 110 | YLT_REFL(storeowner_t, name, telephone); 111 | struct store_t { 112 | std::string_view name; 113 | std::string_view address; 114 | storeowner_t owner; 115 | std::vector goods; 116 | }; 117 | YLT_REFL(store_t, name, address, owner, goods); 118 | -------------------------------------------------------------------------------- /benchmark/xml_benchmark.cpp: -------------------------------------------------------------------------------- 1 | #include "../rapidxml/rapidxml.hpp" 2 | #include "xml_bench.hpp" 3 | #include 4 | 5 | class ScopedTimer { 6 | public: 7 | ScopedTimer(const char *name) 8 | : m_name(name), m_beg(std::chrono::high_resolution_clock::now()) {} 9 | ScopedTimer(const char *name, uint64_t &ns) : ScopedTimer(name) { 10 | m_ns = &ns; 11 | } 12 | ~ScopedTimer() { 13 | auto end = std::chrono::high_resolution_clock::now(); 14 | auto dur = 15 | std::chrono::duration_cast(end - m_beg); 16 | if (m_ns) 17 | *m_ns = dur.count(); 18 | else 19 | std::cout << std::left << std::setw(45) << m_name << " : " << std::right 20 | << std::setw(12) << dur.count() << " ns\n"; 21 | } 22 | 23 | private: 24 | const char *m_name; 25 | std::chrono::time_point m_beg; 26 | uint64_t *m_ns = nullptr; 27 | }; 28 | 29 | std::string xml_file_content(const std::string &filename) { 30 | std::error_code ec; 31 | uint64_t size = std::filesystem::file_size(filename, ec); 32 | if (ec) { 33 | throw std::runtime_error("file size error " + ec.message()); 34 | } 35 | if (size == 0) { 36 | throw std::runtime_error("empty file"); 37 | } 38 | std::string content; 39 | content.resize(size); 40 | std::ifstream file(filename, std::ios::binary); 41 | file.read(content.data(), content.size()); 42 | return content; 43 | } 44 | const int iterations = 1000; 45 | void bench_de_sample_filelists() { 46 | 47 | std::string xmlfilelist = xml_file_content("../data/rpm_filelists.xml"); 48 | rapidxml::xml_document<> doc; 49 | filelists_t filelist; 50 | for (int i = 0; i < 10; i++) { 51 | { 52 | ScopedTimer timer("rapidxml fastest parse rpm_filelists.xml"); 53 | for (int i = 0; i < iterations; ++i) { 54 | doc.parse(xmlfilelist.data()); 55 | doc.clear(); 56 | } 57 | } 58 | 59 | { 60 | ScopedTimer timer("iguana_xml deserialize rpm_filelists.xml"); 61 | for (int i = 0; i < iterations; ++i) { 62 | iguana::from_xml(filelist, xmlfilelist.begin(), xmlfilelist.end()); 63 | filelist.package.clear(); 64 | } 65 | } 66 | } 67 | } 68 | 69 | void bench_de_sample_rss() { 70 | std::string xmlrss = xml_file_content("../data/sample_rss.xml"); 71 | rapidxml::xml_document<> doc; 72 | rss_t rss; 73 | for (int i = 0; i < 10; i++) { 74 | { 75 | ScopedTimer timer("rapidxml fastest parse sample_rss.xml"); 76 | for (int i = 0; i < iterations; ++i) { 77 | doc.parse(xmlrss.data()); 78 | doc.clear(); 79 | } 80 | } 81 | 82 | { 83 | ScopedTimer timer("iguana_xml deserialize sample_rss.xml"); 84 | for (int i = 0; i < iterations; ++i) { 85 | iguana::from_xml(rss, xmlrss.begin(), xmlrss.end()); 86 | rss.channel.item.clear(); 87 | } 88 | } 89 | } 90 | } 91 | 92 | void bench_num() { 93 | std::string xmlnum = xml_file_content("../data/bench_num.xml"); 94 | 95 | store_t s; 96 | iguana::from_xml(s, xmlnum); 97 | auto good = s.goods[1]; 98 | std::cout << iguana::get_number(good.sales) << ", " 99 | << iguana::get_number(good.weight) << "\n"; 100 | s.goods.clear(); 101 | rapidxml::xml_document<> doc; 102 | 103 | for (int i = 0; i < 10; i++) { 104 | { 105 | ScopedTimer timer("iguana_xml deserialize bench_num.xml"); 106 | for (int i = 0; i < iterations; ++i) { 107 | iguana::from_xml(s, xmlnum); 108 | s.goods.clear(); 109 | } 110 | } 111 | 112 | { 113 | ScopedTimer timer("rapidxml fastest parse bench_num.xml"); 114 | for (int i = 0; i < iterations; ++i) { 115 | doc.parse(xmlnum.data()); 116 | doc.clear(); 117 | } 118 | } 119 | } 120 | 121 | // store_t store; 122 | // iguana::from_xml(store, xmlnum); 123 | // std::string ss; 124 | // ss.reserve(xmlnum.size()); 125 | // { 126 | // ScopedTimer timer("iguana_xml serialize bench_num.xml"); 127 | // for (int i = 0; i < iterations; ++i) { 128 | // iguana::to_xml(store, ss); 129 | // ss.clear(); 130 | // } 131 | // } 132 | } 133 | 134 | int main() { 135 | bench_de_sample_filelists(); 136 | bench_de_sample_rss(); 137 | bench_num(); 138 | } 139 | -------------------------------------------------------------------------------- /benchmark/yaml_benchmark.cpp: -------------------------------------------------------------------------------- 1 | #include "yaml_benchmark.hpp" 2 | #ifdef HAS_RAPIDYAML 3 | #define RYML_SINGLE_HDR_DEFINE_NOW 4 | #include "rapidyaml/ryml_all.hpp" 5 | #endif 6 | 7 | const int iterations = 100000; 8 | void test_deserialize() { 9 | std::cout 10 | << "============ deserialize iguana appveyor.yml ===============\n"; 11 | std::string filestr = yaml_file_content("../data/appveyor.yml"); 12 | // ryml::Tree tree = ryml::parse_in_place(filestr.data()); 13 | std::vector src(filestr.begin(), filestr.end()); 14 | appveyor_t app; 15 | { 16 | ScopedTimer timer("test deserialize appveyor.yml"); 17 | for (int i = 0; i < iterations; ++i) { 18 | iguana::from_yaml(app, src.begin(), src.end()); 19 | } 20 | } 21 | std::cout << "============ deserialize iguana travis.yml ===============\n"; 22 | std::string travisstr = yaml_file_content("../data/travis.yml"); 23 | travis_t tra; 24 | { 25 | ScopedTimer timer("test deserialize travis.yml"); 26 | for (int i = 0; i < iterations; ++i) { 27 | iguana::from_yaml(tra, travisstr.begin(), travisstr.end()); 28 | } 29 | } 30 | } 31 | 32 | #ifdef HAS_RAPIDYAML 33 | void test_deserialize_ryml() { 34 | std::cout << "============ deserialize ryml appveyor.yml ===============\n"; 35 | std::string filestr = yaml_file_content("../data/appveyor.yml"); 36 | ryml::Tree tree1; 37 | { 38 | ScopedTimer timer("test deserialize appveyor.yml"); 39 | for (int i = 0; i < iterations; ++i) { 40 | ryml::parse_in_place(filestr.data()); 41 | } 42 | } 43 | std::cout << "============ deserialize ryml travis.yml ===============\n"; 44 | std::string travisstr = yaml_file_content("../data/travis.yml"); 45 | ryml::Tree tree2; 46 | { 47 | ScopedTimer timer("test deserialize travis.yml"); 48 | for (int i = 0; i < iterations; ++i) { 49 | ryml::parse_in_place(travisstr.data()); 50 | } 51 | } 52 | } 53 | #endif 54 | 55 | void test_serialize() { 56 | std::cout << "============ serialize iguana appveyor.yml ===============\n"; 57 | std::string filestr = yaml_file_content("../data/appveyor.yml"); 58 | appveyor_t app; 59 | iguana::from_yaml(app, filestr); 60 | 61 | std::string str; 62 | iguana::to_yaml(app, str); 63 | 64 | { 65 | ScopedTimer timer("test serialize appveyor.yml"); 66 | for (int i = 0; i < iterations; ++i) { 67 | str.clear(); 68 | iguana::to_yaml(app, str); 69 | } 70 | } 71 | std::cout << "============ serialize iguana travis.yml ===============\n"; 72 | std::string travisstr = yaml_file_content("../data/travis.yml"); 73 | travis_t tra; 74 | iguana::from_yaml(tra, travisstr); 75 | iguana::to_yaml(tra, str); 76 | 77 | { 78 | ScopedTimer timer("test serialize travis.yml"); 79 | for (int i = 0; i < iterations; ++i) { 80 | str.clear(); 81 | iguana::to_yaml(tra, str); 82 | } 83 | } 84 | } 85 | 86 | #ifdef HAS_RAPIDYAML 87 | void test_serialize_ryml() { 88 | std::cout << "============ serialize ryml appveyor.yml ===============\n"; 89 | std::string filestr = yaml_file_content("../data/appveyor.yml"); 90 | auto tree1 = ryml::parse_in_place(filestr.data()); 91 | std::string str = ryml::emitrs_yaml(tree1); 92 | 93 | { 94 | ScopedTimer timer("test serialize appveyor.yml"); 95 | for (int i = 0; i < iterations; ++i) { 96 | str.clear(); 97 | str = ryml::emitrs_yaml(tree1); 98 | } 99 | } 100 | std::cout << "============ serialize ryml travis.yml ===============\n"; 101 | std::string travisstr = yaml_file_content("../data/travis.yml"); 102 | auto tree2 = ryml::parse_in_place(travisstr.data()); 103 | str = ryml::emitrs_yaml(tree2); 104 | 105 | { 106 | ScopedTimer timer("test serialize travis.yml"); 107 | for (int i = 0; i < iterations; ++i) { 108 | str.clear(); 109 | str = ryml::emitrs_yaml(tree2); 110 | } 111 | } 112 | } 113 | #endif 114 | 115 | int main() { 116 | test_deserialize(); 117 | #ifdef HAS_RAPIDYAML 118 | test_deserialize_ryml(); 119 | #endif 120 | test_serialize(); 121 | #ifdef HAS_RAPIDYAML 122 | test_serialize_ryml(); 123 | #endif 124 | } -------------------------------------------------------------------------------- /benchmark/yaml_benchmark.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "iguana/yaml_reader.hpp" 4 | #include "iguana/yaml_writer.hpp" 5 | 6 | class ScopedTimer { 7 | public: 8 | ScopedTimer(const char *name) 9 | : m_name(name), m_beg(std::chrono::high_resolution_clock::now()) {} 10 | ScopedTimer(const char *name, uint64_t &ns) : ScopedTimer(name) { 11 | m_ns = &ns; 12 | } 13 | ~ScopedTimer() { 14 | auto end = std::chrono::high_resolution_clock::now(); 15 | auto dur = 16 | std::chrono::duration_cast(end - m_beg); 17 | if (m_ns) 18 | *m_ns = dur.count(); 19 | else 20 | std::cout << std::left << std::setw(45) << m_name << " : " << std::right 21 | << std::setw(12) << dur.count() << " ns\n"; 22 | } 23 | 24 | private: 25 | const char *m_name; 26 | std::chrono::time_point m_beg; 27 | uint64_t *m_ns = nullptr; 28 | }; 29 | 30 | std::string yaml_file_content(const std::string &filename) { 31 | std::error_code ec; 32 | uint64_t size = std::filesystem::file_size(filename, ec); 33 | if (ec) { 34 | throw std::runtime_error("file size error " + ec.message()); 35 | } 36 | if (size == 0) { 37 | throw std::runtime_error("empty file"); 38 | } 39 | std::string content; 40 | content.resize(size); 41 | std::ifstream file(filename, std::ios::binary); 42 | file.read(content.data(), content.size()); 43 | return content; 44 | } 45 | 46 | /*--------- YLT_REFL appveyor.yml-------------*/ 47 | 48 | struct matrix_t { 49 | std::string_view compiler; 50 | std::string_view generator; 51 | std::string_view configuration; 52 | }; 53 | YLT_REFL(matrix_t, compiler, generator, configuration); 54 | struct environment_t { 55 | std::vector matrix; 56 | }; 57 | YLT_REFL(environment_t, matrix); 58 | struct ex_matrix_t { 59 | std::string_view fast_finish; 60 | }; 61 | YLT_REFL(ex_matrix_t, fast_finish); 62 | struct artifact_t { 63 | std::string_view path; 64 | std::string_view name; 65 | }; 66 | YLT_REFL(artifact_t, path, name); 67 | struct skip_commit_t { 68 | std::vector files; 69 | }; 70 | YLT_REFL(skip_commit_t, files); 71 | struct appveyor_t { 72 | std::string_view version; 73 | std::string_view image; 74 | environment_t environment; 75 | ex_matrix_t matrix; 76 | std::vector install; 77 | std::vector build_script; 78 | std::vector test_script; 79 | std::vector artifacts; 80 | skip_commit_t skip_commits; 81 | }; 82 | YLT_REFL(appveyor_t, version, image, environment, matrix, install, build_script, 83 | test_script, artifacts, skip_commits); 84 | 85 | /*--------- YLT_REFL travis.yml-------------*/ 86 | struct apt_t { 87 | std::vector sources; 88 | }; 89 | YLT_REFL(apt_t, sources); 90 | struct addon_t { 91 | apt_t apt; 92 | }; 93 | YLT_REFL(addon_t, apt); 94 | 95 | struct env_t { 96 | std::vector global; 97 | }; 98 | YLT_REFL(env_t, global); 99 | 100 | struct in_env_t { 101 | std::string_view env; 102 | }; 103 | YLT_REFL(in_env_t, env); 104 | 105 | struct mat_t { 106 | std::vector include; 107 | }; 108 | YLT_REFL(mat_t, include); 109 | 110 | struct travis_t { 111 | std::string_view sudo; 112 | std::string_view dist; 113 | std::string_view language; 114 | addon_t addons; 115 | env_t env; 116 | mat_t matrix; 117 | std::vector install; 118 | std::vector script; 119 | std::vector after_success; 120 | }; 121 | YLT_REFL(travis_t, sudo, dist, language, addons, env, matrix, install, script, 122 | after_success); 123 | -------------------------------------------------------------------------------- /data/appveyor.yml: -------------------------------------------------------------------------------- 1 | version: '{build}' 2 | 3 | image: Visual Studio 2017 4 | 5 | environment: 6 | matrix: 7 | 8 | - compiler: msvc-15-seh 9 | generator: "Visual Studio 15 2017" 10 | configuration: Debug 11 | 12 | - compiler: msvc-15-seh 13 | generator: "Visual Studio 15 2017 Win64" 14 | configuration: Debug 15 | 16 | - compiler: msvc-15-seh 17 | generator: "Visual Studio 15 2017" 18 | configuration: Release 19 | 20 | - compiler: msvc-15-seh 21 | generator: "Visual Studio 15 2017 Win64" 22 | configuration: Release 23 | 24 | 25 | - compiler: msvc-14-seh 26 | generator: "Visual Studio 14 2015" 27 | configuration: Debug 28 | 29 | - compiler: msvc-14-seh 30 | generator: "Visual Studio 14 2015 Win64" 31 | configuration: Debug 32 | 33 | - compiler: msvc-14-seh 34 | generator: "Visual Studio 14 2015" 35 | configuration: Release 36 | 37 | - compiler: msvc-14-seh 38 | generator: "Visual Studio 14 2015 Win64" 39 | configuration: Release 40 | 41 | 42 | 43 | #- compiler: gcc-5.3.0-posix 44 | # generator: "MinGW Makefiles" 45 | # cxx_path: 'C:\mingw-w64\i686-5.3.0-posix-dwarf-rt_v4-rev0\mingw32\bin' 46 | # APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 47 | # configuration: Quicktest 48 | # externconfig: Debug 49 | # cmkargs: "-DC4STL_PEDANTIC=ON -DC4STL_WERROR=ON" 50 | 51 | matrix: 52 | fast_finish: true 53 | 54 | install: 55 | - git submodule update --init --recursive 56 | # git bash conflicts with MinGW makefiles 57 | - if "%generator%"=="MinGW Makefiles" (set "PATH=%PATH:C:\Program Files\Git\usr\bin;=%") 58 | - if not "%cxx_path%"=="" (set "PATH=%PATH%;%cxx_path%") 59 | 60 | build_script: 61 | - md _build -Force 62 | - cd _build 63 | 64 | test_script: 65 | - echo %configuration% 66 | - cmake -G "%generator%" "-DCMAKE_BUILD_TYPE=%configuration%" -DRYML_DEV=ON .. 67 | - dir 68 | - dir test 69 | - cmake --build . --config %configuration% --target ryml-test 70 | #- ctest -c %configuration% --timeout 300 --output-on-failure 71 | 72 | artifacts: 73 | - path: '_build/CMakeFiles/*.log' 74 | name: logs 75 | - path: '_build/Testing/**/*.xml' 76 | name: test_results 77 | 78 | skip_commits: 79 | files: 80 | - .gitignore 81 | - .travis* 82 | - .ci/travis* 83 | - .ci/dev_* 84 | - .ci/show_* 85 | - .ci/vagrant* 86 | - .ci/Vagrant* 87 | - bm/html/* 88 | - doc/* 89 | - LICENSE.txt 90 | - README.* 91 | -------------------------------------------------------------------------------- /data/travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: trusty 3 | language: cpp 4 | addons: 5 | apt: 6 | sources: 7 | - ubuntu-toolchain-r-test 8 | # - llvm-toolchain-trusty 9 | 10 | # we're not using combination parameters here to ensure that the builds 11 | # run in the order we want. (We want to perform the fastest tests first so 12 | # failed tests appear as early as possible). 13 | env: 14 | global: 15 | - PATH=/usr/local/bin:$PATH 16 | 17 | # NOTE: The compiler setting is unused. It simply makes the display on 18 | # travis-ci.org more readable. 19 | # WARNING: do not use the name CXX. Travis will ignore the value here. 20 | matrix: 21 | 22 | include: 23 | # 24 | # ----------- Coverage (covers all tests, slow) ------------------------- 25 | # 26 | - env: CXX_=g++-7 A=64 BT=Coverage 27 | - env: CXX_=g++-7 A=32 BT=Coverage 28 | # 29 | # ----------- other tests ----------------------------------------------- 30 | # 31 | #- env: CXX_=clang++-7 A=32 BT=Debug SAN=ALL VG=ON 32 | #- env: CXX_=clang++-7 A=64 BT=Debug SAN=ALL VG=ON 33 | #- env: CXX_=clang++-7 A=32 BT=Release SAN=ALL VG=ON 34 | #- env: CXX_=clang++-7 A=64 BT=Release SAN=ALL VG=ON 35 | 36 | - env: CXX_=g++-7 A=32 BT=Debug SAN=ALL VG=ON 37 | - env: CXX_=g++-7 A=64 BT=Debug SAN=ALL VG=ON 38 | - env: CXX_=g++-7 A=32 BT=Release SAN=ALL VG=ON 39 | - env: CXX_=g++-7 A=64 BT=Release SAN=ALL VG=ON 40 | 41 | - env: CXX_=clang++-6.0 A=32 BT=Debug SAN=ALL VG=ON 42 | - env: CXX_=clang++-6.0 A=64 BT=Debug SAN=ALL VG=ON 43 | - env: CXX_=clang++-6.0 A=32 BT=Release SAN=ALL VG=ON 44 | - env: CXX_=clang++-6.0 A=64 BT=Release SAN=ALL VG=ON 45 | 46 | - env: CXX_=clang++-5.0 A=32 BT=Debug SAN=ALL VG=ON 47 | - env: CXX_=clang++-5.0 A=64 BT=Debug SAN=ALL VG=ON 48 | - env: CXX_=clang++-5.0 A=32 BT=Release SAN=ALL VG=ON 49 | - env: CXX_=clang++-5.0 A=64 BT=Release SAN=ALL VG=ON 50 | 51 | - env: CXX_=clang++-4.0 A=32 BT=Debug SAN=ALL VG=ON 52 | - env: CXX_=clang++-4.0 A=64 BT=Debug SAN=ALL VG=ON 53 | - env: CXX_=clang++-4.0 A=32 BT=Release SAN=ALL VG=ON 54 | - env: CXX_=clang++-4.0 A=64 BT=Release SAN=ALL VG=ON 55 | 56 | - env: CXX_=clang++-3.9 A=32 BT=Debug SAN=ALL VG=ON 57 | - env: CXX_=clang++-3.9 A=64 BT=Debug SAN=ALL VG=ON 58 | - env: CXX_=clang++-3.9 A=32 BT=Release SAN=ALL VG=ON 59 | - env: CXX_=clang++-3.9 A=64 BT=Release SAN=ALL VG=ON 60 | 61 | - env: CXX_=g++-6 A=32 BT=Debug SAN=ALL VG=ON 62 | - env: CXX_=g++-6 A=64 BT=Debug SAN=ALL VG=ON 63 | - env: CXX_=g++-6 A=32 BT=Release SAN=ALL VG=ON 64 | - env: CXX_=g++-6 A=64 BT=Release SAN=ALL VG=ON 65 | 66 | - env: CXX_=clang++-3.8 A=32 BT=Debug SAN=ALL VG=ON 67 | - env: CXX_=clang++-3.8 A=64 BT=Debug SAN=ALL VG=ON 68 | - env: CXX_=clang++-3.8 A=32 BT=Release SAN=ALL VG=ON 69 | - env: CXX_=clang++-3.8 A=64 BT=Release SAN=ALL VG=ON 70 | 71 | - env: CXX_=g++-5 A=32 BT=Debug SAN=ALL VG=ON 72 | - env: CXX_=g++-5 A=64 BT=Debug SAN=ALL VG=ON 73 | - env: CXX_=g++-5 A=32 BT=Release SAN=ALL VG=ON 74 | - env: CXX_=g++-5 A=64 BT=Release SAN=ALL VG=ON 75 | 76 | - env: CXX_=clang++-3.7 A=32 BT=Debug SAN=ALL VG=ON 77 | - env: CXX_=clang++-3.7 A=64 BT=Debug SAN=ALL VG=ON 78 | - env: CXX_=clang++-3.7 A=32 BT=Release SAN=ALL VG=ON 79 | - env: CXX_=clang++-3.7 A=64 BT=Release SAN=ALL VG=ON 80 | 81 | #- env: CXX_=g++-4.9 A=32 BT=Debug SAN=ALL VG=ON 82 | #- env: CXX_=g++-4.9 A=64 BT=Debug SAN=ALL VG=ON 83 | #- env: CXX_=g++-4.9 A=32 BT=Release SAN=ALL VG=ON 84 | #- env: CXX_=g++-4.9 A=64 BT=Release SAN=ALL VG=ON 85 | 86 | - env: CXX_=clang++-3.6 A=32 BT=Debug SAN=ALL VG=ON 87 | - env: CXX_=clang++-3.6 A=64 BT=Debug SAN=ALL VG=ON 88 | - env: CXX_=clang++-3.6 A=32 BT=Release SAN=ALL VG=ON 89 | - env: CXX_=clang++-3.6 A=64 BT=Release SAN=ALL VG=ON 90 | 91 | # ----------- clang-tidy 92 | # 93 | - env: CXX_=clang++-6.0 A=32 BT=Debug LINT=clang-tidy 94 | - env: CXX_=clang++-6.0 A=64 BT=Debug LINT=clang-tidy 95 | - env: CXX_=clang++-6.0 A=32 BT=Release LINT=clang-tidy 96 | - env: CXX_=clang++-6.0 A=64 BT=Release LINT=clang-tidy 97 | # 98 | 99 | install: 100 | - bash -x .ci/travis-install.sh 101 | 102 | script: 103 | - bash -x .ci/travis-test.sh 104 | 105 | after_success: 106 | - echo "Success!" 107 | - bash -x .ci/travis-coverage.sh 108 | -------------------------------------------------------------------------------- /example/example.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | struct person { 8 | std::string name; 9 | int age; 10 | }; 11 | YLT_REFL(person, name, age) 12 | 13 | struct one_t { 14 | int id; 15 | }; 16 | YLT_REFL(one_t, id); 17 | 18 | struct two { 19 | std::string name; 20 | one_t one; 21 | int age; 22 | }; 23 | YLT_REFL(two, name, one, age); 24 | 25 | struct composit_t { 26 | int a; 27 | std::vector b; 28 | int c; 29 | std::map d; 30 | std::unordered_map e; 31 | double f; 32 | std::vector g; 33 | }; 34 | YLT_REFL(composit_t, a, b, c, d, e, f, g); 35 | 36 | void test_json() { 37 | person p; 38 | const std::string json = "{ \"name\" : \"tom\", \"age\" : 20}"; 39 | iguana::from_json(p, json); 40 | 41 | iguana::string_stream ss; 42 | iguana::to_json(p, ss); 43 | std::cout << ss << std::endl; 44 | 45 | one_t one = {2}; 46 | composit_t composit = {1, {"tom", "jack"}, 3, {{2, 3}}, {{5, 6}}, 5.3, {one}}; 47 | iguana::string_stream sst; 48 | iguana::to_json(composit, sst); 49 | std::cout << sst << std::endl; 50 | 51 | // const char* str_comp = R"({"a":1, "b":["tom", "jack"], "c":3, 52 | //"d":{"2":3,"5":6},"e":{"3":4},"f":5.3,"g":[{"id":1},{"id":2}])"; 53 | const std::string str_comp = 54 | R"({"b":["tom", "jack"], "a":1, "c":3, "e":{"3":4}, "d":{"2":3,"5":6},"f":5.3,"g":[{"id":1},{"id":2}])"; 55 | composit_t comp; 56 | iguana::from_json(comp, str_comp); 57 | std::cout << comp.a << " " << comp.f << std::endl; 58 | } 59 | 60 | // void performance() 61 | //{ 62 | // person obj; 63 | // char * json = "{ \"Name\" : \"Boo\", \"Age\" : 28}"; 64 | // ajson::load_from_buff(obj, json); 65 | // 66 | // const size_t LEN = 1000000; 67 | // 68 | // //�����л� 69 | // std::cout << "ajson deserialize: "; 70 | // boost::timer t; 71 | // for (size_t i = 0; i < LEN; i++) 72 | // { 73 | // ajson::load_from_buff(obj, json); 74 | // } 75 | // std::cout << t.elapsed() << std::endl; 76 | // 77 | // std::cout << "reflib deserialize: "; 78 | // t.restart(); 79 | // for (size_t i = 0; i < LEN; i++) 80 | // { 81 | // iguana::from_json(obj, json); 82 | // } 83 | // std::cout << t.elapsed() << std::endl; 84 | // 85 | // //���л� 86 | // std::cout << "ajson serialize: "; 87 | // t.restart(); 88 | // ajson::string_stream ss1; 89 | // 90 | // for (size_t i = 0; i < LEN; i++) 91 | // { 92 | // ss1.clear(); 93 | // ajson::save_to(ss1, obj); 94 | // } 95 | // std::cout << t.elapsed() << std::endl; 96 | // 97 | // std::cout << "reflib serialize: "; 98 | // t.restart(); 99 | // 100 | // iguana::json::string_stream ss; 101 | // for (size_t i = 0; i < LEN; i++) 102 | // { 103 | // ss.clear(); 104 | // iguana::to_json(obj, ss); 105 | // } 106 | // std::cout << t.elapsed() << std::endl; 107 | // } 108 | 109 | void test_xml() { 110 | person p = {"admin", 20}; 111 | iguana::string_stream ss; 112 | iguana::to_xml(p, ss); 113 | std::cout << ss << std::endl; 114 | 115 | ss.clear(); 116 | two t = {"test", {2}, 4}; 117 | iguana::to_xml(t, ss); 118 | 119 | std::cout << ss << std::endl; 120 | 121 | two t1; 122 | iguana::from_xml(t1, ss.data()); 123 | std::cout << t1.age << "\n"; 124 | } 125 | 126 | int main() { 127 | test_json(); 128 | test_xml(); 129 | } -------------------------------------------------------------------------------- /example/json_example.cpp: -------------------------------------------------------------------------------- 1 | #include // for to_chars 2 | #include // for std::cout 3 | 4 | namespace iguana { 5 | 6 | template 7 | inline char* to_chars_float(T value, char* buffer) { 8 | std::cout << "call custom to_chars_float with snprintf\n"; 9 | return buffer + snprintf(buffer, 65, "%g", value); 10 | } 11 | 12 | } // namespace iguana 13 | 14 | #include 15 | #include 16 | 17 | namespace client { 18 | struct person { 19 | std::string name; 20 | int64_t age; 21 | }; 22 | 23 | YLT_REFL(person, name, age); 24 | } // namespace client 25 | 26 | struct MyStruct { 27 | uint64_t a; 28 | }; 29 | YLT_REFL(MyStruct, a); 30 | 31 | struct student { 32 | int id; 33 | std::string name; 34 | int age; 35 | }; 36 | YLT_REFL(student, id, name, age); 37 | 38 | void test() { 39 | MyStruct p = {5566777755311}; 40 | iguana::string_stream ss; 41 | iguana::to_json(p, ss); 42 | 43 | MyStruct p2; 44 | iguana::from_json(p2, ss); 45 | std::cout << p2.a << std::endl; 46 | } 47 | 48 | void test_v() { 49 | client::person p1 = {"tom", 20}; 50 | client::person p2 = {"jack", 19}; 51 | client::person p3 = {"mike", 21}; 52 | 53 | std::vector v{p1, p2, p3}; 54 | iguana::string_stream ss; 55 | iguana::to_json(v, ss); 56 | std::cout << ss << std::endl; 57 | 58 | std::vector v1; 59 | iguana::from_json(v1, ss); 60 | } 61 | 62 | void test_disorder() { 63 | student s{1, "tom", 20}; 64 | iguana::string_stream ss; 65 | iguana::to_json(s, ss); 66 | std::cout << ss << std::endl; 67 | 68 | student s1{}; 69 | std::string str = "{\"name\":\"tom\",\"id\":1,\"age\":20}"; 70 | iguana::from_json(s1, str.data(), str.length()); 71 | std::string str1 = "{\"name\":\"tom\",\"age\":20,\"id\":1}"; 72 | iguana::from_json(s1, str1.data(), str1.length()); 73 | 74 | std::string str2 = "{ \"id\":1,\"name\" : \"madoka\",\"age\" : 27 }"; 75 | iguana::from_json(s1, str2.data(), str2.length()); 76 | } 77 | 78 | struct book_t { 79 | std::string_view title; 80 | std::string_view edition; 81 | std::vector author; 82 | }; 83 | YLT_REFL(book_t, title, edition, author); 84 | 85 | void test_str_view() { 86 | { 87 | std::string str = R"({ 88 | "title": "C++ templates", 89 | "edition": "invalid number", 90 | "author": [ 91 | "David Vandevoorde", 92 | "Nicolai M. Josuttis" 93 | ]})"; 94 | book_t b; 95 | iguana::from_json(b, str); 96 | std::cout << b.title << std::endl; 97 | std::cout << b.edition << std::endl; 98 | std::cout << b.author[0] << std::endl; 99 | std::cout << b.author[1] << std::endl; 100 | 101 | std::string ss; 102 | iguana::to_json(b, ss); 103 | std::cout << "to_json\n" << ss << "\n"; 104 | } 105 | } 106 | 107 | namespace my_space { 108 | struct my_struct { 109 | int x, y, z; 110 | bool operator==(const my_struct& o) const { 111 | return x == o.x && y == o.y && z == o.z; 112 | } 113 | }; 114 | 115 | void ylt_custom_reflect(my_struct*) {} 116 | 117 | template 118 | inline void to_json_impl(Stream& s, const my_struct& t) { 119 | iguana::to_json(*(int(*)[3]) & t, s); 120 | } 121 | 122 | template 123 | IGUANA_INLINE void from_json_impl(my_struct& value, It&& it, It&& end) { 124 | iguana::from_json(*(int(*)[3]) & value, it, end); 125 | } 126 | 127 | } // namespace my_space 128 | 129 | struct nest { 130 | std::string name; 131 | my_space::my_struct value; 132 | bool operator==(const nest& o) const { 133 | return name == o.name && value == o.value; 134 | } 135 | }; 136 | 137 | YLT_REFL(nest, name, value); 138 | 139 | void user_defined_struct_example() { 140 | { 141 | my_space::my_struct v{7, 8, 9}, v2; 142 | std::string s; 143 | iguana::to_json(v, s); 144 | std::cout << s << std::endl; 145 | iguana::from_json(v2, s); 146 | assert(v == v2); 147 | } 148 | { 149 | nest v{"Hi", {1, 2, 3}}, v2; 150 | std::string s; 151 | iguana::to_json(v, s); 152 | std::cout << s << std::endl; 153 | iguana::from_json(v2, s); 154 | assert(v == v2); 155 | } 156 | } 157 | 158 | struct test_float_t { 159 | double a; 160 | float b; 161 | }; 162 | YLT_REFL(test_float_t, a, b); 163 | 164 | void user_defined_tochars_example() { 165 | test_float_t t{2.011111, 2.54}; 166 | std::string ss; 167 | iguana::to_json(t, ss); 168 | std::cout << ss << std::endl; 169 | } 170 | 171 | int main(void) { 172 | test_disorder(); 173 | test_v(); 174 | test(); 175 | client::person p = {"zombie chow", -311}; 176 | iguana::string_stream ss; 177 | iguana::to_json(p, ss); 178 | 179 | std::cout << ss << std::endl; 180 | client::person p2; 181 | 182 | iguana::from_json(p2, ss.data(), ss.length()); 183 | 184 | std::cout << p2.name << " - " << p2.age << std::endl; 185 | test_str_view(); 186 | 187 | user_defined_struct_example(); 188 | user_defined_tochars_example(); 189 | return 0; 190 | } 191 | -------------------------------------------------------------------------------- /frozen/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | target_sources(frozen-headers INTERFACE 2 | "${prefix}/frozen/algorithm.h" 3 | "${prefix}/frozen/map.h" 4 | "${prefix}/frozen/random.h" 5 | "${prefix}/frozen/set.h" 6 | "${prefix}/frozen/string.h" 7 | "${prefix}/frozen/unordered_map.h" 8 | "${prefix}/frozen/unordered_set.h" 9 | "${prefix}/frozen/bits/algorithms.h" 10 | "${prefix}/frozen/bits/basic_types.h" 11 | "${prefix}/frozen/bits/elsa.h" 12 | "${prefix}/frozen/bits/pmh.h") 13 | -------------------------------------------------------------------------------- /frozen/algorithm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Frozen 3 | * Copyright 2016 QuarksLab 4 | * 5 | * Licensed to the Apache Software Foundation (ASF) under one 6 | * or more contributor license agreements. See the NOTICE file 7 | * distributed with this work for additional information 8 | * regarding copyright ownership. The ASF licenses this file 9 | * to you under the Apache License, Version 2.0 (the 10 | * "License"); you may not use this file except in compliance 11 | * with the License. You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, 16 | * software distributed under the License is distributed on an 17 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18 | * KIND, either express or implied. See the License for the 19 | * specific language governing permissions and limitations 20 | * under the License. 21 | */ 22 | 23 | #ifndef FROZEN_LETITGO_ALGORITHM_H 24 | #define FROZEN_LETITGO_ALGORITHM_H 25 | 26 | #include "frozen/bits/basic_types.h" 27 | #include "frozen/bits/version.h" 28 | #include "frozen/string.h" 29 | 30 | namespace frozen { 31 | 32 | // 'search' implementation if C++17 is not available 33 | // https://en.cppreference.com/w/cpp/algorithm/search 34 | template 35 | ForwardIterator search(ForwardIterator first, ForwardIterator last, 36 | const Searcher &searcher) { 37 | return searcher(first, last).first; 38 | } 39 | 40 | // text book implementation from 41 | // https://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm 42 | 43 | template class knuth_morris_pratt_searcher { 44 | bits::carray step_; 45 | bits::carray needle_; 46 | 47 | static constexpr bits::carray 48 | build_kmp_cache(char const (&needle)[size + 1]) { 49 | std::ptrdiff_t cnd = 0; 50 | bits::carray cache; 51 | 52 | cache.fill(-1); 53 | for (std::size_t pos = 1; pos < size; ++pos) { 54 | if (needle[pos] == needle[cnd]) { 55 | cache[pos] = cache[cnd]; 56 | cnd += 1; 57 | } else { 58 | cache[pos] = cnd; 59 | cnd = cache[cnd]; 60 | while (cnd >= 0 && needle[pos] != needle[cnd]) 61 | cnd = cache[cnd]; 62 | cnd += 1; 63 | } 64 | } 65 | return cache; 66 | } 67 | 68 | public: 69 | constexpr knuth_morris_pratt_searcher(char const (&needle)[size + 1]) 70 | : step_{build_kmp_cache(needle)}, needle_(needle) {} 71 | 72 | template 73 | constexpr std::pair 74 | operator()(ForwardIterator first, ForwardIterator last) const { 75 | std::size_t i = 0; 76 | ForwardIterator iter = first; 77 | while (iter != last) { 78 | if (needle_[i] == *iter) { 79 | if (i == (size - 1)) 80 | return {iter - i, iter - i + size}; 81 | ++i; 82 | ++iter; 83 | } else { 84 | if (step_[i] > -1) { 85 | i = step_[i]; 86 | } else { 87 | ++iter; 88 | i = 0; 89 | } 90 | } 91 | } 92 | return {last, last}; 93 | } 94 | }; 95 | 96 | template 97 | constexpr knuth_morris_pratt_searcher 98 | make_knuth_morris_pratt_searcher(char const (&needle)[N]) { 99 | return {needle}; 100 | } 101 | 102 | // text book implementation from 103 | // https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore%E2%80%93Horspool_algorithm 104 | 105 | template class boyer_moore_searcher { 106 | using skip_table_type = bits::carray; 107 | using suffix_table_type = bits::carray; 108 | 109 | skip_table_type skip_table_; 110 | suffix_table_type suffix_table_; 111 | bits::carray needle_; 112 | 113 | constexpr auto build_skip_table(char const (&needle)[size + 1]) { 114 | skip_table_type skip_table; 115 | 116 | skip_table.fill(size); 117 | for (std::size_t i = 0; i < size - 1; ++i) 118 | skip_table[needle[i]] -= i + 1; 119 | return skip_table; 120 | } 121 | 122 | constexpr bool is_prefix(char const (&needle)[size + 1], std::size_t pos) { 123 | std::size_t suffixlen = size - pos; 124 | 125 | for (std::size_t i = 0; i < suffixlen; i++) { 126 | if (needle[i] != needle[pos + i]) 127 | return false; 128 | } 129 | return true; 130 | } 131 | 132 | constexpr std::size_t suffix_length(char const (&needle)[size + 1], 133 | std::size_t pos) { 134 | // increment suffix length slen to the first mismatch or beginning 135 | // of the word 136 | for (std::size_t slen = 0; slen < pos; slen++) 137 | if (needle[pos - slen] != needle[size - 1 - slen]) 138 | return slen; 139 | 140 | return pos; 141 | } 142 | 143 | constexpr auto build_suffix_table(char const (&needle)[size + 1]) { 144 | suffix_table_type suffix; 145 | std::ptrdiff_t last_prefix_index = size - 1; 146 | 147 | // first loop 148 | for (std::ptrdiff_t p = size - 1; p >= 0; p--) { 149 | if (is_prefix(needle, p + 1)) 150 | last_prefix_index = p + 1; 151 | 152 | suffix[p] = last_prefix_index + (size - 1 - p); 153 | } 154 | 155 | // second loop 156 | for (std::size_t p = 0; p < size - 1; p++) { 157 | auto slen = suffix_length(needle, p); 158 | if (needle[p - slen] != needle[size - 1 - slen]) 159 | suffix[size - 1 - slen] = size - 1 - p + slen; 160 | } 161 | return suffix; 162 | } 163 | 164 | public: 165 | constexpr boyer_moore_searcher(char const (&needle)[size + 1]) 166 | : skip_table_{build_skip_table(needle)}, suffix_table_{build_suffix_table( 167 | needle)}, 168 | needle_(needle) {} 169 | 170 | template 171 | constexpr std::pair 172 | operator()(ForwardIterator first, ForwardIterator last) const { 173 | if (size == 0) 174 | return {first, first + size}; 175 | 176 | ForwardIterator iter = first + size - 1; 177 | while (iter < last) { 178 | std::ptrdiff_t j = size - 1; 179 | while (j > 0 && (*iter == needle_[j])) { 180 | --iter; 181 | --j; 182 | } 183 | if (*iter == needle_[0]) 184 | return {iter, iter + size}; 185 | 186 | iter += std::max(skip_table_[*iter], suffix_table_[j]); 187 | } 188 | return {last, last + size}; 189 | } 190 | }; 191 | 192 | template 193 | constexpr boyer_moore_searcher 194 | make_boyer_moore_searcher(char const (&needle)[N]) { 195 | return {needle}; 196 | } 197 | 198 | } // namespace frozen 199 | 200 | #endif 201 | -------------------------------------------------------------------------------- /frozen/bits/basic_types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Frozen 3 | * Copyright 2016 QuarksLab 4 | * 5 | * Licensed to the Apache Software Foundation (ASF) under one 6 | * or more contributor license agreements. See the NOTICE file 7 | * distributed with this work for additional information 8 | * regarding copyright ownership. The ASF licenses this file 9 | * to you under the Apache License, Version 2.0 (the 10 | * "License"); you may not use this file except in compliance 11 | * with the License. You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, 16 | * software distributed under the License is distributed on an 17 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18 | * KIND, either express or implied. See the License for the 19 | * specific language governing permissions and limitations 20 | * under the License. 21 | */ 22 | 23 | #ifndef FROZEN_LETITGO_BASIC_TYPES_H 24 | #define FROZEN_LETITGO_BASIC_TYPES_H 25 | 26 | #include "frozen/bits/exceptions.h" 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | namespace frozen { 34 | 35 | namespace bits { 36 | 37 | // used as a fake argument for frozen::make_set and frozen::make_map in the case 38 | // of N=0 39 | struct ignored_arg {}; 40 | 41 | template class cvector { 42 | T data[N] = {}; // zero-initialization for scalar type T, default-initialized 43 | // otherwise 44 | std::size_t dsize = 0; 45 | 46 | public: 47 | // Container typdefs 48 | using value_type = T; 49 | using reference = value_type &; 50 | using const_reference = const value_type &; 51 | using pointer = value_type *; 52 | using const_pointer = const value_type *; 53 | using iterator = pointer; 54 | using const_iterator = const_pointer; 55 | using size_type = std::size_t; 56 | using difference_type = std::ptrdiff_t; 57 | 58 | // Constructors 59 | constexpr cvector(void) = default; 60 | constexpr cvector(size_type count, const T &value) : dsize(count) { 61 | for (std::size_t i = 0; i < N; ++i) 62 | data[i] = value; 63 | } 64 | 65 | // Iterators 66 | constexpr iterator begin() noexcept { return data; } 67 | constexpr iterator end() noexcept { return data + dsize; } 68 | 69 | // Capacity 70 | constexpr size_type size() const { return dsize; } 71 | 72 | // Element access 73 | constexpr reference operator[](std::size_t index) { return data[index]; } 74 | constexpr const_reference operator[](std::size_t index) const { 75 | return data[index]; 76 | } 77 | 78 | constexpr reference back() { return data[dsize - 1]; } 79 | constexpr const_reference back() const { return data[dsize - 1]; } 80 | 81 | // Modifiers 82 | constexpr void push_back(const T &a) { data[dsize++] = a; } 83 | constexpr void push_back(T &&a) { data[dsize++] = std::move(a); } 84 | constexpr void pop_back() { --dsize; } 85 | 86 | constexpr void clear() { dsize = 0; } 87 | }; 88 | 89 | template class carray { 90 | T data_[N] = {}; // zero-initialization for scalar type T, default-initialized 91 | // otherwise 92 | 93 | template 94 | constexpr carray(T const (&init)[M], std::index_sequence) 95 | : data_{init[I]...} {} 96 | template 97 | constexpr carray(Iter iter, std::index_sequence) 98 | : data_{((void)I, *iter++)...} {} 99 | 100 | public: 101 | // Container typdefs 102 | using value_type = T; 103 | using reference = value_type &; 104 | using const_reference = const value_type &; 105 | using pointer = value_type *; 106 | using const_pointer = const value_type *; 107 | using iterator = pointer; 108 | using const_iterator = const_pointer; 109 | using reverse_iterator = std::reverse_iterator; 110 | using const_reverse_iterator = std::reverse_iterator; 111 | using size_type = std::size_t; 112 | using difference_type = std::ptrdiff_t; 113 | 114 | // Constructors 115 | constexpr carray(void) = default; 116 | template 117 | constexpr carray(T const (&init)[M]) 118 | : carray(init, std::make_index_sequence()) { 119 | static_assert(M >= N, "Cannot initialize a carray with an smaller array"); 120 | } 121 | template 122 | constexpr carray(std::array const &init) 123 | : carray(&init[0], std::make_index_sequence()) { 124 | static_assert(M >= N, "Cannot initialize a carray with an smaller array"); 125 | } 126 | constexpr carray(std::initializer_list init) 127 | : carray(init.begin(), std::make_index_sequence()) { 128 | // clang & gcc doesn't recognize init.size() as a constexpr 129 | // static_assert(init.size() >= N, "Cannot initialize a carray with an 130 | // smaller initializer list"); 131 | } 132 | 133 | // Iterators 134 | constexpr iterator begin() noexcept { return data_; } 135 | constexpr const_iterator begin() const noexcept { return data_; } 136 | constexpr const_iterator cbegin() const noexcept { return data_; } 137 | constexpr iterator end() noexcept { return data_ + N; } 138 | constexpr const_iterator end() const noexcept { return data_ + N; } 139 | constexpr const_iterator cend() const noexcept { return data_ + N; } 140 | 141 | constexpr reverse_iterator rbegin() noexcept { 142 | return reverse_iterator(end()); 143 | } 144 | constexpr const_reverse_iterator rbegin() const noexcept { 145 | return const_reverse_iterator(end()); 146 | } 147 | constexpr const_reverse_iterator crbegin() const noexcept { 148 | return const_reverse_iterator(end()); 149 | } 150 | constexpr reverse_iterator rend() noexcept { 151 | return reverse_iterator(begin()); 152 | } 153 | constexpr const_reverse_iterator rend() const noexcept { 154 | return const_reverse_iterator(begin()); 155 | } 156 | constexpr const_reverse_iterator crend() const noexcept { 157 | return const_reverse_iterator(begin()); 158 | } 159 | 160 | // Capacity 161 | constexpr size_type size() const { return N; } 162 | constexpr size_type max_size() const { return N; } 163 | 164 | // Element access 165 | constexpr reference operator[](std::size_t index) { return data_[index]; } 166 | constexpr const_reference operator[](std::size_t index) const { 167 | return data_[index]; 168 | } 169 | 170 | constexpr reference at(std::size_t index) { 171 | if (index > N) 172 | FROZEN_THROW_OR_ABORT( 173 | std::out_of_range("Index (" + std::to_string(index) + 174 | ") out of bound (" + std::to_string(N) + ')')); 175 | return data_[index]; 176 | } 177 | constexpr const_reference at(std::size_t index) const { 178 | if (index > N) 179 | FROZEN_THROW_OR_ABORT( 180 | std::out_of_range("Index (" + std::to_string(index) + 181 | ") out of bound (" + std::to_string(N) + ')')); 182 | return data_[index]; 183 | } 184 | 185 | constexpr reference front() { return data_[0]; } 186 | constexpr const_reference front() const { return data_[0]; } 187 | 188 | constexpr reference back() { return data_[N - 1]; } 189 | constexpr const_reference back() const { return data_[N - 1]; } 190 | 191 | constexpr value_type *data() noexcept { return data_; } 192 | constexpr const value_type *data() const noexcept { return data_; } 193 | 194 | // Modifiers 195 | constexpr void fill(const value_type &val) { 196 | for (std::size_t i = 0; i < N; ++i) 197 | data_[i] = val; 198 | } 199 | }; 200 | template class carray { 201 | 202 | public: 203 | // Container typdefs 204 | using value_type = T; 205 | using reference = value_type &; 206 | using const_reference = const value_type &; 207 | using pointer = value_type *; 208 | using const_pointer = const value_type *; 209 | using iterator = pointer; 210 | using const_iterator = const_pointer; 211 | using reverse_iterator = std::reverse_iterator; 212 | using const_reverse_iterator = std::reverse_iterator; 213 | using size_type = std::size_t; 214 | using difference_type = std::ptrdiff_t; 215 | 216 | // Constructors 217 | constexpr carray(void) = default; 218 | }; 219 | 220 | } // namespace bits 221 | 222 | } // namespace frozen 223 | 224 | #endif 225 | -------------------------------------------------------------------------------- /frozen/bits/constexpr_assert.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Frozen 3 | * Copyright 2016 QuarksLab 4 | * 5 | * Licensed to the Apache Software Foundation (ASF) under one 6 | * or more contributor license agreements. See the NOTICE file 7 | * distributed with this work for additional information 8 | * regarding copyright ownership. The ASF licenses this file 9 | * to you under the Apache License, Version 2.0 (the 10 | * "License"); you may not use this file except in compliance 11 | * with the License. You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, 16 | * software distributed under the License is distributed on an 17 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18 | * KIND, either express or implied. See the License for the 19 | * specific language governing permissions and limitations 20 | * under the License. 21 | */ 22 | 23 | #ifndef FROZEN_LETITGO_CONSTEXPR_ASSERT_H 24 | #define FROZEN_LETITGO_CONSTEXPR_ASSERT_H 25 | 26 | #include 27 | 28 | #ifdef _MSC_VER 29 | 30 | // FIXME: find a way to implement that correctly for msvc 31 | #define constexpr_assert(cond, msg) 32 | 33 | #else 34 | 35 | #define constexpr_assert(cond, msg) assert(cond &&msg); 36 | #endif 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /frozen/bits/defines.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Frozen 3 | * Copyright 2016 QuarksLab 4 | * 5 | * Licensed to the Apache Software Foundation (ASF) under one 6 | * or more contributor license agreements. See the NOTICE file 7 | * distributed with this work for additional information 8 | * regarding copyright ownership. The ASF licenses this file 9 | * to you under the Apache License, Version 2.0 (the 10 | * "License"); you may not use this file except in compliance 11 | * with the License. You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, 16 | * software distributed under the License is distributed on an 17 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18 | * KIND, either express or implied. See the License for the 19 | * specific language governing permissions and limitations 20 | * under the License. 21 | */ 22 | 23 | #ifndef FROZEN_LETITGO_DEFINES_H 24 | #define FROZEN_LETITGO_DEFINES_H 25 | 26 | #if defined(_MSVC_LANG) && \ 27 | !(defined(__EDG__) && defined(__clang__)) // TRANSITION, VSO#273681 28 | #define FROZEN_LETITGO_IS_MSVC 29 | #endif 30 | 31 | // Code taken from 32 | // https://stackoverflow.com/questions/43639122/which-values-can-msvc-lang-have 33 | #if defined(FROZEN_LETITGO_IS_MSVC) 34 | #if _MSVC_LANG > 201402 35 | #define FROZEN_LETITGO_HAS_CXX17 1 36 | #else /* _MSVC_LANG > 201402 */ 37 | #define FROZEN_LETITGO_HAS_CXX17 0 38 | #endif /* _MSVC_LANG > 201402 */ 39 | #else /* _MSVC_LANG etc. */ 40 | #if __cplusplus > 201402 41 | #define FROZEN_LETITGO_HAS_CXX17 1 42 | #else /* __cplusplus > 201402 */ 43 | #define FROZEN_LETITGO_HAS_CXX17 0 44 | #endif /* __cplusplus > 201402 */ 45 | #endif /* _MSVC_LANG etc. */ 46 | // End if taken code 47 | 48 | #if FROZEN_LETITGO_HAS_CXX17 == 1 && defined(FROZEN_LETITGO_IS_MSVC) 49 | #define FROZEN_LETITGO_HAS_STRING_VIEW // We assume Visual Studio always has 50 | // string_view in C++17 51 | #else 52 | #if FROZEN_LETITGO_HAS_CXX17 == 1 && __has_include() 53 | #define FROZEN_LETITGO_HAS_STRING_VIEW 54 | #endif 55 | #endif 56 | 57 | #ifdef __cpp_char8_t 58 | #define FROZEN_LETITGO_HAS_CHAR8T 59 | #endif 60 | 61 | #if __cpp_deduction_guides >= 201703L 62 | #define FROZEN_LETITGO_HAS_DEDUCTION_GUIDES 63 | #endif 64 | 65 | #if __cpp_lib_constexpr_string >= 201907L 66 | #define FROZEN_LETITGO_HAS_CONSTEXPR_STRING 67 | #endif 68 | 69 | #endif // FROZEN_LETITGO_DEFINES_H 70 | -------------------------------------------------------------------------------- /frozen/bits/elsa.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Frozen 3 | * Copyright 2016 QuarksLab 4 | * 5 | * Licensed to the Apache Software Foundation (ASF) under one 6 | * or more contributor license agreements. See the NOTICE file 7 | * distributed with this work for additional information 8 | * regarding copyright ownership. The ASF licenses this file 9 | * to you under the Apache License, Version 2.0 (the 10 | * "License"); you may not use this file except in compliance 11 | * with the License. You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, 16 | * software distributed under the License is distributed on an 17 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18 | * KIND, either express or implied. See the License for the 19 | * specific language governing permissions and limitations 20 | * under the License. 21 | */ 22 | 23 | #ifndef FROZEN_LETITGO_ELSA_H 24 | #define FROZEN_LETITGO_ELSA_H 25 | 26 | #include 27 | 28 | namespace frozen { 29 | 30 | template struct elsa { 31 | static_assert(std::is_integral::value || std::is_enum::value, 32 | "only supports integral types, specialize for other types"); 33 | 34 | constexpr std::size_t operator()(T const &value, std::size_t seed) const { 35 | std::size_t key = seed ^ static_cast(value); 36 | key = (~key) + (key << 21); // key = (key << 21) - key - 1; 37 | key = key ^ (key >> 24); 38 | key = (key + (key << 3)) + (key << 8); // key * 265 39 | key = key ^ (key >> 14); 40 | key = (key + (key << 2)) + (key << 4); // key * 21 41 | key = key ^ (key >> 28); 42 | key = key + (key << 31); 43 | return key; 44 | } 45 | }; 46 | 47 | template <> struct elsa { 48 | template 49 | constexpr std::size_t operator()(T const &value, std::size_t seed) const { 50 | return elsa{}(value, seed); 51 | } 52 | }; 53 | 54 | template using anna = elsa; 55 | } // namespace frozen 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /frozen/bits/elsa_std.h: -------------------------------------------------------------------------------- 1 | #ifndef FROZEN_LETITGO_BITS_ELSA_STD_H 2 | #define FROZEN_LETITGO_BITS_ELSA_STD_H 3 | 4 | #include "elsa.h" 5 | #include "hash_string.h" 6 | 7 | #ifdef FROZEN_LETITGO_HAS_STRING_VIEW 8 | #include 9 | #endif 10 | #include 11 | 12 | namespace frozen { 13 | 14 | #ifdef FROZEN_LETITGO_HAS_STRING_VIEW 15 | 16 | template struct elsa> { 17 | constexpr std::size_t 18 | operator()(const std::basic_string_view &value) const { 19 | return hash_string(value); 20 | } 21 | constexpr std::size_t operator()(const std::basic_string_view &value, 22 | std::size_t seed) const { 23 | return hash_string(value, seed); 24 | } 25 | }; 26 | 27 | #endif 28 | 29 | template struct elsa> { 30 | constexpr std::size_t 31 | operator()(const std::basic_string &value) const { 32 | return hash_string(value); 33 | } 34 | constexpr std::size_t operator()(const std::basic_string &value, 35 | std::size_t seed) const { 36 | return hash_string(value, seed); 37 | } 38 | }; 39 | 40 | } // namespace frozen 41 | 42 | #endif // FROZEN_LETITGO_BITS_ELSA_STD_H -------------------------------------------------------------------------------- /frozen/bits/exceptions.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Frozen 3 | * Copyright 2016 QuarksLab 4 | * 5 | * Licensed to the Apache Software Foundation (ASF) under one 6 | * or more contributor license agreements. See the NOTICE file 7 | * distributed with this work for additional information 8 | * regarding copyright ownership. The ASF licenses this file 9 | * to you under the Apache License, Version 2.0 (the 10 | * "License"); you may not use this file except in compliance 11 | * with the License. You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, 16 | * software distributed under the License is distributed on an 17 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18 | * KIND, either express or implied. See the License for the 19 | * specific language governing permissions and limitations 20 | * under the License. 21 | */ 22 | 23 | #ifndef FROZEN_LETITGO_EXCEPTIONS_H 24 | #define FROZEN_LETITGO_EXCEPTIONS_H 25 | 26 | #if defined(FROZEN_NO_EXCEPTIONS) || \ 27 | (defined(_MSC_VER) && !defined(_CPPUNWIND)) || \ 28 | (!defined(_MSC_VER) && !defined(__cpp_exceptions)) 29 | 30 | #include 31 | #define FROZEN_THROW_OR_ABORT(_) std::abort() 32 | 33 | #else 34 | 35 | #include 36 | #define FROZEN_THROW_OR_ABORT(err) throw err 37 | 38 | #endif 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /frozen/bits/hash_string.h: -------------------------------------------------------------------------------- 1 | #ifndef FROZEN_LETITGO_BITS_HASH_STRING_H 2 | #define FROZEN_LETITGO_BITS_HASH_STRING_H 3 | 4 | #include 5 | 6 | namespace frozen { 7 | 8 | template 9 | constexpr std::size_t hash_string(const String &value) { 10 | std::size_t d = 5381; 11 | for (const auto &c : value) 12 | d = d * 33 + static_cast(c); 13 | return d; 14 | } 15 | 16 | // https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function 17 | // With the lowest bits removed, based on experimental setup. 18 | template 19 | constexpr std::size_t hash_string(const String &value, std::size_t seed) { 20 | std::size_t d = (0x811c9dc5 ^ seed) * static_cast(0x01000193); 21 | for (const auto &c : value) 22 | d = (d ^ static_cast(c)) * static_cast(0x01000193); 23 | return d >> 8; 24 | } 25 | 26 | } // namespace frozen 27 | 28 | #endif // FROZEN_LETITGO_BITS_HASH_STRING_H -------------------------------------------------------------------------------- /frozen/bits/version.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Frozen 3 | * Copyright 2016 QuarksLab 4 | * 5 | * Licensed to the Apache Software Foundation (ASF) under one 6 | * or more contributor license agreements. See the NOTICE file 7 | * distributed with this work for additional information 8 | * regarding copyright ownership. The ASF licenses this file 9 | * to you under the Apache License, Version 2.0 (the 10 | * "License"); you may not use this file except in compliance 11 | * with the License. You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, 16 | * software distributed under the License is distributed on an 17 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18 | * KIND, either express or implied. See the License for the 19 | * specific language governing permissions and limitations 20 | * under the License. 21 | */ 22 | 23 | #ifndef FROZEN_LETITGO_VERSION_H 24 | #define FROZEN_LETITGO_VERSION_H 25 | 26 | #define FROZEN_MAJOR_VERSION 1 27 | #define FROZEN_MINOR_VERSION 1 28 | #define FROZEN_PATCH_VERSION 1 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /frozen/random.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Frozen 3 | * Copyright 2016 QuarksLab 4 | * 5 | * Licensed to the Apache Software Foundation (ASF) under one 6 | * or more contributor license agreements. See the NOTICE file 7 | * distributed with this work for additional information 8 | * regarding copyright ownership. The ASF licenses this file 9 | * to you under the Apache License, Version 2.0 (the 10 | * "License"); you may not use this file except in compliance 11 | * with the License. You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, 16 | * software distributed under the License is distributed on an 17 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18 | * KIND, either express or implied. See the License for the 19 | * specific language governing permissions and limitations 20 | * under the License. 21 | */ 22 | 23 | #ifndef FROZEN_LETITGO_RANDOM_H 24 | #define FROZEN_LETITGO_RANDOM_H 25 | 26 | #include "frozen/bits/algorithms.h" 27 | #include "frozen/bits/version.h" 28 | 29 | #include 30 | #include 31 | 32 | namespace frozen { 33 | template 34 | class linear_congruential_engine { 35 | 36 | static_assert(std::is_unsigned::value, 37 | "UIntType must be an unsigned integral type"); 38 | 39 | template 40 | static constexpr UIntType modulo(T val, std::integral_constant) { 41 | return static_cast(val); 42 | } 43 | 44 | template 45 | static constexpr UIntType modulo(T val, std::integral_constant) { 46 | // the static cast below may end up doing a truncation 47 | return static_cast(val % M); 48 | } 49 | 50 | public: 51 | using result_type = UIntType; 52 | static constexpr result_type multiplier = a; 53 | static constexpr result_type increment = c; 54 | static constexpr result_type modulus = m; 55 | static constexpr result_type default_seed = 1u; 56 | 57 | linear_congruential_engine() = default; 58 | constexpr linear_congruential_engine(result_type s) { seed(s); } 59 | 60 | void seed(result_type s = default_seed) { state_ = s; } 61 | constexpr result_type operator()() { 62 | using uint_least_t = 63 | bits::select_uint_least_t; 64 | uint_least_t tmp = 65 | static_cast(multiplier) * state_ + increment; 66 | 67 | state_ = modulo(tmp, std::integral_constant()); 68 | return state_; 69 | } 70 | // constexpr void discard(unsigned long long n) { 71 | // while (n--) 72 | // operator()(); 73 | // } 74 | // static constexpr result_type min() { return increment == 0u ? 1u : 0u; } 75 | // static constexpr result_type max() { return modulus - 1u; } 76 | friend constexpr bool operator==(linear_congruential_engine const &self, 77 | linear_congruential_engine const &other) { 78 | return self.state_ == other.state_; 79 | } 80 | friend constexpr bool operator!=(linear_congruential_engine const &self, 81 | linear_congruential_engine const &other) { 82 | return !(self == other); 83 | } 84 | 85 | private: 86 | result_type state_ = default_seed; 87 | }; 88 | 89 | using minstd_rand0 = 90 | linear_congruential_engine; 91 | using minstd_rand = 92 | linear_congruential_engine; 93 | 94 | // This generator is used by default in unordered frozen containers 95 | using default_prg_t = minstd_rand; 96 | 97 | } // namespace frozen 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /frozen/string.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Frozen 3 | * Copyright 2016 QuarksLab 4 | * 5 | * Licensed to the Apache Software Foundation (ASF) under one 6 | * or more contributor license agreements. See the NOTICE file 7 | * distributed with this work for additional information 8 | * regarding copyright ownership. The ASF licenses this file 9 | * to you under the Apache License, Version 2.0 (the 10 | * "License"); you may not use this file except in compliance 11 | * with the License. You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, 16 | * software distributed under the License is distributed on an 17 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18 | * KIND, either express or implied. See the License for the 19 | * specific language governing permissions and limitations 20 | * under the License. 21 | */ 22 | 23 | #ifndef FROZEN_LETITGO_STRING_H 24 | #define FROZEN_LETITGO_STRING_H 25 | 26 | #include "frozen/bits/defines.h" 27 | #include "frozen/bits/elsa.h" 28 | #include "frozen/bits/hash_string.h" 29 | #include "frozen/bits/version.h" 30 | 31 | #include 32 | #include 33 | 34 | #ifdef FROZEN_LETITGO_HAS_STRING_VIEW 35 | #include 36 | #endif 37 | 38 | namespace frozen { 39 | 40 | template class basic_string { 41 | using chr_t = _CharT; 42 | 43 | chr_t const *data_; 44 | std::size_t size_; 45 | 46 | public: 47 | template 48 | constexpr basic_string(chr_t const (&data)[N]) : data_(data), size_(N - 1) {} 49 | constexpr basic_string(chr_t const *data, std::size_t size) 50 | : data_(data), size_(size) {} 51 | 52 | #ifdef FROZEN_LETITGO_HAS_STRING_VIEW 53 | constexpr basic_string(std::basic_string_view data) 54 | : data_(data.data()), size_(data.size()) {} 55 | #endif 56 | 57 | constexpr basic_string(const basic_string &) noexcept = default; 58 | constexpr basic_string &operator=(const basic_string &) noexcept = default; 59 | 60 | constexpr std::size_t size() const { return size_; } 61 | 62 | constexpr chr_t operator[](std::size_t i) const { return data_[i]; } 63 | 64 | constexpr bool operator==(basic_string other) const { 65 | if (size_ != other.size_) 66 | return false; 67 | for (std::size_t i = 0; i < size_; ++i) 68 | if (data_[i] != other.data_[i]) 69 | return false; 70 | return true; 71 | } 72 | 73 | constexpr bool operator<(const basic_string &other) const { 74 | unsigned i = 0; 75 | while (i < size() && i < other.size()) { 76 | if ((*this)[i] < other[i]) { 77 | return true; 78 | } 79 | if ((*this)[i] > other[i]) { 80 | return false; 81 | } 82 | ++i; 83 | } 84 | return size() < other.size(); 85 | } 86 | 87 | constexpr const chr_t *data() const { return data_; } 88 | constexpr const chr_t *begin() const { return data(); } 89 | constexpr const chr_t *end() const { return data() + size(); } 90 | }; 91 | 92 | template struct elsa> { 93 | constexpr std::size_t operator()(basic_string<_CharT> value) const { 94 | return hash_string(value); 95 | } 96 | constexpr std::size_t operator()(basic_string<_CharT> value, 97 | std::size_t seed) const { 98 | return hash_string(value, seed); 99 | } 100 | }; 101 | 102 | using string = basic_string; 103 | using wstring = basic_string; 104 | using u16string = basic_string; 105 | using u32string = basic_string; 106 | 107 | #ifdef FROZEN_LETITGO_HAS_CHAR8T 108 | using u8string = basic_string; 109 | #endif 110 | 111 | namespace string_literals { 112 | 113 | constexpr string operator"" _s(const char *data, std::size_t size) { 114 | return {data, size}; 115 | } 116 | 117 | constexpr wstring operator"" _s(const wchar_t *data, std::size_t size) { 118 | return {data, size}; 119 | } 120 | 121 | constexpr u16string operator"" _s(const char16_t *data, std::size_t size) { 122 | return {data, size}; 123 | } 124 | 125 | constexpr u32string operator"" _s(const char32_t *data, std::size_t size) { 126 | return {data, size}; 127 | } 128 | 129 | #ifdef FROZEN_LETITGO_HAS_CHAR8T 130 | constexpr u8string operator"" _s(const char8_t *data, std::size_t size) { 131 | return {data, size}; 132 | } 133 | #endif 134 | 135 | } // namespace string_literals 136 | 137 | } // namespace frozen 138 | 139 | namespace std { 140 | template struct hash> { 141 | size_t operator()(frozen::basic_string<_CharT> s) const { 142 | return frozen::elsa>{}(s); 143 | } 144 | }; 145 | } // namespace std 146 | 147 | #endif 148 | -------------------------------------------------------------------------------- /frozen/unordered_set.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Frozen 3 | * Copyright 2016 QuarksLab 4 | * 5 | * Licensed to the Apache Software Foundation (ASF) under one 6 | * or more contributor license agreements. See the NOTICE file 7 | * distributed with this work for additional information 8 | * regarding copyright ownership. The ASF licenses this file 9 | * to you under the Apache License, Version 2.0 (the 10 | * "License"); you may not use this file except in compliance 11 | * with the License. You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, 16 | * software distributed under the License is distributed on an 17 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18 | * KIND, either express or implied. See the License for the 19 | * specific language governing permissions and limitations 20 | * under the License. 21 | */ 22 | 23 | #ifndef FROZEN_LETITGO_UNORDERED_SET_H 24 | #define FROZEN_LETITGO_UNORDERED_SET_H 25 | 26 | #include "frozen/bits/basic_types.h" 27 | #include "frozen/bits/constexpr_assert.h" 28 | #include "frozen/bits/elsa.h" 29 | #include "frozen/bits/pmh.h" 30 | #include "frozen/bits/version.h" 31 | #include "frozen/random.h" 32 | 33 | #include 34 | 35 | namespace frozen { 36 | 37 | namespace bits { 38 | 39 | struct Get { 40 | template constexpr T const &operator()(T const &key) const { 41 | return key; 42 | } 43 | }; 44 | 45 | } // namespace bits 46 | 47 | template , 48 | class KeyEqual = std::equal_to> 49 | class unordered_set { 50 | static constexpr std::size_t storage_size = 51 | bits::next_highest_power_of_two(N) * 52 | (N < 32 ? 2 : 1); // size adjustment to prevent high collision rate for 53 | // small sets 54 | using container_type = bits::carray; 55 | using tables_type = bits::pmh_tables; 56 | 57 | KeyEqual const equal_; 58 | container_type keys_; 59 | tables_type tables_; 60 | 61 | public: 62 | /* typedefs */ 63 | using key_type = Key; 64 | using value_type = Key; 65 | using size_type = typename container_type::size_type; 66 | using difference_type = typename container_type::difference_type; 67 | using hasher = Hash; 68 | using key_equal = KeyEqual; 69 | using const_reference = typename container_type::const_reference; 70 | using reference = const_reference; 71 | using const_pointer = typename container_type::const_pointer; 72 | using pointer = const_pointer; 73 | using const_iterator = const_pointer; 74 | using iterator = const_iterator; 75 | 76 | public: 77 | /* constructors */ 78 | unordered_set(unordered_set const &) = default; 79 | constexpr unordered_set(container_type keys, Hash const &hash, 80 | KeyEqual const &equal) 81 | : equal_{equal}, keys_{keys}, tables_{bits::make_pmh_tables( 82 | keys_, hash, bits::Get{}, 83 | default_prg_t{})} {} 84 | explicit constexpr unordered_set(container_type keys) 85 | : unordered_set{keys, Hash{}, KeyEqual{}} {} 86 | 87 | constexpr unordered_set(std::initializer_list keys) 88 | : unordered_set{keys, Hash{}, KeyEqual{}} {} 89 | 90 | constexpr unordered_set(std::initializer_list keys, Hash const &hash, 91 | KeyEqual const &equal) 92 | : unordered_set{container_type{keys}, hash, equal} { 93 | constexpr_assert( 94 | keys.size() == N, 95 | "Inconsistent initializer_list size and type size argument"); 96 | } 97 | 98 | /* iterators */ 99 | constexpr const_iterator begin() const { return keys_.begin(); } 100 | constexpr const_iterator end() const { return keys_.end(); } 101 | constexpr const_iterator cbegin() const { return keys_.cbegin(); } 102 | constexpr const_iterator cend() const { return keys_.cend(); } 103 | 104 | /* capacity */ 105 | constexpr bool empty() const { return !N; } 106 | constexpr size_type size() const { return N; } 107 | constexpr size_type max_size() const { return N; } 108 | 109 | /* lookup */ 110 | template 111 | constexpr std::size_t count(KeyType const &key, Hasher const &hash, 112 | Equal const &equal) const { 113 | auto const k = lookup(key, hash); 114 | return equal(k, key); 115 | } 116 | template 117 | constexpr std::size_t count(KeyType const &key) const { 118 | return count(key, hash_function(), key_eq()); 119 | } 120 | 121 | template 122 | constexpr const_iterator find(KeyType const &key, Hasher const &hash, 123 | Equal const &equal) const { 124 | auto const &k = lookup(key, hash); 125 | if (equal(k, key)) 126 | return &k; 127 | else 128 | return keys_.end(); 129 | } 130 | template 131 | constexpr const_iterator find(KeyType const &key) const { 132 | return find(key, hash_function(), key_eq()); 133 | } 134 | 135 | template 136 | constexpr std::pair 137 | equal_range(KeyType const &key, Hasher const &hash, 138 | Equal const &equal) const { 139 | auto const &k = lookup(key, hash); 140 | if (equal(k, key)) 141 | return {&k, &k + 1}; 142 | else 143 | return {keys_.end(), keys_.end()}; 144 | } 145 | template 146 | constexpr std::pair 147 | equal_range(KeyType const &key) const { 148 | return equal_range(key, hash_function(), key_eq()); 149 | } 150 | 151 | /* bucket interface */ 152 | constexpr std::size_t bucket_count() const { return storage_size; } 153 | constexpr std::size_t max_bucket_count() const { return storage_size; } 154 | 155 | /* observers*/ 156 | constexpr const hasher &hash_function() const { return tables_.hash_; } 157 | constexpr const key_equal &key_eq() const { return equal_; } 158 | 159 | private: 160 | template 161 | constexpr auto const &lookup(KeyType const &key, Hasher const &hash) const { 162 | return keys_[tables_.lookup(key, hash)]; 163 | } 164 | }; 165 | 166 | template 167 | constexpr auto make_unordered_set(T const (&keys)[N]) { 168 | return unordered_set{keys}; 169 | } 170 | 171 | template 172 | constexpr auto make_unordered_set(T const (&keys)[N], Hasher const &hash, 173 | Equal const &equal) { 174 | return unordered_set{keys, hash, equal}; 175 | } 176 | 177 | template 178 | constexpr auto make_unordered_set(std::array const &keys) { 179 | return unordered_set{keys}; 180 | } 181 | 182 | template 183 | constexpr auto make_unordered_set(std::array const &keys, 184 | Hasher const &hash, Equal const &equal) { 185 | return unordered_set{keys, hash, equal}; 186 | } 187 | 188 | #ifdef FROZEN_LETITGO_HAS_DEDUCTION_GUIDES 189 | 190 | template 191 | unordered_set(T, Args...) -> unordered_set; 192 | 193 | #endif 194 | 195 | } // namespace frozen 196 | 197 | #endif 198 | -------------------------------------------------------------------------------- /iguana/define.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if (defined(_MSC_VER) && _MSC_VER >= 1920 && _MSVC_LANG >= 202002L) || \ 4 | (!defined(_MSC_VER) && defined(__cplusplus) && __cplusplus >= 202002L) 5 | #include 6 | #endif 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #if defined __clang__ 14 | #define IGUANA_INLINE __attribute__((always_inline)) inline 15 | #define IGUANA__INLINE_LAMBDA __attribute__((always_inline)) constexpr 16 | #elif defined _MSC_VER 17 | #define IGUANA_INLINE __forceinline 18 | #define IGUANA__INLINE_LAMBDA constexpr 19 | #else 20 | #define IGUANA_INLINE __attribute__((always_inline)) inline 21 | #define IGUANA__INLINE_LAMBDA constexpr __attribute__((always_inline)) 22 | #endif 23 | 24 | #if __has_cpp_attribute(likely) && __has_cpp_attribute(unlikely) && \ 25 | __cplusplus >= 202002L 26 | #define IGUANA_LIKELY [[likely]] 27 | #define IGUANA_UNLIKELY [[unlikely]] 28 | #else 29 | #define IGUANA_LIKELY 30 | #define IGUANA_UNLIKELY 31 | #endif 32 | 33 | #ifdef _MSC_VER 34 | 35 | #if _MSC_VER >= 1920 && _MSVC_LANG >= 202002L 36 | IGUANA_INLINE int countr_zero(unsigned long long x) { 37 | return std::countr_zero(x); 38 | } 39 | template 40 | constexpr inline bool contiguous_iterator = std::contiguous_iterator; 41 | 42 | #else 43 | IGUANA_INLINE int countr_zero(unsigned long long n) { 44 | // x will never be zero in iguana 45 | #if defined(_MSC_VER) && defined(_M_X64) 46 | unsigned long c; 47 | _BitScanForward64(&c, n); 48 | return static_cast(c); 49 | #elif defined(_MSC_VER) && defined(_M_IX86) 50 | unsigned long c; 51 | if (static_cast(n) != 0) { 52 | _BitScanForward(&c, static_cast(n)); 53 | return static_cast(c); 54 | } 55 | else { 56 | _BitScanForward(&c, static_cast(n >> 32)); 57 | return static_cast(c) + 32; 58 | } 59 | #endif 60 | } 61 | 62 | namespace std { 63 | template 64 | using remove_cvref_t = 65 | typename remove_cv::type>::type; 66 | } 67 | template 68 | constexpr inline bool contiguous_iterator = 69 | std::is_same_v, 70 | typename std::vector::iterator> || 71 | std::is_same_v, 72 | typename std::vector::const_iterator> || 73 | std::is_same_v, typename std::string::iterator> || 74 | std::is_same_v, 75 | typename std::string::const_iterator> || 76 | std::is_same_v, char *> || 77 | std::is_same_v, 78 | typename std::string_view::iterator> || 79 | std::is_same_v, 80 | typename std::string_view::const_iterator>; 81 | #endif 82 | 83 | #else 84 | 85 | #if __cplusplus >= 202002L 86 | IGUANA_INLINE int countr_zero(unsigned long long x) { 87 | return std::countr_zero(x); 88 | } 89 | template 90 | constexpr inline bool contiguous_iterator = std::contiguous_iterator; 91 | #else 92 | IGUANA_INLINE int countr_zero(unsigned long long x) { 93 | // x will never be zero in iguana 94 | return __builtin_ctzll(x); 95 | } 96 | namespace std { 97 | template 98 | using remove_cvref_t = 99 | typename remove_cv::type>::type; 100 | } 101 | template 102 | constexpr inline bool contiguous_iterator = 103 | std::is_same_v, 104 | typename std::vector::iterator> || 105 | std::is_same_v, 106 | typename std::vector::const_iterator> || 107 | std::is_same_v, typename std::string::iterator> || 108 | std::is_same_v, 109 | typename std::string::const_iterator> || 110 | std::is_same_v, char *> || 111 | std::is_same_v, 112 | typename std::string_view::iterator> || 113 | std::is_same_v, 114 | typename std::string_view::const_iterator>; 115 | #endif 116 | 117 | #endif 118 | -------------------------------------------------------------------------------- /iguana/detail/charconv.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "dragonbox_to_chars.h" 5 | #include "fast_float.h" 6 | #include "iguana/define.h" 7 | #include "itoa.hpp" 8 | 9 | namespace iguana { 10 | template 11 | struct is_char_type 12 | : std::disjunction, std::is_same, 13 | std::is_same, std::is_same> {}; 14 | 15 | inline void *to_chars_float(...) { 16 | throw std::runtime_error("not allowed to invoke"); 17 | return {}; 18 | } 19 | 20 | template (), std::declval()))> 22 | using return_of_tochars = std::conditional_t, 23 | std::true_type, std::false_type>; 24 | // here std::true_type is used as a type , any other type is also ok. 25 | using has_to_chars_float = iguana::return_of_tochars; 26 | 27 | namespace detail { 28 | 29 | // check_number==true: check if the string [first, last) is a legal number 30 | template 31 | std::pair from_chars(const char *first, 32 | const char *last, U &value) { 33 | using T = std::decay_t; 34 | if constexpr (std::is_floating_point_v) { 35 | auto [p, ec] = fast_float::from_chars(first, last, value); 36 | if constexpr (check_number) { 37 | if (p != last || ec != std::errc{}) 38 | IGUANA_UNLIKELY { throw std::runtime_error("Failed to parse number"); } 39 | } 40 | return {p, ec}; 41 | } 42 | else { 43 | auto [p, ec] = std::from_chars(first, last, value); 44 | if constexpr (check_number) { 45 | if (p != last || ec != std::errc{}) 46 | IGUANA_UNLIKELY { throw std::runtime_error("Failed to parse number"); } 47 | } 48 | return {p, ec}; 49 | } 50 | } 51 | 52 | // not support uint8 for now 53 | template 54 | char *to_chars(char *buffer, T value) noexcept { 55 | using U = std::decay_t; 56 | if constexpr (std::is_floating_point_v) { 57 | if constexpr (has_to_chars_float::value) { 58 | return static_cast(to_chars_float(value, buffer)); 59 | } 60 | else { 61 | return jkj::dragonbox::to_chars(value, buffer); 62 | } 63 | } 64 | else if constexpr (std::is_signed_v && (sizeof(U) >= 8)) { 65 | return xtoa(value, buffer, 10, 1); // int64_t 66 | } 67 | else if constexpr (std::is_unsigned_v && (sizeof(U) >= 8)) { 68 | return xtoa(value, buffer, 10, 0); // uint64_t 69 | } 70 | else if constexpr (std::is_integral_v && (sizeof(U) > 1)) { 71 | return itoa_fwd(value, buffer); // only support more than 2 bytes intergal 72 | } 73 | else if constexpr (!is_char_type::value) { 74 | return itoa_fwd(static_cast(value), 75 | buffer); // only support more than 2 bytes intergal 76 | } 77 | else { 78 | static_assert(!sizeof(U), "only support arithmetic type except char type"); 79 | } 80 | } 81 | 82 | } // namespace detail 83 | } // namespace iguana 84 | -------------------------------------------------------------------------------- /iguana/detail/pb_type.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace iguana { 6 | 7 | struct sint32_t { 8 | using value_type = int32_t; 9 | int32_t val; 10 | bool operator==(const sint32_t& other) const { return val == other.val; } 11 | }; 12 | 13 | inline bool operator==(sint32_t value1, int32_t value2) { 14 | return value1.val == value2; 15 | } 16 | 17 | // for key in std::map 18 | inline bool operator<(const sint32_t& lhs, const sint32_t& rhs) { 19 | return lhs.val < rhs.val; 20 | } 21 | 22 | struct sint64_t { 23 | using value_type = int64_t; 24 | int64_t val; 25 | bool operator==(const sint64_t& other) const { return val == other.val; } 26 | }; 27 | 28 | inline bool operator==(sint64_t value1, int64_t value2) { 29 | return value1.val == value2; 30 | } 31 | 32 | inline bool operator<(const sint64_t& lhs, const sint64_t& rhs) { 33 | return lhs.val < rhs.val; 34 | } 35 | 36 | struct fixed32_t { 37 | using value_type = uint32_t; 38 | uint32_t val; 39 | bool operator==(const fixed32_t& other) const { return val == other.val; } 40 | }; 41 | 42 | inline bool operator==(fixed32_t value1, uint32_t value2) { 43 | return value1.val == value2; 44 | } 45 | 46 | inline bool operator<(const fixed32_t& lhs, const fixed32_t& rhs) { 47 | return lhs.val < rhs.val; 48 | } 49 | 50 | struct fixed64_t { 51 | using value_type = uint64_t; 52 | uint64_t val; 53 | bool operator==(const fixed64_t& other) const { return val == other.val; } 54 | }; 55 | 56 | inline bool operator==(fixed64_t value1, uint64_t value2) { 57 | return value1.val == value2; 58 | } 59 | 60 | inline bool operator<(const fixed64_t& lhs, const fixed64_t& rhs) { 61 | return lhs.val < rhs.val; 62 | } 63 | 64 | struct sfixed32_t { 65 | using value_type = int32_t; 66 | int32_t val; 67 | bool operator==(const sfixed32_t& other) const { return val == other.val; } 68 | }; 69 | 70 | inline bool operator==(sfixed32_t value1, int32_t value2) { 71 | return value1.val == value2; 72 | } 73 | 74 | inline bool operator<(const sfixed32_t& lhs, const sfixed32_t& rhs) { 75 | return lhs.val < rhs.val; 76 | } 77 | 78 | struct sfixed64_t { 79 | using value_type = int64_t; 80 | int64_t val; 81 | bool operator==(const sfixed64_t& other) const { return val == other.val; } 82 | }; 83 | 84 | inline bool operator==(sfixed64_t value1, int64_t value2) { 85 | return value1.val == value2; 86 | } 87 | 88 | inline bool operator<(const sfixed64_t& lhs, const sfixed64_t& rhs) { 89 | return lhs.val < rhs.val; 90 | } 91 | 92 | template > 93 | constexpr bool is_pb_type_v = 94 | std::is_same_v || std::is_same_v || 95 | std::is_same_v || std::is_same_v || 96 | std::is_same_v || std::is_same_v; 97 | 98 | } // namespace iguana 99 | 100 | // for key in std::unordered_map 101 | namespace std { 102 | template <> 103 | struct hash { 104 | size_t operator()(const iguana::sint32_t& x) const noexcept { 105 | return std::hash()(x.val); 106 | } 107 | }; 108 | 109 | template <> 110 | struct hash { 111 | size_t operator()(const iguana::sint64_t& x) const noexcept { 112 | return std::hash()(x.val); 113 | } 114 | }; 115 | 116 | template <> 117 | struct hash { 118 | size_t operator()(const iguana::fixed32_t& x) const noexcept { 119 | return std::hash()(x.val); 120 | } 121 | }; 122 | 123 | template <> 124 | struct hash { 125 | size_t operator()(const iguana::fixed64_t& x) const noexcept { 126 | return std::hash()(x.val); 127 | } 128 | }; 129 | 130 | template <> 131 | struct hash { 132 | size_t operator()(const iguana::sfixed32_t& x) const noexcept { 133 | return std::hash()(x.val); 134 | } 135 | }; 136 | 137 | template <> 138 | struct hash { 139 | size_t operator()(const iguana::sfixed64_t& x) const noexcept { 140 | return std::hash()(x.val); 141 | } 142 | }; 143 | } // namespace std 144 | -------------------------------------------------------------------------------- /iguana/detail/string_resize.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace iguana::detail { 8 | 9 | #if __cpp_lib_string_resize_and_overwrite >= 202110L 10 | template 11 | inline void resize(std::basic_string &str, std::size_t sz) { 12 | str.resize_and_overwrite(sz, [sz](ch *, std::size_t) { 13 | return sz; 14 | }); 15 | } 16 | #elif (defined(_MSC_VER) && _MSC_VER <= 1920) 17 | // old msvc don't support visit private, discard it. 18 | 19 | #else 20 | 21 | template 22 | class string_thief { 23 | public: 24 | friend void string_set_length_hacker(std::string &self, std::size_t sz) { 25 | #if defined(_MSVC_STL_VERSION) 26 | (self.*func_ptr)._Myval2._Mysize = sz; 27 | #else 28 | #if defined(_LIBCPP_VERSION) 29 | (self.*func_ptr)(sz); 30 | #else 31 | #if (_GLIBCXX_USE_CXX11_ABI == 0) && defined(__GLIBCXX__) 32 | (self.*func_ptr)()->_M_set_length_and_sharable(sz); 33 | #else 34 | #if defined(__GLIBCXX__) 35 | (self.*func_ptr)(sz); 36 | #endif 37 | #endif 38 | #endif 39 | #endif 40 | } 41 | }; 42 | 43 | #if defined(__GLIBCXX__) // libstdc++ 44 | #if (_GLIBCXX_USE_CXX11_ABI == 0) 45 | template class string_thief; 47 | #else 48 | template class string_thief; 50 | #endif 51 | #elif defined(_LIBCPP_VERSION) 52 | template class string_thief; 54 | #elif defined(_MSVC_STL_VERSION) 55 | template class string_thief; 57 | #endif 58 | 59 | void string_set_length_hacker(std::string &, std::size_t); 60 | 61 | template 62 | inline void resize(std::basic_string &raw_str, std::size_t sz) { 63 | std::string &str = *reinterpret_cast(&raw_str); 64 | #if defined(__GLIBCXX__) || defined(_LIBCPP_VERSION) || \ 65 | defined(_MSVC_STL_VERSION) 66 | if (sz > str.capacity()) { 67 | str.reserve(sz); 68 | } 69 | string_set_length_hacker(str, sz); 70 | str[sz] = '\0'; 71 | #else 72 | raw_str.resize(sz); 73 | #endif 74 | } 75 | 76 | #endif 77 | 78 | #if (defined(_MSC_VER) && _MSC_VER <= 1920) 79 | #else 80 | void vector_set_length_hacker(std::vector &self, std::size_t sz); 81 | 82 | template 83 | class vector_thief { 84 | public: 85 | friend void vector_set_length_hacker(std::vector &self, 86 | std::size_t sz) { 87 | #if defined(_MSVC_STL_VERSION) 88 | (self.*func_ptr)._Myval2._Mylast = self.data() + sz; 89 | #else 90 | #if defined(_LIBCPP_VERSION) 91 | #if _LIBCPP_VERSION < 14000 92 | ((*(std::__vector_base > *)(&self)).*func_ptr) = 93 | self.data() + sz; 94 | #else 95 | (self.*func_ptr) = self.data() + sz; 96 | #endif 97 | #else 98 | #if defined(__GLIBCXX__) 99 | ((*(std::_Vector_base > *)(&self)).*func_ptr) 100 | ._M_finish = self.data() + sz; 101 | #endif 102 | #endif 103 | #endif 104 | } 105 | }; 106 | 107 | #if defined(__GLIBCXX__) // libstdc++ 108 | template class vector_thief::_M_impl), 109 | &std::vector::_M_impl>; 110 | #elif defined(_LIBCPP_VERSION) 111 | template class vector_thief::__end_), 112 | &std::vector::__end_>; 113 | #elif defined(_MSVC_STL_VERSION) 114 | template class vector_thief::_Mypair), 115 | &std::vector::_Mypair>; 116 | #endif 117 | 118 | template 119 | inline void resize(std::vector &raw_vec, std::size_t sz) { 120 | #if defined(__GLIBCXX__) || \ 121 | (defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_NO_ASAN)) || \ 122 | defined(_MSVC_STL_VERSION) 123 | std::vector &vec = *reinterpret_cast *>(&raw_vec); 124 | vec.reserve(sz); 125 | vector_set_length_hacker(vec, sz); 126 | #else 127 | raw_vec.resize(sz); 128 | #endif 129 | } 130 | #endif 131 | }; // namespace iguana::detail -------------------------------------------------------------------------------- /iguana/detail/string_stream.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #if __has_include() 4 | #include 5 | #endif 6 | 7 | namespace iguana { 8 | #ifdef IGUANA_ENABLE_PMR 9 | #if __has_include() 10 | inline char iguana_buf[2048]; 11 | inline std::pmr::monotonic_buffer_resource iguana_resource(iguana_buf, 2048); 12 | using string_stream = std::pmr::string; 13 | #endif 14 | #else 15 | using string_stream = std::string; 16 | #endif 17 | } // namespace iguana -------------------------------------------------------------------------------- /iguana/detail/traits.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by QY on 2017-01-05. 3 | // 4 | 5 | #ifndef SERIALIZE_TRAITS_HPP 6 | #define SERIALIZE_TRAITS_HPP 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #if __cplusplus > 201703L 18 | #if __has_include() 19 | #include 20 | #endif 21 | #endif 22 | 23 | #include "iguana/define.h" 24 | 25 | namespace iguana { 26 | 27 | template 28 | struct is_signed_intergral_like 29 | : std::integral_constant::value) && 30 | std::is_signed::value> {}; 31 | 32 | template 33 | struct is_unsigned_intergral_like 34 | : std::integral_constant::value) && 35 | std::is_unsigned::value> {}; 36 | 37 | template