mirror of
https://github.com/marzer/tomlplusplus.git
synced 2024-09-07 07:29:39 +00:00
additonal path work
- re-ordered most of the `.inl` implementations to match the declaration order in the class body - fixed a few missing cases of `noexcept` - added additional operator overloads for += - added `operator==` and `operator!=` to `path_component` - changed parse method to "parse into" so it could be re-used in more places without creating a temporary vector - changed all binary operators to be 'hidden friends' - moved the "to string" logic to a "print_to" for streams to avoid creating a temporary string in the ostream<< operator - made the string conversion operators `explicit` - renamed `string()` to `str()` to be consistent with `toml::key` and `std::stringstream` - renamed `wstring()` to `wide_str()` to be consistent with `toml::source_region` - renamed `parent_path()` to `parent()` - removed the `const (w)char*` operator overloads - these were already sufficiently covered by the `std::(w)string_view` ones - removed the `operator/` overloads - since we aren't a file path the `/` doesn't have the same meaning (also `operator+` was doing the same thing)
This commit is contained in:
parent
f4c2749179
commit
3f4acc7c32
@ -20,8 +20,7 @@ template:
|
||||
|
||||
#### Additions:
|
||||
- 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
|
||||
- Added `toml::path` utility type (#153, #156) (@jonestristand)
|
||||
|
||||
#### Changes:
|
||||
- Relaxed cvref requirements of `is_homogeneous()`, `emplace()`, `emplace_back()`, `emplace_hint()`
|
||||
|
@ -107,7 +107,6 @@ TOML_NAMESPACE_START
|
||||
TOML_EXPORTED_FREE_FUNCTION
|
||||
node_view<const node> at_path(const node& root, const toml::path& path) noexcept;
|
||||
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Returns a view of the node matching a fully-qualified "TOML path".
|
||||
|
@ -71,7 +71,7 @@ TOML_ANON_NAMESPACE_START
|
||||
|
||||
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]
|
||||
// fail if unable to parse or entire index not parseable (otherwise would allow a[1bc] == a[1])
|
||||
if (fc_result.ec != std::errc{} || fc_result.ptr != index_str.data() + index_str.length())
|
||||
return nullptr;
|
||||
|
||||
@ -189,7 +189,7 @@ TOML_ANON_NAMESPACE_START
|
||||
|
||||
node* current = &root;
|
||||
|
||||
for (const auto& component: path)
|
||||
for (const auto& component : path)
|
||||
{
|
||||
auto type = component.type;
|
||||
if (type == path_component_type::array_index && std::holds_alternative<size_t>(component.value))
|
||||
@ -262,7 +262,6 @@ TOML_NAMESPACE_START
|
||||
return node_view<const node>{ TOML_ANON_NAMESPACE::get_at_path(const_cast<node&>(root), path) };
|
||||
}
|
||||
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
|
@ -6,15 +6,11 @@
|
||||
|
||||
#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
|
||||
{
|
||||
@ -31,6 +27,29 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
path_component_value value;
|
||||
path_component_type type;
|
||||
|
||||
private:
|
||||
/// \cond
|
||||
|
||||
TOML_PURE_GETTER
|
||||
TOML_EXPORTED_STATIC_FUNCTION
|
||||
static bool equal(const path_component&, const path_component&) noexcept;
|
||||
|
||||
/// \endcond
|
||||
public:
|
||||
/// \brief Returns true if two path components represent the same key or array index.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
friend bool operator==(const path_component& lhs, const path_component& rhs) noexcept
|
||||
{
|
||||
return equal(lhs, rhs);
|
||||
}
|
||||
|
||||
/// \brief Returns true if two path components do not represent the same key or array index.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
friend bool operator!=(const path_component& lhs, const path_component& rhs) noexcept
|
||||
{
|
||||
return !equal(lhs, rhs);
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief A TOML path.
|
||||
@ -50,18 +69,23 @@ TOML_NAMESPACE_START
|
||||
///
|
||||
/// \out
|
||||
/// second cat: lion
|
||||
/// cats: ['tiger', 'lion', 'puma']
|
||||
/// 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);
|
||||
static bool parse_into(std::string_view, std::vector<path_component>&);
|
||||
|
||||
TOML_EXPORTED_MEMBER_FUNCTION
|
||||
void print_to(std::ostream&) const;
|
||||
|
||||
TOML_PURE_GETTER
|
||||
TOML_EXPORTED_STATIC_FUNCTION
|
||||
static bool equal(const path&, const path&) noexcept;
|
||||
|
||||
/// \endcond
|
||||
|
||||
@ -70,138 +94,434 @@ TOML_NAMESPACE_START
|
||||
TOML_NODISCARD_CTOR
|
||||
path() noexcept = default;
|
||||
|
||||
/// \brief Construct from string
|
||||
/// \brief Construct a path by parsing from a string.
|
||||
TOML_NODISCARD_CTOR
|
||||
TOML_EXPORTED_MEMBER_FUNCTION
|
||||
explicit path(std::string_view);
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Construct a path by parsing from a string.
|
||||
///
|
||||
/// \availability This constructor is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
TOML_NODISCARD_CTOR
|
||||
TOML_EXPORTED_MEMBER_FUNCTION
|
||||
explicit path(std::wstring_view);
|
||||
|
||||
#endif
|
||||
|
||||
/// \brief Default destructor.
|
||||
~path() noexcept = default;
|
||||
|
||||
/// \brief Copy constructor.
|
||||
TOML_NODISCARD_CTOR
|
||||
path(const path& other) = default;
|
||||
path(const path&) = default;
|
||||
|
||||
/// \brief Move constructor.
|
||||
TOML_NODISCARD_CTOR
|
||||
path(path&& other) noexcept = default;
|
||||
path(path&&) noexcept = default;
|
||||
|
||||
/// \brief Returns the number of components in the path.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
size_t size() const noexcept
|
||||
{
|
||||
return components_.size();
|
||||
}
|
||||
|
||||
/// \brief Returns true if the path has one or more components.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
explicit operator bool() const noexcept
|
||||
{
|
||||
return !components_.empty();
|
||||
}
|
||||
|
||||
/// \brief Whether (true) or not (false) the path is empty
|
||||
TOML_PURE_INLINE_GETTER
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return components_.empty();
|
||||
}
|
||||
|
||||
/// \brief Fetch a path component by index for modification
|
||||
TOML_PURE_INLINE_GETTER
|
||||
path_component& operator[](size_t index) noexcept
|
||||
{
|
||||
return components_[index];
|
||||
}
|
||||
|
||||
/// \brief Fetch a path component by index
|
||||
TOML_PURE_INLINE_GETTER
|
||||
const path_component& operator[](size_t index) const noexcept
|
||||
{
|
||||
return components_[index];
|
||||
}
|
||||
|
||||
/// \name Assignment
|
||||
/// @{
|
||||
|
||||
/// \brief Copy-assignment operator.
|
||||
path& operator=(const path&) = default;
|
||||
|
||||
/// \brief Move-assignment operator.
|
||||
path& operator=(path&&) = default;
|
||||
path& operator=(path&&) noexcept = default;
|
||||
|
||||
/// \brief Append operator.
|
||||
/// \brief Replaces the contents of the path by parsing from a string.
|
||||
TOML_EXPORTED_MEMBER_FUNCTION
|
||||
path& operator/=(path&&) noexcept;
|
||||
path& operator=(std::string_view);
|
||||
|
||||
/// \brief Append operator.
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Replaces the contents of the path by parsing from a string.
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
TOML_EXPORTED_MEMBER_FUNCTION
|
||||
path& operator/=(std::string_view);
|
||||
path& operator=(std::wstring_view);
|
||||
|
||||
/// \brief Append operator.
|
||||
#endif
|
||||
|
||||
/// \brief Replaces the contents of the path with that of another.
|
||||
TOML_ALWAYS_INLINE
|
||||
path& assign(const path& p)
|
||||
{
|
||||
return *this = p;
|
||||
}
|
||||
|
||||
/// \brief Replaces the contents of the path with that of another.
|
||||
TOML_ALWAYS_INLINE
|
||||
path& assign(path&& p) noexcept
|
||||
{
|
||||
return *this = std::move(p);
|
||||
}
|
||||
|
||||
/// \brief Replaces the contents of the path object by a new path
|
||||
TOML_ALWAYS_INLINE
|
||||
path& assign(std::string_view str)
|
||||
{
|
||||
return *this = str;
|
||||
}
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Replaces the contents of the path object by a new path
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
TOML_ALWAYS_INLINE
|
||||
path& assign(std::wstring_view str)
|
||||
{
|
||||
return *this = str;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Appending
|
||||
/// @{
|
||||
|
||||
/// \brief Appends another path onto the end of this one.
|
||||
TOML_EXPORTED_MEMBER_FUNCTION
|
||||
path& operator+=(const path&);
|
||||
|
||||
/// \brief Appends another path onto the end of this one.
|
||||
TOML_EXPORTED_MEMBER_FUNCTION
|
||||
path& operator+=(path&&) noexcept;
|
||||
|
||||
/// \brief Append operator.
|
||||
/// \brief Parses a path and appends it onto the end of this one.
|
||||
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);
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Parses a path and appends it onto the end of this one.
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
TOML_EXPORTED_MEMBER_FUNCTION
|
||||
path& operator+=(std::wstring_view);
|
||||
|
||||
#endif
|
||||
|
||||
/// \brief Appends another path onto the end of this one.
|
||||
TOML_ALWAYS_INLINE
|
||||
path& append(const path& p)
|
||||
{
|
||||
return *this += p;
|
||||
}
|
||||
|
||||
/// \brief Appends another path onto the end of this one.
|
||||
TOML_ALWAYS_INLINE
|
||||
path& append(path&& p) noexcept
|
||||
{
|
||||
return *this += std::move(p);
|
||||
}
|
||||
|
||||
/// \brief Parses a path and appends it onto the end of this one.
|
||||
TOML_ALWAYS_INLINE
|
||||
path& append(std::string_view str)
|
||||
{
|
||||
return *this += str;
|
||||
}
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Parses a path and appends it onto the end of this one.
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
TOML_ALWAYS_INLINE
|
||||
path& append(std::wstring_view str)
|
||||
{
|
||||
return *this += str;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Prepending
|
||||
/// @{
|
||||
|
||||
/// \brief Prepends another path onto the beginning of this one.
|
||||
TOML_EXPORTED_MEMBER_FUNCTION
|
||||
path& prepend(const path&);
|
||||
|
||||
/// \brief Prepends another path onto the beginning of this one.
|
||||
TOML_EXPORTED_MEMBER_FUNCTION
|
||||
path& prepend(path&&);
|
||||
|
||||
/// \brief Parses a path and prepends it onto the beginning of this one.
|
||||
TOML_EXPORTED_MEMBER_FUNCTION
|
||||
path& prepend(std::string_view);
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Parses a path and prepends it onto the beginning of this one.
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
TOML_EXPORTED_MEMBER_FUNCTION
|
||||
path& prepend(std::wstring_view);
|
||||
|
||||
#endif
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Concatenation
|
||||
/// @{
|
||||
|
||||
/// \brief Concatenates two paths.
|
||||
TOML_NODISCARD
|
||||
friend path operator+(const path& lhs, const path& rhs)
|
||||
{
|
||||
path result = lhs;
|
||||
result += rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// \brief Concatenates two paths.
|
||||
TOML_NODISCARD
|
||||
/// \brief Append a path to the current path
|
||||
inline path operator/(const toml::path& rhs) const
|
||||
friend path operator+(const path& lhs, std::string_view rhs)
|
||||
{
|
||||
return *this + rhs;
|
||||
path result = lhs;
|
||||
result += rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// \brief Evaluate whether path parsing succeeded
|
||||
/// \brief Concatenates two paths.
|
||||
TOML_NODISCARD
|
||||
explicit inline operator bool() const noexcept
|
||||
friend path operator+(std::string_view lhs, const path& rhs)
|
||||
{
|
||||
return !parse_error_;
|
||||
};
|
||||
path result = rhs;
|
||||
result.prepend(lhs);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// \brief Implicitly cast to a std::string
|
||||
TOML_NODISCARD
|
||||
inline operator std::string() const { return string(); }
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Evaluate whether two paths are the same
|
||||
/// \brief Concatenates two paths.
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
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
|
||||
friend path operator+(const path& lhs, std::wstring_view rhs)
|
||||
{
|
||||
return components_[index];
|
||||
};
|
||||
path result = lhs;
|
||||
result += rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// \brief Fetch a path component by index
|
||||
/// \brief Concatenates two paths.
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
TOML_NODISCARD
|
||||
inline const path_component& operator[](size_t index) const noexcept
|
||||
friend path operator+(std::wstring_view lhs, const path& rhs)
|
||||
{
|
||||
return components_[index];
|
||||
};
|
||||
path result = rhs;
|
||||
result.prepend(lhs);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// \brief Number of components in the path
|
||||
TOML_NODISCARD
|
||||
inline size_t size() const noexcept
|
||||
#endif
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name String conversion
|
||||
/// @{
|
||||
|
||||
/// \brief Prints the string representation of a #toml::path out to a stream.
|
||||
TOML_ALWAYS_INLINE
|
||||
friend std::ostream& operator<<(std::ostream& os, const path& rhs)
|
||||
{
|
||||
return components_.size();
|
||||
};
|
||||
rhs.print_to(os);
|
||||
return os;
|
||||
}
|
||||
|
||||
/// \brief Whether (true) or not (false) the path is empty
|
||||
/// \brief Returns a string representation of this path.
|
||||
TOML_NODISCARD
|
||||
inline bool empty() const { return size() <= 0; }
|
||||
TOML_EXPORTED_MEMBER_FUNCTION
|
||||
std::string str() const;
|
||||
|
||||
/// \brief Returns a string representation of this path.
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
explicit operator std::string() const
|
||||
{
|
||||
return str();
|
||||
}
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Returns a string representation of this path.
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
TOML_NODISCARD
|
||||
TOML_EXPORTED_MEMBER_FUNCTION
|
||||
std::wstring wide_str() const;
|
||||
|
||||
/// \brief Returns a string representation of this path.
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
explicit operator std::wstring() const
|
||||
{
|
||||
return wide_str();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Equality
|
||||
/// @{
|
||||
|
||||
/// \brief Returns whether two paths are the same.
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
friend bool operator==(const path& lhs, const path& rhs) noexcept
|
||||
{
|
||||
return equal(lhs, rhs);
|
||||
}
|
||||
|
||||
/// \brief Returns whether two paths are not the same.
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
friend bool operator!=(const path& lhs, const path& rhs) noexcept
|
||||
{
|
||||
return !equal(lhs, rhs);
|
||||
}
|
||||
|
||||
/// \brief Returns whether two paths are the same.
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
friend bool operator==(const path& lhs, std::string_view rhs)
|
||||
{
|
||||
return lhs == path{ rhs };
|
||||
}
|
||||
|
||||
/// \brief Returns whether two paths are the same.
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
friend bool operator==(std::string_view lhs, const path& rhs)
|
||||
{
|
||||
return rhs == lhs;
|
||||
}
|
||||
|
||||
/// \brief Returns whether two paths are not the same.
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
friend bool operator!=(const path& lhs, std::string_view rhs)
|
||||
{
|
||||
return lhs != path{ rhs };
|
||||
}
|
||||
|
||||
/// \brief Returns whether two paths are not the same.
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
friend bool operator!=(std::string_view lhs, const path& rhs)
|
||||
{
|
||||
return rhs != lhs;
|
||||
}
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Returns whether two paths are the same.
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
friend bool operator==(const path& lhs, std::wstring_view rhs)
|
||||
{
|
||||
return lhs == path{ rhs };
|
||||
}
|
||||
|
||||
/// \brief Returns whether two paths are the same.
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
friend bool operator==(std::wstring_view lhs, const path& rhs)
|
||||
{
|
||||
return rhs == lhs;
|
||||
}
|
||||
|
||||
/// \brief Returns whether two paths are not the same.
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
friend bool operator!=(const path& lhs, std::wstring_view rhs)
|
||||
{
|
||||
return lhs != path{ rhs };
|
||||
}
|
||||
|
||||
/// \brief Returns whether two paths are not the same.
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
friend bool operator!=(std::wstring_view lhs, const path& rhs)
|
||||
{
|
||||
return rhs != lhs;
|
||||
}
|
||||
|
||||
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
/// @}
|
||||
|
||||
/// \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
|
||||
auto begin() const noexcept
|
||||
{
|
||||
return components_.begin();
|
||||
}
|
||||
|
||||
/// \brief Iterator at the end of the vector of path components (see #path_component)
|
||||
inline auto end() const noexcept { return components_.end(); }
|
||||
TOML_NODISCARD
|
||||
auto end() const noexcept
|
||||
{
|
||||
return components_.end();
|
||||
}
|
||||
|
||||
/// \brief Removes the number of terminal path components specified by n
|
||||
TOML_EXPORTED_MEMBER_FUNCTION
|
||||
@ -215,7 +535,7 @@ TOML_NAMESPACE_START
|
||||
/// \brief Returns a toml::path object representing the path of the parent node
|
||||
TOML_NODISCARD
|
||||
TOML_EXPORTED_MEMBER_FUNCTION
|
||||
path parent_path() const;
|
||||
path parent() const;
|
||||
|
||||
/// \brief Returns a toml::path object representing terminal n-parts of a TOML path
|
||||
TOML_NODISCARD
|
||||
@ -234,230 +554,6 @@ TOML_NAMESPACE_START
|
||||
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
|
||||
|
@ -3,6 +3,7 @@
|
||||
//# 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
|
||||
@ -11,110 +12,59 @@
|
||||
//# }}
|
||||
|
||||
#include "path.h"
|
||||
|
||||
TOML_DISABLE_WARNINGS;
|
||||
#include <sstream>
|
||||
#include <ostream>
|
||||
#include <istream>
|
||||
#if TOML_INT_CHARCONV
|
||||
#include <charconv>
|
||||
#endif
|
||||
TOML_ENABLE_WARNINGS;
|
||||
#include "print_to_stream.h"
|
||||
#include "header_start.h"
|
||||
|
||||
//#=====================================================================================================================
|
||||
//# toml::path_component
|
||||
//#=====================================================================================================================
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
path::path(std::string_view path_str)
|
||||
bool path_component::equal(const path_component& lhs, const path_component& rhs) noexcept
|
||||
{
|
||||
components_ = parse_(path_str, parse_error_);
|
||||
return lhs.type == rhs.type && lhs.value == rhs.value;
|
||||
}
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
//#=====================================================================================================================
|
||||
//# toml::path
|
||||
//#=====================================================================================================================
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
path& path::operator/=(path&& rhs) noexcept
|
||||
bool path::parse_into(std::string_view path_str, std::vector<path_component> & components)
|
||||
{
|
||||
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)
|
||||
// a blank string is a valid path; it's just one component representing the "" key
|
||||
if (path_str.empty())
|
||||
{
|
||||
if (components_[i].type != compare.components_[i].type
|
||||
|| components_[i].value != compare.components_[i].value)
|
||||
return false;
|
||||
components.emplace_back(path_component{ ""s, path_component_type::key });
|
||||
return true;
|
||||
}
|
||||
|
||||
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'
|
||||
|
||||
const auto parse_failed = [&, original_len = components.size()]() noexcept -> bool
|
||||
{
|
||||
if (components.size() > original_len)
|
||||
components.resize(original_len);
|
||||
return false;
|
||||
};
|
||||
|
||||
while (pos < end)
|
||||
{
|
||||
// start of an array indexer
|
||||
@ -125,9 +75,7 @@ TOML_NAMESPACE_START
|
||||
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;
|
||||
return parse_failed();
|
||||
}
|
||||
auto index_str = std::string_view(&path_str[index_start], index_end - index_start);
|
||||
|
||||
@ -136,9 +84,7 @@ TOML_NAMESPACE_START
|
||||
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;
|
||||
return parse_failed();
|
||||
}
|
||||
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);
|
||||
@ -153,12 +99,10 @@ TOML_NAMESPACE_START
|
||||
|
||||
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]
|
||||
// fail if unable to parse or entire index not parseable (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;
|
||||
return parse_failed();
|
||||
}
|
||||
|
||||
#else
|
||||
@ -168,9 +112,7 @@ TOML_NAMESPACE_START
|
||||
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;
|
||||
return parse_failed();
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -180,7 +122,7 @@ TOML_NAMESPACE_START
|
||||
prev_was_dot = false;
|
||||
prev_was_array_indexer = true;
|
||||
|
||||
parsed_components.emplace_back(path_component{ { index }, path_component_type::array_index });
|
||||
components.emplace_back(path_component{ { index }, path_component_type::array_index });
|
||||
}
|
||||
|
||||
// start of a new table child
|
||||
@ -196,7 +138,7 @@ TOML_NAMESPACE_START
|
||||
// "foo".""."bar"
|
||||
//
|
||||
if (prev_was_dot)
|
||||
parsed_components.emplace_back(path_component{ { ""s }, path_component_type::key });
|
||||
components.emplace_back(path_component{ ""s, path_component_type::key });
|
||||
|
||||
pos++;
|
||||
prev_was_dot = true;
|
||||
@ -229,9 +171,7 @@ TOML_NAMESPACE_START
|
||||
}
|
||||
else
|
||||
{
|
||||
parsed_components.clear(); // empty object in case of error
|
||||
parse_error = true;
|
||||
return parsed_components;
|
||||
return parse_failed();
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,25 +179,182 @@ TOML_NAMESPACE_START
|
||||
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
|
||||
});
|
||||
components.emplace_back(
|
||||
path_component{ std::string(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 });
|
||||
components.emplace_back(path_component{ ""s, path_component_type::key });
|
||||
}
|
||||
|
||||
return parsed_components;
|
||||
return true;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void path::print_to(std::ostream & os) const
|
||||
{
|
||||
bool root = true;
|
||||
for (const auto& component : components_)
|
||||
{
|
||||
if (component.type == path_component_type::key) // key
|
||||
{
|
||||
if (!root)
|
||||
impl::print_to_stream(os, '.');
|
||||
impl::print_to_stream(os, std::get<std::string>(component.value));
|
||||
}
|
||||
else if (component.type == path_component_type::array_index) // array
|
||||
{
|
||||
impl::print_to_stream(os, '[');
|
||||
impl::print_to_stream(os, std::get<size_t>(component.value));
|
||||
impl::print_to_stream(os, ']');
|
||||
}
|
||||
root = false;
|
||||
}
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool path::equal(const path& lhs, const path& rhs) noexcept
|
||||
{
|
||||
return lhs.components_ == rhs.components_;
|
||||
}
|
||||
|
||||
//#=== constructors =================================================
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
path::path(std::string_view str) //
|
||||
{
|
||||
parse_into(str, components_);
|
||||
}
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
path::path(std::wstring_view str) //
|
||||
: path(impl::narrow(str))
|
||||
{}
|
||||
|
||||
#endif
|
||||
|
||||
//#=== assignment =================================================
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
path& path::operator=(std::string_view rhs)
|
||||
{
|
||||
components_.clear();
|
||||
parse_into(rhs, components_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
path& path::operator=(std::wstring_view rhs)
|
||||
{
|
||||
return assign(impl::narrow(rhs));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//#=== appending =================================================
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
path& path::operator+=(const path& rhs)
|
||||
{
|
||||
components_.insert(components_.cend(), rhs.begin(), rhs.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
path& path::operator+=(path&& rhs) noexcept
|
||||
{
|
||||
components_.insert(components_.end(),
|
||||
std::make_move_iterator(rhs.components_.begin()),
|
||||
std::make_move_iterator(rhs.components_.end()));
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
path& path::operator+=(std::string_view str)
|
||||
{
|
||||
parse_into(str, components_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
path& path::operator+=(std::wstring_view str)
|
||||
{
|
||||
return *this += impl::narrow(str);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//#=== prepending =================================================
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
path& path::prepend(const path& source)
|
||||
{
|
||||
components_.insert(components_.begin(), source.components_.begin(), source.components_.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
path& path::prepend(path && source)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return prepend(path{ source });
|
||||
}
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
path& path::prepend(std::wstring_view source)
|
||||
{
|
||||
return prepend(impl::narrow(source));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//#=== string conversion =================================================
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
std::string path::str() const
|
||||
{
|
||||
if (empty())
|
||||
return "";
|
||||
|
||||
std::ostringstream ss;
|
||||
print_to(ss);
|
||||
return std::move(ss).str();
|
||||
}
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
std::wstring path::wide_str() const
|
||||
{
|
||||
return impl::widen(str());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//#=== equality and comparison =================================================
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void path::clear() noexcept
|
||||
{
|
||||
this->components_.clear();
|
||||
components_.clear();
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
@ -265,7 +362,7 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
n = n > components_.size() ? components_.size() : n;
|
||||
|
||||
auto it_end = components_.end();
|
||||
auto it_end = components_.end();
|
||||
components_.erase(it_end - static_cast<int>(n), it_end);
|
||||
|
||||
return *this;
|
||||
@ -274,7 +371,7 @@ TOML_NAMESPACE_START
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
path path::truncated(size_t n) const
|
||||
{
|
||||
path truncated_path {};
|
||||
path truncated_path{};
|
||||
|
||||
n = n > components_.size() ? components_.size() : n;
|
||||
|
||||
@ -288,9 +385,8 @@ TOML_NAMESPACE_START
|
||||
return truncated_path;
|
||||
}
|
||||
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
path path::parent_path() const
|
||||
path path::parent() const
|
||||
{
|
||||
return truncated(1);
|
||||
}
|
||||
@ -298,7 +394,7 @@ TOML_NAMESPACE_START
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
path path::leaf(size_t n) const
|
||||
{
|
||||
toml::path leaf_path {};
|
||||
path leaf_path{};
|
||||
|
||||
n = n > components_.size() ? components_.size() : n;
|
||||
|
||||
@ -316,15 +412,11 @@ TOML_NAMESPACE_START
|
||||
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;
|
||||
}
|
||||
if (start >= end)
|
||||
return {};
|
||||
|
||||
path subpath;
|
||||
subpath.components_.insert(subpath.components_.begin(), start, end);
|
||||
|
||||
return subpath;
|
||||
}
|
||||
|
||||
@ -333,208 +425,6 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
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;
|
||||
|
||||
|
@ -22,6 +22,7 @@ test_sources = [
|
||||
'parsing_spec_example.cpp',
|
||||
'parsing_strings.cpp',
|
||||
'parsing_tables.cpp',
|
||||
'path.cpp',
|
||||
'tests.cpp',
|
||||
'user_feedback.cpp',
|
||||
'using_iterators.cpp',
|
||||
|
316
tests/path.cpp
316
tests/path.cpp
@ -8,39 +8,37 @@ 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");
|
||||
CHECK(toml::path("").str() == "");
|
||||
CHECK(toml::path("[1]").str() == "[1]");
|
||||
CHECK(toml::path("[1][2]").str() == "[1][2]");
|
||||
CHECK(toml::path(" [1][2]").str() == " [1][2]");
|
||||
CHECK(toml::path("a. .b").str() == "a. .b");
|
||||
CHECK(toml::path("test[23]").str() == "test[23]");
|
||||
CHECK(toml::path("[ 120 ]").str() == "[120]");
|
||||
CHECK(toml::path("test.value").str() == "test.value");
|
||||
CHECK(toml::path("test[0].value").str() == "test[0].value");
|
||||
CHECK(toml::path("test[1][2]\t .value").str() == "test[1][2].value");
|
||||
CHECK(toml::path("test[1]\t[2].value").str() == "test[1][2].value");
|
||||
CHECK(toml::path(".test[1][2]\t ..value").str() == ".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");
|
||||
CHECK(toml::path(L"").str() == "");
|
||||
CHECK(toml::path(L"[1]").str() == "[1]");
|
||||
CHECK(toml::path(L"[1][2]").str() == "[1][2]");
|
||||
CHECK(toml::path(L" [1][2]").str() == " [1][2]");
|
||||
CHECK(toml::path(L"a. .b").str() == "a. .b");
|
||||
CHECK(toml::path(L"test[23]").str() == "test[23]");
|
||||
CHECK(toml::path(L"[ 120 ]").str() == "[120]");
|
||||
CHECK(toml::path(L"test.value").str() == "test.value");
|
||||
CHECK(toml::path(L"test[0].value").str() == "test[0].value");
|
||||
CHECK(toml::path(L"test[1][2]\t .value").str() == "test[1][2].value");
|
||||
CHECK(toml::path(L"test[1]\t[2].value").str() == "test[1][2].value");
|
||||
CHECK(toml::path(L".test[1][2]\t ..value").str() == ".test[1][2]..value");
|
||||
|
||||
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
}
|
||||
|
||||
SECTION("parsing - errors")
|
||||
@ -72,20 +70,18 @@ TEST_CASE("path - parsing")
|
||||
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(p0.str() == "a.b.c[1][12]");
|
||||
|
||||
CHECK("ab.cd[1]"_tpath == toml::path("ab.cd[1]"));
|
||||
|
||||
CHECK(("an.invalid.path[a1]"_tpath).string() == "");
|
||||
CHECK(("an.invalid.path[a1]"_tpath).str() == "");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE("path - manipulating")
|
||||
@ -93,113 +89,120 @@ TEST_CASE("path - manipulating")
|
||||
SECTION("parent_node and truncation")
|
||||
{
|
||||
toml::path p0("");
|
||||
CHECK(p0.parent_path().string() == "");
|
||||
CHECK(p0.parent().str() == "");
|
||||
|
||||
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() == "");
|
||||
CHECK(p1.parent().str() == "start.middle");
|
||||
CHECK(p1.parent().parent().str() == "start");
|
||||
CHECK(p1.parent().parent().parent().str() == "");
|
||||
CHECK(p1.parent().parent().parent().parent().str() == "");
|
||||
|
||||
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() == "");
|
||||
CHECK(p2.parent().str() == "[1][2]");
|
||||
CHECK(p2.parent().parent().str() == "[1]");
|
||||
CHECK(p2.parent().parent().parent().str() == "");
|
||||
|
||||
toml::path p3(".test");
|
||||
CHECK(p3.parent_path().string() == "");
|
||||
CHECK(p3.parent().str() == "");
|
||||
|
||||
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() == "");
|
||||
CHECK(p4.parent().str() == "test.");
|
||||
CHECK(p4.parent().parent().str() == "test");
|
||||
CHECK(p4.parent().parent().parent().str() == "");
|
||||
|
||||
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() == "");
|
||||
CHECK(p5.parent().str() == "test.key[12]");
|
||||
CHECK(p5.parent().parent().str() == "test.key");
|
||||
CHECK(p5.parent().parent().parent().str() == "test");
|
||||
CHECK(p5.parent().parent().parent().parent().str() == "");
|
||||
|
||||
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");
|
||||
CHECK(p6.truncated(0).str() == "test.key1.key2.key3.key4");
|
||||
CHECK(p6.truncated(1).str() == "test.key1.key2.key3");
|
||||
CHECK(p6.truncated(4).str() == "test");
|
||||
CHECK(p6.truncated(5).str() == "");
|
||||
CHECK(p6.truncated(20).str() == "");
|
||||
CHECK(p6.str() == "test.key1.key2.key3.key4");
|
||||
|
||||
p6.truncate(0);
|
||||
CHECK(p6.string() == "test.key1.key2.key3.key4");
|
||||
CHECK(p6.str() == "test.key1.key2.key3.key4");
|
||||
p6.truncate(2);
|
||||
CHECK(p6.string() == "test.key1.key2");
|
||||
CHECK(p6.str() == "test.key1.key2");
|
||||
p6.truncate(3);
|
||||
CHECK(p6.string() == "");
|
||||
|
||||
CHECK(p6.str() == "");
|
||||
}
|
||||
|
||||
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() + 1, p0.begin() + 4).str() == "simple[1].path");
|
||||
CHECK(p0.subpath(p0.begin() + 1, p0.end() - 1).str() == "simple[1].path[2]");
|
||||
CHECK(p0.subpath(p0.begin(), p0.begin()).str() == "");
|
||||
CHECK(p0.subpath(p0.begin(), p0.end() - 5).str() == "a");
|
||||
CHECK(p0.subpath(p0.begin() + 2, p0.end() - 1).str() == "[1].path[2]");
|
||||
|
||||
CHECK(p0.subpath(p0.begin() + 5, p0.end() - 5).string() == "");
|
||||
CHECK(p0.subpath(p0.end(), p0.begin()) == "");
|
||||
CHECK(p0.subpath(p0.begin() + 5, p0.end() - 5).str() == "");
|
||||
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]");
|
||||
CHECK(p0.subpath(1, 4).str() == "simple[1].path[2]");
|
||||
CHECK(p0.subpath(0, 0).str() == "");
|
||||
CHECK(p0.subpath(2, 0).str() == "");
|
||||
CHECK(p0.subpath(2, 1).str() == "[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");
|
||||
CHECK(p0.leaf(0).str() == "");
|
||||
CHECK(p0.leaf().str() == "five");
|
||||
CHECK(p0.leaf(3).str() == "three.four.five");
|
||||
CHECK(p0.leaf(5).str() == "one.two.three.four.five");
|
||||
CHECK(p0.leaf(10).str() == "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]");
|
||||
CHECK(p1.leaf(0).str() == "");
|
||||
CHECK(p1.leaf().str() == "[50]");
|
||||
CHECK(p1.leaf(3).str() == "[30][4][50]");
|
||||
CHECK(p1.leaf(5).str() == "[10][2][30][4][50]");
|
||||
CHECK(p1.leaf(10).str() == "[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]");
|
||||
CHECK(p2.leaf(0).str() == "");
|
||||
CHECK(p2.leaf().str() == "[3]");
|
||||
CHECK(p2.leaf(3).str() == "two.three[3]");
|
||||
CHECK(p2.leaf(4).str() == "[1].two.three[3]");
|
||||
CHECK(p2.leaf(10).str() == "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]");
|
||||
CHECK(p0.size() == 1u);
|
||||
CHECK(p0.append("middle.end").str() == "start.middle.end");
|
||||
CHECK(p0.append("[12]").str() == "start.middle.end[12]");
|
||||
|
||||
toml::path p1("");
|
||||
CHECK(p1.append("[1].key").string() == "[1].key");
|
||||
CHECK(p1.size() == 1u);
|
||||
p1.append("[1].key"sv);
|
||||
CHECK(p1.size() == 3u);
|
||||
CHECK(p1.str() == "[1].key"sv);
|
||||
|
||||
#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]");
|
||||
CHECK(p2.size() == 1u);
|
||||
CHECK(p2.append(L"middle.end").str() == "start.middle.end");
|
||||
CHECK(p2.append(L"[12]").str() == "start.middle.end[12]");
|
||||
|
||||
toml::path p3("");
|
||||
CHECK(p3.append(L"[1].key").string() == "[1].key");
|
||||
CHECK(p3.append(L"[1].key").str() == "[1].key");
|
||||
|
||||
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
toml::path p4;
|
||||
CHECK(p4.size() == 0u);
|
||||
CHECK(p4.append("[1].key").str() == "[1].key");
|
||||
}
|
||||
|
||||
SECTION("append - toml::path copy")
|
||||
@ -207,51 +210,55 @@ TEST_CASE("path - manipulating")
|
||||
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]");
|
||||
CHECK(p0.append(appendee1).str() == "start.middle.end");
|
||||
CHECK(p0.append(appendee2).str() == "start.middle.end[12]");
|
||||
|
||||
// Ensure copies and not moves
|
||||
CHECK(appendee1.string() == "middle.end");
|
||||
CHECK(appendee2.string() == "[12]");
|
||||
CHECK(appendee1.str() == "middle.end");
|
||||
CHECK(appendee2.str() == "[12]");
|
||||
|
||||
toml::path p1("");
|
||||
toml::path appendee3("[1].key");
|
||||
CHECK(p1.append(appendee3).string() == "[1].key");
|
||||
CHECK(p1.append(appendee3).str() == "[1].key");
|
||||
|
||||
// Ensure copies and not moves
|
||||
CHECK(appendee3.string() == "[1].key");
|
||||
CHECK(appendee3.str() == "[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]");
|
||||
CHECK(p0.append(toml::path{ "middle.end" }).str() == "start.middle.end");
|
||||
CHECK(p0.append(toml::path{ "[12]" }).str() == "start.middle.end[12]");
|
||||
|
||||
toml::path p1("");
|
||||
CHECK(p1.append(toml::path("[1].key")).string() == "[1].key");
|
||||
CHECK(p1.size() == 1u);
|
||||
CHECK(p1.append(toml::path{ "[1].key" }).str() == "[1].key");
|
||||
|
||||
toml::path p2;
|
||||
CHECK(p2.size() == 0u);
|
||||
CHECK(p2.append(toml::path{ "[1].key" }).str() == "[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");
|
||||
CHECK(p0.prepend("middle.end").str() == "middle.end.start");
|
||||
CHECK(p0.prepend("[12]").str() == "[12].middle.end.start");
|
||||
|
||||
toml::path p1("");
|
||||
CHECK(p1.prepend("[1].key").string() == "[1].key");
|
||||
toml::path p1;
|
||||
CHECK(p1.prepend("[1].key").str() == "[1].key");
|
||||
|
||||
toml::path p2("");
|
||||
CHECK(p2.prepend("[1].key").str() == "[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");
|
||||
toml::path p3("start");
|
||||
CHECK(p3.prepend(L"middle.end").str() == "middle.end.start");
|
||||
CHECK(p3.prepend(L"[12]").str() == "[12].middle.end.start");
|
||||
|
||||
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
}
|
||||
|
||||
SECTION("prepend - toml::path copy")
|
||||
@ -259,29 +266,29 @@ TEST_CASE("path - manipulating")
|
||||
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");
|
||||
CHECK(p0.prepend(prependee1).str() == "middle.end.start");
|
||||
CHECK(p0.prepend(prependee2).str() == "[12].middle.end.start");
|
||||
|
||||
// Ensure copies and not moves
|
||||
CHECK(prependee1.string() == "middle.end");
|
||||
CHECK(prependee2.string() == "[12]");
|
||||
CHECK(prependee1.str() == "middle.end");
|
||||
CHECK(prependee2.str() == "[12]");
|
||||
|
||||
toml::path p1("");
|
||||
toml::path p1;
|
||||
toml::path prependee3("[1].key");
|
||||
CHECK(p1.prepend(prependee3).string() == "[1].key");
|
||||
CHECK(p1.prepend(prependee3).str() == "[1].key");
|
||||
|
||||
// Ensure copies and not moves
|
||||
CHECK(prependee3.string() == "[1].key");
|
||||
CHECK(prependee3.str() == "[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");
|
||||
CHECK(p0.prepend(toml::path("middle.end")).str() == "middle.end.start");
|
||||
CHECK(p0.prepend(toml::path("[12]")).str() == "[12].middle.end.start");
|
||||
|
||||
toml::path p1("");
|
||||
CHECK(p1.prepend(toml::path("[1].key")).string() == "[1].key");
|
||||
toml::path p1;
|
||||
CHECK(p1.prepend(toml::path("[1].key")).str() == "[1].key");
|
||||
}
|
||||
|
||||
SECTION("alter components")
|
||||
@ -289,58 +296,56 @@ TEST_CASE("path - manipulating")
|
||||
toml::path p0("start.mid[1][2].end");
|
||||
|
||||
p0[3].value = std::size_t{ 13 };
|
||||
CHECK(p0.string() == "start.mid[1][13].end");
|
||||
CHECK(p0.str() == "start.mid[1][13].end");
|
||||
|
||||
p0[3].type = path_component_type::key;
|
||||
p0[3].type = path_component_type::key;
|
||||
p0[3].value = "newkey";
|
||||
CHECK(p0.string() == "start.mid[1].newkey.end");
|
||||
CHECK(p0.str() == "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");
|
||||
p0[0].type = path_component_type::array_index;
|
||||
CHECK(p0.str() == "[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]");
|
||||
CHECK(p0.str() == "test.key[1]");
|
||||
p0.assign("");
|
||||
CHECK(p0.string() == "");
|
||||
CHECK(p0.str() == "");
|
||||
|
||||
toml::path p1("a.test.path[1]");
|
||||
p1.assign("invalid[abc]");
|
||||
CHECK(!p1);
|
||||
CHECK(p1.string() == "");
|
||||
CHECK(p1.str() == "");
|
||||
|
||||
toml::path p2("another[1].test.path");
|
||||
p2.assign(toml::path("test"));
|
||||
CHECK(p2.string() == "test");
|
||||
CHECK(p2.str() == "test");
|
||||
p2.assign(toml::path(""));
|
||||
CHECK(p2.string() == "");
|
||||
CHECK(p2.str() == "");
|
||||
|
||||
toml::path p3("final.test[1]");
|
||||
p3.assign(toml::path("invalid[abc"));
|
||||
CHECK(!p3);
|
||||
CHECK(p3.string() == "");
|
||||
CHECK(p3.str() == "");
|
||||
|
||||
#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]");
|
||||
CHECK(p4.str() == "test.key[1]");
|
||||
p4.assign("");
|
||||
CHECK(p4.string() == "");
|
||||
CHECK(p4.str() == "");
|
||||
|
||||
toml::path p5("a.test.path[1]");
|
||||
p5.assign("invalid[abc]");
|
||||
CHECK(!p5);
|
||||
CHECK(p5.string() == "");
|
||||
CHECK(p5.str() == "");
|
||||
|
||||
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE("path - operators")
|
||||
@ -371,38 +376,30 @@ TEST_CASE("path - operators")
|
||||
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") + "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 + 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(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
|
||||
}
|
||||
@ -410,11 +407,15 @@ TEST_CASE("path - operators")
|
||||
|
||||
TEST_CASE("path - misc")
|
||||
{
|
||||
CHECK(toml::path{ "" }.str() == "");
|
||||
CHECK(toml::path{ "a" }.str() == "a");
|
||||
CHECK(toml::path{ "a.b" }.str() == "a.b");
|
||||
CHECK(toml::path{ "a.b.c" }.str() == "a.b.c");
|
||||
CHECK(toml::path{ ".a.b.c" }.str() == ".a.b.c");
|
||||
|
||||
CHECK(toml::path("a.b.c").string() == "a.b.c");
|
||||
|
||||
CHECK(!toml::path("a").empty());
|
||||
CHECK(toml::path("").empty());
|
||||
CHECK(toml::path{}.empty());
|
||||
CHECK(!toml::path{ "" }.empty());
|
||||
CHECK(!toml::path{ "a" }.empty());
|
||||
|
||||
CHECK(static_cast<std::string>(toml::path("a.b[1]")) == "a.b[1]");
|
||||
CHECK(static_cast<bool>(toml::path("a.b[1]")));
|
||||
@ -425,12 +426,10 @@ TEST_CASE("path - misc")
|
||||
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
|
||||
@ -493,11 +492,12 @@ TEST_CASE("path - accessing")
|
||||
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
|
||||
// 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["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")));
|
||||
@ -529,7 +529,7 @@ TEST_CASE("path - accessing")
|
||||
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
|
||||
// indexers
|
||||
|
||||
CHECK(tbl["b"][2]["c"]);
|
||||
CHECK(tbl["b"][2]["c"] == arr.at_path(toml::path("[2].c")));
|
||||
@ -562,12 +562,12 @@ TEST_CASE("path - accessing")
|
||||
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
|
||||
// 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
|
||||
// indexers
|
||||
|
||||
CHECK(tbl["d"]);
|
||||
CHECK(tbl["d"] == tbl[toml::path("d")]);
|
||||
|
Loading…
Reference in New Issue
Block a user