Skip to content

Commit

Permalink
make as_TYPE api templated
Browse files Browse the repository at this point in the history
  • Loading branch information
asdetrefle committed Apr 24, 2020
1 parent 28e30ac commit 0a7c0bd
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 119 deletions.
21 changes: 7 additions & 14 deletions include/tominal/toml_array.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,31 +147,24 @@ class array final : public node
std::vector<U> result;
for (const auto &n : nodes_)
{
if constexpr (is_value_promotable<T>)
if constexpr (std::is_same_v<T, node_view>)
{
if (const auto val = n->template value<U>())
{
result.emplace_back(val.value());
}
result.emplace_back(n->view());
}
else if constexpr (std::is_same_v<T, array>)
else if constexpr (is_one_of_v<T, array, table>)
{
if (const auto arr = n->as_array())
if (const auto arr = n->template as<T>())
{
result.emplace_back(std::move(arr));
}
}
else if constexpr (std::is_same_v<T, table>)
else if constexpr (is_value_promotable<std::decay_t<T>>)
{
if (const auto tbl = n->as_table())
if (const auto val = n->template as<U>())
{
result.emplace_back(std::move(tbl));
result.emplace_back(val.value());
}
}
else if constexpr (std::is_same_v<T, node_view>)
{
result.emplace_back(n->view());
}
}
return result;
}
Expand Down
95 changes: 27 additions & 68 deletions include/tominal/toml_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,57 +78,41 @@ class node : public std::enable_shared_from_this<node>
}
}

std::shared_ptr<array> as_array()
{
if (is_array())
{
return std::static_pointer_cast<toml::array>(shared_from_this());
}
else
{
return nullptr;
}
}
template <typename T>
inline std::optional<T> value() const noexcept; // implemented in toml_value.h

std::shared_ptr<const array> as_array() const
template <typename T, typename U = typename value_type_traits<std::decay_t<T>>::type>
std::enable_if_t<is_value_promotable<std::decay_t<T>>, std::optional<U>> as() const
{
if (is_array())
{
return std::static_pointer_cast<const toml::array>(shared_from_this());
}
else
{
return nullptr;
}
return this->template value<U>();
}

std::shared_ptr<table> as_table()
template <typename T>
std::enable_if_t<is_one_of_v<std::remove_cv_t<T>, array, table>, std::shared_ptr<T>> as()
{
if (is_table())
if (is_array() || is_table())
{
return std::static_pointer_cast<toml::table>(shared_from_this());
return std::static_pointer_cast<std::remove_cv_t<T>>(shared_from_this());
}
else
{
return nullptr;
}
}

std::shared_ptr<const table> as_table() const
template <typename T>
std::enable_if_t<is_one_of_v<std::remove_cv_t<T>, array, table>, std::shared_ptr<std::add_const_t<T>>> as() const
{
if (is_table())
if (is_array() || is_table())
{
return std::static_pointer_cast<const toml::table>(shared_from_this());
return std::static_pointer_cast<std::add_const_t<T>>(shared_from_this());
}
else
{
return nullptr;
}
}

template <typename T>
inline std::optional<T> value() const noexcept; // implemented in toml_value.h

template <typename T, typename U = typename value_type_traits<std::decay_t<T>>::type>
inline auto value_or(T &&default_value) const noexcept
{
Expand All @@ -155,63 +139,38 @@ class node : public std::enable_shared_from_this<node>
typename = std::enable_if_t<!std::is_void_v<U>>>
std::optional<U> map(F &&f) const
{
if constexpr (is_value_promotable<T>)
if constexpr (std::is_same_v<T, node_view>)
{
if (const auto val = this->template value<T>())
{
return {f(val.value())};
}
return {f(this->view())};
}
else if constexpr (std::is_same_v<T, array>)
else
{
if (const auto arr = this->as_array())
if (const auto val = this->template as<T>())
{
return {f(*arr)};
return {f(*val)};
}
}
else if constexpr (std::is_same_v<T, table>)
{
if (const auto tbl = this->as_table())
else
{
return {f(*tbl)};
return std::nullopt;
}
}
else if constexpr (std::is_same_v<T, node_view>)
{
return {f(this->view())};
}
return std::nullopt;
}

template <typename T, typename F, typename U = std::invoke_result_t<F, const T &>,
typename = std::enable_if_t<std::is_void_v<U>>>
void map(F &&f) const
{
if constexpr (is_value_promotable<T>)
{
if (const auto val = this->template value<T>())
{
f(val.value());
}
}
else if constexpr (std::is_same_v<T, array>)
if constexpr (std::is_same_v<T, node_view>)
{
if (const auto arr = this->as_array())
{
f(*arr);
}
f(this->view());
}
else if constexpr (std::is_same_v<T, table>)
else
{
if (const auto tbl = this->as_table())
if (const auto val = this->template as<T>())
{
f(*tbl);
f(val.value());
}
}
else if constexpr (std::is_same_v<T, node_view>)
{
f(this->view());
}
}

template <class Visitor, class... Args>
Expand Down Expand Up @@ -268,12 +227,12 @@ void node::accept(Visitor &&visitor, Args &&... args) const
}
else if (is_table())
{
visitor.visit(static_cast<const toml::table &>(*as_table()),
visitor.visit(static_cast<const toml::table &>(*as<table>()),
std::forward<Args>(args)...);
}
else if (is_array())
{
visitor.visit(static_cast<const toml::array &>(*as_array()),
visitor.visit(static_cast<const toml::array &>(*as<array>()),
std::forward<Args>(args)...);
}
}
Expand Down
41 changes: 13 additions & 28 deletions include/tominal/toml_node_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,19 +64,16 @@ class node_view final
return node_ ? node_->template as_value<T>() : nullptr;
}

