Full Code of taocpp/config for AI

main 93a455e103cd cached
344 files
296.4 KB
87.2k tokens
712 symbols
1 requests
Download .txt
Showing preview only (363K chars total). Download the full file or copy to clipboard to get everything.
Repository: taocpp/config
Branch: main
Commit: 93a455e103cd
Files: 344
Total size: 296.4 KB

Directory structure:
gitextract_84t47bfe/

├── .clang-format
├── .cmake/
│   └── taocpp-config-config.cmake.in
├── .codecov.yml
├── .github/
│   └── workflows/
│       ├── clang-analyze.yml
│       ├── clang-format.yml
│       ├── clang-tidy.yml
│       ├── code-coverage.yml
│       ├── codeql-analysis.yml
│       ├── linux.yml
│       ├── macos.yml
│       ├── sanitizer.yml
│       └── windows.yml
├── .gitignore
├── .gitmodules
├── CMakeLists.txt
├── LICENSE
├── Makefile
├── README.md
├── doc/
│   ├── All-Config-Functions.md
│   ├── Changelog.md
│   ├── Parsing-Config-Files.md
│   ├── README.md
│   └── Writing-Config-Files.md
├── include/
│   └── tao/
│       ├── config/
│       │   ├── access.hpp
│       │   ├── annotation.hpp
│       │   ├── assign.hpp
│       │   ├── contrib/
│       │   │   └── rot13.hpp
│       │   ├── from_file.hpp
│       │   ├── from_files.hpp
│       │   ├── from_input.hpp
│       │   ├── from_string.hpp
│       │   ├── internal/
│       │   │   ├── array.hpp
│       │   │   ├── atom.hpp
│       │   │   ├── change_action_and_states.hpp
│       │   │   ├── concat.hpp
│       │   │   ├── config_action.hpp
│       │   │   ├── config_grammar.hpp
│       │   │   ├── config_parser.hpp
│       │   │   ├── constants.hpp
│       │   │   ├── debug_traits.hpp
│       │   │   ├── entry.hpp
│       │   │   ├── entry_kind.hpp
│       │   │   ├── events_from_value.hpp
│       │   │   ├── forward.hpp
│       │   │   ├── function_implementations.hpp
│       │   │   ├── function_traits.hpp
│       │   │   ├── function_wrapper.hpp
│       │   │   ├── jaxn_action.hpp
│       │   │   ├── jaxn_to_entry.hpp
│       │   │   ├── json.hpp
│       │   │   ├── key1.hpp
│       │   │   ├── key1_action.hpp
│       │   │   ├── key1_grammar.hpp
│       │   │   ├── key1_guard.hpp
│       │   │   ├── key1_kind.hpp
│       │   │   ├── key1_part.hpp
│       │   │   ├── key_action.hpp
│       │   │   ├── key_grammar.hpp
│       │   │   ├── limits.hpp
│       │   │   ├── object.hpp
│       │   │   ├── parse_utility.hpp
│       │   │   ├── pegtl.hpp
│       │   │   ├── phase1_append.hpp
│       │   │   ├── phase1_mode.hpp
│       │   │   ├── phase2_access.hpp
│       │   │   ├── phase2_additions.hpp
│       │   │   ├── phase2_asterisks.hpp
│       │   │   ├── phase2_everything.hpp
│       │   │   ├── phase2_functions.hpp
│       │   │   ├── phase2_references.hpp
│       │   │   ├── phase3_remove.hpp
│       │   │   ├── phase5_repack.hpp
│       │   │   ├── reference2.hpp
│       │   │   ├── reference2_action.hpp
│       │   │   ├── reference2_grammar.hpp
│       │   │   ├── reference2_kind.hpp
│       │   │   ├── reference2_part.hpp
│       │   │   ├── repack_traits.hpp
│       │   │   ├── state.hpp
│       │   │   ├── statistics.hpp
│       │   │   ├── string_utility.hpp
│       │   │   ├── system_utility.hpp
│       │   │   └── to_stream.hpp
│       │   ├── key.hpp
│       │   ├── key_kind.hpp
│       │   ├── key_part.hpp
│       │   ├── parser.hpp
│       │   ├── to_stream.hpp
│       │   ├── traits.hpp
│       │   └── value.hpp
│       └── config.hpp
├── src/
│   ├── example/
│   │   └── config/
│   │       ├── CMakeLists.txt
│   │       ├── dump_all_phases.cpp
│   │       ├── dump_only_data.cpp
│   │       ├── dump_phase_one.cpp
│   │       ├── dump_phase_three.cpp
│   │       ├── dump_phase_two.cpp
│   │       ├── dump_with_meta.cpp
│   │       └── try_catch.hpp
│   └── test/
│       └── config/
│           ├── CMakeLists.txt
│           ├── access.cpp
│           ├── assign.cpp
│           ├── custom.cpp
│           ├── debug_traits.cpp
│           ├── enumerations.cpp
│           ├── failure.cpp
│           ├── independence.cpp
│           ├── key.cpp
│           ├── key_part.cpp
│           ├── main.hpp
│           ├── multi_line_string_position.cpp
│           ├── parse_key.cpp
│           ├── parse_key1.cpp
│           ├── parse_reference2.cpp
│           ├── setenv.hpp
│           ├── success.cpp
│           ├── test.hpp
│           ├── to_stream.cpp
│           └── value.cpp
└── tests/
    ├── add_01.failure
    ├── add_02.failure
    ├── add_03.failure
    ├── add_04.failure
    ├── add_05.failure
    ├── add_06.failure
    ├── add_07.failure
    ├── add_08.failure
    ├── add_09.failure
    ├── add_10.failure
    ├── add_11.failure
    ├── add_12.failure
    ├── add_13.failure
    ├── add_14.failure
    ├── add_15.failure
    ├── add_16.failure
    ├── add_17.failure
    ├── add_18.failure
    ├── add_19.failure
    ├── add_20.failure
    ├── add_21.failure
    ├── add_22.failure
    ├── add_23.failure
    ├── add_24.failure
    ├── add_25.failure
    ├── add_26.failure
    ├── add_27.failure
    ├── add_28.failure
    ├── add_29.failure
    ├── add_30.failure
    ├── add_31.failure
    ├── add_32.failure
    ├── add_33.failure
    ├── add_34.failure
    ├── add_35.failure
    ├── add_36.failure
    ├── add_37.failure
    ├── add_38.failure
    ├── add_39.failure
    ├── add_40.failure
    ├── add_41.failure
    ├── add_42.failure
    ├── add_43.failure
    ├── add_44.failure
    ├── add_45.failure
    ├── add_46.failure
    ├── add_47.failure
    ├── add_48.failure
    ├── add_number.jaxn
    ├── add_number.success
    ├── add_string.jaxn
    ├── add_string.success
    ├── array_index_01.jaxn
    ├── array_index_01.success
    ├── array_index_02.jaxn
    ├── array_index_02.success
    ├── binary.jaxn
    ├── binary.success
    ├── braces.jaxn
    ├── braces.success
    ├── combo_01.jaxn
    ├── combo_01.success
    ├── combo_02.jaxn
    ├── combo_02.success
    ├── commas.jaxn
    ├── commas.success
    ├── comments.jaxn
    ├── comments.success
    ├── complex_01.failure
    ├── complex_02.failure
    ├── complex_03.failure
    ├── debug_traits.config
    ├── debug_traits.output
    ├── delete.jaxn
    ├── delete.success
    ├── doc_asterisk_01.jaxn
    ├── doc_asterisk_01.success
    ├── doc_default.jaxn
    ├── doc_default.success
    ├── doc_delete_01.jaxn
    ├── doc_delete_01.success
    ├── doc_delete_02.jaxn
    ├── doc_delete_02.success
    ├── doc_dotted_names.jaxn
    ├── doc_dotted_names.success
    ├── doc_include.inc
    ├── doc_include.jaxn
    ├── doc_include.success
    ├── doc_object_merge_01.jaxn
    ├── doc_object_merge_01.success
    ├── doc_references_01.jaxn
    ├── doc_references_01.success
    ├── doc_references_02.failure
    ├── doc_references_03.failure
    ├── doc_references_05.jaxn
    ├── doc_references_05.success
    ├── doc_references_06.jaxn
    ├── doc_references_06.success
    ├── doc_temporary.jaxn
    ├── doc_temporary.success
    ├── empty.jaxn
    ├── empty.success
    ├── env.failure
    ├── extensions.jaxn
    ├── extensions.success
    ├── formats.cbor
    ├── formats.jaxn
    ├── formats.json
    ├── formats.msgpack
    ├── formats.success
    ├── formats.txt
    ├── formats.ubjson
    ├── include.jaxn
    ├── include.success
    ├── jaxn.jaxn
    ├── jaxn.success
    ├── merge_number_01.jaxn
    ├── merge_number_01.success
    ├── merge_number_02.jaxn
    ├── merge_number_02.success
    ├── merge_number_03.jaxn
    ├── merge_number_03.success
    ├── merge_number_04.jaxn
    ├── merge_number_04.success
    ├── merge_number_05.jaxn
    ├── merge_number_05.success
    ├── merge_number_06.jaxn
    ├── merge_number_06.success
    ├── merge_number_07.jaxn
    ├── merge_number_07.success
    ├── merge_number_08.jaxn
    ├── merge_number_08.success
    ├── merge_string_01.jaxn
    ├── merge_string_01.success
    ├── merge_string_02.jaxn
    ├── merge_string_02.success
    ├── merge_string_03.jaxn
    ├── merge_string_03.success
    ├── merge_string_04.jaxn
    ├── merge_string_04.success
    ├── merge_string_05.jaxn
    ├── merge_string_05.success
    ├── merge_string_06.jaxn
    ├── merge_string_06.success
    ├── merge_string_07.jaxn
    ├── merge_string_07.success
    ├── merge_string_08.jaxn
    ├── merge_string_08.success
    ├── numbers.jaxn
    ├── numbers.success
    ├── quoted.jaxn
    ├── quoted.success
    ├── reference_01.failure
    ├── reference_01.jaxn
    ├── reference_01.success
    ├── reference_02.failure
    ├── reference_02.jaxn
    ├── reference_02.success
    ├── reference_03.failure
    ├── reference_03.jaxn
    ├── reference_03.success
    ├── reference_04.failure
    ├── reference_05.failure
    ├── reference_06.failure
    ├── reference_07.failure
    ├── reference_08.failure
    ├── reference_09.failure
    ├── reference_10.failure
    ├── reference_11.failure
    ├── reference_12.failure
    ├── regression_01.jaxn
    ├── regression_01.success
    ├── regression_02.jaxn
    ├── regression_02.success
    ├── regression_03.jaxn
    ├── regression_03.success
    ├── regression_04.jaxn
    ├── regression_04.success
    ├── regression_05.jaxn
    ├── regression_05.success
    ├── regression_06.jaxn
    ├── regression_06.success
    ├── regression_07.jaxn
    ├── regression_07.success
    ├── regression_08.jaxn
    ├── regression_08.success
    ├── regression_09.jaxn
    ├── regression_09.success
    ├── regression_10.jaxn
    ├── regression_10.success
    ├── regression_11.jaxn
    ├── regression_11.success
    ├── regression_12.jaxn
    ├── regression_12.success
    ├── regression_13.failure
    ├── scoping.jaxn
    ├── scoping.success
    ├── serialise.jaxn
    ├── serialise.success
    ├── shell.jaxn
    ├── shell.success
    ├── simple.jaxn
    ├── simple.success
    ├── space.jaxn
    ├── space.success
    ├── star_01.jaxn
    ├── star_01.success
    ├── star_02.jaxn
    ├── star_02.success
    ├── star_03.jaxn
    ├── star_03.success
    ├── string_01.failure
    ├── string_02.failure
    ├── temporary_01.jaxn
    ├── temporary_01.success
    ├── temporary_02.jaxn
    ├── temporary_02.success
    ├── temporary_03.jaxn
    ├── temporary_03.success
    ├── temporary_04.jaxn
    ├── temporary_04.success
    ├── temporary_05.jaxn
    ├── temporary_05.success
    ├── unready.jaxn
    └── unready.success

================================================
FILE CONTENTS
================================================

================================================
FILE: .clang-format
================================================
# the official .clang-format style for https://github.com/taocpp
#
# clang-format -i -style=file $(find . -name '[^.]*.[hc]pp')

Language: Cpp
Standard: Latest

AccessModifierOffset: -3
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: false
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
    AfterClass: true
    AfterControlStatement: false
    AfterEnum : true
    AfterFunction : true
    AfterNamespace : true
    AfterStruct : true
    AfterUnion : true
    AfterExternBlock: true
    BeforeCatch : true
    BeforeElse : true
    IndentBraces : false
    SplitEmptyFunction: false
    SplitEmptyRecord: false
    SplitEmptyNamespace: false
BreakBeforeBinaryOperators: All
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: false
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
BreakStringLiterals: false
ColumnLimit: 0
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 3
ContinuationIndentWidth: 3
Cpp11BracedListStyle: false
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
IncludeBlocks: Preserve
IndentCaseLabels: true
IndentPPDirectives: None
IndentWidth: 3
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: false
MaxEmptyLinesToKeep: 1
NamespaceIndentation: All
PointerAlignment: Left
ReflowComments: false
SortIncludes: true
SortUsingDeclarations: false
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: Never
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: true
SpacesInSquareBrackets: true
TabWidth: 8
UseTab: Never


================================================
FILE: .cmake/taocpp-config-config.cmake.in
================================================
@PACKAGE_INIT@

include(CMakeFindDependencyMacro)
find_dependency(taocpp-json @TAOCPP_CONFIG_JSON_MIN_VERSION@ CONFIG)

include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-targets.cmake")


================================================
FILE: .codecov.yml
================================================
ignore:
  - src/example/**/*


================================================
FILE: .github/workflows/clang-analyze.yml
================================================
name: clang-analyze

on:
  push:
    paths-ignore:
      - 'README.md'
      - 'doc/**'
  pull_request:
    paths-ignore:
      - 'README.md'
      - 'doc/**'

jobs:
  clang-analyze:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
      with:
        submodules: recursive

    - run: sudo apt-get install -yq clang-tools

    - run: scan-build cmake -E make_directory build

    - working-directory: build/
      run: scan-build cmake $GITHUB_WORKSPACE

    - working-directory: build/
      run: scan-build cmake --build .


================================================
FILE: .github/workflows/clang-format.yml
================================================
name: clang-format

on:
  push:
    paths-ignore:
      - 'README.md'
      - 'doc/**'
  pull_request:
    paths-ignore:
      - 'README.md'
      - 'doc/**'

jobs:
  clang-format:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
      with:
        submodules: recursive

    - uses: DoozyX/clang-format-lint-action@v0.13
      with:
        source: './include ./src'
        extensions: 'hpp,cpp'
        clangFormatVersion: 13


================================================
FILE: .github/workflows/clang-tidy.yml
================================================
name: clang-tidy

on:
  push:
    paths-ignore:
      - 'README.md'
      - 'doc/**'
  pull_request:
    paths-ignore:
      - 'README.md'
      - 'doc/**'

jobs:
  clang-tidy:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
      with:
        submodules: recursive

    - run: sudo apt-get install -yq clang-tidy

    - run: find include/ -src/ name '*.hpp' | xargs -I '{}' clang-tidy --quiet '{}' -- --std=c++17 -Iinclude -Iexternal/json/include -Iexternal/PEGTL/include


================================================
FILE: .github/workflows/code-coverage.yml
================================================
name: Code Coverage

on:
  push:
    paths-ignore:
      - 'README.md'
      - 'doc/**'
  pull_request:
    paths-ignore:
      - 'README.md'
      - 'doc/**'

jobs:
  code-coverage:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
      with:
        submodules: recursive

    - run: cmake -E make_directory build

    - working-directory: build/
      run: cmake $GITHUB_WORKSPACE -DCMAKE_CXX_FLAGS="-coverage"

    - working-directory: build/
      run: cmake --build .

    - working-directory: build/
      run: ctest --output-on-failure

    - working-directory: build/
      run: bash <(curl -s https://codecov.io/bash)


================================================
FILE: .github/workflows/codeql-analysis.yml
================================================
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"

on:
  push:
    branches: [ main ]
    paths-ignore:
      - 'README.md'
      - 'doc/**'
  pull_request:
    # The branches below must be a subset of the branches above
    branches: [ main ]
    paths-ignore:
      - 'README.md'
      - 'doc/**'
  schedule:
    - cron: '31 6 * * 0'

jobs:
  analyze:
    name: Analyze
    runs-on: ubuntu-latest

    strategy:
      fail-fast: false
      matrix:
        language: [ 'cpp' ]
        # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
        # Learn more:
        # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed

    steps:
    - name: Checkout repository
      uses: actions/checkout@v3
      with:
        submodules: recursive

    # Initializes the CodeQL tools for scanning.
    - name: Initialize CodeQL
      uses: github/codeql-action/init@v2
      with:
        languages: ${{ matrix.language }}
        # If you wish to specify custom queries, you can do so here or in a config file.
        # By default, queries listed here will override any specified in a config file.
        # Prefix the list here with "+" to use these queries and those in the config file.
        # queries: ./path/to/local/query, your-org/your-repo/queries@main

    # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).
    # If this step fails, then you should remove it and run the build manually (see below)
    - name: Autobuild
      uses: github/codeql-action/autobuild@v2

    # ℹ️ Command-line programs to run using the OS shell.
    # 📚 https://git.io/JvXDl

    # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
    #    and modify them (or add more) to build your code if your project
    #    uses a compiled language

    #- run: |
    #   make bootstrap
    #   make release

    - name: Perform CodeQL Analysis
      uses: github/codeql-action/analyze@v2


================================================
FILE: .github/workflows/linux.yml
================================================
name: Linux

on:
  push:
    paths-ignore:
      - 'README.md'
      - 'doc/**'
  pull_request:
    paths-ignore:
      - 'README.md'
      - 'doc/**'

jobs:
  linux:
    strategy:
      fail-fast: false
      matrix:
        compiler:
          - g++-9
          - g++-10
          - g++-11
          - g++-12
          - clang++-13
          - clang++-14
        build_type: [Debug, Release]

    runs-on: ubuntu-latest

    env:
      CXX: ${{ matrix.compiler }}

    steps:
    - uses: actions/checkout@v3
      with:
        submodules: recursive

    - run: cmake -E make_directory build

    - working-directory: build/
      run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=${{ matrix.build_type }}

    - working-directory: build/
      run: cmake --build .

    - working-directory: build/
      run: ctest --output-on-failure

  linux-old:
    strategy:
      fail-fast: false
      matrix:
        compiler:
          - clang++-11
          - clang++-12
        build_type: [Debug, Release]

    runs-on: ubuntu-latest

    env:
      CXX: ${{ matrix.compiler }}

    steps:
    - uses: actions/checkout@v3
      with:
        submodules: recursive

    - run: sudo apt-get update

    - run: sudo apt-get install -y ${{ matrix.compiler }}

    - run: cmake -E make_directory build

    - working-directory: build/
      run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=${{ matrix.build_type }}

    - working-directory: build/
      run: cmake --build .

    - working-directory: build/
      run: ctest --output-on-failure

  linux-clang-extra:
    strategy:
      fail-fast: false
      matrix:
        build_type: [Debug, Release]

    runs-on: ubuntu-latest

    env:
      CXX: clang++

    steps:
    - uses: actions/checkout@v3
      with:
        submodules: recursive

    - run: cmake -E make_directory build

    - working-directory: build/
      run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_CXX_FLAGS="-fms-extensions"

    - working-directory: build/
      run: cmake --build .

    - working-directory: build/
      run: ctest --output-on-failure


================================================
FILE: .github/workflows/macos.yml
================================================
name: macOS

on:
  push:
    paths-ignore:
      - 'README.md'
      - 'doc/**'
  pull_request:
    paths-ignore:
      - 'README.md'
      - 'doc/**'

jobs:
  xcode:
    strategy:
      fail-fast: false
      matrix:
        xcode: ['13', '14']
        build_type: [Debug, Release]

    runs-on: macos-latest

    steps:
    - uses: actions/checkout@v3
      with:
        submodules: recursive

    - uses: maxim-lobanov/setup-xcode@v1
      with:
        xcode-version: ${{ matrix.xcode }}

    - run: cmake -E make_directory build

    - working-directory: build/
      run: cmake $GITHUB_WORKSPACE

    - working-directory: build/
      run: cmake --build . --config ${{ matrix.build_type }}

    - working-directory: build/
      run: ctest --config ${{ matrix.build_type }} --output-on-failure


================================================
FILE: .github/workflows/sanitizer.yml
================================================
name: Sanitizer

on:
  push:
    paths-ignore:
      - 'README.md'
      - 'doc/**'
  pull_request:
    paths-ignore:
      - 'README.md'
      - 'doc/**'

jobs:
  sanitizer:
    strategy:
      fail-fast: false
      matrix:
        cxx: [g++, clang++]
        sanitizer: [address, undefined]

    runs-on: ubuntu-latest

    env:
      CXX: ${{ matrix.cxx }}

    steps:
    - uses: actions/checkout@v3
      with:
        submodules: recursive

    - run: cmake -E make_directory build

    - working-directory: build/
      run: cmake $GITHUB_WORKSPACE -DCMAKE_CXX_FLAGS="-fsanitize=${{ matrix.sanitizer }}"

    - working-directory: build/
      run: cmake --build .

    - working-directory: build/
      run: ctest --output-on-failure


================================================
FILE: .github/workflows/windows.yml
================================================
name: Windows

on:
  push:
    paths-ignore:
      - 'README.md'
      - 'doc/**'
  pull_request:
    paths-ignore:
      - 'README.md'
      - 'doc/**'

jobs:
  vs2022:
    strategy:
      fail-fast: false
      matrix:
        build_type: [Debug, Release]

    runs-on: windows-latest

    steps:
    - uses: actions/checkout@v3
      with:
        submodules: recursive

    - run: cmake -E make_directory build

    - shell: bash
      working-directory: build/
      run: cmake $GITHUB_WORKSPACE -G "Visual Studio 17 2022"

    - working-directory: build/
      run: cmake --build . --config ${{ matrix.build_type }}

    - working-directory: build/
      run: ctest -C ${{ matrix.build_type }} --output-on-failure

  vs2022-clang:
    strategy:
      fail-fast: false
      matrix:
        build_type: [Debug, Release]

    runs-on: windows-latest

    steps:
    - uses: actions/checkout@v3
      with:
        submodules: recursive

    - run: cmake -E make_directory build

    - shell: bash
      working-directory: build/
      run: cmake $GITHUB_WORKSPACE -G "Visual Studio 17 2022" -T ClangCL

    - working-directory: build/
      run: cmake --build . --config ${{ matrix.build_type }}

    - working-directory: build/
      run: ctest -C ${{ matrix.build_type }} --output-on-failure

  vs2019:
    strategy:
      fail-fast: false
      matrix:
        build_type: [Debug, Release]

    runs-on: windows-2019

    steps:
    - uses: actions/checkout@v3
      with:
        submodules: recursive

    - run: cmake -E make_directory build

    - shell: bash
      working-directory: build/
      run: cmake $GITHUB_WORKSPACE -G "Visual Studio 16 2019"

    - working-directory: build/
      run: cmake --build . --config ${{ matrix.build_type }}

    - working-directory: build/
      run: ctest -C ${{ matrix.build_type }} --output-on-failure

  vs2019-clang:
    strategy:
      fail-fast: false
      matrix:
        build_type: [Debug, Release]

    runs-on: windows-2019

    steps:
    - uses: actions/checkout@v3
      with:
        submodules: recursive

    - run: cmake -E make_directory build

    - shell: bash
      working-directory: build/
      run: cmake $GITHUB_WORKSPACE -G "Visual Studio 16 2019" -T ClangCL

    - working-directory: build/
      run: cmake --build . --config ${{ matrix.build_type }}

    - working-directory: build/
      run: ctest -C ${{ matrix.build_type }} --output-on-failure


================================================
FILE: .gitignore
================================================
*~
build
private


================================================
FILE: .gitmodules
================================================
[submodule "external/json"]
	path = external/json
	url = https://github.com/taocpp/json


================================================
FILE: CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.8...3.19)

project(taocpp-config VERSION 1.0.0 LANGUAGES CXX)

set(TAOCPP_CONFIG_IS_MAIN_PROJECT OFF)
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
  set(TAOCPP_CONFIG_IS_MAIN_PROJECT ON)
endif()

# installation directories
include(GNUInstallDirs)

set(TAOCPP_CONFIG_INSTALL_DOC_DIR "${CMAKE_INSTALL_DOCDIR}/tao/config" CACHE STRING "The installation doc directory")
set(TAOCPP_CONFIG_INSTALL_CMAKE_DIR "${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake" CACHE STRING "The installation cmake directory")

# define a header-only library
add_library(taocpp-config INTERFACE)
add_library(taocpp::config ALIAS taocpp-config)
target_include_directories(taocpp-config INTERFACE
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
  $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)

# require C++17
target_compile_features(taocpp-config INTERFACE cxx_std_17)

# find a suitable taoJSON
set(TAOCPP_CONFIG_JSON_MIN_VERSION 1.0.0)
find_package(taocpp-json ${TAOCPP_CONFIG_JSON_MIN_VERSION} QUIET CONFIG)
if(NOT taocpp-json_FOUND)
  # if a compatible version of taoJSON is not already installed, build and install it from the submodule directory
  message(STATUS "Adding taoJSON as submodule from external/json")
  set(TAOCPP_JSON_INSTALL ON)
  set(TAOCPP_JSON_INSTALL_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR} CACHE STRING "Override taoJSON include install directory")
  set(TAOCPP_JSON_INSTALL_CMAKE_DIR ${CMAKE_INSTALL_DATAROOTDIR}/json/cmake CACHE STRING "Override taoJSON cmake install directory")
  add_subdirectory(external/json)
endif()

# add taoJSON as a dependency
target_link_libraries(taocpp-config INTERFACE taocpp-json)

# testing
option(TAOCPP_CONFIG_BUILD_TESTS "Build test programs" ${TAOCPP_CONFIG_IS_MAIN_PROJECT})
if(TAOCPP_CONFIG_BUILD_TESTS)
  enable_testing()
  add_subdirectory(src/test/config)
endif()

# examples
option(TAOCPP_CONFIG_BUILD_EXAMPLES "Build example programs" ${TAOCPP_CONFIG_IS_MAIN_PROJECT})
if(TAOCPP_CONFIG_BUILD_EXAMPLES)
  add_subdirectory(src/example/config)
endif()

option(TAOCPP_CONFIG_INSTALL "Generate the install target" ${TAOCPP_CONFIG_IS_MAIN_PROJECT})
if(TAOCPP_CONFIG_INSTALL)
  include(CMakePackageConfigHelpers)

  # Make package findable
  configure_package_config_file(.cmake/taocpp-config-config.cmake.in ${PROJECT_NAME}-config.cmake
    INSTALL_DESTINATION ${TAOCPP_CONFIG_INSTALL_CMAKE_DIR}
    NO_CHECK_REQUIRED_COMPONENTS_MACRO
    NO_SET_AND_CHECK_MACRO
  )

  # Ignore pointer width differences since this is a header-only library
  unset(CMAKE_SIZEOF_VOID_P)

  # Enable version checks in find_package
  write_basic_package_version_file(${PROJECT_NAME}-config-version.cmake COMPATIBILITY SameMajorVersion)

  # keep taocpp::config target compatibility
  set_target_properties(taocpp-config PROPERTIES EXPORT_NAME config)

  # install and export target
  install(TARGETS taocpp-config taocpp-json EXPORT ${PROJECT_NAME}-targets)
  install(FILES
    ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake
    ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake
    DESTINATION ${TAOCPP_CONFIG_INSTALL_CMAKE_DIR}
  )
  install(EXPORT ${PROJECT_NAME}-targets
    NAMESPACE taocpp::
    DESTINATION ${TAOCPP_CONFIG_INSTALL_CMAKE_DIR}
  )

  install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
  install(FILES LICENSE DESTINATION ${TAOCPP_CONFIG_INSTALL_DOC_DIR})
endif()


================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2018-2023 Dr. Colin Hirsch and Daniel Frey

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: Makefile
================================================
# The Art of C++
# Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey
# Please see LICENSE for license or visit https://github.com/taocpp/config

.SUFFIXES:
.SECONDARY:

CXXSTD = -std=c++17
CPPFLAGS ?= -pedantic -Iinclude -Iexternal/json/include -Iexternal/json/external/PEGTL/include
CXXFLAGS ?= -Wall -Wextra -Werror -O3

HEADERS := $(shell find include -name "*.hpp")
SOURCES := $(shell find src -name '*.cpp')
DEPENDS := $(SOURCES:src/%.cpp=build/dep/%.d)
BINARIES := $(SOURCES:src/%.cpp=build/bin/%)

UNIT_TESTS := $(filter build/bin/test/%,$(BINARIES))

.PHONY: all
all: compile check

.PHONY: compile
compile: $(BINARIES)

.PHONY: check
check: $(UNIT_TESTS)
	echo $(UNIT_TESTS)
	@set -e; for T in $(UNIT_TESTS); do echo $$T; TAO_CONFIG_VAR=hello $$T; done

