diff --git a/.gitignore b/.gitignore index 037c9f2..dbed0eb 100644 --- a/.gitignore +++ b/.gitignore @@ -91,3 +91,4 @@ output/ .idea/ scratch/ +.wraplock diff --git a/build-config/CLI11/meson.build b/build-config/CLI11/meson.build index caa6618..d2d56ff 100644 --- a/build-config/CLI11/meson.build +++ b/build-config/CLI11/meson.build @@ -1,8 +1,8 @@ cli11_proj = subproject('cli11') cli11_dep = cli11_proj.get_variable('CLI11_dep') -install_subdir( - meson.project_source_root() / 'subprojects' / 'CLI11-2.6.1' / 'include', - install_dir: get_option('includedir') / 'fourdst' / 'vendor', - strip_directory: true -) \ No newline at end of file +cli11_headers = cli11_proj.get_variable('cli11_headers') +cli11_impl_headers = cli11_proj.get_variable('cli11_impl_headers') + +install_headers(cli11_headers, subdir: 'fourdst/vendor/CLI') +install_headers(cli11_impl_headers, subdir: 'fourdst/vendor/CLI/impl') \ No newline at end of file diff --git a/build-config/reflect-cpp/meson.build b/build-config/reflect-cpp/meson.build index e576b81..1d72612 100644 --- a/build-config/reflect-cpp/meson.build +++ b/build-config/reflect-cpp/meson.build @@ -19,15 +19,14 @@ reflect_cpp_include_dirs = include_directories('include') reflect_cpp_library = static_library( 'reflect_cpp', reflect_cpp_sources, - include_directories: reflect_cpp_include_dirs, + include_directories: [reflect_cpp_include_dirs, tomlpp_inc_dir], install: true, - dependencies: [tomlpp_dep], + install_dir: get_option('libdir') / 'fourdst' / 'vendor', ) reflect_cpp_dep = declare_dependency( link_with: reflect_cpp_library, - include_directories: reflect_cpp_include_dirs, - dependencies: [tomlpp_dep], + include_directories: [reflect_cpp_include_dirs, tomlpp_inc_dir] ) install_subdir( diff --git a/build-config/tomlpp/meson.build b/build-config/tomlpp/meson.build index 3553417..7b25a36 100644 --- a/build-config/tomlpp/meson.build +++ b/build-config/tomlpp/meson.build @@ -1,7 +1,9 @@ -tomlpp_dep = dependency('tomlplusplus', required: true, static: true).as_system() +tomlpp_inc_dir = include_directories('vendor/include') install_subdir( - meson.project_source_root() / 'subprojects' / 'tomlplusplus-3.4.0' / 'include', + 'vendor/include', install_dir: get_option('includedir') / 'fourdst' / 'vendor', strip_directory: true -) \ No newline at end of file +) + + diff --git a/build-config/tomlpp/vendor/LICENSE b/build-config/tomlpp/vendor/LICENSE new file mode 100644 index 0000000..261cd61 --- /dev/null +++ b/build-config/tomlpp/vendor/LICENSE @@ -0,0 +1,16 @@ +MIT License + +Copyright (c) Mark Gillard + +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. diff --git a/build-config/tomlpp/vendor/README.md b/build-config/tomlpp/vendor/README.md new file mode 100644 index 0000000..be589c3 --- /dev/null +++ b/build-config/tomlpp/vendor/README.md @@ -0,0 +1,349 @@ +[![banner](docs/images/banner.png)][homepage] +[![Releases](https://img.shields.io/github/v/release/marzer/tomlplusplus?style=flat-square)](https://github.com/marzer/tomlplusplus/releases) +[![C++17](docs/images/badge-C++17.svg)][cpp_compilers] +[![TOML](docs/images/badge-TOML.svg)][v1.0.0] +[![MIT license](docs/images/badge-license-MIT.svg)](./LICENSE) +[![ci](https://github.com/marzer/tomlplusplus/actions/workflows/ci.yaml/badge.svg?branch=master)](https://github.com/marzer/tomlplusplus/actions/workflows/ci.yaml) +[![Mentioned in Awesome C++](docs/images/badge-awesome.svg)](https://github.com/fffaraz/awesome-cpp) +[![Sponsor](docs/images/badge-sponsor.svg)](https://github.com/sponsors/marzer) +[![Gitter](docs/images/badge-gitter.svg)](https://gitter.im/marzer/tomlplusplus) +==== + +## toml++ homepage + +

+ ✨️ This README is fine, but the toml++ homepage is better. ✨️ +

+ +
+ +## Library features + +- Header-only (optional!) +- Supports the latest [TOML] release ([v1.0.0]), plus optional support for some unreleased TOML features +- Passes all tests in the [toml-test](https://github.com/BurntSushi/toml-test) suite +- Supports serializing to JSON and YAML +- Proper UTF-8 handling (incl. BOM) +- C++17 (plus some C++20 features where available, e.g. experimental support for [char8_t] strings) +- Doesn't require RTTI +- Works with or without exceptions +- Tested on Clang (8+), GCC (8+) and MSVC (VS2019) +- Tested on x64, x86 and ARM + +
+ +## Basic usage + +> ℹ️ _The following example favours brevity. If you'd prefer full API documentation and lots of specific code +> snippets instead, visit the project [homepage]_ + +Given a [TOML] file `configuration.toml` containing the following: + +```toml +[library] +name = "toml++" +authors = ["Mark Gillard "] + +[dependencies] +cpp = 17 +``` + +Reading it in C++ is easy with toml++: + +```cpp +#include + +auto config = toml::parse_file( "configuration.toml" ); + +// get key-value pairs +std::string_view library_name = config["library"]["name"].value_or(""sv); +std::string_view library_author = config["library"]["authors"][0].value_or(""sv); +int64_t depends_on_cpp_version = config["dependencies"]["cpp"].value_or(0); + +// modify the data +config.insert_or_assign("alternatives", toml::array{ + "cpptoml", + "toml11", + "Boost.TOML" +}); + +// use a visitor to iterate over heterogenous data +config.for_each([](auto& key, auto& value) +{ + std::cout << value << "\n"; + if constexpr (toml::is_string) + do_something_with_string_values(value); +}); + +// you can also iterate more 'traditionally' using a ranged-for +for (auto&& [k, v] : config) +{ + // ... +} + +// re-serialize as TOML +std::cout << config << "\n"; + +// re-serialize as JSON +std::cout << toml::json_formatter{ config } << "\n"; + +// re-serialize as YAML +std::cout << toml::yaml_formatter{ config } << "\n"; + +``` + +You'll find some more code examples in the `examples` directory, and plenty more as part of the [API documentation]. + +
+ +## Adding toml++ to your project + +`toml++` comes in two flavours: Single-header and Regular. The API is the same for both. + +### 🍦️ Single-header flavour + +1. Drop [`toml.hpp`] wherever you like in your source tree +2. There is no step two + +### 🍨️ Regular flavour + +1. Clone the repository +2. Add `tomlplusplus/include` to your include paths +3. `#include ` + +### Conan + +Add `tomlplusplus/3.4.0` to your conanfile. + +### DDS + +Add `tomlpp` to your `package.json5`, e.g.: + +```plaintext +depends: [ + 'tomlpp^3.4.0', +] +``` + +> ℹ️ _[What is DDS?](https://dds.pizza/)_ + +### Tipi.build + +`tomlplusplus` can be easily used in [tipi.build](https://tipi.build) projects by adding the following entry to your `.tipi/deps`: + +```json +{ + "marzer/tomlplusplus": {} +} +``` + +### Vcpkg + +```plaintext +vcpkg install tomlplusplus +``` + +### Meson + +You can install the wrap with: + +```plaintext +meson wrap install tomlplusplus +``` + +After that, you can use it like a regular dependency: + +```meson +tomlplusplus_dep = dependency('tomlplusplus') +``` + +You can also add it as a subproject directly. + +### CMake FetchContent + +```cmake +include(FetchContent) +FetchContent_Declare( + tomlplusplus + GIT_REPOSITORY https://github.com/marzer/tomlplusplus.git + GIT_TAG v3.4.0 +) +FetchContent_MakeAvailable(tomlplusplus) +``` + +> ℹ️ _[What is FetchContent?](https://cmake.org/cmake/help/latest/module/FetchContent.html)_ + +### Git submodules + +```plaintext +git submodule add --depth 1 https://github.com/marzer/tomlplusplus.git tomlplusplus +``` + +### Other environments and package managers + +The C++ tooling ecosystem is a fractal nightmare of unbridled chaos so naturally I'm not up-to-speed with all of the +available packaging and integration options. I'm always happy to see new ones supported, though! If there's some +integration you'd like to see and have the technical know-how to make it happen, feel free to +[make a pull request](./CONTRIBUTING.md). + +### What about dependencies? + +If you just want to consume `toml++` as a regular library then you don't have any dependencies to worry about. +There's a few test-related dependencies to be aware of if you're working on the library, though. +See [CONTRIBUTING] for information. + +
+ +## Configuration + +A number of configurable options are exposed in the form of preprocessor `#defines` Most likely you +won't need to mess with these at all, but if you do, set them before including toml++. + +| Option | Type | Description | Default | +| --------------------------------- | :------------: | --------------------------------------------------------------------------------------------------------- | --------------------- | +| `TOML_ASSERT(expr)` | function macro | Sets the assert function used by the library. | `assert()` | +| `TOML_CALLCONV` | define | Calling convention to apply to exported free/static functions. | undefined | +| `TOML_CONFIG_HEADER` | string literal | Includes the given header file before the rest of the library. | undefined | +| `TOML_ENABLE_FORMATTERS` | boolean | Enables the formatters. Set to `0` if you don't need them to improve compile times and binary size. | `1` | +| `TOML_ENABLE_FLOAT16` | boolean | Enables support for the built-in `_Float16` type. | per compiler settings | +| `TOML_ENABLE_PARSER` | boolean | Enables the parser. Set to `0` if you don't need it to improve compile times and binary size. | `1` | +| `TOML_ENABLE_UNRELEASED_FEATURES` | boolean | Enables support for [unreleased TOML language features]. | `0` | +| `TOML_ENABLE_WINDOWS_COMPAT` | boolean | Enables support for transparent conversion between wide and narrow strings. | `1` on Windows | +| `TOML_EXCEPTIONS` | boolean | Sets whether the library uses exceptions. | per compiler settings | +| `TOML_EXPORTED_CLASS` | define | API export annotation to add to classes. | undefined | +| `TOML_EXPORTED_MEMBER_FUNCTION` | define | API export annotation to add to non-static class member functions. | undefined | +| `TOML_EXPORTED_FREE_FUNCTION` | define | API export annotation to add to free functions. | undefined | +| `TOML_EXPORTED_STATIC_FUNCTION` | define | API export annotation to add to static functions. | undefined | +| `TOML_HEADER_ONLY` | boolean | Disable this to explicitly control where toml++'s implementation is compiled (e.g. as part of a library). | `1` | +| `TOML_IMPLEMENTATION` | define | Define this to enable compilation of the library's implementation when `TOML_HEADER_ONLY` == `0`. | undefined | +| `TOML_OPTIONAL_TYPE` | type name | Overrides the `optional` type used by the library if you need [something better than std::optional]. | undefined | +| `TOML_SMALL_FLOAT_TYPE` | type name | If your codebase has a custom 'small float' type (e.g. half-precision), this tells toml++ about it. | undefined | +| `TOML_SMALL_INT_TYPE` | type name | If your codebase has a custom 'small integer' type (e.g. 24-bits), this tells toml++ about it. | undefined | + +> ℹ️ _A number of these have ABI implications; the library uses inline namespaces to prevent you from accidentally +> linking incompatible combinations together._ + +
+ +## TOML Language Support + +At any given time the library aims to support whatever the [most recently-released version] of TOML is, with opt-in +support for a number of unreleased features from the [TOML master] and some sane cherry-picks from the +[TOML issues list] where the discussion strongly indicates inclusion in a near-future release. + +The library advertises the most recent numbered language version it fully supports via the preprocessor +defines `TOML_LANG_MAJOR`, `TOML_LANG_MINOR` and `TOML_LANG_PATCH`. + +### **Unreleased language features:** + +- [#516]: Allow newlines and trailing commas in inline tables +- [#562]: Allow hex floating-point values +- [#644]: Support `+` in key names +- [#671]: Local time of day format should support `09:30` as opposed to `09:30:00` +- [#687]: Relax bare key restrictions to allow additional unicode characters +- [#790]: Include an `\e` escape code sequence (shorthand for `\u001B`) +- [#796]: Include an `\xHH` escape code sequence +- [#891]: Allow non-English scripts for unquoted keys + +> ℹ️ _`#define TOML_ENABLE_UNRELEASED_FEATURES 1` to enable these features (see [Configuration](#Configuration))._ + +### 🔹️ **TOML v1.0.0:** + +All features supported, including: + +- [#356]: Allow leading zeros in the exponent part of a float +- [#567]: Control characters are not permitted in comments +- [#571]: Allow raw tabs inside strings +- [#665]: Make arrays heterogeneous +- [#766]: Allow comments before commas in arrays + +### 🔹️ **TOML v0.5.0:** + +All features supported. + +
+ +## Contributing + +Contributions are very welcome! Either by [reporting issues] or submitting pull requests. +If you wish to submit a pull request, please see [CONTRIBUTING] for all the details you need to get going. + +
+ +## License and Attribution + +toml++ is licensed under the terms of the MIT license - see [LICENSE]. + +UTF-8 decoding is performed using a state machine based on Bjoern Hoehrmann's '[Flexible and Economical UTF-8 Decoder]'. + +### With thanks to: + +- **[@beastle9end](https://github.com/beastle9end)** - Made Windows.h include bypass +- **[@bjadamson](https://github.com/bjadamson)** - Reported some bugs and helped design a new feature +- **[@bobfang1992](https://github.com/bobfang1992)** - Reported a bug and created a [wrapper in python](https://github.com/bobfang1992/pytomlpp) +- **[@GiulioRomualdi](https://github.com/GiulioRomualdi)** - Added cmake+meson support +- **[@jonestristand](https://github.com/jonestristand)** - Designed and implemented the `toml::path`s feature +- **[@kcsaul](https://github.com/kcsaul)** - Fixed a bug +- **[@levicki](https://github.com/levicki)** - Helped design some new features +- **[@moorereason](https://github.com/moorereason)** - Reported a whole bunch of bugs +- **[@mosra](https://github.com/mosra)** - Created the awesome [m.css] used to generate the API docs +- **[@ned14](https://github.com/ned14)** - Reported a bunch of bugs and helped design some new features +- **[@okureta](https://github.com/okureta)** - Reported a bug +- **[@prince-chrismc](https://github.com/prince-chrismc)** - Added toml++ to ConanCenter, and fixed some typos +- **[@rbrugo](https://github.com/rbrugo)** - Helped design a new feature +- **[@Reedbeta](https://github.com/Reedbeta)** - Fixed a bug and added additional Visual Studio debugger native visualizers +- **[@Ryan-rsm-McKenzie](https://github.com/Ryan-rsm-McKenzie)** - Add natvis file to cmake install script +- **[@shdnx](https://github.com/shdnx)** - Fixed a bug on GCC 8.2.0 and some meson config issues +- **[@sneves](https://github.com/sneves)** - Helped fix a number of parser bugs +- **[@sobczyk](https://github.com/sobczyk)** - Reported some bugs +- **[@std-any-emplace](https://github.com/std-any-emplace)** - Reported some bugs +- **[@Tachi107](https://github.com/Tachi107)** - Made some tweaks to meson.build, added compile_library build option +- **[@traversaro](https://github.com/traversaro)** - Added vcpkg support and reported a bunch of bugs +- **[@whiterabbit963](https://github.com/whiterabbit963)** - Fixed a bug with value_or conversions +- **[@ximion](https://github.com/ximion)** - Added support for installation with meson +- **[@a-is](https://github.com/a-is)** - Fixed a bug + +
+ +## 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) +- LinkedIn: [marzer](https://www.linkedin.com/in/marzer/) + +[API documentation]: https://marzer.github.io/tomlplusplus/ +[homepage]: https://marzer.github.io/tomlplusplus/ +[unreleased TOML language features]: #unreleased-language-features +[most recently-released version]: https://github.com/toml-lang/toml/releases +[char8_t]: https://en.cppreference.com/w/cpp/keyword/char8_t +[TOML]: https://toml.io/ +[TOML master]: https://github.com/toml-lang/toml/blob/master/README.md +[TOML issues list]: https://github.com/toml-lang/toml/issues +[v1.0.0]: https://toml.io/en/v1.0.0 +[CONTRIBUTING]: ./CONTRIBUTING.md +[LICENSE]: ./LICENSE +[Flexible and Economical UTF-8 Decoder]: http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ +[cpp_compilers]: https://en.cppreference.com/w/cpp/compiler_support +[reporting issues]: https://github.com/marzer/tomlplusplus/issues/new/choose +[issues]: https://github.com/marzer/tomlplusplus/issues +[#356]: https://github.com/toml-lang/toml/issues/356 +[#516]: https://github.com/toml-lang/toml/issues/516 +[#562]: https://github.com/toml-lang/toml/issues/562 +[#567]: https://github.com/toml-lang/toml/issues/567 +[#571]: https://github.com/toml-lang/toml/issues/571 +[#644]: https://github.com/toml-lang/toml/issues/644 +[#665]: https://github.com/toml-lang/toml/issues/665 +[#671]: https://github.com/toml-lang/toml/issues/671 +[#687]: https://github.com/toml-lang/toml/issues/687 +[#766]: https://github.com/toml-lang/toml/issues/766 +[#790]: https://github.com/toml-lang/toml/pull/790 +[#796]: https://github.com/toml-lang/toml/pull/796 +[#891]: https://github.com/toml-lang/toml/pull/891 +[something better than std::optional]: https://github.com/TartanLlama/optional +[m.css]: https://mcss.mosra.cz/documentation/doxygen +[`toml.hpp`]: https://raw.githubusercontent.com/marzer/tomlplusplus/master/toml.hpp diff --git a/build-config/tomlpp/vendor/include/meson.build b/build-config/tomlpp/vendor/include/meson.build new file mode 100644 index 0000000..206dc6f --- /dev/null +++ b/build-config/tomlpp/vendor/include/meson.build @@ -0,0 +1,52 @@ +# 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 + +include_dir = include_directories('.') + +if not is_subproject + install_subdir('toml++', install_dir: get_option('includedir')) +endif + +if not build_lib # header-only mode + + tomlplusplus_dep = declare_dependency(include_directories: include_dir) + + if not is_subproject + import('pkgconfig').generate( + name: meson.project_name(), + description: 'Header-only TOML config file parser and serializer for C++', + install_dir: get_option('datadir')/'pkgconfig', + url: 'https://marzer.github.io/tomlplusplus' + ) + endif + + # cmake + if get_option('generate_cmake_config') and not is_subproject and not is_devel + cmake = import('cmake') + # Can't use until Meson 0.62.0, see https://github.com/mesonbuild/meson/pull/9916 + # and https://github.com/marzer/tomlplusplus/issues/140 + #cmake.write_basic_package_version_file( + # name: meson.project_name(), + # version: meson.project_version(), + # install_dir: get_option('datadir')/'cmake'/meson.project_name(), + # arch_independent: true + #) + # In the meantime, install a pre-generated Package Version file + configure_file( + configuration: {'version': meson.project_version()}, + input: '..'/'cmake'/'tomlplusplusConfigVersion.cmake.meson.in', + output: 'tomlplusplusConfigVersion.cmake', + install_dir: get_option('datadir')/'cmake'/meson.project_name() + ) + + cmake.configure_package_config_file( + name: meson.project_name(), + input: '..'/'cmake'/'tomlplusplusConfig.cmake.meson.in', + configuration: configuration_data({'includedir': get_option('includedir')}), + install_dir: get_option('datadir')/'cmake'/meson.project_name(), + ) + endif + +endif diff --git a/build-config/tomlpp/vendor/include/toml++/impl/array.hpp b/build-config/tomlpp/vendor/include/toml++/impl/array.hpp new file mode 100644 index 0000000..ad79379 --- /dev/null +++ b/build-config/tomlpp/vendor/include/toml++/impl/array.hpp @@ -0,0 +1,1790 @@ +//# 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 +#pragma once + +#include "std_utility.hpp" +#include "std_vector.hpp" +#include "std_initializer_list.hpp" +#include "value.hpp" +#include "make_node.hpp" +#include "header_start.hpp" + +#ifndef TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN +#if TOML_GCC && TOML_GCC <= 7 +#define TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN 1 +#else +#define TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN 0 +#endif +#endif + +#if TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN && !defined(TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_ACKNOWLEDGED) +#define TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_MESSAGE \ + "If you're seeing this error it's because you're using one of toml++'s for_each() functions on a compiler with " \ + "known bugs in that area (e.g. GCC 7). On these compilers returning a bool (or bool-convertible) value from the " \ + "for_each() callable causes spurious compilation failures, while returning nothing (void) works fine. " \ + "If you believe this message is incorrect for your compiler, you can try your luck by #defining " \ + "TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN as 0 and recompiling - if it works, great! Let me know at " \ + "https://github.com/marzer/tomlplusplus/issues. Alternatively, if you don't have any need for early-exiting from " \ + "for_each(), you can suppress this error by #defining TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_ACKNOWLEDGED " \ + "and moving on with your life." +#endif + +/// \cond +TOML_IMPL_NAMESPACE_START +{ + template + class TOML_TRIVIAL_ABI array_iterator + { + private: + template + friend class array_iterator; + + using mutable_vector_iterator = std::vector::iterator; + using const_vector_iterator = std::vector::const_iterator; + using vector_iterator = std::conditional_t; + + mutable vector_iterator iter_; + + public: + using value_type = std::conditional_t; + using reference = value_type&; + using pointer = value_type*; + using difference_type = ptrdiff_t; + using iterator_category = typename std::iterator_traits::iterator_category; + + TOML_NODISCARD_CTOR + array_iterator() noexcept = default; + + TOML_NODISCARD_CTOR + explicit array_iterator(mutable_vector_iterator iter) noexcept // + : iter_{ iter } + {} + + TOML_CONSTRAINED_TEMPLATE(C, bool C = IsConst) + TOML_NODISCARD_CTOR + explicit array_iterator(const_vector_iterator iter) noexcept // + : iter_{ iter } + {} + + TOML_CONSTRAINED_TEMPLATE(C, bool C = IsConst) + TOML_NODISCARD_CTOR + array_iterator(const array_iterator& other) noexcept // + : iter_{ other.iter_ } + {} + + TOML_NODISCARD_CTOR + array_iterator(const array_iterator&) noexcept = default; + + array_iterator& operator=(const array_iterator&) noexcept = default; + + array_iterator& operator++() noexcept // ++pre + { + ++iter_; + return *this; + } + + array_iterator operator++(int) noexcept // post++ + { + array_iterator out{ iter_ }; + ++iter_; + return out; + } + + array_iterator& operator--() noexcept // --pre + { + --iter_; + return *this; + } + + array_iterator operator--(int) noexcept // post-- + { + array_iterator out{ iter_ }; + --iter_; + return out; + } + + TOML_PURE_INLINE_GETTER + reference operator*() const noexcept + { + return *iter_->get(); + } + + TOML_PURE_INLINE_GETTER + pointer operator->() const noexcept + { + return iter_->get(); + } + + TOML_PURE_INLINE_GETTER + explicit operator const vector_iterator&() const noexcept + { + return iter_; + } + + TOML_CONSTRAINED_TEMPLATE(!C, bool C = IsConst) + TOML_PURE_INLINE_GETTER + explicit operator const const_vector_iterator() const noexcept + { + return iter_; + } + + array_iterator& operator+=(ptrdiff_t rhs) noexcept + { + iter_ += rhs; + return *this; + } + + array_iterator& operator-=(ptrdiff_t rhs) noexcept + { + iter_ -= rhs; + return *this; + } + + TOML_NODISCARD + friend array_iterator operator+(const array_iterator& lhs, ptrdiff_t rhs) noexcept + { + return array_iterator{ lhs.iter_ + rhs }; + } + + TOML_NODISCARD + friend array_iterator operator+(ptrdiff_t lhs, const array_iterator& rhs) noexcept + { + return array_iterator{ rhs.iter_ + lhs }; + } + + TOML_NODISCARD + friend array_iterator operator-(const array_iterator& lhs, ptrdiff_t rhs) noexcept + { + return array_iterator{ lhs.iter_ - rhs }; + } + + TOML_PURE_INLINE_GETTER + friend ptrdiff_t operator-(const array_iterator& lhs, const array_iterator& rhs) noexcept + { + return lhs.iter_ - rhs.iter_; + } + + TOML_PURE_INLINE_GETTER + friend bool operator==(const array_iterator& lhs, const array_iterator& rhs) noexcept + { + return lhs.iter_ == rhs.iter_; + } + + TOML_PURE_INLINE_GETTER + friend bool operator!=(const array_iterator& lhs, const array_iterator& rhs) noexcept + { + return lhs.iter_ != rhs.iter_; + } + + TOML_PURE_INLINE_GETTER + friend bool operator<(const array_iterator& lhs, const array_iterator& rhs) noexcept + { + return lhs.iter_ < rhs.iter_; + } + + TOML_PURE_INLINE_GETTER + friend bool operator<=(const array_iterator& lhs, const array_iterator& rhs) noexcept + { + return lhs.iter_ <= rhs.iter_; + } + + TOML_PURE_INLINE_GETTER + friend bool operator>(const array_iterator& lhs, const array_iterator& rhs) noexcept + { + return lhs.iter_ > rhs.iter_; + } + + TOML_PURE_INLINE_GETTER + friend bool operator>=(const array_iterator& lhs, const array_iterator& rhs) noexcept + { + return lhs.iter_ >= rhs.iter_; + } + + TOML_PURE_INLINE_GETTER + reference operator[](ptrdiff_t idx) const noexcept + { + return *(iter_ + idx)->get(); + } + }; + + struct array_init_elem + { + mutable node_ptr value; + + template + TOML_NODISCARD_CTOR + array_init_elem(T&& val, value_flags flags = preserve_source_value_flags) // + : value{ make_node(static_cast(val), flags) } + {} + }; +} +TOML_IMPL_NAMESPACE_END; +/// \endcond + +TOML_NAMESPACE_START +{ + /// \brief A RandomAccessIterator for iterating over elements in a toml::array. + using array_iterator = POXY_IMPLEMENTATION_DETAIL(impl::array_iterator); + + /// \brief A RandomAccessIterator for iterating over const elements in a toml::array. + using const_array_iterator = POXY_IMPLEMENTATION_DETAIL(impl::array_iterator); + + /// \brief A TOML array. + /// + /// \detail The interface of this type is modeled after std::vector, with some + /// additional considerations made for the heterogeneous nature of a + /// TOML array. + /// + /// \godbolt{sjK4da} + /// + /// \cpp + /// + /// toml::table tbl = toml::parse(R"( + /// arr = [1, 2, 3, 4, 'five'] + /// )"sv); + /// + /// // get the element as an array + /// toml::array& arr = *tbl.get_as("arr"); + /// std::cout << arr << "\n"; + /// + /// // increment each element with visit() + /// for (auto&& elem : arr) + /// { + /// elem.visit([](auto&& el) noexcept + /// { + /// if constexpr (toml::is_number) + /// (*el)++; + /// else if constexpr (toml::is_string) + /// el = "six"sv; + /// }); + /// } + /// std::cout << arr << "\n"; + /// + /// // add and remove elements + /// arr.push_back(7); + /// arr.push_back(8.0f); + /// arr.push_back("nine"sv); + /// arr.erase(arr.cbegin()); + /// std::cout << arr << "\n"; + /// + /// // emplace elements + /// arr.emplace_back("ten"); + /// arr.emplace_back(11, 12.0); + /// std::cout << arr << "\n"; + /// \ecpp + /// + /// \out + /// [ 1, 2, 3, 4, 'five' ] + /// [ 2, 3, 4, 5, 'six' ] + /// [ 3, 4, 5, 'six', 7, 8.0, 'nine' ] + /// [ 3, 4, 5, 'six', 7, 8.0, 'nine', 'ten', [ 11, 12.0 ] ] + /// \eout + class TOML_EXPORTED_CLASS array : public node + { + private: + /// \cond + + using vector_type = std::vector; + using vector_iterator = typename vector_type::iterator; + using const_vector_iterator = typename vector_type::const_iterator; + vector_type elems_; + + TOML_NODISCARD_CTOR + TOML_EXPORTED_MEMBER_FUNCTION + array(const impl::array_init_elem*, const impl::array_init_elem*); + + TOML_NODISCARD_CTOR + array(std::false_type, std::initializer_list elems) // + : array{ elems.begin(), elems.end() } + {} + + TOML_EXPORTED_MEMBER_FUNCTION + void preinsertion_resize(size_t idx, size_t count); + + TOML_EXPORTED_MEMBER_FUNCTION + void insert_at_back(impl::node_ptr&&); + + TOML_EXPORTED_MEMBER_FUNCTION + vector_iterator insert_at(const_vector_iterator, impl::node_ptr&&); + + template + void emplace_back_if_not_empty_view(T&& val, value_flags flags) + { + if constexpr (is_node_view) + { + if (!val) + return; + } + insert_at_back(impl::make_node(static_cast(val), flags)); + } + + TOML_NODISCARD + TOML_EXPORTED_MEMBER_FUNCTION + size_t total_leaf_count() const noexcept; + + TOML_EXPORTED_MEMBER_FUNCTION + void flatten_child(array&& child, size_t& dest_index) noexcept; + + /// \endcond + + public: + using value_type = node; + using size_type = size_t; + using difference_type = ptrdiff_t; + using reference = node&; + using const_reference = const node&; + + /// \brief Default constructor. + TOML_NODISCARD_CTOR + TOML_EXPORTED_MEMBER_FUNCTION + array() noexcept; + + TOML_EXPORTED_MEMBER_FUNCTION + ~array() noexcept; + + /// \brief Copy constructor. + TOML_NODISCARD_CTOR + TOML_EXPORTED_MEMBER_FUNCTION + array(const array&); + + /// \brief Move constructor. + TOML_NODISCARD_CTOR + TOML_EXPORTED_MEMBER_FUNCTION + array(array&& other) noexcept; + + /// \brief Constructs an array with one or more initial elements. + /// + /// \detail \cpp + /// auto arr = toml::array{ 1, 2.0, "three"sv, toml::array{ 4, 5 } }; + /// std::cout << arr << "\n"; + /// \ecpp + /// + /// \out + /// [ 1, 2.0, 'three', [ 4, 5 ] ] + /// \eout + /// + /// \remark \parblock If you need to construct an array with one child array element, the array's move constructor + /// will take precedence and perform a move-construction instead. You can use toml::inserter to + /// suppress this behaviour: \cpp + /// // desired result: [ [ 42 ] ] + /// auto bad = toml::array{ toml::array{ 42 } } + /// auto good = toml::array{ toml::inserter{ toml::array{ 42 } } } + /// std::cout << "bad: " << bad << "\n"; + /// std::cout << "good:" << good << "\n"; + /// \ecpp + /// + /// \out + /// bad: [ 42 ] + /// good: [ [ 42 ] ] + /// \eout + /// + /// \endparblock + /// + /// \tparam ElemType One of the TOML node or value types (or a type promotable to one). + /// \tparam ElemTypes One of the TOML node or value types (or a type promotable to one). + /// \param val The node or value used to initialize element 0. + /// \param vals The nodes or values used to initialize elements 1...N. + TOML_CONSTRAINED_TEMPLATE((sizeof...(ElemTypes) > 0 || !std::is_same_v, array>), + typename ElemType, + typename... ElemTypes) + TOML_NODISCARD_CTOR + explicit array(ElemType&& val, ElemTypes&&... vals) + : array{ std::false_type{}, + std::initializer_list{ static_cast(val), + static_cast(vals)... } } + {} + + /// \brief Copy-assignment operator. + TOML_EXPORTED_MEMBER_FUNCTION + array& operator=(const array&); + + /// \brief Move-assignment operator. + TOML_EXPORTED_MEMBER_FUNCTION + array& operator=(array&& rhs) noexcept; + + /// \name Type checks + /// @{ + + /// \brief Returns #toml::node_type::array. + TOML_CONST_INLINE_GETTER + node_type type() const noexcept final + { + return node_type::array; + } + + TOML_PURE_GETTER + TOML_EXPORTED_MEMBER_FUNCTION + bool is_homogeneous(node_type ntype) const noexcept final; + + TOML_PURE_GETTER + TOML_EXPORTED_MEMBER_FUNCTION + bool is_homogeneous(node_type ntype, node*& first_nonmatch) noexcept final; + + TOML_PURE_GETTER + TOML_EXPORTED_MEMBER_FUNCTION + bool is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept final; + + /// \cond + template + TOML_PURE_GETTER + bool is_homogeneous() const noexcept + { + using type = impl::remove_cvref>; + static_assert(std::is_void_v || toml::is_value || toml::is_container, + "The template type argument of array::is_homogeneous() must be void or one " + "of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); + + return is_homogeneous(impl::node_type_of); + } + /// \endcond + + /// \brief Returns `false`. + TOML_CONST_INLINE_GETTER + bool is_table() const noexcept final + { + return false; + } + + /// \brief Returns `true`. + TOML_CONST_INLINE_GETTER + bool is_array() const noexcept final + { + return true; + } + + /// \brief Returns `true` if the array contains only tables. + TOML_PURE_GETTER + bool is_array_of_tables() const noexcept final + { + return is_homogeneous(node_type::table); + } + + /// \brief Returns `false`. + TOML_CONST_INLINE_GETTER + bool is_value() const noexcept final + { + return false; + } + + /// \brief Returns `false`. + TOML_CONST_INLINE_GETTER + bool is_string() const noexcept final + { + return false; + } + + /// \brief Returns `false`. + TOML_CONST_INLINE_GETTER + bool is_integer() const noexcept final + { + return false; + } + + /// \brief Returns `false`. + TOML_CONST_INLINE_GETTER + bool is_floating_point() const noexcept final + { + return false; + } + + /// \brief Returns `false`. + TOML_CONST_INLINE_GETTER + bool is_number() const noexcept final + { + return false; + } + + /// \brief Returns `false`. + TOML_CONST_INLINE_GETTER + bool is_boolean() const noexcept final + { + return false; + } + + /// \brief Returns `false`. + TOML_CONST_INLINE_GETTER + bool is_date() const noexcept final + { + return false; + } + + /// \brief Returns `false`. + TOML_CONST_INLINE_GETTER + bool is_time() const noexcept final + { + return false; + } + + /// \brief Returns `false`. + TOML_CONST_INLINE_GETTER + bool is_date_time() const noexcept final + { + return false; + } + + /// @} + + /// \name Type casts + /// @{ + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + table* as_table() noexcept final + { + return nullptr; + } + + /// \brief Returns a pointer to the array. + TOML_CONST_INLINE_GETTER + array* as_array() noexcept final + { + return this; + } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + toml::value* as_string() noexcept final + { + return nullptr; + } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + toml::value* as_integer() noexcept final + { + return nullptr; + } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + toml::value* as_floating_point() noexcept final + { + return nullptr; + } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + toml::value* as_boolean() noexcept final + { + return nullptr; + } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + toml::value* as_date() noexcept final + { + return nullptr; + } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + toml::value