-
Notifications
You must be signed in to change notification settings - Fork 94
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This PR adds an simple data structure which will be used in file config Related PR: #1389
- Loading branch information
Showing
8 changed files
with
551 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors | ||
// | ||
// SPDX-License-Identifier: BSD-3-Clause | ||
|
||
#include <ginkgo/core/config/property_tree.hpp> | ||
|
||
|
||
#include <ginkgo/core/base/exception_helpers.hpp> | ||
|
||
|
||
namespace gko { | ||
namespace config { | ||
|
||
|
||
pnode::pnode() : tag_(tag_t::empty) {} | ||
|
||
|
||
pnode::pnode(bool boolean) : tag_(tag_t::boolean) | ||
{ | ||
union_data_.boolean_ = boolean; | ||
} | ||
|
||
|
||
pnode::pnode(const std::string& str) : tag_(tag_t::string) { str_ = str; } | ||
|
||
|
||
pnode::pnode(double real) : tag_(tag_t::real) { union_data_.real_ = real; } | ||
|
||
|
||
pnode::pnode(const char* str) : pnode(std::string(str)) {} | ||
|
||
|
||
pnode::pnode(const array_type& array) : tag_(tag_t::array), array_(array) {} | ||
|
||
|
||
pnode::pnode(const map_type& map) : tag_(tag_t::map), map_(map) {} | ||
|
||
|
||
pnode::operator bool() const noexcept { return tag_ != tag_t::empty; } | ||
|
||
|
||
pnode::tag_t pnode::get_tag() const { return tag_; } | ||
|
||
const pnode::array_type& pnode::get_array() const | ||
{ | ||
this->throw_if_not_contain(tag_t::array); | ||
return array_; | ||
} | ||
|
||
|
||
const pnode::map_type& pnode::get_map() const | ||
{ | ||
this->throw_if_not_contain(tag_t::map); | ||
return map_; | ||
} | ||
|
||
|
||
bool pnode::get_boolean() const | ||
{ | ||
this->throw_if_not_contain(tag_t::boolean); | ||
return union_data_.boolean_; | ||
} | ||
|
||
|
||
std::int64_t pnode::get_integer() const | ||
{ | ||
this->throw_if_not_contain(tag_t::integer); | ||
return union_data_.integer_; | ||
} | ||
|
||
|
||
double pnode::get_real() const | ||
{ | ||
this->throw_if_not_contain(tag_t::real); | ||
return union_data_.real_; | ||
} | ||
|
||
|
||
const std::string& pnode::get_string() const | ||
{ | ||
this->throw_if_not_contain(tag_t::string); | ||
return str_; | ||
} | ||
|
||
|
||
const pnode& pnode::get(const std::string& key) const | ||
{ | ||
this->throw_if_not_contain(tag_t::map); | ||
auto it = map_.find(key); | ||
if (it != map_.end()) { | ||
return map_.at(key); | ||
} else { | ||
return pnode::empty_node(); | ||
} | ||
} | ||
|
||
const pnode& pnode::get(int index) const | ||
{ | ||
this->throw_if_not_contain(tag_t::array); | ||
return array_.at(index); | ||
} | ||
|
||
|
||
void pnode::throw_if_not_contain(tag_t tag) const | ||
{ | ||
static auto str_tag = [](tag_t tag) -> std::string { | ||
if (tag == tag_t::empty) { | ||
return "empty"; | ||
} else if (tag == tag_t::array) { | ||
return "array"; | ||
} else if (tag == tag_t::map) { | ||
return "map"; | ||
} else if (tag == tag_t::real) { | ||
return "real"; | ||
} else if (tag == tag_t::boolean) { | ||
return "boolean"; | ||
} else if (tag == tag_t::integer) { | ||
return "integer"; | ||
} else if (tag == tag_t::string) { | ||
return "string"; | ||
} else { | ||
return "unknown"; | ||
} | ||
}; | ||
bool is_valid = (tag_ == tag); | ||
std::string msg = | ||
"Contains " + str_tag(tag_) + ", but try to get " + str_tag(tag); | ||
GKO_THROW_IF_INVALID(is_valid, msg); | ||
} | ||
|
||
|
||
const pnode& pnode::empty_node() | ||
{ | ||
static pnode empty_pnode{}; | ||
return empty_pnode; | ||
} | ||
|
||
|
||
} // namespace config | ||
} // namespace gko |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
ginkgo_create_test(property_tree) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors | ||
// | ||
// SPDX-License-Identifier: BSD-3-Clause | ||
|
||
#include <ginkgo/core/config/property_tree.hpp> | ||
|
||
|
||
#include <cstdint> | ||
#include <exception> | ||
#include <limits> | ||
#include <memory> | ||
|
||
|
||
#include <gtest/gtest.h> | ||
|
||
|
||
#include <ginkgo/core/base/exception.hpp> | ||
|
||
|
||
using namespace gko::config; | ||
|
||
|
||
void assert_others_throw(const pnode& node) | ||
{ | ||
auto tag = node.get_tag(); | ||
if (tag != pnode::tag_t::array) { | ||
ASSERT_THROW(node.get_array(), gko::InvalidStateError); | ||
ASSERT_THROW(node.get(0), gko::InvalidStateError); | ||
} | ||
if (tag != pnode::tag_t::map) { | ||
ASSERT_THROW(node.get_map(), gko::InvalidStateError); | ||
ASSERT_THROW(node.get("random"), gko::InvalidStateError); | ||
} | ||
if (tag != pnode::tag_t::boolean) { | ||
ASSERT_THROW(node.get_boolean(), gko::InvalidStateError); | ||
} | ||
if (tag != pnode::tag_t::integer) { | ||
ASSERT_THROW(node.get_integer(), gko::InvalidStateError); | ||
} | ||
if (tag != pnode::tag_t::real) { | ||
ASSERT_THROW(node.get_real(), gko::InvalidStateError); | ||
} | ||
if (tag != pnode::tag_t::string) { | ||
ASSERT_THROW(node.get_string(), gko::InvalidStateError); | ||
} | ||
} | ||
|
||
|
||
TEST(PropertyTree, CreateEmpty) | ||
{ | ||
pnode root; | ||
|
||
ASSERT_EQ(root.get_tag(), pnode::tag_t::empty); | ||
assert_others_throw(root); | ||
} | ||
|
||
|
||
TEST(PropertyTree, CreateStringData) | ||
{ | ||
pnode str(std::string("test_name")); | ||
pnode char_str("test_name"); | ||
|
||
ASSERT_EQ(str.get_tag(), pnode::tag_t::string); | ||
ASSERT_EQ(str.get_string(), "test_name"); | ||
assert_others_throw(str); | ||
ASSERT_EQ(char_str.get_tag(), pnode::tag_t::string); | ||
ASSERT_EQ(char_str.get_string(), "test_name"); | ||
assert_others_throw(char_str); | ||
} | ||
|
||
|
||
TEST(PropertyTree, CreateBoolData) | ||
{ | ||
pnode boolean(true); | ||
|
||
ASSERT_EQ(boolean.get_tag(), pnode::tag_t::boolean); | ||
ASSERT_EQ(boolean.get_boolean(), true); | ||
assert_others_throw(boolean); | ||
} | ||
|
||
|
||
TEST(PropertyTree, CreateIntegerData) | ||
{ | ||
pnode integer(1); | ||
pnode integer_8(std::int8_t(1)); | ||
pnode integer_16(std::int16_t(1)); | ||
pnode integer_32(std::int32_t(1)); | ||
pnode integer_64(std::int64_t(1)); | ||
pnode integer_u8(std::uint8_t(1)); | ||
pnode integer_u16(std::uint16_t(1)); | ||
pnode integer_u32(std::uint32_t(1)); | ||
pnode integer_u64(std::uint64_t(1)); | ||
|
||
|
||
for (auto& node : {integer, integer_8, integer_16, integer_32, integer_64, | ||
integer_u8, integer_u16, integer_u32, integer_u64}) { | ||
ASSERT_EQ(node.get_tag(), pnode::tag_t::integer); | ||
ASSERT_EQ(node.get_integer(), 1); | ||
assert_others_throw(node); | ||
} | ||
ASSERT_THROW( | ||
pnode(std::uint64_t(std::numeric_limits<std::int64_t>::max()) + 1), | ||
std::runtime_error); | ||
} | ||
|
||
|
||
TEST(PropertyTree, CreateRealData) | ||
{ | ||
pnode real(1.0); | ||
pnode real_float(float(1.0)); | ||
pnode real_double(double(1.0)); | ||
|
||
for (auto& node : {real, real_double, real_float}) { | ||
ASSERT_EQ(node.get_tag(), pnode::tag_t::real); | ||
ASSERT_EQ(node.get_real(), 1.0); | ||
assert_others_throw(node); | ||
} | ||
} | ||
|
||
|
||
TEST(PropertyTree, CreateMap) | ||
{ | ||
pnode root({{"p0", pnode{1.0}}, | ||
{"p1", pnode{1}}, | ||
{"p2", pnode{pnode::map_type{{"p0", pnode{"test"}}}}}}); | ||
|
||
ASSERT_EQ(root.get_tag(), pnode::tag_t::map); | ||
ASSERT_EQ(root.get("p0").get_real(), 1.0); | ||
ASSERT_EQ(root.get("p1").get_integer(), 1); | ||
ASSERT_EQ(root.get("p2").get_tag(), pnode::tag_t::map); | ||
ASSERT_EQ(root.get("p2").get("p0").get_string(), "test"); | ||
assert_others_throw(root); | ||
} | ||
|
||
|
||
TEST(PropertyTree, CreateArray) | ||
{ | ||
pnode root(pnode::array_type{pnode{"123"}, pnode{"456"}, pnode{"789"}}); | ||
|
||
ASSERT_EQ(root.get_tag(), pnode::tag_t::array); | ||
ASSERT_EQ(root.get(0).get_string(), "123"); | ||
ASSERT_EQ(root.get(1).get_string(), "456"); | ||
ASSERT_EQ(root.get(2).get_string(), "789"); | ||
ASSERT_THROW(root.get(3), std::out_of_range); | ||
ASSERT_EQ(root.get_array().size(), 3); | ||
assert_others_throw(root); | ||
} | ||
|
||
|
||
TEST(PropertyTree, ConversionToBool) | ||
{ | ||
pnode empty; | ||
pnode non_empty{"test"}; | ||
|
||
ASSERT_FALSE(empty); | ||
ASSERT_TRUE(non_empty); | ||
} | ||
|
||
|
||
TEST(PropertyTree, ReturnEmptyIfNotFound) | ||
{ | ||
pnode ptree(pnode::map_type{{"test", pnode{2}}}); | ||
|
||
auto obj = ptree.get("na"); | ||
|
||
ASSERT_EQ(obj.get_tag(), pnode::tag_t::empty); | ||
} | ||
|
||
|
||
TEST(PropertyTree, UseInCondition) | ||
{ | ||
pnode ptree(pnode::map_type{{"test", pnode{2}}}); | ||
int first = 0; | ||
int second = 0; | ||
|
||
if (auto obj = ptree.get("test")) { | ||
first = static_cast<int>(obj.get_integer()); | ||
} | ||
if (auto obj = ptree.get("na")) { | ||
second = -1; | ||
} else { | ||
second = 1; | ||
} | ||
|
||
ASSERT_EQ(first, 2); | ||
ASSERT_EQ(second, 1); | ||
} |
Oops, something went wrong.