auto as_array() const
{
return node_ ? node_->as_array() : nullptr;
}

auto as_table() const
template <class T>
auto as() const
{
return node_ ? node_->as_table() : nullptr;
using return_type = decltype(node_->template as<T>());
return node_ ? node_->as<T>() : return_type{};
}

bool contains(std::string_view key) const
{
if (auto tbl = as_table())
if (auto tbl = as<table>())
{
return tbl->contains(key);
}
Expand All @@ -86,31 +83,19 @@ class node_view final
}
}

template <typename U>
std::optional<U> value() const noexcept
template <typename T>
std::optional<T> value() const noexcept
{
if (node_)
{
return node_->template value<U>();
return node_->template value<T>();
}
else
{
return {};
}
}

template <typename U>
auto expect() const
{
auto val = this->template value<U>();

if (!val)
{
throw std::runtime_error("toml::node_view is expecting a missing value");
}
return val.value();
}

template <typename T>
auto value_or(T &&default_value) const noexcept
{
Expand All @@ -126,7 +111,7 @@ class node_view final
}

template <typename T>
inline auto value_or_default() const noexcept
auto value_or_default() const noexcept
{
using return_type = decltype(node_->value_or_default<T>());

Expand All @@ -138,7 +123,7 @@ class node_view final
node_view result{nullptr};
auto position = key.find('.');

if (auto tbl = this->as_table())
if (auto tbl = this->as<table>())
{
result = node_view(tbl->at(key.substr(0, position)));
}
Expand All @@ -155,7 +140,7 @@ class node_view final

node_view operator[](size_t index) const
{
if (auto arr = this->as_array())
if (auto arr = this->as<array>())
{
return {(*arr)[index]};
}
Expand Down Expand Up @@ -185,7 +170,7 @@ class node_view final
template <typename T, typename U = typename value_type_traits<T>::type>
std::vector<U> collect() const
{
if (auto arr = this->as_array())
if (auto arr = this->as<array>())
{
return arr->template collect<T>();
}
Expand All @@ -199,7 +184,7 @@ class node_view final
typename = std::enable_if_t<!std::is_void_v<U>>>
std::vector<U> map_collect(F &&f) const
{
if (auto arr = this->as_array())
if (auto arr = this->as<array>())
{
return arr->template map_collect<T>(f);
}
Expand Down
14 changes: 7 additions & 7 deletions include/tominal/toml_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ class parser
if (b->is_table())
curr_table = static_cast<table *>(b.get());
else if (b->is_table_array())
curr_table = b->as_array()->back()->as_table().get();
curr_table = b->as<array>()->back()->as<table>().get();
else
throw_parse_exception("Key " + full_table_name + "already exists as a value");
}
Expand Down Expand Up @@ -377,25 +377,25 @@ class parser
throw_parse_exception("key `" + full_ta_name + "` is not a table array");
}

auto v = b->as_array();
auto v = b->as<array>();
for (auto it = v->begin(); it != v->end(); ++it)
{
if ((*it)->as_table()->is_inline())
if ((*it)->as<table>()->is_inline())
{
throw_parse_exception("static table array `" + full_ta_name + "` cannot be appended to");
}
}

v->push_back(make_table());
curr_table = v->back()->as_table().get();
curr_table = v->back()->as<table>().get();
}
// otherwise, just keep traversing down the key name
else
{
if (b->is_table())
curr_table = static_cast<table *>(b.get());
else if (b->is_table_array())
curr_table = b->as_array()->back()->as_table().get();
curr_table = b->as<array>()->back()->as<table>().get();
else
throw_parse_exception("Key " + full_ta_name + " already exists as a value");
}
Expand All @@ -410,7 +410,7 @@ class parser
auto arr = make_array();
arr->push_back(make_table());
auto [it, success] = curr_table->emplace(part, std::move(arr));
curr_table = it->second->as_array()->back()->as_table().get();
curr_table = it->second->as<array>()->back()->as<table>().get();
}
// otherwise, create the implicitly defined table and move
// down to it
Expand Down Expand Up @@ -459,7 +459,7 @@ class parser
else
{
auto [it, success] = curr_table->emplace(part, make_table());
curr_table = it->second->as_table().get();
curr_table = it->second->as<table>().get();
}
};

Expand Down
4 changes: 2 additions & 2 deletions include/tominal/toml_writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ class toml_writer
{
for (size_t i = 0; i < a.size(); ++i)
{
a.at(i)->as_table()->accept(*this, true);
a.at(i)->as<table>()->accept(*this, true);
}
}
else
Expand All @@ -114,7 +114,7 @@ class toml_writer

if (auto n = a.at(i); n->is_array())
{
n->as_array()->accept(*this, true);
n->as<array>()->accept(*this, true);
}
else
{
Expand Down

0 comments on commit 0a7c0bd

Please sign in to comment.