mirror of
https://github.com/marzer/tomlplusplus.git
synced 2024-09-15 15:13:21 +00:00
Path (#156)
This commit is contained in:
parent
39b80f6c56
commit
65d4b84710
@ -20,6 +20,8 @@ template:
|
|||||||
|
|
||||||
#### Additions:
|
#### Additions:
|
||||||
- Added value type deduction to `emplace()` methods
|
- Added value type deduction to `emplace()` methods
|
||||||
|
- Added toml::path type to parse and manipulate a path to a node in a toml::table
|
||||||
|
- Added at_path overloads to accept toml::path
|
||||||
|
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
|
@ -257,6 +257,7 @@ UTF-8 decoding is performed using a state machine based on Bjoern Hoehrmann's '[
|
|||||||
- **[@bjadamson](https://github.com/bjadamson)** - Reported some bugs and helped design a new feature
|
- **[@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)
|
- **[@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
|
- **[@GiulioRomualdi](https://github.com/GiulioRomualdi)** - Added cmake+meson support
|
||||||
|
- **[@jonestristand](https://github.com/jonestristand)** - Designed and implemented the `toml::path`s feature
|
||||||
- **[@levicki](https://github.com/levicki)** - Helped design some new features
|
- **[@levicki](https://github.com/levicki)** - Helped design some new features
|
||||||
- **[@moorereason](https://github.com/moorereason)** - Reported a whole bunch of bugs
|
- **[@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
|
- **[@mosra](https://github.com/mosra)** - Created the awesome [m.css] used to generate the API docs
|
||||||
|
@ -57,6 +57,57 @@ TOML_NAMESPACE_START
|
|||||||
TOML_EXPORTED_FREE_FUNCTION
|
TOML_EXPORTED_FREE_FUNCTION
|
||||||
node_view<const node> at_path(const node& root, std::string_view path) noexcept;
|
node_view<const node> at_path(const node& root, std::string_view path) noexcept;
|
||||||
|
|
||||||
|
/// \brief Returns a view of the node matching a fully-qualified "TOML path".
|
||||||
|
///
|
||||||
|
/// \detail \cpp
|
||||||
|
/// auto config = toml::parse(R"(
|
||||||
|
///
|
||||||
|
/// [foo]
|
||||||
|
/// bar = [ 0, 1, 2, [ 3 ], { kek = 4 } ]
|
||||||
|
///
|
||||||
|
/// )"sv);
|
||||||
|
///
|
||||||
|
/// toml::path path1("foo.bar[2]");
|
||||||
|
/// toml::path path2("foo.bar[4].kek");
|
||||||
|
/// std::cout << toml::at_path(config, path1) << "\n";
|
||||||
|
/// std::cout << toml::at_path(config, path1.parent_path()) << "\n";
|
||||||
|
/// std::cout << toml::at_path(config, path2) << "\n";
|
||||||
|
/// std::cout << toml::at_path(config, path2.parent_path()) << "\n";
|
||||||
|
/// \ecpp
|
||||||
|
///
|
||||||
|
/// \out
|
||||||
|
/// 2
|
||||||
|
/// [ 0, 1, 2, [ 3 ], { kek = 4 } ]
|
||||||
|
/// 4
|
||||||
|
/// { kek = 4 }
|
||||||
|
/// \eout
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \note Keys in paths are interpreted literally, so whitespace (or lack thereof) matters:
|
||||||
|
/// \cpp
|
||||||
|
/// toml::at_path(config, toml::path("foo.bar")) // same as config["foo"]["bar"]
|
||||||
|
/// toml::at_path(config, toml::path("foo. bar")) // same as config["foo"][" bar"]
|
||||||
|
/// toml::at_path(config, toml::path("foo..bar")) // same as config["foo"][""]["bar"]
|
||||||
|
/// toml::at_path(config, toml::path(".foo.bar")) // same as config[""]["foo"]["bar"]
|
||||||
|
/// \ecpp
|
||||||
|
/// <br>
|
||||||
|
/// Additionally, TOML allows '.' (period) characters to appear in keys if they are quoted strings.
|
||||||
|
/// This function makes no allowance for this, instead treating all period characters as sub-table delimiters.
|
||||||
|
///
|
||||||
|
/// \param root The root node from which the path will be traversed.
|
||||||
|
/// \param path The "TOML path" to traverse.
|
||||||
|
TOML_NODISCARD
|
||||||
|
TOML_EXPORTED_FREE_FUNCTION
|
||||||
|
node_view<node> at_path(node & root, const toml::path& path) noexcept;
|
||||||
|
|
||||||
|
/// \brief Returns a const view of the node matching a fully-qualified "TOML path".
|
||||||
|
///
|
||||||
|
/// \see #toml::at_path(node&, const toml::path& path)
|
||||||
|
TOML_NODISCARD
|
||||||
|
TOML_EXPORTED_FREE_FUNCTION
|
||||||
|
node_view<const node> at_path(const node& root, const toml::path& path) noexcept;
|
||||||
|
|
||||||
|
|
||||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||||
|
|
||||||
/// \brief Returns a view of the node matching a fully-qualified "TOML path".
|
/// \brief Returns a view of the node matching a fully-qualified "TOML path".
|
||||||
|
@ -70,7 +70,9 @@ TOML_ANON_NAMESPACE_START
|
|||||||
#if TOML_INT_CHARCONV
|
#if TOML_INT_CHARCONV
|
||||||
|
|
||||||
auto fc_result = std::from_chars(index_str.data(), index_str.data() + index_str.length(), index);
|
auto fc_result = std::from_chars(index_str.data(), index_str.data() + index_str.length(), index);
|
||||||
if (fc_result.ec != std::errc{})
|
|
||||||
|
// If not able to parse, or entire index not parseable, then fail (otherwise would allow a[1bc] == a[1]
|
||||||
|
if (fc_result.ec != std::errc{} || fc_result.ptr != index_str.data() + index_str.length())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@ -174,6 +176,48 @@ TOML_ANON_NAMESPACE_START
|
|||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TOML_INTERNAL_LINKAGE
|
||||||
|
node* get_at_path(node & root, const toml::path& path)
|
||||||
|
{
|
||||||
|
if (root.is_value()) // values don't have child nodes
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// special check if table has a key that is an empty string, and the path is empty,
|
||||||
|
// return the node at that empty key.
|
||||||
|
if (path.size() == 0 && root.is_table() && root.as_table()->contains(""))
|
||||||
|
return root.as_table()->get("");
|
||||||
|
|
||||||
|
node* current = &root;
|
||||||
|
|
||||||
|
for (const auto& component: path)
|
||||||
|
{
|
||||||
|
auto type = component.type;
|
||||||
|
if (type == path_component_type::array_index && std::holds_alternative<size_t>(component.value))
|
||||||
|
{
|
||||||
|
const auto current_array = current->as<array>();
|
||||||
|
if (!current_array)
|
||||||
|
return nullptr; // not an array, using array index doesn't work
|
||||||
|
|
||||||
|
current = current_array->get(std::get<size_t>(component.value));
|
||||||
|
}
|
||||||
|
else if (type == path_component_type::key && std::holds_alternative<std::string>(component.value))
|
||||||
|
{
|
||||||
|
const auto current_table = current->as<table>();
|
||||||
|
if (!current_table)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
current = current_table->get(std::get<std::string>(component.value));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Error: invalid component
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||||
|
|
||||||
TOML_INTERNAL_LINKAGE
|
TOML_INTERNAL_LINKAGE
|
||||||
@ -206,6 +250,19 @@ TOML_NAMESPACE_START
|
|||||||
return node_view<const node>{ TOML_ANON_NAMESPACE::get_at_path(const_cast<node&>(root), path) };
|
return node_view<const node>{ TOML_ANON_NAMESPACE::get_at_path(const_cast<node&>(root), path) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
node_view<node> at_path(node & root, const toml::path& path) noexcept
|
||||||
|
{
|
||||||
|
return node_view<node>{ TOML_ANON_NAMESPACE::get_at_path(root, path) };
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
node_view<const node> at_path(const node& root, const toml::path& path) noexcept
|
||||||
|
{
|
||||||
|
return node_view<const node>{ TOML_ANON_NAMESPACE::get_at_path(const_cast<node&>(root), path) };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||||
|
|
||||||
TOML_EXTERNAL_LINKAGE
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
@ -95,6 +95,8 @@ TOML_NAMESPACE_START
|
|||||||
template <typename>
|
template <typename>
|
||||||
class value;
|
class value;
|
||||||
|
|
||||||
|
class path;
|
||||||
|
|
||||||
class toml_formatter;
|
class toml_formatter;
|
||||||
class json_formatter;
|
class json_formatter;
|
||||||
class yaml_formatter;
|
class yaml_formatter;
|
||||||
|
@ -1005,6 +1005,54 @@ TOML_NAMESPACE_START
|
|||||||
TOML_EXPORTED_MEMBER_FUNCTION
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
node_view<const node> at_path(std::string_view path) const noexcept;
|
node_view<const node> at_path(std::string_view path) const noexcept;
|
||||||
|
|
||||||
|
/// \brief Returns a view of the subnode matching a fully-qualified "TOML path".
|
||||||
|
///
|
||||||
|
/// \detail \cpp
|
||||||
|
/// auto config = toml::parse(R"(
|
||||||
|
///
|
||||||
|
/// [foo]
|
||||||
|
/// bar = [ 0, 1, 2, [ 3 ], { kek = 4 } ]
|
||||||
|
///
|
||||||
|
/// )"sv);
|
||||||
|
///
|
||||||
|
/// toml::path path1("foo.bar[2]");
|
||||||
|
/// toml::path path2("foo.bar[4].kek");
|
||||||
|
/// std::cout << config.at_path(path1) << "\n";
|
||||||
|
/// std::cout << config.at_path(path1.parent_path()) << "\n";
|
||||||
|
/// std::cout << config.at_path(path2) << "\n";
|
||||||
|
/// std::cout << config.at_path(path2.parent_path()) << "\n";
|
||||||
|
///
|
||||||
|
/// \out
|
||||||
|
/// 2
|
||||||
|
/// [ 0, 1, 2, [ 3 ], { kek = 4 } ]
|
||||||
|
/// 4
|
||||||
|
/// { kek = 4 }
|
||||||
|
/// \eout
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \note Keys in paths are interpreted literally, so whitespace (or lack thereof) matters:
|
||||||
|
/// \cpp
|
||||||
|
/// config.at_path(toml::path("foo.bar")) // same as node_view{ config }["foo"]["bar"]
|
||||||
|
/// config.at_path(toml::path("foo. bar")) // same as node_view{ config }["foo"][" bar"]
|
||||||
|
/// config.at_path(toml::path("foo..bar")) // same as node_view{ config }["foo"][""]["bar"]
|
||||||
|
/// config.at_path(toml::path(".foo.bar")) // same as node_view{ config }[""]["foo"]["bar"]
|
||||||
|
/// \ecpp
|
||||||
|
/// <br>
|
||||||
|
/// Additionally, TOML allows '.' (period) characters to appear in keys if they are quoted strings.
|
||||||
|
/// This function makes no allowance for this, instead treating all period characters as sub-table delimiters.
|
||||||
|
///
|
||||||
|
/// \param path The "TOML path" to traverse.
|
||||||
|
TOML_NODISCARD
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
node_view<node> at_path(const toml::path& path) noexcept;
|
||||||
|
|
||||||
|
/// \brief Returns a const view of the subnode matching a fully-qualified "TOML path".
|
||||||
|
///
|
||||||
|
/// \see #at_path(const toml::path& path)
|
||||||
|
TOML_NODISCARD
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
node_view<const node> at_path(const toml::path& path) const noexcept;
|
||||||
|
|
||||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||||
|
|
||||||
/// \brief Returns a view of the subnode matching a fully-qualified "TOML path".
|
/// \brief Returns a view of the subnode matching a fully-qualified "TOML path".
|
||||||
|
@ -71,6 +71,18 @@ TOML_NAMESPACE_START
|
|||||||
return toml::at_path(*this, path);
|
return toml::at_path(*this, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
node_view<node> node::at_path(const toml::path& path) noexcept
|
||||||
|
{
|
||||||
|
return toml::at_path(*this, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
node_view<const node> node::at_path(const toml::path& path) const noexcept
|
||||||
|
{
|
||||||
|
return toml::at_path(*this, path);
|
||||||
|
}
|
||||||
|
|
||||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||||
|
|
||||||
TOML_EXTERNAL_LINKAGE
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
@ -710,6 +710,18 @@ TOML_NAMESPACE_START
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Returns a view of the selected subnode.
|
||||||
|
///
|
||||||
|
/// \param path A "TOML path" to the desired subnode
|
||||||
|
///
|
||||||
|
/// \returns A view of the selected node if this node represented a table and it contained a
|
||||||
|
/// value at the given key, or an empty view.
|
||||||
|
TOML_NODISCARD
|
||||||
|
node_view operator[](const toml::path& path) const noexcept
|
||||||
|
{
|
||||||
|
return node_ ? node_->at_path(path) : node_view{};
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Returns a view of the subnode matching a fully-qualified "TOML path".
|
/// \brief Returns a view of the subnode matching a fully-qualified "TOML path".
|
||||||
///
|
///
|
||||||
/// \see #toml::node::at_path(std::string_view)
|
/// \see #toml::node::at_path(std::string_view)
|
||||||
@ -719,6 +731,15 @@ TOML_NAMESPACE_START
|
|||||||
return node_ ? node_->at_path(path) : node_view{};
|
return node_ ? node_->at_path(path) : node_view{};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Returns a view of the subnode matching a fully-qualified "TOML path".
|
||||||
|
///
|
||||||
|
/// \see #toml::node::at_path(const toml::path&)
|
||||||
|
TOML_NODISCARD
|
||||||
|
node_view at_path(const toml::path& path) const noexcept
|
||||||
|
{
|
||||||
|
return node_ ? node_->at_path(path) : node_view{};
|
||||||
|
}
|
||||||
|
|
||||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||||
|
|
||||||
/// \brief Returns a view of the selected subnode.
|
/// \brief Returns a view of the selected subnode.
|
||||||
|
491
include/toml++/impl/path.h
Normal file
491
include/toml++/impl/path.h
Normal file
@ -0,0 +1,491 @@
|
|||||||
|
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||||
|
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||||
|
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "forward_declarations.h"
|
||||||
|
#include "std_vector.h"
|
||||||
|
#include "std_string.h"
|
||||||
|
#include "std_variant.h"
|
||||||
|
|
||||||
|
#include "header_start.h"
|
||||||
|
|
||||||
|
|
||||||
|
TOML_NAMESPACE_START
|
||||||
|
{
|
||||||
|
|
||||||
|
/// \brief Indicates type of path component, either a key, an index in an array, or invalid
|
||||||
|
enum class TOML_CLOSED_ENUM path_component_type : uint8_t
|
||||||
|
{
|
||||||
|
invalid = 0x0,
|
||||||
|
key = 0x1,
|
||||||
|
array_index = 0x2
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \brief Holds the value of a path component, either the name of the key in a string_view, or the index of an array as a size_t
|
||||||
|
using path_component_value = std::variant<std::string, size_t>;
|
||||||
|
|
||||||
|
/// \brief Represents a single component of a complete 'TOML-path': either a key or an array index
|
||||||
|
struct path_component
|
||||||
|
{
|
||||||
|
path_component_value value;
|
||||||
|
path_component_type type;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \brief A TOML path.
|
||||||
|
///
|
||||||
|
/// \detail This type parses and represents a path to a TOML node. It validates
|
||||||
|
/// the syntax of the path but does not ensure that the path refers to
|
||||||
|
/// a valid node in any particular TOML document. If parsing fails,
|
||||||
|
/// the object will evaluate as 'falsy', and will be empty.
|
||||||
|
///
|
||||||
|
/// \cpp
|
||||||
|
/// toml::path the_path("animals.cats[1]");
|
||||||
|
///
|
||||||
|
/// // can use with tbl.at_path or operator[]
|
||||||
|
/// std::cout << "second cat: " << tbl[the_path] << "\n";
|
||||||
|
/// std::cout << "cats: " << tbl.at_path(the_path.parent_path()) << "\n";
|
||||||
|
/// \ecpp
|
||||||
|
///
|
||||||
|
/// \out
|
||||||
|
/// second cat: lion
|
||||||
|
/// cats: ['tiger', 'lion', 'puma']
|
||||||
|
/// \eout
|
||||||
|
class TOML_EXPORTED_CLASS path
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/// \cond
|
||||||
|
|
||||||
|
bool parse_error_ = false;
|
||||||
|
|
||||||
|
std::vector<path_component> components_;
|
||||||
|
|
||||||
|
std::vector<path_component> parse_(std::string_view, bool& parse_success);
|
||||||
|
|
||||||
|
/// \endcond
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// \brief Default constructor.
|
||||||
|
TOML_NODISCARD_CTOR
|
||||||
|
path() noexcept = default;
|
||||||
|
|
||||||
|
/// \brief Construct from string
|
||||||
|
TOML_NODISCARD_CTOR
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
explicit path(std::string_view);
|
||||||
|
|
||||||
|
/// \brief Default destructor.
|
||||||
|
~path() noexcept = default;
|
||||||
|
|
||||||
|
/// \brief Copy constructor.
|
||||||
|
TOML_NODISCARD_CTOR
|
||||||
|
path(const path& other) = default;
|
||||||
|
|
||||||
|
/// \brief Move constructor.
|
||||||
|
TOML_NODISCARD_CTOR
|
||||||
|
path(path&& other) noexcept = default;
|
||||||
|
|
||||||
|
/// \brief Copy-assignment operator.
|
||||||
|
path& operator=(const path&) = default;
|
||||||
|
|
||||||
|
/// \brief Move-assignment operator.
|
||||||
|
path& operator=(path&&) = default;
|
||||||
|
|
||||||
|
/// \brief Append operator.
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
path& operator/=(path&&) noexcept;
|
||||||
|
|
||||||
|
/// \brief Append operator.
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
path& operator/=(std::string_view);
|
||||||
|
|
||||||
|
/// \brief Append operator.
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
path& operator+=(path&&) noexcept;
|
||||||
|
|
||||||
|
/// \brief Append operator.
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
path& operator+=(std::string_view);
|
||||||
|
|
||||||
|
TOML_NODISCARD
|
||||||
|
/// \brief Append a path to the current path
|
||||||
|
inline path operator+(const toml::path& rhs) const
|
||||||
|
{
|
||||||
|
toml::path result = { *this };
|
||||||
|
result.append(rhs);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_NODISCARD
|
||||||
|
/// \brief Append a path to the current path
|
||||||
|
inline path operator/(const toml::path& rhs) const
|
||||||
|
{
|
||||||
|
return *this + rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Evaluate whether path parsing succeeded
|
||||||
|
TOML_NODISCARD
|
||||||
|
explicit inline operator bool() const noexcept
|
||||||
|
{
|
||||||
|
return !parse_error_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \brief Implicitly cast to a std::string
|
||||||
|
TOML_NODISCARD
|
||||||
|
inline operator std::string() const { return string(); }
|
||||||
|
|
||||||
|
/// \brief Evaluate whether two paths are the same
|
||||||
|
TOML_NODISCARD
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
bool operator==(const path& compare) const noexcept;
|
||||||
|
|
||||||
|
/// \brief Evaluate whether two paths are the same
|
||||||
|
TOML_NODISCARD
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
bool operator==(std::string_view compare) const noexcept;
|
||||||
|
|
||||||
|
/// \brief Evaluate whether two paths are the same
|
||||||
|
TOML_NODISCARD
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
bool operator==(const char* compare) const noexcept;
|
||||||
|
|
||||||
|
/// \brief Evaluate whether two paths are different
|
||||||
|
TOML_NODISCARD
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
bool operator!=(const path& compare) const noexcept;
|
||||||
|
|
||||||
|
/// \brief Evaluate whether two paths are different
|
||||||
|
TOML_NODISCARD
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
bool operator!=(std::string_view compare) const noexcept;
|
||||||
|
|
||||||
|
/// \brief Evaluate whether two paths are different
|
||||||
|
TOML_NODISCARD
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
bool operator!=(const char* compare) const noexcept;
|
||||||
|
|
||||||
|
/// \brief Fetch a path component by index for modification
|
||||||
|
TOML_NODISCARD
|
||||||
|
inline path_component& operator[](size_t index) noexcept
|
||||||
|
{
|
||||||
|
return components_[index];
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \brief Fetch a path component by index
|
||||||
|
TOML_NODISCARD
|
||||||
|
inline const path_component& operator[](size_t index) const noexcept
|
||||||
|
{
|
||||||
|
return components_[index];
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \brief Number of components in the path
|
||||||
|
TOML_NODISCARD
|
||||||
|
inline size_t size() const noexcept
|
||||||
|
{
|
||||||
|
return components_.size();
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \brief Whether (true) or not (false) the path is empty
|
||||||
|
TOML_NODISCARD
|
||||||
|
inline bool empty() const { return size() <= 0; }
|
||||||
|
|
||||||
|
/// \brief Erases the contents of the path
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
void clear() noexcept;
|
||||||
|
|
||||||
|
TOML_NODISCARD
|
||||||
|
/// \brief Iterator at the start of the vector of path components (see #path_component)
|
||||||
|
inline auto begin() const noexcept { return components_.begin(); }
|
||||||
|
|
||||||
|
TOML_NODISCARD
|
||||||
|
/// \brief Iterator at the end of the vector of path components (see #path_component)
|
||||||
|
inline auto end() const noexcept { return components_.end(); }
|
||||||
|
|
||||||
|
/// \brief Removes the number of terminal path components specified by n
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
path& truncate(size_t n);
|
||||||
|
|
||||||
|
/// \brief Returns a toml::path object which has had n terminal path components removed
|
||||||
|
TOML_NODISCARD
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
path truncated(size_t n) const;
|
||||||
|
|
||||||
|
/// \brief Returns a toml::path object representing the path of the parent node
|
||||||
|
TOML_NODISCARD
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
path parent_path() const;
|
||||||
|
|
||||||
|
/// \brief Returns a toml::path object representing terminal n-parts of a TOML path
|
||||||
|
TOML_NODISCARD
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
path leaf(size_t n = 1) const;
|
||||||
|
|
||||||
|
/// \brief Returns a toml::path object that is a specified subpath of the current path, representing the
|
||||||
|
/// range of path components from [start, end).
|
||||||
|
TOML_NODISCARD
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
path subpath(std::vector<path_component>::const_iterator start,
|
||||||
|
std::vector<path_component>::const_iterator end) const;
|
||||||
|
|
||||||
|
/// \brief Returns a toml::path object that is a specified subpath of the current path, representing the
|
||||||
|
/// range of path components with indexes from [start, start + length].
|
||||||
|
TOML_NODISCARD
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
path subpath(size_t start, size_t length) const;
|
||||||
|
|
||||||
|
/// \brief Appends elements to the end of the TOML path
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
path& append(const toml::path&);
|
||||||
|
|
||||||
|
/// \brief Appends elements to the end of the TOML path
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
path& append(toml::path&&);
|
||||||
|
|
||||||
|
/// \brief Appends elements to the end of the TOML path
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
path& append(std::string_view);
|
||||||
|
|
||||||
|
/// \brief Prepends elements to the beginning of the TOML path
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
path& prepend(const toml::path&);
|
||||||
|
|
||||||
|
/// \brief Prepends elements to the beginning of the TOML path
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
path& prepend(toml::path&&);
|
||||||
|
|
||||||
|
/// \brief Prepends elements to the beginning of the TOML path
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
path& prepend(std::string_view);
|
||||||
|
|
||||||
|
/// \brief Replaces the contents of the path object by a new path
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
path& assign(std::string_view);
|
||||||
|
|
||||||
|
/// \brief Replaces the contents of the path object by a new path
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
path& assign(const path&);
|
||||||
|
|
||||||
|
/// \brief Returns a string representing the path
|
||||||
|
TOML_NODISCARD
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
std::string string() const;
|
||||||
|
|
||||||
|
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||||
|
|
||||||
|
/// \brief Construct from wstring
|
||||||
|
TOML_NODISCARD_CTOR
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
explicit path(std::wstring_view);
|
||||||
|
|
||||||
|
/// \brief Append operator
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
path& operator/=(std::wstring_view);
|
||||||
|
|
||||||
|
/// \brief Append operator.
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
path& operator+=(std::wstring_view);
|
||||||
|
|
||||||
|
/// \brief Implicitly cast to a std::wstring
|
||||||
|
TOML_NODISCARD
|
||||||
|
inline operator std::wstring() const
|
||||||
|
{
|
||||||
|
return wstring();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Evaluate whether two paths are the same
|
||||||
|
TOML_NODISCARD
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
bool operator==(std::wstring_view compare) const noexcept;
|
||||||
|
|
||||||
|
/// \brief Evaluate whether two paths are the same
|
||||||
|
TOML_NODISCARD
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
bool operator!=(std::wstring_view compare) const noexcept;
|
||||||
|
|
||||||
|
/// \brief Appends elements to the end of the TOML path
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
path& append(std::wstring_view);
|
||||||
|
|
||||||
|
/// \brief Prepends elements to the beginning of the TOML path
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
path& prepend(std::wstring_view);
|
||||||
|
|
||||||
|
/// \brief Replaces the contents of the path object by a new path
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
path& assign(std::wstring_view);
|
||||||
|
|
||||||
|
/// \brief Returns a wstring representing the path
|
||||||
|
TOML_NODISCARD
|
||||||
|
TOML_EXPORTED_MEMBER_FUNCTION
|
||||||
|
std::wstring wstring() const;
|
||||||
|
|
||||||
|
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||||
|
|
||||||
|
// === Hidden friend operators ========================================
|
||||||
|
/// \brief Writes the #toml::path out to the output stream in a human-readbale format
|
||||||
|
friend std::ostream& operator<<(std::ostream& os, const toml::path& rhs);
|
||||||
|
|
||||||
|
/// \brief Reads and parses a #toml::path from the input stream
|
||||||
|
friend std::istream& operator>>(std::istream& is, toml::path& rhs);
|
||||||
|
|
||||||
|
/// \brief Appends a string-formatted toml path to a #toml::path object
|
||||||
|
TOML_NODISCARD
|
||||||
|
friend path operator+(const toml::path& lhs, std::string_view rhs)
|
||||||
|
{
|
||||||
|
return lhs + toml::path(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Appends a c-string-formatted toml path to a #toml::path object
|
||||||
|
TOML_NODISCARD
|
||||||
|
friend path operator+(const toml::path& lhs, const char* rhs)
|
||||||
|
{
|
||||||
|
return lhs + toml::path(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Appends a #toml::path object to a string-formatted toml path
|
||||||
|
TOML_NODISCARD
|
||||||
|
friend path operator+(std::string_view lhs, const toml::path& rhs)
|
||||||
|
{
|
||||||
|
toml::path result = { rhs };
|
||||||
|
result.prepend(lhs);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Appends a #toml::path object to a c-string-formatted toml path
|
||||||
|
TOML_NODISCARD
|
||||||
|
friend path operator+(const char* lhs, const toml::path& rhs)
|
||||||
|
{
|
||||||
|
toml::path result = { rhs };
|
||||||
|
result.prepend(lhs);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Appends a string-formatted toml path to a #toml::path object
|
||||||
|
TOML_NODISCARD
|
||||||
|
friend path operator/(const toml::path& lhs, std::string_view rhs)
|
||||||
|
{
|
||||||
|
return lhs + rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Appends a c-string-formatted toml path to a #toml::path object
|
||||||
|
TOML_NODISCARD
|
||||||
|
friend path operator/(const toml::path& lhs, const char* rhs)
|
||||||
|
{
|
||||||
|
return lhs + toml::path(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Appends a #toml::path object to a string-formatted toml path
|
||||||
|
TOML_NODISCARD
|
||||||
|
friend path operator/(std::string_view lhs, const toml::path& rhs)
|
||||||
|
{
|
||||||
|
return lhs + rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Appends a #toml::path object to a c-string-formatted toml path
|
||||||
|
TOML_NODISCARD
|
||||||
|
friend path operator/(const char* lhs, const toml::path& rhs)
|
||||||
|
{
|
||||||
|
return lhs + rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||||
|
|
||||||
|
/// \brief Appends a wide-string-formatted toml path to a #toml::path object
|
||||||
|
TOML_NODISCARD
|
||||||
|
friend path operator+(const toml::path& lhs, std::wstring_view rhs)
|
||||||
|
{
|
||||||
|
return lhs + toml::path(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Appends a wchar_t-string-formatted toml path to a #toml::path object
|
||||||
|
TOML_NODISCARD
|
||||||
|
friend path operator+(const toml::path& lhs, const wchar_t* rhs)
|
||||||
|
{
|
||||||
|
return lhs + toml::path(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Appends a #toml::path object to a wide-string-formatted toml path
|
||||||
|
TOML_NODISCARD
|
||||||
|
friend path operator+(std::wstring_view lhs, const toml::path& rhs)
|
||||||
|
{
|
||||||
|
toml::path result = { rhs };
|
||||||
|
result.prepend(lhs);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Appends a #toml::path object to a wchar_t-string-formatted toml path
|
||||||
|
TOML_NODISCARD
|
||||||
|
friend path operator+(const wchar_t* lhs, const toml::path& rhs)
|
||||||
|
{
|
||||||
|
toml::path result = { rhs };
|
||||||
|
result.prepend(lhs);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Appends a wide-string-formatted toml path to a #toml::path object
|
||||||
|
TOML_NODISCARD
|
||||||
|
friend path operator/(const toml::path& lhs, std::wstring_view rhs)
|
||||||
|
{
|
||||||
|
return lhs + rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Appends a wchar_t-string-formatted toml path to a #toml::path object
|
||||||
|
TOML_NODISCARD
|
||||||
|
friend path operator/(const toml::path& lhs, const wchar_t* rhs)
|
||||||
|
{
|
||||||
|
return lhs + toml::path(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Appends a #toml::path object to a wide-string-formatted toml path
|
||||||
|
TOML_NODISCARD
|
||||||
|
friend path operator/(std::wstring_view lhs, const toml::path& rhs)
|
||||||
|
{
|
||||||
|
return lhs + rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Appends a #toml::path object to a wchar_t-string-formatted toml path
|
||||||
|
TOML_NODISCARD
|
||||||
|
friend path operator/(const wchar_t* lhs, const toml::path& rhs)
|
||||||
|
{
|
||||||
|
return lhs + rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
inline namespace literals
|
||||||
|
{
|
||||||
|
/// \brief Parses a TOML path from a string literal.
|
||||||
|
///
|
||||||
|
/// \detail \cpp
|
||||||
|
/// using namespace toml::literals;
|
||||||
|
///
|
||||||
|
/// auto path = "main.settings.devices[2]"_tpath;
|
||||||
|
/// std::cout << path.parent_path() << "\n";
|
||||||
|
/// \ecpp
|
||||||
|
///
|
||||||
|
/// \out
|
||||||
|
/// main.settings.devices
|
||||||
|
/// \eout
|
||||||
|
///
|
||||||
|
/// \param str The string data.
|
||||||
|
/// \param len The string length.
|
||||||
|
///
|
||||||
|
/// \returns A #toml::path generated from the string literal.
|
||||||
|
TOML_NODISCARD
|
||||||
|
inline toml::path operator"" _tpath(const char* str, size_t len)
|
||||||
|
{
|
||||||
|
return toml::path(std::string_view{ str, len });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TOML_NAMESPACE_END;
|
||||||
|
|
||||||
|
#include "header_end.h"
|
541
include/toml++/impl/path.inl
Normal file
541
include/toml++/impl/path.inl
Normal file
@ -0,0 +1,541 @@
|
|||||||
|
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||||
|
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||||
|
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
#pragma once
|
||||||
|
//# {{
|
||||||
|
#include "preprocessor.h"
|
||||||
|
#if !TOML_IMPLEMENTATION
|
||||||
|
#error This is an implementation-only header.
|
||||||
|
#endif
|
||||||
|
//# }}
|
||||||
|
|
||||||
|
#include "path.h"
|
||||||
|
|
||||||
|
TOML_DISABLE_WARNINGS;
|
||||||
|
#include <sstream>
|
||||||
|
#include <ostream>
|
||||||
|
#include <istream>
|
||||||
|
#if TOML_INT_CHARCONV
|
||||||
|
#include <charconv>
|
||||||
|
#endif
|
||||||
|
TOML_ENABLE_WARNINGS;
|
||||||
|
#include "header_start.h"
|
||||||
|
|
||||||
|
TOML_NAMESPACE_START
|
||||||
|
{
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
path::path(std::string_view path_str)
|
||||||
|
{
|
||||||
|
components_ = parse_(path_str, parse_error_);
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
path& path::operator/=(path&& rhs) noexcept
|
||||||
|
{
|
||||||
|
return append(std::move(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
path& path::operator/=(std::string_view source)
|
||||||
|
{
|
||||||
|
return append(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
path& path::operator+=(path&& rhs) noexcept
|
||||||
|
{
|
||||||
|
return append(std::move(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
path& path::operator+=(std::string_view source)
|
||||||
|
{
|
||||||
|
return append(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
bool path::operator==(const path& compare) const noexcept
|
||||||
|
{
|
||||||
|
if (components_.size() != compare.components_.size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < components_.size(); ++i)
|
||||||
|
{
|
||||||
|
if (components_[i].type != compare.components_[i].type
|
||||||
|
|| components_[i].value != compare.components_[i].value)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
bool path::operator==(std::string_view compare) const noexcept
|
||||||
|
{
|
||||||
|
return string() == compare;
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
bool path::operator==(const char* compare) const noexcept
|
||||||
|
{
|
||||||
|
return string() == std::string_view(compare);
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
bool path::operator!=(const path& compare) const noexcept
|
||||||
|
{
|
||||||
|
return !(*this == compare);
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
bool path::operator!=(std::string_view compare) const noexcept
|
||||||
|
{
|
||||||
|
return !(*this == compare);
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
bool path::operator!=(const char* compare) const noexcept
|
||||||
|
{
|
||||||
|
return !(*this == std::string_view(compare));
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
std::vector<path_component> path::parse_(std::string_view path_str, bool& parse_error)
|
||||||
|
{
|
||||||
|
std::vector<path_component> parsed_components;
|
||||||
|
parse_error = false; // success by default, set to true if fails to parse.
|
||||||
|
|
||||||
|
if (path_str == "") // empty path
|
||||||
|
return parsed_components;
|
||||||
|
|
||||||
|
auto str_start = path_str.data();
|
||||||
|
size_t pos = 0;
|
||||||
|
const auto end = path_str.length();
|
||||||
|
bool prev_was_array_indexer = false;
|
||||||
|
bool prev_was_dot = true; // invisible root 'dot'
|
||||||
|
|
||||||
|
while (pos < end)
|
||||||
|
{
|
||||||
|
// start of an array indexer
|
||||||
|
if (path_str[pos] == '[')
|
||||||
|
{
|
||||||
|
// get array index substring
|
||||||
|
const auto index_start = pos + 1u; // first position after '['
|
||||||
|
const auto index_end = path_str.find(']', index_start); // position of ']'
|
||||||
|
if (index_end == std::string_view::npos || index_end == index_start) // nothing in brackets, error
|
||||||
|
{
|
||||||
|
parsed_components.clear(); // empty object in case of error
|
||||||
|
parse_error = true;
|
||||||
|
return parsed_components;
|
||||||
|
}
|
||||||
|
auto index_str = std::string_view(&path_str[index_start], index_end - index_start);
|
||||||
|
|
||||||
|
// trim whitespace from either side of the index
|
||||||
|
const auto first_non_ws = index_str.find_first_not_of(" \t"sv);
|
||||||
|
const auto last_non_ws = index_str.find_last_not_of(" \t"sv);
|
||||||
|
if (first_non_ws == std::string_view::npos)
|
||||||
|
{
|
||||||
|
parsed_components.clear(); // empty object in case of error
|
||||||
|
parse_error = true;
|
||||||
|
return parsed_components;
|
||||||
|
}
|
||||||
|
TOML_ASSERT_ASSUME(last_non_ws != std::string_view::npos);
|
||||||
|
index_str = index_str.substr(first_non_ws, (last_non_ws - first_non_ws) + 1u);
|
||||||
|
|
||||||
|
// parse the actual array index to an integer type
|
||||||
|
size_t index;
|
||||||
|
if (index_str.length() == 1u && index_str[0] >= '0' && index_str[0] <= '9')
|
||||||
|
index = static_cast<size_t>(index_str[0] - '0');
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if TOML_INT_CHARCONV
|
||||||
|
|
||||||
|
auto fc_result = std::from_chars(index_str.data(), index_str.data() + index_str.length(), index);
|
||||||
|
|
||||||
|
// If not able to parse, or entire index not parseable, then fail (otherwise would allow a[1bc] == a[1]
|
||||||
|
if (fc_result.ec != std::errc{} || fc_result.ptr != index_str.data() + index_str.length())
|
||||||
|
{
|
||||||
|
parsed_components.clear(); // empty object in case of error
|
||||||
|
parse_error_ = true;
|
||||||
|
return parsed_components;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
ss.imbue(std::locale::classic());
|
||||||
|
ss.write(index_str.data(), static_cast<std::streamsize>(index_str.length()));
|
||||||
|
if (!(ss >> index))
|
||||||
|
{
|
||||||
|
clear(); // empty object in case of error
|
||||||
|
parse_error_ = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = index_end + 1u;
|
||||||
|
prev_was_dot = false;
|
||||||
|
prev_was_array_indexer = true;
|
||||||
|
|
||||||
|
parsed_components.emplace_back(path_component{ { index }, path_component_type::array_index });
|
||||||
|
}
|
||||||
|
|
||||||
|
// start of a new table child
|
||||||
|
else if (path_str[pos] == '.')
|
||||||
|
{
|
||||||
|
// a dot immediately following another dot (or at the beginning of the string) is as if we'd asked
|
||||||
|
// for an empty child in between, e.g.
|
||||||
|
//
|
||||||
|
// foo..bar
|
||||||
|
//
|
||||||
|
// is equivalent to
|
||||||
|
//
|
||||||
|
// "foo".""."bar"
|
||||||
|
//
|
||||||
|
if (prev_was_dot)
|
||||||
|
parsed_components.emplace_back(path_component{ { ""s }, path_component_type::key });
|
||||||
|
|
||||||
|
pos++;
|
||||||
|
prev_was_dot = true;
|
||||||
|
prev_was_array_indexer = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// some regular subkey
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto subkey_start = pos;
|
||||||
|
const auto subkey_len =
|
||||||
|
impl::min(path_str.find_first_of(".["sv, subkey_start + 1u), path_str.length()) - subkey_start;
|
||||||
|
const auto subkey = path_str.substr(subkey_start, subkey_len);
|
||||||
|
|
||||||
|
// a regular subkey segment immediately after an array indexer is OK if it was all whitespace, e.g.:
|
||||||
|
//
|
||||||
|
// "foo[0] .bar"
|
||||||
|
// ^^ skip this
|
||||||
|
//
|
||||||
|
// otherwise its an error (since it would have to be preceeded by a dot)
|
||||||
|
if (prev_was_array_indexer)
|
||||||
|
{
|
||||||
|
auto non_ws = subkey.find_first_not_of(" \t");
|
||||||
|
if (non_ws == std::string_view::npos)
|
||||||
|
{
|
||||||
|
pos += subkey_len;
|
||||||
|
prev_was_dot = false;
|
||||||
|
prev_was_array_indexer = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parsed_components.clear(); // empty object in case of error
|
||||||
|
parse_error = true;
|
||||||
|
return parsed_components;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += subkey_len;
|
||||||
|
prev_was_dot = false;
|
||||||
|
prev_was_array_indexer = false;
|
||||||
|
|
||||||
|
parsed_components.emplace_back(path_component{
|
||||||
|
std::string(std::string_view{ str_start + subkey_start, subkey_len }),
|
||||||
|
path_component_type::key
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prev_was_dot) // Last character was a '.', which implies an empty string key at the end of the path
|
||||||
|
{
|
||||||
|
parsed_components.emplace_back(path_component{ ""s, path_component_type::key });
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsed_components;
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
void path::clear() noexcept
|
||||||
|
{
|
||||||
|
this->components_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
path& path::truncate(size_t n)
|
||||||
|
{
|
||||||
|
n = n > components_.size() ? components_.size() : n;
|
||||||
|
|
||||||
|
auto it_end = components_.end();
|
||||||
|
components_.erase(it_end - static_cast<int>(n), it_end);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
path path::truncated(size_t n) const
|
||||||
|
{
|
||||||
|
path truncated_path {};
|
||||||
|
|
||||||
|
n = n > components_.size() ? components_.size() : n;
|
||||||
|
|
||||||
|
// Copy all components except one
|
||||||
|
// Need at least two path components to have a parent, since if there is
|
||||||
|
// only one path component, the parent is the root/null path ""
|
||||||
|
truncated_path.components_.insert(truncated_path.components_.begin(),
|
||||||
|
components_.begin(),
|
||||||
|
components_.end() - static_cast<int>(n));
|
||||||
|
|
||||||
|
return truncated_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
path path::parent_path() const
|
||||||
|
{
|
||||||
|
return truncated(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
path path::leaf(size_t n) const
|
||||||
|
{
|
||||||
|
toml::path leaf_path {};
|
||||||
|
|
||||||
|
n = n > components_.size() ? components_.size() : n;
|
||||||
|
|
||||||
|
if (n > 0)
|
||||||
|
{
|
||||||
|
leaf_path.components_.insert(leaf_path.components_.begin(),
|
||||||
|
components_.end() - static_cast<int>(n),
|
||||||
|
components_.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
return leaf_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
path path::subpath(std::vector<path_component>::const_iterator start,
|
||||||
|
std::vector<path_component>::const_iterator end) const
|
||||||
|
{
|
||||||
|
toml::path subpath{};
|
||||||
|
|
||||||
|
if (start > end)
|
||||||
|
{
|
||||||
|
return subpath;
|
||||||
|
}
|
||||||
|
|
||||||
|
subpath.components_.insert(subpath.components_.begin(), start, end);
|
||||||
|
|
||||||
|
return subpath;
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
path path::subpath(size_t start, size_t length) const
|
||||||
|
{
|
||||||
|
return subpath(begin() + static_cast<int>(start), begin() + static_cast<int>(start + length));
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
path& path::append(const toml::path& source)
|
||||||
|
{
|
||||||
|
parse_error_ = false; // This will end up being a valid path when appended (even if previously failed and now
|
||||||
|
// empty)
|
||||||
|
|
||||||
|
// Copy path parts to this object
|
||||||
|
for (const auto& component : source.components_)
|
||||||
|
{
|
||||||
|
components_.push_back(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
path& path::append(toml::path&& source)
|
||||||
|
{
|
||||||
|
parse_error_ = false; // This will end up being a valid path when appended (even if previously failed and now
|
||||||
|
// empty)
|
||||||
|
|
||||||
|
// Copy path parts to this object
|
||||||
|
for (auto& component : source.components_)
|
||||||
|
{
|
||||||
|
components_.emplace_back(std::move(component));
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
path& path::append(std::string_view source)
|
||||||
|
{
|
||||||
|
auto components_to_append = parse_(source, parse_error_);
|
||||||
|
for (auto& component : components_to_append)
|
||||||
|
{
|
||||||
|
components_.emplace_back(std::move(component));
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
path& path::prepend(const toml::path& source)
|
||||||
|
{
|
||||||
|
parse_error_ = false; // This will end up being a valid path when appended (even if previously failed and now
|
||||||
|
// empty)
|
||||||
|
|
||||||
|
components_.insert(components_.begin(), source.components_.begin(), source.components_.end());
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
path& path::prepend(toml::path&& source)
|
||||||
|
{
|
||||||
|
parse_error_ = false; // This will end up being a valid path when appended (even if previously failed and now
|
||||||
|
// empty)
|
||||||
|
|
||||||
|
components_.insert(components_.begin(), std::make_move_iterator(source.components_.begin()), std::make_move_iterator(source.components_.end()));
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
path& path::prepend(std::string_view source)
|
||||||
|
{
|
||||||
|
auto components_to_prepend = parse_(source, parse_error_);
|
||||||
|
|
||||||
|
components_.insert(components_.begin(), components_to_prepend.begin(), components_to_prepend.end());
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
path& path::assign(std::string_view source)
|
||||||
|
{
|
||||||
|
components_ = parse_(source, parse_error_);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
path& path::assign(const path& source)
|
||||||
|
{
|
||||||
|
if (source)
|
||||||
|
{
|
||||||
|
components_ = source.components_;
|
||||||
|
}
|
||||||
|
else // propagate error of source
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
parse_error_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
std::string path::string() const
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
bool atRoot = true;
|
||||||
|
|
||||||
|
for (const auto& component : components_)
|
||||||
|
{
|
||||||
|
if (component.type == path_component_type::key) // key
|
||||||
|
{
|
||||||
|
ss << (atRoot ? "" : ".") << std::get<std::string>(component.value);
|
||||||
|
}
|
||||||
|
else if (component.type == path_component_type::array_index) // array
|
||||||
|
{
|
||||||
|
ss << "[" << std::get<size_t>(component.value) << "]";
|
||||||
|
}
|
||||||
|
atRoot = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
std::ostream& operator<<(std::ostream& os, const toml::path& rhs)
|
||||||
|
{
|
||||||
|
os << rhs.string();
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
std::istream& operator>>(std::istream& is, toml::path& rhs)
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
is >> s;
|
||||||
|
rhs.assign(s);
|
||||||
|
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||||
|
|
||||||
|
/// \brief Construct from wstring
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
path::path(std::wstring_view path_str) : path(impl::narrow(path_str))
|
||||||
|
{ }
|
||||||
|
|
||||||
|
/// \brief Append operator
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
path& path::operator/=(std::wstring_view rhs)
|
||||||
|
{
|
||||||
|
return append(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Append operator.
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
path& path::operator+=(std::wstring_view rhs)
|
||||||
|
{
|
||||||
|
return append(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Evaluate whether two paths are the same
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
bool path::operator==(std::wstring_view compare) const noexcept
|
||||||
|
{
|
||||||
|
return *this == impl::narrow(compare);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Evaluate whether two paths are the same
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
bool path::operator!=(std::wstring_view compare) const noexcept
|
||||||
|
{
|
||||||
|
return *this != impl::narrow(compare);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Appends elements to the end of the TOML path
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
path& path::append(std::wstring_view source)
|
||||||
|
{
|
||||||
|
return append(impl::narrow(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Prepends elements to the beginning of the TOML path
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
path& path::prepend(std::wstring_view source)
|
||||||
|
{
|
||||||
|
return prepend(impl::narrow(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Replaces the contents of the path object by a new path
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
path& path::assign(std::wstring_view source)
|
||||||
|
{
|
||||||
|
return assign(impl::narrow(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Returns a wstring representing the path
|
||||||
|
TOML_EXTERNAL_LINKAGE
|
||||||
|
std::wstring path::wstring() const
|
||||||
|
{
|
||||||
|
return impl::widen(string());
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||||
|
|
||||||
|
}
|
||||||
|
TOML_NAMESPACE_END;
|
||||||
|
|
||||||
|
#include "header_end.h"
|
10
include/toml++/impl/std_variant.h
Normal file
10
include/toml++/impl/std_variant.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||||
|
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||||
|
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "preprocessor.h"
|
||||||
|
TOML_DISABLE_WARNINGS;
|
||||||
|
#include <variant>
|
||||||
|
TOML_ENABLE_WARNINGS;
|
@ -4,6 +4,7 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "forward_declarations.h"
|
||||||
#include "std_map.h"
|
#include "std_map.h"
|
||||||
#include "std_initializer_list.h"
|
#include "std_initializer_list.h"
|
||||||
#include "array.h"
|
#include "array.h"
|
||||||
@ -1858,6 +1859,40 @@ TOML_NAMESPACE_START
|
|||||||
return node_view<const node>{ get(key) };
|
return node_view<const node>{ get(key) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Gets a node_view for the provided path.
|
||||||
|
///
|
||||||
|
/// \param path The "TOML path" to the desired key.
|
||||||
|
///
|
||||||
|
/// \returns A view of the value at the given path if one existed, or an empty node view.
|
||||||
|
///
|
||||||
|
/// \remarks std::map::operator[]'s behaviour of default-constructing a value at a key if it
|
||||||
|
/// didn't exist is a crazy bug factory so I've deliberately chosen not to emulate it.
|
||||||
|
/// <strong>This is not an error.</strong>
|
||||||
|
///
|
||||||
|
/// \see toml::node_view
|
||||||
|
TOML_NODISCARD
|
||||||
|
node_view<node> operator[](const toml::path& path) noexcept
|
||||||
|
{
|
||||||
|
return node_view<node>{ at_path(path) };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Gets a node_view for the provided path (const overload).
|
||||||
|
///
|
||||||
|
/// \param path The "TOML path" to the desired key.
|
||||||
|
///
|
||||||
|
/// \returns A view of the value at the given path if one existed, or an empty node view.
|
||||||
|
///
|
||||||
|
/// \remarks std::map::operator[]'s behaviour of default-constructing a value at a key if it
|
||||||
|
/// didn't exist is a crazy bug factory so I've deliberately chosen not to emulate it.
|
||||||
|
/// <strong>This is not an error.</strong>
|
||||||
|
///
|
||||||
|
/// \see toml::node_view
|
||||||
|
TOML_NODISCARD
|
||||||
|
node_view<const node> operator[](const toml::path& path) const noexcept
|
||||||
|
{
|
||||||
|
return node_view<const node>{ at_path(path) };
|
||||||
|
}
|
||||||
|
|
||||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||||
|
|
||||||
/// \brief Gets a node_view for the selected value.
|
/// \brief Gets a node_view for the selected value.
|
||||||
|
@ -41,6 +41,7 @@ TOML_DISABLE_SUGGEST_ATTR_WARNINGS;
|
|||||||
#include "impl/source_region.h"
|
#include "impl/source_region.h"
|
||||||
#include "impl/date_time.h"
|
#include "impl/date_time.h"
|
||||||
#include "impl/at_path.h"
|
#include "impl/at_path.h"
|
||||||
|
#include "impl/path.h"
|
||||||
#include "impl/node.h"
|
#include "impl/node.h"
|
||||||
#include "impl/node_view.h"
|
#include "impl/node_view.h"
|
||||||
#include "impl/value.h"
|
#include "impl/value.h"
|
||||||
@ -64,6 +65,7 @@ TOML_DISABLE_SUGGEST_ATTR_WARNINGS;
|
|||||||
#include "impl/print_to_stream.inl"
|
#include "impl/print_to_stream.inl"
|
||||||
#include "impl/node.inl"
|
#include "impl/node.inl"
|
||||||
#include "impl/at_path.inl"
|
#include "impl/at_path.inl"
|
||||||
|
#include "impl/path.inl"
|
||||||
#include "impl/array.inl"
|
#include "impl/array.inl"
|
||||||
#include "impl/table.inl"
|
#include "impl/table.inl"
|
||||||
#include "impl/unicode.inl"
|
#include "impl/unicode.inl"
|
||||||
|
594
tests/path.cpp
Normal file
594
tests/path.cpp
Normal file
@ -0,0 +1,594 @@
|
|||||||
|
// This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||||
|
// Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||||
|
// See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#include "tests.h"
|
||||||
|
TOML_DISABLE_SPAM_WARNINGS;
|
||||||
|
|
||||||
|
TEST_CASE("path - parsing")
|
||||||
|
{
|
||||||
|
|
||||||
|
SECTION("parsing")
|
||||||
|
{
|
||||||
|
CHECK(toml::path("").string() == "");
|
||||||
|
CHECK(toml::path("[1]").string() == "[1]");
|
||||||
|
CHECK(toml::path("[1][2]").string() == "[1][2]");
|
||||||
|
CHECK(toml::path(" [1][2]").string() == " [1][2]");
|
||||||
|
CHECK(toml::path("a. .b").string() == "a. .b");
|
||||||
|
CHECK(toml::path("test[23]").string() == "test[23]");
|
||||||
|
CHECK(toml::path("[ 120 ]").string() == "[120]");
|
||||||
|
CHECK(toml::path("test.value").string() == "test.value");
|
||||||
|
CHECK(toml::path("test[0].value").string() == "test[0].value");
|
||||||
|
CHECK(toml::path("test[1][2]\t .value").string() == "test[1][2].value");
|
||||||
|
CHECK(toml::path("test[1]\t[2].value").string() == "test[1][2].value");
|
||||||
|
CHECK(toml::path(".test[1][2]\t ..value").string() == ".test[1][2]..value");
|
||||||
|
|
||||||
|
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||||
|
|
||||||
|
CHECK(toml::path(L"").string() == "");
|
||||||
|
CHECK(toml::path(L"[1]").string() == "[1]");
|
||||||
|
CHECK(toml::path(L"[1][2]").string() == "[1][2]");
|
||||||
|
CHECK(toml::path(L" [1][2]").string() == " [1][2]");
|
||||||
|
CHECK(toml::path(L"a. .b").string() == "a. .b");
|
||||||
|
CHECK(toml::path(L"test[23]").string() == "test[23]");
|
||||||
|
CHECK(toml::path(L"[ 120 ]").string() == "[120]");
|
||||||
|
CHECK(toml::path(L"test.value").string() == "test.value");
|
||||||
|
CHECK(toml::path(L"test[0].value").string() == "test[0].value");
|
||||||
|
CHECK(toml::path(L"test[1][2]\t .value").string() == "test[1][2].value");
|
||||||
|
CHECK(toml::path(L"test[1]\t[2].value").string() == "test[1][2].value");
|
||||||
|
CHECK(toml::path(L".test[1][2]\t ..value").string() == ".test[1][2]..value");
|
||||||
|
|
||||||
|
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("parsing - errors")
|
||||||
|
{
|
||||||
|
CHECK(!toml::path("test[][2].value"));
|
||||||
|
CHECK(!toml::path("test[ "));
|
||||||
|
CHECK(!toml::path("test[1]a.b"));
|
||||||
|
CHECK(!toml::path("test[1] a.b"));
|
||||||
|
CHECK(!toml::path("test[1a]"));
|
||||||
|
CHECK(!toml::path("test[a1]"));
|
||||||
|
CHECK(!toml::path("test[1!]"));
|
||||||
|
CHECK(!toml::path("test[!1]"));
|
||||||
|
CHECK(!toml::path("test[1 2]"));
|
||||||
|
CHECK(!toml::path("test[1.2]"));
|
||||||
|
CHECK(!toml::path("test[0.2]"));
|
||||||
|
|
||||||
|
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||||
|
|
||||||
|
CHECK(!toml::path(L"test[][2].value"));
|
||||||
|
CHECK(!toml::path(L"test[ "));
|
||||||
|
CHECK(!toml::path(L"test[1]a.b"));
|
||||||
|
CHECK(!toml::path(L"test[1] a.b"));
|
||||||
|
CHECK(!toml::path(L"test[1a]"));
|
||||||
|
CHECK(!toml::path(L"test[a1]"));
|
||||||
|
CHECK(!toml::path(L"test[1!]"));
|
||||||
|
CHECK(!toml::path(L"test[!1]"));
|
||||||
|
CHECK(!toml::path(L"test[1 2]"));
|
||||||
|
CHECK(!toml::path(L"test[1.2]"));
|
||||||
|
CHECK(!toml::path(L"test[0.2]"));
|
||||||
|
|
||||||
|
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("parsing from literal")
|
||||||
|
{
|
||||||
|
auto p0 = "a.b.c[1][12]"_tpath;
|
||||||
|
CHECK(p0);
|
||||||
|
CHECK(p0.string() == "a.b.c[1][12]");
|
||||||
|
|
||||||
|
CHECK("ab.cd[1]"_tpath == toml::path("ab.cd[1]"));
|
||||||
|
|
||||||
|
CHECK(("an.invalid.path[a1]"_tpath).string() == "");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("path - manipulating")
|
||||||
|
{
|
||||||
|
SECTION("parent_node and truncation")
|
||||||
|
{
|
||||||
|
toml::path p0("");
|
||||||
|
CHECK(p0.parent_path().string() == "");
|
||||||
|
|
||||||
|
toml::path p1("start.middle.end");
|
||||||
|
CHECK(p1.parent_path().string() == "start.middle");
|
||||||
|
CHECK(p1.parent_path().parent_path().string() == "start");
|
||||||
|
CHECK(p1.parent_path().parent_path().parent_path().string() == "");
|
||||||
|
CHECK(p1.parent_path().parent_path().parent_path().parent_path().string() == "");
|
||||||
|
|
||||||
|
toml::path p2("[1][2][3]");
|
||||||
|
CHECK(p2.parent_path().string() == "[1][2]");
|
||||||
|
CHECK(p2.parent_path().parent_path().string() == "[1]");
|
||||||
|
CHECK(p2.parent_path().parent_path().parent_path().string() == "");
|
||||||
|
|
||||||
|
toml::path p3(".test");
|
||||||
|
CHECK(p3.parent_path().string() == "");
|
||||||
|
|
||||||
|
toml::path p4("test..");
|
||||||
|
CHECK(p4.parent_path().string() == "test.");
|
||||||
|
CHECK(p4.parent_path().parent_path().string() == "test");
|
||||||
|
CHECK(p4.parent_path().parent_path().parent_path().string() == "");
|
||||||
|
|
||||||
|
toml::path p5("test.key[12].subkey");
|
||||||
|
CHECK(p5.parent_path().string() == "test.key[12]");
|
||||||
|
CHECK(p5.parent_path().parent_path().string() == "test.key");
|
||||||
|
CHECK(p5.parent_path().parent_path().parent_path().string() == "test");
|
||||||
|
CHECK(p5.parent_path().parent_path().parent_path().parent_path().string() == "");
|
||||||
|
|
||||||
|
toml::path p6("test.key1.key2.key3.key4");
|
||||||
|
CHECK(p6.truncated(0).string() == "test.key1.key2.key3.key4");
|
||||||
|
CHECK(p6.truncated(1).string() == "test.key1.key2.key3");
|
||||||
|
CHECK(p6.truncated(4).string() == "test");
|
||||||
|
CHECK(p6.truncated(5).string() == "");
|
||||||
|
CHECK(p6.truncated(20).string() == "");
|
||||||
|
CHECK(p6.string() == "test.key1.key2.key3.key4");
|
||||||
|
|
||||||
|
p6.truncate(0);
|
||||||
|
CHECK(p6.string() == "test.key1.key2.key3.key4");
|
||||||
|
p6.truncate(2);
|
||||||
|
CHECK(p6.string() == "test.key1.key2");
|
||||||
|
p6.truncate(3);
|
||||||
|
CHECK(p6.string() == "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("subpath")
|
||||||
|
{
|
||||||
|
toml::path p0("a.simple[1].path[2].object");
|
||||||
|
|
||||||
|
CHECK(p0.subpath(p0.begin() + 1, p0.begin() + 4).string() == "simple[1].path");
|
||||||
|
CHECK(p0.subpath(p0.begin() + 1, p0.end() - 1).string() == "simple[1].path[2]");
|
||||||
|
CHECK(p0.subpath(p0.begin(), p0.begin()).string() == "");
|
||||||
|
CHECK(p0.subpath(p0.begin(), p0.end() - 5).string() == "a");
|
||||||
|
CHECK(p0.subpath(p0.begin() + 2, p0.end() - 1).string() == "[1].path[2]");
|
||||||
|
|
||||||
|
CHECK(p0.subpath(p0.begin() + 5, p0.end() - 5).string() == "");
|
||||||
|
CHECK(p0.subpath(p0.end(), p0.begin()) == "");
|
||||||
|
|
||||||
|
CHECK(p0.subpath(1, 4).string() == "simple[1].path[2]");
|
||||||
|
CHECK(p0.subpath(0, 0).string() == "");
|
||||||
|
CHECK(p0.subpath(2, 0).string() == "");
|
||||||
|
CHECK(p0.subpath(2, 1).string() == "[1]");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("leaf")
|
||||||
|
{
|
||||||
|
toml::path p0("one.two.three.four.five");
|
||||||
|
CHECK(p0.leaf(0).string() == "");
|
||||||
|
CHECK(p0.leaf().string() == "five");
|
||||||
|
CHECK(p0.leaf(3).string() == "three.four.five");
|
||||||
|
CHECK(p0.leaf(5).string() == "one.two.three.four.five");
|
||||||
|
CHECK(p0.leaf(10).string() == "one.two.three.four.five");
|
||||||
|
|
||||||
|
toml::path p1("[10][2][30][4][50]");
|
||||||
|
CHECK(p1.leaf(0).string() == "");
|
||||||
|
CHECK(p1.leaf().string() == "[50]");
|
||||||
|
CHECK(p1.leaf(3).string() == "[30][4][50]");
|
||||||
|
CHECK(p1.leaf(5).string() == "[10][2][30][4][50]");
|
||||||
|
CHECK(p1.leaf(10).string() == "[10][2][30][4][50]");
|
||||||
|
|
||||||
|
toml::path p2("one[1].two.three[3]");
|
||||||
|
CHECK(p2.leaf(0).string() == "");
|
||||||
|
CHECK(p2.leaf().string() == "[3]");
|
||||||
|
CHECK(p2.leaf(3).string() == "two.three[3]");
|
||||||
|
CHECK(p2.leaf(4).string() == "[1].two.three[3]");
|
||||||
|
CHECK(p2.leaf(10).string() == "one[1].two.three[3]");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("append - string")
|
||||||
|
{
|
||||||
|
toml::path p0("start");
|
||||||
|
CHECK(p0.append("middle.end").string() == "start.middle.end");
|
||||||
|
CHECK(p0.append("[12]").string() == "start.middle.end[12]");
|
||||||
|
|
||||||
|
toml::path p1("");
|
||||||
|
CHECK(p1.append("[1].key").string() == "[1].key");
|
||||||
|
|
||||||
|
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||||
|
|
||||||
|
toml::path p2("start");
|
||||||
|
CHECK(p2.append(L"middle.end").string() == "start.middle.end");
|
||||||
|
CHECK(p2.append(L"[12]").string() == "start.middle.end[12]");
|
||||||
|
|
||||||
|
toml::path p3("");
|
||||||
|
CHECK(p3.append(L"[1].key").string() == "[1].key");
|
||||||
|
|
||||||
|
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("append - toml::path copy")
|
||||||
|
{
|
||||||
|
toml::path p0("start");
|
||||||
|
toml::path appendee1("middle.end");
|
||||||
|
toml::path appendee2("[12]");
|
||||||
|
CHECK(p0.append(appendee1).string() == "start.middle.end");
|
||||||
|
CHECK(p0.append(appendee2).string() == "start.middle.end[12]");
|
||||||
|
|
||||||
|
// Ensure copies and not moves
|
||||||
|
CHECK(appendee1.string() == "middle.end");
|
||||||
|
CHECK(appendee2.string() == "[12]");
|
||||||
|
|
||||||
|
toml::path p1("");
|
||||||
|
toml::path appendee3("[1].key");
|
||||||
|
CHECK(p1.append(appendee3).string() == "[1].key");
|
||||||
|
|
||||||
|
// Ensure copies and not moves
|
||||||
|
CHECK(appendee3.string() == "[1].key");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("append - toml::path move")
|
||||||
|
{
|
||||||
|
toml::path p0("start");
|
||||||
|
CHECK(p0.append(toml::path("middle.end")).string() == "start.middle.end");
|
||||||
|
CHECK(p0.append(toml::path("[12]")).string() == "start.middle.end[12]");
|
||||||
|
|
||||||
|
toml::path p1("");
|
||||||
|
CHECK(p1.append(toml::path("[1].key")).string() == "[1].key");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("prepend - string")
|
||||||
|
{
|
||||||
|
toml::path p0("start");
|
||||||
|
CHECK(p0.prepend("middle.end").string() == "middle.end.start");
|
||||||
|
CHECK(p0.prepend("[12]").string() == "[12].middle.end.start");
|
||||||
|
|
||||||
|
toml::path p1("");
|
||||||
|
CHECK(p1.prepend("[1].key").string() == "[1].key");
|
||||||
|
|
||||||
|
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||||
|
|
||||||
|
toml::path p2("start");
|
||||||
|
CHECK(p2.prepend(L"middle.end").string() == "middle.end.start");
|
||||||
|
CHECK(p2.prepend(L"[12]").string() == "[12].middle.end.start");
|
||||||
|
|
||||||
|
toml::path p3("");
|
||||||
|
CHECK(p3.prepend(L"[1].key").string() == "[1].key");
|
||||||
|
|
||||||
|
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("prepend - toml::path copy")
|
||||||
|
{
|
||||||
|
toml::path p0("start");
|
||||||
|
toml::path prependee1("middle.end");
|
||||||
|
toml::path prependee2("[12]");
|
||||||
|
CHECK(p0.prepend(prependee1).string() == "middle.end.start");
|
||||||
|
CHECK(p0.prepend(prependee2).string() == "[12].middle.end.start");
|
||||||
|
|
||||||
|
// Ensure copies and not moves
|
||||||
|
CHECK(prependee1.string() == "middle.end");
|
||||||
|
CHECK(prependee2.string() == "[12]");
|
||||||
|
|
||||||
|
toml::path p1("");
|
||||||
|
toml::path prependee3("[1].key");
|
||||||
|
CHECK(p1.prepend(prependee3).string() == "[1].key");
|
||||||
|
|
||||||
|
// Ensure copies and not moves
|
||||||
|
CHECK(prependee3.string() == "[1].key");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("prepend - toml::path move")
|
||||||
|
{
|
||||||
|
toml::path p0("start");
|
||||||
|
CHECK(p0.prepend(toml::path("middle.end")).string() == "middle.end.start");
|
||||||
|
CHECK(p0.prepend(toml::path("[12]")).string() == "[12].middle.end.start");
|
||||||
|
|
||||||
|
toml::path p1("");
|
||||||
|
CHECK(p1.prepend(toml::path("[1].key")).string() == "[1].key");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("alter components")
|
||||||
|
{
|
||||||
|
toml::path p0("start.mid[1][2].end");
|
||||||
|
|
||||||
|
p0[3].value = std::size_t{ 13 };
|
||||||
|
CHECK(p0.string() == "start.mid[1][13].end");
|
||||||
|
|
||||||
|
p0[3].type = path_component_type::key;
|
||||||
|
p0[3].value = "newkey";
|
||||||
|
CHECK(p0.string() == "start.mid[1].newkey.end");
|
||||||
|
|
||||||
|
p0[0].value = std::size_t{ 2 };
|
||||||
|
p0[0].type = path_component_type::array_index;
|
||||||
|
CHECK(p0.string() == "[2].mid[1].newkey.end");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("assign")
|
||||||
|
{
|
||||||
|
toml::path p0("start.mid[1][2].end");
|
||||||
|
p0.assign("test.key[1]");
|
||||||
|
CHECK(p0.string() == "test.key[1]");
|
||||||
|
p0.assign("");
|
||||||
|
CHECK(p0.string() == "");
|
||||||
|
|
||||||
|
toml::path p1("a.test.path[1]");
|
||||||
|
p1.assign("invalid[abc]");
|
||||||
|
CHECK(!p1);
|
||||||
|
CHECK(p1.string() == "");
|
||||||
|
|
||||||
|
toml::path p2("another[1].test.path");
|
||||||
|
p2.assign(toml::path("test"));
|
||||||
|
CHECK(p2.string() == "test");
|
||||||
|
p2.assign(toml::path(""));
|
||||||
|
CHECK(p2.string() == "");
|
||||||
|
|
||||||
|
toml::path p3("final.test[1]");
|
||||||
|
p3.assign(toml::path("invalid[abc"));
|
||||||
|
CHECK(!p3);
|
||||||
|
CHECK(p3.string() == "");
|
||||||
|
|
||||||
|
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||||
|
|
||||||
|
toml::path p4("start.mid[1][2].end");
|
||||||
|
p4.assign(L"test.key[1]");
|
||||||
|
CHECK(p4.string() == "test.key[1]");
|
||||||
|
p4.assign("");
|
||||||
|
CHECK(p4.string() == "");
|
||||||
|
|
||||||
|
toml::path p5("a.test.path[1]");
|
||||||
|
p5.assign("invalid[abc]");
|
||||||
|
CHECK(!p5);
|
||||||
|
CHECK(p5.string() == "");
|
||||||
|
|
||||||
|
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("path - operators")
|
||||||
|
{
|
||||||
|
SECTION("object equality")
|
||||||
|
{
|
||||||
|
CHECK(toml::path("a.b.c") == toml::path("a.b.c"));
|
||||||
|
CHECK(toml::path("[1].a") == toml::path("[1].a"));
|
||||||
|
|
||||||
|
CHECK(toml::path("a.b.c") != toml::path("a.b"));
|
||||||
|
CHECK(toml::path("[1].b") != toml::path("[1].b.c"));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("string equality")
|
||||||
|
{
|
||||||
|
CHECK(toml::path("a.b.c") == "a.b.c");
|
||||||
|
CHECK(toml::path("[1].a") == "[1].a");
|
||||||
|
|
||||||
|
CHECK(toml::path("a.b.c") != "a.b");
|
||||||
|
CHECK(toml::path("[1].b") != "[1].b.c");
|
||||||
|
|
||||||
|
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||||
|
|
||||||
|
CHECK(toml::path("a.b.c") == L"a.b.c");
|
||||||
|
CHECK(toml::path("[1].a") == L"[1].a");
|
||||||
|
|
||||||
|
CHECK(toml::path("a.b.c") != L"a.b");
|
||||||
|
CHECK(toml::path("[1].b") != L"[1].b.c");
|
||||||
|
|
||||||
|
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("arithmetic")
|
||||||
|
{
|
||||||
|
CHECK(toml::path("a.b.c") / "a[1]" == "a.b.c.a[1]");
|
||||||
|
CHECK((toml::path("a.b.c") / "a[1]") == "a.b.c.a[1]");
|
||||||
|
|
||||||
|
CHECK(toml::path("a.b.c") + toml::path("a[1]") == "a.b.c.a[1]");
|
||||||
|
CHECK(toml::path("a.b.c") / toml::path("a[1]") == "a.b.c.a[1]");
|
||||||
|
|
||||||
|
toml::path p1("a.b");
|
||||||
|
toml::path p2("c[1]");
|
||||||
|
CHECK((p1 + p2) == "a.b.c[1]");
|
||||||
|
CHECK(p1 / p2 == "a.b.c[1]");
|
||||||
|
|
||||||
|
CHECK(p1 + "c[1]" == "a.b.c[1]");
|
||||||
|
CHECK(p1 / "c[1]" == "a.b.c[1]");
|
||||||
|
|
||||||
|
CHECK("a.b" + p2 == "a.b.c[1]");
|
||||||
|
CHECK("a.b" / p2 == "a.b.c[1]");
|
||||||
|
|
||||||
|
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||||
|
|
||||||
|
CHECK(toml::path("a.b.c") / L"a[1]" == "a.b.c.a[1]");
|
||||||
|
CHECK((toml::path("a.b.c") / L"a[1]") == "a.b.c.a[1]");
|
||||||
|
|
||||||
|
CHECK(p1 + L"c[1]" == "a.b.c[1]");
|
||||||
|
CHECK(p1 / L"c[1]" == "a.b.c[1]");
|
||||||
|
|
||||||
|
CHECK(L"a.b" + p2 == "a.b.c[1]");
|
||||||
|
CHECK(L"a.b" / p2 == "a.b.c[1]");
|
||||||
|
|
||||||
|
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("path - misc")
|
||||||
|
{
|
||||||
|
|
||||||
|
CHECK(toml::path("a.b.c").string() == "a.b.c");
|
||||||
|
|
||||||
|
CHECK(!toml::path("a").empty());
|
||||||
|
CHECK(toml::path("").empty());
|
||||||
|
|
||||||
|
CHECK(static_cast<std::string>(toml::path("a.b[1]")) == "a.b[1]");
|
||||||
|
CHECK(static_cast<bool>(toml::path("a.b[1]")));
|
||||||
|
CHECK(!static_cast<bool>(toml::path("a.b[a b]")));
|
||||||
|
|
||||||
|
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||||
|
|
||||||
|
CHECK(static_cast<std::wstring>(toml::path("a.b[1]")) == L"a.b[1]");
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("path - accessing")
|
||||||
|
{
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
const auto tbl = table
|
||||||
|
{
|
||||||
|
{ ""sv, 0 }, // blank key
|
||||||
|
{ "a"sv, 1 },
|
||||||
|
{
|
||||||
|
"b"sv,
|
||||||
|
array
|
||||||
|
{
|
||||||
|
2,
|
||||||
|
array{ 3 },
|
||||||
|
table { { "c", 4 } }
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ "d", table{ {"e", 5, }, {""sv, -1 } } }
|
||||||
|
};
|
||||||
|
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
# equivalent to the following TOML:
|
||||||
|
|
||||||
|
"" = 0
|
||||||
|
a = 1
|
||||||
|
b = [
|
||||||
|
2,
|
||||||
|
[ 3 ],
|
||||||
|
{ "c" = 4 }
|
||||||
|
]
|
||||||
|
d = { "e" = 5, "" = -1 }
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
SECTION("table")
|
||||||
|
{
|
||||||
|
// this section uses the free function version of at_path
|
||||||
|
|
||||||
|
CHECK(tbl[""]);
|
||||||
|
CHECK(tbl[""] == at_path(tbl, toml::path("")));
|
||||||
|
|
||||||
|
CHECK(tbl["a"]);
|
||||||
|
CHECK(tbl["a"] == at_path(tbl, toml::path("a")));
|
||||||
|
CHECK(tbl["a"] != at_path(tbl, toml::path(".a"))); // equivalent to ""."a"
|
||||||
|
CHECK(!at_path(tbl, toml::path(".a")));
|
||||||
|
|
||||||
|
CHECK(tbl["b"]);
|
||||||
|
CHECK(tbl["b"] == at_path(tbl, toml::path("b")));
|
||||||
|
|
||||||
|
CHECK(tbl["b"][0]);
|
||||||
|
CHECK(tbl["b"][0] == at_path(tbl, toml::path("b[0]")));
|
||||||
|
CHECK(tbl["b"][0] == at_path(tbl, toml::path("b[0] ")));
|
||||||
|
CHECK(tbl["b"][0] == at_path(tbl, toml::path("b[ 0\t]"))); // whitespace is allowed inside array indexer
|
||||||
|
|
||||||
|
CHECK(tbl["b"][1]);
|
||||||
|
CHECK(tbl["b"][1] != tbl["b"][0]);
|
||||||
|
CHECK(tbl["b"][1] == at_path(tbl, toml::path("b[1]")));
|
||||||
|
|
||||||
|
CHECK(tbl["b"][1][0]);
|
||||||
|
CHECK(tbl["b"][1][0] == at_path(tbl, toml::path("b[1][0]")));
|
||||||
|
CHECK(tbl["b"][1][0] == at_path(tbl, toml::path("b[1] \t [0]"))); // whitespace is allowed after array
|
||||||
|
// indexers
|
||||||
|
|
||||||
|
CHECK(tbl["b"][2]["c"]);
|
||||||
|
CHECK(tbl["b"][2]["c"] == at_path(tbl, toml::path("b[2].c")));
|
||||||
|
CHECK(tbl["b"][2]["c"] == at_path(tbl, toml::path("b[2] \t.c"))); // whitespace is allowed after array indexers
|
||||||
|
|
||||||
|
CHECK(tbl["d"]);
|
||||||
|
CHECK(tbl["d"] == at_path(tbl, toml::path("d")));
|
||||||
|
|
||||||
|
CHECK(tbl["d"]["e"]);
|
||||||
|
CHECK(tbl["d"]["e"] == at_path(tbl, toml::path("d.e")));
|
||||||
|
CHECK(tbl["d"]["e"] != at_path(tbl, toml::path("d. e"))); // equivalent to "d"." e"
|
||||||
|
CHECK(!at_path(tbl, toml::path("d. e")));
|
||||||
|
|
||||||
|
CHECK(tbl["d"][""]);
|
||||||
|
CHECK(tbl["d"][""] == at_path(tbl, toml::path("d.")));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("array")
|
||||||
|
{
|
||||||
|
// this section uses the node_view member function version of at_path
|
||||||
|
|
||||||
|
auto arr = tbl["b"];
|
||||||
|
|
||||||
|
CHECK(tbl["b"][0]);
|
||||||
|
CHECK(tbl["b"][0] == arr.at_path(toml::path("[0]")));
|
||||||
|
CHECK(tbl["b"][0] == arr.at_path(toml::path("[0] ")));
|
||||||
|
CHECK(tbl["b"][0] == arr.at_path(toml::path("[ 0\t]"))); // whitespace is allowed inside array indexer
|
||||||
|
|
||||||
|
CHECK(tbl["b"][1]);
|
||||||
|
CHECK(tbl["b"][1].node() != arr[0].node());
|
||||||
|
CHECK(tbl["b"][1] == arr.at_path(toml::path("[1]")));
|
||||||
|
|
||||||
|
CHECK(tbl["b"][1][0]);
|
||||||
|
CHECK(tbl["b"][1][0] == arr.at_path(toml::path("[1][0]")));
|
||||||
|
CHECK(tbl["b"][1][0] == arr.at_path(toml::path("[1] \t [0]"))); // whitespace is allowed after array
|
||||||
|
// indexers
|
||||||
|
|
||||||
|
CHECK(tbl["b"][2]["c"]);
|
||||||
|
CHECK(tbl["b"][2]["c"] == arr.at_path(toml::path("[2].c")));
|
||||||
|
CHECK(tbl["b"][2]["c"] == arr.at_path(toml::path("[2] \t.c"))); // whitespace is allowed after array indexers
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("indexing operator")
|
||||||
|
{
|
||||||
|
// this section uses the operator[] of table and node_view
|
||||||
|
CHECK(tbl[""]);
|
||||||
|
CHECK(tbl[""] == tbl[toml::path("")]);
|
||||||
|
|
||||||
|
CHECK(tbl["a"]);
|
||||||
|
CHECK(tbl["a"] == tbl[toml::path("a")]);
|
||||||
|
CHECK(tbl["a"] != tbl[toml::path(".a")]); // equivalent to ""."a"
|
||||||
|
CHECK(!tbl[toml::path(".a")]);
|
||||||
|
|
||||||
|
CHECK(tbl["b"]);
|
||||||
|
CHECK(tbl["b"] == tbl[toml::path("b")]);
|
||||||
|
|
||||||
|
CHECK(tbl["b"][0]);
|
||||||
|
CHECK(tbl["b"][0] == tbl[toml::path("b[0]")]);
|
||||||
|
CHECK(tbl["b"][0] == tbl[toml::path("b[0] ")]);
|
||||||
|
CHECK(tbl["b"][0] == tbl[toml::path("b[ 0\t]")]); // whitespace is allowed inside array indexer
|
||||||
|
|
||||||
|
CHECK(tbl["b"][1]);
|
||||||
|
CHECK(tbl["b"][1] != tbl[toml::path("b")][0]);
|
||||||
|
CHECK(tbl["b"][1] == tbl[toml::path("b[1]")]);
|
||||||
|
|
||||||
|
CHECK(tbl["b"][1][0]);
|
||||||
|
CHECK(tbl["b"][1][0] == tbl[toml::path("b[1]")][0]);
|
||||||
|
CHECK(tbl["b"][1][0] == tbl[toml::path("b[1] \t [0]")]); // whitespace is allowed after array
|
||||||
|
// indexers
|
||||||
|
|
||||||
|
CHECK(tbl["b"][2]["c"]);
|
||||||
|
CHECK(tbl["b"][2]["c"] == tbl[toml::path("b")][toml::path("[2].c")]);
|
||||||
|
CHECK(tbl["b"][2]["c"] == tbl[toml::path("b[2] \t.c")]); // whitespace is allowed after array
|
||||||
|
// indexers
|
||||||
|
|
||||||
|
CHECK(tbl["d"]);
|
||||||
|
CHECK(tbl["d"] == tbl[toml::path("d")]);
|
||||||
|
|
||||||
|
CHECK(tbl["d"]["e"]);
|
||||||
|
CHECK(tbl["d"]["e"] == tbl[toml::path("d.e")]);
|
||||||
|
CHECK(tbl["d"]["e"] != tbl[toml::path("d. e")]); // equivalent to "d"." e"
|
||||||
|
CHECK(!tbl[toml::path("d. e")]);
|
||||||
|
|
||||||
|
CHECK(tbl["d"][""]);
|
||||||
|
CHECK(tbl["d"][""] == tbl[toml::path("d.")]);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("std::variant mismatches")
|
||||||
|
{
|
||||||
|
toml::path p0("b[2].c");
|
||||||
|
p0[1].value = "abc";
|
||||||
|
CHECK(!at_path(tbl, p0));
|
||||||
|
|
||||||
|
toml::path p1("b[2].c");
|
||||||
|
p1[0].value = std::size_t{ 1 };
|
||||||
|
CHECK(!at_path(tbl, p1));
|
||||||
|
}
|
||||||
|
}
|
@ -94,6 +94,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
@ -40,8 +40,11 @@
|
|||||||
<ClInclude Include="include\toml++\impl\at_path.h" />
|
<ClInclude Include="include\toml++\impl\at_path.h" />
|
||||||
<ClInclude Include="include\toml++\impl\date_time.h" />
|
<ClInclude Include="include\toml++\impl\date_time.h" />
|
||||||
<ClInclude Include="include\toml++\impl\key.h" />
|
<ClInclude Include="include\toml++\impl\key.h" />
|
||||||
|
<ClInclude Include="include\toml++\impl\path.h" />
|
||||||
<ClInclude Include="include\toml++\impl\simd.h" />
|
<ClInclude Include="include\toml++\impl\simd.h" />
|
||||||
|
<ClInclude Include="include\toml++\impl\std_algorithm.h" />
|
||||||
<ClInclude Include="include\toml++\impl\std_utility.h" />
|
<ClInclude Include="include\toml++\impl\std_utility.h" />
|
||||||
|
<ClInclude Include="include\toml++\impl\std_variant.h" />
|
||||||
<ClInclude Include="include\toml++\impl\toml_formatter.h" />
|
<ClInclude Include="include\toml++\impl\toml_formatter.h" />
|
||||||
<ClInclude Include="include\toml++\impl\toml_formatter.inl" />
|
<ClInclude Include="include\toml++\impl\toml_formatter.inl" />
|
||||||
<ClInclude Include="include\toml++\impl\formatter.h" />
|
<ClInclude Include="include\toml++\impl\formatter.h" />
|
||||||
@ -102,6 +105,7 @@
|
|||||||
<None Include="CONTRIBUTING.md" />
|
<None Include="CONTRIBUTING.md" />
|
||||||
<None Include="include\meson.build" />
|
<None Include="include\meson.build" />
|
||||||
<None Include="include\toml++\impl\at_path.inl" />
|
<None Include="include\toml++\impl\at_path.inl" />
|
||||||
|
<None Include="include\toml++\impl\path.inl" />
|
||||||
<None Include="include\toml++\impl\unicode.inl" />
|
<None Include="include\toml++\impl\unicode.inl" />
|
||||||
<None Include="include\toml++\impl\yaml_formatter.inl" />
|
<None Include="include\toml++\impl\yaml_formatter.inl" />
|
||||||
<None Include="LICENSE" />
|
<None Include="LICENSE" />
|
||||||
|
@ -133,6 +133,11 @@
|
|||||||
<ClInclude Include="include\toml++\impl\unicode_autogenerated.h">
|
<ClInclude Include="include\toml++\impl\unicode_autogenerated.h">
|
||||||
<Filter>include\impl</Filter>
|
<Filter>include\impl</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="include\toml++\impl\path.h">
|
||||||
|
<Filter>include\impl</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="include\toml++\impl\std_variant.h" />
|
||||||
|
<ClInclude Include="include\toml++\impl\std_algorithm.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="toml++.props" />
|
<None Include="toml++.props" />
|
||||||
@ -236,6 +241,9 @@
|
|||||||
<None Include="vendor\README.md">
|
<None Include="vendor\README.md">
|
||||||
<Filter>vendor</Filter>
|
<Filter>vendor</Filter>
|
||||||
</None>
|
</None>
|
||||||
|
<None Include="include\toml++\impl\path.inl">
|
||||||
|
<Filter>include\impl</Filter>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="docs">
|
<Filter Include="docs">
|
||||||
|
@ -117,6 +117,7 @@ def main():
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\at_path.cpp" />
|
<ClCompile Include="..\at_path.cpp" />
|
||||||
|
<ClCompile Include="..\path.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||||
|
Loading…
Reference in New Issue
Block a user