Skip to content

Commit 2acbcdd

Browse files
authored
Merge #1801 Add pnode equality operator
This PR adds pnode equality check operator (`operator ==` and `operator !=`) Related PR: #1801
2 parents e80ef1e + 7410fa6 commit 2acbcdd

File tree

3 files changed

+192
-3
lines changed

3 files changed

+192
-3
lines changed

core/config/property_tree.cpp

+31-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors
1+
// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors
22
//
33
// SPDX-License-Identifier: BSD-3-Clause
44

@@ -37,6 +37,36 @@ pnode::pnode(const map_type& map) : tag_(tag_t::map), map_(map) {}
3737

3838
pnode::operator bool() const noexcept { return tag_ != tag_t::empty; }
3939

40+
bool pnode::operator==(const pnode& rhs) const
41+
{
42+
if (tag_ == rhs.tag_) {
43+
switch (tag_) {
44+
case pnode::tag_t::empty:
45+
return true;
46+
case pnode::tag_t::array:
47+
return array_ == rhs.array_;
48+
case pnode::tag_t::map:
49+
return map_ == rhs.map_;
50+
case pnode::tag_t::string:
51+
return str_ == rhs.str_;
52+
case pnode::tag_t::boolean:
53+
return union_data_.boolean_ == rhs.union_data_.boolean_;
54+
case pnode::tag_t::real:
55+
return union_data_.real_ == rhs.union_data_.real_;
56+
case pnode::tag_t::integer:
57+
return union_data_.integer_ == rhs.union_data_.integer_;
58+
default:
59+
GKO_NOT_IMPLEMENTED;
60+
}
61+
}
62+
return false;
63+
}
64+
65+
bool pnode::operator!=(const pnode& rhs) const
66+
{
67+
return !(this->operator==(rhs));
68+
}
69+
4070

4171
pnode::tag_t pnode::get_tag() const { return tag_; }
4272

core/test/config/property_tree.cpp

+150-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors
1+
// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors
22
//
33
// SPDX-License-Identifier: BSD-3-Clause
44

