├── .clang-format ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── clang-format.yml │ ├── codeql.yml │ └── ctest.yml ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── cpp-dump.hpp ├── cpp-dump └── hpp │ ├── escape_sequence.hpp │ ├── expand_va_macro.hpp │ ├── export_command │ ├── export_command.hpp │ └── skip_container.hpp │ ├── export_var │ ├── export_arithmetic.hpp │ ├── export_asterisk.hpp │ ├── export_container.hpp │ ├── export_enum.hpp │ ├── export_enum_generic.hpp │ ├── export_exception.hpp │ ├── export_map.hpp │ ├── export_object.hpp │ ├── export_object_common.hpp │ ├── export_object_generic.hpp │ ├── export_ostream.hpp │ ├── export_other │ │ ├── export_es_value_t.hpp │ │ ├── export_optional.hpp │ │ ├── export_other.hpp │ │ ├── export_other_object.hpp │ │ └── export_type_info.hpp │ ├── export_pointer.hpp │ ├── export_set.hpp │ ├── export_string.hpp │ ├── export_tuple.hpp │ ├── export_unsupported.hpp │ ├── export_var.hpp │ ├── export_var_fwd.hpp │ └── export_xixo.hpp │ ├── iterable.hpp │ ├── log_label.hpp │ ├── options.hpp │ ├── type_check.hpp │ └── utility.hpp ├── dump.hpp ├── readme ├── auto-indent.cpp ├── auto-indent.png ├── cpp-dump.gif ├── customizable-colors-light-plus.png ├── customizable-colors.cpp ├── customizable-colors.png ├── customize-dump.cpp ├── customize-dump.png ├── formatting-with-manipulators.cpp ├── introduction.cpp ├── introduction.png ├── manipulator-addr.png ├── manipulator-bin-etc.png ├── manipulator-bw-boolnum.png ├── manipulator-charhex.png ├── manipulator-format.png ├── manipulator-front-etc.png ├── manipulator-index.png ├── manipulator-int-style.png ├── manipulator-int-style2.png ├── manipulator-stresc.png ├── manipulator-ubin-etc.png ├── no-es.cpp ├── supports-various-types.cpp ├── supports-various-types.png ├── test-code.cpp ├── user-defined-class-generic.cpp ├── user-defined-class-generic.png ├── user-defined-class-ostream.cpp ├── user-defined-class-ostream.png ├── user-defined-class.cpp ├── user-defined-class.png ├── user-defined-enum-generic.cpp ├── user-defined-enum-generic.png ├── user-defined-enum.cpp └── user-defined-enum.png └── test ├── clean_logs.sh ├── color_indent_test.cmake ├── color_non_variable_test.cmake ├── color_non_variable_test.cpp ├── color_rtti_test.cmake ├── color_rtti_test.cpp ├── color_std_version_test.cmake ├── color_std_version_test.cpp ├── color_variable_test.cmake ├── common.cmake ├── copy_txts.sh ├── dump_indent_test.cmake ├── dump_indent_test.cpp ├── dump_non_variable_test.cmake ├── dump_non_variable_test.cpp ├── dump_variable_test.cmake ├── dump_variable_test.cpp ├── log_label_test.cmake ├── log_label_test.cpp ├── odr_test.cpp ├── odr_test.hpp ├── readme_test.cmake ├── static_test.cpp └── txt ├── color_indent_normal_by_syntax.txt ├── color_indent_normal_original.txt ├── color_indent_shallow_by_syntax.txt ├── color_indent_shallow_original.txt ├── color_non_variable_by_syntax.txt ├── color_non_variable_original.txt ├── color_rtti.txt ├── color_std_version_20_clang.txt ├── color_std_version_20_gnu.txt ├── color_std_version_20_msvc.txt ├── color_variable_apple_by_syntax.txt ├── color_variable_apple_original.txt ├── color_variable_clang_by_syntax.txt ├── color_variable_clang_original.txt ├── color_variable_gnu_by_syntax.txt ├── color_variable_gnu_original.txt ├── color_variable_linux_by_syntax.txt ├── color_variable_linux_original.txt ├── color_variable_msvc_by_syntax.txt ├── color_variable_msvc_original.txt ├── color_variable_win32_by_syntax.txt ├── color_variable_win32_original.txt ├── dump_indent_narrow.txt ├── dump_indent_normal.txt ├── dump_indent_shallow.txt ├── dump_indent_wide.txt ├── dump_non_variable.txt ├── dump_variable_apple.txt ├── dump_variable_clang.txt ├── dump_variable_gnu.txt ├── dump_variable_linux.txt ├── dump_variable_msvc.txt ├── dump_variable_win32.txt ├── log_label_test.txt ├── readme_auto-indent.txt ├── readme_customizable-colors.txt ├── readme_customize-dump.txt ├── readme_formatting-with-manipulators.txt ├── readme_introduction.txt ├── readme_no-es.txt ├── readme_supports-various-types.txt ├── readme_test-code.txt ├── readme_user-defined-class-generic.txt ├── readme_user-defined-class-ostream.txt ├── readme_user-defined-class.txt ├── readme_user-defined-enum-generic.txt └── readme_user-defined-enum.txt /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: Google 3 | ColumnLimit: 100 4 | 5 | AlignAfterOpenBracket: BlockIndent 6 | 7 | BinPackArguments: false 8 | AllowAllArgumentsOnNextLine: true 9 | 10 | BinPackParameters: false 11 | AllowAllParametersOfDeclarationOnNextLine: true 12 | 13 | AllowShortIfStatementsOnASingleLine: AllIfsAndElse 14 | 15 | AlignConsecutiveAssignments: false 16 | AlignConsecutiveMacros: true 17 | 18 | BreakBeforeBinaryOperators: NonAssignment 19 | 20 | AlignEscapedNewlines: Right 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/clang-format.yml: -------------------------------------------------------------------------------- 1 | name: Clang-Format 2 | 3 | on: 4 | push: 5 | branches: ["main"] 6 | pull_request: 7 | schedule: 8 | - cron: "0 2 * * 6" 9 | 10 | jobs: 11 | run-clang-format: 12 | name: Run clang-format 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v3 18 | - name: Run clang-format 19 | uses: DoozyX/clang-format-lint-action@v0.16.2 20 | with: 21 | source: "." 22 | clangFormatVersion: 15 23 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: ["main"] 17 | pull_request: 18 | schedule: 19 | - cron: "0 2 * * 6" 20 | 21 | jobs: 22 | analyze: 23 | name: Analyze (${{ matrix.language }}) 24 | # Runner size impacts CodeQL analysis time. To learn more, please see: 25 | # - https://gh.io/recommended-hardware-resources-for-running-codeql 26 | # - https://gh.io/supported-runners-and-hardware-resources 27 | # - https://gh.io/using-larger-runners (GitHub.com only) 28 | # Consider using larger runners or machines with greater resources for possible analysis time improvements. 29 | runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} 30 | timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} 31 | permissions: 32 | # required for all workflows 33 | security-events: write 34 | 35 | # required to fetch internal or private CodeQL packs 36 | packages: read 37 | 38 | # only required for workflows in private repositories 39 | actions: read 40 | contents: read 41 | 42 | strategy: 43 | fail-fast: false 44 | matrix: 45 | include: 46 | - language: c-cpp 47 | build-mode: autobuild 48 | # CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' 49 | # Use `c-cpp` to analyze code written in C, C++ or both 50 | # Use 'java-kotlin' to analyze code written in Java, Kotlin or both 51 | # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both 52 | # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, 53 | # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. 54 | # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how 55 | # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages 56 | steps: 57 | - name: Checkout repository 58 | uses: actions/checkout@v4 59 | 60 | # Initializes the CodeQL tools for scanning. 61 | - name: Initialize CodeQL 62 | uses: github/codeql-action/init@v3 63 | with: 64 | languages: ${{ matrix.language }} 65 | build-mode: ${{ matrix.build-mode }} 66 | # If you wish to specify custom queries, you can do so here or in a config file. 67 | # By default, queries listed here will override any specified in a config file. 68 | # Prefix the list here with "+" to use these queries and those in the config file. 69 | 70 | # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 71 | # queries: security-extended,security-and-quality 72 | 73 | # If the analyze step fails for one of the languages you are analyzing with 74 | # "We were unable to automatically build your code", modify the matrix above 75 | # to set the build mode to "manual" for that language. Then modify this step 76 | # to build your code. 77 | # ℹ️ Command-line programs to run using the OS shell. 78 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 79 | - if: matrix.build-mode == 'manual' 80 | shell: bash 81 | run: | 82 | echo 'If you are using a "manual" build mode for one or more of the' \ 83 | 'languages you are analyzing, replace this with the commands to build' \ 84 | 'your code, for example:' 85 | echo ' make bootstrap' 86 | echo ' make release' 87 | exit 1 88 | 89 | - name: Perform CodeQL Analysis 90 | uses: github/codeql-action/analyze@v3 91 | with: 92 | category: "/language:${{matrix.language}}" 93 | -------------------------------------------------------------------------------- /.github/workflows/ctest.yml: -------------------------------------------------------------------------------- 1 | name: CTest 2 | 3 | on: 4 | push: 5 | branches: ["main"] 6 | pull_request: 7 | schedule: 8 | - cron: "0 2 * * 6" 9 | 10 | jobs: 11 | ctest: 12 | name: Test 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | env: 17 | - { os: ubuntu-22.04, compiler: g++ } 18 | - { os: ubuntu-22.04, compiler: clang++ } 19 | - { os: macos-latest, compiler: clang++ } 20 | - { os: windows-latest, compiler: cl } 21 | std: [17, 20] 22 | runs-on: ${{ matrix.env.os }} 23 | 24 | steps: 25 | - name: Checkout 26 | uses: actions/checkout@v3 27 | - name: Run Test 28 | run: | 29 | cmake -S . -B build -D CMAKE_CXX_COMPILER=${{matrix.env.compiler}} -D CMAKE_CXX_STANDARD=${{matrix.std}} -D CMAKE_CXX_STANDARD_REQUIRED=ON 30 | cmake --build build 31 | ctest --test-dir build --output-on-failure -C Debug 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | .cache/ 3 | build/ 4 | log/ 5 | *.out 6 | *.o 7 | *.log -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Ryota Sasaki 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /cpp-dump/hpp/export_command/skip_container.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Ryota Sasaki. 3 | * 4 | * This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "../iterable.hpp" 16 | 17 | namespace cpp_dump { 18 | 19 | namespace _detail { 20 | 21 | template 22 | struct skip_container; 23 | 24 | template 25 | struct skip_iterator { 26 | public: 27 | // It is not a reference when the constructor is given an rvalue. 28 | // It is an lvalue reference when the constructor is given an lvalue (reference). 29 | It it; 30 | 31 | skip_iterator( 32 | It &&it_, 33 | const std::function &)> 34 | &skip_size_func, 35 | const std::function &orig_size_func 36 | ) 37 | : it(std::forward(it_)), 38 | _skip_size_func(skip_size_func), 39 | _orig_size_func(orig_size_func), 40 | _index(0), 41 | _done(false) {} 42 | 43 | skip_iterator(skip_iterator &&) = delete; 44 | skip_iterator &operator=(skip_iterator &&) = delete; 45 | skip_iterator(const skip_iterator &) = delete; 46 | skip_iterator &operator=(const skip_iterator &) = delete; 47 | skip_iterator() = delete; 48 | 49 | std::tuple operator*() const noexcept { 50 | bool is_ellipsis = calc_skip_size() != 0; 51 | // Pass the iterator to support the case that *it is rvalue. 52 | // Pass the reference to support non-copyable iterators. 53 | // https://stackoverflow.com/questions/2568294/is-it-a-good-idea-to-create-an-stl-iterator-which-is-noncopyable 54 | return {is_ellipsis, const_cast(it), _index}; 55 | } 56 | template 57 | bool operator!=(const skip_iterator &to) noexcept { 58 | return !_done && it != to.it; 59 | } 60 | skip_iterator &operator++() noexcept { 61 | std::size_t skip_size = calc_skip_size(); 62 | if (skip_size == static_cast(-1)) { 63 | _done = true; 64 | } else if (skip_size == 0) { 65 | ++it; 66 | ++_index; 67 | } else { 68 | iterator_advance(it, skip_size); 69 | _index += skip_size; 70 | } 71 | return *this; 72 | } 73 | 74 | private: 75 | const std::function &)> 76 | &_skip_size_func; 77 | const std::function &_orig_size_func; 78 | std::size_t _index; 79 | bool _done; 80 | 81 | std::size_t calc_skip_size() const noexcept { return _skip_size_func(_index, _orig_size_func); } 82 | }; 83 | 84 | template 85 | skip_iterator(It &&, const std::function &)> &, const std::function &) 86 | -> skip_iterator; 87 | 88 | template 89 | struct skip_container { 90 | public: 91 | explicit skip_container( 92 | const T &container, 93 | const std::function &)> 94 | &skip_size_func 95 | ) 96 | : _original(container), _skip_size_func(skip_size_func) {} 97 | 98 | skip_container(skip_container &&) = delete; 99 | skip_container &operator=(skip_container &&) = delete; 100 | skip_container(const skip_container &) = delete; 101 | skip_container &operator=(const skip_container &) = delete; 102 | skip_container() = delete; 103 | 104 | auto begin() const noexcept { 105 | return skip_iterator(iterable_begin(_original), _skip_size_func, _orig_size_func); 106 | } 107 | auto end() const noexcept { 108 | return skip_iterator(iterable_end(_original), _skip_size_func, _orig_size_func); 109 | } 110 | 111 | private: 112 | const T &_original; 113 | const std::function &)> 114 | &_skip_size_func; 115 | 116 | std::optional _orig_size_cache; 117 | const std::function _orig_size_func = [this] { 118 | if (!_orig_size_cache) { 119 | _orig_size_cache = iterable_size(_original); 120 | } 121 | return _orig_size_cache.value(); 122 | }; 123 | }; 124 | 125 | } // namespace _detail 126 | 127 | } // namespace cpp_dump 128 | -------------------------------------------------------------------------------- /cpp-dump/hpp/export_var/export_asterisk.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Ryota Sasaki. 3 | * 4 | * This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "../escape_sequence.hpp" 15 | #include "../export_command/export_command.hpp" 16 | #include "../options.hpp" 17 | #include "../type_check.hpp" 18 | #include "./export_unsupported.hpp" 19 | #include "./export_var_fwd.hpp" 20 | 21 | namespace cpp_dump { 22 | 23 | namespace _detail { 24 | 25 | namespace _export_asterisk { 26 | 27 | inline std::string _es_asterisk(std::string_view s) { 28 | return options::es_style == types::es_style_t::original ? es::identifier(s) : es::op(s); 29 | } 30 | 31 | template 32 | inline auto export_asterisk( 33 | const T &value, 34 | const std::string &indent, 35 | std::size_t last_line_length, 36 | std::size_t current_depth, 37 | bool fail_on_newline, 38 | const export_command &command 39 | ) -> std::enable_if_t, std::string> { 40 | if (!options::enable_asterisk) { 41 | return export_unsupported(); 42 | } 43 | if (current_depth >= options::max_depth) { 44 | return _es_asterisk("*") + es::op("..."); 45 | } 46 | 47 | // We increase depth just in case so that *value won't enter an infinite loop. 48 | return _es_asterisk("*") 49 | + export_var( 50 | *value, indent, last_line_length + 1, current_depth + 1, fail_on_newline, command 51 | ); 52 | } 53 | 54 | } // namespace _export_asterisk 55 | 56 | using _export_asterisk::export_asterisk; 57 | 58 | } // namespace _detail 59 | 60 | } // namespace cpp_dump 61 | -------------------------------------------------------------------------------- /cpp-dump/hpp/export_var/export_container.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Ryota Sasaki. 3 | * 4 | * This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "../escape_sequence.hpp" 15 | #include "../export_command/export_command.hpp" 16 | #include "../iterable.hpp" 17 | #include "../options.hpp" 18 | #include "../type_check.hpp" 19 | #include "../utility.hpp" 20 | #include "./export_var_fwd.hpp" 21 | 22 | namespace cpp_dump { 23 | 24 | namespace _detail { 25 | 26 | template 27 | inline auto export_container( 28 | const T &container, 29 | const std::string &indent, 30 | std::size_t last_line_length, 31 | std::size_t current_depth, 32 | bool fail_on_newline, 33 | const export_command &command 34 | ) -> std::enable_if_t, std::string> { 35 | // In case the container is empty. 36 | if (is_empty_iterable(container)) { 37 | return es::bracket("[ ]", current_depth); 38 | } 39 | // In case the depth exceeds max_depth. 40 | if (current_depth >= options::max_depth) { 41 | return es::bracket("[ ", current_depth) + es::op("...") + es::bracket(" ]", current_depth); 42 | } 43 | 44 | // Declare variables. 45 | std::size_t next_depth = current_depth + 1; 46 | const auto &next_command = command.next(); 47 | auto skipped_container = command.create_skip_container(container); 48 | bool shift_indent = false; 49 | if (options::cont_indent_style == types::cont_indent_style_t::always) { 50 | shift_indent = true; 51 | } else if (options::cont_indent_style == types::cont_indent_style_t::when_nested) { 52 | shift_indent = is_iterable_like>; 53 | } else if (options::cont_indent_style == types::cont_indent_style_t::when_non_tuples_nested) { 54 | shift_indent = is_iterable_like> && !is_tuple>; 55 | } 56 | 57 | // Try printing on one line. 58 | if (!shift_indent) { 59 | std::string output = es::bracket("[ ", current_depth); 60 | bool is_first_elem = true; 61 | for (auto &&[is_ellipsis, it, index_] : skipped_container) { 62 | const auto &elem = *it; 63 | 64 | // Add comma. 65 | if (is_first_elem) { 66 | is_first_elem = false; 67 | } else { 68 | output += es::op(", "); 69 | } 70 | 71 | // If the `elem` is an ellipsis, skip it. 72 | if (is_ellipsis) { 73 | output += es::op("..."); 74 | if (last_line_length + get_length(output) + std::string_view(" ]").size() 75 | > options::max_line_width) { 76 | shift_indent = true; 77 | break; 78 | } 79 | continue; 80 | } 81 | 82 | // Add the index if needed. 83 | if (command.show_index()) { 84 | output += es::member(std::to_string(index_)) + es::op(": "); 85 | } 86 | 87 | // Add the stringified `elem`. 88 | std::string elem_str = export_var( 89 | elem, indent, last_line_length + get_length(output), next_depth, true, next_command 90 | ); 91 | if (has_newline(elem_str)) { 92 | shift_indent = true; 93 | break; 94 | } 95 | output += elem_str; 96 | 97 | // If the line length exceeds, stop the iteration. 98 | if (last_line_length + get_length(output) + std::string_view(" ]").size() 99 | > options::max_line_width) { 100 | shift_indent = true; 101 | break; 102 | } 103 | } 104 | 105 | if (!shift_indent) { 106 | output += es::bracket(" ]", current_depth); 107 | return output; 108 | } 109 | } 110 | 111 | // Print on multiple lines. 112 | 113 | if (fail_on_newline) { 114 | return "\n"; 115 | } 116 | 117 | // Declare variables. 118 | std::string new_indent = indent + " "; 119 | std::string output = es::bracket("[", current_depth); 120 | bool is_first_elem = true; 121 | 122 | // universal references; it.operator*() might not be const 123 | for (auto &&[is_ellipsis, it, index_] : skipped_container) { 124 | const auto &elem = *it; 125 | 126 | // Add comma. 127 | if (is_first_elem) { 128 | is_first_elem = false; 129 | } else { 130 | output += es::op(","); 131 | } 132 | 133 | // If the `elem` is an ellipsis, skip it. 134 | if (is_ellipsis) { 135 | output += "\n" + new_indent + es::op("..."); 136 | continue; 137 | } 138 | 139 | output += "\n" + new_indent; 140 | 141 | // Add the index if needed. 142 | if (command.show_index()) { 143 | output += es::member(std::to_string(index_)) + es::op(": "); 144 | } 145 | 146 | // Add the stringified `elem`. 147 | output += 148 | export_var(elem, new_indent, get_last_line_length(output), next_depth, false, next_command); 149 | } 150 | output += "\n" + indent + es::bracket("]", current_depth); 151 | 152 | return output; 153 | } 154 | 155 | } // namespace _detail 156 | 157 | } // namespace cpp_dump 158 | -------------------------------------------------------------------------------- /cpp-dump/hpp/export_var/export_enum.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Ryota Sasaki. 3 | * 4 | * This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "../escape_sequence.hpp" 15 | #include "../expand_va_macro.hpp" 16 | #include "../export_command/export_command.hpp" 17 | #include "../options.hpp" 18 | #include "../type_check.hpp" 19 | 20 | #define _p_CPP_DUMP_EXPAND_FOR_EXPORT_ENUM(member) \ 21 | { member, #member } 22 | 23 | /** 24 | * Make cpp_dump::export_var() support enum TYPE. 25 | */ 26 | #define CPP_DUMP_DEFINE_EXPORT_ENUM(TYPE, ...) \ 27 | namespace cpp_dump { \ 28 | \ 29 | namespace _detail { \ 30 | \ 31 | template <> \ 32 | inline constexpr bool _is_exportable_enum = true; \ 33 | \ 34 | template <> \ 35 | inline std::string \ 36 | export_enum(const TYPE &enum_const, const std::string &, std::size_t, std::size_t, bool, const export_command &) { \ 37 | static const std::map enum_to_string{ \ 38 | _p_CPP_DUMP_EXPAND_VA(_p_CPP_DUMP_EXPAND_FOR_EXPORT_ENUM, __VA_ARGS__)}; \ 39 | return enum_to_string.count(enum_const) \ 40 | ? es::enumerator(enum_to_string.at(enum_const)) \ 41 | : es::class_name(#TYPE) + es::op("::") + es::unsupported("?"); \ 42 | } \ 43 | \ 44 | } /* namespace _detail */ \ 45 | \ 46 | } // namespace cpp_dump 47 | 48 | namespace cpp_dump { 49 | 50 | namespace _detail { 51 | 52 | template 53 | inline std::string 54 | export_enum(const T &, const std::string &, std::size_t, std::size_t, bool, const export_command &); 55 | 56 | } // namespace _detail 57 | 58 | } // namespace cpp_dump 59 | 60 | CPP_DUMP_DEFINE_EXPORT_ENUM( 61 | cpp_dump::types::es_style_t, 62 | cpp_dump::types::es_style_t::no_es, 63 | cpp_dump::types::es_style_t::original, 64 | cpp_dump::types::es_style_t::by_syntax 65 | ); 66 | CPP_DUMP_DEFINE_EXPORT_ENUM( 67 | cpp_dump::types::cont_indent_style_t, 68 | cpp_dump::types::cont_indent_style_t::minimal, 69 | cpp_dump::types::cont_indent_style_t::when_nested, 70 | cpp_dump::types::cont_indent_style_t::when_non_tuples_nested, 71 | cpp_dump::types::cont_indent_style_t::always 72 | ); 73 | -------------------------------------------------------------------------------- /cpp-dump/hpp/export_var/export_enum_generic.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Ryota Sasaki. 3 | * 4 | * This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "../escape_sequence.hpp" 15 | #include "../expand_va_macro.hpp" 16 | #include "../export_command/export_command.hpp" 17 | #include "../type_check.hpp" 18 | 19 | #define _p_CPP_DUMP_EXPAND_FOR_EXPORT_ENUM_GENERIC(member) T::member 20 | #define _p_CPP_DUMP_EXPAND_FOR_EXPORT_ENUM_GENERIC2(member) \ 21 | { T::member, #member } 22 | 23 | /** 24 | * Make cpp_dump::export_var() support every enum type that has the specified members. 25 | * Compile errors in this macro, such as ambiguous function calls, are never reported due to SFINAE. 26 | */ 27 | #define CPP_DUMP_DEFINE_EXPORT_ENUM_GENERIC(...) \ 28 | namespace cpp_dump { \ 29 | \ 30 | namespace _detail { \ 31 | \ 32 | template \ 33 | inline auto \ 34 | export_enum_generic(T value, const std::string &, std::size_t, std::size_t, bool, const export_command &) \ 35 | -> std::enable_if_t< \ 36 | std::is_enum_v, \ 37 | decltype(_p_CPP_DUMP_EXPAND_VA(_p_CPP_DUMP_EXPAND_FOR_EXPORT_ENUM_GENERIC, __VA_ARGS__), std::string())> { \ 38 | static const std::map enum_to_string{ \ 39 | _p_CPP_DUMP_EXPAND_VA(_p_CPP_DUMP_EXPAND_FOR_EXPORT_ENUM_GENERIC2, __VA_ARGS__)}; \ 40 | return es::class_name(get_typename()) + es::op("::") \ 41 | + (enum_to_string.count(value) ? es::member(enum_to_string.at(value)) \ 42 | : es::unsupported("?")); \ 43 | } \ 44 | \ 45 | } /* namespace _detail */ \ 46 | \ 47 | } // namespace cpp_dump 48 | -------------------------------------------------------------------------------- /cpp-dump/hpp/export_var/export_exception.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Ryota Sasaki. 3 | * 4 | * This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | 13 | #include "../escape_sequence.hpp" 14 | #include "../export_command/export_command.hpp" 15 | #include "../type_check.hpp" 16 | #include "./export_object_common.hpp" 17 | 18 | namespace cpp_dump { 19 | 20 | namespace _detail { 21 | 22 | template 23 | inline auto export_exception( 24 | const T &exception, 25 | const std::string &indent, 26 | std::size_t last_line_length, 27 | std::size_t current_depth, 28 | bool fail_on_newline, 29 | const export_command &command 30 | ) -> std::enable_if_t, std::string> { 31 | std::string class_name = es::class_name(get_typename()); 32 | 33 | _p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON1; 34 | 35 | append_output("what()", exception.what()); 36 | 37 | _p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON2; 38 | } 39 | 40 | } // namespace _detail 41 | 42 | } // namespace cpp_dump 43 | -------------------------------------------------------------------------------- /cpp-dump/hpp/export_var/export_object.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Ryota Sasaki. 3 | * 4 | * This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | #include "../escape_sequence.hpp" 13 | #include "../expand_va_macro.hpp" 14 | #include "../export_command/export_command.hpp" 15 | #include "../type_check.hpp" 16 | #include "./export_object_common.hpp" 17 | 18 | #define _p_CPP_DUMP_EXPAND_FOR_EXPORT_OBJECT(member) append_output(#member, value.member) 19 | 20 | /** 21 | * Make cpp_dump::export_var() support type TYPE. 22 | * Member functions to be displayed must be const. 23 | */ 24 | #define CPP_DUMP_DEFINE_EXPORT_OBJECT(TYPE, ...) \ 25 | namespace cpp_dump { \ 26 | \ 27 | namespace _detail { \ 28 | \ 29 | template <> \ 30 | inline constexpr bool _is_exportable_object = true; \ 31 | \ 32 | template <> \ 33 | inline std::string export_object( \ 34 | const TYPE &value, \ 35 | const std::string &indent, \ 36 | std::size_t last_line_length, \ 37 | std::size_t current_depth, \ 38 | bool fail_on_newline, \ 39 | const export_command &command \ 40 | ) { \ 41 | std::string class_name = es::class_name(#TYPE); \ 42 | \ 43 | _p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON1; \ 44 | \ 45 | _p_CPP_DUMP_EXPAND_VA(_p_CPP_DUMP_EXPAND_FOR_EXPORT_OBJECT, __VA_ARGS__); \ 46 | \ 47 | _p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON2; \ 48 | } \ 49 | \ 50 | } /* namespace _detail */ \ 51 | \ 52 | } // namespace cpp_dump 53 | 54 | namespace cpp_dump { 55 | 56 | namespace _detail { 57 | 58 | template 59 | inline std::string 60 | export_object(const T &, const std::string &, std::size_t, std::size_t, bool, const export_command &); 61 | 62 | } // namespace _detail 63 | 64 | } // namespace cpp_dump 65 | -------------------------------------------------------------------------------- /cpp-dump/hpp/export_var/export_object_common.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Ryota Sasaki. 3 | * 4 | * This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | 13 | #include "../escape_sequence.hpp" 14 | #include "../export_command/export_command.hpp" 15 | #include "../options.hpp" 16 | #include "../utility.hpp" 17 | #include "./export_var_fwd.hpp" 18 | 19 | #define _p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON1_1 \ 20 | if (current_depth >= options::max_depth) { \ 21 | return class_name + es::bracket("{ ", current_depth) + es::op("...") \ 22 | + es::bracket(" }", current_depth); \ 23 | } \ 24 | \ 25 | std::string new_indent = indent + " "; \ 26 | std::size_t next_depth = current_depth + 1; \ 27 | bool shift_indent = false; \ 28 | std::string output; \ 29 | bool is_first; 30 | 31 | #define _p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON1_2 \ 32 | auto append_output = [&](std::string_view member_name, const auto &member) -> void { \ 33 | if (is_first) { \ 34 | is_first = false; \ 35 | } else { \ 36 | output += es::op(", "); \ 37 | } \ 38 | if (shift_indent) { \ 39 | output += "\n" + new_indent + es::class_member(member_name) + es::op("= "); \ 40 | output += export_var( \ 41 | member, new_indent, get_last_line_length(output), next_depth, false, command \ 42 | ); \ 43 | } else { \ 44 | output += es::class_member(member_name) + es::op("= "); \ 45 | output += export_var( \ 46 | member, indent, last_line_length + get_length(output), next_depth, true, command \ 47 | ); \ 48 | } \ 49 | }; 50 | 51 | #define _p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON1_3 \ 52 | rollback: \ 53 | output = class_name + es::bracket("{ ", current_depth); \ 54 | is_first = true; 55 | 56 | #define _p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON1 \ 57 | _p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON1_1; \ 58 | _p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON1_2; \ 59 | _p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON1_3; 60 | 61 | #define _p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON2 \ 62 | if (!shift_indent) { \ 63 | output += es::bracket(" }", current_depth); \ 64 | if (!has_newline(output) \ 65 | && last_line_length + get_length(output) <= options::max_line_width) { \ 66 | return output; \ 67 | } \ 68 | if (fail_on_newline) { \ 69 | return "\n"; \ 70 | } \ 71 | shift_indent = true; \ 72 | goto rollback; \ 73 | } \ 74 | output += "\n" + indent + es::bracket("}", current_depth); \ 75 | \ 76 | return output; 77 | -------------------------------------------------------------------------------- /cpp-dump/hpp/export_var/export_object_generic.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Ryota Sasaki. 3 | * 4 | * This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | #include "../escape_sequence.hpp" 13 | #include "../expand_va_macro.hpp" 14 | #include "../export_command/export_command.hpp" 15 | #include "../type_check.hpp" 16 | #include "./export_object_common.hpp" 17 | 18 | #define _p_CPP_DUMP_EXPAND_FOR_EXPORT_OBJECT_GENERIC(member) value.member 19 | #define _p_CPP_DUMP_EXPAND_FOR_EXPORT_OBJECT_GENERIC2(member) append_output(#member, value.member) 20 | 21 | /** 22 | * Make cpp_dump::export_var() support every type that has the specified members. 23 | * Member functions to be displayed must be const. 24 | * Compile errors in this macro, such as ambiguous function calls, are never reported due to SFINAE. 25 | */ 26 | #define CPP_DUMP_DEFINE_EXPORT_OBJECT_GENERIC(...) \ 27 | namespace cpp_dump { \ 28 | \ 29 | namespace _detail { \ 30 | \ 31 | template \ 32 | inline auto export_object_generic( \ 33 | const T &value, \ 34 | const std::string &indent, \ 35 | std::size_t last_line_length, \ 36 | std::size_t current_depth, \ 37 | bool fail_on_newline, \ 38 | const export_command &command \ 39 | ) -> decltype(_p_CPP_DUMP_EXPAND_VA(_p_CPP_DUMP_EXPAND_FOR_EXPORT_OBJECT_GENERIC, __VA_ARGS__), std::string()) { \ 40 | std::string class_name = es::class_name(get_typename()); \ 41 | \ 42 | _p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON1; \ 43 | \ 44 | _p_CPP_DUMP_EXPAND_VA(_p_CPP_DUMP_EXPAND_FOR_EXPORT_OBJECT_GENERIC2, __VA_ARGS__); \ 45 | \ 46 | _p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON2; \ 47 | } \ 48 | \ 49 | } /* namespace _detail */ \ 50 | \ 51 | } // namespace cpp_dump 52 | 53 | /** 54 | * This is deprecated. 55 | * Use CPP_DUMP_DEFINE_EXPORT_OBJECT_GENERIC() instead. 56 | */ 57 | #define CPP_DUMP_DEFINE_DANGEROUS_EXPORT_OBJECT(...) \ 58 | _Pragma( \ 59 | "message (\"WARNING: Deprecated. Use CPP_DUMP_DEFINE_EXPORT_OBJECT_GENERIC() instead.\")" \ 60 | ) CPP_DUMP_DEFINE_EXPORT_OBJECT_GENERIC(__VA_ARGS__) 61 | -------------------------------------------------------------------------------- /cpp-dump/hpp/export_var/export_ostream.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Ryota Sasaki. 3 | * 4 | * This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "../export_command/export_command.hpp" 15 | #include "../type_check.hpp" 16 | #include "./export_unsupported.hpp" 17 | 18 | namespace cpp_dump { 19 | 20 | namespace _detail { 21 | 22 | template 23 | inline auto 24 | export_ostream(const T &value, const std::string &, std::size_t, std::size_t, bool, const export_command &) 25 | -> std::enable_if_t, std::string> { 26 | std::ostringstream ss; 27 | ss << value; 28 | std::string output = ss.str(); 29 | return output.empty() ? export_unsupported() : output; 30 | } 31 | 32 | } // namespace _detail 33 | 34 | } // namespace cpp_dump 35 | -------------------------------------------------------------------------------- /cpp-dump/hpp/export_var/export_other/export_es_value_t.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Ryota Sasaki. 3 | * 4 | * This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "../../escape_sequence.hpp" 15 | #include "../../export_command/export_command.hpp" 16 | #include "../../options.hpp" 17 | #include "../../utility.hpp" 18 | #include "../export_object_common.hpp" 19 | 20 | namespace cpp_dump { 21 | 22 | namespace _detail { 23 | 24 | namespace _export_other { 25 | 26 | inline std::string _export_es_value_vector( 27 | const std::vector &es_vec, 28 | const std::string &indent, 29 | std::size_t last_line_length, 30 | std::size_t current_depth, 31 | bool fail_on_newline, 32 | const export_command &command 33 | ) { 34 | // In case the container is empty. 35 | if (es_vec.empty()) { 36 | return es::bracket("[ ]", current_depth); 37 | } 38 | // In case the depth exceeds max_depth. 39 | if (current_depth >= options::max_depth) { 40 | return es::bracket("[ ", current_depth) + es::op("...") + es::bracket(" ]", current_depth); 41 | } 42 | 43 | // Declare variables. 44 | auto skip_cont = command.create_skip_container(es_vec); 45 | bool shift_indent = options::cont_indent_style == types::cont_indent_style_t::always; 46 | 47 | // Try printing on one line. 48 | if (!shift_indent) { 49 | std::string output = es::bracket("[ ", current_depth); 50 | bool is_first_elem = true; 51 | for (const auto &[is_ellipsis, it, index_] : skip_cont) { 52 | const std::string &es = *it; 53 | 54 | // Add comma. 55 | if (is_first_elem) { 56 | is_first_elem = false; 57 | } else { 58 | output += es::op(", "); 59 | } 60 | 61 | // If the `elem` is an ellipsis, skip it. 62 | if (is_ellipsis) { 63 | output += es::op("..."); 64 | if (last_line_length + get_length(output) + std::string_view(" ]").size() 65 | > options::max_line_width) { 66 | shift_indent = true; 67 | break; 68 | } 69 | continue; 70 | } 71 | 72 | // Add the index if needed. 73 | if (command.show_index()) { 74 | output += es::member(std::to_string(index_)) + es::op(": "); 75 | } 76 | 77 | // Add the stringified `es`. 78 | output += es::apply(es, escape_string(es)); 79 | 80 | // If the line length exceeds, stop the iteration. 81 | if (last_line_length + get_length(output) + std::string_view(" ]").size() 82 | > options::max_line_width) { 83 | shift_indent = true; 84 | break; 85 | } 86 | } 87 | 88 | if (!shift_indent) { 89 | output += es::bracket(" ]", current_depth); 90 | return output; 91 | } 92 | } 93 | 94 | // Print on multiple lines. 95 | 96 | if (fail_on_newline) { 97 | return "\n"; 98 | } 99 | 100 | // Declare variables. 101 | std::string new_indent = indent + " "; 102 | std::string output = es::bracket("[", current_depth); 103 | bool is_first_elem = true; 104 | for (const auto &[is_ellipsis, it, index_] : skip_cont) { 105 | const std::string &es = *it; 106 | 107 | // Add comma. 108 | if (is_first_elem) { 109 | is_first_elem = false; 110 | } else { 111 | output += es::op(","); 112 | } 113 | 114 | // If the `elem` is an ellipsis, skip it. 115 | if (is_ellipsis) { 116 | output += "\n" + new_indent + es::op("..."); 117 | continue; 118 | } 119 | 120 | output += "\n" + new_indent; 121 | 122 | // Add the index if needed. 123 | if (command.show_index()) { 124 | output += es::member(std::to_string(index_)) + es::op(": "); 125 | } 126 | 127 | // Add the stringified `es`. 128 | output += es::apply(es, escape_string(es)); 129 | } 130 | output += "\n" + indent + es::bracket("]", current_depth); 131 | 132 | return output; 133 | } 134 | 135 | inline std::string export_es_value_t( 136 | const types::es_value_t &esv, 137 | const std::string &indent, 138 | std::size_t last_line_length, 139 | std::size_t current_depth, 140 | bool fail_on_newline, 141 | const export_command &command 142 | ) { 143 | std::string class_name = es::class_name("cpp_dump::types::es_value_t"); 144 | 145 | _p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON1_1; 146 | 147 | auto append_output = [&](std::string_view member_name, const auto &member) -> void { 148 | if (is_first) { 149 | is_first = false; 150 | } else { 151 | output += es::op(", "); 152 | } 153 | if (shift_indent) { 154 | output += "\n" + new_indent; 155 | } 156 | if constexpr (std::is_same_v) { 157 | output += es::apply(member, std::string(member_name) + "= " + escape_string(member)); 158 | } else { 159 | output += es::member(member_name) + es::op("= "); 160 | output += _export_es_value_vector( 161 | member, new_indent, get_last_line_length(output), next_depth, false, command 162 | ); 163 | } 164 | }; 165 | 166 | _p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON1_3; 167 | 168 | append_output("log", esv.log); 169 | append_output("expression", esv.expression); 170 | append_output("reserved", esv.reserved); 171 | append_output("character", esv.character); 172 | append_output("escaped_char", esv.escaped_char); 173 | append_output("op", esv.op); 174 | append_output("identifier", esv.identifier); 175 | append_output("member", esv.member); 176 | append_output("unsupported", esv.unsupported); 177 | append_output("bracket_by_depth", esv.bracket_by_depth); 178 | append_output("class_op", esv.class_op); 179 | append_output("member_op", esv.member_op); 180 | append_output("number_op", esv.number_op); 181 | 182 | _p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON2; 183 | } 184 | 185 | } // namespace _export_other 186 | 187 | } // namespace _detail 188 | 189 | } // namespace cpp_dump 190 | -------------------------------------------------------------------------------- /cpp-dump/hpp/export_var/export_other/export_optional.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Ryota Sasaki. 3 | * 4 | * This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "../../escape_sequence.hpp" 16 | #include "../../export_command/export_command.hpp" 17 | #include "../../type_check.hpp" 18 | #include "../export_var_fwd.hpp" 19 | 20 | namespace cpp_dump { 21 | 22 | namespace _detail { 23 | 24 | namespace _export_other { 25 | 26 | inline std::string 27 | export_optional(const std::nullopt_t &, const std::string &, std::size_t, std::size_t, bool, const export_command &) { 28 | return es::class_name("std::nullopt"); 29 | } 30 | 31 | inline std::string _es_optional_question(std::string_view s) { 32 | return options::es_style == types::es_style_t::original ? es::identifier(s) : es::op(s); 33 | } 34 | 35 | template 36 | inline auto export_optional( 37 | const T &optional, 38 | const std::string &indent, 39 | std::size_t last_line_length, 40 | std::size_t current_depth, 41 | bool fail_on_newline, 42 | const export_command &command 43 | ) -> std::enable_if_t, std::string> { 44 | if (optional == std::nullopt) { 45 | return es::class_name("std::nullopt"); 46 | } 47 | return _es_optional_question("?") 48 | + export_var( 49 | optional.value(), indent, last_line_length + 1, current_depth, fail_on_newline, command 50 | ); 51 | } 52 | 53 | } // namespace _export_other 54 | 55 | } // namespace _detail 56 | 57 | } // namespace cpp_dump 58 | -------------------------------------------------------------------------------- /cpp-dump/hpp/export_var/export_other/export_other.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Ryota Sasaki. 3 | * 4 | * This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "../../escape_sequence.hpp" 17 | #include "../../export_command/export_command.hpp" 18 | #include "../../options.hpp" 19 | #include "../../type_check.hpp" 20 | #include "../export_var_fwd.hpp" 21 | #include "./export_es_value_t.hpp" 22 | #include "./export_optional.hpp" 23 | #include "./export_other_object.hpp" 24 | #include "./export_type_info.hpp" 25 | 26 | namespace cpp_dump { 27 | 28 | namespace _detail { 29 | 30 | namespace _export_other { 31 | 32 | template 33 | inline auto export_other( 34 | const T &optional, 35 | const std::string &indent, 36 | std::size_t last_line_length, 37 | std::size_t current_depth, 38 | bool fail_on_newline, 39 | const export_command &command 40 | ) -> std::enable_if_t, std::string> { 41 | return export_optional( 42 | optional, indent, last_line_length, current_depth, fail_on_newline, command 43 | ); 44 | } 45 | 46 | template 47 | inline auto export_other( 48 | const T &type_info, 49 | const std::string &indent, 50 | std::size_t last_line_length, 51 | std::size_t current_depth, 52 | bool fail_on_newline, 53 | const export_command &command 54 | ) -> std::enable_if_t, std::string> { 55 | return export_type_info( 56 | type_info, indent, last_line_length, current_depth, fail_on_newline, command 57 | ); 58 | } 59 | 60 | template 61 | inline std::string export_other( 62 | const std::reference_wrapper &ref, 63 | const std::string &indent, 64 | std::size_t last_line_length, 65 | std::size_t current_depth, 66 | bool fail_on_newline, 67 | const export_command &command 68 | ) { 69 | return export_var(ref.get(), indent, last_line_length, current_depth, fail_on_newline, command); 70 | } 71 | 72 | inline std::string _es_bitset(std::string_view s) { 73 | return options::es_style == types::es_style_t::original ? es::identifier(s) : es::number(s); 74 | } 75 | 76 | template 77 | inline std::string 78 | export_other(const std::bitset &bitset, const std::string &, std::size_t, std::size_t, bool, const export_command &) { 79 | constexpr unsigned int chunk = 4; 80 | 81 | std::string bitset_str = bitset.to_string(); 82 | std::string output; 83 | output.reserve(3 + N + (N - 1) / chunk); 84 | output.append("0b "); 85 | 86 | std::size_t pos = bitset_str.length() % chunk; 87 | if (pos > 0) output.append(bitset_str, 0, pos); 88 | for (; pos < bitset_str.length(); pos += chunk) { 89 | if (pos > 0) output.push_back(' '); 90 | output.append(bitset_str, pos, chunk); 91 | } 92 | return _es_bitset(output); 93 | } 94 | 95 | inline std::string _es_complex_complex(std::string_view s) { 96 | return options::es_style == types::es_style_t::original ? es::identifier(s) 97 | : es::signed_number(s); 98 | } 99 | 100 | template 101 | inline std::string export_other( 102 | const std::complex &complex, 103 | const std::string &, 104 | std::size_t, 105 | std::size_t current_depth, 106 | bool, 107 | const export_command &command 108 | ) { 109 | constexpr T pi = static_cast(3.141592653589793238462643383279502884L); 110 | auto to_str = [&](T value) -> std::string { 111 | std::string output = command.format(value); 112 | if (output.empty()) { 113 | return std::to_string(value); 114 | } 115 | return output; 116 | }; 117 | auto imag = std::imag(complex); 118 | auto imag_sign = imag >= 0 ? "+" : "-"; 119 | 120 | return _es_complex_complex( 121 | to_str(std::real(complex)) + " " + imag_sign + " " + to_str(std::abs(imag)) + "i " 122 | ) 123 | + es::bracket("( ", current_depth) + es::member("abs") + es::op("= ") 124 | + es::signed_number(to_str(std::abs(complex))) + es::op(", ") + es::class_member("arg/pi") 125 | + es::op("= ") + es::signed_number(to_str(std::arg(complex) / pi)) 126 | + es::bracket(" )", current_depth); 127 | } 128 | 129 | inline std::string _es_variant_bar(std::string_view s) { 130 | return options::es_style == types::es_style_t::original ? es::identifier(s) : es::op(s); 131 | } 132 | 133 | template 134 | inline std::string export_other( 135 | const std::variant &variant, 136 | const std::string &indent, 137 | std::size_t last_line_length, 138 | std::size_t current_depth, 139 | bool fail_on_newline, 140 | const export_command &command 141 | ) { 142 | return std::visit( 143 | [=, &indent, &command](const auto &value) -> std::string { 144 | return _es_variant_bar("|") 145 | + export_var( 146 | value, indent, last_line_length + 1, current_depth, fail_on_newline, command 147 | ); 148 | }, 149 | variant 150 | ); 151 | } 152 | 153 | inline std::string export_other( 154 | const types::es_value_t &esv, 155 | const std::string &indent, 156 | std::size_t last_line_length, 157 | std::size_t current_depth, 158 | bool fail_on_newline, 159 | const export_command &command 160 | ) { 161 | return export_es_value_t(esv, indent, last_line_length, current_depth, fail_on_newline, command); 162 | } 163 | 164 | template 165 | inline auto export_other( 166 | const T &value, 167 | const std::string &indent, 168 | std::size_t last_line_length, 169 | std::size_t current_depth, 170 | bool fail_on_newline, 171 | const export_command &command 172 | ) -> std::enable_if_t, std::string> { 173 | return export_other_object( 174 | value, indent, last_line_length, current_depth, fail_on_newline, command 175 | ); 176 | } 177 | 178 | } // namespace _export_other 179 | 180 | using _export_other::export_other; 181 | 182 | } // namespace _detail 183 | 184 | } // namespace cpp_dump 185 | -------------------------------------------------------------------------------- /cpp-dump/hpp/export_var/export_other/export_other_object.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Ryota Sasaki. 3 | * 4 | * This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | #if __cplusplus >= 202002L 13 | 14 | #if !defined(__clang__) 15 | #include 16 | #endif 17 | 18 | #endif 19 | 20 | #include "../../escape_sequence.hpp" 21 | #include "../../expand_va_macro.hpp" 22 | #include "../../export_command/export_command.hpp" 23 | #include "../../type_check.hpp" 24 | #include "../export_object_common.hpp" 25 | 26 | #define _p_CPP_DUMP_EXPAND_FOR_EXPORT_OTHER_OBJECT(member) append_output(#member, value.member) 27 | 28 | #define _p_CPP_DUMP_DEFINE_EXPORT_OTHER_OBJECT(TYPE, ...) \ 29 | namespace cpp_dump { \ 30 | \ 31 | namespace _detail { \ 32 | \ 33 | template <> \ 34 | inline constexpr bool _is_other_object = true; \ 35 | \ 36 | namespace _export_other { \ 37 | \ 38 | template <> \ 39 | inline std::string export_other_object( \ 40 | const TYPE &value, \ 41 | const std::string &indent, \ 42 | std::size_t last_line_length, \ 43 | std::size_t current_depth, \ 44 | bool fail_on_newline, \ 45 | const export_command &command \ 46 | ) { \ 47 | std::string class_name = es::class_name(#TYPE); \ 48 | \ 49 | _p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON1; \ 50 | \ 51 | _p_CPP_DUMP_EXPAND_VA(_p_CPP_DUMP_EXPAND_FOR_EXPORT_OTHER_OBJECT, __VA_ARGS__); \ 52 | \ 53 | _p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON2; \ 54 | } \ 55 | \ 56 | } /* namespace _export_other */ \ 57 | \ 58 | } /* namespace _detail */ \ 59 | \ 60 | } // namespace cpp_dump 61 | 62 | namespace cpp_dump { 63 | 64 | namespace _detail { 65 | 66 | namespace _export_other { 67 | 68 | template 69 | inline std::string 70 | export_other_object(const T &, const std::string &, std::size_t, std::size_t, bool, const export_command &); 71 | 72 | } // namespace _export_other 73 | 74 | } // namespace _detail 75 | 76 | } // namespace cpp_dump 77 | 78 | // By not using CPP_DUMP_DEFINE_EXPORT_OBJECT() here, users can use CPP_DUMP_DEFINE_EXPORT_OBJECT() 79 | // to overwrite cpp_dump::export_var() 80 | #if __cplusplus >= 202002L 81 | 82 | #if !defined(__clang__) 83 | _p_CPP_DUMP_DEFINE_EXPORT_OTHER_OBJECT( 84 | std::source_location, file_name(), line(), column(), function_name() 85 | ); 86 | #endif 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /cpp-dump/hpp/export_var/export_other/export_type_info.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Ryota Sasaki. 3 | * 4 | * This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #if defined(__GNUC__) 15 | #include 16 | #endif 17 | 18 | #include "../../export_command/export_command.hpp" 19 | #include "../export_object_common.hpp" 20 | 21 | namespace cpp_dump { 22 | 23 | namespace _detail { 24 | 25 | namespace _export_other { 26 | 27 | template 28 | inline auto export_type_info( 29 | const T &type_info, 30 | const std::string &indent, 31 | std::size_t last_line_length, 32 | std::size_t current_depth, 33 | bool fail_on_newline, 34 | const export_command &command 35 | ) -> std::enable_if_t, std::string> { 36 | std::string class_name = 37 | es::class_name(std::is_same_v ? "std::type_info" : "std::type_index"); 38 | 39 | #if defined(__GNUC__) 40 | int status = 0; 41 | std::string name = abi::__cxa_demangle(type_info.name(), 0, 0, &status); 42 | #else 43 | std::string name = type_info.name(); 44 | #endif 45 | 46 | _p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON1; 47 | 48 | if (shift_indent) { 49 | output += "\n" + new_indent; 50 | } 51 | 52 | output += es::class_member("name()") + es::op("= "); 53 | output += es::class_op(R"(")") + es::type_name(name) + es::class_op(R"(")"); 54 | 55 | is_first = false; 56 | append_output("hash_code()", type_info.hash_code()); 57 | 58 | _p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON2; 59 | } 60 | 61 | } // namespace _export_other 62 | 63 | } // namespace _detail 64 | 65 | } // namespace cpp_dump 66 | -------------------------------------------------------------------------------- /cpp-dump/hpp/export_var/export_pointer.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Ryota Sasaki. 3 | * 4 | * This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "../escape_sequence.hpp" 16 | #include "../export_command/export_command.hpp" 17 | #include "../options.hpp" 18 | #include "../type_check.hpp" 19 | #include "./export_unsupported.hpp" 20 | #include "./export_var_fwd.hpp" 21 | 22 | namespace cpp_dump { 23 | 24 | namespace _detail { 25 | 26 | namespace _export_pointer { 27 | 28 | inline std::string _es_ptr_asterisk(std::string_view s) { 29 | return options::es_style == types::es_style_t::original ? es::identifier(s) : es::op(s); 30 | } 31 | 32 | inline std::string _es_raw_address(std::string_view s) { 33 | return options::es_style == types::es_style_t::original ? es::identifier(s) : es::number(s); 34 | } 35 | 36 | template 37 | inline auto export_pointer( 38 | const T &pointer, 39 | [[maybe_unused]] const std::string &indent, 40 | [[maybe_unused]] std::size_t last_line_length, 41 | [[maybe_unused]] std::size_t current_depth, 42 | [[maybe_unused]] bool fail_on_newline, 43 | [[maybe_unused]] const export_command &command 44 | ) -> std::enable_if_t, std::string> { 45 | if (pointer == nullptr) { 46 | return es::reserved("nullptr"); 47 | } 48 | // If the pointer is not exportable, export the address. 49 | if constexpr (is_null_pointer || !is_exportable>) { 50 | if constexpr (std::is_function_v>) { 51 | return export_unsupported(); 52 | } else { 53 | std::ostringstream ss; 54 | ss << std::hex << static_cast(pointer); 55 | 56 | // Make the entire string an identifier 57 | return _es_raw_address(ss.str()); 58 | } 59 | } else { 60 | // If the depth exceeds addr_depth, export the address. 61 | if (current_depth >= command.addr_depth()) { 62 | std::ostringstream ss; 63 | if constexpr (is_smart_pointer) { 64 | ss << std::hex << static_cast(pointer.get()); 65 | } else { 66 | ss << std::hex << static_cast(pointer); 67 | } 68 | 69 | // Make the entire string an identifier 70 | return _es_raw_address(ss.str()); 71 | } 72 | // In case the depth exceeds `max_depth`. 73 | if (current_depth >= options::max_depth) { 74 | return _es_ptr_asterisk("*") + es::op("..."); 75 | } 76 | // Export *value. 77 | return _es_ptr_asterisk("*") 78 | + export_var( 79 | *pointer, indent, last_line_length + 1, current_depth + 1, fail_on_newline, command 80 | ); 81 | } 82 | } 83 | 84 | template 85 | inline std::string export_pointer( 86 | const std::weak_ptr &wk_ptr, 87 | const std::string &indent, 88 | std::size_t last_line_length, 89 | std::size_t current_depth, 90 | bool fail_on_newline, 91 | const export_command &command 92 | ) { 93 | return export_pointer( 94 | wk_ptr.lock(), indent, last_line_length, current_depth, fail_on_newline, command 95 | ); 96 | } 97 | 98 | } // namespace _export_pointer 99 | 100 | using _export_pointer::export_pointer; 101 | 102 | } // namespace _detail 103 | 104 | } // namespace cpp_dump 105 | -------------------------------------------------------------------------------- /cpp-dump/hpp/export_var/export_set.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Ryota Sasaki. 3 | * 4 | * This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "../escape_sequence.hpp" 15 | #include "../export_command/export_command.hpp" 16 | #include "../options.hpp" 17 | #include "../type_check.hpp" 18 | #include "../utility.hpp" 19 | #include "./export_var_fwd.hpp" 20 | 21 | namespace cpp_dump { 22 | 23 | namespace _detail { 24 | 25 | namespace _export_set { 26 | 27 | template 28 | struct _set_dummy_wrapper { 29 | public: 30 | explicit _set_dummy_wrapper(const T &set) : _set(set) {} 31 | 32 | auto begin() const noexcept { return _set.begin(); } 33 | auto end() const noexcept { return _set.end(); } 34 | auto size() const noexcept { return _set.size(); } 35 | 36 | private: 37 | const T &_set; 38 | }; 39 | 40 | template 41 | struct _multiset_wrapper { 42 | public: 43 | explicit _multiset_wrapper(const T &set) : _set(set) {} 44 | 45 | auto begin() const noexcept { return multiset_wrapper_iterator(_set, _set.begin()); } 46 | auto end() const noexcept { return multiset_wrapper_iterator(_set, _set.end()); } 47 | 48 | private: 49 | struct multiset_wrapper_iterator { 50 | public: 51 | using It = typename T::const_iterator; 52 | multiset_wrapper_iterator(const T &set, It it) : _set(set), _it(it) {} 53 | 54 | const auto &operator*() const noexcept { return *_it; } 55 | bool operator!=(const multiset_wrapper_iterator &to) const noexcept { return _it != to._it; } 56 | multiset_wrapper_iterator &operator++() { 57 | _it = _set.equal_range(*_it).second; 58 | return *this; 59 | } 60 | 61 | private: 62 | const T &_set; 63 | It _it; 64 | }; 65 | 66 | const T &_set; 67 | }; 68 | 69 | template 70 | inline auto export_set( 71 | const T &set, 72 | const std::string &indent, 73 | std::size_t last_line_length, 74 | std::size_t current_depth, 75 | bool fail_on_newline, 76 | const export_command &command 77 | ) -> std::enable_if_t, std::string> { 78 | // In case the container is empty. 79 | if (set.empty()) { 80 | return es::bracket("{ }", current_depth); 81 | } 82 | // In case the depth exceeds max_depth. 83 | if (current_depth >= options::max_depth) { 84 | return es::bracket("{ ", current_depth) + es::op("...") + es::bracket(" }", current_depth); 85 | } 86 | 87 | // Declare variables. 88 | std::size_t next_depth = current_depth + 1; 89 | const auto &next_command = command.next(); 90 | auto set_wrapper = ([&]() { 91 | if constexpr (is_multiset) { 92 | return _multiset_wrapper(set); 93 | } else { 94 | // The wrapper is to avoid calling the copy constructor. 95 | return _set_dummy_wrapper(set); 96 | } 97 | })(); 98 | auto skipped_set = command.create_skip_container(set_wrapper); 99 | bool shift_indent = false; 100 | if (options::cont_indent_style == types::cont_indent_style_t::always) { 101 | shift_indent = true; 102 | } else if (options::cont_indent_style == types::cont_indent_style_t::when_nested) { 103 | shift_indent = is_iterable_like>; 104 | } else if (options::cont_indent_style == types::cont_indent_style_t::when_non_tuples_nested) { 105 | shift_indent = is_iterable_like> && !is_tuple>; 106 | } 107 | 108 | // Try printing on one line. 109 | if (!shift_indent) { 110 | std::string output = es::bracket("{ ", current_depth); 111 | bool is_first_elem = true; 112 | for (const auto &[is_ellipsis, it, _index] : skipped_set) { 113 | [[maybe_unused]] const auto &_index_unused = _index; // for g++-7 compiler support 114 | const auto &elem = *it; 115 | 116 | // Add comma. 117 | if (is_first_elem) { 118 | is_first_elem = false; 119 | } else { 120 | output += es::op(", "); 121 | } 122 | 123 | // If the `elem` is an ellipsis, skip it. 124 | if (is_ellipsis) { 125 | output += es::op("..."); 126 | if (last_line_length + get_length(output) + std::string_view(" }").size() 127 | > options::max_line_width) { 128 | shift_indent = true; 129 | break; 130 | } 131 | continue; 132 | } 133 | 134 | // Add the stringified `elem`. 135 | std::string elem_str = export_var( 136 | elem, indent, last_line_length + get_length(output), next_depth, true, next_command 137 | ); 138 | if constexpr (is_multiset) { 139 | // Treat the multiplicity as a member as export_map() does. 140 | elem_str += es::member(" (" + std::to_string(set.count(elem)) + ")"); 141 | } 142 | if (has_newline(elem_str)) { 143 | shift_indent = true; 144 | break; 145 | } 146 | output += elem_str; 147 | 148 | // If the line length exceeds, stop the iteration. 149 | if (last_line_length + get_length(output) + std::string_view(" }").size() 150 | > options::max_line_width) { 151 | shift_indent = true; 152 | break; 153 | } 154 | } 155 | 156 | if (!shift_indent) { 157 | output += es::bracket(" }", current_depth); 158 | return output; 159 | } 160 | } 161 | 162 | // Print on multiple lines. 163 | 164 | if (fail_on_newline) { 165 | return "\n"; 166 | } 167 | 168 | // Declare variables. 169 | std::string new_indent = indent + " "; 170 | std::string output = es::bracket("{", current_depth); 171 | bool is_first_elem = true; 172 | 173 | for (const auto &[is_ellipsis, it, _index] : skipped_set) { 174 | [[maybe_unused]] const auto &_index_unused = _index; // for g++-7 compiler support 175 | const auto &elem = *it; 176 | 177 | // Add comma. 178 | if (is_first_elem) { 179 | is_first_elem = false; 180 | } else { 181 | output += es::op(","); 182 | } 183 | 184 | // If the `elem` is an ellipsis, skip it. 185 | if (is_ellipsis) { 186 | output += "\n" + new_indent + es::op("..."); 187 | continue; 188 | } 189 | 190 | // Add the stringified `elem`. 191 | output += "\n" + new_indent 192 | + export_var(elem, new_indent, new_indent.length(), next_depth, false, next_command); 193 | if constexpr (is_multiset) { 194 | // Treat the multiplicity as a member as export_map() does. 195 | output += es::member(" (" + std::to_string(set.count(elem)) + ")"); 196 | } 197 | } 198 | output += "\n" + indent + es::bracket("}", current_depth); 199 | 200 | return output; 201 | } 202 | 203 | } // namespace _export_set 204 | 205 | using _export_set::export_set; 206 | 207 | } // namespace _detail 208 | 209 | } // namespace cpp_dump 210 | -------------------------------------------------------------------------------- /cpp-dump/hpp/export_var/export_string.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Ryota Sasaki. 3 | * 4 | * This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | 13 | #include "../escape_sequence.hpp" 14 | #include "../export_command/export_command.hpp" 15 | #include "../type_check.hpp" 16 | #include "../utility.hpp" 17 | 18 | namespace cpp_dump { 19 | 20 | namespace _detail { 21 | 22 | inline std::string export_string( 23 | std::string_view value, 24 | const std::string &, 25 | std::size_t, 26 | std::size_t, 27 | bool fail_on_newline, 28 | const export_command &command 29 | ) { 30 | // Escape and export if needed. 31 | if (command.escape_str()) { 32 | return es::escaped_str(escape_string(value)); 33 | } 34 | 35 | // str = replace_string(str, R"(\)", R"(\\)"); 36 | // str = replace_string(str, R"(`)", R"(\`)"); 37 | 38 | // If the value has a line break, wrap the value with ` 39 | if (has_newline(value)) { 40 | if (fail_on_newline) { 41 | return "\n"; 42 | } 43 | return "\n" + es::character(std::string(1, '`').append(value)) + es::character("`"); 44 | } 45 | 46 | // Wrap the value with " or ' 47 | if (value.find('"') == std::string::npos) { 48 | return es::character(std::string(1, '"').append(value)) + es::character("\""); 49 | } 50 | return es::character(std::string(1, '`').append(value)) + es::character("`"); 51 | } 52 | 53 | } // namespace _detail 54 | 55 | } // namespace cpp_dump 56 | -------------------------------------------------------------------------------- /cpp-dump/hpp/export_var/export_tuple.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Ryota Sasaki. 3 | * 4 | * This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "../escape_sequence.hpp" 15 | #include "../export_command/export_command.hpp" 16 | #include "../options.hpp" 17 | #include "../type_check.hpp" 18 | #include "../utility.hpp" 19 | #include "./export_var_fwd.hpp" 20 | 21 | namespace cpp_dump { 22 | 23 | namespace _detail { 24 | 25 | namespace _export_tuple { 26 | 27 | template 28 | inline auto get(const T &tuple, int) -> decltype(tuple.template get()) { 29 | return tuple.template get(); 30 | } 31 | 32 | template 33 | inline auto get(const T &tuple, long) -> decltype(get(tuple)) { 34 | return get(tuple); 35 | } 36 | 37 | template 38 | inline auto _export_tuple_in_one_line( 39 | const T &tuple, 40 | const std::string &indent, 41 | std::size_t last_line_length, 42 | std::size_t next_depth, 43 | const export_command &command 44 | ) -> std::enable_if_t, std::string> { 45 | std::string output = export_var( 46 | _export_tuple::get(tuple, 0), indent, last_line_length, next_depth, true, command 47 | ); 48 | if (has_newline(output)) { 49 | return "\n"; 50 | } 51 | 52 | if constexpr (i < size - 1) { 53 | return output + es::op(", ") 54 | + _export_tuple_in_one_line( 55 | tuple, indent, get_length(output) + 2, next_depth, command 56 | ); 57 | } else { 58 | return output; 59 | } 60 | } 61 | 62 | template 63 | inline auto _export_tuple_in_lines( 64 | const T &tuple, const std::string &indent, std::size_t next_depth, const export_command &command 65 | ) -> std::enable_if_t, std::string> { 66 | std::string output = export_var( 67 | _export_tuple::get(tuple, 0), indent, get_length(indent), next_depth, false, command 68 | ); 69 | 70 | if constexpr (i < size - 1) { 71 | return output + es::op(",\n") + indent 72 | + _export_tuple_in_lines(tuple, indent, next_depth, command); 73 | } else { 74 | return output; 75 | } 76 | } 77 | 78 | template 79 | inline auto export_tuple( 80 | const T &tuple, 81 | const std::string &indent, 82 | std::size_t last_line_length, 83 | std::size_t current_depth, 84 | bool fail_on_newline, 85 | const export_command &command 86 | ) -> std::enable_if_t, std::string> { 87 | constexpr std::size_t tuple_size = std::tuple_size_v; 88 | 89 | if constexpr (tuple_size == 0) { 90 | return es::bracket("( )", current_depth); 91 | } else { 92 | if (current_depth >= options::max_depth) { 93 | return es::bracket("( ", current_depth) + es::op("...") + es::bracket(" )", current_depth); 94 | } 95 | 96 | // Try exporting on one line. 97 | std::size_t next_depth = current_depth + 1; 98 | std::string output = es::bracket("( ", current_depth) 99 | + _export_tuple_in_one_line<0, tuple_size>( 100 | tuple, indent, last_line_length + 2, next_depth, command 101 | ) 102 | + es::bracket(" )", current_depth); 103 | if (!has_newline(output) && last_line_length + get_length(output) <= options::max_line_width) { 104 | return output; 105 | } 106 | 107 | if (fail_on_newline) { 108 | return "\n"; 109 | } 110 | 111 | // Try exporting on multiple lines. 112 | std::string new_indent = indent + " "; 113 | return es::bracket("(\n", current_depth) + new_indent 114 | + _export_tuple_in_lines<0, tuple_size>(tuple, new_indent, next_depth, command) + "\n" 115 | + indent + es::bracket(")", current_depth); 116 | } 117 | } 118 | 119 | } // namespace _export_tuple 120 | 121 | using _export_tuple::export_tuple; 122 | 123 | } // namespace _detail 124 | 125 | } // namespace cpp_dump 126 | -------------------------------------------------------------------------------- /cpp-dump/hpp/export_var/export_unsupported.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Ryota Sasaki. 3 | * 4 | * This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | #include "../escape_sequence.hpp" 13 | 14 | namespace cpp_dump { 15 | 16 | namespace _detail { 17 | 18 | inline std::string export_unsupported() { return es::unsupported("Unsupported Type"); } 19 | 20 | } // namespace _detail 21 | 22 | } // namespace cpp_dump 23 | -------------------------------------------------------------------------------- /cpp-dump/hpp/export_var/export_var.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Ryota Sasaki. 3 | * 4 | * This source code is licensed under the MIT license found in the LICENSE file 5 | * in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | #include "../export_command/export_command.hpp" 13 | #include "../type_check.hpp" 14 | #include "./export_arithmetic.hpp" 15 | #include "./export_asterisk.hpp" 16 | #include "./export_container.hpp" 17 | #include "./export_enum.hpp" 18 | #include "./export_enum_generic.hpp" // for including macro 19 | #include "./export_exception.hpp" 20 | #include "./export_map.hpp" 21 | #include "./export_object.hpp" 22 | #include "./export_object_generic.hpp" // for including macro 23 | #include "./export_ostream.hpp" 24 | #include "./export_other/export_other.hpp" 25 | #include "./export_pointer.hpp" 26 | #include "./export_set.hpp" 27 | #include "./export_string.hpp" 28 | #include "./export_tuple.hpp" 29 | #include "./export_unsupported.hpp" 30 | #include "./export_xixo.hpp" 31 | 32 | namespace cpp_dump { 33 | 34 | namespace _detail { 35 | 36 | // This is the real implementation of export_var(). 37 | // This calls itself recursively. 38 | template 39 | std::string export_var( 40 | [[maybe_unused]] const T &value, 41 | [[maybe_unused]] const std::string &indent, 42 | [[maybe_unused]] std::size_t last_line_length, 43 | [[maybe_unused]] std::size_t current_depth, 44 | [[maybe_unused]] bool fail_on_newline, 45 | [[maybe_unused]] const export_command &command 46 | ) { 47 | if constexpr (is_value_with_command) { 48 | return export_var( 49 | value.value, indent, last_line_length, current_depth, fail_on_newline, value.command 50 | ); 51 | } else if constexpr (is_exportable_object) { 52 | return export_object(value, indent, last_line_length, current_depth, fail_on_newline, command); 53 | } else if constexpr (is_exportable_enum) { 54 | return export_enum(value, indent, last_line_length, current_depth, fail_on_newline, command); 55 | } else if constexpr (is_arithmetic) { 56 | return export_arithmetic( 57 | value, indent, last_line_length, current_depth, fail_on_newline, command 58 | ); 59 | } else if constexpr (is_string) { 60 | return export_string(value, indent, last_line_length, current_depth, fail_on_newline, command); 61 | } else if constexpr (is_map) { 62 | return export_map(value, indent, last_line_length, current_depth, fail_on_newline, command); 63 | } else if constexpr (is_set) { 64 | return export_set(value, indent, last_line_length, current_depth, fail_on_newline, command); 65 | } else if constexpr (is_container) { 66 | return export_container( 67 | value, indent, last_line_length, current_depth, fail_on_newline, command 68 | ); 69 | } else if constexpr (is_tuple) { 70 | return export_tuple(value, indent, last_line_length, current_depth, fail_on_newline, command); 71 | } else if constexpr (is_xixo) { 72 | return export_xixo(value, indent, last_line_length, current_depth, fail_on_newline, command); 73 | } else if constexpr (is_pointer) { 74 | return export_pointer(value, indent, last_line_length, current_depth, fail_on_newline, command); 75 | } else if constexpr (is_exception) { 76 | return export_exception( 77 | value, indent, last_line_length, current_depth, fail_on_newline, command 78 | ); 79 | } else if constexpr (is_other_type) { 80 | return export_other(value, indent, last_line_length, current_depth, fail_on_newline, command); 81 | } else if constexpr (is_exportable_object_generic) { 82 | return export_object_generic( 83 | value, indent, last_line_length, current_depth, fail_on_newline, command 84 | ); 85 | } else if constexpr (is_exportable_enum_generic) { 86 | return export_enum_generic( 87 | value, indent, last_line_length, current_depth, fail_on_newline, command 88 | ); 89 | } else if constexpr (is_ostream) { 90 | return export_ostream(value, indent, last_line_length, current_depth, fail_on_newline, command); 91 | } else if constexpr (is_asterisk) { 92 | return export_asterisk( 93 | value, indent, last_line_length, current_depth, fail_on_newline, command 94 | ); 95 | } else { 96 | static_assert(!is_exportable, "is_exportable has a bug! This should not be showed."); 97 | return export_unsupported(); 98 | } 99 | } 100 | 101 | } // namespace _detail 102 | 103 | /** 104 | * Return a string representation of a variable. 105 | */ 106 | template 107 | std::string export_var(const T &value) { 108 | return _detail::export_var(value, "", 0, 0, false, _detail::export_command::default_command); 109 | } 110 | 111 | } // namespace cpp_dump 112 | -------------------------------------------------------------------------------- /cpp-dump/hpp/export_var/export_var_fwd.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Ryota Sasaki. 3 | * 4 | * This source code is licensed under the MIT license found in the LICENSE file 5 | * in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | #include "../export_command/export_command.hpp" 13 | 14 | namespace cpp_dump { 15 | 16 | namespace _detail { 17 | 18 | template 19 | std::string 20 | export_var(const T &, const std::string &, std::size_t, std::size_t, bool, const export_command &); 21 | 22 | } // namespace _detail 23 | 24 | } // namespace cpp_dump 25 | -------------------------------------------------------------------------------- /cpp-dump/hpp/export_var/export_xixo.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Ryota Sasaki. 3 | * 4 | * This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "../escape_sequence.hpp" 15 | #include "../export_command/export_command.hpp" 16 | #include "./export_object_common.hpp" 17 | 18 | namespace cpp_dump { 19 | 20 | namespace _detail { 21 | 22 | template 23 | inline std::string export_xixo( 24 | const std::queue &queue, 25 | const std::string &indent, 26 | std::size_t last_line_length, 27 | std::size_t current_depth, 28 | bool fail_on_newline, 29 | const export_command &command 30 | ) { 31 | std::string class_name = es::class_name("std::queue"); 32 | 33 | _p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON1; 34 | 35 | append_output("size()", queue.size()); 36 | if (!queue.empty()) { 37 | append_output("front()", queue.front()); 38 | if (queue.size() >= 2) { 39 | append_output("back()", queue.back()); 40 | } 41 | } 42 | 43 | _p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON2; 44 | } 45 | 46 | template 47 | inline std::string export_xixo( 48 | const std::priority_queue &pq, 49 | const std::string &indent, 50 | std::size_t last_line_length, 51 | std::size_t current_depth, 52 | bool fail_on_newline, 53 | const export_command &command 54 | ) { 55 | std::string class_name = es::class_name("std::priority_queue"); 56 | 57 | _p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON1; 58 | 59 | append_output("size()", pq.size()); 60 | if (!pq.empty()) { 61 | append_output("top()", pq.top()); 62 | } 63 | 64 | _p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON2; 65 | } 66 | 67 | template 68 | inline std::string export_xixo( 69 | const std::stack &stack, 70 | const std::string &indent, 71 | std::size_t last_line_length, 72 | std::size_t current_depth, 73 | bool fail_on_newline, 74 | const export_command &command 75 | ) { 76 | std::string class_name = es::class_name("std::stack"); 77 | 78 | _p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON1; 79 | 80 | append_output("size()", stack.size()); 81 | if (!stack.empty()) { 82 | append_output("top()", stack.top()); 83 | } 84 | 85 | _p_CPP_DUMP_DEFINE_EXPORT_OBJECT_COMMON2; 86 | } 87 | 88 | } // namespace _detail 89 | 90 | } // namespace cpp_dump 91 | -------------------------------------------------------------------------------- /cpp-dump/hpp/iterable.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Ryota Sasaki. 3 | * 4 | * This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | namespace cpp_dump { 13 | 14 | namespace _detail { 15 | 16 | template 17 | inline auto _iterable_begin(const T &t, int) -> decltype(begin(t)) { 18 | return begin(t); 19 | } 20 | 21 | template 22 | inline auto _iterable_begin(const T &t, long) -> decltype(std::begin(t)) { 23 | return std::begin(t); 24 | } 25 | 26 | template 27 | inline auto iterable_begin(const T &t) -> decltype(_iterable_begin(t, 0)) { 28 | return _iterable_begin(t, 0); 29 | } 30 | 31 | template 32 | inline auto _iterable_end(const T &t, int) -> decltype(end(t)) { 33 | return end(t); 34 | } 35 | 36 | template 37 | inline auto _iterable_end(const T &t, long) -> decltype(std::end(t)) { 38 | return std::end(t); 39 | } 40 | 41 | template 42 | inline auto iterable_end(const T &t) -> decltype(_iterable_end(t, 0)) { 43 | return _iterable_end(t, 0); 44 | } 45 | 46 | template 47 | inline bool is_empty_iterable(const T &t) { 48 | return !(iterable_begin(t) != iterable_end(t)); 49 | } 50 | 51 | template 52 | inline auto _iterable_size(const T &t, int, int) -> decltype(size(t)) { 53 | return std::size(t); 54 | } 55 | 56 | template 57 | inline auto _iterable_size(const T &t, int, long) -> decltype(std::size(t)) { 58 | return std::size(t); 59 | } 60 | 61 | template 62 | inline auto _iterable_size(const T &t, long, long) 63 | -> decltype(std::distance(iterable_begin(t), iterable_end(t))) { 64 | return std::distance(iterable_begin(t), iterable_end(t)); 65 | } 66 | 67 | template 68 | inline std::size_t _iterable_size(const T &t, ...) { 69 | std::size_t size = 0; 70 | // allow lvalue iterator 71 | auto &&begin = iterable_begin(t); 72 | auto &&end = iterable_end(t); 73 | for (; begin != end; ++begin) ++size; 74 | return size; 75 | } 76 | 77 | template 78 | inline std::size_t iterable_size(const T &t) { 79 | return _iterable_size(t, 0, 0); 80 | } 81 | 82 | template ::difference_type> 83 | inline void _iterator_advance(It &it, std::size_t n, int) { 84 | std::advance(it, n); 85 | } 86 | 87 | template 88 | inline void _iterator_advance(It &it, std::size_t n, long) { 89 | for (; n > 0; --n) ++it; 90 | } 91 | 92 | template 93 | inline void iterator_advance(It &it, std::size_t n) { 94 | _iterator_advance(it, n, 0); 95 | } 96 | 97 | } // namespace _detail 98 | 99 | } // namespace cpp_dump 100 | -------------------------------------------------------------------------------- /cpp-dump/hpp/log_label.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Ryota Sasaki. 3 | * 4 | * This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | namespace cpp_dump { 16 | 17 | namespace types { 18 | 19 | /** 20 | * Type of cpp_dump::options::log_label_func. 21 | */ 22 | using log_label_func_t = 23 | std::function; 24 | 25 | } // namespace types 26 | 27 | namespace log_label { 28 | 29 | /** 30 | * Default function assigned to cpp_dump::options::log_label_func. 31 | */ 32 | inline std::string default_func(std::string_view, std::size_t, std::string_view) { 33 | return "[dump] "; 34 | } 35 | 36 | /** 37 | * Function that create a function to assign to cpp_dump::options::log_label_func. 38 | * See README for details. 39 | */ 40 | inline types::log_label_func_t line(bool show_func = false, int min_width = 0) { 41 | return [=](std::string_view, std::size_t line, std::string_view func_name) -> std::string { 42 | std::string output = "[:" + std::to_string(line); 43 | if (show_func) { 44 | output.append(" (").append(func_name).append(")"); 45 | } 46 | 47 | int space_len = (min_width - 2) - static_cast(output.size()); 48 | if (space_len > 0) { 49 | output.append(space_len, ' '); 50 | } 51 | 52 | output += "] "; 53 | return output; 54 | }; 55 | } 56 | 57 | /** 58 | * Function that create a function to assign to cpp_dump::options::log_label_func. 59 | * See README for details. 60 | */ 61 | inline types::log_label_func_t basename(bool show_func = false, int min_width = 0) { 62 | return 63 | [=](std::string_view fullpath, std::size_t line, std::string_view func_name) -> std::string { 64 | auto slash_pos = fullpath.find_last_of("/\\"); 65 | if (slash_pos == std::string::npos) { 66 | slash_pos = 0; 67 | } else { 68 | ++slash_pos; 69 | } 70 | std::string file_name(fullpath.substr(slash_pos)); 71 | 72 | auto dot_pos = file_name.rfind('.'); 73 | if (dot_pos == std::string::npos) { 74 | dot_pos = file_name.length(); 75 | } 76 | std::string basename = file_name.substr(0, dot_pos); 77 | 78 | std::string output = "[" + basename + ":" + std::to_string(line); 79 | if (show_func) { 80 | output.append(" (").append(func_name).append(")"); 81 | } 82 | 83 | int space_len = (min_width - 2) - static_cast(output.size()); 84 | if (space_len > 0) { 85 | output.append(space_len, ' '); 86 | } 87 | 88 | output += "] "; 89 | return output; 90 | }; 91 | } 92 | 93 | /** 94 | * Function that create a function to assign to cpp_dump::options::log_label_func. 95 | * See README for details. 96 | */ 97 | inline types::log_label_func_t filename(bool show_func = false, int min_width = 0) { 98 | return 99 | [=](std::string_view fullpath, std::size_t line, std::string_view func_name) -> std::string { 100 | auto slash_pos = fullpath.find_last_of("/\\"); 101 | if (slash_pos == std::string::npos) { 102 | slash_pos = 0; 103 | } else { 104 | ++slash_pos; 105 | } 106 | std::string file_name(fullpath.substr(slash_pos)); 107 | 108 | std::string output = "[" + file_name + ":" + std::to_string(line); 109 | if (show_func) { 110 | output.append(" (").append(func_name).append(")"); 111 | } 112 | 113 | int space_len = (min_width - 2) - static_cast(output.size()); 114 | if (space_len > 0) { 115 | output.append(space_len, ' '); 116 | } 117 | 118 | output += "] "; 119 | return output; 120 | }; 121 | } 122 | 123 | /** 124 | * Function that create a function to assign to cpp_dump::options::log_label_func. 125 | * See README for details. 126 | */ 127 | inline types::log_label_func_t fullpath( 128 | int substr_start, bool show_func = false, int min_width = 0 129 | ) { 130 | return 131 | [=](std::string_view fullpath, std::size_t line, std::string_view func_name) -> std::string { 132 | std::string output = "["; 133 | output.append(fullpath.substr(std::min(substr_start, fullpath.length()))); 134 | output.append(":").append(std::to_string(line)); 135 | 136 | if (show_func) { 137 | output.append(" (").append(func_name).append(")"); 138 | } 139 | 140 | int space_len = (min_width - 2) - static_cast(output.size()); 141 | if (space_len > 0) { 142 | output.append(space_len, ' '); 143 | } 144 | 145 | output += "] "; 146 | return output; 147 | }; 148 | } 149 | 150 | /** 151 | * Function that create a function to assign to cpp_dump::options::log_label_func. 152 | * See README for details. 153 | */ 154 | inline types::log_label_func_t fixed_length( 155 | int min_width, int max_width, int substr_start, bool show_func = false 156 | ) { 157 | return 158 | [=](std::string_view fullpath, std::size_t line, std::string_view func_name) -> std::string { 159 | std::string output = "["; 160 | output.append(fullpath.substr(std::min(substr_start, fullpath.length()))); 161 | output.append(":").append(std::to_string(line)); 162 | 163 | if (show_func) { 164 | output.append(" (").append(func_name).append(")"); 165 | } 166 | 167 | int space_len = (min_width - 2) - static_cast(output.size()); 168 | if (space_len > 0) { 169 | output.append(space_len, ' '); 170 | } 171 | 172 | if (max_width > 2 && output.length() > static_cast(max_width - 2)) { 173 | output = "[.. " + output.substr(output.length() - std::max(max_width - 6, 0)); 174 | } 175 | 176 | output += "] "; 177 | return output; 178 | }; 179 | } 180 | 181 | } // namespace log_label 182 | 183 | } // namespace cpp_dump 184 | -------------------------------------------------------------------------------- /cpp-dump/hpp/options.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Ryota Sasaki. 3 | * 4 | * This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "./log_label.hpp" 11 | 12 | namespace cpp_dump { 13 | 14 | /** 15 | * Set a value to a variable in cpp_dump::options namespace. 16 | */ 17 | #define CPP_DUMP_SET_OPTION(variable, value) cpp_dump::options::variable = (value) 18 | 19 | namespace _detail { 20 | 21 | struct empty_class {}; 22 | 23 | } // namespace _detail 24 | 25 | #define _p_CPP_DUMP_SET_OPTION_GLOBAL_AUX2(variable, value, line) \ 26 | namespace cpp_dump { \ 27 | \ 28 | namespace _detail { \ 29 | \ 30 | namespace _dummy_variables_for_set_option_global { \ 31 | \ 32 | [[maybe_unused]] inline auto _dummy_##line = \ 33 | (cpp_dump::options::variable = (value), empty_class{}); \ 34 | \ 35 | } /* namespace _dummy_variables_for_set_option_global */ \ 36 | \ 37 | } /* namespace _detail */ \ 38 | \ 39 | } // namespace cpp_dump 40 | 41 | #define _p_CPP_DUMP_SET_OPTION_GLOBAL_AUX(variable, value, line) \ 42 | _p_CPP_DUMP_SET_OPTION_GLOBAL_AUX2(variable, value, line) 43 | 44 | /** 45 | * Set a value to a variable in cpp_dump::options namespace. 46 | * Use this if you want to run it in the global namespace, meaning before the main starts. 47 | */ 48 | #define CPP_DUMP_SET_OPTION_GLOBAL(variable, value) \ 49 | _p_CPP_DUMP_SET_OPTION_GLOBAL_AUX(variable, value, __LINE__) 50 | 51 | namespace types { 52 | 53 | /** 54 | * Type of cpp_dump::options::cont_indent_style. 55 | * cpp_dump::export_var() supports this type. 56 | */ 57 | enum class cont_indent_style_t { minimal, when_nested, when_non_tuples_nested, always }; 58 | 59 | /** 60 | * Type of cpp_dump::options::es_style. 61 | * cpp_dump::export_var() supports this type. 62 | */ 63 | enum class es_style_t { no_es, original, by_syntax }; 64 | 65 | /** 66 | * Type of cpp_dump::options::es_value. 67 | * cpp_dump::export_var() supports this type. 68 | */ 69 | struct es_value_t { 70 | std::string log = "\x1b[02m"; // dark 71 | std::string expression = "\x1b[36m"; // cyan 72 | std::string reserved{}; // default 73 | std::string number{}; // default 74 | std::string character{}; // default 75 | std::string escaped_char = "\x1b[02m"; // dark 76 | std::string op = "\x1b[02m"; // dark 77 | std::string identifier = "\x1b[32m"; // green 78 | std::string member = "\x1b[36m"; // cyan 79 | std::string unsupported = "\x1b[31m"; // red 80 | std::vector bracket_by_depth{"\x1b[02m"}; // dark 81 | std::string class_op = "\x1b[02m"; // dark 82 | std::string member_op = "\x1b[02m"; // dark 83 | std::string number_op{}; // default 84 | }; 85 | 86 | } // namespace types 87 | 88 | namespace options { 89 | 90 | /** 91 | * Maximum line width of the strings returned by cpp_dump() and cpp_dump::export_var(). 92 | */ 93 | inline std::size_t max_line_width = 160; 94 | 95 | /** 96 | * Maximum number of times cpp_dump::export_var() is called recursively. 97 | */ 98 | inline std::size_t max_depth = 4; 99 | 100 | /** 101 | * Maximum number of iterations of cpp_dump::export_var() over an iterator. 102 | * Note that in a single call, cpp_dump::export_var() calls itself at most 103 | * (max_iteration_count^(max_depth+1)-1)/(max_iteration_count-1) times. 104 | */ 105 | inline std::size_t max_iteration_count = 16; 106 | 107 | /** 108 | * Style of indents of the Container, Set and Map categories (See 'Supported types'). 109 | */ 110 | inline types::cont_indent_style_t cont_indent_style = types::cont_indent_style_t::when_nested; 111 | 112 | /** 113 | * Whether cpp_dump() prints types of the Asterisk category (See 'Supported types'). 114 | */ 115 | inline bool enable_asterisk = false; 116 | 117 | /** 118 | * Whether cpp_dump() prints the expressions. 119 | */ 120 | inline bool print_expr = true; 121 | 122 | /** 123 | * Function that returns the label that cpp_dump() prints at the beginning of the output. 124 | */ 125 | inline types::log_label_func_t log_label_func = log_label::default_func; 126 | 127 | /** 128 | * Style of the escape sequences (output coloring). 129 | */ 130 | inline types::es_style_t es_style = types::es_style_t::original; 131 | 132 | /** 133 | * Values of the escape sequences (output coloring). 134 | */ 135 | inline types::es_value_t es_value; 136 | 137 | /** 138 | * If true, the 'es_value.class_op' color is used for operators in class names (::, <>, etc...). 139 | */ 140 | inline bool detailed_class_es = false; 141 | 142 | /** 143 | * If true, the 'es_value.member_op' color is used for operators in members ((), etc...). 144 | */ 145 | inline bool detailed_member_es = false; 146 | 147 | /** 148 | * If true, the 'es_value.number_op' color is used for operators in numbers (-, +, etc...). 149 | */ 150 | inline bool detailed_number_es = false; 151 | 152 | } // namespace options 153 | 154 | } // namespace cpp_dump 155 | -------------------------------------------------------------------------------- /cpp-dump/hpp/utility.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Ryota Sasaki. 3 | * 4 | * This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "./escape_sequence.hpp" 17 | 18 | namespace cpp_dump { 19 | 20 | namespace _detail { 21 | 22 | inline bool has_newline(std::string_view s) { return s.find('\n') != std::string::npos; } 23 | 24 | inline std::size_t get_length(std::string_view s) { 25 | if (!use_es()) { 26 | return s.length(); 27 | } 28 | 29 | static constexpr std::string_view es_begin_token = "\x1b["; 30 | std::size_t length = 0; 31 | auto begin = s.begin(); 32 | decltype(begin) end; 33 | while ((end = std::search(begin, s.end(), es_begin_token.begin(), es_begin_token.end())) 34 | != s.end()) { 35 | length += end - begin; 36 | begin = end + es_begin_token.size(); 37 | end = std::find_if(begin, s.end(), [](char c) { 38 | return !(std::isdigit(static_cast(c)) || c == ';'); 39 | }); 40 | if (end == s.end()) { 41 | break; 42 | } 43 | begin = end + 1; 44 | } 45 | length += end - begin; 46 | 47 | return length; 48 | } 49 | 50 | inline std::size_t get_first_line_length(std::string_view s) { 51 | auto lf_pos = s.find('\n'); 52 | if (lf_pos == std::string::npos) { 53 | return get_length(s); 54 | } 55 | return get_length(s.substr(0, lf_pos)); 56 | } 57 | 58 | inline std::size_t get_last_line_length( 59 | std::string_view s, std::size_t additional_first_line_length = 0 60 | ) { 61 | auto lf_pos = s.rfind('\n'); 62 | if (lf_pos == std::string::npos) { 63 | return additional_first_line_length + get_length(s); 64 | } 65 | return get_length(s.substr(lf_pos + 1)); 66 | } 67 | 68 | inline std::string replace_string( 69 | std::string_view s, std::string_view search, std::string_view replace 70 | ) { 71 | std::string retval; 72 | auto begin = s.begin(); 73 | decltype(begin) end; 74 | while ((end = std::search(begin, s.end(), search.begin(), search.end())) != s.end()) { 75 | retval.append(begin, end); 76 | retval.append(replace); 77 | begin = end + search.size(); 78 | } 79 | retval.append(begin, s.end()); 80 | return retval; 81 | } 82 | 83 | inline std::string escape_non_printable_char(char c) { 84 | static const std::map char_to_escaped{ 85 | {'\0', "\\0"}, // null 86 | {'\a', "\\a"}, // bell 87 | {'\b', "\\b"}, // backspace 88 | {'\f', "\\f"}, // form feed 89 | {'\n', "\\n"}, // LF 90 | {'\r', "\\r"}, // CR 91 | {'\t', "\\t"}, // Horizontal tab 92 | {'\v', "\\v"}, // Vertical tab 93 | }; 94 | 95 | if (char_to_escaped.count(c)) { 96 | return std::string(char_to_escaped.at(c)); 97 | } 98 | 99 | auto to_hex_char = [](unsigned char uc) -> char { 100 | return static_cast(uc < 10 ? '0' + uc : 'A' + (uc - 10)); 101 | }; 102 | char upper = to_hex_char((c >> 4) & 0x0f); 103 | char lower = to_hex_char(c & 0x0f); 104 | return std::string({'\\', 'x', upper, lower}); 105 | } 106 | 107 | inline std::string escape_string(std::string_view s) { 108 | auto need_escape = [](char c) { 109 | return !std::isprint(static_cast(c)) || c == '"' || c == '\\'; 110 | }; 111 | auto escape_char = [](char c) -> std::string { 112 | switch (c) { 113 | case '"': 114 | return R"(\")"; 115 | case '\\': 116 | return R"(\\)"; 117 | default: 118 | return escape_non_printable_char(c); 119 | } 120 | }; 121 | 122 | std::string retval(1, '"'); 123 | auto begin = s.begin(); 124 | decltype(begin) end; 125 | while ((end = std::find_if(begin, s.end(), need_escape)) != s.end()) { 126 | retval.append(begin, end); 127 | retval.append(escape_char(*end)); 128 | begin = end + 1; 129 | } 130 | retval.append(begin, end).push_back('"'); 131 | 132 | return retval; 133 | } 134 | 135 | } // namespace _detail 136 | 137 | } // namespace cpp_dump 138 | -------------------------------------------------------------------------------- /dump.hpp: -------------------------------------------------------------------------------- 1 | // See https://github.com/philip82148/cpp-dump/pull/100 for details of this file. 2 | #pragma once 3 | #pragma message( \ 4 | "WARNING: The 'dump.hpp' header is deprecated. Include the 'cpp-dump.hpp' header instead." \ 5 | ) 6 | #include "./cpp-dump.hpp" 7 | -------------------------------------------------------------------------------- /readme/auto-indent.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "../cpp-dump.hpp" 6 | 7 | int main() { 8 | std::clog << std::endl; 9 | 10 | CPP_DUMP_SET_OPTION(max_line_width, 100); 11 | 12 | std::vector my_vector(3, "This is a test string."); 13 | cpp_dump(my_vector); 14 | 15 | my_vector.push_back("This is a test string."); 16 | cpp_dump(my_vector); 17 | 18 | std::clog << std::endl; 19 | } 20 | -------------------------------------------------------------------------------- /readme/auto-indent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philip82148/cpp-dump/aabd98dd8a4b5ae3f62cf12387a68a9f6591197e/readme/auto-indent.png -------------------------------------------------------------------------------- /readme/cpp-dump.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philip82148/cpp-dump/aabd98dd8a4b5ae3f62cf12387a68a9f6591197e/readme/cpp-dump.gif -------------------------------------------------------------------------------- /readme/customizable-colors-light-plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philip82148/cpp-dump/aabd98dd8a4b5ae3f62cf12387a68a9f6591197e/readme/customizable-colors-light-plus.png -------------------------------------------------------------------------------- /readme/customizable-colors.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "../cpp-dump.hpp" 16 | 17 | int main() { 18 | // Use more colors 19 | CPP_DUMP_SET_OPTION(es_value.log, "\x1b[02m"); // log: dark 20 | CPP_DUMP_SET_OPTION(es_value.expression, "\x1b[34m"); // expression: blue 21 | CPP_DUMP_SET_OPTION(es_value.reserved, "\x1b[38;5;39m"); // reserved: light blue 22 | CPP_DUMP_SET_OPTION(es_value.number, "\x1b[38;5;150m"); // number: light green 23 | CPP_DUMP_SET_OPTION(es_value.character, "\x1b[38;5;172m"); // character: orange 24 | CPP_DUMP_SET_OPTION(es_value.escaped_char, "\x1b[38;5;220m"); // escaped_char: light orange 25 | CPP_DUMP_SET_OPTION(es_value.op, "\x1b[02m"); // op: dark 26 | CPP_DUMP_SET_OPTION(es_value.identifier, "\x1b[32m"); // identifier: green 27 | CPP_DUMP_SET_OPTION(es_value.member, "\x1b[96m"); // member: light cyan 28 | CPP_DUMP_SET_OPTION(es_value.unsupported, "\x1b[31m"); // unsupported: red 29 | CPP_DUMP_SET_OPTION( 30 | es_value.bracket_by_depth, 31 | (std::vector{ 32 | "\x1b[33m", // bracket_by_depth[0]: yellow 33 | "\x1b[35m", // bracket_by_depth[1]: magenta 34 | "\x1b[36m", // bracket_by_depth[2]: cyan 35 | }) 36 | ); 37 | CPP_DUMP_SET_OPTION(es_value.class_op, "\x1b[02m"); // class_op: dark 38 | CPP_DUMP_SET_OPTION(es_value.member_op, "\x1b[02m"); // member_op: dark 39 | CPP_DUMP_SET_OPTION(es_value.number_op, ""); // number_op: default 40 | 41 | // Use the 'class_op'/'member_op'/'number_op' color for operators 42 | // in class names, members, and numbers (::, <>, (), -, +, etc...). 43 | CPP_DUMP_SET_OPTION(detailed_class_es, true); 44 | CPP_DUMP_SET_OPTION(detailed_member_es, true); 45 | CPP_DUMP_SET_OPTION(detailed_number_es, true); 46 | 47 | // Use a color scheme closer to standard syntax highlighting. 48 | // CPP_DUMP_SET_OPTION(es_style, cp::types::es_style_t::by_syntax); 49 | 50 | bool my_bool = true; 51 | double my_double = 3.141592; 52 | int my_int = 65; 53 | char my_char = 'a', LF_char = '\n'; 54 | std::string my_string = "This is a string."; 55 | int *int_ptr = &my_int; 56 | void *void_ptr = &my_int; 57 | std::vector> my_vector{{3, 5, 8, 9, 7}, {9, 3, 2, 3, 8}}; 58 | std::set my_set{'A', 'p', 'p', 'l', 'e'}; 59 | std::map my_map{{2, 6}, {4, 6}, {5, 3}}; 60 | std::multiset my_multiset{'A', 'p', 'p', 'l', 'e'}; 61 | std::multimap my_multimap{{2, 4}, {4, 6}, {5, 3}, {4, 7}}; 62 | std::pair my_pair{8, 'a'}; 63 | std::tuple my_tuple{7, 4.5, "This is a string."}; 64 | std::queue my_queue; 65 | std::priority_queue my_priority_queue; 66 | std::stack my_stack; 67 | for (auto v : {1, 2, 3, 4, 5}) my_queue.push(v), my_priority_queue.push(v), my_stack.push(v); 68 | std::bitset<8> my_bitset(0x3a); 69 | std::complex my_complex{1.0, -1.0}; 70 | std::optional my_optional{15}; 71 | std::variant my_variant{"This is a string."}; 72 | std::vector> vector_of_pairs{{1, "apple"}, {3, "banana"}}; 73 | 74 | std::clog << "\n// Basic Type" << std::endl; 75 | cpp_dump(my_bool, my_double, my_int), cpp_dump(my_string, my_char, LF_char); 76 | cpp_dump(int_ptr, void_ptr, nullptr); 77 | 78 | std::clog << "\n// Container" << std::endl; 79 | cpp_dump(my_vector); 80 | 81 | std::clog << "\n// Set/Map" << std::endl; 82 | cpp_dump(my_set), cpp_dump(my_map); 83 | 84 | std::clog << "\n// Multiset/Multimap" << std::endl; 85 | cpp_dump(my_multiset), cpp_dump(my_multimap); 86 | 87 | std::clog << "\n// Tuple" << std::endl; 88 | cpp_dump(my_tuple), cpp_dump(my_pair); 89 | 90 | std::clog << "\n// FIFO/LIFO" << std::endl; 91 | cpp_dump(my_queue), cpp_dump(my_priority_queue), cpp_dump(my_stack); 92 | 93 | std::clog << "\n// Other" << std::endl; 94 | cpp_dump(my_bitset), cpp_dump(my_complex); 95 | cpp_dump(my_optional, std::nullopt), cpp_dump(my_variant); 96 | 97 | std::clog << "\n// Combination" << std::endl; 98 | cpp_dump(vector_of_pairs); 99 | 100 | std::clog << std::endl; 101 | } 102 | -------------------------------------------------------------------------------- /readme/customizable-colors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philip82148/cpp-dump/aabd98dd8a4b5ae3f62cf12387a68a9f6591197e/readme/customizable-colors.png -------------------------------------------------------------------------------- /readme/customize-dump.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "../cpp-dump.hpp" 7 | namespace cp = cpp_dump; 8 | 9 | void my_func() { 10 | std::map my_map{{2, 6}, {4, 6}, {5, 3}}; 11 | std::set my_set{'A', 'p', 'p', 'l', 'e'}; 12 | cpp_dump(my_map); 13 | cpp_dump(my_set); 14 | } 15 | 16 | int main() { 17 | std::clog << std::endl; 18 | 19 | std::vector> my_vector{{3, 5, 8, 9, 7}, {9, 3, 2, 3, 8}}; 20 | 21 | std::clog << "// Print the filename and line instead of [dump]" << std::endl; 22 | CPP_DUMP_SET_OPTION(log_label_func, cp::log_label::filename()); 23 | 24 | cpp_dump(my_vector); 25 | my_func(); 26 | 27 | std::clog << std::endl; 28 | 29 | std::clog << "// Print along with the function name" << std::endl; 30 | CPP_DUMP_SET_OPTION(log_label_func, cp::log_label::filename(true)); 31 | 32 | cpp_dump(my_vector); 33 | my_func(); 34 | 35 | std::clog << std::endl; 36 | } 37 | -------------------------------------------------------------------------------- /readme/customize-dump.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philip82148/cpp-dump/aabd98dd8a4b5ae3f62cf12387a68a9f6591197e/readme/customize-dump.png -------------------------------------------------------------------------------- /readme/formatting-with-manipulators.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "../cpp-dump.hpp" 6 | namespace cp = cpp_dump; 7 | 8 | int main() { 9 | std::clog << std::endl; 10 | 11 | std::vector> some_huge_vector(100, std::vector(100)); 12 | std::vector> unsigned_int_vector(100, std::vector(100)); 13 | 14 | for (int i = 0; i < 100; ++i) { 15 | for (int j = 0; j < 100; ++j) { 16 | some_huge_vector[i][j] = ((i + 1) * 7 % 19 - 9) * ((j + 1) * 3 % 19 - 9); 17 | unsigned_int_vector[i][j] = std::abs(some_huge_vector[i][j]); 18 | } 19 | } 20 | 21 | // default: max_iteration_count = 16; 22 | cpp_dump(some_huge_vector); 23 | 24 | std::clog << "\n// manipulator-front-etc.png\n" << std::endl; 25 | 26 | cpp_dump(some_huge_vector | cp::back(10) | cp::both_ends(5) | cp::dec(2)); 27 | 28 | std::clog << "\n// manipulator-index.png\n" << std::endl; 29 | 30 | CPP_DUMP_SET_OPTION(max_iteration_count, 5); 31 | cpp_dump(some_huge_vector | cp::dec(2) | cp::index()); 32 | 33 | std::clog << "\n// manipulator-int-style.png\n" << std::endl; 34 | 35 | cpp_dump(0x3e8u | cp::bin(16, 4)); 36 | cpp_dump(0x3e8u | cp::oct(6, 3)); 37 | cpp_dump(0x3e8u | cp::hex(4, 2)); 38 | cpp_dump(0x3e8u | cp::dec(4)); 39 | 40 | std::clog << "\n// manipulator-int-style2.png\n" << std::endl; 41 | 42 | auto &int_vector = unsigned_int_vector; 43 | 44 | cpp_dump(int_vector | cp::front(2) | cp::bin(8)); 45 | cpp_dump(int_vector | cp::front(2) | cp::oct(3)); 46 | cpp_dump(int_vector | cp::front(2) | cp::dec(2)); 47 | cpp_dump(int_vector | cp::front(2) | cp::hex(2)); 48 | 49 | std::clog << "\n// manipulator-bin-etc.png\n" << std::endl; 50 | 51 | auto &signed_int_vector = some_huge_vector; 52 | 53 | cpp_dump(signed_int_vector | cp::front(2) | cp::hex(2)); 54 | cpp_dump(unsigned_int_vector | cp::front(2) | cp::hex(2)); 55 | cpp_dump(signed_int_vector | cp::front(2) | cp::dec(2)); 56 | cpp_dump(unsigned_int_vector | cp::front(2) | cp::dec(2)); 57 | 58 | std::clog << "\n// manipulator-ubin-etc.png\n" << std::endl; 59 | 60 | cpp_dump(signed_int_vector | cp::front(2) | cp::uhex()); 61 | cpp_dump(unsigned_int_vector | cp::front(2) | cp::uhex(2)); 62 | cpp_dump(signed_int_vector | cp::front(2) | cp::udec(2)); 63 | cpp_dump(unsigned_int_vector | cp::front(2) | cp::udec(2)); 64 | 65 | std::clog << "\n// manipulator-format.png\n" << std::endl; 66 | 67 | constexpr double pi = 3.14159265358979323846; 68 | cpp_dump(pi | cp::format("%.10f")); 69 | 70 | std::clog << "\n// manipulator-bw-boolnum.png\n" << std::endl; 71 | 72 | std::vector> bool_vector{ 73 | {true, false, true, true, false}, 74 | {false, false, false, true, true}, 75 | }; 76 | 77 | cpp_dump(bool_vector | cp::bw()); 78 | cpp_dump(bool_vector | cp::bw(true)); 79 | cpp_dump(bool_vector | cp::boolnum()); 80 | 81 | std::clog << "\n// manipulator-stresc.png\n" << std::endl; 82 | 83 | cpp_dump("\a\t\\\"\n\x7f need to be escaped."); 84 | cpp_dump("\a\t\\\"\n\x7f need to be escaped." | cp::stresc()); 85 | 86 | std::clog << "\n// manipulator-charhex.png\n" << std::endl; 87 | 88 | for (auto c : "\a\t\\\"\n\x7f ABC") cpp_dump(c | cp::charhex()); 89 | 90 | std::clog << "\n// manipulator-addr.png\n" << std::endl; 91 | 92 | int my_int = 15; 93 | int *int_ptr = &my_int; 94 | int **int_ptr_ptr = &int_ptr; 95 | cpp_dump(int_ptr_ptr); 96 | cpp_dump(int_ptr_ptr | cp::addr()); 97 | cpp_dump(int_ptr_ptr | cp::addr(1)); 98 | 99 | std::clog << std::endl; 100 | } 101 | -------------------------------------------------------------------------------- /readme/introduction.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../cpp-dump.hpp" 5 | 6 | int main() { 7 | std::clog << std::endl; 8 | 9 | std::vector> my_vector{{3, 5, 8, 9, 7}, {9, 3, 2, 3, 8}}; 10 | cpp_dump(my_vector); 11 | 12 | std::clog << std::endl; 13 | } 14 | -------------------------------------------------------------------------------- /readme/introduction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philip82148/cpp-dump/aabd98dd8a4b5ae3f62cf12387a68a9f6591197e/readme/introduction.png -------------------------------------------------------------------------------- /readme/manipulator-addr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philip82148/cpp-dump/aabd98dd8a4b5ae3f62cf12387a68a9f6591197e/readme/manipulator-addr.png -------------------------------------------------------------------------------- /readme/manipulator-bin-etc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philip82148/cpp-dump/aabd98dd8a4b5ae3f62cf12387a68a9f6591197e/readme/manipulator-bin-etc.png -------------------------------------------------------------------------------- /readme/manipulator-bw-boolnum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philip82148/cpp-dump/aabd98dd8a4b5ae3f62cf12387a68a9f6591197e/readme/manipulator-bw-boolnum.png -------------------------------------------------------------------------------- /readme/manipulator-charhex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philip82148/cpp-dump/aabd98dd8a4b5ae3f62cf12387a68a9f6591197e/readme/manipulator-charhex.png -------------------------------------------------------------------------------- /readme/manipulator-format.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philip82148/cpp-dump/aabd98dd8a4b5ae3f62cf12387a68a9f6591197e/readme/manipulator-format.png -------------------------------------------------------------------------------- /readme/manipulator-front-etc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philip82148/cpp-dump/aabd98dd8a4b5ae3f62cf12387a68a9f6591197e/readme/manipulator-front-etc.png -------------------------------------------------------------------------------- /readme/manipulator-index.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philip82148/cpp-dump/aabd98dd8a4b5ae3f62cf12387a68a9f6591197e/readme/manipulator-index.png -------------------------------------------------------------------------------- /readme/manipulator-int-style.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philip82148/cpp-dump/aabd98dd8a4b5ae3f62cf12387a68a9f6591197e/readme/manipulator-int-style.png -------------------------------------------------------------------------------- /readme/manipulator-int-style2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philip82148/cpp-dump/aabd98dd8a4b5ae3f62cf12387a68a9f6591197e/readme/manipulator-int-style2.png -------------------------------------------------------------------------------- /readme/manipulator-stresc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philip82148/cpp-dump/aabd98dd8a4b5ae3f62cf12387a68a9f6591197e/readme/manipulator-stresc.png -------------------------------------------------------------------------------- /readme/manipulator-ubin-etc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philip82148/cpp-dump/aabd98dd8a4b5ae3f62cf12387a68a9f6591197e/readme/manipulator-ubin-etc.png -------------------------------------------------------------------------------- /readme/no-es.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "../cpp-dump.hpp" 16 | namespace cp = cpp_dump; 17 | 18 | int main() { 19 | CPP_DUMP_SET_OPTION(es_style, cp::types::es_style_t::no_es); 20 | 21 | bool my_bool = true; 22 | double my_double = 3.141592; 23 | int my_int = 65; 24 | char my_char = 'a', LF_char = '\n'; 25 | std::string my_string = "This is a string."; 26 | int *int_ptr = &my_int; 27 | void *void_ptr = &my_int; 28 | std::vector> my_vector{{3, 5, 8, 9, 7}, {9, 3, 2, 3, 8}}; 29 | std::set my_set{'A', 'p', 'p', 'l', 'e'}; 30 | std::map my_map{{2, 6}, {4, 6}, {5, 3}}; 31 | std::multiset my_multiset{'A', 'p', 'p', 'l', 'e'}; 32 | std::multimap my_multimap{{2, 4}, {4, 6}, {5, 3}, {4, 7}}; 33 | std::pair my_pair{8, 'a'}; 34 | std::tuple my_tuple{7, 4.5, "This is a string."}; 35 | std::queue my_queue; 36 | std::priority_queue my_priority_queue; 37 | std::stack my_stack; 38 | for (auto v : {1, 2, 3, 4, 5}) my_queue.push(v), my_priority_queue.push(v), my_stack.push(v); 39 | std::bitset<8> my_bitset(0x3a); 40 | std::complex my_complex{1.0, -1.0}; 41 | std::optional my_optional{15}; 42 | std::variant my_variant{"This is a string."}; 43 | std::vector> vector_of_pairs{{1, "apple"}, {3, "banana"}}; 44 | 45 | std::clog << "\n// Basic Type" << std::endl; 46 | cpp_dump(my_bool, my_double, my_int), cpp_dump(my_string, my_char, LF_char); 47 | cpp_dump(int_ptr, void_ptr, nullptr); 48 | 49 | std::clog << "\n// Container" << std::endl; 50 | cpp_dump(my_vector); 51 | 52 | std::clog << "\n// Set/Map" << std::endl; 53 | cpp_dump(my_set), cpp_dump(my_map); 54 | 55 | std::clog << "\n// Multiset/Multimap" << std::endl; 56 | cpp_dump(my_multiset), cpp_dump(my_multimap); 57 | 58 | std::clog << "\n// Tuple" << std::endl; 59 | cpp_dump(my_tuple), cpp_dump(my_pair); 60 | 61 | std::clog << "\n// FIFO/LIFO" << std::endl; 62 | cpp_dump(my_queue), cpp_dump(my_priority_queue), cpp_dump(my_stack); 63 | 64 | std::clog << "\n// Other" << std::endl; 65 | cpp_dump(my_bitset), cpp_dump(my_complex); 66 | cpp_dump(my_optional, std::nullopt), cpp_dump(my_variant); 67 | 68 | std::clog << "\n// Combination" << std::endl; 69 | cpp_dump(vector_of_pairs); 70 | 71 | std::clog << std::endl; 72 | } 73 | -------------------------------------------------------------------------------- /readme/supports-various-types.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "../cpp-dump.hpp" 16 | 17 | int main() { 18 | bool my_bool = true; 19 | double my_double = 3.141592; 20 | int my_int = 65; 21 | char my_char = 'a', LF_char = '\n'; 22 | std::string my_string = "This is a string."; 23 | int *int_ptr = &my_int; 24 | void *void_ptr = &my_int; 25 | std::vector> my_vector{{3, 5, 8, 9, 7}, {9, 3, 2, 3, 8}}; 26 | std::set my_set{'A', 'p', 'p', 'l', 'e'}; 27 | std::map my_map{{2, 6}, {4, 6}, {5, 3}}; 28 | std::multiset my_multiset{'A', 'p', 'p', 'l', 'e'}; 29 | std::multimap my_multimap{{2, 4}, {4, 6}, {5, 3}, {4, 7}}; 30 | std::pair my_pair{8, 'a'}; 31 | std::tuple my_tuple{7, 4.5, "This is a string."}; 32 | std::queue my_queue; 33 | std::priority_queue my_priority_queue; 34 | std::stack my_stack; 35 | for (auto v : {1, 2, 3, 4, 5}) my_queue.push(v), my_priority_queue.push(v), my_stack.push(v); 36 | std::bitset<8> my_bitset(0x3a); 37 | std::complex my_complex{1.0, -1.0}; 38 | std::optional my_optional{15}; 39 | std::variant my_variant{"This is a string."}; 40 | std::vector> vector_of_pairs{{1, "apple"}, {3, "banana"}}; 41 | 42 | std::clog << "\n// Basic Type" << std::endl; 43 | cpp_dump(my_bool, my_double, my_int), cpp_dump(my_string, my_char, LF_char); 44 | cpp_dump(int_ptr, void_ptr, nullptr); 45 | 46 | std::clog << "\n// Container" << std::endl; 47 | cpp_dump(my_vector); 48 | 49 | std::clog << "\n// Set/Map" << std::endl; 50 | cpp_dump(my_set), cpp_dump(my_map); 51 | 52 | std::clog << "\n// Multiset/Multimap" << std::endl; 53 | cpp_dump(my_multiset), cpp_dump(my_multimap); 54 | 55 | std::clog << "\n// Tuple" << std::endl; 56 | cpp_dump(my_tuple), cpp_dump(my_pair); 57 | 58 | std::clog << "\n// FIFO/LIFO" << std::endl; 59 | cpp_dump(my_queue), cpp_dump(my_priority_queue), cpp_dump(my_stack); 60 | 61 | std::clog << "\n// Other" << std::endl; 62 | cpp_dump(my_bitset), cpp_dump(my_complex); 63 | cpp_dump(my_optional, std::nullopt), cpp_dump(my_variant); 64 | 65 | std::clog << "\n// Combination" << std::endl; 66 | cpp_dump(vector_of_pairs); 67 | 68 | std::clog << std::endl; 69 | } 70 | -------------------------------------------------------------------------------- /readme/supports-various-types.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philip82148/cpp-dump/aabd98dd8a4b5ae3f62cf12387a68a9f6591197e/readme/supports-various-types.png -------------------------------------------------------------------------------- /readme/test-code.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "../cpp-dump.hpp" 16 | namespace cp = cpp_dump; 17 | 18 | int main() { 19 | bool my_bool = true; 20 | double my_double = 3.141592; 21 | int my_int = 65; 22 | char my_char = 'a', LF_char = '\n'; 23 | std::string my_string = "This is a string."; 24 | int *int_ptr = &my_int; 25 | void *void_ptr = &my_int; 26 | std::vector> my_vector{{3, 5, 8, 9, 7}, {9, 3, 2, 3, 8}}; 27 | std::set my_set{'A', 'p', 'p', 'l', 'e'}; 28 | std::map my_map{{2, 6}, {4, 6}, {5, 3}}; 29 | std::multiset my_multiset{'A', 'p', 'p', 'l', 'e'}; 30 | std::multimap my_multimap{{2, 4}, {4, 6}, {5, 3}, {4, 7}}; 31 | std::pair my_pair{8, 'a'}; 32 | std::tuple my_tuple{7, 4.5, "This is a string."}; 33 | std::queue my_queue; 34 | std::priority_queue my_priority_queue; 35 | std::stack my_stack; 36 | for (auto v : {1, 2, 3, 4, 5}) my_queue.push(v), my_priority_queue.push(v), my_stack.push(v); 37 | std::bitset<8> my_bitset(0x3a); 38 | std::complex my_complex{1.0, -1.0}; 39 | std::optional my_optional{15}; 40 | std::variant my_variant{"This is a string."}; 41 | std::vector> vector_of_pairs{{1, "apple"}, {3, "banana"}}; 42 | 43 | CPP_DUMP_SET_OPTION(max_line_width, 100); 44 | CPP_DUMP_SET_OPTION(max_iteration_count, 10); 45 | 46 | std::clog << "\n// Basic Type" << std::endl; 47 | cpp_dump(my_bool, my_double, my_int), cpp_dump(my_string, my_char, LF_char); 48 | cpp_dump(int_ptr, void_ptr, nullptr); 49 | 50 | std::clog << "\n// Container" << std::endl; 51 | cpp_dump(my_vector); 52 | 53 | std::clog << "\n// Set/Map" << std::endl; 54 | cpp_dump(my_set), cpp_dump(my_map); 55 | 56 | std::clog << "\n// Multiset/Multimap" << std::endl; 57 | cpp_dump(my_multiset), cpp_dump(my_multimap); 58 | 59 | std::clog << "\n// Tuple" << std::endl; 60 | cpp_dump(my_tuple), cpp_dump(my_pair); 61 | 62 | std::clog << "\n// FIFO/LIFO" << std::endl; 63 | cpp_dump(my_queue), cpp_dump(my_priority_queue), cpp_dump(my_stack); 64 | 65 | std::clog << "\n// Other" << std::endl; 66 | cpp_dump(my_bitset), cpp_dump(my_complex); 67 | cpp_dump(my_optional, std::nullopt), cpp_dump(my_variant); 68 | 69 | std::clog << "\n// Combination" << std::endl; 70 | cpp_dump(vector_of_pairs); 71 | 72 | std::vector> some_huge_vector(100, std::vector(100)); 73 | std::vector> unsigned_int_vector(100, std::vector(100)); 74 | 75 | for (int i = 0; i < 100; ++i) { 76 | for (int j = 0; j < 100; ++j) { 77 | some_huge_vector[i][j] = ((i + 1) * 7 % 19 - 9) * ((j + 1) * 3 % 19 - 9); 78 | unsigned_int_vector[i][j] = std::abs(some_huge_vector[i][j]); 79 | } 80 | } 81 | 82 | std::clog << "\n// Manipulator Test" << std::endl; 83 | cpp_dump(some_huge_vector | cp::back() | cp::both_ends() | cp::dec(2)); 84 | cpp_dump(some_huge_vector | cp::dec(2) | cp::index()); 85 | } 86 | -------------------------------------------------------------------------------- /readme/user-defined-class-generic.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../cpp-dump.hpp" 5 | 6 | CPP_DUMP_DEFINE_EXPORT_OBJECT_GENERIC(i, str()); 7 | 8 | int main() { 9 | std::clog << std::endl; 10 | 11 | struct class_A { 12 | int i; 13 | std::string str() const { return std::to_string(i); } 14 | } my_class_A{10}; 15 | 16 | cpp_dump(my_class_A); 17 | 18 | std::clog << std::endl; 19 | } 20 | -------------------------------------------------------------------------------- /readme/user-defined-class-generic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philip82148/cpp-dump/aabd98dd8a4b5ae3f62cf12387a68a9f6591197e/readme/user-defined-class-generic.png -------------------------------------------------------------------------------- /readme/user-defined-class-ostream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../cpp-dump.hpp" 5 | 6 | struct class_A { 7 | int i; 8 | std::string str() const { return std::to_string(i); } 9 | }; 10 | 11 | std::ostream &operator<<(std::ostream &os, const class_A &a) { 12 | os << "class_A{ i= " << a.i << ", str()= \"" << a.str() << "\" }"; 13 | return os; 14 | } 15 | 16 | int main() { 17 | std::clog << std::endl; 18 | 19 | class_A my_class_A{10}; 20 | cpp_dump(my_class_A); 21 | 22 | std::clog << std::endl; 23 | } 24 | -------------------------------------------------------------------------------- /readme/user-defined-class-ostream.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philip82148/cpp-dump/aabd98dd8a4b5ae3f62cf12387a68a9f6591197e/readme/user-defined-class-ostream.png -------------------------------------------------------------------------------- /readme/user-defined-class.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../cpp-dump.hpp" 5 | 6 | struct class_A { 7 | int i; 8 | std::string str() const { return std::to_string(i); } 9 | }; 10 | CPP_DUMP_DEFINE_EXPORT_OBJECT(class_A, i, str()); 11 | 12 | int main() { 13 | std::clog << std::endl; 14 | 15 | class_A my_class_A{10}; 16 | cpp_dump(my_class_A); 17 | 18 | std::clog << std::endl; 19 | } 20 | -------------------------------------------------------------------------------- /readme/user-defined-class.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philip82148/cpp-dump/aabd98dd8a4b5ae3f62cf12387a68a9f6591197e/readme/user-defined-class.png -------------------------------------------------------------------------------- /readme/user-defined-enum-generic.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "../cpp-dump.hpp" 4 | 5 | CPP_DUMP_DEFINE_EXPORT_ENUM_GENERIC(member_a, member_b, member_c); 6 | 7 | int main() { 8 | std::clog << std::endl; 9 | 10 | enum class enum_A { member_a, member_b, member_c }; 11 | 12 | enum_A my_enum_A = enum_A::member_c; 13 | cpp_dump(my_enum_A); 14 | 15 | std::clog << std::endl; 16 | } 17 | -------------------------------------------------------------------------------- /readme/user-defined-enum-generic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philip82148/cpp-dump/aabd98dd8a4b5ae3f62cf12387a68a9f6591197e/readme/user-defined-enum-generic.png -------------------------------------------------------------------------------- /readme/user-defined-enum.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "../cpp-dump.hpp" 4 | 5 | enum class enum_A { member_a, member_b, member_c }; 6 | CPP_DUMP_DEFINE_EXPORT_ENUM(enum_A, enum_A::member_a, enum_A::member_b, enum_A::member_c); 7 | 8 | int main() { 9 | std::clog << std::endl; 10 | 11 | enum_A my_enum_A = enum_A::member_c; 12 | cpp_dump(my_enum_A); 13 | 14 | std::clog << std::endl; 15 | } 16 | -------------------------------------------------------------------------------- /readme/user-defined-enum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/philip82148/cpp-dump/aabd98dd8a4b5ae3f62cf12387a68a9f6591197e/readme/user-defined-enum.png -------------------------------------------------------------------------------- /test/clean_logs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -eu 2 | 3 | cd ./test/.. 4 | 5 | rm -rf ./test/logs 6 | -------------------------------------------------------------------------------- /test/color_indent_test.cmake: -------------------------------------------------------------------------------- 1 | if(NOT test_dir) 2 | message(FATAL_ERROR "Variable test_dir not defined") 3 | endif() 4 | 5 | if(NOT cmd_path) 6 | message(FATAL_ERROR "Variable cmd_path not defined") 7 | endif() 8 | 9 | if(NOT cmd_args) 10 | message(FATAL_ERROR "Variable cmd_args not defined") 11 | endif() 12 | 13 | include("${test_dir}/common.cmake") 14 | 15 | file(MAKE_DIRECTORY "${test_dir}/log") 16 | 17 | list(GET cmd_args 0 suffix) 18 | list(GET cmd_args 1 width) 19 | list(GET cmd_args 2 depth) 20 | list(GET cmd_args 3 es_style) 21 | set(log_file "${test_dir}/log/color_indent_${suffix}.log") 22 | set(txt_file "${test_dir}/txt/color_indent_${suffix}.txt") 23 | 24 | execute_process( 25 | COMMAND "${cmd_path}" "${width}" "${depth}" "${es_style}" 1 ERROR_VARIABLE error_contents COMMAND_ERROR_IS_FATAL ANY 26 | ) 27 | crlf_to_lf(error_contents) 28 | file(WRITE "${log_file}" "${error_contents}") 29 | diff_and_message("${log_file}" "${txt_file}" "${log_file} does not match ${txt_file} !") 30 | -------------------------------------------------------------------------------- /test/color_non_variable_test.cmake: -------------------------------------------------------------------------------- 1 | if(NOT test_dir) 2 | message(FATAL_ERROR "Variable test_dir not defined") 3 | endif() 4 | 5 | if(NOT cmd_path) 6 | message(FATAL_ERROR "Variable cmd_path not defined") 7 | endif() 8 | 9 | if(NOT cmd_args) 10 | message(FATAL_ERROR "Variable cmd_args not defined") 11 | endif() 12 | 13 | include("${test_dir}/common.cmake") 14 | 15 | file(MAKE_DIRECTORY "${test_dir}/log") 16 | 17 | list(GET cmd_args 0 suffix) 18 | list(GET cmd_args 1 es_style) 19 | set(log_file "${test_dir}/log/color_non_variable_${suffix}.log") 20 | set(txt_file "${test_dir}/txt/color_non_variable_${suffix}.txt") 21 | 22 | execute_process( 23 | COMMAND "${cmd_path}" "${es_style}" ERROR_FILE "${log_file}" COMMAND_ERROR_IS_FATAL ANY 24 | ) 25 | diff_and_message("${log_file}" "${txt_file}" "${log_file} does not match ${txt_file} !") 26 | -------------------------------------------------------------------------------- /test/color_rtti_test.cmake: -------------------------------------------------------------------------------- 1 | if(NOT test_dir) 2 | message(FATAL_ERROR "Variable test_dir not defined") 3 | endif() 4 | 5 | if(NOT cmd_path) 6 | message(FATAL_ERROR "Variable cmd_path not defined") 7 | endif() 8 | 9 | include("${test_dir}/common.cmake") 10 | 11 | file(MAKE_DIRECTORY "${test_dir}/log") 12 | 13 | set(log_file "${test_dir}/log/color_rtti.log") 14 | set(txt_file "${test_dir}/txt/color_rtti.txt") 15 | 16 | execute_process( 17 | COMMAND "${cmd_path}" ERROR_VARIABLE error_contents COMMAND_ERROR_IS_FATAL ANY 18 | ) 19 | string(REGEX REPLACE "struct${esc0x1b}\\[0m${esc0x1b}\\[38;2;139;191;139m ${esc0x1b}\\[0m${esc0x1b}\\[32m" "" error_contents "${error_contents}") 20 | string(REGEX REPLACE "${esc0x1b}\\[38;2;181;206;168m[^${esc0x1b}]*${esc0x1b}" "${esc0x1b}[38;2;181;206;168m314159265358979${esc0x1b}" error_contents "${error_contents}") 21 | file(WRITE "${log_file}" "${error_contents}") 22 | diff_and_message("${log_file}" "${txt_file}" "${log_file} does not match ${txt_file} !") 23 | -------------------------------------------------------------------------------- /test/color_rtti_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "../cpp-dump.hpp" 4 | 5 | namespace cp = cpp_dump; 6 | 7 | namespace ns { 8 | 9 | struct class_a {}; 10 | 11 | } // namespace ns 12 | 13 | int main() { 14 | CPP_DUMP_SET_OPTION( 15 | es_value, 16 | (cp::types::es_value_t{ 17 | "\x1b[02m", // log: dark 18 | "\x1b[38;2;86;154;214m", // expression: 19 | "\x1b[36m", // reserved: cyan 20 | "\x1b[38;2;181;206;168m", // number: 21 | "\x1b[38;2;215;152;61m", // character: 22 | "\x1b[38;2;203;186;113m", // escaped_char: 23 | "\x1b[38;2;150;150;150m", // op: dark2 24 | "\x1b[32m", // identifier: green 25 | "\x1b[38;2;156;220;254m", // member: light blue 26 | "\x1b[31m", // unsupported: red 27 | { 28 | "\x1b[33m", // bracket_by_depth[0]: yellow 29 | "\x1b[35m", // bracket_by_depth[1]: magenta 30 | }, 31 | "\x1b[38;2;139;191;139m", // class_op: white closer to green 32 | "\x1b[38;2;217;242;255m", // member_op: white closer to light blue 33 | "", // number_op: default 34 | }) 35 | ); 36 | CPP_DUMP_SET_OPTION(detailed_class_es, true); 37 | CPP_DUMP_SET_OPTION(detailed_member_es, true); 38 | CPP_DUMP_SET_OPTION(detailed_number_es, true); 39 | 40 | cpp_dump(typeid(void)); 41 | 42 | CPP_DUMP_SET_OPTION(max_line_width, 2000); 43 | 44 | std::type_index type_index1 = typeid(ns::class_a); 45 | cpp_dump(typeid(ns::class_a), type_index1); 46 | 47 | CPP_DUMP_SET_OPTION(max_line_width, 20); 48 | 49 | cpp_dump(typeid(ns::class_a), type_index1); 50 | 51 | CPP_DUMP_SET_OPTION(max_depth, 0); 52 | 53 | cpp_dump(typeid(ns::class_a), type_index1); 54 | } 55 | -------------------------------------------------------------------------------- /test/color_std_version_test.cmake: -------------------------------------------------------------------------------- 1 | if(NOT test_dir) 2 | message(FATAL_ERROR "Variable test_dir not defined") 3 | endif() 4 | 5 | if(NOT cmd_path) 6 | message(FATAL_ERROR "Variable cmd_path not defined") 7 | endif() 8 | 9 | if(NOT std_version) 10 | message(FATAL_ERROR "Variable std_version not defined") 11 | endif() 12 | 13 | if(NOT compiler_id) 14 | message(FATAL_ERROR "Variable compiler_id not defined") 15 | endif() 16 | 17 | include("${test_dir}/common.cmake") 18 | 19 | file(MAKE_DIRECTORY "${test_dir}/log") 20 | 21 | if(compiler_id MATCHES "GNU") 22 | set(log_file "${test_dir}/log/color_std_version_${std_version}_gnu.log") 23 | set(txt_file "${test_dir}/txt/color_std_version_${std_version}_gnu.txt") 24 | elseif(compiler_id MATCHES "MSVC") 25 | set(log_file "${test_dir}/log/color_std_version_${std_version}_msvc.log") 26 | set(txt_file "${test_dir}/txt/color_std_version_${std_version}_msvc.txt") 27 | else() 28 | set(log_file "${test_dir}/log/color_std_version_${std_version}_clang.log") 29 | set(txt_file "${test_dir}/txt/color_std_version_${std_version}_clang.txt") 30 | endif() 31 | 32 | execute_process( 33 | COMMAND "${cmd_path}" ERROR_VARIABLE error_contents COMMAND_ERROR_IS_FATAL ANY 34 | ) 35 | string(REGEX REPLACE "\"[^}]*\\.cpp" "\"" error_contents "${error_contents}") 36 | file(WRITE "${log_file}" "${error_contents}") 37 | diff_and_message("${log_file}" "${txt_file}" "${log_file} does not match ${txt_file} !") 38 | -------------------------------------------------------------------------------- /test/color_std_version_test.cpp: -------------------------------------------------------------------------------- 1 | #if __cplusplus >= 202002L 2 | #if !defined(__clang__) 3 | #include 4 | #else 5 | #include 6 | 7 | struct source_location { 8 | static std::string current() { return "The compiler doesn't support this class."; }; 9 | }; 10 | #endif 11 | #endif 12 | 13 | #include "../cpp-dump.hpp" 14 | 15 | // These are often used to write code faster in competitive programming. 16 | // This is the test for it. 17 | #define rep(i, n) for (int i = 0; i < (int)(n); i++) 18 | using namespace std; 19 | namespace cp = cpp_dump; 20 | 21 | int main() { 22 | CPP_DUMP_SET_OPTION( 23 | es_value, 24 | (cp::types::es_value_t{ 25 | "\x1b[02m", // log: dark 26 | "\x1b[38;2;86;154;214m", // expression: 27 | "\x1b[36m", // reserved: cyan 28 | "\x1b[38;2;181;206;168m", // number: 29 | "\x1b[38;2;215;152;61m", // character: 30 | "\x1b[38;2;203;186;113m", // escaped_char: 31 | "\x1b[38;2;150;150;150m", // op: dark2 32 | "\x1b[32m", // identifier: green 33 | "\x1b[38;2;156;220;254m", // member: light blue 34 | "\x1b[31m", // unsupported: red 35 | { 36 | "\x1b[33m", // bracket_by_depth[0]: yellow 37 | "\x1b[35m", // bracket_by_depth[1]: magenta 38 | }, 39 | "\x1b[38;2;139;191;139m", // class_op: white closer to green 40 | "\x1b[38;2;217;242;255m", // member_op: white closer to light blue 41 | "", // number_op: default 42 | }) 43 | ); 44 | 45 | // 46 | // 47 | // 48 | // 49 | // 50 | // 51 | // 52 | // 53 | // 54 | // 55 | // 56 | // 57 | // 58 | // 59 | // 60 | // 61 | // 62 | // 63 | // 64 | // 65 | // 66 | // 67 | // 68 | // 69 | // 70 | // 71 | // 72 | // 73 | // 74 | // 75 | // 76 | // 77 | // 78 | // 79 | // 80 | // 81 | // 82 | // 83 | // 84 | // 85 | // 86 | // 87 | // 88 | // 89 | // 90 | // 91 | // 92 | // 93 | // 94 | // 95 | // 96 | 97 | #if __cplusplus >= 202002L 98 | CPP_DUMP_SET_OPTION(max_line_width, 2000); 99 | 100 | cpp_dump(source_location::current()); 101 | 102 | CPP_DUMP_SET_OPTION(max_line_width, 20); 103 | 104 | cpp_dump(source_location::current()); 105 | 106 | CPP_DUMP_SET_OPTION(max_depth, 0); 107 | 108 | cpp_dump(source_location::current()); 109 | #endif 110 | } 111 | -------------------------------------------------------------------------------- /test/color_variable_test.cmake: -------------------------------------------------------------------------------- 1 | if(NOT test_dir) 2 | message(FATAL_ERROR "Variable test_dir not defined") 3 | endif() 4 | 5 | if(NOT cmd_path) 6 | message(FATAL_ERROR "Variable cmd_path not defined") 7 | endif() 8 | 9 | if(NOT compiler_id) 10 | message(FATAL_ERROR "Variable compiler_id not defined") 11 | endif() 12 | 13 | include("${test_dir}/common.cmake") 14 | 15 | file(MAKE_DIRECTORY "${test_dir}/log") 16 | 17 | list(GET cmd_args 0 suffix) 18 | list(GET cmd_args 1 es_style) 19 | 20 | # os-dependent 21 | if(UNIX AND NOT APPLE) 22 | set(log_file "${test_dir}/log/color_variable_linux_${suffix}.log") 23 | set(txt_file "${test_dir}/txt/color_variable_linux_${suffix}.txt") 24 | elseif(APPLE) 25 | set(log_file "${test_dir}/log/color_variable_apple_${suffix}.log") 26 | set(txt_file "${test_dir}/txt/color_variable_apple_${suffix}.txt") 27 | else() 28 | set(log_file "${test_dir}/log/color_variable_win32_${suffix}.log") 29 | set(txt_file "${test_dir}/txt/color_variable_win32_${suffix}.txt") 30 | endif() 31 | 32 | execute_process( 33 | COMMAND "${cmd_path}" 0 "${es_style}" 1 ERROR_FILE "${log_file}" COMMAND_ERROR_IS_FATAL ANY 34 | ) 35 | diff_and_message("${log_file}" "${txt_file}" "${log_file} does not match ${txt_file} !") 36 | 37 | # compiler-dependent 38 | if(compiler_id MATCHES "GNU") 39 | set(log_file "${test_dir}/log/color_variable_gnu_${suffix}.log") 40 | set(txt_file "${test_dir}/txt/color_variable_gnu_${suffix}.txt") 41 | elseif(compiler_id MATCHES "MSVC") 42 | set(log_file "${test_dir}/log/color_variable_msvc_${suffix}.log") 43 | set(txt_file "${test_dir}/txt/color_variable_msvc_${suffix}.txt") 44 | else() 45 | set(log_file "${test_dir}/log/color_variable_clang_${suffix}.log") 46 | set(txt_file "${test_dir}/txt/color_variable_clang_${suffix}.txt") 47 | endif() 48 | 49 | execute_process( 50 | COMMAND "${cmd_path}" 1 "${es_style}" 1 ERROR_FILE "${log_file}" COMMAND_ERROR_IS_FATAL ANY 51 | ) 52 | diff_and_message("${log_file}" "${txt_file}" "${log_file} does not match ${txt_file} !") 53 | -------------------------------------------------------------------------------- /test/common.cmake: -------------------------------------------------------------------------------- 1 | string(ASCII 27 esc0x1b) 2 | 3 | function(diff_and_message log_file txt_file error_message) 4 | if(WIN32) 5 | string(REPLACE "/" "\\" log_file "${log_file}") 6 | string(REPLACE "/" "\\" txt_file "${txt_file}") 7 | execute_process( 8 | COMMAND fc.exe "${log_file}" "${txt_file}" RESULT_VARIABLE not_successful OUTPUT_VARIABLE output 9 | ) 10 | else() 11 | execute_process(COMMAND diff -u "${log_file}" "${txt_file}" RESULT_VARIABLE not_successful OUTPUT_VARIABLE output) 12 | endif() 13 | 14 | if(not_successful) 15 | if(WIN32) 16 | file(READ "${log_file}" output) 17 | endif() 18 | 19 | message(SEND_ERROR "${error_message}\n${output}") 20 | endif() 21 | endfunction() 22 | 23 | macro(crlf_to_lf var) 24 | string(REGEX REPLACE "\r\n" "\n" "${var}" "${${var}}") 25 | endmacro() 26 | 27 | macro(remove_es var) 28 | string(REGEX REPLACE "${esc0x1b}\\[[^m]*m" "" "${var}" "${${var}}") 29 | endmacro() 30 | -------------------------------------------------------------------------------- /test/copy_txts.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -eu 2 | 3 | cd ./test/.. 4 | 5 | for f in ./test/log/*.log; do 6 | basename=$(basename $f .log) 7 | cp $f "./test/txt/${basename}.txt" 8 | done 9 | -------------------------------------------------------------------------------- /test/dump_indent_test.cmake: -------------------------------------------------------------------------------- 1 | if(NOT test_dir) 2 | message(FATAL_ERROR "Variable test_dir not defined") 3 | endif() 4 | 5 | if(NOT cmd_path) 6 | message(FATAL_ERROR "Variable cmd_path not defined") 7 | endif() 8 | 9 | if(NOT cmd_args) 10 | message(FATAL_ERROR "Variable cmd_args not defined") 11 | endif() 12 | 13 | include("${test_dir}/common.cmake") 14 | 15 | file(MAKE_DIRECTORY "${test_dir}/log") 16 | 17 | list(GET cmd_args 0 suffix) 18 | list(GET cmd_args 1 width) 19 | list(GET cmd_args 2 depth) 20 | set(log_file "${test_dir}/log/dump_indent_${suffix}.log") 21 | set(txt_file "${test_dir}/txt/dump_indent_${suffix}.txt") 22 | 23 | # no color 24 | execute_process( 25 | COMMAND "${cmd_path}" "${width}" "${depth}" 0 0 ERROR_VARIABLE error_contents COMMAND_ERROR_IS_FATAL ANY 26 | ) 27 | crlf_to_lf(error_contents) 28 | file(WRITE "${log_file}" "${error_contents}") 29 | diff_and_message("${log_file}" "${txt_file}" "${log_file} does not match ${txt_file} !") 30 | 31 | # original 32 | execute_process( 33 | COMMAND "${cmd_path}" "${width}" "${depth}" 1 0 ERROR_VARIABLE error_contents COMMAND_ERROR_IS_FATAL ANY 34 | ) 35 | remove_es(error_contents) 36 | crlf_to_lf(error_contents) 37 | file(WRITE "${log_file}" "${error_contents}") 38 | diff_and_message("${log_file}" "${txt_file}" "${log_file} with color (original) does not match ${txt_file} !") 39 | 40 | # by_syntax 41 | execute_process( 42 | COMMAND "${cmd_path}" "${width}" "${depth}" 2 0 ERROR_VARIABLE error_contents COMMAND_ERROR_IS_FATAL ANY 43 | ) 44 | remove_es(error_contents) 45 | crlf_to_lf(error_contents) 46 | file(WRITE "${log_file}" "${error_contents}") 47 | diff_and_message("${log_file}" "${txt_file}" "${log_file} with color (by_syntax) does not match ${txt_file} !") 48 | -------------------------------------------------------------------------------- /test/dump_non_variable_test.cmake: -------------------------------------------------------------------------------- 1 | if(NOT test_dir) 2 | message(FATAL_ERROR "Variable test_dir not defined") 3 | endif() 4 | 5 | if(NOT cmd_path) 6 | message(FATAL_ERROR "Variable cmd_path not defined") 7 | endif() 8 | 9 | include("${test_dir}/common.cmake") 10 | 11 | file(MAKE_DIRECTORY "${test_dir}/log") 12 | 13 | set(log_file "${test_dir}/log/dump_non_variable.log") 14 | set(txt_file "${test_dir}/txt/dump_non_variable.txt") 15 | 16 | # no color 17 | execute_process( 18 | COMMAND "${cmd_path}" 0 ERROR_FILE "${log_file}" COMMAND_ERROR_IS_FATAL ANY 19 | ) 20 | diff_and_message("${log_file}" "${txt_file}" "${log_file} does not match ${txt_file} !") 21 | 22 | # original 23 | execute_process( 24 | COMMAND "${cmd_path}" 1 ERROR_VARIABLE error_contents COMMAND_ERROR_IS_FATAL ANY 25 | ) 26 | remove_es(error_contents) 27 | file(WRITE "${log_file}" "${error_contents}") 28 | diff_and_message("${log_file}" "${txt_file}" "${log_file} with color (original) does not match ${txt_file} !") 29 | 30 | # by_syntax 31 | execute_process( 32 | COMMAND "${cmd_path}" 2 ERROR_FILE "${log_file}" COMMAND_ERROR_IS_FATAL ANY 33 | ) 34 | remove_es(error_contents) 35 | file(WRITE "${log_file}" "${error_contents}") 36 | diff_and_message("${log_file}" "${txt_file}" "${log_file} with color (by_syntax) does not match ${txt_file} !") 37 | -------------------------------------------------------------------------------- /test/dump_variable_test.cmake: -------------------------------------------------------------------------------- 1 | if(NOT test_dir) 2 | message(FATAL_ERROR "Variable test_dir not defined") 3 | endif() 4 | 5 | if(NOT cmd_path) 6 | message(FATAL_ERROR "Variable cmd_path not defined") 7 | endif() 8 | 9 | if(NOT compiler_id) 10 | message(FATAL_ERROR "Variable compiler_id not defined") 11 | endif() 12 | 13 | include("${test_dir}/common.cmake") 14 | 15 | file(MAKE_DIRECTORY "${test_dir}/log") 16 | 17 | # os-dependent 18 | if(UNIX AND NOT APPLE) 19 | set(log_file "${test_dir}/log/dump_variable_linux.log") 20 | set(txt_file "${test_dir}/txt/dump_variable_linux.txt") 21 | elseif(APPLE) 22 | set(log_file "${test_dir}/log/dump_variable_apple.log") 23 | set(txt_file "${test_dir}/txt/dump_variable_apple.txt") 24 | else() 25 | set(log_file "${test_dir}/log/dump_variable_win32.log") 26 | set(txt_file "${test_dir}/txt/dump_variable_win32.txt") 27 | endif() 28 | 29 | # no color 30 | execute_process( 31 | COMMAND "${cmd_path}" 0 0 0 ERROR_FILE "${log_file}" COMMAND_ERROR_IS_FATAL ANY 32 | ) 33 | diff_and_message("${log_file}" "${txt_file}" "${log_file} with color (original) does not match ${txt_file} !") 34 | 35 | # original 36 | execute_process( 37 | COMMAND "${cmd_path}" 0 1 0 ERROR_VARIABLE error_contents COMMAND_ERROR_IS_FATAL ANY 38 | ) 39 | remove_es(error_contents) 40 | file(WRITE "${log_file}" "${error_contents}") 41 | diff_and_message("${log_file}" "${txt_file}" "${log_file} with color (original) does not match ${txt_file} !") 42 | 43 | # by_syntax 44 | execute_process( 45 | COMMAND "${cmd_path}" 0 2 0 ERROR_VARIABLE error_contents COMMAND_ERROR_IS_FATAL ANY 46 | ) 47 | remove_es(error_contents) 48 | file(WRITE "${log_file}" "${error_contents}") 49 | diff_and_message("${log_file}" "${txt_file}" "${log_file} with color (by_syntax) does not match ${txt_file} !") 50 | 51 | # compiler-dependent 52 | if(compiler_id MATCHES "GNU") 53 | set(log_file "${test_dir}/log/dump_variable_gnu.log") 54 | set(txt_file "${test_dir}/txt/dump_variable_gnu.txt") 55 | elseif(compiler_id MATCHES "MSVC") 56 | set(log_file "${test_dir}/log/dump_variable_msvc.log") 57 | set(txt_file "${test_dir}/txt/dump_variable_msvc.txt") 58 | else() 59 | set(log_file "${test_dir}/log/dump_variable_clang.log") 60 | set(txt_file "${test_dir}/txt/dump_variable_clang.txt") 61 | endif() 62 | 63 | # no color 64 | execute_process( 65 | COMMAND "${cmd_path}" 1 0 0 ERROR_FILE "${log_file}" COMMAND_ERROR_IS_FATAL ANY 66 | ) 67 | diff_and_message("${log_file}" "${txt_file}" "${log_file} does not match ${txt_file} !") 68 | 69 | # with color 70 | execute_process( 71 | COMMAND "${cmd_path}" 1 1 0 ERROR_VARIABLE error_contents COMMAND_ERROR_IS_FATAL ANY 72 | ) 73 | remove_es(error_contents) 74 | file(WRITE "${log_file}" "${error_contents}") 75 | diff_and_message("${log_file}" "${txt_file}" "${log_file} with color (original) does not match ${txt_file} !") 76 | 77 | # by_syntax 78 | execute_process( 79 | COMMAND "${cmd_path}" 1 2 0 ERROR_VARIABLE error_contents COMMAND_ERROR_IS_FATAL ANY 80 | ) 81 | remove_es(error_contents) 82 | file(WRITE "${log_file}" "${error_contents}") 83 | diff_and_message("${log_file}" "${txt_file}" "${log_file} with color (by_syntax) does not match ${txt_file} !") 84 | -------------------------------------------------------------------------------- /test/dump_variable_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | // 6 | #include "../cpp-dump.hpp" 7 | 8 | // These are often used to write code faster in competitive programming. 9 | // This is the test for it. 10 | #define rep(i, n) for (int i = 0; i < (int)(n); i++) 11 | using namespace std; 12 | namespace cp = cpp_dump; 13 | 14 | CPP_DUMP_DEFINE_EXPORT_OBJECT_GENERIC(member_var, member_func()); 15 | CPP_DUMP_DEFINE_EXPORT_ENUM_GENERIC(member1, member2); 16 | 17 | namespace ns { 18 | 19 | template 20 | struct template_class { 21 | int member_var = 5; 22 | std::string member_func() const { return "This is a member_func."; } 23 | }; 24 | 25 | } // namespace ns 26 | 27 | int main(int argc, char *argv[]) { 28 | if (argc != 4) return 1; 29 | bool compiler_dependent = static_cast(stoi(argv[1])); 30 | auto es_style_ = (array{ 31 | cp::types::es_style_t::no_es, 32 | cp::types::es_style_t::original, 33 | cp::types::es_style_t::by_syntax, 34 | }[stoi(argv[2])]); 35 | bool detailed_es = es_style_ == cp::types::es_style_t::by_syntax; 36 | bool color_test = stoi(argv[3]); 37 | 38 | CPP_DUMP_SET_OPTION(es_style, es_style_); 39 | CPP_DUMP_SET_OPTION(detailed_class_es, detailed_es); 40 | CPP_DUMP_SET_OPTION(detailed_member_es, detailed_es); 41 | CPP_DUMP_SET_OPTION(detailed_number_es, detailed_es); 42 | 43 | if (color_test) 44 | CPP_DUMP_SET_OPTION( 45 | es_value, 46 | (cp::types::es_value_t{ 47 | "\x1b[02m", // log: dark 48 | "\x1b[38;2;86;154;214m", // expression: 49 | "\x1b[36m", // reserved: cyan 50 | "\x1b[38;2;181;206;168m", // number: 51 | "\x1b[38;2;215;152;61m", // character: 52 | "\x1b[38;2;203;186;113m", // escaped_char: 53 | "\x1b[38;2;150;150;150m", // op: dark2 54 | "\x1b[32m", // identifier: green 55 | "\x1b[38;2;156;220;254m", // member: light blue 56 | "\x1b[31m", // unsupported: red 57 | { 58 | "\x1b[33m", // bracket_by_depth[0]: yellow 59 | "\x1b[35m", // bracket_by_depth[1]: magenta 60 | }, 61 | "\x1b[38;2;139;191;139m", // class_op: white closer to green 62 | "\x1b[38;2;217;242;255m", // member_op: white closer to light blue 63 | "", // number_op: default 64 | }) 65 | ); 66 | 67 | if (compiler_dependent) { 68 | class original_error : public logic_error { 69 | using logic_error::logic_error; 70 | } original_error1("This is an original error."); 71 | 72 | struct original_class { 73 | int member_var = 5; 74 | std::string member_func() const { return "This is a member_func."; } 75 | }; 76 | 77 | enum original_enum { member1, member2, member3 }; 78 | enum class original_scoped_enum { member1, member2, member3 }; 79 | 80 | struct unsupported_original_class { 81 | int member_var = 5; 82 | std::string member_func() { return "This is a member_func."; } 83 | }; 84 | 85 | cpp_dump::_detail::export_enum_generic( 86 | original_scoped_enum::member1, 87 | "", 88 | 0, 89 | 0, 90 | false, 91 | cpp_dump::_detail::export_command::default_command 92 | ); 93 | 94 | cpp_dump(original_error1); 95 | cpp_dump(ns::template_class>()); 96 | cpp_dump(original_class()); 97 | cpp_dump(original_enum::member1, original_enum::member2, original_enum::member3); 98 | cpp_dump( 99 | original_scoped_enum::member1, original_scoped_enum::member2, original_scoped_enum::member3 100 | ); 101 | cpp_dump(unsupported_original_class()); 102 | } else { 103 | // pointer 104 | const void *void_ptr = (void *)0x7ffd06586204; 105 | cpp_dump(void_ptr); 106 | 107 | // addr 108 | const int *int_ptr = reinterpret_cast(void_ptr); 109 | const int **int_ptr_ptr = &int_ptr; 110 | unique_ptr int_ptr_ptr_ptr(new const int **(int_ptr_ptr)); 111 | cpp_dump(int_ptr | cp::addr()); 112 | cpp_dump(int_ptr_ptr | cp::addr(1)); 113 | cpp_dump(int_ptr_ptr_ptr | cp::addr(2)); 114 | 115 | // unordered 116 | cpp_dump((unordered_map{{4, 6}, {2, 6}, {4, 3}})); 117 | 118 | unordered_multimap unordered_multimap1{ 119 | {'c', 30}, 120 | {'a', 10}, 121 | {'b', 20}, 122 | {'a', 40}, 123 | }; 124 | cpp_dump(unordered_multimap1); 125 | 126 | cpp_dump((unordered_set{3, 1, 4, 1, 5})); 127 | 128 | unordered_multiset unordered_multiset1; 129 | unordered_multiset1.insert(3); 130 | unordered_multiset1.insert(1); 131 | unordered_multiset1.insert(4); 132 | unordered_multiset1.insert(1); 133 | cpp_dump(unordered_multiset1); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /test/log_label_test.cmake: -------------------------------------------------------------------------------- 1 | if(NOT test_dir) 2 | message(FATAL_ERROR "Variable test_dir not defined") 3 | endif() 4 | 5 | if(NOT cmd_path) 6 | message(FATAL_ERROR "Variable cmd_path not defined") 7 | endif() 8 | 9 | include("${test_dir}/common.cmake") 10 | 11 | file(MAKE_DIRECTORY "${test_dir}/log") 12 | 13 | set(log_file "${test_dir}/log/log_label_test.log") 14 | set(txt_file "${test_dir}/txt/log_label_test.txt") 15 | 16 | # no color 17 | execute_process( 18 | COMMAND "${cmd_path}" 0 0 ERROR_VARIABLE error_contents COMMAND_ERROR_IS_FATAL ANY 19 | ) 20 | 21 | if(WIN32) 22 | string(REGEX REPLACE "\\\\" "/" error_contents "${error_contents}") 23 | endif() 24 | 25 | file(WRITE "${log_file}" "${error_contents}") 26 | diff_and_message("${log_file}" "${txt_file}" "${log_file} does not match ${txt_file} !") 27 | 28 | # original 29 | execute_process( 30 | COMMAND "${cmd_path}" 0 1 ERROR_VARIABLE error_contents COMMAND_ERROR_IS_FATAL ANY 31 | ) 32 | 33 | if(WIN32) 34 | string(REGEX REPLACE "\\\\" "/" error_contents "${error_contents}") 35 | endif() 36 | 37 | remove_es(error_contents) 38 | file(WRITE "${log_file}" "${error_contents}") 39 | diff_and_message("${log_file}" "${txt_file}" "${log_file} with color (original) does not match ${txt_file} !") 40 | 41 | # by_syntax 42 | execute_process( 43 | COMMAND "${cmd_path}" 0 2 ERROR_VARIABLE error_contents COMMAND_ERROR_IS_FATAL ANY 44 | ) 45 | 46 | if(WIN32) 47 | string(REGEX REPLACE "\\\\" "/" error_contents "${error_contents}") 48 | endif() 49 | 50 | remove_es(error_contents) 51 | file(WRITE "${log_file}" "${error_contents}") 52 | diff_and_message("${log_file}" "${txt_file}" "${log_file} with color (by_syntax) does not match ${txt_file} !") 53 | -------------------------------------------------------------------------------- /test/log_label_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "../cpp-dump.hpp" 7 | 8 | // 9 | using namespace std; 10 | namespace cp = cpp_dump; 11 | 12 | #define PRINT(x) (x), (clog << #x ";" << endl) 13 | 14 | int main(int argc, char *argv[]) { 15 | if (argc != 3) return 1; 16 | bool path_dependent = static_cast(stoi(argv[1])); 17 | auto es_style_ = (array{ 18 | cp::types::es_style_t::no_es, 19 | cp::types::es_style_t::original, 20 | cp::types::es_style_t::by_syntax, 21 | }[stoi(argv[2])]); 22 | 23 | CPP_DUMP_SET_OPTION(es_style, es_style_); 24 | 25 | vector> vec{{3, 1, 4}, {1, 5, 9}}; 26 | 27 | clog << "// default" << endl; 28 | cpp_dump(vec); 29 | 30 | clog << "// line()" << endl; 31 | PRINT(cp::options::log_label_func = cp::log_label::line()); 32 | cpp_dump(vec); 33 | cpp_dump(vec); 34 | cpp_dump(vec); 35 | PRINT(cp::options::log_label_func = cp::log_label::line(true)); 36 | cpp_dump(vec); 37 | cpp_dump(vec); 38 | cpp_dump(vec); 39 | 40 | clog << "// basename()" << endl; 41 | PRINT(cp::options::log_label_func = cp::log_label::basename()); 42 | cpp_dump(vec); 43 | cpp_dump(vec); 44 | cpp_dump(vec); 45 | PRINT(cp::options::log_label_func = cp::log_label::basename(true)); 46 | cpp_dump(vec); 47 | cpp_dump(vec); 48 | cpp_dump(vec); 49 | 50 | clog << "// filename()" << endl; 51 | PRINT(cp::options::log_label_func = cp::log_label::filename()); 52 | cpp_dump(vec); 53 | cpp_dump(vec); 54 | cpp_dump(vec); 55 | PRINT(cp::options::log_label_func = cp::log_label::filename(true)); 56 | cpp_dump(vec); 57 | cpp_dump(vec); 58 | cpp_dump(vec); 59 | 60 | if (path_dependent) { 61 | clog << "// fullpath()" << endl; 62 | PRINT(cp::options::log_label_func = cp::log_label::fullpath(0)); 63 | cpp_dump(vec); 64 | cpp_dump(vec); 65 | cpp_dump(vec); 66 | PRINT(cp::options::log_label_func = cp::log_label::fullpath(0, false, 33)); 67 | cpp_dump(vec); 68 | cpp_dump(vec); 69 | cpp_dump(vec); 70 | PRINT(cp::options::log_label_func = cp::log_label::fullpath(0, true, 33)); 71 | cpp_dump(vec); 72 | cpp_dump(vec); 73 | cpp_dump(vec); 74 | 75 | clog << "// fixed_length()" << endl; 76 | PRINT(cp::options::log_label_func = cp::log_label::fixed_length(0, 0, 0)); 77 | cpp_dump(vec); 78 | cpp_dump(vec); 79 | cpp_dump(vec); 80 | PRINT(cp::options::log_label_func = cp::log_label::fixed_length(0, 0, 0, true)); 81 | cpp_dump(vec); 82 | cpp_dump(vec); 83 | cpp_dump(vec); 84 | PRINT(cp::options::log_label_func = cp::log_label::fixed_length(0, 0, 33)); 85 | cpp_dump(vec); 86 | cpp_dump(vec); 87 | cpp_dump(vec); 88 | PRINT(cp::options::log_label_func = cp::log_label::fixed_length(0, 0, 33, true)); 89 | cpp_dump(vec); 90 | cpp_dump(vec); 91 | cpp_dump(vec); 92 | PRINT(cp::options::log_label_func = cp::log_label::fixed_length(0, 40, 33, false)); 93 | cpp_dump(vec); 94 | cpp_dump(vec); 95 | cpp_dump(vec); 96 | PRINT(cp::options::log_label_func = cp::log_label::fixed_length(0, 40, 33, true)); 97 | cpp_dump(vec); 98 | cpp_dump(vec); 99 | cpp_dump(vec); 100 | } 101 | 102 | clog << "// line()" << endl; 103 | PRINT(cp::options::log_label_func = cp::log_label::line(false, 40)); 104 | cpp_dump(vec); 105 | cpp_dump(vec); 106 | cpp_dump(vec); 107 | PRINT(cp::options::log_label_func = cp::log_label::line(true, 40)); 108 | cpp_dump(vec); 109 | cpp_dump(vec); 110 | cpp_dump(vec); 111 | 112 | clog << "// basename()" << endl; 113 | PRINT(cp::options::log_label_func = cp::log_label::basename(false, 40)); 114 | cpp_dump(vec); 115 | cpp_dump(vec); 116 | cpp_dump(vec); 117 | PRINT(cp::options::log_label_func = cp::log_label::basename(true, 40)); 118 | cpp_dump(vec); 119 | cpp_dump(vec); 120 | cpp_dump(vec); 121 | 122 | clog << "// filename()" << endl; 123 | PRINT(cp::options::log_label_func = cp::log_label::filename(false, 40)); 124 | cpp_dump(vec); 125 | cpp_dump(vec); 126 | cpp_dump(vec); 127 | PRINT(cp::options::log_label_func = cp::log_label::filename(true, 40)); 128 | cpp_dump(vec); 129 | cpp_dump(vec); 130 | cpp_dump(vec); 131 | 132 | if (path_dependent) { 133 | clog << "// fullpath()" << endl; 134 | PRINT(cp::options::log_label_func = cp::log_label::fullpath(33, false, 40)); 135 | cpp_dump(vec); 136 | cpp_dump(vec); 137 | cpp_dump(vec); 138 | PRINT(cp::options::log_label_func = cp::log_label::fullpath(33, true, 40)); 139 | cpp_dump(vec); 140 | cpp_dump(vec); 141 | cpp_dump(vec); 142 | } 143 | 144 | clog << "// fixed_length()" << endl; 145 | PRINT(cp::options::log_label_func = cp::log_label::fixed_length(0, 40, 0)); 146 | cpp_dump(vec); 147 | cpp_dump(vec); 148 | cpp_dump(vec); 149 | if (path_dependent) { 150 | PRINT(cp::options::log_label_func = cp::log_label::fixed_length(40, 50, 33, false)); 151 | cpp_dump(vec); 152 | cpp_dump(vec); 153 | cpp_dump(vec); 154 | PRINT(cp::options::log_label_func = cp::log_label::fixed_length(40, 50, 33, true)); 155 | cpp_dump(vec); 156 | cpp_dump(vec); 157 | cpp_dump(vec); 158 | } 159 | PRINT(cp::options::log_label_func = cp::log_label::fixed_length(0, 40, 0, true)); 160 | cpp_dump(vec); 161 | cpp_dump(vec); 162 | cpp_dump(vec); 163 | } 164 | -------------------------------------------------------------------------------- /test/odr_test.cpp: -------------------------------------------------------------------------------- 1 | #include "./odr_test.hpp" 2 | 3 | #include "../cpp-dump.hpp" 4 | 5 | void odr_test() { cpp_dump(class_a(), class_b(), enum_a::s); } 6 | -------------------------------------------------------------------------------- /test/odr_test.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "../cpp-dump.hpp" 4 | 5 | enum class enum_a { s, k, l }; 6 | 7 | struct class_a { 8 | int int_a = 5; 9 | std::string a_str() const { return std::to_string(int_a); } 10 | }; 11 | 12 | struct class_b { 13 | int int_b; 14 | std::string b_str() const { return std::to_string(int_b); } 15 | }; 16 | 17 | CPP_DUMP_DEFINE_EXPORT_ENUM(enum_a, enum_a::s, enum_a::k); 18 | CPP_DUMP_DEFINE_EXPORT_OBJECT(class_a, int_a, a_str()); 19 | CPP_DUMP_DEFINE_EXPORT_OBJECT_GENERIC(int_b, b_str()); 20 | CPP_DUMP_SET_OPTION_GLOBAL(max_line_width, 100); 21 | CPP_DUMP_SET_OPTION_GLOBAL(max_depth, 5); 22 | CPP_DUMP_SET_OPTION_GLOBAL(max_iteration_count, 20); 23 | CPP_DUMP_SET_OPTION_GLOBAL(enable_asterisk, false); 24 | CPP_DUMP_SET_OPTION_GLOBAL(print_expr, true); 25 | CPP_DUMP_SET_OPTION_GLOBAL(log_label_func, cpp_dump::log_label::filename()); 26 | CPP_DUMP_SET_OPTION_GLOBAL(es_style, cpp_dump::types::es_style_t::by_syntax); 27 | CPP_DUMP_SET_OPTION_GLOBAL( 28 | cont_indent_style, cpp_dump::types::cont_indent_style_t::when_non_tuples_nested 29 | ); 30 | 31 | void odr_test(); 32 | -------------------------------------------------------------------------------- /test/readme_test.cmake: -------------------------------------------------------------------------------- 1 | cmake_policy(SET CMP0057 NEW) 2 | 3 | if(NOT test_dir) 4 | message(FATAL_ERROR "Variable test_dir not defined") 5 | endif() 6 | 7 | if(NOT cmd_path) 8 | message(FATAL_ERROR "Variable cmd_path not defined") 9 | endif() 10 | 11 | if(NOT compiler_id) 12 | message(FATAL_ERROR "Variable compiler_id not defined") 13 | endif() 14 | 15 | if(NOT basename) 16 | message(FATAL_ERROR "Variable basename not defined") 17 | endif() 18 | 19 | include("${test_dir}/common.cmake") 20 | 21 | file(MAKE_DIRECTORY "${test_dir}/log") 22 | 23 | set(log_file "${test_dir}/log/readme_${basename}.log") 24 | set(txt_file "${test_dir}/txt/readme_${basename}.txt") 25 | 26 | execute_process( 27 | COMMAND "${cmd_path}" ERROR_VARIABLE error_contents COMMAND_ERROR_IS_FATAL ANY 28 | ) 29 | 30 | set(raw_address_file supports-various-types;customizable-colors;no-es;formatting-with-manipulators;test-code) 31 | set(auto_classname_file user-defined-class-generic;user-defined-enum-generic) 32 | 33 | if("${basename}" IN_LIST raw_address_file) 34 | # Do not remove escape sequences but remove raw addresses. 35 | if("${basename}" STREQUAL no-es) 36 | string(REGEX REPLACE " (0x[0-9a-f]+|00[0-9A-F]+)," " 0x7fffffffffff," error_contents "${error_contents}") 37 | else() 38 | string(REGEX REPLACE "${esc0x1b}\\[32m(0x[0-9a-f]+|00[0-9A-F]+)${esc0x1b}\\[0m" "${esc0x1b}[32m0x7fffffffffff${esc0x1b}[0m" error_contents "${error_contents}") 39 | endif() 40 | elseif("${basename}" IN_LIST auto_classname_file) 41 | string(REGEX REPLACE "main[^:]*::" "" error_contents "${error_contents}") 42 | endif() 43 | 44 | file(WRITE "${log_file}" "${error_contents}") 45 | diff_and_message("${log_file}" "${txt_file}" "${log_file} does not match ${txt_file} !") 46 | -------------------------------------------------------------------------------- /test/static_test.cpp: -------------------------------------------------------------------------------- 1 | #include "../cpp-dump.hpp" 2 | #include "./odr_test.hpp" 3 | 4 | template 5 | constexpr bool check_iota(Args... args) { 6 | int x = 0; 7 | return (... && (args == x--)); 8 | } 9 | 10 | #define MINUS(x) -x 11 | #define EXPAND_VA(...) _p_CPP_DUMP_EXPAND_VA(MINUS, __VA_ARGS__) 12 | 13 | #define TO_16 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 14 | 15 | int main() { 16 | // for ODR 17 | odr_test(); 18 | cpp_dump(class_a(), class_b(), enum_a::s); 19 | 20 | // _p_CPP_DUMP_EXPAND_VA 21 | static_assert(check_iota(EXPAND_VA(0))); 22 | static_assert(check_iota(EXPAND_VA(0, 1))); 23 | static_assert(check_iota(EXPAND_VA(0, 1, 2))); 24 | static_assert(check_iota(EXPAND_VA(0, 1, 2, 3))); 25 | static_assert(check_iota(EXPAND_VA(0, 1, 2, 3, 4))); 26 | static_assert(check_iota(EXPAND_VA(0, 1, 2, 3, 4, 5))); 27 | static_assert(check_iota(EXPAND_VA(0, 1, 2, 3, 4, 5, 6))); 28 | static_assert(check_iota(EXPAND_VA(0, 1, 2, 3, 4, 5, 6, 7))); 29 | static_assert(check_iota(EXPAND_VA(0, 1, 2, 3, 4, 5, 6, 7, 8))); 30 | static_assert(check_iota(EXPAND_VA(0, 1, 2, 3, 4, 5, 6, 7, 8, 9))); 31 | static_assert(check_iota(EXPAND_VA(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10))); 32 | static_assert(check_iota(EXPAND_VA(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11))); 33 | static_assert(check_iota(EXPAND_VA(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12))); 34 | static_assert(check_iota(EXPAND_VA(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13))); 35 | static_assert(check_iota(EXPAND_VA(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14))); 36 | static_assert(check_iota(EXPAND_VA(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15))); 37 | static_assert(check_iota(EXPAND_VA(TO_16))); 38 | static_assert(check_iota(EXPAND_VA(TO_16, 17))); 39 | static_assert(check_iota(EXPAND_VA(TO_16, 17, 18))); 40 | static_assert(check_iota(EXPAND_VA(TO_16, 17, 18, 19))); 41 | static_assert(check_iota(EXPAND_VA(TO_16, 17, 18, 19, 20))); 42 | static_assert(check_iota(EXPAND_VA(TO_16, 17, 18, 19, 20, 21))); 43 | static_assert(check_iota(EXPAND_VA(TO_16, 17, 18, 19, 20, 21, 22))); 44 | static_assert(check_iota(EXPAND_VA(TO_16, 17, 18, 19, 20, 21, 22, 23))); 45 | static_assert(check_iota(EXPAND_VA(TO_16, 17, 18, 19, 20, 21, 22, 23, 24))); 46 | static_assert(check_iota(EXPAND_VA(TO_16, 17, 18, 19, 20, 21, 22, 23, 24, 25))); 47 | static_assert(check_iota(EXPAND_VA(TO_16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26))); 48 | static_assert(check_iota(EXPAND_VA(TO_16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27))); 49 | static_assert(check_iota(EXPAND_VA(TO_16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28))); 50 | static_assert(check_iota(EXPAND_VA(TO_16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29))); 51 | static_assert(check_iota(EXPAND_VA(TO_16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30)) 52 | ); 53 | static_assert( 54 | check_iota(EXPAND_VA(TO_16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31)) 55 | ); 56 | } 57 | -------------------------------------------------------------------------------- /test/txt/color_rtti.txt: -------------------------------------------------------------------------------- 1 | [dump] typeid(void) => std::type_info{ name()= "void", hash_code()= 314159265358979 } 2 | [dump] typeid(ns::class_a) => std::type_info{ name()= "ns::class_a", hash_code()= 314159265358979 }, type_index1 => std::type_index{ name()= "ns::class_a", hash_code()= 314159265358979 } 3 | [dump] typeid(ns::class_a) 4 | => std::type_info{  5 | name()= "ns::class_a",  6 | hash_code()= 314159265358979 7 | }, 8 |  type_index1 9 | => std::type_index{  10 | name()= "ns::class_a",  11 | hash_code()= 314159265358979 12 | } 13 | [dump] typeid(ns::class_a) 14 | => std::type_info{ ... },  15 | type_index1 16 | => std::type_index{ ... } 17 | -------------------------------------------------------------------------------- /test/txt/color_std_version_20_clang.txt: -------------------------------------------------------------------------------- 1 | [dump] source_location::current() => "The compiler doesn't support this class." 2 | [dump] source_location::current() 3 | => "The compiler doesn't support this class." 4 | [dump] source_location::current() 5 | => "The compiler doesn't support this class." 6 | -------------------------------------------------------------------------------- /test/txt/color_std_version_20_gnu.txt: -------------------------------------------------------------------------------- 1 | [dump] source_location::current() => std::source_location{ file_name()= "", line()= 100, column()= 3, function_name()= "int main()" } 2 | [dump] source_location::current() 3 | => std::source_location{  4 | file_name()= "",  5 | line()= 104,  6 | column()= 3,  7 | function_name()= "int main()" 8 | } 9 | [dump] source_location::current() 10 | => std::source_location{ ... } 11 | -------------------------------------------------------------------------------- /test/txt/color_std_version_20_msvc.txt: -------------------------------------------------------------------------------- 1 | [dump] source_location::current() => std::source_location{ file_name()= "", line()= 100, column()= 3, function_name()= "int __cdecl main(void)" } 2 | [dump] source_location::current() 3 | => std::source_location{  4 | file_name()= "",  5 | line()= 104,  6 | column()= 3,  7 | function_name()= "int __cdecl main(void)" 8 | } 9 | [dump] source_location::current() 10 | => std::source_location{ ... } 11 | -------------------------------------------------------------------------------- /test/txt/color_variable_apple_by_syntax.txt: -------------------------------------------------------------------------------- 1 | [dump] void_ptr => 0x7ffd06586204 2 | [dump] int_ptr | cp::addr() => 0x7ffd06586204 3 | [dump] int_ptr_ptr | cp::addr(1) => *0x7ffd06586204 4 | [dump] int_ptr_ptr_ptr | cp::addr(2) => **0x7ffd06586204 5 | [dump] (unordered_map{{4, 6}, {2, 6}, {4, 3}}) => { 2: 6, 4: 6 } 6 | [dump] unordered_multimap1 => { 7 | 'b' (1): [ 20 ], 8 | 'c' (1): [ 30 ], 9 | 'a' (2): [ 10, 40 ] 10 | } 11 | [dump] (unordered_set{3, 1, 4, 1, 5}) => { 5, 4, 1, 3 } 12 | [dump] unordered_multiset1 => { 4 (1), 3 (1), 1 (2) } 13 | -------------------------------------------------------------------------------- /test/txt/color_variable_apple_original.txt: -------------------------------------------------------------------------------- 1 | [dump] void_ptr => 0x7ffd06586204 2 | [dump] int_ptr | cp::addr() => 0x7ffd06586204 3 | [dump] int_ptr_ptr | cp::addr(1) => *0x7ffd06586204 4 | [dump] int_ptr_ptr_ptr | cp::addr(2) => **0x7ffd06586204 5 | [dump] (unordered_map{{4, 6}, {2, 6}, {4, 3}}) => { 2: 6, 4: 6 } 6 | [dump] unordered_multimap1 => { 7 | 'b' (1): [ 20 ], 8 | 'c' (1): [ 30 ], 9 | 'a' (2): [ 10, 40 ] 10 | } 11 | [dump] (unordered_set{3, 1, 4, 1, 5}) => { 5, 4, 1, 3 } 12 | [dump] unordered_multiset1 => { 4 (1), 3 (1), 1 (2) } 13 | -------------------------------------------------------------------------------- /test/txt/color_variable_clang_by_syntax.txt: -------------------------------------------------------------------------------- 1 | [dump] original_error1 => original_error{ what()= "This is an original error." } 2 | [dump] ns::template_class>() => ns::template_class<ns::template_class<int>>{ member_var= 5, member_func()= "This is a member_func." } 3 | [dump] original_class() => original_class{ member_var= 5, member_func()= "This is a member_func." } 4 | [dump] original_enum::member1 => original_enum::member1, original_enum::member2 => original_enum::member2, original_enum::member3 => original_enum::? 5 | [dump] original_scoped_enum::member1 => original_scoped_enum::member1, original_scoped_enum::member2 => original_scoped_enum::member2,  6 | original_scoped_enum::member3 => original_scoped_enum::? 7 | [dump] unsupported_original_class() => Unsupported Type 8 | -------------------------------------------------------------------------------- /test/txt/color_variable_clang_original.txt: -------------------------------------------------------------------------------- 1 | [dump] original_error1 => original_error{ what()= "This is an original error." } 2 | [dump] ns::template_class>() => ns::template_class>{ member_var= 5, member_func()= "This is a member_func." } 3 | [dump] original_class() => original_class{ member_var= 5, member_func()= "This is a member_func." } 4 | [dump] original_enum::member1 => original_enum::member1, original_enum::member2 => original_enum::member2, original_enum::member3 => original_enum::? 5 | [dump] original_scoped_enum::member1 => original_scoped_enum::member1, original_scoped_enum::member2 => original_scoped_enum::member2,  6 | original_scoped_enum::member3 => original_scoped_enum::? 7 | [dump] unsupported_original_class() => Unsupported Type 8 | -------------------------------------------------------------------------------- /test/txt/color_variable_gnu_by_syntax.txt: -------------------------------------------------------------------------------- 1 | [dump] original_error1 => main(int, char**)::original_error{ what()= "This is an original error." } 2 | [dump] ns::template_class>() => ns::template_class<ns::template_class<int> >{ member_var= 5, member_func()= "This is a member_func." } 3 | [dump] original_class() => main(int, char**)::original_class{ member_var= 5, member_func()= "This is a member_func." } 4 | [dump] original_enum::member1 => main(int, char**)::original_enum::member1, original_enum::member2 => main(int, char**)::original_enum::member2,  5 | original_enum::member3 => main(int, char**)::original_enum::? 6 | [dump] original_scoped_enum::member1 => main(int, char**)::original_scoped_enum::member1,  7 | original_scoped_enum::member2 => main(int, char**)::original_scoped_enum::member2,  8 | original_scoped_enum::member3 => main(int, char**)::original_scoped_enum::? 9 | [dump] unsupported_original_class() => Unsupported Type 10 | -------------------------------------------------------------------------------- /test/txt/color_variable_gnu_original.txt: -------------------------------------------------------------------------------- 1 | [dump] original_error1 => main(int, char**)::original_error{ what()= "This is an original error." } 2 | [dump] ns::template_class>() => ns::template_class >{ member_var= 5, member_func()= "This is a member_func." } 3 | [dump] original_class() => main(int, char**)::original_class{ member_var= 5, member_func()= "This is a member_func." } 4 | [dump] original_enum::member1 => main(int, char**)::original_enum::member1, original_enum::member2 => main(int, char**)::original_enum::member2,  5 | original_enum::member3 => main(int, char**)::original_enum::? 6 | [dump] original_scoped_enum::member1 => main(int, char**)::original_scoped_enum::member1,  7 | original_scoped_enum::member2 => main(int, char**)::original_scoped_enum::member2,  8 | original_scoped_enum::member3 => main(int, char**)::original_scoped_enum::? 9 | [dump] unsupported_original_class() => Unsupported Type 10 | -------------------------------------------------------------------------------- /test/txt/color_variable_linux_by_syntax.txt: -------------------------------------------------------------------------------- 1 | [dump] void_ptr => 0x7ffd06586204 2 | [dump] int_ptr | cp::addr() => 0x7ffd06586204 3 | [dump] int_ptr_ptr | cp::addr(1) => *0x7ffd06586204 4 | [dump] int_ptr_ptr_ptr | cp::addr(2) => **0x7ffd06586204 5 | [dump] (unordered_map{{4, 6}, {2, 6}, {4, 3}}) => { 2: 6, 4: 6 } 6 | [dump] unordered_multimap1 => { 7 | 'b' (1): [ 20 ], 8 | 'a' (2): [ 40, 10 ], 9 | 'c' (1): [ 30 ] 10 | } 11 | [dump] (unordered_set{3, 1, 4, 1, 5}) => { 5, 4, 1, 3 } 12 | [dump] unordered_multiset1 => { 4 (1), 1 (2), 3 (1) } 13 | -------------------------------------------------------------------------------- /test/txt/color_variable_linux_original.txt: -------------------------------------------------------------------------------- 1 | [dump] void_ptr => 0x7ffd06586204 2 | [dump] int_ptr | cp::addr() => 0x7ffd06586204 3 | [dump] int_ptr_ptr | cp::addr(1) => *0x7ffd06586204 4 | [dump] int_ptr_ptr_ptr | cp::addr(2) => **0x7ffd06586204 5 | [dump] (unordered_map{{4, 6}, {2, 6}, {4, 3}}) => { 2: 6, 4: 6 } 6 | [dump] unordered_multimap1 => { 7 | 'b' (1): [ 20 ], 8 | 'a' (2): [ 40, 10 ], 9 | 'c' (1): [ 30 ] 10 | } 11 | [dump] (unordered_set{3, 1, 4, 1, 5}) => { 5, 4, 1, 3 } 12 | [dump] unordered_multiset1 => { 4 (1), 1 (2), 3 (1) } 13 | -------------------------------------------------------------------------------- /test/txt/color_variable_msvc_by_syntax.txt: -------------------------------------------------------------------------------- 1 | [dump] original_error1 => main::original_error{ what()= "This is an original error." } 2 | [dump] ns::template_class>() => ns::template_class<ns::template_class<int> >{ member_var= 5, member_func()= "This is a member_func." } 3 | [dump] original_class() => main::original_class{ member_var= 5, member_func()= "This is a member_func." } 4 | [dump] original_enum::member1 => main::original_enum::member1, original_enum::member2 => main::original_enum::member2,  5 | original_enum::member3 => main::original_enum::? 6 | [dump] original_scoped_enum::member1 => main::original_scoped_enum::member1, original_scoped_enum::member2 => main::original_scoped_enum::member2,  7 | original_scoped_enum::member3 => main::original_scoped_enum::? 8 | [dump] unsupported_original_class() => Unsupported Type 9 | -------------------------------------------------------------------------------- /test/txt/color_variable_msvc_original.txt: -------------------------------------------------------------------------------- 1 | [dump] original_error1 => main::original_error{ what()= "This is an original error." } 2 | [dump] ns::template_class>() => ns::template_class >{ member_var= 5, member_func()= "This is a member_func." } 3 | [dump] original_class() => main::original_class{ member_var= 5, member_func()= "This is a member_func." } 4 | [dump] original_enum::member1 => main::original_enum::member1, original_enum::member2 => main::original_enum::member2,  5 | original_enum::member3 => main::original_enum::? 6 | [dump] original_scoped_enum::member1 => main::original_scoped_enum::member1, original_scoped_enum::member2 => main::original_scoped_enum::member2,  7 | original_scoped_enum::member3 => main::original_scoped_enum::? 8 | [dump] unsupported_original_class() => Unsupported Type 9 | -------------------------------------------------------------------------------- /test/txt/color_variable_win32_by_syntax.txt: -------------------------------------------------------------------------------- 1 | [dump] void_ptr => 00007FFD06586204 2 | [dump] int_ptr | cp::addr() => 00007FFD06586204 3 | [dump] int_ptr_ptr | cp::addr(1) => *00007FFD06586204 4 | [dump] int_ptr_ptr_ptr | cp::addr(2) => **00007FFD06586204 5 | [dump] (unordered_map{{4, 6}, {2, 6}, {4, 3}}) => { 4: 6, 2: 6 } 6 | [dump] unordered_multimap1 => { 7 | 'c' (1): [ 30 ], 8 | 'a' (2): [ 10, 40 ], 9 | 'b' (1): [ 20 ] 10 | } 11 | [dump] (unordered_set{3, 1, 4, 1, 5}) => { 3, 1, 4, 5 } 12 | [dump] unordered_multiset1 => { 3 (1), 1 (2), 4 (1) } 13 | -------------------------------------------------------------------------------- /test/txt/color_variable_win32_original.txt: -------------------------------------------------------------------------------- 1 | [dump] void_ptr => 00007FFD06586204 2 | [dump] int_ptr | cp::addr() => 00007FFD06586204 3 | [dump] int_ptr_ptr | cp::addr(1) => *00007FFD06586204 4 | [dump] int_ptr_ptr_ptr | cp::addr(2) => **00007FFD06586204 5 | [dump] (unordered_map{{4, 6}, {2, 6}, {4, 3}}) => { 4: 6, 2: 6 } 6 | [dump] unordered_multimap1 => { 7 | 'c' (1): [ 30 ], 8 | 'a' (2): [ 10, 40 ], 9 | 'b' (1): [ 20 ] 10 | } 11 | [dump] (unordered_set{3, 1, 4, 1, 5}) => { 3, 1, 4, 5 } 12 | [dump] unordered_multiset1 => { 3 (1), 1 (2), 4 (1) } 13 | -------------------------------------------------------------------------------- /test/txt/dump_variable_apple.txt: -------------------------------------------------------------------------------- 1 | [dump] void_ptr => 0x7ffd06586204 2 | [dump] int_ptr | cp::addr() => 0x7ffd06586204 3 | [dump] int_ptr_ptr | cp::addr(1) => *0x7ffd06586204 4 | [dump] int_ptr_ptr_ptr | cp::addr(2) => **0x7ffd06586204 5 | [dump] (unordered_map{{4, 6}, {2, 6}, {4, 3}}) => { 2: 6, 4: 6 } 6 | [dump] unordered_multimap1 => { 7 | 'b' (1): [ 20 ], 8 | 'c' (1): [ 30 ], 9 | 'a' (2): [ 10, 40 ] 10 | } 11 | [dump] (unordered_set{3, 1, 4, 1, 5}) => { 5, 4, 1, 3 } 12 | [dump] unordered_multiset1 => { 4 (1), 3 (1), 1 (2) } 13 | -------------------------------------------------------------------------------- /test/txt/dump_variable_clang.txt: -------------------------------------------------------------------------------- 1 | [dump] original_error1 => original_error{ what()= "This is an original error." } 2 | [dump] ns::template_class>() => ns::template_class>{ member_var= 5, member_func()= "This is a member_func." } 3 | [dump] original_class() => original_class{ member_var= 5, member_func()= "This is a member_func." } 4 | [dump] original_enum::member1 => original_enum::member1, original_enum::member2 => original_enum::member2, original_enum::member3 => original_enum::? 5 | [dump] original_scoped_enum::member1 => original_scoped_enum::member1, original_scoped_enum::member2 => original_scoped_enum::member2, 6 | original_scoped_enum::member3 => original_scoped_enum::? 7 | [dump] unsupported_original_class() => Unsupported Type 8 | -------------------------------------------------------------------------------- /test/txt/dump_variable_gnu.txt: -------------------------------------------------------------------------------- 1 | [dump] original_error1 => main(int, char**)::original_error{ what()= "This is an original error." } 2 | [dump] ns::template_class>() => ns::template_class >{ member_var= 5, member_func()= "This is a member_func." } 3 | [dump] original_class() => main(int, char**)::original_class{ member_var= 5, member_func()= "This is a member_func." } 4 | [dump] original_enum::member1 => main(int, char**)::original_enum::member1, original_enum::member2 => main(int, char**)::original_enum::member2, 5 | original_enum::member3 => main(int, char**)::original_enum::? 6 | [dump] original_scoped_enum::member1 => main(int, char**)::original_scoped_enum::member1, 7 | original_scoped_enum::member2 => main(int, char**)::original_scoped_enum::member2, 8 | original_scoped_enum::member3 => main(int, char**)::original_scoped_enum::? 9 | [dump] unsupported_original_class() => Unsupported Type 10 | -------------------------------------------------------------------------------- /test/txt/dump_variable_linux.txt: -------------------------------------------------------------------------------- 1 | [dump] void_ptr => 0x7ffd06586204 2 | [dump] int_ptr | cp::addr() => 0x7ffd06586204 3 | [dump] int_ptr_ptr | cp::addr(1) => *0x7ffd06586204 4 | [dump] int_ptr_ptr_ptr | cp::addr(2) => **0x7ffd06586204 5 | [dump] (unordered_map{{4, 6}, {2, 6}, {4, 3}}) => { 2: 6, 4: 6 } 6 | [dump] unordered_multimap1 => { 7 | 'b' (1): [ 20 ], 8 | 'a' (2): [ 40, 10 ], 9 | 'c' (1): [ 30 ] 10 | } 11 | [dump] (unordered_set{3, 1, 4, 1, 5}) => { 5, 4, 1, 3 } 12 | [dump] unordered_multiset1 => { 4 (1), 1 (2), 3 (1) } 13 | -------------------------------------------------------------------------------- /test/txt/dump_variable_msvc.txt: -------------------------------------------------------------------------------- 1 | [dump] original_error1 => main::original_error{ what()= "This is an original error." } 2 | [dump] ns::template_class>() => ns::template_class >{ member_var= 5, member_func()= "This is a member_func." } 3 | [dump] original_class() => main::original_class{ member_var= 5, member_func()= "This is a member_func." } 4 | [dump] original_enum::member1 => main::original_enum::member1, original_enum::member2 => main::original_enum::member2, 5 | original_enum::member3 => main::original_enum::? 6 | [dump] original_scoped_enum::member1 => main::original_scoped_enum::member1, original_scoped_enum::member2 => main::original_scoped_enum::member2, 7 | original_scoped_enum::member3 => main::original_scoped_enum::? 8 | [dump] unsupported_original_class() => Unsupported Type 9 | -------------------------------------------------------------------------------- /test/txt/dump_variable_win32.txt: -------------------------------------------------------------------------------- 1 | [dump] void_ptr => 00007FFD06586204 2 | [dump] int_ptr | cp::addr() => 00007FFD06586204 3 | [dump] int_ptr_ptr | cp::addr(1) => *00007FFD06586204 4 | [dump] int_ptr_ptr_ptr | cp::addr(2) => **00007FFD06586204 5 | [dump] (unordered_map{{4, 6}, {2, 6}, {4, 3}}) => { 4: 6, 2: 6 } 6 | [dump] unordered_multimap1 => { 7 | 'c' (1): [ 30 ], 8 | 'a' (2): [ 10, 40 ], 9 | 'b' (1): [ 20 ] 10 | } 11 | [dump] (unordered_set{3, 1, 4, 1, 5}) => { 3, 1, 4, 5 } 12 | [dump] unordered_multiset1 => { 3 (1), 1 (2), 4 (1) } 13 | -------------------------------------------------------------------------------- /test/txt/readme_auto-indent.txt: -------------------------------------------------------------------------------- 1 | 2 | [dump] my_vector => [ "This is a test string.", "This is a test string.", "This is a test string." ] 3 | [dump] my_vector => [ 4 | "This is a test string.", 5 | "This is a test string.", 6 | "This is a test string.", 7 | "This is a test string." 8 | ] 9 | 10 | -------------------------------------------------------------------------------- /test/txt/readme_customizable-colors.txt: -------------------------------------------------------------------------------- 1 | 2 | // Basic Type 3 | [dump] my_bool => true, my_double => 3.141592, my_int => 65 4 | [dump] my_string => "This is a string.", my_char => 'a', LF_char => '\n' 5 | [dump] int_ptr => *65, void_ptr => 0x7fffffffffff, nullptr => nullptr 6 | 7 | // Container 8 | [dump] my_vector => [ 9 | [ 3, 5, 8, 9, 7 ], 10 | [ 9, 3, 2, 3, 8 ] 11 | ] 12 | 13 | // Set/Map 14 | [dump] my_set => { 'A', 'e', 'l', 'p' } 15 | [dump] my_map => { 2: 6, 4: 6, 5: 3 } 16 | 17 | // Multiset/Multimap 18 | [dump] my_multiset => { 'A' (1), 'e' (1), 'l' (1), 'p' (2) } 19 | [dump] my_multimap => { 20 | 2 (1): [ 4 ], 21 | 4 (2): [ 6, 7 ], 22 | 5 (1): [ 3 ] 23 | } 24 | 25 | // Tuple 26 | [dump] my_tuple => ( 7, 4.500000, "This is a string." ) 27 | [dump] my_pair => ( 8, 'a' ) 28 | 29 | // FIFO/LIFO 30 | [dump] my_queue => std::queue{ size()= 5, front()= 1, back()= 5 } 31 | [dump] my_priority_queue => std::priority_queue{ size()= 5, top()= 5 } 32 | [dump] my_stack => std::stack{ size()= 5, top()= 5 } 33 | 34 | // Other 35 | [dump] my_bitset => 0b 0011 1010 36 | [dump] my_complex => 1.000000 - 1.000000i ( abs= 1.414214, arg/pi= -0.250000 ) 37 | [dump] my_optional => ?15, std::nullopt => std::nullopt 38 | [dump] my_variant => |"This is a string." 39 | 40 | // Combination 41 | [dump] vector_of_pairs => [ 42 | ( 1, "apple" ), 43 | ( 3, "banana" ) 44 | ] 45 | 46 | -------------------------------------------------------------------------------- /test/txt/readme_customize-dump.txt: -------------------------------------------------------------------------------- 1 | 2 | // Print the filename and line instead of [dump] 3 | [customize-dump.cpp:24] my_vector => [ 4 | [ 3, 5, 8, 9, 7 ], 5 | [ 9, 3, 2, 3, 8 ] 6 | ] 7 | [customize-dump.cpp:12] my_map => { 2: 6, 4: 6, 5: 3 } 8 | [customize-dump.cpp:13] my_set => { 'A', 'e', 'l', 'p' } 9 | 10 | // Print along with the function name 11 | [customize-dump.cpp:32 (main)] my_vector => [ 12 | [ 3, 5, 8, 9, 7 ], 13 | [ 9, 3, 2, 3, 8 ] 14 | ] 15 | [customize-dump.cpp:12 (my_func)] my_map => { 2: 6, 4: 6, 5: 3 } 16 | [customize-dump.cpp:13 (my_func)] my_set => { 'A', 'e', 'l', 'p' } 17 | 18 | -------------------------------------------------------------------------------- /test/txt/readme_introduction.txt: -------------------------------------------------------------------------------- 1 | 2 | [dump] my_vector => [ 3 | [ 3, 5, 8, 9, 7 ], 4 | [ 9, 3, 2, 3, 8 ] 5 | ] 6 | 7 | -------------------------------------------------------------------------------- /test/txt/readme_no-es.txt: -------------------------------------------------------------------------------- 1 | 2 | // Basic Type 3 | [dump] my_bool => true, my_double => 3.141592, my_int => 65 4 | [dump] my_string => "This is a string.", my_char => 'a', LF_char => '\n' 5 | [dump] int_ptr => *65, void_ptr => 0x7fffffffffff, nullptr => nullptr 6 | 7 | // Container 8 | [dump] my_vector => [ 9 | [ 3, 5, 8, 9, 7 ], 10 | [ 9, 3, 2, 3, 8 ] 11 | ] 12 | 13 | // Set/Map 14 | [dump] my_set => { 'A', 'e', 'l', 'p' } 15 | [dump] my_map => { 2: 6, 4: 6, 5: 3 } 16 | 17 | // Multiset/Multimap 18 | [dump] my_multiset => { 'A' (1), 'e' (1), 'l' (1), 'p' (2) } 19 | [dump] my_multimap => { 20 | 2 (1): [ 4 ], 21 | 4 (2): [ 6, 7 ], 22 | 5 (1): [ 3 ] 23 | } 24 | 25 | // Tuple 26 | [dump] my_tuple => ( 7, 4.500000, "This is a string." ) 27 | [dump] my_pair => ( 8, 'a' ) 28 | 29 | // FIFO/LIFO 30 | [dump] my_queue => std::queue{ size()= 5, front()= 1, back()= 5 } 31 | [dump] my_priority_queue => std::priority_queue{ size()= 5, top()= 5 } 32 | [dump] my_stack => std::stack{ size()= 5, top()= 5 } 33 | 34 | // Other 35 | [dump] my_bitset => 0b 0011 1010 36 | [dump] my_complex => 1.000000 - 1.000000i ( abs= 1.414214, arg/pi= -0.250000 ) 37 | [dump] my_optional => ?15, std::nullopt => std::nullopt 38 | [dump] my_variant => |"This is a string." 39 | 40 | // Combination 41 | [dump] vector_of_pairs => [ 42 | ( 1, "apple" ), 43 | ( 3, "banana" ) 44 | ] 45 | 46 | -------------------------------------------------------------------------------- /test/txt/readme_supports-various-types.txt: -------------------------------------------------------------------------------- 1 | 2 | // Basic Type 3 | [dump] my_bool => true, my_double => 3.141592, my_int => 65 4 | [dump] my_string => "This is a string.", my_char => 'a', LF_char => '\n' 5 | [dump] int_ptr => *65, void_ptr => 0x7fffffffffff, nullptr => nullptr 6 | 7 | // Container 8 | [dump] my_vector => [ 9 | [ 3, 5, 8, 9, 7 ], 10 | [ 9, 3, 2, 3, 8 ] 11 | ] 12 | 13 | // Set/Map 14 | [dump] my_set => { 'A', 'e', 'l', 'p' } 15 | [dump] my_map => { 2: 6, 4: 6, 5: 3 } 16 | 17 | // Multiset/Multimap 18 | [dump] my_multiset => { 'A' (1), 'e' (1), 'l' (1), 'p' (2) } 19 | [dump] my_multimap => { 20 | 2 (1): [ 4 ], 21 | 4 (2): [ 6, 7 ], 22 | 5 (1): [ 3 ] 23 | } 24 | 25 | // Tuple 26 | [dump] my_tuple => ( 7, 4.500000, "This is a string." ) 27 | [dump] my_pair => ( 8, 'a' ) 28 | 29 | // FIFO/LIFO 30 | [dump] my_queue => std::queue{ size()= 5, front()= 1, back()= 5 } 31 | [dump] my_priority_queue => std::priority_queue{ size()= 5, top()= 5 } 32 | [dump] my_stack => std::stack{ size()= 5, top()= 5 } 33 | 34 | // Other 35 | [dump] my_bitset => 0b 0011 1010 36 | [dump] my_complex => 1.000000 - 1.000000i ( abs= 1.414214, arg/pi= -0.250000 ) 37 | [dump] my_optional => ?15, std::nullopt => std::nullopt 38 | [dump] my_variant => |"This is a string." 39 | 40 | // Combination 41 | [dump] vector_of_pairs => [ 42 | ( 1, "apple" ), 43 | ( 3, "banana" ) 44 | ] 45 | 46 | -------------------------------------------------------------------------------- /test/txt/readme_user-defined-class-generic.txt: -------------------------------------------------------------------------------- 1 | 2 | [dump] my_class_A => class_A{ i= 10, str()= "10" } 3 | 4 | -------------------------------------------------------------------------------- /test/txt/readme_user-defined-class-ostream.txt: -------------------------------------------------------------------------------- 1 | 2 | [dump] my_class_A => class_A{ i= 10, str()= "10" } 3 | 4 | -------------------------------------------------------------------------------- /test/txt/readme_user-defined-class.txt: -------------------------------------------------------------------------------- 1 | 2 | [dump] my_class_A => class_A{ i= 10, str()= "10" } 3 | 4 | -------------------------------------------------------------------------------- /test/txt/readme_user-defined-enum-generic.txt: -------------------------------------------------------------------------------- 1 | 2 | [dump] my_enum_A => enum_A::member_c 3 | 4 | -------------------------------------------------------------------------------- /test/txt/readme_user-defined-enum.txt: -------------------------------------------------------------------------------- 1 | 2 | [dump] my_enum_A => enum_A::member_c 3 | 4 | --------------------------------------------------------------------------------