Skip to content

Commit c5ef975

Browse files
committed
Add support for range to construct json_arrayt and json_objectt
The end result of this commit is that code like the following example can be used to construct `json_arrayt` / `json_objectt` - ``` const std::vector<std::string> input{"foo", "bar"}; const auto json_array = make_range(input) .map(constructor_of<json_stringt>()) .collect<json_arrayt>(); ``` This commit includes - * Constructors from iterators for json_arrayt and json_objectt, so that the iterators from a range can be used to construct these classes. * A `collect` member function for `ranget`, so that a chain of range operations can finish with the construction of a resulting container containing a collection of the results. * A `constructor_of` template function, which provides syntactic sugar when using `map` to call a constructor, compared to writing a new lambda function each time such an operation is carried out. * Unit tests covering all of the above functionality.
1 parent ddbc2b9 commit c5ef975

File tree

5 files changed

+115
-0
lines changed

5 files changed

+115
-0
lines changed

src/util/constructor_of.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*******************************************************************\
2+
3+
Module: constructor_of
4+
5+
Author: Diffblue Ltd.
6+
7+
\*******************************************************************/
8+
9+
#ifndef CPROVER_UTIL_CONSTRUCTOR_OF_H
10+
#define CPROVER_UTIL_CONSTRUCTOR_OF_H
11+
12+
/// A type of functor which wraps around the set of constructors of a type.
13+
/// \tparam constructedt: The type which this functor constructs.
14+
template <typename constructedt>
15+
class constructort final
16+
{
17+
public:
18+
template <typename... argumentst>
19+
constructedt operator()(argumentst &&... arguments)
20+
{
21+
return constructedt{std::forward<argumentst...>(arguments...)};
22+
}
23+
};
24+
25+
/// \tparam constructedt: A type for construction.
26+
/// \brief Returns a functor which constructs type `constructedt`.
27+
template <typename constructedt>
28+
constexpr constructort<constructedt> constructor_of()
29+
{
30+
return {};
31+
}
32+
33+
#endif // CPROVER_UTIL_CONSTRUCTOR_OF_H

src/util/json.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,13 @@ class json_arrayt:public jsont
170170
{
171171
}
172172

173+
template <typename begin_iteratort, typename end_iteratort>
174+
json_arrayt(begin_iteratort &&begin_iterator, end_iteratort &&end_iterator)
175+
: json_arrayt{arrayt{std::forward<begin_iteratort>(begin_iterator),
176+
std::forward<end_iteratort>(end_iterator)}}
177+
{
178+
}
179+
173180
void resize(std::size_t size)
174181
{
175182
array.resize(size);
@@ -294,6 +301,13 @@ class json_objectt:public jsont
294301
{
295302
}
296303

304+
template <typename begin_iteratort, typename end_iteratort>
305+
json_objectt(begin_iteratort &&begin_iterator, end_iteratort &&end_iterator)
306+
: json_objectt{{std::forward<begin_iteratort>(begin_iterator),
307+
std::forward<end_iteratort>(end_iterator)}}
308+
{
309+
}
310+
297311
jsont &operator[](const std::string &key)
298312
{
299313
return object[key];

src/util/range.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,14 @@ struct ranget final
351351
return end_value;
352352
}
353353

354+
/// Constructs a collection containing the values, which this range iterates
355+
/// over.
356+
template <typename containert>
357+
containert collect() const
358+
{
359+
return {begin(), end()};
360+
}
361+
354362
private:
355363
iteratort begin_value;
356364
iteratort end_value;

unit/util/json_array.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@ Author: Diffblue Ltd.
77
\*******************************************************************/
88

99
#include <testing-utils/catch.hpp>
10+
#include <util/constructor_of.h>
1011
#include <util/json.h>
12+
#include <util/range.h>
13+
14+
#include <string>
15+
#include <vector>
1116

1217
SCENARIO(
1318
"Test that json_arrayt can be constructed from an initializer list.",
@@ -33,3 +38,29 @@ SCENARIO(
3338
}
3439
}
3540
}
41+
42+
SCENARIO(
43+
"Test that json_arrayt can be constructed using `ranget`",
44+
"[core][util][json]")
45+
{
46+
GIVEN("A vector of strings.")
47+
{
48+
const std::vector<std::string> input{"foo", "bar"};
49+
THEN(
50+
"A json_arrayt can be constructed from the vector of strings using range "
51+
"and map.")
52+
{
53+
const json_arrayt array = make_range(input)
54+
.map(constructor_of<json_stringt>())
55+
.collect<json_arrayt>();
56+
auto it = array.begin();
57+
REQUIRE(it->kind == jsont::kindt::J_STRING);
58+
REQUIRE(it->value == "foo");
59+
++it;
60+
REQUIRE(it->kind == jsont::kindt::J_STRING);
61+
REQUIRE(it->value == "bar");
62+
++it;
63+
REQUIRE(it == array.end());
64+
}
65+
}
66+
}

unit/util/json_object.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@ Author: Diffblue Ltd.
1010
#include <util/json.h>
1111
#include <util/optional.h>
1212
#include <util/optional_utils.h>
13+
#include <util/range.h>
1314

1415
#include <algorithm>
1516
#include <iterator>
17+
#include <string>
18+
#include <vector>
1619

1720
SCENARIO(
1821
"Test that json_objectt is compatible with STL algorithms",
@@ -73,3 +76,29 @@ SCENARIO(
7376
}
7477
}
7578
}
79+
80+
SCENARIO("Test that json_objectt can be constructed using `ranget`")
81+
{
82+
GIVEN("A vector of numbers.")
83+
{
84+
const std::vector<int> input{1, 2, 3};
85+
THEN(
86+
"A json_objectt can be constructed from the vector of numbers using "
87+
"range and map.")
88+
{
89+
const json_objectt output =
90+
make_range(input)
91+
.map([](const int number) {
92+
const std::string number_as_string = std::to_string(number);
93+
return make_pair(number_as_string, json_stringt{number_as_string});
94+
})
95+
.collect<json_objectt>();
96+
REQUIRE(output["1"].kind == jsont::kindt::J_STRING);
97+
REQUIRE(output["1"].value == "1");
98+
REQUIRE(output["2"].kind == jsont::kindt::J_STRING);
99+
REQUIRE(output["2"].value == "2");
100+
REQUIRE(output["3"].kind == jsont::kindt::J_STRING);
101+
REQUIRE(output["3"].value == "3");
102+
};
103+
}
104+
}

0 commit comments

Comments
 (0)