Files
tomlplusplus/include/toml++/toml_node_view.h
Mark Gillard 930bf0ad58 new file: .circleci/config.yml
new file:   .editorconfig
new file:   .gitattributes
new file:   .gitignore
new file:   .gitmodules
new file:   LICENSE
new file:   README.md
new file:   examples/example.cpp
new file:   examples/example.toml
new file:   examples/meson.build
new file:   include/toml++/toml.h
new file:   include/toml++/toml_array.h
new file:   include/toml++/toml_common.h
new file:   include/toml++/toml_formatter.h
new file:   include/toml++/toml_node.h
new file:   include/toml++/toml_node_view.h
new file:   include/toml++/toml_parser.h
new file:   include/toml++/toml_table.h
new file:   include/toml++/toml_utf8.h
new file:   include/toml++/toml_utf8_generated.h
new file:   include/toml++/toml_value.h
new file:   meson.build
new file:   python/ci_single_header_check.py
new file:   python/generate_single_header.py
new file:   python/generate_unicode_functions.py
new file:   tests/catch2
new file:   tests/catch2.h
new file:   tests/lifetimes.cpp
new file:   tests/main.cpp
new file:   tests/meson.build
new file:   tests/parsing_arrays.cpp
new file:   tests/parsing_booleans.cpp
new file:   tests/parsing_comments.cpp
new file:   tests/parsing_dates_and_times.cpp
new file:   tests/parsing_floats.cpp
new file:   tests/parsing_integers.cpp
new file:   tests/parsing_key_value_pairs.cpp
new file:   tests/parsing_spec_example.cpp
new file:   tests/parsing_strings.cpp
new file:   tests/parsing_tables.cpp
new file:   tests/tests.cpp
new file:   tests/tests.h
new file:   toml.hpp
new file:   vs/.runsettings
new file:   vs/example.vcxproj
new file:   vs/test_char.vcxproj
new file:   vs/test_char8.vcxproj
new file:   vs/test_char8_noexcept.vcxproj
new file:   vs/test_char_noexcept.vcxproj
new file:   vs/test_strict_char.vcxproj
new file:   vs/test_strict_char8.vcxproj
new file:   vs/test_strict_char8_noexcept.vcxproj
new file:   vs/test_strict_char_noexcept.vcxproj
new file:   vs/toml++.natvis
new file:   vs/toml++.props
new file:   vs/toml++.sln
new file:   vs/toml++.vcxproj
new file:   vs/toml++.vcxproj.filters
2020-01-04 16:21:38 +02:00

313 lines
9.0 KiB
C++