.PHONE: clean
clean:
	@rm -rf build/*
	@find . -name '*~' -delete

build/dep/%.d: src/%.cpp Makefile
	@mkdir -p $(@D)
	$(CXX) $(CXXSTD) $(CPPFLAGS) -MM -MQ $@ $< -o $@

build/bin/%: src/%.cpp build/dep/%.d
	@mkdir -p $(@D)
	$(CXX) $(CXXSTD) $(CPPFLAGS) $(CXXFLAGS) $< -o $@

ifeq ($(findstring $(MAKECMDGOALS),clean),)
-include $(DEPENDS)
endif


================================================
FILE: README.md
================================================
# The Art of C++ / Config

[![Windows CI](https://github.com/taocpp/config/workflows/Windows/badge.svg)](https://github.com/taocpp/config/actions?query=workflow%3AWindows)
[![macOS CI](https://github.com/taocpp/config/workflows/macOS/badge.svg)](https://github.com/taocpp/config/actions?query=workflow%3AmacOS)
[![Linux CI](https://github.com/taocpp/config/workflows/Linux/badge.svg)](https://github.com/taocpp/config/actions?query=workflow%3ALinux)
<br>
[![clang-analyze](https://github.com/taocpp/config/workflows/clang-analyze/badge.svg)](https://github.com/taocpp/config/actions?query=workflow%3Aclang-analyze)
[![clang-tidy](https://github.com/taocpp/config/workflows/clang-tidy/badge.svg)](https://github.com/taocpp/config/actions?query=workflow%3Aclang-tidy)
[![Sanitizer](https://github.com/taocpp/config/workflows/Sanitizer/badge.svg)](https://github.com/taocpp/config/actions?query=workflow%3ASanitizer)
[![CodeQL](https://github.com/taocpp/config/workflows/CodeQL/badge.svg)](https://github.com/taocpp/config/actions?query=workflow%3ACodeQL)
[![Code Coverage](https://codecov.io/gh/taocpp/config/branch/main/graph/badge.svg?token=ykWa8RRdyk)](https://codecov.io/gh/taocpp/config)

[The Art of C++] / Config is a C++ header-only library that reads config files in a format based on [JSON] and [JAXN] and produces a single [JSON Value] as result.

## Documentation

 * [Changelog](doc/Changelog.md)
 * [Version 1.x](doc/README.md) (requires C++17)

## Contact

For questions and suggestions regarding The Art of C++ / Config, success or failure stories, and any other kind of feedback, please feel free to open a [discussion](https://github.com/taocpp/config/discussions), an [issue](https://github.com/taocpp/config/issues) or a [pull request](https://github.com/taocpp/config/pulls) on GitHub or contact the authors at `taocpp(at)icemx.net`.

## Introduction

 * [JAXN] syntax with extensions (backward compatible with [JSON]).
 * [JAXN] data model ([JSON] extended with binary data and non-finites).
 * Meta data; all sub-values are annotated with filename and position.
 * Copy via [reference](Writing-Config-Files.md#references), [overwrite](Writing-Config-Files.md#overwrite) and [delete](Writing-Config-Files.md#delete) anything in the data structure.
 * [Include](doc/Writing-Config-Files.md#include-files) other config files into any position in the data structure.
 * And more, the complete list of features is documented on the [Writing Config Files](doc/Writing-Config-Files.md) page.
 * The function [`tao::config::from_file()`](doc/Parsing-Config-Files.md) is all you need to get going.

Every JSON file with a top-level object can be used as [config file](doc/Writing-Config-Files.md).

```
{
   "ip": "127.0.0.2",
   "port": 27960,
   "maps": [ "ztn", "dm13", "t9" ]
}
```

This small example can be rendered differently using some of the additional syntactic possibilities of the [config file](doc/Writing-Config-Files.md) format.

```
#!/usr/local/bin/q3s

ip = "127.0.0.2"
port = 27960
maps = [ "ztn" "dm13" "t9" ]  // Add dm6 or t4?
```

Semantic features like [deleting](doc/Writing-Config-Files.md#delete) and [referencing](doc/Writing-Config-Files.md#references) values, or [including files](doc/Writing-Config-Files.md#include-files) and [reading environment variables](doc/All-Config-Functions.md#env), usually only make sense with larger, non-trivial real-world examples.

These features can be used to manage situations that go beyond single deployments with a single config, for example providing the tools to manage configuration templates that are adapted to different environments.

[Parsing](doc/Parsing-Config-Files.md) a [config file](doc/Writing-Config-Files.md) is as simple as calling the appropriate `from_file()` function with the filename.

```
#include <tao/config.hpp>

const tao::config::value config = tao::config::from_file( "foo.cfg" );
```

The resulting value is a [JSON Value] from [taoJSON] with a custom taoCONFIG traits class that annotates every sub-value with the filename and position it was parsed from.
It can be inspected -- and manipulated -- using all the facilities of the [taoJSON] library.

## License

<a href="https://opensource.org/licenses/MIT"><img align="right" src="https://opensource.org/files/OSIApproved.png" width="150" hspace="20" alt="Open Source Initiative"></a>

The Art of C++ / Config is certified [Open Source] software.
It may be used for any purpose, including commercial purposes, at absolutely no cost.
It is distributed under the terms of the [MIT license] reproduced here.

> Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey
>
> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

[JAXN]: https://github.com/stand-art/jaxn/
[JSON]: https://tools.ietf.org/html/rfc8259
[JSON Value]: https://github.com/taocpp/json/
[MIT license]: http://www.opensource.org/licenses/mit-license.html
[Open Source]: http://www.opensource.org/docs/definition.html
[taoJSON]: https://github.com/taocpp/json/
[The Art of C++]: https://taocpp.github.io/


================================================
FILE: doc/All-Config-Functions.md
================================================
# All Config Functions

 * [binary](#binary)
 * [default](#default)
 * [env](#env)
 * [jaxn](#jaxn)
 * [parse](#parse)
 * [print](#print)
 * [read](#read)
 * [shell](#shell)
 * [split](#split)
 * [string](#string)

This page is the reference documentation for all included config functions.

The [general information on functions and how to use them can be found here.](Writing-Config-Files.md#functions)


## binary

The `binary` function explicitly transforms a string value into a binary value.
Only the type is changed, the sequence of bytes stays the same.

#### Example taoCONFIG Input File

```
foo = (binary "Hello, world!")
```

#### Resulting JAXN Config Data

```javascript
{
   foo: $48656C6C6F2C20776F726C6421
}
```


## default

The `default` function takes one or more arguments and returns the first one that is not a JSON `null`.
It is an error if all arguments are `null`.

#### Example taoCONFIG Input File

```
foo = (default 1 2)
bar = (default null false true)
```

#### Resulting JAXN Config Data

```javascript
{
   bar: false,
   foo: 1
}
```


## env

The `env` functions obtain the value of an environment variable as string.
For plain `env` it is an error when the environment variable does not exist, the `env?` alternative form returns a default value.

#### Example taoCONFIG Input File

```
foo = (env "USER")
bar = (env? "GRMBLFX" "default")
```

#### Resulting JAXN Config Data

```javascript
{
   bar: "default",
   foo: "colin"
}
```


## jaxn

The `jaxn` function parses string (or binary) data as [JAXN] and returns the resulting value.
In the case of binary data the input is automatically converted to a string, including a check for valid UTF-8.

#### Example taoCONFIG Input File

```
foo = (jaxn '[Infinity, $ff]')
```

#### Resulting JAXN Config Data

```javascript
{
   foo: [
      Infinity,
      $FF
   ]
}
```

Note that `jaxn` is frequently combined with `read` as in `foo = (jaxn (read "filename.jaxn"))`.


## parse

The `parse` function parses the given string as a single config value just "as if" the config file contained the string instead of the invocation of `parse`.

#### Example taoCONFIG Input File

```
foo = (parse "null")
```

#### Resulting JAXN Config Data

```javascript
{
   foo: null
}
```

This can be useful when combined with [`env`](#env) for environment variables that contain numeric values as in `foo = (parse (env "MYVAR"))`.

Note that the value described in the string is *not* allowed to use addition/concatenation, however references and functions *are* allowed.
Further, the `parse` function can **only** be used on "top-level", not inside of arguments to other functions.

For example `foo = (parse (default ...))` is allowed, but `foo = (default (parse ...) ...)` is not.


## print

The `print` function takes a part of the config and turns it back into a JAXN string (which is the same as a JSON string as long as the JAXN extension to the JSON data model, binary data and non-finite floating point numbers, are **not** used).

#### Example taoCONFIG Input File

```
(temporary foo)

foo
{
    b1 = true
    b2 = "Hello, Test!"
    b3 = [ $00, $deadbeef ]
    b4 = 42
}

str = (print (foo))
```

#### Resulting JAXN Config Data

```javascript
{
   str: "{b1:true,b2:\"Hello, Test!\",b3:[$00,$DEADBEEF],b4:42}"
}
```


## read

The `read` function returns the contents of a file as binary data.

#### Example taoCONFIG Input File

```
foo = (read "tests/doc_value_read.config")
bar = (string (read "tests/doc_value_read.config"))
```

#### Resulting JAXN Config Data

```javascript
{
   bar: "foo = (read \"tests/doc_value_read.config\")\nbar = (string (read \"tests/doc_value_read.config\"))\n",
   foo: $666F6F203D202872656164202274657374732F646F635F76616C75655F726561642E636F6E66696722290A626172203D2028737472696E67202872656164202274657374732F646F635F76616C75655F726561642E636F6E6669672229290A
}
```

Note that `read` can be combined with `string` to validate the data as UTF-8 and transform it into a string.

Note that the conversion from `binary` to `string` is automatic when the binary data is passed to a function that expects a string.
Like [`string`](#string), the automatic conversion checks whether the binary data is a valid UTF-8 sequence and throws an exception if that is not the case.


## shell

The `shell` function executes the given string as shell script and returns its output.

#### Example taoCONFIG Input File

```
foo = (shell "uname -s")
```

#### Resulting JAXN Config Data

```javascript
{
   foo: "Darwin\n"
}
```

Note that availability and behaviour of the `shell` function are inherently system dependent.
Currently it is only supported on Unix-style operating systems that are sufficiently POSIX compliant, most prominently Linux and macOS.


## split

The `split` function splits a string into its space-separated components and returns an array of them.
Here "space" is a non-empty sequence of `' ', '\n', '\r', '\t', '\v' and/or '\f'` characters.

#### Example taoCONFIG Input File

```
foo = (split "a b c ")
```

#### Resulting JAXN Config Data

```javascript
{
   foo: [
      "a",
      "b",
      "c"
   ]
}
```


## string

The `string` function transforms a binary value into a string value and leaves string values unchanged.
It validates that the binary data is valid UTF-8 and produces an error if that is not the case.

#### Example taoCONFIG Input File

```
foo = (string $48656C6C6F2C20776F726C6421)
```

#### Resulting JAXN Config Data

```javascript
{
   foo: "Hello, world!"
}
```

Note that the conversion from `binary` to `string` is automatic when the binary data is passed to a function that expects a string argument.
The automatic conversion, too, checks whether the binary data is a valid UTF-8 sequence and throws an exception if that is not the case.



Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey

[CBOR]: http://cbor.io
[JAXN]: https://github.com/stand-art/jaxn
[JSON]: https://tools.ietf.org/html/rfc8259
[MsgPack]: http://msgpack.org
[taoCONFIG]: https://github.com/taocpp/config
[taoJSON]: https://github.com/taocpp/json
[UBJSON]: http://ubjson.org


================================================
FILE: doc/Changelog.md
================================================
# Changelog

## 1.0.0

**Not yet released**

## Milestones

Pre-1.0.0 milestones in rough reverse chronological order.

* Restrict some phase 1 features[^1].
* Make functions[^2] a phase 2 features.
* Remove schema support (temporarily?).
* Reduce member extensions to the essentials.
* Remove the minus token from config keys.
* Change the semantics of star and move evaluation to phase two.
* Refactor everything in order to simplify the implementation.
* Syntactically turn `delete` into a literal pseudo-value.
* More intuitive semantics requires less knowledge of implementation details.
* Change the semantics to perform nested additions by default.
* Get the interactions between references and additions correct for both arrays and objects.

## History

Development of taoCONFIG started in September 2018 to provide a more expressive config file syntax for [JSON] (or [JAXN]) config files.



Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey

[^1]: Previously "member extensions".
[^2]: Previously "value extensions".
[JAXN]: https://github.com/stand-art/jaxn
[JSON]: https://tools.ietf.org/html/rfc8259


================================================
FILE: doc/Parsing-Config-Files.md
================================================
# Parsing Config Files

*  [Parsing](#parsing)
*  [Inspecting](#inspecting)
*  [Annotations](#annotations)
*  [Custom Traits](#custom-traits)
*  [Builtin Schema](#builtin-schema)

This library requires decent C++17 support.
Minimum supported compiler versions are GCC 9 and Clang 11.

The following assumes that the [PEGTL], [taoJSON] and [taoCONFIG] are all available to your compiler, i.e. the include paths are set up correctly.
When checking out [taoCONFIG] via git this can be achieved by (recursively!) initialising and updating all git submodules.

To access the facilities of this library simply include `<tao/config.hpp>` in your source(s).

## Parsing

The following functions read and parse one or more config files.
The return value is a single [taoJSON] Object in the form of a `tao::config::value` aka. `tao::json::basic_value< tao::config::traits >`.

```c++
tao::config::value tao::config::from_file( const std::filesystem::path& );
tao::config::value tao::config::from_files( const std::vector< std::filesystem::path >& files );
```

When more than one file is passed to `from_files()` it behaves (mostly) like parsing a single file with the concatenated contents (the only difference being that while individual files may optionally contain top-level curly braces for the implicit top-level JSON Object it would produce an error if the hypothetical concatenated file would contain multiple top-level objects).

The config can also be parsed from a `std::string` instead of a file.
The second parameter, `source`, should be a string that describes the source of the data.
It is used in error messages to indicate not just the line and column numbers.
See the [PEGTL] documentation for more details.

```c++
tao::config::value tao::config::from_string( const std::string& data, const std::string& source );
```

## Inspecting

Since the parsed config is returned as single [taoJSON] value object, a `tao::json::basic_value< tao::config::traits >`, all facilities from the [taoJSON] library can be used to inspect and operate on such an in-memory config representation.

## Annotations

By default, i.e. when using the included `tao::config::traits` for `tao::json::basic_value`, the [taoJSON] annotation feature is used to store the "config Key", as well as the filename (or, more generally, the source) and line and column numbers where they occurred in the parsed input.

The config Key is conceptually a kind of strongly typed JSON Pointer.
That is, unlike in a JSON Pointer, the string "2" and the integer 2 are distinguished.
Strings can only be used to index objects, and integers can only be used to index arrays.

The annotation feature sets up `tao::config::annotation` as public base class of every `tao::config::value` object, whereby the public data members of `tao::config::annotation` are available as public data members of every `tao::config::value`, the returned one and all of its sub-values.

These public data members are:

```c++
   tao::config::key key;
   tao::json::position position;  // From tao/json/contrib/position.hpp
```

## Custom Traits

The parsing functions are also available in a "basic" version that takes the traits for the returned [taoJSON] value as template parameter.

```c++
template< template< typename... > class Traits >
tao::json:basic_value< Traits > tao::config::basic_from_file( const std::filesystem::path& );

template< template< typename... > class Traits >
tao::json:basic_value< Traits > tao::config::basic_from_files( const std::vector< std::filesystem::path >& );

template< template< typename... > class Traits >
tao::json::basic_value< Traits > tao::config::basic_from_string( const std::string& data, const std::string& source );
```

Beyond the possibilities given to the traits by the [taoJSON] library this also gives control over the annotation.

The type `tao::config::annotation` implements the following non-static member functions that are used by the library to set the corresponding annotations.

```c++
   void set_key( tao::config::key&& );
   void set_position( const tao::pegtl::position& );
```

However these functions are only called when they are available, so a custom traits class template can choose to omit the annotations by either not setting up a public base class for the [taoJSON] values or by not implementing either or both of these functions in the public base.



Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey

[PEGTL]: https://github.com/taocpp/PEGTL
[taoCONFIG]: https://github.com/taocpp/config
[taoJSON]: https://github.com/taocpp/json


================================================
FILE: doc/README.md
================================================
# taoCONFIG Documentation

 * [Project](https://github.com/taocpp/config)
 * [Writing Config Files](Writing-Config-Files.md)
 * [All Config Functions](All-Config-Functions.md)
 * [Parsing Config Files](Parsing-Config-Files.md)
 * [Changelog](Changelog.md)



Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey


================================================
FILE: doc/Writing-Config-Files.md
================================================
# Writing Config Files

The config file syntax is based on [JSON] and is completely backwards compatible:

> **Every [JSON]** (or [JAXN]) **file** with a top-level [JSON] object **is a valid [taoCONFIG] file**.

The data model is also based on [JSON] and corresponds exactly to the [JAXN] data model as implemented by the [taoJSON] library.
We assume that the reader is somewhat familiar with [JSON] and its terminology.

 * [General Syntax](#general-syntax)
   - [Example](#example)
   - [Comments](#comments)
   - [Member Names](#member-names)
   - [Implicit Object](#implicit-object)
   - [Implicit Commas](#implicit-commas)
   - [Trailing Commas](#trailing-commas)
   - [Equality Sign](#equality-sign)
 * [Atomic Values](#atomic-values)
   - [Literal Names](#literal-names)
   - [Number Values](#number-values)
   - [String Values](#string-values)
   - [Binary Values](#binary-values)
 * [Additional Features](#additional-features)
   - [Additions](#additions)
   - [Overwrite](#overwrite)
   - [Delete](#delete)
   - [Asterisks](#asterisks)
   - [References](#references)
   - [Functions](#functions)
   - [Dotted Names](#dotted-names)
   - [Temporaries](#temporaries)
   - [Include Files](#include-files)
 * [Advanced Considerations](#advanced-considerations)



# General Syntax

This first section is in tutorial form.
It starts with a simple config file example in JSON form and successively introduces the main syntactic features of taoCONFIG by changing the example to use these features.


## Example

The config file syntax is based on [JSON] and is completely backwards compatible:
**Every [JSON]** or [JAXN] **file** with a top-level [JSON] object **is a valid [taoCONFIG] file**.

In particular curly braces and square brackets have the same role as in [JSON], namely defining objects (key-value mappings where the keys are strings) and arrays, respectively.

The following very simple example [JSON] file will be transformed by using the syntactic possibilities of [taoCONFIG] in the order they are introduced below.

#### Example JSON Config File

```javascript
{
   "ip": "127.0.0.2",
   "port": 27960,
   "maps": [ "ztn", "dm13", "t9" ]
}
```


## Comments

All comments that are allowed in [JAXN] can be used in config files, namely

* "shell-style" until-end-of-line with `#`,
* "C++-style" until-end-of-line with `//`,
* and "C-style" non-nesting block comments with `/*` and `*/`.

#### Example taoCONFIG Input File

```
#!/usr/local/bin/qs
{
   "ip": "127.0.0.2",
   "port": 27960,
   "maps": [ "ztn", "dm13", "t9" ]  // Add dm6 or t4?
}
```

#### Resulting JSON Config Data

```javascript
{
   "ip": "127.0.0.2",
   "maps": [
      "ztn",
      "dm13",
      "t9"
   ],
   "port": 27960
}
```


## Member Names

Member names can use single quotation marks instead of the standard [JSON] double quotation marks.

Member names that are C-style identifiers (non-empty sequences of ASCII characters, digits and underscores that do not start with a digit) can be written without quotation marks.

#### Example taoCONFIG Input File

```
#!/usr/local/bin/qs
{
   ip: "127.0.0.2",
   "port": 27960,
   'maps': [ "ztn", "dm13", "t9" ]  // Add dm6 or t4?
}
```

#### Resulting JSON Config Data

```javascript
{
   "ip": "127.0.0.2",
   "maps": [
      "ztn",
      "dm13",
      "t9"
   ],
   "port": 27960
}
```


## Implicit Object

The curly braces for the top-level object are optional and can be omitted.

#### Example taoCONFIG Input File

```
#!/usr/local/bin/qs

ip: "127.0.0.2",
port: 27960,
maps: [ "ztn", "dm13", "t9" ]  // Add dm6 or t4?
```

#### Resulting JSON Config Data

```javascript
{
   "ip": "127.0.0.2",
   "maps": [
      "ztn",
      "dm13",
      "t9"
   ],
   "port": 27960
}
```


## Implicit Commas

The commas separating array elements and object members are also optional and can be omitted.

#### Example taoCONFIG Input File

```
#!/usr/local/bin/qs

ip: "127.0.0.2"
port: 27960
maps: [ "ztn" "dm13" "t9" ]  // Add dm6 or t4?
```

#### Resulting JSON Config Data

```javascript
{
   "ip": "127.0.0.2",
   "maps": [
      "ztn",
      "dm13",
      "t9"
   ],
   "port": 27960
}
```

Note that every single separating comma is individually optional.


## Trailing Commas

A single trailing comma is permitted after the last array element or last object member, including after the last member of the implicit top-level object.

#### Example taoCONFIG Input File

```
#!/usr/local/bin/qs

ip: "127.0.0.2",
port: 27960,
maps: [ "ztn",
        "dm13",
        "t9", ],  // Add dm6 or t4?
```

#### Resulting JSON Config Data

```javascript
{
   "ip": "127.0.0.2",
   "maps": [
      "ztn",
      "dm13",
      "t9"
   ],
   "port": 27960
}
```


## Equality Sign

The equality sign `=` can be used instead of the standard [JSON] colon `:` to separate the name and value of an object member.

#### Example taoCONFIG Input File

```
#!/usr/local/bin/qs

ip = "127.0.0.2"
port = 27960
maps = [ "ztn" "dm13" "t9" ]  // Add dm6 or t4?
```

#### Resulting JSON Config Data

```javascript
{
   "ip": "127.0.0.2",
   "maps": [
      "ztn",
      "dm13",
      "t9"
   ],
   "port": 27960
}
```



# Atomic Values

Atomic values are just as in [JSON] and [JAXN].


## Literal Names

The three literal names `null`, `true` and `false` are carred over from [JSON].

#### Example taoCONFIG Input File

```
a = null
b = true
c = false
```

#### Resulting JSON Config Data

```javascript
{
   "a": null,
   "b": true,
   "c": false
}
```

Note that `null`, `true` and `false` as member names are shortcuts for `"null"`, `"true"` and `"false"`, respectively.


## Number Values

Numbers are like in [JAXN], i.e. [JSON] numbers with [extensions](https://github.com/stand-art/jaxn/blob/main/Specification.md#numbers).


## String Values

Strings are like in [JAXN], i.e. [JSON] strings with [extensions](https://github.com/stand-art/jaxn/blob/main/Specification.md#strings).


## Binary Values

[Binary data](https://github.com/stand-art/jaxn/blob/main/Specification.md#binary-data) is also exactly like in [JAXN].



# Additional Features

Features that extend the syntax and/or semantics beyond simple syntactic sugar for [JSON].


## Additions

Values of certain types can be added together explicitly or, in some cases, implicitly.

#### Numbers

For numbers the addition must be explicit and performs the usual addition, however:

Given that there are three data types for numeric values, signed integer, unsigned integer, and floating point, each with 64bits, the following rules are applied.

 * Integer values of the same signedness yield an integer with that signedness as result.
 * Integer values of mixed signedness are converted to signed integers before adding and yield a signed integer as result.
 * Floating-point values can only be added to other floating-point values and yield a floating-point value as result.

The order in which the additions are performed is undefined, e.g. `foo = 1 + 2 + 3` can be evaluated as either `(1 + 2) + 3` or `1 + (2 + 3)`.

```
foo = 42 + 10
foo += 3
// foo is 55
```

#### Strings

For strings the addition must be explicit and performs concatenation.

```
foo = "a" + "b"
foo += "c"
// foo is "abc"
```

Like in [JAXN] the same concatenations can be performed for binary data, and strings and binary data can **not** be mixed.

#### Arrays

For arrays the addition can be explicit or implicit and performs concatenation.

The implicit form is obtained by omitting a `+=` after a name.

```
foo = [ 1 2 ] + [ 3 ]
foo += [ 4 5 ]
foo [ 6 7 ]
// foo is [ 1 2 3 4 5 6 7 ]
```

#### Objects

For objects the addition can be explicit or implicit and performs an object "merge" operation.

For keys that exist only in one of the two objects being merged the result of the merge will contain that object member unchanged.

For keys that exist in both of the objects being merged the value of the member in the result will depend on whether the second object used a `=` or a `+=` to define the member.
In the case of `=` the member from the second object overwrites the member of the first, in the case of `+=` the corresponding values are recursively merged.

#### Example taoCONFIG Input File

```
foo
{
    a = 1
    b = 2
    c = 3
}
foo
{
    a = 10
    b += 20
    d = 40
}
```

#### Resulting JSON Config Data

```javascript
{
   foo: {
      a: 10,
      b: 22,
      c: 3,
      d: 40
   }
}
```


## Overwrite

A named object member can be assigned-to multiple times with the final assignment "winning".

#### Example taoCONFIG Input File

```
#!/usr/local/bin/qs

port = "TODO!"
ip = "127.0.0.2"
port = 27960
maps = [ "ztn" "dm13" "t9" ]  // Add dm6 or t4?
```

#### Resulting JSON Config Data

```javascript
{
   "ip": "127.0.0.2",
   "maps": [
      "ztn",
      "dm13",
      "t9"
   ],
   "port": 27960
}
```

Note that overwriting earlier values can be done on top-level or in any arbitrarily deeply nested part of the config.


## Delete

Previously defined values can be deleted with the literal pseudo-value `delete`.

#### Example taoCONFIG Input File

```
#!/usr/local/bin/qs

ip = "127.0.0.2"
port = 27960
maps = [ "ztn" "dm13" "t9" ]
maps = delete  // Changed our minds, no maps.
```

#### Resulting JSON Config Data

```javascript
{
   "ip": "127.0.0.2",
   "port": 27960
}
```

Deleted values can subsequently be assigned new values or added-to in which case they behave "as if" anything that was assigned or added prior to the `delete` never happened.

#### Example taoCONFIG Input File

```
foo = 42
foo = delete
foo += 44
```

#### Resulting JSON Config Data

```javascript
{
   foo: 44
}
```

Note that `delete` may not be an operand of an addition, i.e. `42 + delete` or similar are **not** allowed.


## Asterisks

The asterisk can be used as special name to designate all array or object members.
It is frequently used in conjunction with [dotted names](#dotted-names) to form a pattern for an assignment or addition.

#### Example taoCONFIG Input File

```
servers
{
    primary
    {
	port = 443
    }
    secondary
    {
        port = 8888
    }
}
servers.*.port = 7000  // Testing
```

#### Resulting JSON Config Data

```javascript
{
   servers: {
      primary: {
         port: 7000
      },
      secondary: {
         port: 7000
      }
   }
}
```

Assignments using asterisks **can** be combined with the literal pseudo-value `delete`.


## References

References are (nested) dotted names written in parentheses that refer to other parts of the config.
During processing of the config file they copy the referenced value.

```
foo = 42
bar = (foo)
// bar is 42
```

References are resolved relative to the array or object scope in which they syntactically occur, similar to how name lookups from within nested namespaces are handled in the C++ programming language.

#### Example taoCONFIG Input File

```
r = (a.b.x)

a
{
    b
    {
        c
        {
            i = (x)
            j = (b.x)
            k = (a.x)

            x = 4
	}
        x = 3
    }
    x = 2
}
x = 1
```

#### Resulting JSON Config Data

```javascript
{
   a: {
      b: {
         c: {
            i: 4,
            j: 3,
            k: 2,
            x: 4
         },
         x: 3
      },
      x: 2
   },
   r: 3,
   x: 1
}
```

It is an error if there is no order in which all additions, functions and references can be resolved due cyclic references!

#### Example Broken Input Files

Cyclic references are an error for obvious reasons.

```
a = (b)
b = (a)
```

It is also an error when a reference can't be resolved due to the first component of the reference "anchoring" the lookup to the "wrong" place.
Consider the following example:

```
a
{
    a
    {
        c = (a.b)
    }
    b = 1
}
```

The lookup of `a.b` starts by attempting to find `a` inside of `a.a`.
This fails because there is only `c` within `a.a`, not another `a` that could be matched to the `a` in `a.b`.
Next the lookup steps outside of `a.a` and attempts to find the `a` from `a.b` within `a`.
This succeeds, anchoring the lookup of `a.b` to `a.a`.
More precisely, the second component of `a.a` is matched with the first component of `a.b`.
Now the example generates an error because there is no `b` within `a.a`.

The search is not continued inside the top-level `a` because once the lookup is anchored no backtracking is performed.
This is similar to the name lookup rules in the C++ programming language.


### Nested References

References can be arbitrarily **nested**, that is parts of a reference can themselves be a reference!
For this to work the "inner" reference must refer to a value that can natuarlly occur as part of a reference, namely a string or an integer.

#### Example taoCONFIG Input File

```
foo = [ 10 11 12 13 14 ]
bar = 3
baz = (foo.(bar))
```

#### Resulting JSON Config Data

```javascript
{
   bar: 3,
   baz: 13,
   foo: [
      10,
      11,
      12,
      13,
      14
   ]
}
```

### References vs. Temporary

When referencing values marked as [temporary](Member-Extensions.md#temporary) the copied value will **not** be marked as [temporary](#temporaries), however any sub-values will retain their temporary status.

#### Example taoCONFIG Input File

```
(temporary foo)
(temporary foo.baz)

foo
{
    bar
    {
        a = 1
    }
    baz
    {
        b = 2
    }
}

ttt = (foo)
```

#### Resulting JSON Config Data

```javascript
{
   ttt: {
      bar: {
         a: 1
      }
   }
}
```


## Functions

This library contains [a set of config functions](All-Config-Functions.md).
These functions can be used in config files to perform operations on values.
Applications can also add custom functions.

Functions are syntactically similar to references in taoCONFIG, and to lists or function calls in Scheme and LISP.
A function call has one or more arguments, wherefore `(foo)` is parsed as a reference rather than a call to a nullary function.

For example the following config file assigns the value of the environment (shell) variable `$USER` to the config key `foo`.

```
foo = (env "USER")
```

Functions can occur anywhere a value can occur.
A function's arguments can be literal values, other function calls, additions, references, or any combination or nesting of these.

The next example does the same as the previous one, albeit in a slightly contrived manner that shows a composed function argument with reference.

```
bar = "ER"
foo = (env "US" + (bar))
```

The config functions supplied with this library are listed and explained on [a separate page](All-Config-Functions.md).

To add custom functions to a config parser and make them available to your config files please consult `src/test/config/custom.cpp` or contact the developers of this library.


## Dotted Names

Wherever the name of an object member is expected it is also possible to use a name with multiple dot-separated components.

Dotted names can contain multiple kinds of components.

1.  Strings, intended to index objects.
2.  Unsigned integers, intended to index arrays.
4.  The [asterisk](#asterisks), intended to index objects or arrays.

The asterisk indexes into all object members or array elements.

#### Example taoCONFIG Input File

```
foo
{
    bar.baz += 1
}
foo.bar
{
    baz += 1
}
foo.bar.baz += 1
```

#### Resulting JSON Config Data

```javascript
{
   foo: {
      bar: {
         baz: 3
      }
   }
}
```

Just as for single-component names, integers, and other strings that are not C-style identifiers can be used with (single or double) quotes.
For example the dotted name `foo."1.2.3".bar` consists of three components, the strings `"foo"`, `"1.2.3"` and `"bar"`.

Dotted names can be thought of as strongly-typed JSON Pointers; there is no ambiguity about whether an integer is intended to index an array or an object.


## Include Files

The `include` feature reads the named file relative to the current working directory and parses it "as if" the contents of that file were present instead of the `include`.
For plain `include` it is an error when the file does not exist, the `include?` alternative form silently ignores this case.

The filename has to be supplied as non-empty string in double quotes and can contain arbitrary characters except for the double quote itself.
Consequently, and unlike all other quoted strings in this library, *no escape sequences* are recognised.

Files can be included anywhere an object member can be defined.
The top-level definitions of the included file will appear in the same place of the JSON hierarchy as the `include`.

#### Example taoCONFIG Input File

```
// Include the file whose contents are shown below.
(include "tests/doc_include.inc")

foo
{
    // Include the same file again, this time within an object.
    (include "tests/doc_include.inc")
}

// Use include? with a non-existing file, not an error.
(include? "tests/non_existing_file_is_no_error_with_include?")
```

#### Example taoCONFIG Include File

```
bar = 42
baz = [ true, false ]
```

#### Resulting JAXN Config Data

```javascript
{
   bar: 42,
   baz: [
      true,
      false
   ],
   foo: {
      bar: 42,
      baz: [
         true,
         false
      ]
   }
}
```


## Temporaries

Sometimes parts of the configuration that are required during config file parsing, for example in order to be [referenced](#references), are not themselves considered part of the actual config.
In these cases the `temporary` feature can be used to exclude any part of the JSON hierarchy from the final config parsing result.

Like `include` the `temporary` statement can occur anywhere an object member can be defined.
It takes a single config key, which can include [asterisks](#asterisks) and be any [dotted name](#dotted-names), as argument.

The argument is always interpreted relative to the position of the `temporary` in the object hierarchy.
For example a `(temporary c.d)` within an object at `a.b` would mark `a.b.c.d` as temporary, independent of whether that node exists (yet).

#### Example taoCONFIG Input File

```
(temporary template)  // Can occur before...

template
{
    host = "127.0.0.1"
    port = 6000
    version = 42
}

foo = (template) +
{
    host = "127.0.0.2"
}

bar = (template) +
{
    port = 6001
}

(temporary template)  // ...and/or after.

```

#### Resulting JAXN Config Data

```javascript
{
   bar: {
      host: "127.0.0.1",
      port: 6001,
      version: 42
   },
   foo: {
      host: "127.0.0.2",
      port: 6000,
      version: 42
   }
}
```

Similarly the `permanent` feature can be used to restore any part of the JSON hierarchy that was marked as `temporary` to the default behaviour of being part of the final result data.



# Advanced Considerations

For technical reasons reading a configuration is performed in multiple steps.
Authors of config files need to be aware of the two main phases in order to fully understand the semantics of their configs.

### Phase One

The first phase does the reading and parsing of all configuration files.

During this phase all assignments, additions and deletions are recorded in their order of occurrence.
The same goes for included files, their assignments, additions and deletions are performed when and where the include was encountered during parsing.

### Phase Two

The second phase successively replaces all functions, references and additions with the result of their evaluation.

During this phase the order in which things were parsed is no longer relevant.

 * Functions are eliminated as soon as their arguments are "plain" values, i.e. they are free from functions, references and additions, by replacing the function with the result of calling said function.
 * References are eliminated as soon as the referenced value is "plain", by replacing the reference with a (deep) copy of the referenced value.
 * Additions are eliminated as soon as both operands are "plain", again by replacing the two operands with the result of the addition (which can be a concatenation, or, for objects, a merge).

### Why Phases?

The semantics of `delete`, `+=` and `=`, and, by extension, `include`, depends on the order in which they are processed.
This is due to the combination of features being non-monotonic, which requires linear processing for predictable behaviour.

However for references this would be too limiting as only previously defined values could be referenced, and delta[^1] config files might not be able to make the required modifications.
With references that can "point" both forwards and backwards this problem does not arise.

#### Example taoCONFIG Input File

```
hosts
{
    arctic
    {
        foo = 42
    }
    mystic
    {
        foo = 23
    }
}
host = (env "HOST")

(temporary host)
(temporary hosts)

config
{
    mode = "FOBBLE"
    size = (hosts.(host).foo)
}

