Skip to content

Commit ada9d27

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 46585bf commit ada9d27

File tree

5 files changed

+119
-0
lines changed

5 files changed

+119
-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: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,14 @@ 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(
176+
std::forward<begin_iteratort>(begin_iterator),
177+
std::forward<end_iteratort>(end_iterator)))
178+
{
179+
}
180+
173181
void resize(std::size_t size)
174182
{
175183
array.resize(size);
@@ -294,6 +302,14 @@ class json_objectt:public jsont
294302
{
295303
}
296304

305+
template <typename begin_iteratort, typename end_iteratort>
306+
json_objectt(begin_iteratort &&begin_iterator, end_iteratort &&end_iterator)
307+
: json_objectt(objectt(
308+
std::forward<begin_iteratort>(begin_iterator),
309+
std::forward<end_iteratort>(end_iterator)))
310+
{
311+
}
312+
297313
jsont &operator[](const std::string &key)
298314
{
299315
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 containert(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: 31 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,31 @@ SCENARIO(
7376
}
7477
}
7578
}
79+
80+
SCENARIO(
81+
"Test that json_objectt can be constructed using `ranget`",
82+
"[core][util][json]")
83+
{
84+
GIVEN("A vector of numbers.")
85+
{
86+
const std::vector<int> input{1, 2, 3};
87+
THEN(
88+
"A json_objectt can be constructed from the vector of numbers using "
89+
"range and map.")
90+
{
91+
const json_objectt output =
92+
make_range(input)
93+
.map([](const int number) {
94+
const std::string number_as_string = std::to_string(number);
95+
return make_pair(number_as_string, json_stringt{number_as_string});
96+
})
97+
.collect<json_objectt>();
98+
REQUIRE(output["1"].kind == jsont::kindt::J_STRING);
99+
REQUIRE(output["1"].value == "1");
100+
REQUIRE(output["2"].kind == jsont::kindt::J_STRING);
101+
REQUIRE(output["2"].value == "2");
102+
REQUIRE(output["3"].kind == jsont::kindt::J_STRING);
103+
REQUIRE(output["3"].value == "3");
104+
};
105+
}
106+
}

0 commit comments

Comments
 (0)