#pragma once
#include "toml_table.h"
#include "toml_array.h"
#include "toml_value.h"
namespace toml::impl
{
template <typename T>
struct node_view_traits;
template <>
struct node_view_traits<const table>
{
using member_type = const table*;
using key_type = string_view;
[[nodiscard]]
static const node* get(const table* tbl, key_type key) noexcept
{
return tbl->get(key);
}
template <typename U>
[[nodiscard]]
static const node_of<U>* as(const table* tbl, key_type key) noexcept
{
return tbl->get_as<U>(key);
}
};
template <>
struct node_view_traits<table>
{
using member_type = table*;
using key_type = string_view;
[[nodiscard]]
static node* get(table* tbl, key_type key) noexcept
{
return tbl->get(key);
}
[[nodiscard]]
static const node* get(const table* tbl, key_type key) noexcept
{
return tbl->get(key);
}
template <typename T>
[[nodiscard]]
static node_of<T>* as(table* tbl, key_type key) noexcept
{
return tbl->get_as<T>(key);
}
template <typename T>
[[nodiscard]]
static const node_of<T>* as(const table* tbl, key_type key) noexcept
{
return tbl->get_as<T>(key);
}
};
template <typename T, typename K>
struct sub_view final { };
template <typename T>
struct node_view_traits<sub_view<T, string_view>>
{
using member_type = T;
using key_type = string_view;
[[nodiscard]]
static auto get(member_type& view, string_view key) noexcept
{
auto parent = view.as_table();
return parent ? parent->get(key) : nullptr;
}
[[nodiscard]]
static const node* get(const member_type& view, string_view key) noexcept
{
auto parent = view.as_table();
return parent ? parent->get(key) : nullptr;
}
template <typename U>
[[nodiscard]]
static auto as(member_type& view, string_view key) noexcept
{
auto parent = view.as_table();
return parent ? parent->template get_as<U>(key) : nullptr;
}
template <typename U>
[[nodiscard]]
static const node_of<U>* as(const member_type& view, string_view key) noexcept
{
auto parent = view.as_table();
return parent ? parent->template get_as<U>(key) : nullptr;
}
};
template <typename T>
struct node_view_traits<sub_view<T, size_t>>
{
using member_type = T;
using key_type = size_t;
[[nodiscard]]
static auto get(member_type& view, size_t index) noexcept
{
auto parent = view.as_array();
return parent ? parent->get(index) : nullptr;
}
[[nodiscard]]
static const node* get(const member_type& view, size_t index) noexcept
{
auto parent = view.as_array();
return parent ? parent->get(index) : nullptr;
}
template <typename U>
[[nodiscard]]
static auto as(member_type& view, size_t index) noexcept
{
auto parent = view.as_array();
return parent ? parent->template get_as<U>(index) : nullptr;
}
template <typename U>
[[nodiscard]]
static const node_of<U>* as(const member_type& view, size_t index) noexcept
{
auto parent = view.as_array();
return parent ? parent->template get_as<U>(index) : nullptr;
}
};
}
namespace toml
{
template <typename T>
class node_view final
{
public:
using traits = impl::node_view_traits<T>;
using key_type = typename traits::key_type;
private:
using member_type = typename traits::member_type;
member_type obj_;
key_type key_;
public:
TOML_NODISCARD_CTOR
node_view(member_type obj, key_type key) noexcept
: obj_{ obj },
key_{ key }
{}
[[nodiscard]] auto get() noexcept { return traits::get(obj_, key_); }
[[nodiscard]] const node* get() const noexcept { return traits::get(obj_, key_); }
[[nodiscard]] explicit operator bool() const noexcept { return !!get(); }
template <typename U>
[[nodiscard]]
auto as() noexcept
{
static_assert(
impl::is_value_or_node<U>,
"Template type parameter must be one of the basic value types, a toml::table, or a toml::array"
);
return traits::template as<U>(obj_, key_);
}
template <typename U>
[[nodiscard]]
const node_of<U>* as() const noexcept
{
static_assert(
impl::is_value_or_node<U>,
"Template type parameter must be one of the basic value types, a toml::table, or a toml::array"
);
return traits::template as<U>(obj_, key_);
}
[[nodiscard]] auto as_string() noexcept { return as<string>(); }
[[nodiscard]] auto as_integer() noexcept { return as<int64_t>(); }
[[nodiscard]] auto as_floating_point() noexcept { return as<double>(); }
[[nodiscard]] auto as_boolean() noexcept { return as<bool>(); }
[[nodiscard]] auto as_date() noexcept { return as<date>(); }
[[nodiscard]] auto as_time() noexcept { return as<time>(); }
[[nodiscard]] auto as_date_time() noexcept { return as<date_time>(); }
[[nodiscard]] auto as_array() noexcept { return as<array>(); }
[[nodiscard]] auto as_table() noexcept { return as<table>(); }
[[nodiscard]] const value<string>* as_string() const noexcept { return as<string>(); }
[[nodiscard]] const value<int64_t>* as_integer() const noexcept { return as<int64_t>(); }
[[nodiscard]] const value<double>* as_floating_point() const noexcept { return as<double>(); }
[[nodiscard]] const value<bool>* as_boolean() const noexcept { return as<bool>(); }
[[nodiscard]] const value<date>* as_date() const noexcept { return as<date>(); }
[[nodiscard]] const value<time>* as_time() const noexcept { return as<time>(); }
[[nodiscard]] const value<date_time>* as_date_time() const noexcept { return as<date_time>(); }
[[nodiscard]] const array* as_array() const noexcept { return as<array>(); }
[[nodiscard]] const table* as_table() const noexcept { return as<table>(); }
private:
template <typename U>
[[nodiscard]]
static bool value_equality(const node_view& lhs, const U& rhs) noexcept
{
const auto val = lhs.as<value_of<U>>();
return val && val->get() == rhs;
}
template <typename U>
[[nodiscard]]
static bool container_equality(const node_view& lhs, const U& rhs) noexcept
{
using elem_t = std::remove_const_t<typename U::value_type>;
static_assert(
impl::is_value_or_promotable<elem_t>,
"Container element type must be (or be convertible to) one of the basic value types"
);
const array* arr = lhs.as<array>();
if (!arr || arr->size() != rhs.size())
return false;
if (rhs.size() == 0_sz)
return true;
size_t i{};
for (auto& list_elem : rhs)
{
const auto elem = arr->get_as<value_of<elem_t>>(i++);
if (!elem || elem->get() != list_elem)
return false;
}
return true;
}
public:
[[nodiscard]] bool operator == (const string& rhs) const noexcept { return value_equality(*this, rhs); }
[[nodiscard]] bool operator == (string_view rhs) const noexcept { return value_equality(*this, rhs); }
[[nodiscard]] bool operator == (int64_t rhs) const noexcept { return value_equality(*this, rhs); }
[[nodiscard]] bool operator == (int32_t rhs) const noexcept { return value_equality(*this, rhs); }
[[nodiscard]] bool operator == (int16_t rhs) const noexcept { return value_equality(*this, rhs); }
[[nodiscard]] bool operator == (int8_t rhs) const noexcept { return value_equality(*this, rhs); }
[[nodiscard]] bool operator == (uint32_t rhs) const noexcept { return value_equality(*this, rhs); }
[[nodiscard]] bool operator == (uint16_t rhs) const noexcept { return value_equality(*this, rhs); }
[[nodiscard]] bool operator == (uint8_t rhs) const noexcept { return value_equality(*this, rhs); }
[[nodiscard]] bool operator == (double rhs) const noexcept { return value_equality(*this, rhs); }
[[nodiscard]] bool operator == (float rhs) const noexcept { return value_equality(*this, rhs); }
[[nodiscard]] bool operator == (bool rhs) const noexcept { return value_equality(*this, rhs); }
[[nodiscard]] bool operator == (const date& rhs) const noexcept { return value_equality(*this, rhs); }
[[nodiscard]] bool operator == (const time& rhs) const noexcept { return value_equality(*this, rhs); }
[[nodiscard]] bool operator == (const date_time& rhs) const noexcept { return value_equality(*this, rhs); }
template <typename U>
[[nodiscard]]
bool operator == (const std::initializer_list<U>& rhs) const noexcept
{
return container_equality(*this, rhs);
}
template <typename U>
[[nodiscard]]
bool operator == (const std::vector<U>& rhs) const noexcept
{
return container_equality(*this, rhs);
}
template <typename U>
[[nodiscard]]
friend bool operator == (const U& lhs, const node_view& rhs) noexcept
{
return rhs == lhs;
}
[[nodiscard]]
node_view<impl::sub_view<node_view<T>, string_view>> operator[] (string_view key) noexcept
{
return { *this, key };
}
[[nodiscard]]
node_view<impl::sub_view<node_view<T>, size_t>> operator[] (size_t index) noexcept
{
return { *this, index };
}
};
inline node_view<table> table::operator[] (string_view key) noexcept
{
return { this, key };
}
inline node_view<const table> table::operator[] (string_view key) const noexcept
{
return { this, key };
}
}