diff --git a/README.md b/README.md index c6fa6e3..54c9247 100644 --- a/README.md +++ b/README.md @@ -280,6 +280,7 @@ UTF-8 decoding is performed using a state machine based on Bjoern Hoehrmann's '[ # Contact For bug reports and feature requests please consider using the [issues] system here on GitHub. For anything else though you're welcome to reach out via other means. In order of likely response time: +- Gitter: [marzer/tomlplusplus](https://gitter.im/marzer/tomlplusplus) ("Discord for repos") - Twitter: [marzer8789](https://twitter.com/marzer8789) - Email: [mark.gillard@outlook.com.au](mailto:mark.gillard@outlook.com.au) - Facebook: [marzer](https://www.facebook.com/marzer) diff --git a/docs/pages/main_page.dox b/docs/pages/main_page.dox index 3b91c7d..1982157 100644 --- a/docs/pages/main_page.dox +++ b/docs/pages/main_page.dox @@ -591,6 +591,7 @@ it is embedded in the preamble at the top of the header. \section mainpage-contact Contacting the author For bug reports and feature requests please use the \github{marzer/tomlplusplus/issues, Github Issues} system. For anything else you're welcome to reach out via other means. In order of likely response speed: +- Gitter: [marzer/tomlplusplus](https://gitter.im/marzer/tomlplusplus) ("Discord for repos") - Twitter: [marzer8789](https://twitter.com/marzer8789) - Email: [mark.gillard@outlook.com.au](mailto:mark.gillard@outlook.com.au) - Facebook: [marzer](https://www.facebook.com/marzer) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index f5d85fd..5cc5fe2 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -21,6 +21,7 @@ endfunction() add_example(error_printer) add_example(parse_benchmark) -add_example(simple_parser ARGS "${PROJECT_SOURCE_DIR}/example.toml") -add_example(toml_generator ARGS 100) +add_example(simple_parser) +add_example(toml_generator) +add_example(toml_merger) add_example(toml_to_json_transcoder ARGS "${PROJECT_SOURCE_DIR}/example.toml") diff --git a/examples/merge_base.toml b/examples/merge_base.toml new file mode 100644 index 0000000..a863b27 --- /dev/null +++ b/examples/merge_base.toml @@ -0,0 +1,5 @@ +[section1] +key1="value1" +key2="value2" + +[section1.child1] diff --git a/examples/merge_overrides.toml b/examples/merge_overrides.toml new file mode 100644 index 0000000..792396e --- /dev/null +++ b/examples/merge_overrides.toml @@ -0,0 +1,8 @@ +[section1] +key2="value3" + +[section1.child1] +foo="bar" + +[section1.child2] +foo2="bar2" diff --git a/examples/meson.build b/examples/meson.build index 9d69b26..8795efe 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -23,6 +23,7 @@ examples = [ 'toml_generator', 'error_printer', 'parse_benchmark', + 'toml_merger', ] example_executables = [] diff --git a/examples/toml_merger.cpp b/examples/toml_merger.cpp new file mode 100644 index 0000000..852eb16 --- /dev/null +++ b/examples/toml_merger.cpp @@ -0,0 +1,69 @@ +// This file is a part of toml++ and is subject to the the terms of the MIT license. +// Copyright (c) Mark Gillard +// See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT + +// This example demonstrates a method of merging one TOML data tree into another. + +#include "examples.h" +#include + +using namespace std::string_view_literals; + +namespace +{ + // recursively merge 'rhs' into 'lhs'. + // + // note that this implementation always prioritizes 'rhs' over 'lhs' in the event of a conflict; + // extending it to handle conflicts in some other manner is left as an exercise to the reader :) + + static void merge(toml::table& lhs, toml::table&& rhs) + { + rhs.for_each( + [&](const toml::key& rhs_key, auto&& rhs_val) + { + auto lhs_it = lhs.lower_bound(rhs_key); + + // not found in lhs - direct move + if (lhs_it == lhs.cend() || lhs_it->first != rhs_key) + { + lhs.emplace_hint(lhs_it, rhs_key, std::move(rhs_val)); + return; + } + + // both nodes were tables - recurse into them + if constexpr (toml::is_table) + { + if (auto lhs_child_table = lhs_it->second.as_table()) + { + merge(*lhs_child_table, std::move(rhs_val)); + return; + } + } + + // one or both weren't tables - replace lhs with rhs + lhs.insert_or_assign(rhs_key, std::move(rhs_val)); + }); + } +} + +int main(int argc, char** argv) +{ + const auto base_path = argc > 1 ? std::string_view{ argv[1] } : "merge_base.toml"sv; + const auto overrides_path = argc > 2 ? std::string_view{ argv[2] } : "merge_overrides.toml"sv; + + toml::table tbl; + try + { + tbl = toml::parse_file(base_path); + merge(tbl, toml::parse_file(overrides_path)); + } + catch (const toml::parse_error& err) + { + std::cerr << err << "\n"; + return 1; + } + + std::cout << tbl << "\n"; + return 0; +} diff --git a/examples/toml_merger.vcxproj b/examples/toml_merger.vcxproj new file mode 100644 index 0000000..cb93dbb --- /dev/null +++ b/examples/toml_merger.vcxproj @@ -0,0 +1,63 @@ + + + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {E467EB97-B066-4D38-B3DB-60961E3F96A1} + 10.0 + + + + Application + true + v143 + MultiByte + + + Application + false + v143 + true + MultiByte + + + + + + + + + Console + + + + ..\examples + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/toml++.sln b/toml++.sln index c2b58a7..fe8e512 100644 --- a/toml++.sln +++ b/toml++.sln @@ -91,6 +91,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tt_encoder", "toml-test\tt_ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "odr_test", "tests\vs\odr_test.vcxproj", "{723FC4CA-0E24-4956-8FDC-E537EA3847AA}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "toml_merger", "examples\toml_merger.vcxproj", "{E467EB97-B066-4D38-B3DB-60961E3F96A1}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -259,6 +261,10 @@ Global {723FC4CA-0E24-4956-8FDC-E537EA3847AA}.Debug|x64.Build.0 = Debug|x64 {723FC4CA-0E24-4956-8FDC-E537EA3847AA}.Release|x64.ActiveCfg = Release|x64 {723FC4CA-0E24-4956-8FDC-E537EA3847AA}.Release|x64.Build.0 = Release|x64 + {E467EB97-B066-4D38-B3DB-60961E3F96A1}.Debug|x64.ActiveCfg = Debug|x64 + {E467EB97-B066-4D38-B3DB-60961E3F96A1}.Debug|x64.Build.0 = Debug|x64 + {E467EB97-B066-4D38-B3DB-60961E3F96A1}.Release|x64.ActiveCfg = Release|x64 + {E467EB97-B066-4D38-B3DB-60961E3F96A1}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -304,6 +310,7 @@ Global {8D19DE49-9687-4305-B59E-21F398415F5A} = {5DE43BF4-4EDD-4A7A-A422-764415BB3224} {8F673261-5DFE-4B67-937A-61FC3F0082A2} = {5DE43BF4-4EDD-4A7A-A422-764415BB3224} {723FC4CA-0E24-4956-8FDC-E537EA3847AA} = {4E25CF88-D7D8-4A9C-A52E-0D78281E82EC} + {E467EB97-B066-4D38-B3DB-60961E3F96A1} = {412816A5-9D22-4A30-BCDF-ABFB54BB3735} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {0926DDCC-88CD-4839-A82D-D9B99E02A0B1}