@@ -181,3 +181,152 @@ TEST(PropertyTree, UseInCondition)
181181
ASSERT_EQ(first, 2);
182182
ASSERT_EQ(second, 1);
183183
}
184+
185+
186+
class PropertyTreeEquality : public ::testing::Test {
187+
protected:
188+
PropertyTreeEquality()
189+
{
190+
auto generator = [](auto&& vector) {
191+
// empty node
192+
vector.emplace_back(pnode());
193+
// boolean
194+
vector.emplace_back(pnode(true));
195+
// real
196+
vector.emplace_back(pnode(1.2));
197+
// integer
198+
vector.emplace_back(pnode(4));
199+
// string
200+
vector.emplace_back(pnode("123"));
201+
// array
202+
vector.emplace_back(
203+
pnode(pnode::array_type{pnode{"1"}, pnode{4}, pnode{true}}));
204+
// array2
205+
vector.emplace_back(
206+
pnode(pnode::array_type{pnode{"2"}, pnode{4}, pnode{true}}));
207+
// array3
208+
vector.emplace_back(
209+
pnode(pnode::array_type{pnode{"3"}, pnode{4}, pnode{true}}));
210+
// array4 with map
211+
vector.emplace_back(pnode(pnode::array_type{
212+
pnode(pnode::map_type{{"first", pnode{"1"}}})}));
213+
// array5 with array
214+
vector.emplace_back(
215+
pnode(pnode::array_type{pnode(pnode::array_type{pnode{"1"}})}));
216+
// map
217+
vector.emplace_back(pnode(pnode::map_type{{"first", pnode{"1"}},
218+
{"second", pnode{1.2}}}));
219+
// map2
220+
vector.emplace_back(pnode(pnode::map_type{{"first", pnode{"2"}},
221+
{"second", pnode{1.2}}}));
222+
// map3
223+
vector.emplace_back(pnode(pnode::map_type{{"first", pnode{"3"}},
224+
{"second", pnode{1.2}}}));
225+
// map4 with array
226+
vector.emplace_back(pnode(pnode::map_type{
227+
{"first", pnode(pnode::array_type{pnode{"1"}})}}));
228+
// map5 with map
229+
vector.emplace_back(pnode(pnode::map_type{
230+
{"first", pnode(pnode::map_type{{"first", pnode{"1"}}})}}));
231+
};
232+
// first and second have the same content
233+
generator(first);
234+
generator(second);
235+
// diff_content have different content but type still the same
236+
// still keep the empty node here for easy index mapping.
237+
// empty node
238+
diff_content.emplace_back(pnode());
239+
// boolean
240+
diff_content.emplace_back(pnode(false));
241+
// real
242+
diff_content.emplace_back(pnode(2.4));
243+
// integer
244+
diff_content.emplace_back(pnode(3));
245+
// string
246+
diff_content.emplace_back(pnode("456"));
247+
// array1 with different content
248+
diff_content.emplace_back(
249+
pnode(pnode::array_type{pnode{"456"}, pnode{3}, pnode{false}}));
250+
// array2 with different number of item
251+
diff_content.emplace_back(
252+
pnode(pnode::array_type{pnode{"2"}, pnode{4}}));
253+
// array3 with different order
254+
diff_content.emplace_back(
255+
pnode(pnode::array_type{pnode{4}, pnode{"3"}, pnode{true}}));
256+
// array4 with different map
257+
diff_content.emplace_back(pnode(
258+
pnode::array_type{pnode(pnode::map_type{{"first", pnode{"2"}}})}));
259+
// array5 with different array
260+
diff_content.emplace_back(
261+
pnode(pnode::array_type{pnode(pnode::array_type{pnode{"2"}})}));
262+
// map1 with different key
263+
diff_content.emplace_back(pnode(
264+
pnode::map_type{{"second", pnode{"1"}}, {"first", pnode{1.2}}}));
265+
// map2 with different number of item
266+
diff_content.emplace_back(
267+
pnode(pnode::map_type{{"first", pnode{"2"}}}));
268+
// map3 with different content
269+
diff_content.emplace_back(pnode(
270+
pnode::map_type{{"first", pnode{"456"}}, {"second", pnode{2.4}}}));
271+
// map4 with different array
272+
diff_content.emplace_back(pnode(
273+
pnode::map_type{{"first", pnode(pnode::array_type{pnode{"2"}})}}));
274+
// map5 with different map
275+
diff_content.emplace_back(pnode(pnode::map_type{
276+
{"first", pnode(pnode::map_type{{"first", pnode{"2"}}})}}));
277+
}
278+
std::vector<pnode> first;
279+
std::vector<pnode> second;
280+
std::vector<pnode> diff_content;
281+
};
282+
283+
284+
TEST_F(PropertyTreeEquality, CheckEquality)
285+
{
286+
ASSERT_EQ(first.size(), second.size());
287+
for (size_t i = 0; i < first.size(); i++) {
288+
for (size_t j = 0; j < second.size(); j++) {
289+
if (i == j) {
290+
ASSERT_EQ(first.at(i), second.at(j));
291+
} else {
292+
ASSERT_NE(first.at(i), second.at(j));
293+
}
294+
}
295+
}
296+
}
297+
298+
299+
TEST_F(PropertyTreeEquality, CheckEqualityOnlyContentDiff)
300+
{
301+
ASSERT_EQ(first.size(), diff_content.size());
302+
for (size_t i = 1; i < diff_content.size(); i++) {
303+
ASSERT_EQ(first.at(i).get_tag(), diff_content.at(i).get_tag());
304+
ASSERT_NE(first.at(i), diff_content.at(i));
305+
}
306+
}
307+
308+
309+
TEST_F(PropertyTreeEquality, CheckEqualityOfDiffOrderMap)
310+
{
311+
pnode map_1{pnode::map_type{{"first", first.at(5)},
312+
{"second", first.at(7)},
313+
{"third", first.at(8)},
314+
{"forth", first.at(9)}}};
315+
pnode map_2{pnode::map_type{{"first", first.at(5)},
316+
{"forth", first.at(9)},
317+
{"third", first.at(8)},
318+
{"second", first.at(7)}}};
319+
320+
// We use std::map is ordered map, so the input order does not affect the
321+
// equality
322+
ASSERT_EQ(map_1, map_2);
323+
}
324+
325+
326+
TEST_F(PropertyTreeEquality, CheckInequalityOfDiffOrderArray)
327+
{
328+
pnode array_1{pnode::array_type{first.at(5), first.at(6)}};
329+
pnode array_2{pnode::array_type{first.at(6), first.at(5)}};
330+
331+
ASSERT_NE(array_1, array_2);
332+
}

include/ginkgo/core/config/property_tree.hpp

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors
1+
// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors
22
//
33
// SPDX-License-Identifier: BSD-3-Clause
44

@@ -99,6 +99,16 @@ class pnode final {
9999
*/
100100
explicit operator bool() const noexcept;
101101

102+
/**
103+
* Check whether the representing data of two pnodes are the same
104+
*/
105+
bool operator==(const pnode& rhs) const;
106+
107+
/**
108+
* Check whether the representing data of two pnodes are different.
109+
*/
110+
bool operator!=(const pnode& rhs) const;
111+
102112
/**
103113
* Get the current node tag.
104114
*

0 commit comments

Comments
 (0)