(include? "test_delta_config.cfg")
```

This example shows a configuration with parameters that depend on the name of the host machine.

#### Example taoCONFIG Delta File

```
hosts.test01.foo = 3
```

If references were resolved when encountered then the delta config would have no effect -- the `foo` value for the additional host `test01` would be available only *after* the refernce for `config.size` was resolved.

Luckily this is not how taoCONFIG works, the references are resolved during the second phase, and everything will work as expected.



Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey

[^1]: A "delta" config is typically a configuration file that is optionally included at the end of a full configuration file. The full configuration file usually configures an application for an operational environment; the delta config can optionally modify the full configuration, e.g. for a test environment that might be funcionally identical to the operational environment but have minor differences like using different hostnames.

[CBOR]: http://cbor.io
[JAXN]: https://github.com/stand-art/jaxn
[JSON]: https://tools.ietf.org/html/rfc8259
[MsgPack]: http://msgpack.org
[taoCONFIG]: https://github.com/taocpp/config
[taoJSON]: https://github.com/taocpp/json
[UBJSON]: http://ubjson.org


================================================
FILE: include/tao/config/access.hpp
================================================
// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_ACCESS_HPP
#define TAO_CONFIG_ACCESS_HPP

#include <cassert>
#include <stdexcept>

#include "key.hpp"
#include "value.hpp"

#include "internal/json.hpp"
#include "internal/string_utility.hpp"

namespace tao::config
{
   template< template< typename... > class Traits >
   [[nodiscard]] const json::basic_value< Traits >& access( const json::basic_value< Traits >& v, const key& k );

   template< template< typename... > class Traits >
   [[nodiscard]] const json::basic_value< Traits >& access_name( const json::basic_value< Traits >& v, const std::string& k, const key& p )
   {
      if( !v.is_object() ) {
         throw std::runtime_error( internal::strcat( "attempt to index non-object with \"", k, "\"" ) );
      }
      const auto j = v.get_object().find( k );

      if( j == v.get_object().end() ) {
         throw std::runtime_error( internal::strcat( "object index \"", k, "\" not found" ) );
      }
      return access( j->second, p );
   }

   template< template< typename... > class Traits >
   [[nodiscard]] const json::basic_value< Traits >& access_index( const json::basic_value< Traits >& v, const std::size_t n, const key& p )
   {
      if( !v.is_array() ) {
         throw std::runtime_error( internal::strcat( "attempt to index non-array with ", n ) );
      }
      if( v.get_array().size() <= n ) {
         throw std::runtime_error( internal::strcat( "array index ", n, " out of bounds ", v.get_array().size() ) );
      }
      return access( v.get_array()[ n ], p );
   }

   template< template< typename... > class Traits >
   [[nodiscard]] const json::basic_value< Traits >& access( const json::basic_value< Traits >& v, const key& k )
   {
      if( k.empty() ) {
         return v;
      }
      switch( k[ 0 ].kind() ) {
         case key_kind::name:
            return access_name( v, k[ 0 ].get_name(), pop_front( k ) );
         case key_kind::index:
            return access_index( v, k[ 0 ].get_index(), pop_front( k ) );
      }
      throw std::logic_error( "code should be unreachable" );  // LCOV_EXCL_LINE
   }

}  // namespace tao::config

#endif


================================================
FILE: include/tao/config/annotation.hpp
================================================
// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_ANNOTATION_HPP
#define TAO_CONFIG_ANNOTATION_HPP

#include <ostream>

#include <tao/json.hpp>
#include <tao/json/contrib/position.hpp>

#include <tao/pegtl/position.hpp>

#include "key.hpp"

namespace tao::config
{
   struct annotation
   {
      config::key key;
      json::position position;  // TODO: json::position, pegtl::position or TBD config::position?

      annotation() = default;

      annotation( annotation&& ) = default;
      annotation& operator=( annotation&& ) = default;

      annotation( const annotation& ) = default;
      annotation& operator=( const annotation& ) = default;

      void set_key( config::key k ) noexcept
      {
         key = std::move( k );
      }

      void set_position( json::position p ) noexcept
      {
         position = std::move( p );
      }

      void set_position( const pegtl::position& pos )
      {
         position.set_position( pos );
      }

      void append_message_extension( std::ostream& o ) const
      {
         to_stream( o, key );
         o << ' ';
         position.append_message_extension( o );
      }
   };

}  // namespace tao::config

#endif


================================================
FILE: include/tao/config/assign.hpp
================================================
// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_ASSIGN_HPP
#define TAO_CONFIG_ASSIGN_HPP

#include <cassert>
#include <stdexcept>

#include "key.hpp"
#include "value.hpp"

#include "internal/json.hpp"
#include "internal/string_utility.hpp"

namespace tao::config
{
   template< template< typename... > class Traits >
   [[nodiscard]] json::basic_value< Traits >& assign( json::basic_value< Traits >& v, const key& k );

   template< template< typename... > class Traits >
   [[nodiscard]] json::basic_value< Traits >& assign( json::basic_value< Traits >& v, const std::string& k, const key& p )
   {
      if( !v.is_object() ) {
         throw std::runtime_error( internal::strcat( "attempt to index non-object with \"", k, "\"" ) );
      }
      const auto t = v.get_object().try_emplace( k, json::empty_object );  // TODO: Detect empty_array vs. empty_object?
      return assign( t.first->second, p );
   }

   template< template< typename... > class Traits >
   [[nodiscard]] json::basic_value< Traits >& assign( json::basic_value< Traits >& v, const std::size_t n, const key& p )
   {
      if( !v.is_array() ) {
         throw std::runtime_error( internal::strcat( "attempt to index non-array with ", n ) );
      }
      if( v.get_array().size() <= n ) {
         throw std::runtime_error( internal::strcat( "array index ", n, " out of bounds ", v.get_array().size() ) );
      }
      return assign( v.get_array()[ n ], p );
   }

   template< template< typename... > class Traits >
   [[nodiscard]] json::basic_value< Traits >& assign( json::basic_value< Traits >& v, const key& k )
   {
      if( k.empty() ) {
         return v;
      }
      switch( k[ 0 ].kind() ) {
         case key_kind::name:
            return assign( v, k[ 0 ].get_name(), pop_front( k ) );
         case key_kind::index:
            return assign( v, k[ 0 ].get_index(), pop_front( k ) );
      }
      throw std::logic_error( "code should be unreachable" );  // LCOV_EXCL_LINE
   }

}  // namespace tao::config

#endif


================================================
FILE: include/tao/config/contrib/rot13.hpp
================================================
// Copyright (c) 2022-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_CONTRIB_ROT13_HPP
#define TAO_CONFIG_CONTRIB_ROT13_HPP

#include <string>

#include "../internal/atom.hpp"
#include "../internal/pegtl.hpp"

namespace tao::config
{
   [[nodiscard]] inline internal::string_t rot13( const pegtl::position& pos, const std::string& in )
   {
      internal::string_t out( in, pos );

      for( char& c : out.value ) {
         if( ( ( 'a' <= c ) && ( c <= 'm' ) ) || ( ( 'A' <= c ) && ( c <= 'M' ) ) ) {
            c += 13;
         }
         else if( ( ( 'n' <= c ) && ( c <= 'z' ) ) || ( ( 'N' <= c ) && ( c <= 'Z' ) ) ) {
            c -= 13;
         }
      }
      return out;
   }

}  // namespace tao::config

#endif


================================================
FILE: include/tao/config/from_file.hpp
================================================
// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_FROM_FILE_HPP
#define TAO_CONFIG_FROM_FILE_HPP

#include <filesystem>
#include <utility>

#include "internal/config_parser.hpp"
#include "value.hpp"

namespace tao::config
{
   template< template< typename... > class Traits >
   [[nodiscard]] json::basic_value< Traits > basic_from_file( const std::filesystem::path& path )
   {
      internal::config_parser c;
      c.parse( path );
      return c.finish< Traits >();
   }

   [[nodiscard]] inline value from_file( const std::filesystem::path& path )
   {
      return basic_from_file< traits >( path );
   }

}  // namespace tao::config

#endif


================================================
FILE: include/tao/config/from_files.hpp
================================================
// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_FROM_FILES_HPP
#define TAO_CONFIG_FROM_FILES_HPP

#include <filesystem>
#include <utility>
#include <vector>

#include "internal/config_parser.hpp"
#include "value.hpp"

namespace tao::config
{
   template< template< typename... > class Traits >
   [[nodiscard]] json::basic_value< Traits > basic_from_files( const std::vector< std::filesystem::path >& paths )
   {
      internal::config_parser c;
      for( const auto& path : paths ) {
         c.parse( path );
      }
      return c.finish< Traits >();
   }

   [[nodiscard]] inline value from_files( const std::vector< std::filesystem::path >& paths )
   {
      return basic_from_files< traits >( paths );
   }

}  // namespace tao::config

#endif


================================================
FILE: include/tao/config/from_input.hpp
================================================
// Copyright (c) 2019-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_FROM_INPUT_HPP
#define TAO_CONFIG_FROM_INPUT_HPP

#include <utility>

#include "internal/config_parser.hpp"
#include "internal/pegtl.hpp"
#include "value.hpp"

namespace tao::config
{
   template< template< typename... > class Traits >
   [[nodiscard]] json::basic_value< Traits > basic_from_input( pegtl_input_t&& in )
   {
      internal::config_parser c;
      c.parse( std::move( in ) );
      return c.finish< Traits >();
   }

   [[nodiscard]] inline value from_input( pegtl_input_t&& in )
   {
      return basic_from_input< traits >( std::move( in ) );
   }

}  // namespace tao::config

#endif


================================================
FILE: include/tao/config/from_string.hpp
================================================
// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_FROM_STRING_HPP
#define TAO_CONFIG_FROM_STRING_HPP

#include <string>
#include <string_view>
#include <utility>

#include "internal/config_parser.hpp"
#include "value.hpp"

namespace tao::config
{
   template< template< typename... > class Traits >
   [[nodiscard]] json::basic_value< Traits > basic_from_string( const char* data, const std::size_t size, const std::string& source )
   {
      internal::config_parser c;
      c.parse( data, size, source );
      return c.finish< Traits >();
   }

   template< template< typename... > class Traits >
   [[nodiscard]] json::basic_value< Traits > basic_from_string( const std::string_view data, const std::string& source )
   {
      return basic_from_string< Traits >( data.data(), data.size(), source );
   }

   [[nodiscard]] inline value from_string( const char* data, const std::size_t size, const std::string& source )
   {
      return basic_from_string< traits >( data, size, source );
   }

   [[nodiscard]] inline value from_string( const std::string_view data, const std::string& source )
   {
      return from_string( data.data(), data.size(), source );
   }

}  // namespace tao::config

#endif


================================================
FILE: include/tao/config/internal/array.hpp
================================================
// Copyright (c) 2019-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_ARRAY_HPP
#define TAO_CONFIG_INTERNAL_ARRAY_HPP

#include <list>
#include <string>

#include "forward.hpp"
#include "pegtl.hpp"

namespace tao::config::internal
{
   template< typename C >
   struct basic_array
   {
      using data_t = std::list< C >;

      basic_array() = delete;

      explicit basic_array( const pegtl::position& p )
         : position( p )
      {}

      explicit basic_array( const std::string& f, const pegtl::position& p )
         : function( f ),
           position( p )
      {}

      basic_array( basic_array&& ) = default;
      basic_array( const basic_array& ) = default;

      ~basic_array() = default;

      basic_array& operator=( basic_array&& ) = default;
      basic_array& operator=( const basic_array& ) = default;

      [[nodiscard]] const pegtl::position& get_position() const noexcept
      {
         return position;
      }

      std::string function;
      std::list< C > array;
      pegtl::position position;
   };

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/atom.hpp
================================================
// Copyright (c) 2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_ATOM_HPP
#define TAO_CONFIG_INTERNAL_ATOM_HPP

#include <cstdint>
#include <string>
#include <utility>
#include <vector>

#include "pegtl.hpp"

namespace tao::config::internal
{
   struct null
   {
      explicit null( const pegtl::position& pos )
         : position( pos )
      {}

      [[nodiscard]] const pegtl::position& get_position() const noexcept
      {
         return position;
      }

      pegtl::position position;
   };

   template< typename T >
   struct atom
   {
      template< typename V >
      atom( V&& v, const pegtl::position& pos )
         : value( std::forward< V >( v ) ),
           position( pos )
      {}

      [[nodiscard]] const pegtl::position& get_position() const noexcept
      {
         return position;
      }

      T value;
      pegtl::position position;
   };

   using boolean = atom< bool >;
   using string_t = atom< std::string >;
   using binary_t = atom< std::vector< std::byte > >;

   using signed_t = atom< std::int64_t >;
   using unsigned_t = atom< std::uint64_t >;
   using double_t = atom< double >;

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/change_action_and_states.hpp
================================================
// Copyright (c) 2019-2024 Dr. Colin Hirsch and Daniel Frey
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)

#ifndef TAO_CONFIG_INTERNAL_CHANGE_ACTION_AND_STATES_HPP
#define TAO_CONFIG_INTERNAL_CHANGE_ACTION_AND_STATES_HPP

#include <cstddef>
#include <tuple>
#include <type_traits>
#include <utility>

#include "pegtl.hpp"

namespace tao::config::internal
{
   template< template< typename... > class NewAction, typename... NewStates >
   struct change_action_and_states
      : pegtl::maybe_nothing
   {
      template< typename Rule,
                pegtl::apply_mode A,
                pegtl::rewind_mode M,
                template< typename... >
                class Action,
                template< typename... >
                class Control,
                std::size_t... Ns,
                typename ParseInput,
                typename... States >
      [[nodiscard]] static bool match( std::index_sequence< Ns... > /*unused*/, ParseInput& in, States&&... st )
      {
         auto t = std::tie( st... );
         const auto pos = in.position();
         if( Control< Rule >::template match< A, M, NewAction, Control >( in, std::get< Ns >( t )... ) ) {
            if constexpr( A == pegtl::apply_mode::action ) {
               Action< Rule >::success( pos, st... );
            }
            return true;
         }
         return false;
      }

      template< typename Rule,
                pegtl::apply_mode A,
                pegtl::rewind_mode M,
                template< typename... >
                class Action,
                template< typename... >
                class Control,
                typename ParseInput,
                typename... States >
      [[nodiscard]] static bool match( ParseInput& in, States&&... st )
      {
         static_assert( !std::is_same_v< Action< void >, NewAction< void > >, "old and new action class templates are identical" );
         return match< Rule, A, M, Action, Control >( std::index_sequence_for< NewStates... >(), in, NewStates()..., st... );
      }
   };

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/concat.hpp
================================================
// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_CONCAT_HPP
#define TAO_CONFIG_INTERNAL_CONCAT_HPP

#include <cstddef>
#include <cstdint>
#include <iterator>
#include <list>
#include <stdexcept>
#include <string>
#include <utility>

#include "constants.hpp"
#include "entry_kind.hpp"
#include "forward.hpp"
#include "json.hpp"
#include "key1.hpp"
#include "pegtl.hpp"

namespace tao::config::internal
{
   template< typename E >
   struct basic_concat
   {
      using data_t = std::list< E >;
      using iterator_t = typename std::list< E >::iterator;

      basic_concat() = delete;

      explicit basic_concat( const pegtl::position& p )
         : position( p )
      {}

      basic_concat( basic_concat&& ) = default;
      basic_concat( const basic_concat& ) = default;

      ~basic_concat() = default;

      basic_concat& operator=( basic_concat&& ) = default;
      basic_concat& operator=( const basic_concat& ) = default;

      [[nodiscard]] bool omit_from_final_result() const noexcept
      {
         return implicit || temporary || concat.empty();
      }

      template< typename T >
      void back_ensure_init( const T k, const pegtl::position& p )
      {
         if( concat.empty() ) {
            concat.emplace_back( k, p );
         }
         else if( concat.back().kind() != T::kind ) {
            concat.emplace_back( k, p );
         }
      }

      void back_emplace_func( const std::string& name, const pegtl::position& p )
      {
         back_ensure_init( array_init, p );
         concat.back().get_array().function = name;
      }

      [[nodiscard]] const pegtl::position& get_position() const noexcept
      {
         return position;
      }

      bool remove = false;     // Whether generated by += (false) or by = (true), because in the latter case everything that comes before must be removed.
      bool implicit = false;   // Whether implicitly generated by a delete, e.g. a.b.c = delete when a.b doesn't even exist, so it's implicitly generated to set the remove flag on a.b.c.
      bool temporary = false;  // Whether flagged as temporary by the user, i.e. this is not to be included in the final result and will be omitted by phase3.

      std::uint64_t generation = 0;

      std::list< E > concat;
      pegtl::position position;
   };

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/config_action.hpp
================================================
// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_CONFIG_ACTION_HPP
#define TAO_CONFIG_INTERNAL_CONFIG_ACTION_HPP

#include <cassert>
#include <cerrno>
#include <string>
#include <system_error>
#include <utility>
#include <vector>

#include "concat.hpp"
#include "config_grammar.hpp"
#include "constants.hpp"
#include "entry_kind.hpp"
#include "forward.hpp"
#include "json.hpp"
#include "key1.hpp"
#include "key1_action.hpp"
#include "key1_guard.hpp"
#include "pegtl.hpp"
#include "phase1_append.hpp"
#include "string_utility.hpp"

namespace tao::config::internal
{
   template< typename Rule >
   struct config_action
      : pegtl::nothing< Rule >
   {};

   template<>
   struct config_action< rules::assign_head >
   {
      template< typename State >
      static void apply0( State& st, const function_map& /*unused*/ )
      {
         const auto f = []( concat& c ) { c.concat.clear(); c.remove = true; };
         phase1_append( st.root, st.prefix + st.suffix, f, phase1_mode::implicit );
      }
   };

   template<>
   struct config_action< json::jaxn::internal::rules::begin_array >
   {
      template< typename Input, typename State >
      static void apply( Input& in, State& st, const function_map& /*unused*/ )
      {
         const auto p = in.position();
         const auto f = [ & ]( concat& c ) { c.back_ensure_init( array_init, p ); };
         phase1_append( st.root, st.prefix + st.suffix, f, phase1_mode::manifest );
      }
   };

   template<>
   struct config_action< json::jaxn::internal::rules::begin_object >
   {
      template< typename Input, typename State >
      static void apply( Input& in, State& st, const function_map& /*unused*/ )
      {
         const auto p = in.position();
         const auto f = [ & ]( concat& c ) { c.back_ensure_init( object_init, p ); };
         phase1_append( st.root, st.prefix + st.suffix, f, phase1_mode::manifest );
      }
   };

   template<>
   struct config_action< rules::function_name >
   {
      template< typename Input, typename State >
      static void apply( Input& in, State& st, const function_map& /*unused*/ )
      {
         const auto s = in.string();
         const auto p = in.position();
         const auto f = [ & ]( concat& c ) { c.back_emplace_func( s, p ); };
         phase1_append( st.root, st.prefix + st.suffix, f, phase1_mode::manifest );
      }
   };

   template<>
   struct config_action< rules::value_list >
   {
      template< typename State >
      static void apply0( State& st, const function_map& /*unused*/ )
      {
         assert( !st.suffix.empty() );

         st.suffix.back().set_generation( ++st.generation );
      }
   };

   template<>
   struct config_action< rules::element_list >
      : pegtl::instantiate< key1_guard >
   {};

   template<>
   struct config_action< rules::extension_list >
      : pegtl::instantiate< key1_guard >
   {};

   template<>
   struct config_action< rules::key1_rule >
      : pegtl::change_action_and_state< key1_action, std::vector< key1_part > >
   {
      template< typename Input, typename State >
      static void success( const Input& /*unused*/, std::vector< key1_part >& s, State& st, const function_map& /*unused*/ )
      {
         assert( st.member.empty() );
         std::swap( st.member.vector(), s );
      }
   };

   template<>
   struct config_action< rules::temporary_extension >
   {
      template< typename State >
      static void apply0( State& st, const function_map& /*unused*/ )
      {
         assert( !st.member.empty() );
         const auto f = []( concat& c ) { c.temporary = true; };
         phase1_append( st.root, st.prefix + st.suffix + st.member, f, phase1_mode::implicit );
         st.member.vector().clear();
      }
   };

   template<>
   struct config_action< rules::permanent_extension >
   {
      template< typename State >
      static void apply0( State& st, const function_map& /*unused*/ )
      {
         assert( !st.member.empty() );
         const auto f = []( concat& c ) { c.temporary = false; };
         phase1_append( st.root, st.prefix + st.suffix + st.member, f, phase1_mode::implicit );
         st.member.vector().clear();
      }
   };

   template<>
   struct config_action< rules::include >
   {
      template< typename State >
      static void apply0( State& st, const function_map& /*unused*/ )
      {
         st.include_is_optional = false;
      }
   };

   template<>
   struct config_action< rules::inc_if >
   {
      template< typename State >
      static void apply0( State& st, const function_map& /*unused*/ )
      {
         st.include_is_optional = true;
      }
   };

   template<>
   struct config_action< rules::inc_fn >
   {
      template< typename Input, typename State >
      static void apply( const Input& ai, State& st, const function_map& fm )
      {
         try {
            pegtl::file_input in( ai.string() );
            pegtl::parse_nested< rules::config_file, config_action >( ai.position(), static_cast< pegtl_input_t& >( in ), st, fm );
         }
         catch( const std::system_error& e ) {
            if( !st.include_is_optional ) {
               throw pegtl::parse_error( strcat( "include error: ", e.what() ), ai.position() );
            }
            if( e.code().value() != ENOENT ) {
               throw pegtl::parse_error( strcat( "include optional error: ", e.what() ), ai.position() );
            }
         }
      }
   };

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/config_grammar.hpp
================================================
// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_CONFIG_GRAMMAR_HPP
#define TAO_CONFIG_INTERNAL_CONFIG_GRAMMAR_HPP

#include "forward.hpp"
#include "jaxn_action.hpp"
#include "jaxn_to_entry.hpp"
#include "json.hpp"
#include "key1_grammar.hpp"
#include "key1_guard.hpp"
#include "parse_utility.hpp"
#include "pegtl.hpp"
#include "phase1_append.hpp"
#include "reference2.hpp"

namespace tao::config::internal::rules
{
   struct jaxn_value
   {
      using rule_t = jaxn_value;
      using subs_t = pegtl::type_list< json::jaxn::internal::rules::sor_single_value >;

      template< pegtl::apply_mode A,
                pegtl::rewind_mode M,
                template< typename... >
                class Action,
                template< typename... >
                class Control,
                typename State >
      [[nodiscard]] static bool match( pegtl_input_t& in, State& st, const function_map& /*unused*/ )
      {
         jaxn_to_entry consumer;
         pegtl::parse< pegtl::must< json::jaxn::internal::rules::sor_single_value >, jaxn_action, json::jaxn::internal::errors >( in, consumer );
         // assert( consumer.value.has_value() );
         const auto f = [ &e = *consumer.value ]( concat& c ) { c.concat.emplace_back( std::move( e ) ); };
         phase1_append( st.root, st.prefix + st.suffix, f, phase1_mode::manifest );
         return true;
      }
   };

   struct reference_value
   {
      using rule_t = reference_value;
      using subs_t = pegtl::type_list< reference2_rest >;

      template< pegtl::apply_mode A,
                pegtl::rewind_mode M,
                template< typename... >
                class Action,
                template< typename... >
                class Control,
                typename State >
      [[nodiscard]] static bool match( pegtl_input_t& in, State& st, const function_map& /*unused*/ )
      {
         const auto r = parse_reference2( in );
         const auto f = [ & ]( concat& c ) { c.concat.emplace_back( r ); };
         phase1_append( st.root, st.prefix + st.suffix, f, phase1_mode::manifest );
         return true;
      }
   };

   struct array;
   struct object;

   struct extension_list;

   // clang-format off
   struct remove : pegtl::keyword< 'd', 'e', 'l', 'e', 't', 'e' > {};

   struct function_name : pegtl::seq< ident, pegtl::opt< pegtl::one< '?' > > > {};
   struct extension_value : pegtl::seq< function_name, wsp, extension_list > {};
   struct bracketed_value : pegtl::if_must< pegtl::one< '(' >, wss, pegtl::if_must_else< pegtl::at< reference2_rest >, reference_value, extension_value > > {};

   struct value_part : pegtl::sor< array, object, bracketed_value, jaxn_value > {};
   struct value_list : pegtl::list< value_part, pegtl::one< '+' >, jaxn::ws > {};

   struct assign_head : pegtl::one< ':', '=' > {};
   struct assign_member : pegtl::if_must< assign_head, wss, pegtl::sor< remove, value_list > > {};

   struct append_head : pegtl::sor< pegtl::string< '+', '=' >, pegtl::at< pegtl::one< '{', '[' > > > {};
   struct append_member : pegtl::if_must< append_head, wss, value_list > {};

   struct key_member : pegtl::sor< assign_member, append_member > {};

   struct member_key
   {
      using rule_t = member_key;
      using subs_t = pegtl::type_list< key1_rule, pegtl::must< wss, key_member > >;

      template< pegtl::apply_mode A,
                pegtl::rewind_mode M,
                template< typename... >
                class Action,
                template< typename... >
                class Control,
                typename State >
      [[nodiscard]] static bool match( pegtl_input_t& in, State& st, const function_map& fm )
      {
         const key1_guard kg( st, parse_key1( in ) );
         return Control< pegtl::must< wss, key_member > >::template match< A, M, Action, Control >( in, st, fm );
      }
   };

   struct inc_if : pegtl::one< '?' > {};
   struct opt_if : pegtl::opt< inc_if > {};
   struct inc_fn : pegtl::plus< pegtl::not_one< '"' > > {};  // TODO: Do we want/need to allow JSON escape sequences in filenames?

   struct include : pegtl::string< 'i', 'n', 'c', 'l', 'u', 'd', 'e' > {};
   struct permanent : pegtl::string< 'p', 'e', 'r', 'm', 'a', 'n', 'e', 'n', 't' > {};
   struct temporary : pegtl::string< 't', 'e', 'm', 'p', 'o', 'r', 'a', 'r', 'y' > {};

   struct filename : pegtl::seq< pegtl::one< '"' >, inc_fn, pegtl::one< '"' > > {};

   struct include_extension : pegtl::if_must< include, opt_if, wsp, filename > {};
   struct permanent_extension : pegtl::if_must< permanent, wsp, key1_rule > {};
   struct temporary_extension : pegtl::if_must< temporary, wsp, key1_rule > {};

   struct extension_member : pegtl::if_must< pegtl::one< '(' >, wss, pegtl::sor< include_extension, temporary_extension, permanent_extension >, wss, pegtl::one< ')' > > {};

   struct member : pegtl::sor< extension_member, member_key > {};

   struct opt_comma : pegtl::opt< pegtl::one< ',' >, wss > {};

   template< typename U > struct member_list_impl : pegtl::until< U, member, wss, opt_comma > {};
   template< typename U > struct element_list_impl : pegtl::until< U, value_list, wss, opt_comma > {};

   struct element_list : element_list_impl< jaxn::end_array > {};
   struct extension_list : element_list_impl< pegtl::one< ')' > > {};
   struct array : pegtl::if_must< jaxn::begin_array, element_list > {};
   struct member_list : member_list_impl< jaxn::end_object > {};
   struct object : pegtl::if_must< jaxn::begin_object, member_list > {};
   struct compat_file : pegtl::must< member_list, wss, pegtl::eof > {};
   struct config_list : member_list_impl< pegtl::eof > {};
   struct begin_compat : pegtl::disable< jaxn::begin_object > {};
   struct config_file : pegtl::must< wss, pegtl::if_must_else< begin_compat, compat_file, config_list > > {};
   struct value : pegtl::must< wss, value_part, wss, pegtl::eof > {};
   // clang-format on

}  // namespace tao::config::internal::rules

#endif


================================================
FILE: include/tao/config/internal/config_parser.hpp
================================================
// Copyright (c) 2019-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_CONFIG_PARSER_HPP
#define TAO_CONFIG_INTERNAL_CONFIG_PARSER_HPP

#include <cstdint>
#include <filesystem>
#include <string>
#include <string_view>
#include <utility>

#include "config_action.hpp"
#include "config_grammar.hpp"
#include "forward.hpp"
#include "function_implementations.hpp"
#include "function_wrapper.hpp"
#include "json.hpp"
#include "pegtl.hpp"
#include "phase2_everything.hpp"
#include "phase3_remove.hpp"
#include "phase5_repack.hpp"
#include "state.hpp"

namespace tao::config::internal
{
   struct config_parser
   {
      config_parser()
         : fm( { { "binary", wrap( binary_function ) },
                 { "default", wrap( default_function ) },
                 { "env", wrap( env_function ) },
                 { "env?", wrap( env_if_function ) },
                 { "jaxn", wrap( jaxn_function ) },
                 { "print", wrap( print_function ) },
                 { "read", wrap( read_function ) },
                 { "shell", wrap( shell_function ) },
                 { "split", wrap( split_function ) },
                 { "string", wrap( string_function ) } } )
      {}

      config_parser( config_parser&& ) = delete;
      config_parser( const config_parser& ) = delete;

      void operator=( config_parser&& ) = delete;
      void operator=( const config_parser& ) = delete;

      state st;
      function_map fm;

      void parse( pegtl_input_t&& in )
      {
         pegtl::parse< rules::config_file, config_action >( in, st, fm );
      }

      void parse( const std::filesystem::path& path )
      {
         parse( pegtl::file_input( path ) );
      }

      void parse( const char* data, const std::size_t size, const std::string& source )
      {
         parse( pegtl_input_t( data, size, source ) );
      }

      void parse( const std::string_view data, const std::string& source )
      {
         parse( data.data(), data.size(), source );
      }

      template< template< typename... > class Traits >
      [[nodiscard]] json::basic_value< Traits > finish()
      {
         phase2_everything( st, fm );
         phase3_remove( st.root );
         return phase5_repack< Traits >( st.root );
      }
   };

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/constants.hpp
================================================
// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_CONSTANTS_HPP
#define TAO_CONFIG_INTERNAL_CONSTANTS_HPP

#include "entry_kind.hpp"

namespace tao::config::internal
{
   struct part_asterisk_t
   {
      explicit constexpr part_asterisk_t( int /*unused*/ ) {}
   };

   struct part_vector_t
   {
      explicit constexpr part_vector_t( int /*unused*/ ) {}
   };

   constexpr part_asterisk_t part_asterisk{ 0 };
   constexpr part_vector_t part_vector{ 0 };

   [[nodiscard]] constexpr bool operator<( const part_asterisk_t, const part_asterisk_t ) noexcept
   {
      return false;
   }

   struct array_init_t
   {
      explicit constexpr array_init_t( int /*unused*/ ) {}

      static constexpr entry_kind kind = entry_kind::ARRAY;
   };

   struct object_init_t
   {
      explicit constexpr object_init_t( int /*unused*/ ) {}

      static constexpr entry_kind kind = entry_kind::OBJECT;
   };

   struct asterisk_init_t
   {
      explicit constexpr asterisk_init_t( int /*unused*/ ) {}

      static constexpr entry_kind kind = entry_kind::ASTERISK;
   };

   constexpr array_init_t array_init{ 0 };
   constexpr object_init_t object_init{ 0 };
   constexpr asterisk_init_t asterisk_init{ 0 };

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/debug_traits.hpp
================================================
// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_DEBUG_TRAITS_HPP
#define TAO_CONFIG_INTERNAL_DEBUG_TRAITS_HPP

#include <stdexcept>
#include <string>
#include <vector>

#include <tao/json/contrib/variant_traits.hpp>

#include "array.hpp"
#include "concat.hpp"
#include "entry.hpp"
#include "json.hpp"
#include "key1.hpp"
#include "object.hpp"
#include "pegtl.hpp"
#include "reference2.hpp"

#include "../annotation.hpp"
#include "../key.hpp"

namespace tao::config::internal
{
   template< typename T >
   struct debug_traits
      : json::traits< T >
   {};

   template<>
   struct debug_traits< void >
      : json::traits< void >
   {};

   template<>
   struct debug_traits< key_kind >
   {
      TAO_JSON_DEFAULT_KEY( "key_kind" );

      template< template< typename... > class Traits, typename Consumer >
      static void produce( Consumer& c, const key_kind k )
      {
         switch( k ) {
            case key_kind::name:
               c.string( "name" );
               return;
            case key_kind::index:
               c.string( "index" );
               return;
         }
         throw std::logic_error( "code should be unreachable" );  // LCOV_EXCL_LINE
      }
   };

   template<>
   struct debug_traits< key_part >
   {
      TAO_JSON_DEFAULT_KEY( "key_part" );

      template< template< typename... > class Traits, typename Consumer >
      static void produce( Consumer& c, const key_part& p )
      {
         c.begin_object( 2 );
         c.key( "key_kind" );
         json::events::produce< Traits >( c, p.kind() );
         c.member();
         c.key( "key_data" );
         json::events::produce< Traits >( c, p.data );
         c.member();
         c.end_object( 2 );
      }
   };

   template<>
   struct debug_traits< key >
      : json::traits< std::vector< key_part > >
   {
      TAO_JSON_DEFAULT_KEY( "key" );
   };

   template<>
   struct debug_traits< annotation >
      : json::binding::object< TAO_JSON_BIND_REQUIRED( "key", &annotation::key ),
                               TAO_JSON_BIND_REQUIRED( "position", &annotation::position ) >
   {
      TAO_JSON_DEFAULT_KEY( "annotation" );
   };

   template<>
   struct debug_traits< json::position >
   {
      TAO_JSON_DEFAULT_KEY( "position" );

      template< template< typename... > class Traits, typename Consumer >
      static void produce( Consumer& c, const json::position& p )
      {
         c.string( p.source() + ':' + std::to_string( p.line() ) + ':' + std::to_string( p.column() ) );
      }
   };

   template<>
   struct debug_traits< pegtl::position >
   {
      TAO_JSON_DEFAULT_KEY( "position" );

      template< template< typename... > class Traits, typename Consumer >
      static void produce( Consumer& c, const pegtl::position& p )
      {
         c.string( p.source + ':' + std::to_string( p.line ) + ':' + std::to_string( p.column ) );
      }
   };

   template<>
   struct debug_traits< part_asterisk_t >
   {
      template< template< typename... > class Traits, typename Consumer >
      static void produce( Consumer& c, const part_asterisk_t /*unused*/ )
      {
         c.string( "asterisk" );
      }
   };

   template<>
   struct debug_traits< key1_kind >
   {
      TAO_JSON_DEFAULT_KEY( "key1_kind" );

      template< template< typename... > class Traits, typename Consumer >
      static void produce( Consumer& c, const key1_kind k )
      {
         switch( k ) {
            case key1_kind::name:
               c.string( "name" );
               return;
            case key1_kind::index:
               c.string( "index" );
               return;
            case key1_kind::asterisk:
               c.string( "asterisk" );
               return;
            case key1_kind::append:
               c.string( "append" );
               return;
         }
         throw std::logic_error( "code should be unreachable" );  // LCOV_EXCL_LINE
      }
   };

   template<>
   struct debug_traits< key1_part >
   {
      TAO_JSON_DEFAULT_KEY( "key1_part" );

      template< template< typename... > class Traits, typename Consumer >
      static void produce( Consumer& c, const key1_part& p )
      {
         c.begin_object( 3 );
         c.key( "key1_kind" );
         json::events::produce< Traits >( c, p.kind() );
         c.member();
         c.key( "key1_data" );
         json::events::produce< Traits >( c, p.data );
         c.member();
         c.key( "position" );
         json::events::produce< Traits >( c, p.position );
         c.member();
         c.end_object( 3 );
      }
   };

   template<>
   struct debug_traits< key1 >
      : json::traits< std::vector< key1_part > >
   {
      TAO_JSON_DEFAULT_KEY( "key1" );
   };

   template<>
   struct debug_traits< reference2_kind >
   {
      TAO_JSON_DEFAULT_KEY( "reference2_kind" );

      template< template< typename... > class Traits, typename Consumer >
      static void produce( Consumer& c, const reference2_kind k )
      {
         switch( k ) {
            case reference2_kind::name:
               c.string( "name" );
               return;
            case reference2_kind::index:
               c.string( "index" );
               return;
            case reference2_kind::vector:
               c.string( "reference" );
               return;
         }
         throw std::logic_error( "code should be unreachable" );  // LCOV_EXCL_LINE
      }
   };

   template<>
   struct debug_traits< reference2_part >
   {
      TAO_JSON_DEFAULT_KEY( "reference2_part" );

      template< template< typename... > class Traits, typename Consumer >
      static void produce( Consumer& c, const reference2_part& p )
      {
         c.begin_object( 3 );
         c.key( "reference2_kind" );
         json::events::produce< Traits >( c, p.kind() );
         c.member();
         c.key( "reference2_data" );
         json::events::produce< Traits >( c, p.data );
         c.member();
         c.key( "position" );
         json::events::produce< Traits >( c, p.position );
         c.member();
         c.end_object( 3 );
      }
   };

   template<>
   struct debug_traits< reference2 >
      : json::traits< std::vector< reference2_part > >
   {
      TAO_JSON_DEFAULT_KEY( "reference2" );
   };

   template<>
   struct debug_traits< entry_kind >
   {
      TAO_JSON_DEFAULT_KEY( "entry_kind" );

      template< template< typename... > class Traits, typename Consumer >
      static void produce( Consumer& c, const entry_kind k )
      {
         switch( k ) {
            case entry_kind::NULL_:
               c.string( "null" );
               return;
            case entry_kind::BOOLEAN:
               c.string( "boolean" );
               return;
            case entry_kind::STRING:
               c.string( "string" );
               return;
            case entry_kind::BINARY:
               c.string( "binary" );
               return;
            case entry_kind::SIGNED:
               c.string( "signed" );
               return;
            case entry_kind::UNSIGNED:
               c.string( "unsigned" );
               return;
            case entry_kind::DOUBLE:
               c.string( "double" );
               return;
            case entry_kind::ARRAY:
               c.string( "array" );
               return;
            case entry_kind::OBJECT:
               c.string( "object" );
               return;
            case entry_kind::ASTERISK:
               c.string( "asterisk" );
               return;
            case entry_kind::REFERENCE:
               c.string( "reference" );
               return;
         }
         throw std::logic_error( "code should be unreachable" );  // LCOV_EXCL_LINE
      }
   };

   template<>
   struct debug_traits< entry >
   {
      template< template< typename... > class Traits, typename Consumer >
      static void produce( Consumer& c, const entry& v )
      {
         c.begin_object();
         c.key( "type" );
         json::events::produce< Traits >( c, v.kind() );
         c.member();
         switch( v.kind() ) {
            case entry_kind::NULL_:
               c.end_object();
               return;
            case entry_kind::BOOLEAN:
               c.key( "data" );
               json::events::produce< Traits >( c, v.get_boolean() );
               break;
            case entry_kind::STRING:
               c.key( "data" );
               json::events::produce< Traits >( c, v.get_string() );
               break;
            case entry_kind::BINARY:
               c.key( "data" );
               json::events::produce< Traits >( c, v.get_binary() );
               break;
            case entry_kind::SIGNED:
               c.key( "data" );
               json::events::produce< Traits >( c, v.get_signed() );
               break;
            case entry_kind::UNSIGNED:
               c.key( "data" );
               json::events::produce< Traits >( c, v.get_unsigned() );
               break;
            case entry_kind::DOUBLE:
               c.key( "data" );
               json::events::produce< Traits >( c, v.get_double() );
               break;
            case entry_kind::ARRAY:
               c.key( "data" );
               json::events::produce< Traits >( c, v.get_array() );
               break;
            case entry_kind::OBJECT:
               c.key( "data" );
               json::events::produce< Traits >( c, v.get_object() );
               break;
            case entry_kind::ASTERISK:
               c.key( "data" );
               json::events::produce< Traits >( c, v.get_asterisk() );
               break;
            case entry_kind::REFERENCE:
               c.key( "data" );
               json::events::produce< Traits >( c, v.get_reference() );
               break;
         }
         c.member();
         c.end_object();
      }
   };

   template<>
   struct debug_traits< concat >
      : json::binding::object< TAO_JSON_BIND_REQUIRED( "remove", &concat::remove ),
                               TAO_JSON_BIND_REQUIRED( "implicit", &concat::implicit ),
                               TAO_JSON_BIND_REQUIRED( "temporary", &concat::temporary ),
                               TAO_JSON_BIND_REQUIRED( "position", &concat::position ),
                               TAO_JSON_BIND_REQUIRED( "concat_list", &concat::concat ) >
   {};

   template<>
   struct debug_traits< array >
      : json::binding::object< TAO_JSON_BIND_REQUIRED( "position", &array::position ),
                               TAO_JSON_BIND_OPTIONAL( "function", &array::function ),
                               TAO_JSON_BIND_REQUIRED( "array_data", &array::array ) >
   {};

   template<>
   struct debug_traits< object >
      : json::binding::object< TAO_JSON_BIND_REQUIRED( "position", &object::position ),
                               TAO_JSON_BIND_REQUIRED( "object_data", &object::object ) >
   {};

   template< typename T >
   struct debug_traits< const T* >
   {
      template< template< typename... > class Traits >
      static void assign( json::basic_value< Traits >& v, const T* p )
      {
         v.set_opaque_ptr( p );
      }
   };

   template< typename T >
   struct debug_traits< T* >
      : debug_traits< const T* >
   {};

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/entry.hpp
================================================
// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_ENTRY_HPP
#define TAO_CONFIG_INTERNAL_ENTRY_HPP

#include <cassert>
#include <cstddef>
#include <stdexcept>
#include <string>
#include <utility>
#include <variant>

#include "array.hpp"
#include "atom.hpp"
#include "concat.hpp"
#include "constants.hpp"
#include "entry_kind.hpp"
#include "forward.hpp"
#include "object.hpp"
#include "pegtl.hpp"
#include "reference2.hpp"

namespace tao::config::internal
{
   struct entry
   {
      using data_t = std::variant< null, boolean, string_t, binary_t, signed_t, unsigned_t, double_t, array, object, concat, reference2 >;

      explicit entry( const null& n )
         : m_data( n )
      {}

      explicit entry( const boolean& b )
         : m_data( b )
      {}

      explicit entry( const string_t& s )
         : m_data( s )
      {}

      explicit entry( const binary_t& b )
         : m_data( b )
      {}

      explicit entry( const signed_t& s )
         : m_data( s )
      {}

      explicit entry( const unsigned_t& u )
         : m_data( u )
      {}

      explicit entry( const double_t& d )
         : m_data( d )
      {}

      explicit entry( const reference2& r )
         : m_data( r )
      {
         assert( !r.empty() );
      }

      entry( const std::string& n, const pegtl::position& p )
         : m_data( std::in_place_type_t< array >(), n, p )
      {}

      entry( const array_init_t /*unused*/, const pegtl::position& p )
         : m_data( std::in_place_type_t< array >(), p )
      {}

      entry( const object_init_t /*unused*/, const pegtl::position& p )
         : m_data( std::in_place_type_t< object >(), p )
      {}

      entry( const asterisk_init_t /*unused*/, const pegtl::position& p )
         : m_data( std::in_place_type_t< concat >(), p )
      {}

      entry( entry&& ) noexcept = default;
      entry( const entry& ) = default;

      ~entry() = default;

      entry& operator=( entry&& ) noexcept = default;
      entry& operator=( const entry& ) = default;

      [[nodiscard]] entry_kind kind() const noexcept
      {
         return entry_kind( m_data.index() );
      }

      [[nodiscard]] bool is_null() const noexcept
      {
         return std::holds_alternative< null >( m_data );
      }

      [[nodiscard]] bool is_string() const noexcept
      {
         return std::holds_alternative< string_t >( m_data );
      }

      [[nodiscard]] bool is_binary() const noexcept
      {
         return std::holds_alternative< binary_t >( m_data );
      }

      [[nodiscard]] bool is_array() const noexcept
      {
         return std::holds_alternative< array >( m_data );
      }

      [[nodiscard]] bool is_object() const noexcept
      {
         return std::holds_alternative< object >( m_data );
      }

      [[nodiscard]] bool is_asterisk() const noexcept
      {
         return std::holds_alternative< concat >( m_data );
      }

      [[nodiscard]] bool is_reference() const noexcept
      {
         return std::holds_alternative< reference2 >( m_data );
      }

      template< typename T >
      void set_value( atom< T >&& t )
      {
         m_data.emplace< atom< T > >( std::move( t ) );
      }

      void set_array( pegtl::position p )
      {
         m_data.emplace< std::size_t( entry_kind::ARRAY ) >( std::move( p ) );
      }

      void set_object( pegtl::position p )
      {
         m_data.emplace< std::size_t( entry_kind::OBJECT ) >( std::move( p ) );
      }

      [[nodiscard]] bool get_boolean() const noexcept
      {
         return std::get< boolean >( m_data ).value;
      }

      [[nodiscard]] boolean& get_boolean_atom() noexcept
      {
         return std::get< boolean >( m_data );
      }

      [[nodiscard]] const boolean& get_boolean_atom() const noexcept
      {
         return std::get< boolean >( m_data );
      }

      [[nodiscard]] std::string& get_string() noexcept
      {
         return std::get< string_t >( m_data ).value;
      }

      [[nodiscard]] const std::string& get_string() const noexcept
      {
         return std::get< string_t >( m_data ).value;
      }

      [[nodiscard]] string_t& get_string_atom() noexcept
      {
         return std::get< string_t >( m_data );
      }

      [[nodiscard]] const string_t& get_string_atom() const noexcept
      {
         return std::get< string_t >( m_data );
      }

      [[nodiscard]] std::vector< std::byte >& get_binary() noexcept
      {
         return std::get< binary_t >( m_data ).value;
      }

      [[nodiscard]] const std::vector< std::byte >& get_binary() const noexcept
      {
         return std::get< binary_t >( m_data ).value;
      }

      [[nodiscard]] binary_t& get_binary_atom() noexcept
      {
         return std::get< binary_t >( m_data );
      }

      [[nodiscard]] const binary_t& get_binary_atom() const noexcept
      {
         return std::get< binary_t >( m_data );
      }

      [[nodiscard]] std::int64_t get_signed() const noexcept
      {
         return std::get< signed_t >( m_data ).value;
      }

      [[nodiscard]] signed_t& get_signed_atom() noexcept
      {
         return std::get< signed_t >( m_data );
      }

      [[nodiscard]] const signed_t& get_signed_atom() const noexcept
      {
         return std::get< signed_t >( m_data );
      }

      [[nodiscard]] std::uint64_t get_unsigned() const noexcept
      {
         return std::get< unsigned_t >( m_data ).value;
      }

      [[nodiscard]] unsigned_t& get_unsigned_atom() noexcept
      {
         return std::get< unsigned_t >( m_data );
      }

      [[nodiscard]] const unsigned_t& get_unsigned_atom() const noexcept
      {
         return std::get< unsigned_t >( m_data );
      }

      [[nodiscard]] double get_double() const noexcept
      {
         return std::get< double_t >( m_data ).value;
      }

      [[nodiscard]] double_t& get_double_atom() noexcept
      {
         return std::get< double_t >( m_data );
      }

      [[nodiscard]] const double_t& get_double_atom() const noexcept
      {
         return std::get< double_t >( m_data );
      }

      [[nodiscard]] array& get_array() noexcept
      {
         return std::get< array >( m_data );
      }

      [[nodiscard]] const array& get_array() const noexcept
      {
         return std::get< array >( m_data );
      }

      [[nodiscard]] object& get_object() noexcept
      {
         return std::get< object >( m_data );
      }

      [[nodiscard]] const object& get_object() const noexcept
      {
         return std::get< object >( m_data );
      }

      [[nodiscard]] concat& get_asterisk() noexcept
      {
         return std::get< concat >( m_data );
      }

      [[nodiscard]] const concat& get_asterisk() const noexcept
      {
         return std::get< concat >( m_data );
      }

      [[nodiscard]] reference2& get_reference() noexcept
      {
         return std::get< reference2 >( m_data );
      }

      [[nodiscard]] const reference2& get_reference() const noexcept
      {
         return std::get< reference2 >( m_data );
      }

      [[nodiscard]] const pegtl::position& get_position() const noexcept
      {
         return std::visit( []( const auto& v ) -> const pegtl::position& { return v.get_position(); }, m_data );
      }

   private:
      data_t m_data;
   };

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/entry_kind.hpp
================================================
// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_ENTRY_KIND_HPP
#define TAO_CONFIG_INTERNAL_ENTRY_KIND_HPP

#include <cassert>
#include <cstdlib>
#include <ostream>
#include <string_view>

namespace tao::config::internal
{
   enum class entry_kind : char
   {
      NULL_ = 0,
      BOOLEAN = 1,
      STRING = 2,
      BINARY = 3,
      SIGNED = 4,
      UNSIGNED = 5,
      DOUBLE = 6,
      ARRAY = 7,
      OBJECT = 8,
      ASTERISK = 9,
      REFERENCE = 10
   };

   [[nodiscard]] constexpr std::string_view to_string( const entry_kind k ) noexcept
   {
      switch( k ) {
         case entry_kind::NULL_:
            return "null";
         case entry_kind::BOOLEAN:
            return "boolean";
         case entry_kind::STRING:
            return "string";
         case entry_kind::BINARY:
            return "binary";
         case entry_kind::SIGNED:
            return "signed";
         case entry_kind::UNSIGNED:
            return "unsigned";
         case entry_kind::DOUBLE:
            return "double";
         case entry_kind::ARRAY:
            return "array";
         case entry_kind::OBJECT:
            return "object";
         case entry_kind::ASTERISK:
            return "asterisk";
         case entry_kind::REFERENCE:
            return "reference";
      }
      std::abort();
   }

   inline std::ostream& operator<<( std::ostream& o, const entry_kind k )
   {
      return o << to_string( k );
   }

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/events_from_value.hpp
================================================
// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_EVENTS_FROM_VALUE_HPP
#define TAO_CONFIG_INTERNAL_EVENTS_FROM_VALUE_HPP

#include "debug_traits.hpp"
#include "json.hpp"

namespace tao::config::internal
{
   template< typename Consumer, template< typename... > class Traits >
   void events_from_value( Consumer& c, const json::basic_value< Traits >& v )
   {
      c.begin_object( 2 );
      c.key( "meta" );
      json::events::produce< debug_traits >( c, v.public_base() );
      c.member();
      c.key( "data" );
      json::events::from_value< events_from_value< Consumer, Traits > >( c, v );
      c.member();
      c.end_object( 2 );
   }

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/forward.hpp
================================================
// Copyright (c) 2019-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_FORWARD_HPP
#define TAO_CONFIG_INTERNAL_FORWARD_HPP

#include <functional>
#include <map>
#include <string>

namespace tao::config::internal
{
   struct entry;
   struct state;

   template< typename E >
   struct basic_concat;

   using concat = basic_concat< entry >;

   template< typename C >
   struct basic_array;
   template< typename C >
   struct basic_object;

   using array = basic_array< concat >;
   using object = basic_object< concat >;

   template< typename, typename >
   struct function_traits;

   using function = std::function< bool( entry& ) >;
   using function_map = std::map< std::string, function >;

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/function_implementations.hpp
================================================
// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_FUNCTION_IMPLEMENTATIONS_HPP
#define TAO_CONFIG_INTERNAL_FUNCTION_IMPLEMENTATIONS_HPP

#include <cstddef>
#include <string>
#include <utility>
#include <vector>

#include "entry.hpp"
#include "forward.hpp"
#include "jaxn_action.hpp"
#include "jaxn_to_entry.hpp"
#include "json.hpp"
#include "pegtl.hpp"
#include "phase5_repack.hpp"
#include "statistics.hpp"
#include "system_utility.hpp"

#include "../key.hpp"

namespace tao::config::internal
{
   [[nodiscard]] inline binary_t binary_function( const pegtl::position& p, const std::string& s )
   {
      const auto* const d = reinterpret_cast< const std::byte* >( s.data() );
      return binary_t( std::vector< std::byte >( d, d + s.size() ), p );
   }

   [[nodiscard]] inline bool default_function( entry& e )
   {
      array& a = e.get_array();
      if( a.array.size() < 1 ) {
         throw pegtl::parse_error( "default function requires at least one argument", a.position );
      }
      for( concat& c : a.array ) {
         if( c.concat.size() != 1 ) {
            return false;
         }
         entry& f = c.concat.front();

         switch( f.kind() ) {
            case entry_kind::NULL_:
               continue;
            case entry_kind::STRING:
            case entry_kind::BINARY:
            case entry_kind::BOOLEAN:
            case entry_kind::SIGNED:
            case entry_kind::UNSIGNED:
            case entry_kind::DOUBLE:
               break;
            case entry_kind::ARRAY:
               if( !f.get_array().function.empty() ) {
                  return false;
               }
               break;
            case entry_kind::OBJECT:
               break;
            case entry_kind::ASTERISK:
               return false;
            case entry_kind::REFERENCE:
               return false;
         }
         // Both f and a are sub-objects of e.
         entry t = std::move( f );
         e = std::move( t );
         return true;
      }
      throw pegtl::parse_error( "default function requires at least one non-null argument", a.position );
   }

   [[nodiscard]] inline string_t env_function( const pegtl::position& p, const std::string& s )
   {
      return string_t( getenv_throws( p, s ), p );
   }

   [[nodiscard]] inline string_t env_if_function( const pegtl::position& p, const std::string& s, const std::string& d )
   {
      const auto r = getenv_nothrow( s );
      return string_t( r ? ( *r ) : d, p );
   }

   [[nodiscard]] inline entry jaxn_function( const pegtl::position& /*unused*/, const std::string& s )
   {
      jaxn_to_entry consumer;
      pegtl::memory_input in( s, "TODO" );
      pegtl::parse< json::jaxn::internal::grammar, jaxn_action, json::jaxn::internal::errors >( static_cast< pegtl_input_t& >( in ), consumer );
      return std::move( consumer.value ).value();
   }

   [[nodiscard]] inline binary_t read_function( const pegtl::position& p, const std::string& filename )
   {
      const std::string d = read_file_throws( filename );
      const std::byte* x = reinterpret_cast< const std::byte* >( d.data() );
      return binary_t( std::vector< std::byte >( x, x + d.size() ), p );
   }

   [[nodiscard]] inline bool print_function( entry& e )
   {
      array& a = e.get_array();
      if( a.array.size() != 1 ) {
         throw pegtl::parse_error( "print function requires exactly one argument", a.position );
      }
      concat& c = a.array.front();
      if( statistics( c ).is_primitive() ) {
         const tao::json::value v = phase5_repack< json::traits >( c );  // TODO: Optimise away this intermediate data structure.
         std::string s = json::jaxn::to_string( v );
         pegtl::position p = c.position;
         e = entry( string_t( std::move( s ), std::move( p ) ) );
         return true;
      }
      return false;
   }

   [[nodiscard]] inline string_t shell_function( const pegtl::position& p, [[maybe_unused]] const std::string& script )
   {
#if defined( _MSC_VER )
      throw pegtl::parse_error( "shell extension not supported on this platform", p );
#else
      return string_t( shell_popen_throws( p, script ), p );
#endif
   }

   // clang-format off
   struct split_star_ws : pegtl::star< pegtl::space > {};
   struct split_string : pegtl::plus< pegtl::invert< pegtl::space > > {};
   struct split_rule : pegtl::must< split_star_ws, pegtl::star< split_string, split_star_ws >, pegtl::eof > {};
   // clang-format on

   template< typename Rule >
   struct split_action
      : pegtl::nothing< Rule >
   {};

   template<>
   struct split_action< split_string >
   {
      template< typename Input >
      static void apply( const Input& in, entry& result, const pegtl::position& p )
      {
         concat& c = result.get_array().array.emplace_back( p );
         c.concat.emplace_back( string_t( in.string(), in.position() ) );
      }
   };

   [[nodiscard]] inline entry split_function( const pegtl::position& p, const std::string& s )
   {
      entry result( array_init, p );
      pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl_input_t::eol_t, const char* > in( s, __FUNCTION__ );
      pegtl::parse_nested< split_rule, split_action >( p, in, result, p );
      return result;
   }

   [[nodiscard]] inline string_t string_function( const pegtl::position& p, const std::string& s )
   {
      return string_t( s, p );
   }

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/function_traits.hpp
================================================
// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_FUNCTION_TRAITS_HPP
#define TAO_CONFIG_INTERNAL_FUNCTION_TRAITS_HPP

#include <cassert>
#include <cstddef>
#include <iterator>
#include <stdexcept>
#include <string>
#include <vector>

#include "array.hpp"
#include "entry.hpp"
#include "forward.hpp"
#include "json.hpp"
#include "key1.hpp"
#include "parse_utility.hpp"
#include "pegtl.hpp"

namespace tao::config::internal
{
   struct arguments_unready
   {};

   template< typename, typename = void >
   struct function_traits;

   template<>
   struct function_traits< entry >
   {
      static void put( entry& e, entry&& f )
      {
         e = std::move( f );
      }

      static void put( entry& e, const entry& f )
      {
         e = f;
      }
   };

   template< typename T >
   struct function_traits< atom< T > >
   {
      static void put( entry& e, atom< T >&& v )
      {
         e.set_value( std::move( v ) );
      }

      static void put( entry& e, const atom< T >& v )
      {
         e.set_value( v );
      }
   };

   [[nodiscard]] inline const entry& function_traits_entry( array& f, const std::size_t i )
   {
      assert( f.array.size() > i );

      auto p = f.array.begin();
      std::advance( p, i );

      assert( !p->concat.empty() );

      if( p->concat.size() != 1 ) {
         throw arguments_unready();
      }
      return p->concat.front();
   }

   template<>
   struct function_traits< std::string >
   {
      [[nodiscard]] static std::string get( array& f, const std::size_t i )
      {
         const entry& e = function_traits_entry( f, i );

         if( e.is_string() ) {
            return e.get_string();
         }
         if( e.is_binary() ) {
            const std::vector< std::byte >& b = e.get_binary();
            const std::string s( reinterpret_cast< const char* >( b.data() ), b.size() );
            if( !json::internal::validate_utf8_nothrow( s ) ) {
               throw pegtl::parse_error( "invalid utf-8 in binary data used as string", e.get_position() );
            }
            return s;
         }
         throw pegtl::parse_error( "invalid type for string argument", e.get_position() );
      }
   };

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/function_wrapper.hpp
================================================
// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_FUNCTION_WRAPPER_HPP
#define TAO_CONFIG_INTERNAL_FUNCTION_WRAPPER_HPP

#include <cstddef>
#include <type_traits>
#include <utility>

#include "forward.hpp"
#include "function_traits.hpp"
#include "json.hpp"
#include "pegtl.hpp"

namespace tao::config::internal
{
   [[nodiscard]] inline function wrap( bool ( *x )( entry& e ) )
   {
      return function( [ x ]( entry& e ) {
         try {
            return x( e );
         }
         catch( const arguments_unready& ) {
            return false;
         }
      } );
   }

   template< typename R, typename A >
   [[nodiscard]] function wrap( R ( *x )( const pegtl::position&, A ) )
   {
      static_assert( !std::is_pointer_v< R > );
      static_assert( !std::is_reference_v< R > );
      static_assert( !std::is_same_v< R, void > );

      return function( [ x ]( entry& e ) {
         try {
            array& f = e.get_array();
            function_traits< std::decay_t< R > >::put( e, x( f.position, function_traits< std::decay_t< A > >::get( f, 0 ) ) );
         }
         catch( const arguments_unready& ) {
            return false;
         }
         return true;
      } );
   }

   template< typename R, typename A, typename B >
   [[nodiscard]] function wrap( R ( *x )( const pegtl::position&, A, B ) )
   {
      static_assert( !std::is_pointer_v< R > );
      static_assert( !std::is_reference_v< R > );
      static_assert( !std::is_same_v< R, void > );

      return function( [ x ]( entry& e ) {
         try {
            array& f = e.get_array();
            function_traits< std::decay_t< R > >::put( e, x( f.position, function_traits< std::decay_t< A > >::get( f, 0 ), function_traits< std::decay_t< B > >::get( f, 1 ) ) );
         }
         catch( const arguments_unready& ) {
            return false;
         }
         return true;
      } );
   }

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/jaxn_action.hpp
================================================
// Copyright (c) 2017-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_JAXN_ACTION_HPP
#define TAO_CONFIG_INTERNAL_JAXN_ACTION_HPP

#include <algorithm>
#include <cstring>
#include <string>
#include <string_view>
#include <utility>
#include <vector>

#include "change_action_and_states.hpp"
#include "json.hpp"
#include "pegtl.hpp"

namespace tao::config::internal
{
   template< typename Rule >
   struct jaxn_action
      : pegtl::nothing< Rule >
   {};

   template<>
   struct jaxn_action< json::jaxn::internal::rules::kw_null >
   {
      template< typename Input, typename Consumer >
      static void apply( const Input& in, Consumer& consumer )
      {
         consumer.null( in.position() );
      }
   };

   template<>
   struct jaxn_action< json::jaxn::internal::rules::kw_true >
   {
      template< typename Input, typename Consumer >
      static void apply( const Input& in, Consumer& consumer )
      {
         consumer.boolean( true, in.position() );
      }
   };

   template<>
   struct jaxn_action< json::jaxn::internal::rules::kw_false >
   {
      template< typename Input, typename Consumer >
      static void apply( const Input& in, Consumer& consumer )
      {
         consumer.boolean( false, in.position() );
      }
   };

   template<>
   struct jaxn_action< json::jaxn::internal::rules::identifier >
   {
      template< typename Input, typename Consumer >
      static void apply( const Input& in, Consumer& consumer )
      {
         consumer.key( std::string_view( in.begin(), in.size() ), in.position() );
      }
   };

   template< bool NEG >
   struct jaxn_action< json::jaxn::internal::rules::hexnum< NEG > >
   {
      template< typename Input, typename Consumer >
      static void apply( const Input& in, Consumer& consumer )
      {
         std::uint64_t value = 0;
         for( char c : in ) {
            if( value & 0xF000000000000000 ) {
               throw pegtl::parse_error( "JAXN hexadecimal number too large", in );
            }
            value <<= 4;
            value += json::internal::hex_char_to_integer< std::uint8_t >( c );
         }
         if constexpr( NEG ) {
            if( value < 9223372036854775808ULL ) {
               consumer.number( -static_cast< std::int64_t >( value ), in.position() );
            }
            else if( value == 9223372036854775808ULL ) {
               consumer.number( static_cast< std::int64_t >( -9223372036854775807LL - 1 ), in.position() );
            }
            else {
               throw pegtl::parse_error( "JAXN hexadecimal number too large to negate", in );
            }
         }
         else {
            consumer.number( value, in.position() );
         }
      }
   };

   template<>
   struct jaxn_action< json::jaxn::internal::rules::array::begin >
   {
      template< typename Input, typename Consumer >
      static void apply( const Input& in, Consumer& consumer )
      {
         consumer.begin_array( in.position() );
      }
   };

   template<>
   struct jaxn_action< json::jaxn::internal::rules::array::element >
   {
      template< typename Input, typename Consumer >
      static void apply( const Input& in, Consumer& consumer )
      {
         consumer.element( in.position() );  // TODO: Position needed here?
      }
   };

   template<>
   struct jaxn_action< json::jaxn::internal::rules::array::end >
   {
      template< typename Input, typename Consumer >
      static void apply( const Input& in, Consumer& consumer )
      {
         consumer.end_array( in.position() );
      }
   };

   template<>
   struct jaxn_action< json::jaxn::internal::rules::object::begin >
   {
      template< typename Input, typename Consumer >
      static void apply( const Input& in, Consumer& consumer )
      {
         consumer.begin_object( in.position() );
      }
   };

   template<>
   struct jaxn_action< json::jaxn::internal::rules::object::element >
   {
      template< typename Input, typename Consumer >
      static void apply( const Input& in, Consumer& consumer )
      {
         consumer.member( in.position() );  // TODO: Position needed here?
      }
   };

   template<>
   struct jaxn_action< json::jaxn::internal::rules::object::end >
   {
      template< typename Input, typename Consumer >
      static void apply( const Input& in, Consumer& consumer )
      {
         consumer.end_object( in.position() );  // TODO: Position needed here?
      }
   };

   template<>
   struct jaxn_action< json::jaxn::internal::rules::zero< false > >
   {
      template< typename Input, typename Consumer >
      static void apply( const Input& in, Consumer& consumer )
      {
         consumer.number( std::uint64_t( 0 ), in.position() );
      }
   };

   template<>
   struct jaxn_action< json::jaxn::internal::rules::zero< true > >
   {
      template< typename Input, typename Consumer >
      static void apply( const Input& in, Consumer& consumer )
      {
         consumer.number( std::int64_t( 0 ), in.position() );
      }
   };

   template<>
   struct jaxn_action< json::jaxn::internal::rules::kw_nan >
   {
      template< typename Input, typename Consumer >
      static void apply( const Input& in, Consumer& consumer )
      {
         consumer.number( NAN, in.position() );
      }
   };

   template<>
   struct jaxn_action< json::jaxn::internal::rules::kw_infinity< false > >
   {
      template< typename Input, typename Consumer >
      static void apply( const Input& in, Consumer& consumer )
      {
         consumer.number( INFINITY, in.position() );
      }
   };

   template<>
   struct jaxn_action< json::jaxn::internal::rules::kw_infinity< true > >
   {
      template< typename Input, typename Consumer >
      static void apply( const Input& in, Consumer& consumer )
      {
         consumer.number( -INFINITY, in.position() );
      }
   };

   template<>
   struct jaxn_action< json::jaxn::internal::rules::esign >
   {
      template< typename Input, bool NEG >
      static void apply( const Input& in, json::internal::number_state< NEG >& result )
      {
         result.eneg = ( in.peek_char() == '-' );
      }
   };

   template<>
   struct jaxn_action< json::jaxn::internal::rules::idigits >
   {
      template< typename Input, bool NEG >
      static void apply( const Input& in, json::internal::number_state< NEG >& result )
      {
         const auto s = in.size();

         if( s == 1 && in.peek_char() == '0' ) {
            return;
         }

         if( s > ( 1 << 20 ) ) {
            throw pegtl::parse_error( "JSON number with 1 megabyte digits", in );
         }

         const auto c = ( std::min )( s, json::internal::max_mantissa_digits );
         std::memcpy( result.mantissa, in.begin(), c );
         result.exponent10 += static_cast< typename json::internal::number_state< NEG >::exponent10_t >( s - c );
         result.msize = static_cast< typename json::internal::number_state< NEG >::msize_t >( c );

         for( std::size_t i = c; i < s; ++i ) {
            if( in.peek_char( i ) != '0' ) {
               result.drop = true;
               return;
            }
         }
      }
   };

   template<>
   struct jaxn_action< json::jaxn::internal::rules::fdigits >
   {
      template< typename Input, bool NEG >
      static void apply( const Input& in, json::internal::number_state< NEG >& result )
      {
         result.isfp = true;

         const auto* b = in.begin();
         const auto* e = in.end();

         while( ( e > b ) && ( e[ -1 ] == '0' ) ) {
            --e;
         }
         if( !result.msize ) {
            while( ( b < e ) && ( b[ 0 ] == '0' ) ) {
               ++b;
               --result.exponent10;
            }
         }
         const auto c = ( std::min )( std::size_t( e - b ), json::internal::max_mantissa_digits - result.msize );
         std::memcpy( result.mantissa + result.msize, b, c );
         result.exponent10 -= static_cast< typename json::internal::number_state< NEG >::exponent10_t >( c );
         result.msize += static_cast< typename json::internal::number_state< NEG >::msize_t >( c );

         for( const auto* r = b + c; r < e; ++r ) {
            if( *r != '0' ) {
               result.drop = true;
               return;
            }
         }
      }
   };

   template<>
   struct jaxn_action< json::jaxn::internal::rules::edigits >
   {
      template< typename Input, bool NEG >
      static void apply( const Input& in, json::internal::number_state< NEG >& result )
      {
         result.isfp = true;

         const char* b = in.begin();

         while( ( b < in.end() ) && ( b[ 0 ] == '0' ) ) {
            ++b;
         }
         if( ( in.end() - b ) > 9 ) {
            throw pegtl::parse_error( "JSON exponent has more than 9 significant digits", in );
         }
         int exponent10 = 0;

         while( b < in.end() ) {
            exponent10 = ( exponent10 * 10 ) + ( b[ 0 ] - '0' );
            ++b;
         }
         result.exponent10 += ( result.eneg ? -exponent10 : exponent10 );
      }
   };

   template< bool NEG >
   struct jaxn_action< json::jaxn::internal::rules::number< NEG > >
      : pegtl::change_states< json::internal::number_state< NEG > >
   {
      template< typename Input, typename Consumer >
      static void success( const Input& in, json::internal::number_state< NEG >& state, Consumer& consumer )
      {
         state.success( consumer, in.position() );
      }
   };

   template<>
   struct jaxn_action< json::jaxn::internal::rules::single_string >
      : change_action_and_states< json::jaxn::internal::unescape_action, std::string >
   {
      template< typename Consumer >
      static void success( const pegtl::position& pos, std::string& unescaped, Consumer& consumer )
      {
         consumer.string( std::move( unescaped ), pos );
      }
   };

   template<>
   struct jaxn_action< json::jaxn::internal::rules::string >
      : change_action_and_states< json::jaxn::internal::unescape_action, std::string >
   {
      template< typename Consumer >
      static void success( const pegtl::position& pos, std::string& unescaped, Consumer& consumer )
      {
         consumer.string( std::move( unescaped ), pos );
      }
   };

   template<>
   struct jaxn_action< json::jaxn::internal::rules::key >
      : change_action_and_states< json::jaxn::internal::unescape_action, std::string >
   {
      template< typename Consumer >
      static void success( const pegtl::position& pos, std::string& unescaped, Consumer& consumer )
      {
         consumer.key( std::move( unescaped ), pos );
      }
   };

   template<>
   struct jaxn_action< json::jaxn::internal::rules::single_binary >
      : change_action_and_states< json::jaxn::internal::bunescape_action, std::vector< std::byte > >
   {
      template< typename Consumer >
      static void success( const pegtl::position& pos, std::vector< std::byte >& value, Consumer& consumer )
      {
         consumer.binary( std::move( value ), pos );
      }
   };

   template<>
   struct jaxn_action< json::jaxn::internal::rules::binary >
      : change_action_and_states< json::jaxn::internal::bunescape_action, std::vector< std::byte > >
   {
      template< typename Consumer >
      static void success( const pegtl::position& pos, std::vector< std::byte >& value, Consumer& consumer )
      {
         consumer.binary( std::move( value ), pos );
      }
   };

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/jaxn_to_entry.hpp
================================================
// Copyright (c) 2016-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config

#ifndef TAO_CONFIG_INTERNAL_JAXN_TO_ENTRY_HPP
#define TAO_CONFIG_INTERNAL_JAXN_TO_ENTRY_HPP

#include <cassert>
#include <cstddef>
#include <cstdint>
#include <optional>
#include <string>
#include <string_view>
#include <utility>
#include <vector>

#include "array.hpp"
#include "concat.hpp"
#include "constants.hpp"
#include "entry.hpp"
#include "forward.hpp"
#include "object.hpp"

namespace tao::config::internal
{
   struct jaxn_to_entry
   {
      jaxn_to_entry() noexcept = default;

      std::vector< entry > stack_;
      std::vector< std::string > keys_;
      std::optional< entry > value;

      void null( const pegtl::position& p )
      {
         value.emplace( internal::null( p ) );
      }

      void boolean( const bool v, const pegtl::position& p )
      {
         value.emplace( internal::boolean( v, p ) );
      }

      void number( const std::int64_t v, const pegtl::position& p )
      {
         value.emplace( internal::signed_t( v, p ) );
      }

      void number( const std::uint64_t v, const pegtl::position& p )
      {
         value.emplace( internal::unsigned_t( v, p ) );
      }

      void number( const double v, const pegtl::position& p )
      {
         value.emplace( internal::double_t( v, p ) );
      }

      void string( const std::string_view v, const pegtl::position& p )
      {
         value.emplace( internal::string_t( v, p ) );
      }

      void string( const char* v, const pegtl::position& p )
      {
         value.emplace( internal::string_t( v, p ) );
      }

      void string( std::string&& v, const pegtl::position& p )
      {
         value.emplace( internal::string_t( std::move( v ), p ) );
      }

      void binary( const tao::binary_view v, const pegtl::position& p )
      {
         binary( std::vector< std::byte >( v.data(), v.data() + v.size() ), p );
      }

      void binary( std::vector< std::byte >&& v, const pegtl::position& p )
      {
         value.emplace( internal::binary_t( std::move( v ), p ) );
      }

      void begin_array( const pegtl::position& p )
      {
         stack_.emplace_back( array_init, p );
      }

      void begin_array( const std::size_t /*unused*/, const pegtl::position& p )
      {
         begin_array( p );
      }

      void element( const pegtl::position& p )
      {
         concat& c = stack_.back().get_array().array.emplace_back( p );
         c.remove = true;
         c.concat.emplace_back( std::move( value ).value() );
      }

      void end_array( const pegtl::position& /*unused*/ )
      {
         value = std::move( stack_.back() );
         stack_.pop_back();
      }

      void end_array( const std::size_t /*unused*/, const pegtl::position& p )
      {
         end_array( p );
      }

      void begin_object( const pegtl::position& p )
      {
         stack_.emplace_back( object_init, p );
      }

      void begin_object( const std::size_t /*unused*/, const pegtl::position& p )
      {
         begin_object( p );
      }

      void key( const std::string_view v, const pegtl::position& /*unused*/ )
      {
         keys_.emplace_back( v );
      }

      void key( const char* v, const pegtl::position& /*unused*/ )
      {
         keys_.emplace_back( v );
      }

      void key( std::string&& v, const pegtl::position& /*unused*/ )
      {
         keys_.emplace_back( std::move( v ) );
      }

      void member( const pegtl::position& p )
      {
         auto [ i, b ] = stack_.back().get_object().object.try_emplace( std::move( keys_.back() ), p );
         (void)b;
         keys_.pop_back();
         i->second.remove = true;
         i->second.concat.emplace_back( std::move( value ).value() );
      }

      void end_object( const pegtl::position& /*unused*/ )
      {
         value = std::move( stack_.back() );
         stack_.pop_back();
      }

      void end_object( const std::size_t /*unused*/, const pegtl::position& p )
      {
         end_object( p );
      }
   };

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/json.hpp
================================================
// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_JSON_HPP
#define TAO_CONFIG_INTERNAL_JSON_HPP

#include <tao/json.hpp>

#include <tao/json/contrib/position.hpp>
#include <tao/json/contrib/traits.hpp>  // TODO: This might be a problem...

#include "pegtl.hpp"

namespace tao::config::internal::rules
{
   namespace jaxn = tao::json::jaxn::internal::rules;

   struct wss
      : pegtl::star< jaxn::ws >
   {};

   struct wsp
      : pegtl::plus< jaxn::ws >
   {};

}  // namespace tao::config::internal::rules

#endif


================================================
FILE: include/tao/config/internal/key1.hpp
================================================
// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_KEY1_HPP
#define TAO_CONFIG_INTERNAL_KEY1_HPP

#include <initializer_list>
#include <string>
#include <vector>

#include "key1_action.hpp"
#include "key1_grammar.hpp"
#include "key1_part.hpp"
#include "pegtl.hpp"

namespace tao::config::internal
{
   struct key1
      : std::vector< key1_part >
   {
      key1() = default;

      key1( key1&& ) = default;
      key1& operator=( key1&& ) = default;

      ~key1() = default;

      key1( const key1& ) = default;
      key1& operator=( const key1& ) = default;

      explicit key1( const std::string& s )
      {
         assign( s );
      }

      key1( const std::initializer_list< key1_part >& l )
         : std::vector< key1_part >( l )
      {}

      key1( const std::vector< key1_part >::const_iterator& begin, const std::vector< key1_part >::const_iterator& end )
         : std::vector< key1_part >( begin, end )
      {}

      key1& operator=( const std::string& s )
      {
         clear();
         assign( s );
         return *this;
      }

      key1& operator=( const std::initializer_list< key1_part >& l )
      {
         vector() = l;
         return *this;
      }

      [[nodiscard]] std::vector< key1_part >& vector() noexcept
      {
         return static_cast< std::vector< key1_part >& >( *this );
      }

      [[nodiscard]] const std::vector< key1_part >& vector() const noexcept
      {
         return static_cast< const std::vector< key1_part >& >( *this );
      }

      void assign( const std::string& s )
      {
         using grammar = pegtl::must< rules::key1_rule, pegtl::eof >;
         pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > in( s, __FUNCTION__ );
         pegtl::parse< grammar, key1_action >( in, vector() );
      }
   };

   inline key1 pop_front( const key1& p )
   {
      assert( !p.empty() );

      return key1( p.begin() + 1, p.end() );
   }

   inline key1 pop_back( const key1& p )
   {
      assert( !p.empty() );

      return key1( p.begin(), p.end() - 1 );
   }

   inline key1& operator+=( key1& l, const key1& r )
   {
      l.insert( l.end(), r.begin(), r.end() );
      return l;
   }

   inline key1& operator+=( key1& l, const key1_part& p )
   {
      l.emplace_back( p );
      return l;
   }

   [[nodiscard]] inline key1 operator+( const key1& l, const key1& r )
   {
      key1 t( l );
      t += r;
      return t;
   }

   [[nodiscard]] inline key1 operator+( const key1& l, const key1_part& r )
   {
      key1 t( l );
      t += r;
      return t;
   }

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/key1_action.hpp
================================================
// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_KEY1_ACTION_HPP
#define TAO_CONFIG_INTERNAL_KEY1_ACTION_HPP

#include <cstddef>
#include <string>
#include <utility>
#include <vector>

#include "json.hpp"
#include "key1_grammar.hpp"
#include "key1_part.hpp"
#include "pegtl.hpp"

namespace tao::config::internal
{
   template< typename Rule >
   struct key1_action
      : pegtl::nothing< Rule >
   {};

   template<>
   struct key1_action< rules::ident >
   {
      template< typename Input >
      static void apply( const Input& in, std::vector< key1_part >& st )
      {
         st.emplace_back( in.string(), in.position() );
      }
   };

   template<>
   struct key1_action< rules::index >
   {
      template< typename Input >
      static void apply( const Input& in, std::vector< key1_part >& st )
      {
         st.emplace_back( std::size_t( std::stoul( in.string() ) ), in.position() );
      }
   };

   template<>
   struct key1_action< rules::asterisk >
   {
      template< typename Input >
      static void apply( const Input& in, std::vector< key1_part >& st )
      {
         st.emplace_back( part_asterisk, in.position() );
      }
   };

   template<>
   struct key1_action< rules::quoted_choice >
      : pegtl::change_action_and_states< json::jaxn::internal::unescape_action, std::string >
   {
      template< typename Input >
      static void success( const Input& in, std::string& unescaped, std::vector< key1_part >& st )
      {
         st.emplace_back( std::move( unescaped ), in.position() );  // TODO: Position from beginning of quoted string instead of end.
      }
   };

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/key1_grammar.hpp
================================================
// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_KEY1_GRAMMAR_HPP
#define TAO_CONFIG_INTERNAL_KEY1_GRAMMAR_HPP

#include "key_grammar.hpp"
#include "pegtl.hpp"

namespace tao::config::internal::rules
{
   // clang-format off
   struct asterisk : pegtl::one< '*' > {};

   struct key1_part : pegtl::sor< ident, quoted, index, asterisk > {};
   struct key1_rule : pegtl::list_must< key1_part, dot > {};
   // clang-format on

}  // namespace tao::config::internal::rules

#endif


================================================
FILE: include/tao/config/internal/key1_guard.hpp
================================================
// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_KEY1_GUARD_HPP
#define TAO_CONFIG_INTERNAL_KEY1_GUARD_HPP

#include <cassert>
#include <cstddef>
#include <utility>

#include "forward.hpp"
#include "key1.hpp"
#include "pegtl.hpp"

namespace tao::config::internal
{
   class [[nodiscard]] key1_guard
   {
   public:
      key1_guard() = delete;

      template< typename State >
      key1_guard( State& st, key1&& suffix )
         : m_prefix( st.prefix ),
           m_suffix( st.suffix ),
           m_size( m_prefix.size() )
      {
         m_prefix += m_suffix;
         m_suffix = std::move( suffix );
      }

      template< typename State >
      key1_guard( const pegtl_input_t& in, State& st, const function_map& /*unused*/ )
         : m_prefix( st.prefix ),
           m_suffix( st.suffix ),
           m_size( m_prefix.size() )
      {
         m_prefix += m_suffix;
         m_suffix.clear();
         m_suffix.emplace_back( in.position(), ++st.generation );
      }

      key1_guard( key1_guard&& ) = delete;
      key1_guard( const key1_guard& ) = delete;

      ~key1_guard()
      {
         assert( m_prefix.size() >= m_size );

         m_suffix.clear();
         m_suffix.insert( m_suffix.end(), m_prefix.begin() + m_size, m_prefix.end() );
         m_prefix.erase( m_prefix.begin() + m_size, m_prefix.end() );
      }

      void operator=( key1_guard&& ) = delete;
      void operator=( const key1_guard& ) = delete;

   private:
      key1& m_prefix;
      key1& m_suffix;

      const std::size_t m_size;
   };

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/key1_kind.hpp
================================================
// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_KEY1_KIND_HPP
#define TAO_CONFIG_INTERNAL_KEY1_KIND_HPP

namespace tao::config::internal
{
   enum class key1_kind : char
   {
      name = 0,
      index = 1,
      asterisk = 2,
      append = 3
   };

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/key1_part.hpp
================================================
// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_KEY1_PART_HPP
#define TAO_CONFIG_INTERNAL_KEY1_PART_HPP

#include <cassert>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <string>
#include <variant>

#include "constants.hpp"
#include "key1_kind.hpp"
#include "pegtl.hpp"

namespace tao::config::internal
{
   struct key1_part
   {
      using data_t = std::variant< std::string, std::size_t, part_asterisk_t, std::shared_ptr< std::uint64_t > >;

      key1_part( const part_asterisk_t t, const pegtl::position& p )
         : position( p ),
           data( t )
      {}

      // key1_part( const char, const pegtl::position& ) = delete;
      // key1_part( const signed char, const pegtl::position& ) = delete;
      // key1_part( const unsigned char, const pegtl::position& ) = delete;

      key1_part( const std::size_t i, const pegtl::position& p )
         : position( p ),
           data( i )
      {}

      key1_part( const pegtl::position& p, const std::uint64_t g )
         : position( p ),
           data( std::make_shared< std::uint64_t >( g ) )
      {}

      key1_part( const std::string& n, const pegtl::position& p )
         : position( p ),
           data( n )
      {}

      [[nodiscard]] key1_kind kind() const noexcept
      {
         return key1_kind( data.index() );
      }

      [[nodiscard]] std::size_t get_index() const noexcept
      {
         const auto* s = std::get_if< std::size_t >( &data );
         assert( s != nullptr );
         return *s;
      }

      [[nodiscard]] const std::string& get_name() const noexcept
      {
         const auto* s = std::get_if< std::string >( &data );
         assert( s != nullptr );
         return *s;
      }

      void set_generation( const std::uint64_t g ) noexcept
      {
         assert( g > 0 );

         if( const auto* s = std::get_if< std::shared_ptr< std::uint64_t > >( &data ) ) {
            assert( s != nullptr );
            assert( s->get() != nullptr );
            assert( g > **s );
            **s = g;
         }
      }

      [[nodiscard]] std::uint64_t get_generation() const noexcept
      {
         const auto* s = std::get_if< std::shared_ptr< std::uint64_t > >( &data );
         assert( s != nullptr );
         assert( s->get() != nullptr );
         assert( **s > 0 );
         return **s;
      }

      pegtl::position position;
      data_t data;
   };

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/key_action.hpp
================================================
// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_KEY_ACTION_HPP
#define TAO_CONFIG_INTERNAL_KEY_ACTION_HPP

#include <cstddef>
#include <string>
#include <utility>
#include <vector>

#include "json.hpp"
#include "key_grammar.hpp"
#include "pegtl.hpp"

#include "../key_part.hpp"

namespace tao::config::internal
{
   template< typename Rule >
   struct key_action
      : pegtl::nothing< Rule >
   {};

   template<>
   struct key_action< rules::ident >
   {
      template< typename Input >
      static void apply( const Input& in, std::vector< key_part >& st )
      {
         st.emplace_back( in.string() );
      }
   };

   template<>
   struct key_action< rules::index >
   {
      template< typename Input >
      static void apply( const Input& in, std::vector< key_part >& st )
      {
         st.emplace_back( std::size_t( std::stoul( in.string() ) ) );
      }
   };

   template<>
   struct key_action< rules::quoted_choice >
      : pegtl::change_action_and_states< json::jaxn::internal::unescape_action, std::string >
   {
      template< typename Input >
      static void success( const Input& /*unused*/, std::string& unescaped, std::vector< key_part >& st )
      {
         st.emplace_back( std::move( unescaped ) );
      }
   };

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/key_grammar.hpp
================================================
// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_KEY_GRAMMAR_HPP
#define TAO_CONFIG_INTERNAL_KEY_GRAMMAR_HPP

#include "json.hpp"
#include "pegtl.hpp"

namespace tao::config::internal::rules
{
   namespace jaxn = tao::json::jaxn::internal::rules;

   // clang-format off
   struct dot : pegtl::one< '.' > {};

   struct index : pegtl::rep_min_max< 1, 15, pegtl::digit > {};

   struct ident_first : pegtl::ranges< 'a', 'z', 'A', 'Z', '_' > {};
   struct ident_other : pegtl::ranges< 'a', 'z', 'A', 'Z', '0', '9', '-', '-', '_' > {};
   struct ident : pegtl::seq< ident_first, pegtl::star< ident_other > > {};

   struct at_quote : pegtl::at< pegtl::one< '\'', '"' > > {};

   struct quoted_choice : jaxn::string_fragment {};
   struct quoted : pegtl::if_must< at_quote, quoted_choice > {};

   struct key_other : pegtl::sor< ident, quoted, index > {};
   struct key_first : pegtl::sor< ident, quoted > {};

   struct key_rule : pegtl::seq< key_first, pegtl::star_must< dot, key_other > > {};
   // clang-format on

}  // namespace tao::config::internal::rules

#endif


================================================
FILE: include/tao/config/internal/limits.hpp
================================================
// Copyright (c) 2021-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_LIMITS_HPP
#define TAO_CONFIG_INTERNAL_LIMITS_HPP

#include <cstddef>

namespace tao::config::internal
{
   static constexpr std::size_t global_nesting_limit = 96;

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/object.hpp
================================================
// Copyright (c) 2019-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_OBJECT_HPP
#define TAO_CONFIG_INTERNAL_OBJECT_HPP

#include <cassert>
#include <map>
#include <string>

#include "forward.hpp"
#include "pegtl.hpp"

namespace tao::config::internal
{
   template< typename C >
   struct basic_object
   {
      using data_t = std::map< std::string, C >;

      basic_object() = delete;

      explicit basic_object( const pegtl::position& p )
         : position( p )
      {}

      basic_object( basic_object&& ) = default;
      basic_object( const basic_object& ) = default;

      ~basic_object() = default;

      basic_object& operator=( basic_object&& ) = default;
      basic_object& operator=( const basic_object& ) = default;

      [[nodiscard]] std::pair< const std::string, C >* find( const std::string& k ) noexcept
      {
         const auto i = object.find( k );
         return ( i == object.end() ) ? nullptr : ( &*i );
      }

      [[nodiscard]] const std::pair< const std::string, C >* find( const std::string& k ) const noexcept
      {
         const auto i = object.find( k );
         return ( i == object.end() ) ? nullptr : ( &*i );
      }

      [[nodiscard]] const pegtl::position& get_position() const noexcept
      {
         return position;
      }

      std::map< std::string, C > object;
      pegtl::position position;
   };

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/parse_utility.hpp
================================================
// Copyright (c) 2019-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_PARSE_UTILITY_HPP
#define TAO_CONFIG_INTERNAL_PARSE_UTILITY_HPP

#include <utility>

#include "forward.hpp"
#include "key1.hpp"
#include "key1_action.hpp"
#include "key1_grammar.hpp"
#include "pegtl.hpp"
#include "reference2.hpp"
#include "reference2_action.hpp"
#include "reference2_grammar.hpp"

namespace tao::config::internal
{
   [[nodiscard]] inline key1 parse_key1( pegtl_input_t& in )
   {
      key1 result;
      pegtl::parse< pegtl::must< rules::key1_rule >, key1_action >( in, result.vector() );
      return result;
   }

   [[nodiscard]] inline reference2 parse_reference2( pegtl_input_t& in )
   {
      reference2 result;
      pegtl::parse< pegtl::must< rules::reference2_rest >, reference2_action >( in, result.vector() );  // NOTE: Assumes that the opening bracket was already parsed!
      return result;
   }

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/pegtl.hpp
================================================
// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_PEGTL_HPP
#define TAO_CONFIG_INTERNAL_PEGTL_HPP

#include <tao/pegtl.hpp>

#include <tao/pegtl/contrib/function.hpp>
#include <tao/pegtl/contrib/instantiate.hpp>
#include <tao/pegtl/contrib/predicates.hpp>

#include <tao/pegtl/change_action_and_state.hpp>

namespace tao::pegtl
{
   template< typename P >
   using invert = internal::predicates< internal::predicate_not_test, typename P::peek_t, P >;

}  // namespace tao::pegtl

namespace tao::config
{
   using pegtl_input_t = pegtl::memory_input< pegtl::tracking_mode::eager, pegtl::eol::lf_crlf >;

}  // namespace tao::config

#endif


================================================
FILE: include/tao/config/internal/phase1_append.hpp
================================================
// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_PHASE1_APPEND_HPP
#define TAO_CONFIG_INTERNAL_PHASE1_APPEND_HPP

#include <cassert>
#include <cstddef>
#include <iterator>
#include <optional>
#include <set>
#include <stdexcept>
#include <string>
#include <type_traits>

#include "array.hpp"
#include "concat.hpp"
#include "constants.hpp"
#include "entry.hpp"
#include "json.hpp"
#include "key1.hpp"
#include "limits.hpp"
#include "object.hpp"
#include "phase1_mode.hpp"
#include "reference2.hpp"

namespace tao::config::internal
{
   template< typename T >
   void phase1_append( concat& c, const key1& path, const T& thing, const phase1_mode mode );

   template< typename T >
   void phase1_append_asterisk( concat& c, const pegtl::position& p, const key1& path, const T& thing, const phase1_mode mode )
   {
      c.back_ensure_init( asterisk_init, p );
      phase1_append( c.concat.back().get_asterisk(), path, thing, mode );
   }

   template< typename T >
   void phase1_append_name( concat& c, const pegtl::position& p, const std::string& name, const key1& path, const T& thing, const phase1_mode mode )
   {
      c.back_ensure_init( object_init, p );
      const auto pair = c.concat.back().get_object().object.try_emplace( name, p );
      pair.first->second.implicit = ( mode == phase1_mode::implicit ) && ( pair.second || pair.first->second.implicit );
      phase1_append( pair.first->second, path, thing, mode );
   }

   template< typename T >
   void phase1_append_index( concat& c, const pegtl::position& p, const std::size_t index, const key1& path, const T& thing, const phase1_mode mode )
   {
      std::size_t n = index;

      for( auto& e : c.concat ) {
         switch( e.kind() ) {
            case entry_kind::NULL_:
            case entry_kind::BOOLEAN:
            case entry_kind::STRING:
            case entry_kind::BINARY:
            case entry_kind::SIGNED:
            case entry_kind::UNSIGNED:
            case entry_kind::DOUBLE:
               throw pegtl::parse_error( "cannot index (across) value", p );
            case entry_kind::ARRAY:
               if( e.get_array().array.size() > n ) {
                  phase1_append( *std::next( e.get_array().array.begin(), n ), path, thing, mode );
                  return;
               }
               n -= e.get_array().array.size();
               continue;
            case entry_kind::OBJECT:
               throw pegtl::parse_error( "cannot index (across) object", p );
            case entry_kind::ASTERISK:
               throw pegtl::parse_error( "cannot index (across) asterisk", p );
            case entry_kind::REFERENCE:
               throw pegtl::parse_error( "cannot index (across) reference", p );
         }
      }
      throw pegtl::parse_error( "index out of range", p );
   }

   template< typename T >
   void phase1_append_append( concat& c, const pegtl::position& p, const std::uint64_t g, const key1& path, const T& thing, const phase1_mode mode )
   {
      c.back_ensure_init( array_init, p );
      auto& a = c.concat.back().get_array();
      if( g > c.generation ) {
         c.generation = g;
         concat& d = a.array.emplace_back( p );
         d.remove = false;  // TODO: Make consistent with entry::expand()?
         phase1_append( d, path, thing, mode );
         return;
      }
      assert( !a.array.empty() );
      phase1_append( a.array.back(), path, thing, mode );
   }

   template< typename T >
   void phase1_append( concat& c, const key1& path, const T& thing, const phase1_mode mode )
   {
      if( path.empty() ) {
         thing( c );
         return;
      }
      const auto& part = path.at( 0 );

      switch( part.kind() ) {
         case key1_kind::asterisk:
            phase1_append_asterisk( c, part.position, pop_front( path ), thing, mode );
            return;
         case key1_kind::name:
            phase1_append_name( c, part.position, part.get_name(), pop_front( path ), thing, mode );
            return;
         case key1_kind::index:
            phase1_append_index( c, part.position, part.get_index(), pop_front( path ), thing, mode );
            return;
         case key1_kind::append:
            phase1_append_append( c, part.position, part.get_generation(), pop_front( path ), thing, mode );
            return;
      }
      throw std::logic_error( "code should be unreachable" );  // LCOV_EXCL_LINE
   }

   template< typename T >
   void phase1_append( object& o, const key1& path, const T& thing, const phase1_mode mode )
   {
      assert( !path.empty() );

      if( path.size() > global_nesting_limit ) {
         throw pegtl::parse_error( "nesting depth exceeded", path.at( global_nesting_limit ).position );
      }
      if( path.front().kind() != key1_kind::name ) {
         throw pegtl::parse_error( "expected name", path.front().position );
      }
      const std::string& name = path.front().get_name();
      const auto pair = o.object.try_emplace( name, path.front().position );
      pair.first->second.implicit = ( mode == phase1_mode::implicit ) && ( pair.second || pair.first->second.implicit );
      phase1_append( pair.first->second, pop_front( path ), thing, mode );
   }

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/phase1_mode.hpp
================================================
// Copyright (c) 2021-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_PHASE1_MODE_HPP
#define TAO_CONFIG_INTERNAL_PHASE1_MODE_HPP

namespace tao::config::internal
{
   enum class phase1_mode : bool
   {
      implicit = true,
      manifest = false  // Can't use explicit as enum label.
   };

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/phase2_access.hpp
================================================
// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_PHASE2_ACCESS_HPP
#define TAO_CONFIG_INTERNAL_PHASE2_ACCESS_HPP

#include <cassert>
#include <cstddef>
#include <iterator>
#include <stdexcept>
#include <string>

#include "array.hpp"
#include "concat.hpp"
#include "constants.hpp"
#include "entry.hpp"
#include "key1.hpp"
#include "object.hpp"
#include "statistics.hpp"

namespace tao::config::internal
{
   struct phase2_access_return
   {};

   [[nodiscard]] inline const concat* phase2_access( const concat& c, const key1& suffix, const int down );

   [[nodiscard]] inline const concat* phase2_access_name( const concat& c, const pegtl::position& p, const std::string& name, const key1& suffix, const int down )
   {
      if( c.concat.empty() ) {
         if( down >= 0 ) {
            return nullptr;
         }
         throw phase2_access_return();  // TODO: Or error or return?
      }
      if( c.concat.size() > 1 ) {
         throw phase2_access_return();
      }
      const auto& e = c.concat.front();
      switch( e.kind() ) {
         case entry_kind::NULL_:
         case entry_kind::BOOLEAN:
         case entry_kind::STRING:
         case entry_kind::BINARY:
         case entry_kind::SIGNED:
         case entry_kind::UNSIGNED:
         case entry_kind::DOUBLE:
            throw pegtl::parse_error( "access name in value", p );  // TODO: Add c.position to the exception, too?
         case entry_kind::ARRAY:
            if( down >= 0 ) {
               return nullptr;
            }
            throw pegtl::parse_error( "access name in array", p );
         case entry_kind::OBJECT:
            if( const auto i = e.get_object().object.find( name ); i != e.get_object().object.end() ) {
               return phase2_access( i->second, suffix, down - 1 );
            }
            if( down >= 0 ) {
               return nullptr;
            }
            throw pegtl::parse_error( "name not found", p );
         case entry_kind::ASTERISK:
            if( down >= 0 ) {
               return nullptr;
            }
            throw pegtl::parse_error( "name not found", p );
         case entry_kind::REFERENCE:
            throw phase2_access_return();
      }
      throw std::logic_error( "code should be unreachable" );  // LCOV_EXCL_LINE
   }

   [[nodiscard]] inline const concat* phase2_access_index( const concat& c, const pegtl::position& p, const std::size_t index, const key1& suffix, const int down )
   {
      if( c.concat.empty() ) {
         if( down >= 0 ) {
            return nullptr;
         }
         throw phase2_access_return();  // TODO: Or error or return?
      }
      if( c.concat.size() > 1 ) {
         throw phase2_access_return();
      }
      const auto& e = c.concat.front();
      switch( e.kind() ) {
         case entry_kind::NULL_:
         case entry_kind::BOOLEAN:
         case entry_kind::STRING:
         case entry_kind::BINARY:
         case entry_kind::SIGNED:
         case entry_kind::UNSIGNED:
         case entry_kind::DOUBLE:
            throw pegtl::parse_error( "cannot index (across) value", p );
         case entry_kind::ARRAY:
            if( e.get_array().array.size() > index ) {
               return phase2_access( *std::next( e.get_array().array.begin(), index ), suffix, down - 1 );
            }
            if( down >= 0 ) {
               return nullptr;
            }
            throw pegtl::parse_error( "index out of range", p );
         case entry_kind::OBJECT:
            throw pegtl::parse_error( "cannot index (across) object", p );
         case entry_kind::ASTERISK:
            if( down >= 0 ) {
               return nullptr;
            }
            throw pegtl::parse_error( "cannot index (across) asterisk", p );
         case entry_kind::REFERENCE:
            throw pegtl::parse_error( "cannot index (across) reference", p );
      }
      throw std::logic_error( "code should be unreachable" );  // LCOV_EXCL_LINE
   }

   [[nodiscard]] inline const concat* phase2_access( const concat& c, const key1_part& p, const key1& suffix, const int down )
   {
      switch( p.kind() ) {
         case key1_kind::asterisk:
            throw pegtl::parse_error( "unable to access asterisk", p.position );
         case key1_kind::name:
            return phase2_access_name( c, p.position, p.get_name(), suffix, down );
         case key1_kind::index:
            return phase2_access_index( c, p.position, p.get_index(), suffix, down );
         case key1_kind::append:
            throw pegtl::parse_error( "this should be impossible", p.position );
      }
      throw std::logic_error( "code should be unreachable" );  // LCOV_EXCL_LINE
   }

   [[nodiscard]] inline const concat* phase2_access( const concat& c, const key1& suffix, const int down )
   {
      if( !suffix.empty() ) {
         return phase2_access( c, suffix.at( 0 ), pop_front( suffix ), down );
      }
      if( statistics( c ).is_primitive() ) {
         return &c;
      }
      throw phase2_access_return();
   }

   [[nodiscard]] inline const concat* phase2_access( const object& o, const key1& prefix, const key1& suffix )
   {
      assert( !suffix.empty() );

      try {
         for( std::size_t i = 0; i <= prefix.size(); ++i ) {
            const int down = int( prefix.size() ) - int( i );
            const key1 path = key1( prefix.begin(), prefix.end() - i ) + suffix;
            const auto j = o.object.find( path.front().get_name() );
            if( j != o.object.end() ) {
               if( const concat* c = phase2_access( j->second, pop_front( path ), down - 1 ) ) {
                  return c;
               }
            }
         }
         return nullptr;
      }
      catch( const phase2_access_return& /*unused*/ ) {
         return nullptr;
      }
   }

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/phase2_additions.hpp
================================================
// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_PHASE2_ADDITIONS_HPP
#define TAO_CONFIG_INTERNAL_PHASE2_ADDITIONS_HPP

#include <cassert>
#include <cstddef>
#include <iterator>
#include <stdexcept>

#include "array.hpp"
#include "concat.hpp"
#include "entry.hpp"
#include "forward.hpp"
#include "json.hpp"
#include "object.hpp"
#include "string_utility.hpp"

namespace tao::config::internal
{
   struct phase2_additions_impl
   {
      explicit phase2_additions_impl( object& root )
         : m_root( root )
      {}

      [[nodiscard]] std::size_t process()
      {
         for( auto& p : m_root.object ) {
            process_concat( p.second );
         }
         return m_changes;
      }

   private:
      object& m_root;
      std::size_t m_changes = 0;

      void process_concat( concat& c )
      {
         for( entry& e : c.concat ) {
            process_entry( e );
         }
         if( c.concat.size() < 2 ) {
            return;
         }
         for( auto r = ++c.concat.begin(); r != c.concat.end(); ++r ) {
            const auto l = std::prev( r );
            switch( r->kind() ) {
               case entry_kind::NULL_:
               case entry_kind::BOOLEAN:
                  throw_type_error( *l, *r );

               case entry_kind::SIGNED:
               case entry_kind::UNSIGNED:
                  if( ignore_entry( *l ) || ignore_entry( *r ) ) {
                     continue;
                  }
                  if( ( r->kind() == entry_kind::SIGNED ) ) {
                     if( l->kind() == entry_kind::SIGNED ) {
                        r->get_signed_atom().value += l->get_signed();
                        break;
                     }
                     else if( l->kind() == entry_kind::UNSIGNED ) {
                        r->get_signed_atom().value += std::int64_t( l->get_unsigned() );
                        break;
                     }
                  }
                  else {  // r->kind() == entry_kind::UNSIGNED
                     if( l->kind() == entry_kind::UNSIGNED ) {
                        r->get_unsigned_atom().value += l->get_unsigned();
                        break;
                     }
                     else if( l->kind() == entry_kind::SIGNED ) {
                        l->get_signed_atom().value += std::int64_t( r->get_unsigned() );
                        ( *r ) = ( *l );
                        break;
                     }
                  }
                  throw_type_error( *l, *r );

               case entry_kind::DOUBLE:
                  if( !throw_type_error_if( *l, *r, entry_kind::DOUBLE ) ) {
                     continue;
                  }
                  r->get_double_atom().value += l->get_double();
                  break;

               case entry_kind::STRING:
                  if( !throw_type_error_if( *l, *r, entry_kind::STRING ) ) {
                     continue;
                  }
                  r->get_string_atom().value = l->get_string() + r->get_string();
                  break;

               case entry_kind::BINARY:
                  if( !throw_type_error_if( *l, *r, entry_kind::BINARY ) ) {
                     continue;
                  }
                  r->get_binary_atom().value.insert( r->get_binary().begin(), l->get_binary().begin(), l->get_binary().end() );
                  break;

               case entry_kind::ARRAY:
                  if( !throw_type_error_if( *l, *r, entry_kind::ARRAY ) ) {
                     continue;
                  }
                  r->get_array().array.splice( r->get_array().array.begin(), l->get_array().array );  // throw_type_error_if returns false if l and/or r are functions.
                  break;

               case entry_kind::OBJECT:
                  if( !throw_type_error_if( *l, *r, entry_kind::OBJECT ) ) {
                     continue;
                  }
                  process_object( std::move( l->get_object() ), r->get_object() );
                  break;

               case entry_kind::ASTERISK:
               case entry_kind::REFERENCE:
                  continue;
            }
            [[maybe_unused]] const auto t = c.concat.erase( l );
            assert( t == r );
            ++m_changes;
         }
      }

      void process_entry( entry& e )
      {
         switch( e.kind() ) {
            case entry_kind::NULL_:
            case entry_kind::BOOLEAN:
            case entry_kind::STRING:
            case entry_kind::BINARY:
            case entry_kind::SIGNED:
            case entry_kind::UNSIGNED:
            case entry_kind::DOUBLE:
               return;
            case entry_kind::ARRAY:
               for( concat& c : e.get_array().array ) {
                  process_concat( c );
               }
               return;
            case entry_kind::OBJECT:
               for( auto& p : e.get_object().object ) {
                  process_concat( p.second );
               }
               return;
            case entry_kind::ASTERISK:
               process_concat( e.get_asterisk() );
               return;
            case entry_kind::REFERENCE:
               return;
         }
         throw std::logic_error( "code should be unreachable" );  // LCOV_EXCL_LINE
      }

      [[nodiscard]] static bool ignore_entry( const entry& e ) noexcept
      {
         if( ( e.kind() == entry_kind::ASTERISK ) || ( e.kind() == entry_kind::REFERENCE ) ) {
            return true;
         }
         if( ( e.kind() == entry_kind::ARRAY ) && ( !e.get_array().function.empty() ) ) {
            return true;
         }
         return false;
      }

      [[nodiscard]] static bool throw_type_error_if( const entry& l, const entry& r, const entry_kind k )
      {
         if( ignore_entry( l ) ) {
            return false;
         }
         if( ignore_entry( r ) ) {
            return false;
         }
         if( l.kind() == k ) {
            return true;
         }
         throw_type_error( l, r );
      }

      [[noreturn]] static void throw_type_error( const entry& l, const entry& r )
      {
         throw pegtl::parse_error( strcat( "incompatible or invalid type(s) in addition ", l.kind(), "@", l.get_position(), " and ", r.kind(), "@", r.get_position() ), pegtl::position( 0, 0, 0, "TODO: location of '+'" ) );
      }

      static void process_object( object&& l, object& r )
      {
         for( std::pair< const std::string, concat >& m : l.object ) {
            const auto pair = r.object.try_emplace( m.first, m.second );
            if( !pair.second ) {
               if( pair.first->second.remove ) {
                  continue;
               }
               if( m.second.remove ) {
                  pair.first->second.remove = true;
               }
               if( m.second.temporary ) {
                  pair.first->second.temporary = true;
               }
               pair.first->second.concat.splice( pair.first->second.concat.begin(), m.second.concat );
            }
         }
      }
   };

   [[nodiscard]] inline std::size_t phase2_additions( object& root )
   {
      return phase2_additions_impl( root ).process();
   }

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/phase2_asterisks.hpp
================================================
// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_PHASE2_ASTERISKS_HPP
#define TAO_CONFIG_INTERNAL_PHASE2_ASTERISKS_HPP

#include <cstddef>
#include <list>
#include <set>
#include <stdexcept>
#include <string>

#include "array.hpp"
#include "concat.hpp"
#include "entry.hpp"
#include "forward.hpp"
#include "json.hpp"
#include "object.hpp"

namespace tao::config::internal
{
   struct phase2_asterisks_impl
   {
      explicit phase2_asterisks_impl( object& root )
         : m_root( root )
      {}

      [[nodiscard]] std::size_t process()
      {
         for( auto& p : m_root.object ) {
            process_concat( p.second );
         }
         return m_changes;
      }

   private:
      object& m_root;
      std::size_t m_changes = 0;

      void process_concat( concat& c )
      {
         auto i = c.concat.begin();

         while( i != c.concat.end() ) {
            process_entry( c, i );
         }
      }

      void process_entry( concat& c, std::list< entry >::iterator& i )
      {
         switch( i->kind() ) {
            case entry_kind::NULL_:
            case entry_kind::BOOLEAN:
            case entry_kind::STRING:
            case entry_kind::BINARY:
            case entry_kind::SIGNED:
            case entry_kind::UNSIGNED:
            case entry_kind::DOUBLE:
               ++i;
               return;
            case entry_kind::ARRAY:
               if( c.concat.size() == 1 ) {
                  for( concat& d : i->get_array().array ) {
                     process_concat( d );
                  }
               }
               ++i;
               return;
            case entry_kind::OBJECT:
               if( c.concat.size() == 1 ) {
                  for( auto& p : i->get_object().object ) {
                     process_concat( p.second );
                  }
               }
               ++i;
               return;
            case entry_kind::ASTERISK:
               process_asterisk( c, i );
               return;
            case entry_kind::REFERENCE:
               ++i;
               return;
         }
         throw std::logic_error( "code should be unreachable" );  // LCOV_EXCL_LINE
      }

      void process_asterisk( concat& c, std::list< entry >::iterator& i )
      {
         const concat star = std::move( i->get_asterisk() );

         std::set< std::string > names;

         for( auto j = c.concat.begin(); j != i; ++j ) {
            switch( j->kind() ) {
               case entry_kind::NULL_:
               case entry_kind::BOOLEAN:
               case entry_kind::STRING:
               case entry_kind::BINARY:
               case entry_kind::SIGNED:
               case entry_kind::UNSIGNED:
               case entry_kind::DOUBLE:
                  continue;
               case entry_kind::ARRAY:
                  if( !j->get_array().function.empty() ) {
                     throw pegtl::parse_error( "please do not use an asterisk inside of a function", j->get_array().position );
                  }
                  process_array_and_asterisk( j->get_array(), star );
                  continue;
               case entry_kind::OBJECT:
                  for( const auto& p : j->get_object().object ) {
                     names.emplace( p.first );
                  }
                  continue;
               case entry_kind::ASTERISK:
               case entry_kind::REFERENCE:
                  continue;
            }
         }
         for( auto j = i; j != c.concat.end(); ++j ) {
            switch( j->kind() ) {
               case entry_kind::NULL_:
               case entry_kind::BOOLEAN:
               case entry_kind::STRING:
               case entry_kind::BINARY:
               case entry_kind::SIGNED:
               case entry_kind::UNSIGNED:
               case entry_kind::DOUBLE:
                  continue;
               case entry_kind::ARRAY:
                  if( !j->get_array().function.empty() ) {
                     throw pegtl::parse_error( "please do not use an asterisk inside of a function", j->get_array().position );
                  }
                  process_asterisk_and_array( star, j->get_array() );
                  continue;
               case entry_kind::OBJECT:
                  for( const auto& p : j->get_object().object ) {
                     names.emplace( p.first );
                  }
                  continue;
               case entry_kind::ASTERISK:
               case entry_kind::REFERENCE:
                  continue;
            }
         }
         ++m_changes;

         if( names.empty() ) {
            i = c.concat.erase( i );
            return;
         }
         i->set_object( star.position );

         for( const auto& name : names ) {
            [[maybe_unused]] const auto [ j, b ] = i->get_object().object.try_emplace( name, star );
            assert( b && ( j->second.temporary == star.temporary ) );
         }
         ++i;
      }

      void process_asterisk_and_array( const concat& s, array& a )
      {
         for( concat& c : a.array ) {
            if( c.remove ) {
               continue;
            }
            c.remove = s.remove;
            c.temporary |= s.temporary;
            c.concat.insert( c.concat.begin(), s.concat.begin(), s.concat.end() );
         }
      }

      void process_array_and_asterisk( array& a, const concat& s )
      {
         for( concat& c : a.array ) {
            if( s.remove ) {
               c.remove = true;
               c.concat.clear();
            }
            c.temporary |= s.temporary;
            c.concat.insert( c.concat.end(), s.concat.begin(), s.concat.end() );
         }
      }
   };

   [[nodiscard]] inline std::size_t phase2_asterisks( object& root )
   {
      return phase2_asterisks_impl( root ).process();
   }

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/phase2_everything.hpp
================================================
// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_PHASE2_EVERYTHING_HPP
#define TAO_CONFIG_INTERNAL_PHASE2_EVERYTHING_HPP

#include "forward.hpp"
#include "phase2_additions.hpp"
#include "phase2_asterisks.hpp"
#include "phase2_functions.hpp"
#include "phase2_references.hpp"
#include "state.hpp"

namespace tao::config::internal
{
   [[nodiscard]] inline bool phase2_iteration( state& st, const function_map& fm )
   {
      return ( phase2_functions( st, fm ) | phase2_additions( st.root ) | phase2_references( st.root ) | phase2_asterisks( st.root ) ) > 0;
   }

   inline void phase2_everything( state& st, const function_map& fm )
   {
      while( phase2_iteration( st, fm ) ) {
         // This loop could do with some major optimisations; probably not worth the effort for config files.
      }
   }

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/phase2_functions.hpp
================================================
// Copyright (c) 2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_PHASE2_FUNCTIONS_HPP
#define TAO_CONFIG_INTERNAL_PHASE2_FUNCTIONS_HPP

#include <cstddef>
#include <stdexcept>
#include <string>

#include "array.hpp"
#include "concat.hpp"
#include "config_action.hpp"
#include "config_grammar.hpp"
#include "entry.hpp"
#include "forward.hpp"
#include "function_traits.hpp"
#include "object.hpp"
#include "pegtl.hpp"
#include "state.hpp"

namespace tao::config::internal
{
   struct phase2_functions_impl
   {
      phase2_functions_impl( state& st, const function_map& fm )
         : m_state( st ),
           m_functions( fm )
      {}

      [[nodiscard]] std::size_t process()
      {
         for( auto& p : m_state.root.object ) {
            process_concat( p.second );
         }
         return m_changes;
      }

   private:
      state& m_state;
      std::size_t m_changes = 0;
      const function_map& m_functions;

      void process_concat( concat& c )
      {
         for( auto& e : c.concat ) {
            process_entry( e );
         }
      }

      void process_entry( entry& e )
      {
         switch( e.kind() ) {
            case entry_kind::NULL_:
            case entry_kind::BOOLEAN:
            case entry_kind::STRING:
            case entry_kind::BINARY:
            case entry_kind::SIGNED:
            case entry_kind::UNSIGNED:
            case entry_kind::DOUBLE:
               return;
            case entry_kind::ARRAY:
               for( auto& c : e.get_array().array ) {
                  process_concat( c );
               }
               if( !e.get_array().function.empty() ) {
                  process_function( e );
               }
               return;
            case entry_kind::OBJECT:
               for( auto& p : e.get_object().object ) {
                  process_concat( p.second );
               }
               return;
            case entry_kind::ASTERISK:
            case entry_kind::REFERENCE:
               return;
         }
         throw std::logic_error( "code should be unreachable" );  // LCOV_EXCL_LINE
      }

      void process_function( entry& e )
      {
         array& a = e.get_array();

         if( a.function == "parse" ) {
            process_parse_function( e, a );
            ++m_changes;
            return;
         }
         const auto i = m_functions.find( a.function );

         if( i == m_functions.end() ) {
            throw pegtl::parse_error( "unknown function name " + a.function, a.position );
         }
         if( i->second( e ) ) {
            ++m_changes;
         }
      }

      void process_parse_function( entry& e, array& a )
      {
         try {
            state st;
            std::size_t i = 0;
            const std::string s = function_traits< std::string >::get( a, i );
            const key1 k = { key1_part( std::string( "\0", 1 ), a.position ) };
            const key1_guard kg( st, key1( k ) );
            pegtl::string_input< pegtl::tracking_mode::eager, pegtl_input_t::eol_t > in( s, __FUNCTION__ );
            pegtl::parse_nested< rules::value, config_action >( a.position, static_cast< pegtl_input_t& >( in ), st, m_functions );
            assert( st.root.object.size() == 1 );
            assert( st.root.object.begin()->second.concat.size() == 1 );
            e = st.root.object.begin()->second.concat.front();  // TODO: This is slightly hack-ish.
         }
         catch( const arguments_unready& ) {
         }
      }
   };

   [[nodiscard]] inline std::size_t phase2_functions( state& st, const function_map& fm )
   {
      return phase2_functions_impl( st, fm ).process();
   }

}  // namespace tao::config::internal

#endif


================================================
FILE: include/tao/config/internal/phase2_references.hpp
================================================
// Copyright (c) 2019-2024 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/config/

#ifndef TAO_CONFIG_INTERNAL_PHASE2_REFERENCES_HPP
#define TAO_CONFIG_INTERNAL_PHASE2_REFERENCES_HPP

#include <cassert>
#include <cstddef>
#include <optional>
#include <set>
#include <stdexcept>
#include <vector>

#include "array.hpp"
#include "concat.hpp"
#include "entry.hpp"
#include "forward.hpp"
#include "json.hpp"
#include "object.hpp"
#include "phase2_access.hpp"
#include "string_utility.hpp"

namespace tao::config::internal
{
   struct phase2_references_impl
   {
      explicit phase2_references_impl( object& root )
         : m_root( root )
      {}

      [[nodiscard]] std::size_t process()
      {
         for( auto& p : m_root.object ) {
            process_concat( key1{ key1_part( p.first, m_root.position ) }, p.second );
         }
         return m_changes;
      }

   private:
      object& m_root;
      std::size_t m_changes = 0;

      void process_concat( const key1& prefix, concat& c )
      {
         for( auto& e : c.concat ) {
            if( const concat* d = process_entry( prefix, e ); d != nullptr ) {
               assert( d != &c );  // TODO: This needs to be ensured elsewhere/in another way.

               if( !d->concat.empty() ) {
                  assert( d->concat.size() == 1 );

                  e = d->concat.front();
                  ++m_changes;
               }
            }
         }
      }

      [[nodiscard]] std::optional< key1_part > process_reference_part( const key1& prefix, const reference2_part& part )
      {
         switch( part.kind() ) {
            case reference2_kind::name:
               return key1_part( part.get_name(), part.position );
            case reference2_kind::index:
               return key1_part( part.get_index(), part.position );
            case reference2_kind::vector:
               return process_inner_reference( prefix, part.get_vector() );
         }
         throw std::logic_error( "code should be unreachable" );  // LCOV_EXCL_LINE
      }

      [[nodiscard]] const concat* process_reference_parts( const key1& prefix, const std::vector< reference2_part >& reference )
      {
         key1 suffix;

         for( auto& p : reference ) {
            if( const std::optional< key1_part > k = process_reference_part( prefix, p ) ) {
               suffix += *k;
               continue;
            }
            return nullptr;
         }
         assert( !prefix.empty() );

         return phase2_access( m_root, pop_back( prefix ), suffix );  // Returns nullptr if not primitive.
      }

      [[nodiscard]] std::optional< key1_part > process_inner_reference( const key1& prefix, const std::vector< reference2_part >& reference )
      {
         if( const concat* c = process_reference_parts( prefix, reference ) ) {
            if( c->concat.size() == 1 ) {
               const entry& e = c->concat.back();
               switch( e.kind() ) {
                  case entry_kind::STRING:
                     return key1_part( e.get_string(), e.get_string_atom().position );
                  case entry_kind::UNSIGNED:
                     return key1_part( e.get_unsigned(), e.get_unsigned_atom().position );
                  case entry_kind::NULL_:
                  case entry_kind::BOOLEAN:
                  case entry_kind::BINARY:
                  case entry_kind::SIGNED:
                  case entry_kind::DOUBLE:
                  case entry_kind::ARRAY:
                  case entry_kind::OBJECT:
                  case entry_kind::ASTERISK:
                  case entry_kind::REFERENCE:
                     throw pegtl::parse_error( strcat( "invalid type '", e.kind(), "' for reference part" ), e.get_position() );
               }
            }
         }
         return std::nullopt;
      }

      [[nodiscard]] const concat* process_entry( const key1& prefix, entry& e )
      {
         switch( e.kind() ) {
            case entry_kind::NULL_:
            case entry_kind::BOOL
Download .txt
gitextract_84t47bfe/

├── .clang-format
├── .cmake/
│   └── taocpp-config-config.cmake.in
├── .codecov.yml
├── .github/
│   └── workflows/
│       ├── clang-analyze.yml
│       ├── clang-format.yml
│       ├── clang-tidy.yml
│       ├── code-coverage.yml
│       ├── codeql-analysis.yml
│       ├── linux.yml
│       ├── macos.yml
│       ├── sanitizer.yml
│       └── windows.yml
├── .gitignore
├── .gitmodules
├── CMakeLists.txt
├── LICENSE
├── Makefile
├── README.md
├── doc/
│   ├── All-Config-Functions.md
│   ├── Changelog.md
│   ├── Parsing-Config-Files.md
│   ├── README.md
│   └── Writing-Config-Files.md
├── include/
│   └── tao/
│       ├── config/
│       │   ├── access.hpp
│       │   ├── annotation.hpp
│       │   ├── assign.hpp
│       │   ├── contrib/
│       │   │   └── rot13.hpp
│       │   ├── from_file.hpp
│       │   ├── from_files.hpp
│       │   ├── from_input.hpp
│       │   ├── from_string.hpp
│       │   ├── internal/
│       │   │   ├── array.hpp
│       │   │   ├── atom.hpp
│       │   │   ├── change_action_and_states.hpp
│       │   │   ├── concat.hpp
│       │   │   ├── config_action.hpp
│       │   │   ├── config_grammar.hpp
│       │   │   ├── config_parser.hpp
│       │   │   ├── constants.hpp
│       │   │   ├── debug_traits.hpp
│       │   │   ├── entry.hpp
│       │   │   ├── entry_kind.hpp
│       │   │   ├── events_from_value.hpp
│       │   │   ├── forward.hpp
│       │   │   ├── function_implementations.hpp
│       │   │   ├── function_traits.hpp
│       │   │   ├── function_wrapper.hpp
│       │   │   ├── jaxn_action.hpp
│       │   │   ├── jaxn_to_entry.hpp
│       │   │   ├── json.hpp
│       │   │   ├── key1.hpp
│       │   │   ├── key1_action.hpp
│       │   │   ├── key1_grammar.hpp
│       │   │   ├── key1_guard.hpp
│       │   │   ├── key1_kind.hpp
│       │   │   ├── key1_part.hpp
│       │   │   ├── key_action.hpp
│       │   │   ├── key_grammar.hpp
│       │   │   ├── limits.hpp
│       │   │   ├── object.hpp
│       │   │   ├── parse_utility.hpp
│       │   │   ├── pegtl.hpp
│       │   │   ├── phase1_append.hpp
│       │   │   ├── phase1_mode.hpp
│       │   │   ├── phase2_access.hpp
│       │   │   ├── phase2_additions.hpp
│       │   │   ├── phase2_asterisks.hpp
│       │   │   ├── phase2_everything.hpp
│       │   │   ├── phase2_functions.hpp
│       │   │   ├── phase2_references.hpp
│       │   │   ├── phase3_remove.hpp
│       │   │   ├── phase5_repack.hpp
│       │   │   ├── reference2.hpp
│       │   │   ├── reference2_action.hpp
│       │   │   ├── reference2_grammar.hpp
│       │   │   ├── reference2_kind.hpp
│       │   │   ├── reference2_part.hpp
│       │   │   ├── repack_traits.hpp
│       │   │   ├── state.hpp
│       │   │   ├── statistics.hpp
│       │   │   ├── string_utility.hpp
│       │   │   ├── system_utility.hpp
│       │   │   └── to_stream.hpp
│       │   ├── key.hpp
│       │   ├── key_kind.hpp
│       │   ├── key_part.hpp
│       │   ├── parser.hpp
│       │   ├── to_stream.hpp
│       │   ├── traits.hpp
│       │   └── value.hpp
│       └── config.hpp
├── src/
│   ├── example/
│   │   └── config/
│   │       ├── CMakeLists.txt
│   │       ├── dump_all_phases.cpp
│   │       ├── dump_only_data.cpp
│   │       ├── dump_phase_one.cpp
│   │       ├── dump_phase_three.cpp
│   │       ├── dump_phase_two.cpp
│   │       ├── dump_with_meta.cpp
│   │       └── try_catch.hpp
│   └── test/
│       └── config/
│           ├── CMakeLists.txt
│           ├── access.cpp
│           ├── assign.cpp
│           ├── custom.cpp
│           ├── debug_traits.cpp
│           ├── enumerations.cpp
│           ├── failure.cpp
│           ├── independence.cpp
│           ├── key.cpp
│           ├── key_part.cpp
│           ├── main.hpp
│           ├── multi_line_string_position.cpp
│           ├── parse_key.cpp
│           ├── parse_key1.cpp
│           ├── parse_reference2.cpp
│           ├── setenv.hpp
│           ├── success.cpp
│           ├── test.hpp
│           ├── to_stream.cpp
│           └── value.cpp
└── tests/
    ├── add_01.failure
    ├── add_02.failure
    ├── add_03.failure
    ├── add_04.failure
    ├── add_05.failure
    ├── add_06.failure
    ├── add_07.failure
    ├── add_08.failure
    ├── add_09.failure
    ├── add_10.failure
    ├── add_11.failure
    ├── add_12.failure
    ├── add_13.failure
    ├── add_14.failure
    ├── add_15.failure
    ├── add_16.failure
    ├── add_17.failure
    ├── add_18.failure
    ├── add_19.failure
    ├── add_20.failure
    ├── add_21.failure
    ├── add_22.failure
    ├── add_23.failure
    ├── add_24.failure
    ├── add_25.failure
    ├── add_26.failure
    ├── add_27.failure
    ├── add_28.failure
    ├── add_29.failure
    ├── add_30.failure
    ├── add_31.failure
    ├── add_32.failure
    ├── add_33.failure
    ├── add_34.failure
    ├── add_35.failure
    ├── add_36.failure
    ├── add_37.failure
    ├── add_38.failure
    ├── add_39.failure
    ├── add_40.failure
    ├── add_41.failure
    ├── add_42.failure
    ├── add_43.failure
    ├── add_44.failure
    ├── add_45.failure
    ├── add_46.failure
    ├── add_47.failure
    ├── add_48.failure
    ├── add_number.jaxn
    ├── add_number.success
    ├── add_string.jaxn
    ├── add_string.success
    ├── array_index_01.jaxn
    ├── array_index_01.success
    ├── array_index_02.jaxn
    ├── array_index_02.success
    ├── binary.jaxn
    ├── binary.success
    ├── braces.jaxn
    ├── braces.success
    ├── combo_01.jaxn
    ├── combo_01.success
    ├── combo_02.jaxn
    ├── combo_02.success
    ├── commas.jaxn
    ├── commas.success
    ├── comments.jaxn
    ├── comments.success
    ├── complex_01.failure
    ├── complex_02.failure
    ├── complex_03.failure
    ├── debug_traits.config
    ├── debug_traits.output
    ├── delete.jaxn
    ├── delete.success
    ├── doc_asterisk_01.jaxn
    ├── doc_asterisk_01.success
    ├── doc_default.jaxn
    ├── doc_default.success
    ├── doc_delete_01.jaxn
    ├── doc_delete_01.success
    ├── doc_delete_02.jaxn
    ├── doc_delete_02.success
    ├── doc_dotted_names.jaxn
    ├── doc_dotted_names.success
    ├── doc_include.inc
    ├── doc_include.jaxn
    ├── doc_include.success
    ├── doc_object_merge_01.jaxn
    ├── doc_object_merge_01.success
    ├── doc_references_01.jaxn
    ├── doc_references_01.success
    ├── doc_references_02.failure
    ├── doc_references_03.failure
    ├── doc_references_05.jaxn
    ├── doc_references_05.success
    ├── doc_references_06.jaxn
    ├── doc_references_06.success
    ├── doc_temporary.jaxn
    ├── doc_temporary.success
    ├── empty.jaxn
    ├── empty.success
    ├── env.failure
    ├── extensions.jaxn
    ├── extensions.success
    ├── formats.cbor
    ├── formats.jaxn
    ├── formats.json
    ├── formats.msgpack
    ├── formats.success
    ├── formats.txt
    ├── formats.ubjson
    ├── include.jaxn
    ├── include.success
    ├── jaxn.jaxn
    ├── jaxn.success
    ├── merge_number_01.jaxn
    ├── merge_number_01.success
    ├── merge_number_02.jaxn
    ├── merge_number_02.success
    ├── merge_number_03.jaxn
    ├── merge_number_03.success
    ├── merge_number_04.jaxn
    ├── merge_number_04.success
    ├── merge_number_05.jaxn
    ├── merge_number_05.success
    ├── merge_number_06.jaxn
    ├── merge_number_06.success
    ├── merge_number_07.jaxn
    ├── merge_number_07.success
    ├── merge_number_08.jaxn
    ├── merge_number_08.success
    ├── merge_string_01.jaxn
    ├── merge_string_01.success
    ├── merge_string_02.jaxn
    ├── merge_string_02.success
    ├── merge_string_03.jaxn
    ├── merge_string_03.success
    ├── merge_string_04.jaxn
    ├── merge_string_04.success
    ├── merge_string_05.jaxn
    ├── merge_string_05.success
    ├── merge_string_06.jaxn
    ├── merge_string_06.success
    ├── merge_string_07.jaxn
    ├── merge_string_07.success
    ├── merge_string_08.jaxn
    ├── merge_string_08.success
    ├── numbers.jaxn
    ├── numbers.success
    ├── quoted.jaxn
    ├── quoted.success
    ├── reference_01.failure
    ├── reference_01.jaxn
    ├── reference_01.success
    ├── reference_02.failure
    ├── reference_02.jaxn
    ├── reference_02.success
    ├── reference_03.failure
    ├── reference_03.jaxn
    ├── reference_03.success
    ├── reference_04.failure
    ├── reference_05.failure
    ├── reference_06.failure
    ├── reference_07.failure
    ├── reference_08.failure
    ├── reference_09.failure
    ├── reference_10.failure
    ├── reference_11.failure
    ├── reference_12.failure
    ├── regression_01.jaxn
    ├── regression_01.success
    ├── regression_02.jaxn
    ├── regression_02.success
    ├── regression_03.jaxn
    ├── regression_03.success
    ├── regression_04.jaxn
    ├── regression_04.success
    ├── regression_05.jaxn
    ├── regression_05.success
    ├── regression_06.jaxn
    ├── regression_06.success
    ├── regression_07.jaxn
    ├── regression_07.success
    ├── regression_08.jaxn
    ├── regression_08.success
    ├── regression_09.jaxn
    ├── regression_09.success
    ├── regression_10.jaxn
    ├── regression_10.success
    ├── regression_11.jaxn
    ├── regression_11.success
    ├── regression_12.jaxn
    ├── regression_12.success
    ├── regression_13.failure
    ├── scoping.jaxn
    ├── scoping.success
    ├── serialise.jaxn
    ├── serialise.success
    ├── shell.jaxn
    ├── shell.success
    ├── simple.jaxn
    ├── simple.success
    ├── space.jaxn
    ├── space.success
    ├── star_01.jaxn
    ├── star_01.success
    ├── star_02.jaxn
    ├── star_02.success
    ├── star_03.jaxn
    ├── star_03.success
    ├── string_01.failure
    ├── string_02.failure
    ├── temporary_01.jaxn
    ├── temporary_01.success
    ├── temporary_02.jaxn
    ├── temporary_02.success
    ├── temporary_03.jaxn
    ├── temporary_03.success
    ├── temporary_04.jaxn
    ├── temporary_04.success
    ├── temporary_05.jaxn
    ├── temporary_05.success
    ├── unready.jaxn
    └── unready.success
Download .txt
SYMBOL INDEX (712 symbols across 93 files)

FILE: include/tao/config/access.hpp
  type tao::config (line 16) | namespace tao::config

FILE: include/tao/config/annotation.hpp
  type tao::config (line 16) | namespace tao::config
    type annotation (line 18) | struct annotation
      method annotation (line 23) | annotation() = default;
      method annotation (line 25) | annotation( annotation&& ) = default;
      method annotation (line 26) | annotation& operator=( annotation&& ) = default;
      method annotation (line 28) | annotation( const annotation& ) = default;
      method annotation (line 29) | annotation& operator=( const annotation& ) = default;
      method set_key (line 31) | void set_key( config::key k ) noexcept
      method set_position (line 36) | void set_position( json::position p ) noexcept
      method set_position (line 41) | void set_position( const pegtl::position& pos )
      method append_message_extension (line 46) | void append_message_extension( std::ostream& o ) const

FILE: include/tao/config/assign.hpp
  type tao::config (line 16) | namespace tao::config

FILE: include/tao/config/contrib/rot13.hpp
  type tao::config (line 12) | namespace tao::config
    function rot13 (line 14) | [[nodiscard]] inline internal::string_t rot13( const pegtl::position& ...

FILE: include/tao/config/from_file.hpp
  type tao::config (line 13) | namespace tao::config
    function basic_from_file (line 16) | [[nodiscard]] json::basic_value< Traits > basic_from_file( const std::...
    function value (line 23) | [[nodiscard]] inline value from_file( const std::filesystem::path& path )

FILE: include/tao/config/from_files.hpp
  type tao::config (line 14) | namespace tao::config
    function basic_from_files (line 17) | [[nodiscard]] json::basic_value< Traits > basic_from_files( const std:...
    function value (line 26) | [[nodiscard]] inline value from_files( const std::vector< std::filesys...

FILE: include/tao/config/from_input.hpp
  type tao::config (line 13) | namespace tao::config
    function basic_from_input (line 16) | [[nodiscard]] json::basic_value< Traits > basic_from_input( pegtl_inpu...
    function value (line 23) | [[nodiscard]] inline value from_input( pegtl_input_t&& in )

FILE: include/tao/config/from_string.hpp
  type tao::config (line 14) | namespace tao::config
    function basic_from_string (line 17) | [[nodiscard]] json::basic_value< Traits > basic_from_string( const cha...
    function basic_from_string (line 25) | [[nodiscard]] json::basic_value< Traits > basic_from_string( const std...
    function value (line 30) | [[nodiscard]] inline value from_string( const char* data, const std::s...
    function value (line 35) | [[nodiscard]] inline value from_string( const std::string_view data, c...

FILE: include/tao/config/internal/array.hpp
  type tao::config::internal (line 13) | namespace tao::config::internal
    type basic_array (line 16) | struct basic_array
      method basic_array (line 20) | basic_array() = delete;
      method basic_array (line 22) | explicit basic_array( const pegtl::position& p )
      method basic_array (line 26) | explicit basic_array( const std::string& f, const pegtl::position& p )
      method basic_array (line 31) | basic_array( basic_array&& ) = default;
      method basic_array (line 32) | basic_array( const basic_array& ) = default;
      method basic_array (line 36) | basic_array& operator=( basic_array&& ) = default;
      method basic_array (line 37) | basic_array& operator=( const basic_array& ) = default;

FILE: include/tao/config/internal/atom.hpp
  type tao::config::internal (line 14) | namespace tao::config::internal
    type null (line 16) | struct null
      method null (line 18) | explicit null( const pegtl::position& pos )
    type atom (line 31) | struct atom
      method atom (line 34) | atom( V&& v, const pegtl::position& pos )

FILE: include/tao/config/internal/change_action_and_states.hpp
  type tao::config::internal (line 15) | namespace tao::config::internal
    type change_action_and_states (line 18) | struct change_action_and_states
      method match (line 31) | [[nodiscard]] static bool match( std::index_sequence< Ns... > /*unus...
      method match (line 53) | [[nodiscard]] static bool match( ParseInput& in, States&&... st )

FILE: include/tao/config/internal/concat.hpp
  type tao::config::internal (line 22) | namespace tao::config::internal
    type basic_concat (line 25) | struct basic_concat
      method basic_concat (line 30) | basic_concat() = delete;
      method basic_concat (line 32) | explicit basic_concat( const pegtl::position& p )
      method basic_concat (line 36) | basic_concat( basic_concat&& ) = default;
      method basic_concat (line 37) | basic_concat( const basic_concat& ) = default;
      method basic_concat (line 41) | basic_concat& operator=( basic_concat&& ) = default;
      method basic_concat (line 42) | basic_concat& operator=( const basic_concat& ) = default;
      method omit_from_final_result (line 44) | [[nodiscard]] bool omit_from_final_result() const noexcept
      method back_ensure_init (line 50) | void back_ensure_init( const T k, const pegtl::position& p )
      method back_emplace_func (line 60) | void back_emplace_func( const std::string& name, const pegtl::positi...

FILE: include/tao/config/internal/config_action.hpp
  type tao::config::internal (line 27) | namespace tao::config::internal
    type config_action (line 30) | struct config_action
    type config_action< rules::assign_head > (line 35) | struct config_action< rules::assign_head >
      method apply0 (line 38) | static void apply0( State& st, const function_map& /*unused*/ )
    type config_action< json::jaxn::internal::rules::begin_array > (line 46) | struct config_action< json::jaxn::internal::rules::begin_array >
      method apply (line 49) | static void apply( Input& in, State& st, const function_map& /*unuse...
    type config_action< json::jaxn::internal::rules::begin_object > (line 58) | struct config_action< json::jaxn::internal::rules::begin_object >
      method apply (line 61) | static void apply( Input& in, State& st, const function_map& /*unuse...
    type config_action< rules::function_name > (line 70) | struct config_action< rules::function_name >
      method apply (line 73) | static void apply( Input& in, State& st, const function_map& /*unuse...
    type config_action< rules::value_list > (line 83) | struct config_action< rules::value_list >
      method apply0 (line 86) | static void apply0( State& st, const function_map& /*unused*/ )
    type config_action< rules::element_list > (line 95) | struct config_action< rules::element_list >
    type config_action< rules::extension_list > (line 100) | struct config_action< rules::extension_list >
    type config_action< rules::key1_rule > (line 105) | struct config_action< rules::key1_rule >
      method success (line 109) | static void success( const Input& /*unused*/, std::vector< key1_part...
    type config_action< rules::temporary_extension > (line 117) | struct config_action< rules::temporary_extension >
      method apply0 (line 120) | static void apply0( State& st, const function_map& /*unused*/ )
    type config_action< rules::permanent_extension > (line 130) | struct config_action< rules::permanent_extension >
      method apply0 (line 133) | static void apply0( State& st, const function_map& /*unused*/ )
    type config_action< rules::include > (line 143) | struct config_action< rules::include >
      method apply0 (line 146) | static void apply0( State& st, const function_map& /*unused*/ )
    type config_action< rules::inc_if > (line 153) | struct config_action< rules::inc_if >
      method apply0 (line 156) | static void apply0( State& st, const function_map& /*unused*/ )
    type config_action< rules::inc_fn > (line 163) | struct config_action< rules::inc_fn >
      method apply (line 166) | static void apply( const Input& ai, State& st, const function_map& fm )

FILE: include/tao/config/internal/config_grammar.hpp
  type tao::config::internal::rules (line 18) | namespace tao::config::internal::rules
    type jaxn_value (line 20) | struct jaxn_value
      method match (line 32) | [[nodiscard]] static bool match( pegtl_input_t& in, State& st, const...
    type reference_value (line 43) | struct reference_value
      method match (line 55) | [[nodiscard]] static bool match( pegtl_input_t& in, State& st, const...
    type array (line 64) | struct array
    type object (line 65) | struct object
    type extension_list (line 67) | struct extension_list
    type remove (line 70) | struct remove : pegtl::keyword< 'd', 'e', 'l', 'e', 't', 'e' > {}
    type function_name (line 72) | struct function_name : pegtl::seq< ident, pegtl::opt< pegtl::one< '?' ...
    type extension_value (line 73) | struct extension_value : pegtl::seq< function_name, wsp, extension_lis...
    type bracketed_value (line 74) | struct bracketed_value : pegtl::if_must< pegtl::one< '(' >, wss, pegtl...
    type value_part (line 76) | struct value_part : pegtl::sor< array, object, bracketed_value, jaxn_v...
    type value_list (line 77) | struct value_list : pegtl::list< value_part, pegtl::one< '+' >, jaxn::...
    type assign_head (line 79) | struct assign_head : pegtl::one< ':', '=' > {}
    type assign_member (line 80) | struct assign_member : pegtl::if_must< assign_head, wss, pegtl::sor< r...
    type append_head (line 82) | struct append_head : pegtl::sor< pegtl::string< '+', '=' >, pegtl::at<...
    type append_member (line 83) | struct append_member : pegtl::if_must< append_head, wss, value_list > {}
    type key_member (line 85) | struct key_member : pegtl::sor< assign_member, append_member > {}
    type member_key (line 87) | struct member_key
      method match (line 99) | [[nodiscard]] static bool match( pegtl_input_t& in, State& st, const...
    type inc_if (line 106) | struct inc_if : pegtl::one< '?' > {}
    type opt_if (line 107) | struct opt_if : pegtl::opt< inc_if > {}
    type inc_fn (line 108) | struct inc_fn : pegtl::plus< pegtl::not_one< '"' > > {}
    type include (line 110) | struct include : pegtl::string< 'i', 'n', 'c', 'l', 'u', 'd', 'e' > {}
    type permanent (line 111) | struct permanent : pegtl::string< 'p', 'e', 'r', 'm', 'a', 'n', 'e', '...
    type temporary (line 112) | struct temporary : pegtl::string< 't', 'e', 'm', 'p', 'o', 'r', 'a', '...
    type filename (line 114) | struct filename : pegtl::seq< pegtl::one< '"' >, inc_fn, pegtl::one< '...
    type include_extension (line 116) | struct include_extension : pegtl::if_must< include, opt_if, wsp, filen...
    type permanent_extension (line 117) | struct permanent_extension : pegtl::if_must< permanent, wsp, key1_rule...
    type temporary_extension (line 118) | struct temporary_extension : pegtl::if_must< temporary, wsp, key1_rule...
    type extension_member (line 120) | struct extension_member : pegtl::if_must< pegtl::one< '(' >, wss, pegt...
    type member (line 122) | struct member : pegtl::sor< extension_member, member_key > {}
    type opt_comma (line 124) | struct opt_comma : pegtl::opt< pegtl::one< ',' >, wss > {}
    type member_list_impl (line 126) | struct member_list_impl : pegtl::until< U, member, wss, opt_comma > {}
    type element_list_impl (line 127) | struct element_list_impl : pegtl::until< U, value_list, wss, opt_comma...
    type element_list (line 129) | struct element_list : element_list_impl< jaxn::end_array > {}
    type extension_list (line 130) | struct extension_list : element_list_impl< pegtl::one< ')' > > {}
    type array (line 131) | struct array : pegtl::if_must< jaxn::begin_array, element_list > {}
    type member_list (line 132) | struct member_list : member_list_impl< jaxn::end_object > {}
    type object (line 133) | struct object : pegtl::if_must< jaxn::begin_object, member_list > {}
    type compat_file (line 134) | struct compat_file : pegtl::must< member_list, wss, pegtl::eof > {}
    type config_list (line 135) | struct config_list : member_list_impl< pegtl::eof > {}
    type begin_compat (line 136) | struct begin_compat : pegtl::disable< jaxn::begin_object > {}
    type config_file (line 137) | struct config_file : pegtl::must< wss, pegtl::if_must_else< begin_comp...
    type value (line 138) | struct value : pegtl::must< wss, value_part, wss, pegtl::eof > {}

FILE: include/tao/config/internal/config_parser.hpp
  type tao::config::internal (line 25) | namespace tao::config::internal
    type config_parser (line 27) | struct config_parser
      method config_parser (line 29) | config_parser()
      method config_parser (line 42) | config_parser( config_parser&& ) = delete;
      method config_parser (line 43) | config_parser( const config_parser& ) = delete;
      method parse (line 51) | void parse( pegtl_input_t&& in )
      method parse (line 56) | void parse( const std::filesystem::path& path )
      method parse (line 61) | void parse( const char* data, const std::size_t size, const std::str...
      method parse (line 66) | void parse( const std::string_view data, const std::string& source )
      method finish (line 72) | [[nodiscard]] json::basic_value< Traits > finish()

FILE: include/tao/config/internal/constants.hpp
  type tao::config::internal (line 9) | namespace tao::config::internal
    type part_asterisk_t (line 11) | struct part_asterisk_t
      method part_asterisk_t (line 13) | explicit constexpr part_asterisk_t( int /*unused*/ ) {}
    type part_vector_t (line 16) | struct part_vector_t
      method part_vector_t (line 18) | explicit constexpr part_vector_t( int /*unused*/ ) {}
    type array_init_t (line 29) | struct array_init_t
      method array_init_t (line 31) | explicit constexpr array_init_t( int /*unused*/ ) {}
    type object_init_t (line 36) | struct object_init_t
      method object_init_t (line 38) | explicit constexpr object_init_t( int /*unused*/ ) {}
    type asterisk_init_t (line 43) | struct asterisk_init_t
      method asterisk_init_t (line 45) | explicit constexpr asterisk_init_t( int /*unused*/ ) {}

FILE: include/tao/config/internal/debug_traits.hpp
  type tao::config::internal (line 25) | namespace tao::config::internal
    type debug_traits (line 28) | struct debug_traits
    type debug_traits< void > (line 33) | struct debug_traits< void >
    type debug_traits< key_kind > (line 38) | struct debug_traits< key_kind >
      method produce (line 43) | static void produce( Consumer& c, const key_kind k )
    type debug_traits< key_part > (line 58) | struct debug_traits< key_part >
      method produce (line 63) | static void produce( Consumer& c, const key_part& p )
    type debug_traits< key > (line 77) | struct debug_traits< key >
    type debug_traits< annotation > (line 84) | struct debug_traits< annotation >
    type debug_traits< json::position > (line 92) | struct debug_traits< json::position >
      method produce (line 97) | static void produce( Consumer& c, const json::position& p )
    type debug_traits< pegtl::position > (line 104) | struct debug_traits< pegtl::position >
      method produce (line 109) | static void produce( Consumer& c, const pegtl::position& p )
    type debug_traits< part_asterisk_t > (line 116) | struct debug_traits< part_asterisk_t >
      method produce (line 119) | static void produce( Consumer& c, const part_asterisk_t /*unused*/ )
    type debug_traits< key1_kind > (line 126) | struct debug_traits< key1_kind >
      method produce (line 131) | static void produce( Consumer& c, const key1_kind k )
    type debug_traits< key1_part > (line 152) | struct debug_traits< key1_part >
      method produce (line 157) | static void produce( Consumer& c, const key1_part& p )
    type debug_traits< key1 > (line 174) | struct debug_traits< key1 >
    type debug_traits< reference2_kind > (line 181) | struct debug_traits< reference2_kind >
      method produce (line 186) | static void produce( Consumer& c, const reference2_kind k )
    type debug_traits< reference2_part > (line 204) | struct debug_traits< reference2_part >
      method produce (line 209) | static void produce( Consumer& c, const reference2_part& p )
    type debug_traits< reference2 > (line 226) | struct debug_traits< reference2 >
    type debug_traits< entry_kind > (line 233) | struct debug_traits< entry_kind >
      method produce (line 238) | static void produce( Consumer& c, const entry_kind k )
    type debug_traits< entry > (line 280) | struct debug_traits< entry >
      method produce (line 283) | static void produce( Consumer& c, const entry& v )
    type debug_traits< concat > (line 340) | struct debug_traits< concat >
    type debug_traits< array > (line 349) | struct debug_traits< array >
    type debug_traits< object > (line 356) | struct debug_traits< object >
    type debug_traits< const T* > (line 362) | struct debug_traits< const T* >
      method assign (line 365) | static void assign( json::basic_value< Traits >& v, const T* p )
    type debug_traits< T* > (line 372) | struct debug_traits< T* >

FILE: include/tao/config/internal/entry.hpp
  type tao::config::internal (line 24) | namespace tao::config::internal
    type entry (line 26) | struct entry
      method entry (line 30) | explicit entry( const null& n )
      method entry (line 34) | explicit entry( const boolean& b )
      method entry (line 38) | explicit entry( const string_t& s )
      method entry (line 42) | explicit entry( const binary_t& b )
      method entry (line 46) | explicit entry( const signed_t& s )
      method entry (line 50) | explicit entry( const unsigned_t& u )
      method entry (line 54) | explicit entry( const double_t& d )
      method entry (line 58) | explicit entry( const reference2& r )
      method entry (line 64) | entry( const std::string& n, const pegtl::position& p )
      method entry (line 68) | entry( const array_init_t /*unused*/, const pegtl::position& p )
      method entry (line 72) | entry( const object_init_t /*unused*/, const pegtl::position& p )
      method entry (line 76) | entry( const asterisk_init_t /*unused*/, const pegtl::position& p )
      method entry (line 80) | entry( entry&& ) noexcept = default;
      method entry (line 81) | entry( const entry& ) = default;
      method entry (line 85) | entry& operator=( entry&& ) noexcept = default;
      method entry (line 86) | entry& operator=( const entry& ) = default;
      method entry_kind (line 88) | [[nodiscard]] entry_kind kind() const noexcept
      method is_null (line 93) | [[nodiscard]] bool is_null() const noexcept
      method is_string (line 98) | [[nodiscard]] bool is_string() const noexcept
      method is_binary (line 103) | [[nodiscard]] bool is_binary() const noexcept
      method is_array (line 108) | [[nodiscard]] bool is_array() const noexcept
      method is_object (line 113) | [[nodiscard]] bool is_object() const noexcept
      method is_asterisk (line 118) | [[nodiscard]] bool is_asterisk() const noexcept
      method is_reference (line 123) | [[nodiscard]] bool is_reference() const noexcept
      method set_value (line 129) | void set_value( atom< T >&& t )
      method set_array (line 134) | void set_array( pegtl::position p )
      method set_object (line 139) | void set_object( pegtl::position p )
      method get_boolean (line 144) | [[nodiscard]] bool get_boolean() const noexcept
      method boolean (line 149) | [[nodiscard]] boolean& get_boolean_atom() noexcept
      method boolean (line 154) | [[nodiscard]] const boolean& get_boolean_atom() const noexcept
      method string_t (line 169) | [[nodiscard]] string_t& get_string_atom() noexcept
      method string_t (line 174) | [[nodiscard]] const string_t& get_string_atom() const noexcept
      method binary_t (line 189) | [[nodiscard]] binary_t& get_binary_atom() noexcept
      method binary_t (line 194) | [[nodiscard]] const binary_t& get_binary_atom() const noexcept
      method get_signed (line 199) | [[nodiscard]] std::int64_t get_signed() const noexcept
      method signed_t (line 204) | [[nodiscard]] signed_t& get_signed_atom() noexcept
      method signed_t (line 209) | [[nodiscard]] const signed_t& get_signed_atom() const noexcept
      method get_unsigned (line 214) | [[nodiscard]] std::uint64_t get_unsigned() const noexcept
      method unsigned_t (line 219) | [[nodiscard]] unsigned_t& get_unsigned_atom() noexcept
      method unsigned_t (line 224) | [[nodiscard]] const unsigned_t& get_unsigned_atom() const noexcept
      method get_double (line 229) | [[nodiscard]] double get_double() const noexcept
      method double_t (line 234) | [[nodiscard]] double_t& get_double_atom() noexcept
      method double_t (line 239) | [[nodiscard]] const double_t& get_double_atom() const noexcept
      method array (line 244) | [[nodiscard]] array& get_array() noexcept
      method array (line 249) | [[nodiscard]] const array& get_array() const noexcept
      method object (line 254) | [[nodiscard]] object& get_object() noexcept
      method object (line 259) | [[nodiscard]] const object& get_object() const noexcept
      method concat (line 264) | [[nodiscard]] concat& get_asterisk() noexcept
      method concat (line 269) | [[nodiscard]] const concat& get_asterisk() const noexcept
      method reference2 (line 274) | [[nodiscard]] reference2& get_reference() noexcept
      method reference2 (line 279) | [[nodiscard]] const reference2& get_reference() const noexcept

FILE: include/tao/config/internal/entry_kind.hpp
  type tao::config::internal (line 12) | namespace tao::config::internal
    type entry_kind (line 14) | enum class entry_kind : char
    function to_string (line 29) | [[nodiscard]] constexpr std::string_view to_string( const entry_kind k...

FILE: include/tao/config/internal/events_from_value.hpp
  type tao::config::internal (line 10) | namespace tao::config::internal
    function events_from_value (line 13) | void events_from_value( Consumer& c, const json::basic_value< Traits >...

FILE: include/tao/config/internal/forward.hpp
  type tao::config::internal (line 11) | namespace tao::config::internal
    type entry (line 13) | struct entry
    type state (line 14) | struct state
    type basic_concat (line 17) | struct basic_concat
    type basic_array (line 22) | struct basic_array
    type basic_object (line 24) | struct basic_object
    type function_traits (line 30) | struct function_traits

FILE: include/tao/config/internal/function_implementations.hpp
  type tao::config::internal (line 24) | namespace tao::config::internal
    function binary_t (line 26) | [[nodiscard]] inline binary_t binary_function( const pegtl::position& ...
    function default_function (line 32) | [[nodiscard]] inline bool default_function( entry& e )
    function string_t (line 74) | [[nodiscard]] inline string_t env_function( const pegtl::position& p, ...
    function string_t (line 79) | [[nodiscard]] inline string_t env_if_function( const pegtl::position& ...
    function entry (line 85) | [[nodiscard]] inline entry jaxn_function( const pegtl::position& /*unu...
    function binary_t (line 93) | [[nodiscard]] inline binary_t read_function( const pegtl::position& p,...
    function print_function (line 100) | [[nodiscard]] inline bool print_function( entry& e )
    function string_t (line 117) | [[nodiscard]] inline string_t shell_function( const pegtl::position& p...
    type split_star_ws (line 127) | struct split_star_ws : pegtl::star< pegtl::space > {}
    type split_string (line 128) | struct split_string : pegtl::plus< pegtl::invert< pegtl::space > > {}
    type split_rule (line 129) | struct split_rule : pegtl::must< split_star_ws, pegtl::star< split_str...
    type split_action (line 133) | struct split_action
    type split_action< split_string > (line 138) | struct split_action< split_string >
      method apply (line 141) | static void apply( const Input& in, entry& result, const pegtl::posi...
    function entry (line 148) | [[nodiscard]] inline entry split_function( const pegtl::position& p, c...
    function string_t (line 156) | [[nodiscard]] inline string_t string_function( const pegtl::position& ...

FILE: include/tao/config/internal/function_traits.hpp
  type tao::config::internal (line 22) | namespace tao::config::internal
    type arguments_unready (line 24) | struct arguments_unready
    type function_traits (line 28) | struct function_traits
    type function_traits< entry > (line 31) | struct function_traits< entry >
      method put (line 33) | static void put( entry& e, entry&& f )
      method put (line 38) | static void put( entry& e, const entry& f )
    type function_traits< atom< T > > (line 45) | struct function_traits< atom< T > >
      method put (line 47) | static void put( entry& e, atom< T >&& v )
      method put (line 52) | static void put( entry& e, const atom< T >& v )
    function entry (line 58) | [[nodiscard]] inline const entry& function_traits_entry( array& f, con...
    type function_traits< std::string > (line 74) | struct function_traits< std::string >
      method get (line 76) | [[nodiscard]] static std::string get( array& f, const std::size_t i )

FILE: include/tao/config/internal/function_wrapper.hpp
  type tao::config::internal (line 16) | namespace tao::config::internal
    function function (line 18) | [[nodiscard]] inline function wrap( bool ( *x )( entry& e ) )
    function function (line 31) | [[nodiscard]] function wrap( R ( *x )( const pegtl::position&, A ) )
    function function (line 50) | [[nodiscard]] function wrap( R ( *x )( const pegtl::position&, A, B ) )

FILE: include/tao/config/internal/jaxn_action.hpp
  type tao::config::internal (line 18) | namespace tao::config::internal
    type jaxn_action (line 21) | struct jaxn_action
    type jaxn_action< json::jaxn::internal::rules::kw_null > (line 26) | struct jaxn_action< json::jaxn::internal::rules::kw_null >
      method apply (line 29) | static void apply( const Input& in, Consumer& consumer )
    type jaxn_action< json::jaxn::internal::rules::kw_true > (line 36) | struct jaxn_action< json::jaxn::internal::rules::kw_true >
      method apply (line 39) | static void apply( const Input& in, Consumer& consumer )
    type jaxn_action< json::jaxn::internal::rules::kw_false > (line 46) | struct jaxn_action< json::jaxn::internal::rules::kw_false >
      method apply (line 49) | static void apply( const Input& in, Consumer& consumer )
    type jaxn_action< json::jaxn::internal::rules::identifier > (line 56) | struct jaxn_action< json::jaxn::internal::rules::identifier >
      method apply (line 59) | static void apply( const Input& in, Consumer& consumer )
    type jaxn_action< json::jaxn::internal::rules::hexnum< NEG > > (line 66) | struct jaxn_action< json::jaxn::internal::rules::hexnum< NEG > >
      method apply (line 69) | static void apply( const Input& in, Consumer& consumer )
    type jaxn_action< json::jaxn::internal::rules::array::begin > (line 97) | struct jaxn_action< json::jaxn::internal::rules::array::begin >
      method apply (line 100) | static void apply( const Input& in, Consumer& consumer )
    type jaxn_action< json::jaxn::internal::rules::array::element > (line 107) | struct jaxn_action< json::jaxn::internal::rules::array::element >
      method apply (line 110) | static void apply( const Input& in, Consumer& consumer )
    type jaxn_action< json::jaxn::internal::rules::array::end > (line 117) | struct jaxn_action< json::jaxn::internal::rules::array::end >
      method apply (line 120) | static void apply( const Input& in, Consumer& consumer )
    type jaxn_action< json::jaxn::internal::rules::object::begin > (line 127) | struct jaxn_action< json::jaxn::internal::rules::object::begin >
      method apply (line 130) | static void apply( const Input& in, Consumer& consumer )
    type jaxn_action< json::jaxn::internal::rules::object::element > (line 137) | struct jaxn_action< json::jaxn::internal::rules::object::element >
      method apply (line 140) | static void apply( const Input& in, Consumer& consumer )
    type jaxn_action< json::jaxn::internal::rules::object::end > (line 147) | struct jaxn_action< json::jaxn::internal::rules::object::end >
      method apply (line 150) | static void apply( const Input& in, Consumer& consumer )
    type jaxn_action< json::jaxn::internal::rules::zero< false > > (line 157) | struct jaxn_action< json::jaxn::internal::rules::zero< false > >
      method apply (line 160) | static void apply( const Input& in, Consumer& consumer )
    type jaxn_action< json::jaxn::internal::rules::zero< true > > (line 167) | struct jaxn_action< json::jaxn::internal::rules::zero< true > >
      method apply (line 170) | static void apply( const Input& in, Consumer& consumer )
    type jaxn_action< json::jaxn::internal::rules::kw_nan > (line 177) | struct jaxn_action< json::jaxn::internal::rules::kw_nan >
      method apply (line 180) | static void apply( const Input& in, Consumer& consumer )
    type jaxn_action< json::jaxn::internal::rules::kw_infinity< false > > (line 187) | struct jaxn_action< json::jaxn::internal::rules::kw_infinity< false > >
      method apply (line 190) | static void apply( const Input& in, Consumer& consumer )
    type jaxn_action< json::jaxn::internal::rules::kw_infinity< true > > (line 197) | struct jaxn_action< json::jaxn::internal::rules::kw_infinity< true > >
      method apply (line 200) | static void apply( const Input& in, Consumer& consumer )
    type jaxn_action< json::jaxn::internal::rules::esign > (line 207) | struct jaxn_action< json::jaxn::internal::rules::esign >
      method apply (line 210) | static void apply( const Input& in, json::internal::number_state< NE...
    type jaxn_action< json::jaxn::internal::rules::idigits > (line 217) | struct jaxn_action< json::jaxn::internal::rules::idigits >
      method apply (line 220) | static void apply( const Input& in, json::internal::number_state< NE...
    type jaxn_action< json::jaxn::internal::rules::fdigits > (line 247) | struct jaxn_action< json::jaxn::internal::rules::fdigits >
      method apply (line 250) | static void apply( const Input& in, json::internal::number_state< NE...
    type jaxn_action< json::jaxn::internal::rules::edigits > (line 281) | struct jaxn_action< json::jaxn::internal::rules::edigits >
      method apply (line 284) | static void apply( const Input& in, json::internal::number_state< NE...
    type jaxn_action< json::jaxn::internal::rules::number< NEG > > (line 307) | struct jaxn_action< json::jaxn::internal::rules::number< NEG > >
      method success (line 311) | static void success( const Input& in, json::internal::number_state< ...
    type jaxn_action< json::jaxn::internal::rules::single_string > (line 318) | struct jaxn_action< json::jaxn::internal::rules::single_string >
      method success (line 322) | static void success( const pegtl::position& pos, std::string& unesca...
    type jaxn_action< json::jaxn::internal::rules::string > (line 329) | struct jaxn_action< json::jaxn::internal::rules::string >
      method success (line 333) | static void success( const pegtl::position& pos, std::string& unesca...
    type jaxn_action< json::jaxn::internal::rules::key > (line 340) | struct jaxn_action< json::jaxn::internal::rules::key >
      method success (line 344) | static void success( const pegtl::position& pos, std::string& unesca...
    type jaxn_action< json::jaxn::internal::rules::single_binary > (line 351) | struct jaxn_action< json::jaxn::internal::rules::single_binary >
      method success (line 355) | static void success( const pegtl::position& pos, std::vector< std::b...
    type jaxn_action< json::jaxn::internal::rules::binary > (line 362) | struct jaxn_action< json::jaxn::internal::rules::binary >
      method success (line 366) | static void success( const pegtl::position& pos, std::vector< std::b...

FILE: include/tao/config/internal/jaxn_to_entry.hpp
  type tao::config::internal (line 23) | namespace tao::config::internal
    type jaxn_to_entry (line 25) | struct jaxn_to_entry
      method jaxn_to_entry (line 27) | jaxn_to_entry() noexcept = default;
      method null (line 33) | void null( const pegtl::position& p )
      method boolean (line 38) | void boolean( const bool v, const pegtl::position& p )
      method number (line 43) | void number( const std::int64_t v, const pegtl::position& p )
      method number (line 48) | void number( const std::uint64_t v, const pegtl::position& p )
      method number (line 53) | void number( const double v, const pegtl::position& p )
      method string (line 58) | void string( const std::string_view v, const pegtl::position& p )
      method string (line 63) | void string( const char* v, const pegtl::position& p )
      method string (line 68) | void string( std::string&& v, const pegtl::position& p )
      method binary (line 73) | void binary( const tao::binary_view v, const pegtl::position& p )
      method binary (line 78) | void binary( std::vector< std::byte >&& v, const pegtl::position& p )
      method begin_array (line 83) | void begin_array( const pegtl::position& p )
      method begin_array (line 88) | void begin_array( const std::size_t /*unused*/, const pegtl::positio...
      method element (line 93) | void element( const pegtl::position& p )
      method end_array (line 100) | void end_array( const pegtl::position& /*unused*/ )
      method end_array (line 106) | void end_array( const std::size_t /*unused*/, const pegtl::position&...
      method begin_object (line 111) | void begin_object( const pegtl::position& p )
      method begin_object (line 116) | void begin_object( const std::size_t /*unused*/, const pegtl::positi...
      method key (line 121) | void key( const std::string_view v, const pegtl::position& /*unused*/ )
      method key (line 126) | void key( const char* v, const pegtl::position& /*unused*/ )
      method key (line 131) | void key( std::string&& v, const pegtl::position& /*unused*/ )
      method member (line 136) | void member( const pegtl::position& p )
      method end_object (line 145) | void end_object( const pegtl::position& /*unused*/ )
      method end_object (line 151) | void end_object( const std::size_t /*unused*/, const pegtl::position...

FILE: include/tao/config/internal/json.hpp
  type tao::config::internal::rules (line 14) | namespace tao::config::internal::rules
    type wss (line 18) | struct wss
    type wsp (line 22) | struct wsp

FILE: include/tao/config/internal/key1.hpp
  type tao::config::internal (line 16) | namespace tao::config::internal
    type key1 (line 18) | struct key1
      method key1 (line 21) | key1() = default;
      method key1 (line 23) | key1( key1&& ) = default;
      method key1 (line 24) | key1& operator=( key1&& ) = default;
      method key1 (line 28) | key1( const key1& ) = default;
      method key1 (line 29) | key1& operator=( const key1& ) = default;
      method key1 (line 31) | explicit key1( const std::string& s )
      method key1 (line 36) | key1( const std::initializer_list< key1_part >& l )
      method key1 (line 40) | key1( const std::vector< key1_part >::const_iterator& begin, const s...
      method key1 (line 44) | key1& operator=( const std::string& s )
      method key1 (line 51) | key1& operator=( const std::initializer_list< key1_part >& l )
      method assign (line 67) | void assign( const std::string& s )
    function key1 (line 75) | inline key1 pop_front( const key1& p )
      method key1 (line 21) | key1() = default;
      method key1 (line 23) | key1( key1&& ) = default;
      method key1 (line 24) | key1& operator=( key1&& ) = default;
      method key1 (line 28) | key1( const key1& ) = default;
      method key1 (line 29) | key1& operator=( const key1& ) = default;
      method key1 (line 31) | explicit key1( const std::string& s )
      method key1 (line 36) | key1( const std::initializer_list< key1_part >& l )
      method key1 (line 40) | key1( const std::vector< key1_part >::const_iterator& begin, const s...
      method key1 (line 44) | key1& operator=( const std::string& s )
      method key1 (line 51) | key1& operator=( const std::initializer_list< key1_part >& l )
      method assign (line 67) | void assign( const std::string& s )
    function key1 (line 82) | inline key1 pop_back( const key1& p )
      method key1 (line 21) | key1() = default;
      method key1 (line 23) | key1( key1&& ) = default;
      method key1 (line 24) | key1& operator=( key1&& ) = default;
      method key1 (line 28) | key1( const key1& ) = default;
      method key1 (line 29) | key1& operator=( const key1& ) = default;
      method key1 (line 31) | explicit key1( const std::string& s )
      method key1 (line 36) | key1( const std::initializer_list< key1_part >& l )
      method key1 (line 40) | key1( const std::vector< key1_part >::const_iterator& begin, const s...
      method key1 (line 44) | key1& operator=( const std::string& s )
      method key1 (line 51) | key1& operator=( const std::initializer_list< key1_part >& l )
      method assign (line 67) | void assign( const std::string& s )
    function key1 (line 89) | inline key1& operator+=( key1& l, const key1& r )
      method key1 (line 21) | key1() = default;
      method key1 (line 23) | key1( key1&& ) = default;
      method key1 (line 24) | key1& operator=( key1&& ) = default;
      method key1 (line 28) | key1( const key1& ) = default;
      method key1 (line 29) | key1& operator=( const key1& ) = default;
      method key1 (line 31) | explicit key1( const std::string& s )
      method key1 (line 36) | key1( const std::initializer_list< key1_part >& l )
      method key1 (line 40) | key1( const std::vector< key1_part >::const_iterator& begin, const s...
      method key1 (line 44) | key1& operator=( const std::string& s )
      method key1 (line 51) | key1& operator=( const std::initializer_list< key1_part >& l )
      method assign (line 67) | void assign( const std::string& s )
    function key1 (line 95) | inline key1& operator+=( key1& l, const key1_part& p )
      method key1 (line 21) | key1() = default;
      method key1 (line 23) | key1( key1&& ) = default;
      method key1 (line 24) | key1& operator=( key1&& ) = default;
      method key1 (line 28) | key1( const key1& ) = default;
      method key1 (line 29) | key1& operator=( const key1& ) = default;
      method key1 (line 31) | explicit key1( const std::string& s )
      method key1 (line 36) | key1( const std::initializer_list< key1_part >& l )
      method key1 (line 40) | key1( const std::vector< key1_part >::const_iterator& begin, const s...
      method key1 (line 44) | key1& operator=( const std::string& s )
      method key1 (line 51) | key1& operator=( const std::initializer_list< key1_part >& l )
      method assign (line 67) | void assign( const std::string& s )
    function key1 (line 101) | [[nodiscard]] inline key1 operator+( const key1& l, const key1& r )
      method key1 (line 21) | key1() = default;
      method key1 (line 23) | key1( key1&& ) = default;
      method key1 (line 24) | key1& operator=( key1&& ) = default;
      method key1 (line 28) | key1( const key1& ) = default;
      method key1 (line 29) | key1& operator=( const key1& ) = default;
      method key1 (line 31) | explicit key1( const std::string& s )
      method key1 (line 36) | key1( const std::initializer_list< key1_part >& l )
      method key1 (line 40) | key1( const std::vector< key1_part >::const_iterator& begin, const s...
      method key1 (line 44) | key1& operator=( const std::string& s )
      method key1 (line 51) | key1& operator=( const std::initializer_list< key1_part >& l )
      method assign (line 67) | void assign( const std::string& s )
    function key1 (line 108) | [[nodiscard]] inline key1 operator+( const key1& l, const key1_part& r )
      method key1 (line 21) | key1() = default;
      method key1 (line 23) | key1( key1&& ) = default;
      method key1 (line 24) | key1& operator=( key1&& ) = default;
      method key1 (line 28) | key1( const key1& ) = default;
      method key1 (line 29) | key1& operator=( const key1& ) = default;
      method key1 (line 31) | explicit key1( const std::string& s )
      method key1 (line 36) | key1( const std::initializer_list< key1_part >& l )
      method key1 (line 40) | key1( const std::vector< key1_part >::const_iterator& begin, const s...
      method key1 (line 44) | key1& operator=( const std::string& s )
      method key1 (line 51) | key1& operator=( const std::initializer_list< key1_part >& l )
      method assign (line 67) | void assign( const std::string& s )

FILE: include/tao/config/internal/key1_action.hpp
  type tao::config::internal (line 17) | namespace tao::config::internal
    type key1_action (line 20) | struct key1_action
    type key1_action< rules::ident > (line 25) | struct key1_action< rules::ident >
      method apply (line 28) | static void apply( const Input& in, std::vector< key1_part >& st )
    type key1_action< rules::index > (line 35) | struct key1_action< rules::index >
      method apply (line 38) | static void apply( const Input& in, std::vector< key1_part >& st )
    type key1_action< rules::asterisk > (line 45) | struct key1_action< rules::asterisk >
      method apply (line 48) | static void apply( const Input& in, std::vector< key1_part >& st )
    type key1_action< rules::quoted_choice > (line 55) | struct key1_action< rules::quoted_choice >
      method success (line 59) | static void success( const Input& in, std::string& unescaped, std::v...

FILE: include/tao/config/internal/key1_grammar.hpp
  type tao::config::internal::rules (line 10) | namespace tao::config::internal::rules
    type asterisk (line 13) | struct asterisk : pegtl::one< '*' > {}
    type key1_part (line 15) | struct key1_part : pegtl::sor< ident, quoted, index, asterisk > {}
    type key1_rule (line 16) | struct key1_rule : pegtl::list_must< key1_part, dot > {}

FILE: include/tao/config/internal/key1_guard.hpp
  type tao::config::internal (line 15) | namespace tao::config::internal
    class key1_guard (line 17) | class [[nodiscard]] key1_guard
      method key1_guard (line 20) | key1_guard() = delete;
      method key1_guard (line 23) | key1_guard( State& st, key1&& suffix )
      method key1_guard (line 33) | key1_guard( const pegtl_input_t& in, State& st, const function_map& ...
      method key1_guard (line 43) | key1_guard( key1_guard&& ) = delete;
      method key1_guard (line 44) | key1_guard( const key1_guard& ) = delete;

FILE: include/tao/config/internal/key1_kind.hpp
  type tao::config::internal (line 7) | namespace tao::config::internal
    type key1_kind (line 9) | enum class key1_kind : char

FILE: include/tao/config/internal/key1_part.hpp
  type tao::config::internal (line 18) | namespace tao::config::internal
    type key1_part (line 20) | struct key1_part
      method key1_part (line 24) | key1_part( const part_asterisk_t t, const pegtl::position& p )
      method key1_part (line 33) | key1_part( const std::size_t i, const pegtl::position& p )
      method key1_part (line 38) | key1_part( const pegtl::position& p, const std::uint64_t g )
      method key1_part (line 43) | key1_part( const std::string& n, const pegtl::position& p )
      method key1_kind (line 48) | [[nodiscard]] key1_kind kind() const noexcept
      method get_index (line 53) | [[nodiscard]] std::size_t get_index() const noexcept
      method set_generation (line 67) | void set_generation( const std::uint64_t g ) noexcept
      method get_generation (line 79) | [[nodiscard]] std::uint64_t get_generation() const noexcept

FILE: include/tao/config/internal/key_action.hpp
  type tao::config::internal (line 18) | namespace tao::config::internal
    type key_action (line 21) | struct key_action
    type key_action< rules::ident > (line 26) | struct key_action< rules::ident >
      method apply (line 29) | static void apply( const Input& in, std::vector< key_part >& st )
    type key_action< rules::index > (line 36) | struct key_action< rules::index >
      method apply (line 39) | static void apply( const Input& in, std::vector< key_part >& st )
    type key_action< rules::quoted_choice > (line 46) | struct key_action< rules::quoted_choice >
      method success (line 50) | static void success( const Input& /*unused*/, std::string& unescaped...

FILE: include/tao/config/internal/key_grammar.hpp
  type tao::config::internal::rules (line 10) | namespace tao::config::internal::rules
    type dot (line 15) | struct dot : pegtl::one< '.' > {}
    type index (line 17) | struct index : pegtl::rep_min_max< 1, 15, pegtl::digit > {}
    type ident_first (line 19) | struct ident_first : pegtl::ranges< 'a', 'z', 'A', 'Z', '_' > {}
    type ident_other (line 20) | struct ident_other : pegtl::ranges< 'a', 'z', 'A', 'Z', '0', '9', '-',...
    type ident (line 21) | struct ident : pegtl::seq< ident_first, pegtl::star< ident_other > > {}
    type at_quote (line 23) | struct at_quote : pegtl::at< pegtl::one< '\'', '"' > > {}
    type quoted_choice (line 25) | struct quoted_choice : jaxn::string_fragment {}
    type quoted (line 26) | struct quoted : pegtl::if_must< at_quote, quoted_choice > {}
    type key_other (line 28) | struct key_other : pegtl::sor< ident, quoted, index > {}
    type key_first (line 29) | struct key_first : pegtl::sor< ident, quoted > {}
    type key_rule (line 31) | struct key_rule : pegtl::seq< key_first, pegtl::star_must< dot, key_ot...

FILE: include/tao/config/internal/limits.hpp
  type tao::config::internal (line 9) | namespace tao::config::internal

FILE: include/tao/config/internal/object.hpp
  type tao::config::internal (line 14) | namespace tao::config::internal
    type basic_object (line 17) | struct basic_object
      method basic_object (line 21) | basic_object() = delete;
      method basic_object (line 23) | explicit basic_object( const pegtl::position& p )
      method basic_object (line 27) | basic_object( basic_object&& ) = default;
      method basic_object (line 28) | basic_object( const basic_object& ) = default;
      method basic_object (line 32) | basic_object& operator=( basic_object&& ) = default;
      method basic_object (line 33) | basic_object& operator=( const basic_object& ) = default;

FILE: include/tao/config/internal/parse_utility.hpp
  type tao::config::internal (line 18) | namespace tao::config::internal
    function key1 (line 20) | [[nodiscard]] inline key1 parse_key1( pegtl_input_t& in )
    function reference2 (line 27) | [[nodiscard]] inline reference2 parse_reference2( pegtl_input_t& in )

FILE: include/tao/config/internal/pegtl.hpp
  type tao::pegtl (line 15) | namespace tao::pegtl
  type tao::config (line 22) | namespace tao::config

FILE: include/tao/config/internal/phase1_append.hpp
  type tao::config::internal (line 27) | namespace tao::config::internal
    function phase1_append_asterisk (line 33) | void phase1_append_asterisk( concat& c, const pegtl::position& p, cons...
    function phase1_append_name (line 40) | void phase1_append_name( concat& c, const pegtl::position& p, const st...
    function phase1_append_index (line 49) | void phase1_append_index( concat& c, const pegtl::position& p, const s...
    function phase1_append_append (line 82) | void phase1_append_append( concat& c, const pegtl::position& p, const ...
    function phase1_append (line 98) | void phase1_append( concat& c, const key1& path, const T& thing, const...
    function phase1_append (line 124) | void phase1_append( object& o, const key1& path, const T& thing, const...

FILE: include/tao/config/internal/phase1_mode.hpp
  type tao::config::internal (line 7) | namespace tao::config::internal
    type phase1_mode (line 9) | enum class phase1_mode : bool

FILE: include/tao/config/internal/phase2_access.hpp
  type tao::config::internal (line 21) | namespace tao::config::internal
    type phase2_access_return (line 23) | struct phase2_access_return
    function concat (line 28) | [[nodiscard]] inline const concat* phase2_access_name( const concat& c...
    function concat (line 73) | [[nodiscard]] inline const concat* phase2_access_index( const concat& ...
    function concat (line 115) | [[nodiscard]] inline const concat* phase2_access( const concat& c, con...
    function concat (line 130) | [[nodiscard]] inline const concat* phase2_access( const concat& c, con...
    function concat (line 141) | [[nodiscard]] inline const concat* phase2_access( const object& o, con...

FILE: include/tao/config/internal/phase2_additions.hpp
  type tao::config::internal (line 20) | namespace tao::config::internal
    type phase2_additions_impl (line 22) | struct phase2_additions_impl
      method phase2_additions_impl (line 24) | explicit phase2_additions_impl( object& root )
      method process (line 28) | [[nodiscard]] std::size_t process()
      method process_concat (line 40) | void process_concat( concat& c )
      method process_entry (line 128) | void process_entry( entry& e )
      method ignore_entry (line 158) | [[nodiscard]] static bool ignore_entry( const entry& e ) noexcept
      method throw_type_error_if (line 169) | [[nodiscard]] static bool throw_type_error_if( const entry& l, const...
      method throw_type_error (line 183) | [[noreturn]] static void throw_type_error( const entry& l, const ent...
      method process_object (line 188) | static void process_object( object&& l, object& r )
    function phase2_additions (line 208) | [[nodiscard]] inline std::size_t phase2_additions( object& root )

FILE: include/tao/config/internal/phase2_asterisks.hpp
  type tao::config::internal (line 20) | namespace tao::config::internal
    type phase2_asterisks_impl (line 22) | struct phase2_asterisks_impl
      method phase2_asterisks_impl (line 24) | explicit phase2_asterisks_impl( object& root )
      method process (line 28) | [[nodiscard]] std::size_t process()
      method process_concat (line 40) | void process_concat( concat& c )
      method process_entry (line 49) | void process_entry( concat& c, std::list< entry >::iterator& i )
      method process_asterisk (line 87) | void process_asterisk( concat& c, std::list< entry >::iterator& i )
      method process_asterisk_and_array (line 160) | void process_asterisk_and_array( const concat& s, array& a )
      method process_array_and_asterisk (line 172) | void process_array_and_asterisk( array& a, const concat& s )
    function phase2_asterisks (line 185) | [[nodiscard]] inline std::size_t phase2_asterisks( object& root )

FILE: include/tao/config/internal/phase2_everything.hpp
  type tao::config::internal (line 14) | namespace tao::config::internal
    function phase2_iteration (line 16) | [[nodiscard]] inline bool phase2_iteration( state& st, const function_...
    function phase2_everything (line 21) | inline void phase2_everything( state& st, const function_map& fm )

FILE: include/tao/config/internal/phase2_functions.hpp
  type tao::config::internal (line 22) | namespace tao::config::internal
    type phase2_functions_impl (line 24) | struct phase2_functions_impl
      method phase2_functions_impl (line 26) | phase2_functions_impl( state& st, const function_map& fm )
      method process (line 31) | [[nodiscard]] std::size_t process()
      method process_concat (line 44) | void process_concat( concat& c )
      method process_entry (line 51) | void process_entry( entry& e )
      method process_function (line 82) | void process_function( entry& e )
      method process_parse_function (line 101) | void process_parse_function( entry& e, array& a )
    function phase2_functions (line 120) | [[nodiscard]] inline std::size_t phase2_functions( state& st, const fu...

FILE: include/tao/config/internal/phase2_references.hpp
  type tao::config::internal (line 23) | namespace tao::config::internal
    type phase2_references_impl (line 25) | struct phase2_references_impl
      method phase2_references_impl (line 27) | explicit phase2_references_impl( object& root )
      method process (line 31) | [[nodiscard]] std::size_t process()
      method process_concat (line 43) | void process_concat( const key1& prefix, concat& c )
      method process_reference_part (line 59) | [[nodiscard]] std::optional< key1_part > process_reference_part( con...
      method concat (line 72) | [[nodiscard]] const concat* process_reference_parts( const key1& pre...
      method process_inner_reference (line 88) | [[nodiscard]] std::optional< key1_part > process_inner_reference( co...
      method concat (line 114) | [[nodiscard]] const concat* process_entry( const key1& prefix, entry...
    function phase2_references (line 146) | [[nodiscard]] inline std::size_t phase2_references( object& root )

FILE: include/tao/config/internal/phase3_remove.hpp
  type tao::config::internal (line 19) | namespace tao::config::internal
    function phase3_remove (line 24) | inline void phase3_remove( concat& c )
    function phase3_remove (line 54) | inline void phase3_remove( array& a )
    function phase3_remove (line 69) | inline void phase3_remove( object& o )

FILE: include/tao/config/internal/phase5_repack.hpp
  type tao::config::internal (line 21) | namespace tao::config::internal
    function set_key_and_position (line 24) | void set_key_and_position( [[maybe_unused]] json::basic_value< Traits ...
    function phase5_repack (line 38) | void phase5_repack( const key& k, json::events::to_basic_value< Traits...
    function phase5_repack (line 51) | void phase5_repack( const key& k, json::events::to_basic_value< Traits...
    function phase5_repack (line 64) | void phase5_repack( const key& k, json::events::to_basic_value< Traits...
    function phase5_repack (line 112) | void phase5_repack( const key& k, json::events::to_basic_value< Traits...
    function phase5_repack (line 120) | [[nodiscard]] json::basic_value< Traits > phase5_repack( const concat&...
    function phase5_repack (line 128) | [[nodiscard]] json::basic_value< Traits > phase5_repack( const object&...

FILE: include/tao/config/internal/reference2.hpp
  type tao::config::internal (line 16) | namespace tao::config::internal
    type reference2 (line 18) | struct reference2
      method reference2 (line 21) | reference2() = default;
      method reference2 (line 23) | reference2( reference2&& ) = default;
      method reference2 (line 24) | reference2( const reference2& ) = default;
      method reference2 (line 28) | reference2& operator=( reference2&& ) = default;
      method reference2 (line 29) | reference2& operator=( const reference2& ) = default;
      method reference2 (line 31) | explicit reference2( const std::string& s )
      method reference2 (line 36) | reference2( const std::initializer_list< reference2_part >& l )
      method reference2 (line 40) | reference2( const std::vector< reference2_part >::const_iterator& be...
      method reference2 (line 44) | reference2& operator=( const std::string& s )
      method reference2 (line 51) | reference2& operator=( const std::initializer_list< reference2_part ...
      method to_string (line 67) | [[nodiscard]] std::string to_string() const
      method assign (line 72) | void assign( const std::string& s )

FILE: include/tao/config/internal/reference2_action.hpp
  type tao::config::internal (line 16) | namespace tao::config::internal
    type reference2_action (line 19) | struct reference2_action
    type reference2_action< rules::ident > (line 24) | struct reference2_action< rules::ident >
      method apply (line 27) | static void apply( const Input& in, std::vector< reference2_part >& ...
    type reference2_action< rules::index > (line 34) | struct reference2_action< rules::index >
      method apply (line 37) | static void apply( const Input& in, std::vector< reference2_part >& ...
    type reference2_action< rules::quoted_choice > (line 44) | struct reference2_action< rules::quoted_choice >
      method success (line 48) | static void success( const Input& in, std::string& unescaped, std::v...
    type reference2_action< rules::reference2_must > (line 55) | struct reference2_action< rules::reference2_must >
      method match (line 66) | [[nodiscard]] static bool match( ParseInput& in, std::vector< refere...

FILE: include/tao/config/internal/reference2_grammar.hpp
  type tao::config::internal::rules (line 10) | namespace tao::config::internal::rules
    type reference2_must (line 12) | struct reference2_must
    type reference2_part (line 15) | struct reference2_part : pegtl::sor< ident, quoted, index, reference2_...
    type reference2_list (line 16) | struct reference2_list : pegtl::list_must< reference2_part, dot > {}
    type reference2_rest (line 17) | struct reference2_rest : pegtl::seq< reference2_list, pegtl::one< ')' ...
    type reference2_must (line 18) | struct reference2_must : pegtl::if_must< pegtl::one< '(' >, reference2...
    type reference2_rule (line 19) | struct reference2_rule : pegtl::if_must< pegtl::one< '(' >, reference2...

FILE: include/tao/config/internal/reference2_kind.hpp
  type tao::config::internal (line 7) | namespace tao::config::internal
    type reference2_kind (line 9) | enum class reference2_kind : char

FILE: include/tao/config/internal/reference2_part.hpp
  type tao::config::internal (line 19) | namespace tao::config::internal
    type reference2_part (line 21) | struct reference2_part
      method reference2_part (line 29) | reference2_part( const part_vector_t /*unused*/, const pegtl::positi...
      method reference2_part (line 34) | reference2_part( const std::size_t i, const pegtl::position& p )
      method reference2_part (line 39) | reference2_part( const std::string& n, const pegtl::position& p )
      method reference2_kind (line 44) | [[nodiscard]] reference2_kind kind() const noexcept
      method get_index (line 49) | [[nodiscard]] std::size_t get_index() const noexcept
      method to_string (line 77) | [[nodiscard]] std::string to_string() const
    type reference2_part (line 25) | struct reference2_part
      method reference2_part (line 29) | reference2_part( const part_vector_t /*unused*/, const pegtl::positi...
      method reference2_part (line 34) | reference2_part( const std::size_t i, const pegtl::position& p )
      method reference2_part (line 39) | reference2_part( const std::string& n, const pegtl::position& p )
      method reference2_kind (line 44) | [[nodiscard]] reference2_kind kind() const noexcept
      method get_index (line 49) | [[nodiscard]] std::size_t get_index() const noexcept
      method to_string (line 77) | [[nodiscard]] std::string to_string() const
    function to_string (line 94) | [[nodiscard]] inline std::string to_string( const std::vector< referen...

FILE: include/tao/config/internal/repack_traits.hpp
  type tao::config::internal (line 13) | namespace tao::config::internal

FILE: include/tao/config/internal/state.hpp
  type tao::config::internal (line 13) | namespace tao::config::internal
    type state (line 15) | struct state
      method state (line 17) | state()
      method state (line 21) | state( state&& ) = delete;
      method state (line 22) | state( const state& ) = delete;

FILE: include/tao/config/internal/statistics.hpp
  type tao::config::internal (line 15) | namespace tao::config::internal
    type statistics (line 17) | struct statistics
      method statistics (line 19) | statistics() noexcept = default;
      method statistics (line 21) | explicit statistics( const entry& e )
      method statistics (line 26) | explicit statistics( const concat& c )
      method statistics (line 31) | explicit statistics( const array& a )
      method count (line 36) | void count( const entry& e )
      method count (line 67) | void count( const array& a )
      method count (line 80) | void count( const object& o )
      method count (line 88) | void count( const concat& c )
      method nulls (line 98) | [[nodiscard]] std::size_t nulls() const noexcept
      method references (line 103) | [[nodiscard]] std::size_t references() const noexcept
      method is_primitive (line 108) | [[nodiscard]] bool is_primitive() const noexcept

FILE: include/tao/config/internal/string_utility.hpp
  type tao::config::internal (line 13) | namespace tao::config::internal
    type strcat_stream (line 15) | struct strcat_stream
    function strcat_stream (line 21) | strcat_stream& operator<<=( strcat_stream& ss, const T& t )
    function strcat_stream (line 27) | inline strcat_stream& operator<<=( strcat_stream& ss, const json::type...
    function strcat (line 34) | [[nodiscard]] std::string strcat( const Ts&... ts )

FILE: include/tao/config/internal/system_utility.hpp
  type tao::config::internal (line 18) | namespace tao::config::internal
    function read_file_throws (line 22) | [[nodiscard]] inline std::string read_file_throws( const std::string& ...
    function read_file_nothrow (line 27) | [[nodiscard]] inline std::optional< std::string > read_file_nothrow( c...
    function getenv_nothrow (line 37) | [[nodiscard]] inline std::optional< std::string > getenv_nothrow( cons...
    function getenv_throws (line 56) | [[nodiscard]] inline std::string getenv_throws( const pegtl::position&...
    function shell_popen_throws (line 65) | [[nodiscard]] inline std::string shell_popen_throws( const pegtl::posi...

FILE: include/tao/config/internal/to_stream.hpp
  type tao::config::internal (line 13) | namespace tao::config::internal
    function to_stream (line 16) | void to_stream( std::ostream& os, const T& t )
    function to_stream (line 23) | void to_stream( std::ostream& os, const T& t, const std::size_t indent )

FILE: include/tao/config/key.hpp
  type tao::config (line 18) | namespace tao::config
    type key (line 20) | struct key
      method key (line 23) | key() = default;
      method key (line 25) | key( key&& ) = default;
      method key (line 26) | key& operator=( key&& ) = default;
      method key (line 30) | key( const key& ) = default;
      method key (line 31) | key& operator=( const key& ) = default;
      method key (line 33) | explicit key( const std::string& s )
      method key (line 38) | key( const std::initializer_list< key_part >& l )
      method key (line 42) | key( const std::vector< key_part >::const_iterator& begin, const std...
      method key (line 46) | key& operator=( const std::string& s )
      method key (line 53) | key& operator=( const std::initializer_list< key_part >& l )
      method assign (line 69) | void assign( const std::string& s )
    function key (line 77) | inline key pop_front( const key& p )
      method key (line 23) | key() = default;
      method key (line 25) | key( key&& ) = default;
      method key (line 26) | key& operator=( key&& ) = default;
      method key (line 30) | key( const key& ) = default;
      method key (line 31) | key& operator=( const key& ) = default;
      method key (line 33) | explicit key( const std::string& s )
      method key (line 38) | key( const std::initializer_list< key_part >& l )
      method key (line 42) | key( const std::vector< key_part >::const_iterator& begin, const std...
      method key (line 46) | key& operator=( const std::string& s )
      method key (line 53) | key& operator=( const std::initializer_list< key_part >& l )
      method assign (line 69) | void assign( const std::string& s )
    function key (line 83) | inline key pop_back( const key& p )
      method key (line 23) | key() = default;
      method key (line 25) | key( key&& ) = default;
      method key (line 26) | key& operator=( key&& ) = default;
      method key (line 30) | key( const key& ) = default;
      method key (line 31) | key& operator=( const key& ) = default;
      method key (line 33) | explicit key( const std::string& s )
      method key (line 38) | key( const std::initializer_list< key_part >& l )
      method key (line 42) | key( const std::vector< key_part >::const_iterator& begin, const std...
      method key (line 46) | key& operator=( const std::string& s )
      method key (line 53) | key& operator=( const std::initializer_list< key_part >& l )
      method assign (line 69) | void assign( const std::string& s )
    function key (line 89) | inline key& operator+=( key& l, const key& r )
      method key (line 23) | key() = default;
      method key (line 25) | key( key&& ) = default;
      method key (line 26) | key& operator=( key&& ) = default;
      method key (line 30) | key( const key& ) = default;
      method key (line 31) | key& operator=( const key& ) = default;
      method key (line 33) | explicit key( const std::string& s )
      method key (line 38) | key( const std::initializer_list< key_part >& l )
      method key (line 42) | key( const std::vector< key_part >::const_iterator& begin, const std...
      method key (line 46) | key& operator=( const std::string& s )
      method key (line 53) | key& operator=( const std::initializer_list< key_part >& l )
      method assign (line 69) | void assign( const std::string& s )
    function key (line 95) | inline key& operator+=( key& l, const key_part& p )
      method key (line 23) | key() = default;
      method key (line 25) | key( key&& ) = default;
      method key (line 26) | key& operator=( key&& ) = default;
      method key (line 30) | key( const key& ) = default;
      method key (line 31) | key& operator=( const key& ) = default;
      method key (line 33) | explicit key( const std::string& s )
      method key (line 38) | key( const std::initializer_list< key_part >& l )
      method key (line 42) | key( const std::vector< key_part >::const_iterator& begin, const std...
      method key (line 46) | key& operator=( const std::string& s )
      method key (line 53) | key& operator=( const std::initializer_list< key_part >& l )
      method assign (line 69) | void assign( const std::string& s )
    function key (line 101) | inline key& operator+=( key& l, const std::size_t i )
      method key (line 23) | key() = default;
      method key (line 25) | key( key&& ) = default;
      method key (line 26) | key& operator=( key&& ) = default;
      method key (line 30) | key( const key& ) = default;
      method key (line 31) | key& operator=( const key& ) = default;
      method key (line 33) | explicit key( const std::string& s )
      method key (line 38) | key( const std::initializer_list< key_part >& l )
      method key (line 42) | key( const std::vector< key_part >::const_iterator& begin, const std...
      method key (line 46) | key& operator=( const std::string& s )
      method key (line 53) | key& operator=( const std::initializer_list< key_part >& l )
      method assign (line 69) | void assign( const std::string& s )
    function key (line 107) | inline key& operator+=( key& l, std::string&& n )
      method key (line 23) | key() = default;
      method key (line 25) | key( key&& ) = default;
      method key (line 26) | key& operator=( key&& ) = default;
      method key (line 30) | key( const key& ) = default;
      method key (line 31) | key& operator=( const key& ) = default;
      method key (line 33) | explicit key( const std::string& s )
      method key (line 38) | key( const std::initializer_list< key_part >& l )
      method key (line 42) | key( const std::vector< key_part >::const_iterator& begin, const std...
      method key (line 46) | key& operator=( const std::string& s )
      method key (line 53) | key& operator=( const std::initializer_list< key_part >& l )
      method assign (line 69) | void assign( const std::string& s )
    function key (line 113) | inline key& operator+=( key& l, const std::string& n )
      method key (line 23) | key() = default;
      method key (line 25) | key( key&& ) = default;
      method key (line 26) | key& operator=( key&& ) = default;
      method key (line 30) | key( const key& ) = default;
      method key (line 31) | key& operator=( const key& ) = default;
      method key (line 33) | explicit key( const std::string& s )
      method key (line 38) | key( const std::initializer_list< key_part >& l )
      method key (line 42) | key( const std::vector< key_part >::const_iterator& begin, const std...
      method key (line 46) | key& operator=( const std::string& s )
      method key (line 53) | key& operator=( const std::initializer_list< key_part >& l )
      method assign (line 69) | void assign( const std::string& s )
    function key (line 119) | [[nodiscard]] inline key operator+( const key& l, const key& r )
      method key (line 23) | key() = default;
      method key (line 25) | key( key&& ) = default;
      method key (line 26) | key& operator=( key&& ) = default;
      method key (line 30) | key( const key& ) = default;
      method key (line 31) | key& operator=( const key& ) = default;
      method key (line 33) | explicit key( const std::string& s )
      method key (line 38) | key( const std::initializer_list< key_part >& l )
      method key (line 42) | key( const std::vector< key_part >::const_iterator& begin, const std...
      method key (line 46) | key& operator=( const std::string& s )
      method key (line 53) | key& operator=( const std::initializer_list< key_part >& l )
      method assign (line 69) | void assign( const std::string& s )
    function key (line 126) | [[nodiscard]] inline key operator+( const key& l, const key_part& r )
      method key (line 23) | key() = default;
      method key (line 25) | key( key&& ) = default;
      method key (line 26) | key& operator=( key&& ) = default;
      method key (line 30) | key( const key& ) = default;
      method key (line 31) | key& operator=( const key& ) = default;
      method key (line 33) | explicit key( const std::string& s )
      method key (line 38) | key( const std::initializer_list< key_part >& l )
      method key (line 42) | key( const std::vector< key_part >::const_iterator& begin, const std...
      method key (line 46) | key& operator=( const std::string& s )
      method key (line 53) | key& operator=( const std::initializer_list< key_part >& l )
      method assign (line 69) | void assign( const std::string& s )
    function key (line 133) | [[nodiscard]] inline key operator+( const key& l, const std::size_t i )
      method key (line 23) | key() = default;
      method key (line 25) | key( key&& ) = default;
      method key (line 26) | key& operator=( key&& ) = default;
      method key (line 30) | key( const key& ) = default;
      method key (line 31) | key& operator=( const key& ) = default;
      method key (line 33) | explicit key( const std::string& s )
      method key (line 38) | key( const std::initializer_list< key_part >& l )
      method key (line 42) | key( const std::vector< key_part >::const_iterator& begin, const std...
      method key (line 46) | key& operator=( const std::string& s )
      method key (line 53) | key& operator=( const std::initializer_list< key_part >& l )
      method assign (line 69) | void assign( const std::string& s )
    function key (line 140) | [[nodiscard]] inline key operator+( const key& l, std::string&& n )
      method key (line 23) | key() = default;
      method key (line 25) | key( key&& ) = default;
      method key (line 26) | key& operator=( key&& ) = default;
      method key (line 30) | key( const key& ) = default;
      method key (line 31) | key& operator=( const key& ) = default;
      method key (line 33) | explicit key( const std::string& s )
      method key (line 38) | key( const std::initializer_list< key_part >& l )
      method key (line 42) | key( const std::vector< key_part >::const_iterator& begin, const std...
      method key (line 46) | key& operator=( const std::string& s )
      method key (line 53) | key& operator=( const std::initializer_list< key_part >& l )
      method assign (line 69) | void assign( const std::string& s )
    function key (line 147) | [[nodiscard]] inline key operator+( const key& l, const std::string& n )
      method key (line 23) | key() = default;
      method key (line 25) | key( key&& ) = default;
      method key (line 26) | key& operator=( key&& ) = default;
      method key (line 30) | key( const key& ) = default;
      method key (line 31) | key& operator=( const key& ) = default;
      method key (line 33) | explicit key( const std::string& s )
      method key (line 38) | key( const std::initializer_list< key_part >& l )
      method key (line 42) | key( const std::vector< key_part >::const_iterator& begin, const std...
      method key (line 46) | key& operator=( const std::string& s )
      method key (line 53) | key& operator=( const std::initializer_list< key_part >& l )
      method assign (line 69) | void assign( const std::string& s )
    function to_stream (line 154) | inline void to_stream( std::ostream& o, const key& p )
    function to_string (line 166) | [[nodiscard]] inline std::string to_string( const key& p )

FILE: include/tao/config/key_kind.hpp
  type tao::config (line 7) | namespace tao::config
    type key_kind (line 9) | enum class key_kind : char

FILE: include/tao/config/key_part.hpp
  type tao::config (line 20) | namespace tao::config
    type key_part (line 22) | struct key_part
      method key_part (line 26) | explicit key_part( const std::size_t i ) noexcept
      method key_part (line 30) | explicit key_part( std::string&& n ) noexcept
      method key_part (line 34) | explicit key_part( const std::string& n )
      method key_kind (line 38) | [[nodiscard]] key_kind kind() const noexcept
      method get_index (line 43) | [[nodiscard]] std::size_t get_index() const noexcept
    function is_identifier (line 66) | [[nodiscard]] inline bool is_identifier( const std::string& n )
    function name_to_string (line 73) | [[nodiscard]] inline std::string name_to_string( const std::string& n )
    function to_string (line 78) | [[nodiscard]] inline std::string to_string( const key_part& t )
    function name_to_stream (line 89) | inline void name_to_stream( std::ostream& o, const std::string& n )
    function to_stream (line 99) | inline void to_stream( std::ostream& o, const key_part& t )

FILE: include/tao/config/parser.hpp
  type tao::config (line 10) | namespace tao::config
    class parser (line 12) | class parser
      method parser (line 15) | parser() = default;
      method parse (line 17) | void parse( const std::filesystem::path& path )
      method parse (line 22) | void parse( const std::string_view data, const std::string& source )
      method set_inner_extension (line 28) | void set_inner_extension( const std::string& name, F& f )
      method result (line 34) | [[nodiscard]] json::basic_value< Traits > result()

FILE: include/tao/config/to_stream.hpp
  type tao::config (line 16) | namespace tao::config
    function to_stream (line 18) | inline void to_stream( std::ostream& os, const value& v )
    function to_stream (line 24) | inline void to_stream( std::ostream& os, const value& v, const std::si...

FILE: include/tao/config/traits.hpp
  type tao::config (line 11) | namespace tao::config
    type traits (line 14) | struct traits
    type traits< void > (line 19) | struct traits< void >

FILE: include/tao/config/value.hpp
  type tao::config (line 11) | namespace tao::config

FILE: src/example/config/dump_all_phases.cpp
  function main (line 12) | int main( int argc, char** argv )

FILE: src/example/config/dump_only_data.cpp
  function main (line 14) | int main( int argc, char** argv )

FILE: src/example/config/dump_phase_one.cpp
  function main (line 12) | int main( int argc, char** argv )

FILE: src/example/config/dump_phase_three.cpp
  function main (line 12) | int main( int argc, char** argv )

FILE: src/example/config/dump_phase_two.cpp
  function main (line 12) | int main( int argc, char** argv )

FILE: src/example/config/dump_with_meta.cpp
  function main (line 12) | int main( int argc, char** argv )

FILE: src/example/config/try_catch.hpp
  type tao::config::internal (line 15) | namespace tao::config::internal
    function try_catch (line 18) | void try_catch( const F& f )

FILE: src/test/config/access.cpp
  type tao::config (line 8) | namespace tao::config
    function unit_test (line 10) | void unit_test()

FILE: src/test/config/assign.cpp
  type tao::config (line 8) | namespace tao::config
    function unit_test (line 10) | void unit_test()

FILE: src/test/config/custom.cpp
  type tao::config (line 9) | namespace tao::config
    function unit_test (line 11) | void unit_test()

FILE: src/test/config/debug_traits.cpp
  type tao::config (line 13) | namespace tao::config
    function unit_test (line 15) | void unit_test()

FILE: src/test/config/enumerations.cpp
  type tao::config (line 18) | namespace tao::config
    function unit_test (line 20) | void unit_test()

FILE: src/test/config/failure.cpp
  type tao (line 15) | namespace tao
    function unit_test (line 20) | void unit_test( const std::filesystem::path& path )
  function main (line 42) | int main()

FILE: src/test/config/independence.cpp
  type tao::config (line 16) | namespace tao::config
    function p2fun (line 20) | [[nodiscard]] std::size_t p2fun( internal::state& st, const internal::...
    function p2add (line 25) | [[nodiscard]] std::size_t p2add( internal::state& st, const internal::...
    function p2ref (line 30) | [[nodiscard]] std::size_t p2ref( internal::state& st, const internal::...
    function p2ast (line 35) | [[nodiscard]] std::size_t p2ast( internal::state& st, const internal::...
    function unit_test (line 44) | void unit_test( const std::filesystem::path& path )
  function main (line 91) | int main()

FILE: src/test/config/key.cpp
  type tao::config (line 11) | namespace tao::config
    function unit_test (line 13) | void unit_test()

FILE: src/test/config/key_part.cpp
  type tao::config (line 11) | namespace tao::config
    function test_name1 (line 13) | void test_name1()
    function test_name2 (line 25) | void test_name2()
    function test_index (line 37) | void test_index()
    function unit_test (line 49) | void unit_test()

FILE: src/test/config/main.hpp
  function main (line 10) | int main( int /*unused*/, char** argv )

FILE: src/test/config/multi_line_string_position.cpp
  type tao (line 8) | namespace tao
    function test1 (line 10) | void test1()
    function test2 (line 19) | void test2()
    function test3 (line 28) | void test3()
    function test4 (line 37) | void test4()
  function main (line 48) | int main()

FILE: src/test/config/parse_key.cpp
  type tao::config (line 8) | namespace tao::config
    function unit_test (line 10) | void unit_test()

FILE: src/test/config/parse_key1.cpp
  type tao::config (line 8) | namespace tao::config
    function unit_test (line 10) | void unit_test()

FILE: src/test/config/parse_reference2.cpp
  type tao::config (line 8) | namespace tao::config
    function unit_test (line 10) | void unit_test()

FILE: src/test/config/setenv.hpp
  function setenv_throws (line 13) | void setenv_throws( const std::string& name, const std::string& value )

FILE: src/test/config/success.cpp
  type tao::config (line 14) | namespace tao::config
    function unit_test (line 17) | void unit_test( const std::filesystem::path& path )
  function main (line 95) | int main()

FILE: src/test/config/test.hpp
  type tao::config (line 10) | namespace tao::config

FILE: src/test/config/to_stream.cpp
  type tao::config (line 12) | namespace tao::config
    function unit_test (line 14) | void unit_test()

FILE: src/test/config/value.cpp
  type tao::config (line 11) | namespace tao::config
    function unit_test (line 15) | void unit_test()
Condensed preview — 344 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (337K chars).
[
  {
    "path": ".clang-format",
    "chars": 2416,
    "preview": "# the official .clang-format style for https://github.com/taocpp\n#\n# clang-format -i -style=file $(find . -name '[^.]*.["
  },
  {
    "path": ".cmake/taocpp-config-config.cmake.in",
    "chars": 186,
    "preview": "@PACKAGE_INIT@\n\ninclude(CMakeFindDependencyMacro)\nfind_dependency(taocpp-json @TAOCPP_CONFIG_JSON_MIN_VERSION@ CONFIG)\n\n"
  },
  {
    "path": ".codecov.yml",
    "chars": 29,
    "preview": "ignore:\n  - src/example/**/*\n"
  },
  {
    "path": ".github/workflows/clang-analyze.yml",
    "chars": 548,
    "preview": "name: clang-analyze\n\non:\n  push:\n    paths-ignore:\n      - 'README.md'\n      - 'doc/**'\n  pull_request:\n    paths-ignore"
  },
  {
    "path": ".github/workflows/clang-format.yml",
    "chars": 452,
    "preview": "name: clang-format\n\non:\n  push:\n    paths-ignore:\n      - 'README.md'\n      - 'doc/**'\n  pull_request:\n    paths-ignore:"
  },
  {
    "path": ".github/workflows/clang-tidy.yml",
    "chars": 497,
    "preview": "name: clang-tidy\n\non:\n  push:\n    paths-ignore:\n      - 'README.md'\n      - 'doc/**'\n  pull_request:\n    paths-ignore:\n "
  },
  {
    "path": ".github/workflows/code-coverage.yml",
    "chars": 650,
    "preview": "name: Code Coverage\n\non:\n  push:\n    paths-ignore:\n      - 'README.md'\n      - 'doc/**'\n  pull_request:\n    paths-ignore"
  },
  {
    "path": ".github/workflows/codeql-analysis.yml",
    "chars": 2494,
    "preview": "# For most projects, this workflow file will not need changing; you simply need\n# to commit it to your repository.\n#\n# Y"
  },
  {
    "path": ".github/workflows/linux.yml",
    "chars": 2108,
    "preview": "name: Linux\n\non:\n  push:\n    paths-ignore:\n      - 'README.md'\n      - 'doc/**'\n  pull_request:\n    paths-ignore:\n      "
  },
  {
    "path": ".github/workflows/macos.yml",
    "chars": 801,
    "preview": "name: macOS\n\non:\n  push:\n    paths-ignore:\n      - 'README.md'\n      - 'doc/**'\n  pull_request:\n    paths-ignore:\n      "
  },
  {
    "path": ".github/workflows/sanitizer.yml",
    "chars": 742,
    "preview": "name: Sanitizer\n\non:\n  push:\n    paths-ignore:\n      - 'README.md'\n      - 'doc/**'\n  pull_request:\n    paths-ignore:\n  "
  },
  {
    "path": ".github/workflows/windows.yml",
    "chars": 2433,
    "preview": "name: Windows\n\non:\n  push:\n    paths-ignore:\n      - 'README.md'\n      - 'doc/**'\n  pull_request:\n    paths-ignore:\n    "
  },
  {
    "path": ".gitignore",
    "chars": 17,
    "preview": "*~\nbuild\nprivate\n"
  },
  {
    "path": ".gitmodules",
    "chars": 88,
    "preview": "[submodule \"external/json\"]\n\tpath = external/json\n\turl = https://github.com/taocpp/json\n"
  },
  {
    "path": "CMakeLists.txt",
    "chars": 3404,
    "preview": "cmake_minimum_required(VERSION 3.8...3.19)\n\nproject(taocpp-config VERSION 1.0.0 LANGUAGES CXX)\n\nset(TAOCPP_CONFIG_IS_MAI"
  },
  {
    "path": "LICENSE",
    "chars": 1104,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2018-2023 Dr. Colin Hirsch and Daniel Frey\n\nPermission is hereby granted, free of c"
  },
  {
    "path": "Makefile",
    "chars": 1115,
    "preview": "# The Art of C++\n# Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n# Please see LICENSE for license or visit ht"
  },
  {
    "path": "README.md",
    "chars": 6012,
    "preview": "# The Art of C++ / Config\n\n[![Windows CI](https://github.com/taocpp/config/workflows/Windows/badge.svg)](https://github."
  },
  {
    "path": "doc/All-Config-Functions.md",
    "chars": 6118,
    "preview": "# All Config Functions\n\n * [binary](#binary)\n * [default](#default)\n * [env](#env)\n * [jaxn](#jaxn)\n * [parse](#parse)\n "
  },
  {
    "path": "doc/Changelog.md",
    "chars": 1120,
    "preview": "# Changelog\n\n## 1.0.0\n\n**Not yet released**\n\n## Milestones\n\nPre-1.0.0 milestones in rough reverse chronological order.\n\n"
  },
  {
    "path": "doc/Parsing-Config-Files.md",
    "chars": 4559,
    "preview": "# Parsing Config Files\n\n*  [Parsing](#parsing)\n*  [Inspecting](#inspecting)\n*  [Annotations](#annotations)\n*  [Custom Tr"
  },
  {
    "path": "doc/README.md",
    "chars": 316,
    "preview": "# taoCONFIG Documentation\n\n * [Project](https://github.com/taocpp/config)\n * [Writing Config Files](Writing-Config-Files"
  },
  {
    "path": "doc/Writing-Config-Files.md",
    "chars": 22036,
    "preview": "# Writing Config Files\n\nThe config file syntax is based on [JSON] and is completely backwards compatible:\n\n> **Every [JS"
  },
  {
    "path": "include/tao/config/access.hpp",
    "chars": 2251,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/annotation.hpp",
    "chars": 1288,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/assign.hpp",
    "chars": 2117,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/contrib/rot13.hpp",
    "chars": 815,
    "preview": "// Copyright (c) 2022-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/from_file.hpp",
    "chars": 755,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/from_files.hpp",
    "chars": 862,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/from_input.hpp",
    "chars": 760,
    "preview": "// Copyright (c) 2019-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/from_string.hpp",
    "chars": 1315,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/array.hpp",
    "chars": 1187,
    "preview": "// Copyright (c) 2019-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/atom.hpp",
    "chars": 1274,
    "preview": "// Copyright (c) 2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.com/tao"
  },
  {
    "path": "include/tao/config/internal/change_action_and_states.hpp",
    "chars": 2191,
    "preview": "// Copyright (c) 2019-2024 Dr. Colin Hirsch and Daniel Frey\n// Distributed under the Boost Software License, Version 1.0"
  },
  {
    "path": "include/tao/config/internal/concat.hpp",
    "chars": 2461,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/config_action.hpp",
    "chars": 5587,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/config_grammar.hpp",
    "chars": 6064,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/config_parser.hpp",
    "chars": 2385,
    "preview": "// Copyright (c) 2019-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/constants.hpp",
    "chars": 1366,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/debug_traits.hpp",
    "chars": 11351,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/entry.hpp",
    "chars": 7458,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/entry_kind.hpp",
    "chars": 1601,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/events_from_value.hpp",
    "chars": 811,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/forward.hpp",
    "chars": 841,
    "preview": "// Copyright (c) 2019-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/function_implementations.hpp",
    "chars": 5531,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/function_traits.hpp",
    "chars": 2345,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/function_wrapper.hpp",
    "chars": 2048,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/jaxn_action.hpp",
    "chars": 11522,
    "preview": "// Copyright (c) 2017-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/jaxn_to_entry.hpp",
    "chars": 4141,
    "preview": "// Copyright (c) 2016-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/json.hpp",
    "chars": 635,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/key1.hpp",
    "chars": 2744,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/key1_action.hpp",
    "chars": 1775,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/key1_grammar.hpp",
    "chars": 594,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/key1_guard.hpp",
    "chars": 1702,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/key1_kind.hpp",
    "chars": 416,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/key1_part.hpp",
    "chars": 2560,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/key_action.hpp",
    "chars": 1417,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/key_grammar.hpp",
    "chars": 1185,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/limits.hpp",
    "chars": 377,
    "preview": "// Copyright (c) 2021-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/object.hpp",
    "chars": 1512,
    "preview": "// Copyright (c) 2019-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/parse_utility.hpp",
    "chars": 1043,
    "preview": "// Copyright (c) 2019-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/pegtl.hpp",
    "chars": 755,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/phase1_append.hpp",
    "chars": 5341,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/phase1_mode.hpp",
    "chars": 436,
    "preview": "// Copyright (c) 2021-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/phase2_access.hpp",
    "chars": 5929,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/phase2_additions.hpp",
    "chars": 7299,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/phase2_asterisks.hpp",
    "chars": 5947,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/phase2_everything.hpp",
    "chars": 970,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/phase2_functions.hpp",
    "chars": 3776,
    "preview": "// Copyright (c) 2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.com/tao"
  },
  {
    "path": "include/tao/config/internal/phase2_references.hpp",
    "chars": 5263,
    "preview": "// Copyright (c) 2019-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/phase3_remove.hpp",
    "chars": 2551,
    "preview": "// Copyright (c) 2019-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/phase5_repack.hpp",
    "chars": 5205,
    "preview": "// Copyright (c) 2019-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/reference2.hpp",
    "chars": 2471,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/reference2_action.hpp",
    "chars": 2229,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/reference2_grammar.hpp",
    "chars": 956,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/reference2_kind.hpp",
    "chars": 414,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/reference2_part.hpp",
    "chars": 3071,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/repack_traits.hpp",
    "chars": 935,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/state.hpp",
    "chars": 822,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/statistics.hpp",
    "chars": 2953,
    "preview": "// Copyright (c) 2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.com/tao"
  },
  {
    "path": "include/tao/config/internal/string_utility.hpp",
    "chars": 932,
    "preview": "// Copyright (c) 2021-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/system_utility.hpp",
    "chars": 2750,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/internal/to_stream.hpp",
    "chars": 830,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/key.hpp",
    "chars": 3908,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/key_kind.hpp",
    "chars": 337,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/key_part.hpp",
    "chars": 2939,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/parser.hpp",
    "chars": 1032,
    "preview": "// Copyright (c) 2022-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/to_stream.hpp",
    "chars": 839,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/traits.hpp",
    "chars": 611,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config/value.hpp",
    "chars": 352,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "include/tao/config.hpp",
    "chars": 501,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "src/example/config/CMakeLists.txt",
    "chars": 1335,
    "preview": "cmake_minimum_required(VERSION 3.8...3.19)\n\nset(examplesources\n  dump_all_phases.cpp\n  dump_only_data.cpp\n  dump_phase_o"
  },
  {
    "path": "src/example/config/dump_all_phases.cpp",
    "chars": 1530,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "src/example/config/dump_only_data.cpp",
    "chars": 613,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "src/example/config/dump_phase_one.cpp",
    "chars": 889,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "src/example/config/dump_phase_three.cpp",
    "chars": 1094,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "src/example/config/dump_phase_two.cpp",
    "chars": 992,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "src/example/config/dump_with_meta.cpp",
    "chars": 562,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "src/example/config/try_catch.hpp",
    "chars": 1122,
    "preview": "// Copyright (c) 2019-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "src/test/config/CMakeLists.txt",
    "chars": 1551,
    "preview": "cmake_minimum_required(VERSION 3.8...3.19)\n\nset(testsources\n  access.cpp\n  assign.cpp\n  custom.cpp\n  debug_traits.cpp\n  "
  },
  {
    "path": "src/test/config/access.cpp",
    "chars": 1339,
    "preview": "// Copyright (c) 2021-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "src/test/config/assign.cpp",
    "chars": 1451,
    "preview": "// Copyright (c) 2022-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "src/test/config/custom.cpp",
    "chars": 681,
    "preview": "// Copyright (c) 2022-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "src/test/config/debug_traits.cpp",
    "chars": 1184,
    "preview": "// Copyright (c) 2021-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "src/test/config/enumerations.cpp",
    "chars": 2381,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "src/test/config/failure.cpp",
    "chars": 1873,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "src/test/config/independence.cpp",
    "chars": 3607,
    "preview": "// Copyright (c) 2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.com/tao"
  },
  {
    "path": "src/test/config/key.cpp",
    "chars": 1690,
    "preview": "// Copyright (c) 2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.com/tao"
  },
  {
    "path": "src/test/config/key_part.cpp",
    "chars": 1542,
    "preview": "// Copyright (c) 2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.com/tao"
  },
  {
    "path": "src/test/config/main.hpp",
    "chars": 583,
    "preview": "// Copyright (c) 2014-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "src/test/config/multi_line_string_position.cpp",
    "chars": 1618,
    "preview": "// Copyright (c) 2023-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "src/test/config/parse_key.cpp",
    "chars": 793,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "src/test/config/parse_key1.cpp",
    "chars": 940,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "src/test/config/parse_reference2.cpp",
    "chars": 1214,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "src/test/config/setenv.hpp",
    "chars": 825,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "src/test/config/success.cpp",
    "chars": 4473,
    "preview": "// Copyright (c) 2018-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "src/test/config/test.hpp",
    "chars": 3316,
    "preview": "// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.co"
  },
  {
    "path": "src/test/config/to_stream.cpp",
    "chars": 6770,
    "preview": "// Copyright (c) 2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.com/tao"
  },
  {
    "path": "src/test/config/value.cpp",
    "chars": 730,
    "preview": "// Copyright (c) 2024 Dr. Colin Hirsch and Daniel Frey\n// Please see LICENSE for license or visit https://github.com/tao"
  },
  {
    "path": "tests/add_01.failure",
    "chars": 16,
    "preview": "a = null + null\n"
  },
  {
    "path": "tests/add_02.failure",
    "chars": 16,
    "preview": "a = null + true\n"
  },
  {
    "path": "tests/add_03.failure",
    "chars": 16,
    "preview": "a = true + null\n"
  },
  {
    "path": "tests/add_04.failure",
    "chars": 17,
    "preview": "a = true + false\n"
  },
  {
    "path": "tests/add_05.failure",
    "chars": 13,
    "preview": "a = null + 1\n"
  },
  {
    "path": "tests/add_06.failure",
    "chars": 13,
    "preview": "a = 1 + null\n"
  },
  {
    "path": "tests/add_07.failure",
    "chars": 13,
    "preview": "a = true + 1\n"
  },
  {
    "path": "tests/add_08.failure",
    "chars": 13,
    "preview": "a = 1 + true\n"
  },
  {
    "path": "tests/add_09.failure",
    "chars": 14,
    "preview": "a = null + \"\"\n"
  },
  {
    "path": "tests/add_10.failure",
    "chars": 14,
    "preview": "a = \"\" + null\n"
  },
  {
    "path": "tests/add_11.failure",
    "chars": 14,
    "preview": "a = true + \"\"\n"
  },
  {
    "path": "tests/add_12.failure",
    "chars": 14,
    "preview": "a = \"\" + true\n"
  },
  {
    "path": "tests/add_13.failure",
    "chars": 11,
    "preview": "a = 1 + \"\"\n"
  },
  {
    "path": "tests/add_14.failure",
    "chars": 11,
    "preview": "a = \"\" + 1\n"
  },
  {
    "path": "tests/add_15.failure",
    "chars": 15,
    "preview": "a = null + $\"\"\n"
  },
  {
    "path": "tests/add_16.failure",
    "chars": 15,
    "preview": "a = $\"\" + null\n"
  },
  {
    "path": "tests/add_17.failure",
    "chars": 15,
    "preview": "a = true + $\"\"\n"
  },
  {
    "path": "tests/add_18.failure",
    "chars": 15,
    "preview": "a = $\"\" + true\n"
  },
  {
    "path": "tests/add_19.failure",
    "chars": 12,
    "preview": "a = 1 + $\"\"\n"
  },
  {
    "path": "tests/add_20.failure",
    "chars": 12,
    "preview": "a = $\"\" + 1\n"
  },
  {
    "path": "tests/add_21.failure",
    "chars": 13,
    "preview": "a = \"\" + $\"\"\n"
  },
  {
    "path": "tests/add_22.failure",
    "chars": 13,
    "preview": "a = $\"\" + \"\"\n"
  },
  {
    "path": "tests/add_23.failure",
    "chars": 14,
    "preview": "a = null + {}\n"
  },
  {
    "path": "tests/add_24.failure",
    "chars": 14,
    "preview": "a = {} + null\n"
  },
  {
    "path": "tests/add_25.failure",
    "chars": 14,
    "preview": "a = true + {}\n"
  },
  {
    "path": "tests/add_26.failure",
    "chars": 14,
    "preview": "a = {} + true\n"
  },
  {
    "path": "tests/add_27.failure",
    "chars": 11,
    "preview": "a = 1 + {}\n"
  },
  {
    "path": "tests/add_28.failure",
    "chars": 11,
    "preview": "a = {} + 1\n"
  },
  {
    "path": "tests/add_29.failure",
    "chars": 12,
    "preview": "a = \"\" + {}\n"
  },
  {
    "path": "tests/add_30.failure",
    "chars": 12,
    "preview": "a = {} + \"\"\n"
  },
  {
    "path": "tests/add_31.failure",
    "chars": 13,
    "preview": "a = $\"\" + {}\n"
  },
  {
    "path": "tests/add_32.failure",
    "chars": 13,
    "preview": "a = {} + $\"\"\n"
  },
  {
    "path": "tests/add_33.failure",
    "chars": 14,
    "preview": "a = null + []\n"
  },
  {
    "path": "tests/add_34.failure",
    "chars": 14,
    "preview": "a = [] + null\n"
  },
  {
    "path": "tests/add_35.failure",
    "chars": 14,
    "preview": "a = true + []\n"
  },
  {
    "path": "tests/add_36.failure",
    "chars": 14,
    "preview": "a = [] + true\n"
  },
  {
    "path": "tests/add_37.failure",
    "chars": 11,
    "preview": "a = 1 + []\n"
  },
  {
    "path": "tests/add_38.failure",
    "chars": 11,
    "preview": "a = [] + 1\n"
  },
  {
    "path": "tests/add_39.failure",
    "chars": 12,
    "preview": "a = \"\" + []\n"
  },
  {
    "path": "tests/add_40.failure",
    "chars": 12,
    "preview": "a = [] + \"\"\n"
  },
  {
    "path": "tests/add_41.failure",
    "chars": 13,
    "preview": "a = $\"\" + []\n"
  },
  {
    "path": "tests/add_42.failure",
    "chars": 13,
    "preview": "a = [] + $\"\"\n"
  },
  {
    "path": "tests/add_43.failure",
    "chars": 12,
    "preview": "a = {} + []\n"
  },
  {
    "path": "tests/add_44.failure",
    "chars": 12,
    "preview": "a = [] + {}\n"
  },
  {
    "path": "tests/add_45.failure",
    "chars": 28,
    "preview": "a = []\nb = {}\nc = (a) + (b)\n"
  },
  {
    "path": "tests/add_46.failure",
    "chars": 29,
    "preview": "a = null\nb = 1\nc = (a) + (b)\n"
  },
  {
    "path": "tests/add_47.failure",
    "chars": 45,
    "preview": "a = null\nb = 1\nc = (a)\nd = (b)\ne = (c) + (d)\n"
  },
  {
    "path": "tests/add_48.failure",
    "chars": 64,
    "preview": "a {\n    b {\n        c {\n        }\n        c [\n        ]\n    }\n}\n"
  },
  {
    "path": "tests/add_number.jaxn",
    "chars": 155,
    "preview": "{\n   a: 18446744073709551615,\n   b: -1,\n   c: -7,\n   d: -1,\n   e: -1,\n   f: -19,\n   g: 1,\n   h: 1,\n   i: 0,\n   j: 0,\n   "
  },
  {
    "path": "tests/add_number.success",
    "chars": 228,
    "preview": "a = 9223372036854775807 + 9223372036854775808\nb = -9223372036854775808 + 9223372036854775807\nc = -3 + -4\nd = -6 + 5\ne = "
  },
  {
    "path": "tests/add_string.jaxn",
    "chars": 39,
    "preview": "{\n   a: \"a\",\n   b: \"ab\",\n   c: \"abc\"\n}\n"
  },
  {
    "path": "tests/add_string.success",
    "chars": 47,
    "preview": "a = \"a\"\n\nb = \"a\"\nb += \"b\"\n\nc = \"a\" + \"b\" + \"c\"\n"
  },
  {
    "path": "tests/array_index_01.jaxn",
    "chars": 87,
    "preview": "{\n   bar: 1,\n   baz: 5,\n   foo: [\n      1,\n      12,\n      3,\n      34,\n      5\n   ]\n}\n"
  },
  {
    "path": "tests/array_index_01.success",
    "chars": 83,
    "preview": "foo = [ 0 1 2 3 4 ]\nbar = (foo.0)\nbaz = (foo.4)\nfoo.1 += 10\nfoo.3 += 30\nfoo.* += 1\n"
  },
  {
    "path": "tests/array_index_02.jaxn",
    "chars": 15,
    "preview": "{\n   foo: []\n}\n"
  },
  {
    "path": "tests/array_index_02.success",
    "chars": 31,
    "preview": "foo = [ 1 2 3 ]\nfoo.* = delete\n"
  },
  {
    "path": "tests/binary.jaxn",
    "chars": 45,
    "preview": "{\n   a : $3031,\n   b : $3031,\n   c : $3031\n}\n"
  },
  {
    "path": "tests/binary.success",
    "chars": 40,
    "preview": "a = $3031\nb = $30 + $31\nc = $\"\\x30\\x31\"\n"
  },
  {
    "path": "tests/braces.jaxn",
    "chars": 3,
    "preview": "{}\n"
  },
  {
    "path": "tests/braces.success",
    "chars": 4,
    "preview": "{\n}\n"
  },
  {
    "path": "tests/combo_01.jaxn",
    "chars": 108,
    "preview": "{\n   foo: {\n      a: {\n         baz: 2\n      },\n      b: {\n         bar: 42,\n         baz: 1\n      }\n   }\n}\n"
  },
  {
    "path": "tests/combo_01.success",
    "chars": 62,
    "preview": "foo.*.bar = 42\nfoo.a.bar = delete\nfoo.b.baz = 1\nfoo.a.baz = 2\n"
  },
  {
    "path": "tests/combo_02.jaxn",
    "chars": 126,
    "preview": "{\n   foo: {\n      a: {\n         bar: 42,\n         baz: 2\n      },\n      b: {\n         bar: 42,\n         baz: 1\n      }\n "
  },
  {
    "path": "tests/combo_02.success",
    "chars": 62,
    "preview": "foo.a.bar = delete\nfoo.*.bar = 42\nfoo.b.baz = 1\nfoo.a.baz = 2\n"
  },
  {
    "path": "tests/commas.jaxn",
    "chars": 785,
    "preview": "{\n   commas: {\n      arrays: [\n         [\n            1,\n            2,\n            3\n         ],\n         [\n           "
  },
  {
    "path": "tests/commas.success",
    "chars": 316,
    "preview": "commas : {\n    arrays : [\n        [ 1 2 3 ],\n        [ 1, 2, 3 ],\n        [ 1, 2, 3, ],\n        [ 1 2, 3 ]\n        [ 1 2"
  },
  {
    "path": "tests/comments.jaxn",
    "chars": 98,
    "preview": "{\n   a: 1,\n   b: 2,\n   c: 3,\n   d: 4,\n   e: {\n      f: 6\n   },\n   g: [\n      7\n   ],\n   h: \"hH\"\n}\n"
  },
  {
    "path": "tests/comments.success",
    "chars": 397,
    "preview": "#!/bin/grmblfx\n\n# This is a comment.\n\n// This is another comment.\n\n/* And another one. */\n\n/* These comments /* don't ne"
  },
  {
    "path": "tests/complex_01.failure",
    "chars": 48,
    "preview": "a = (default (b) \"foo\")\nb = (default (a) \"bar\")\n"
  },
  {
    "path": "tests/complex_02.failure",
    "chars": 43,
    "preview": "x.* = 3\nx.a += 1\n\na = 2\ny.a = 1\ny.* += (a)\n"
  },
  {
    "path": "tests/complex_03.failure",
    "chars": 60,
    "preview": "a = (default (b) \"foo\") + \"a\"\nb = (default (a) \"bar\") + \"b\"\n"
  },
  {
    "path": "tests/debug_traits.config",
    "chars": 114,
    "preview": "a = 1 b { c = 42 d = [ null, true ] e = (a.42.(b)) f = 'yo' g = -3 h = 3.14 i = (env \"USER\") j = $beef } c.* = 42\n"
  },
  {
    "path": "tests/debug_traits.output",
    "chars": 8990,
    "preview": "{\n   position: \"(root):1:1\",\n   object_data: {\n      a: {\n         remove: true,\n         implicit: false,\n         temp"
  },
  {
    "path": "tests/delete.jaxn",
    "chars": 116,
    "preview": "{\n   c: [\n      {},\n      {}\n   ],\n   d: {\n      a: {},\n      b: {},\n      c: {}\n   },\n   f: {},\n   g: 2,\n   h: 2\n}\n"
  },
  {
    "path": "tests/delete.success",
    "chars": 239,
    "preview": "a = 1\na = delete\n\nb.c.d = delete\n\nc = [ {\n  d = delete\n} {\n  e = 42\n} ]\n\nc.1.e = delete\n\nd.a.d = 1\nd.b.d = 2\nd.c.d = 3\n\n"
  },
  {
    "path": "tests/doc_asterisk_01.jaxn",
    "chars": 116,
    "preview": "{\n   servers: {\n      primary: {\n         port: 7000\n      },\n      secondary: {\n         port: 7000\n      }\n   }\n}\n"
  },
  {
    "path": "tests/doc_asterisk_01.success",
    "chars": 135,
    "preview": "servers\n{\n    primary\n    {\n        port = 443\n    }\n    secondary\n    {\n        port = 8888\n    }\n}\nservers.*.port = 70"
  },
  {
    "path": "tests/doc_default.jaxn",
    "chars": 29,
    "preview": "{\n   bar: false,\n   foo: 1\n}\n"
  },
  {
    "path": "tests/doc_default.success",
    "chars": 52,
    "preview": "foo = (default 1 2)\nbar = (default null false true)\n"
  },
  {
    "path": "tests/doc_delete_01.jaxn",
    "chars": 39,
    "preview": "{\n   ip: \"127.0.0.2\",\n   port: 27960\n}\n"
  },
  {
    "path": "tests/doc_delete_01.success",
    "chars": 126,
    "preview": "#!/usr/local/bin/qs\n\nip = \"127.0.0.2\"\nport = 27960\nmaps = [ \"ztn\" \"dm13\" \"t9\" ]\nmaps = delete  // Changed our minds, no "
  }
]

// ... and 144 more files (download for full content)

About this extraction

This page contains the full source code of the taocpp/config GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 344 files (296.4 KB), approximately 87.2k tokens, and a symbol index with 712 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!