Skip to content

Commit 6e65a8b

Browse files
authored
Use (non)std variant instead boost::variant (#43)
* Switch on actual Martin's Moene 'variant-lite' * boost::variant -> nonstd::variant (2) * boost::variant -> nonstd::variant (3) * boost::variant -> nonstd::variant (4) * boost::variant -> nonstd::variant (4) * Performance improvement * martinmoene/value-ptr-lite -> flexferrum/value-ptr-lite * Fix map retrival from jinja2::Value * Fix crash * Fix stream operator application * Completely remove boost from public headers
1 parent 80b2db0 commit 6e65a8b

21 files changed

+353
-130
lines changed

.gitmodules

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
[submodule "thirdparty/gtest"]
2-
path = thirdparty/gtest
3-
url = https://github.com/google/googletest.git
2+
path = thirdparty/gtest
3+
url = https://github.com/google/googletest.git
44
[submodule "thirdparty/nonstd/variant-light"]
5-
path = thirdparty/nonstd/variant-light
6-
url = https://github.com/flexferrum/variant-lite.git
5+
path = thirdparty/nonstd/variant-light
6+
url = https://github.com/martinmoene/variant-lite.git
77
[submodule "thirdparty/nonstd/expected-light"]
8-
path = thirdparty/nonstd/expected-light
9-
url = https://github.com/martinmoene/expected-lite.git
8+
path = thirdparty/nonstd/expected-light
9+
url = https://github.com/martinmoene/expected-lite.git
10+
[submodule "thirdparty/nonstd/value-ptr-lite"]
11+
path = thirdparty/nonstd/value-ptr-lite
12+
url = https://github.com/flexferrum/value-ptr-lite.git

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,8 @@ install(TARGETS ${LIB_TARGET_NAME}
173173

174174
install (DIRECTORY include/ DESTINATION include)
175175
install (DIRECTORY thirdparty/nonstd/expected-light/include/ DESTINATION include)
176+
install (DIRECTORY thirdparty/nonstd/variant-light/include/ DESTINATION include)
177+
install (DIRECTORY thirdparty/nonstd/value-ptr-light/include/ DESTINATION include)
176178
install (FILES cmake/public/FindJinja2Cpp.cmake DESTINATION cmake)
177179

178180
add_test(NAME jinja2cpp_tests COMMAND jinja2cpp_tests)

include/jinja2cpp/error_info.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
#include "value.h"
55

6-
#include <boost/optional.hpp>
6+
#include <nonstd/optional.hpp>
77

88
#include <iostream>
99
#include <vector>

include/jinja2cpp/filesystem_handler.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#ifndef JINJA2CPP_FILESYSTEM_HANDLER_H
22
#define JINJA2CPP_FILESYSTEM_HANDLER_H
33

4-
#include <boost/variant.hpp>
4+
#include <nonstd/variant.hpp>
55

66
#include <iostream>
77
#include <memory>
@@ -37,7 +37,7 @@ class MemoryFileSystem : public IFilesystemHandler
3737
WCharFileStreamPtr OpenWStream(const std::string& name) const override;
3838

3939
private:
40-
using FileContent = boost::variant<std::string, std::wstring>;
40+
using FileContent = nonstd::variant<std::string, std::wstring>;
4141
std::unordered_map<std::string, FileContent> m_filesMap;
4242
};
4343

include/jinja2cpp/value.h

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
#include <unordered_map>
88
#include <string>
99
#include <functional>
10-
#include <boost/variant.hpp>
10+
#include <nonstd/variant.hpp>
11+
#include <nonstd/value_ptr.hpp>
1112

1213
namespace jinja2
1314
{
@@ -34,6 +35,7 @@ class GenericMap
3435
{
3536
public:
3637
GenericMap() = default;
38+
3739
GenericMap(std::function<const MapItemAccessor* ()> accessor)
3840
: m_accessor(std::move(accessor))
3941
{
@@ -89,13 +91,20 @@ class GenericList
8991

9092
using ValuesList = std::vector<Value>;
9193
using ValuesMap = std::unordered_map<std::string, Value>;
92-
using ValueData = boost::variant<EmptyValue, bool, std::string, std::wstring, int64_t, double, boost::recursive_wrapper<ValuesList>, boost::recursive_wrapper<ValuesMap>, GenericList, GenericMap>;
94+
struct FunctionCallParams;
95+
96+
using UserFunction = std::function<Value (const FunctionCallParams&)>;
97+
98+
template<typename T>
99+
using RecWrapper = nonstd::value_ptr<T>;
93100

94101
class Value {
95102
public:
103+
using ValueData = nonstd::variant<EmptyValue, bool, std::string, std::wstring, int64_t, double, RecWrapper<ValuesList>, RecWrapper<ValuesMap>, GenericList, GenericMap, UserFunction>;
104+
96105
Value() = default;
97106
template<typename T>
98-
Value(T&& val, typename std::enable_if<!std::is_same<std::decay_t<T>, Value>::value>::type* = nullptr)
107+
Value(T&& val, typename std::enable_if<!std::is_same<std::decay_t<T>, Value>::value && !std::is_same<std::decay_t<T>, ValuesList>::value>::type* = nullptr)
99108
: m_data(std::forward<T>(val))
100109
{
101110
}
@@ -112,51 +121,67 @@ class Value {
112121
: m_data(static_cast<int64_t>(val))
113122
{
114123
}
124+
Value(const ValuesList& list)
125+
: m_data(RecWrapper<ValuesList>(list))
126+
{
127+
}
128+
Value(const ValuesMap& map)
129+
: m_data(RecWrapper<ValuesMap>(map))
130+
{
131+
}
132+
Value(ValuesList&& list) noexcept
133+
: m_data(RecWrapper<ValuesList>(std::move(list)))
134+
{
135+
}
136+
Value(ValuesMap&& map) noexcept
137+
: m_data(RecWrapper<ValuesMap>(std::move(map)))
138+
{
139+
}
115140

116141
const ValueData& data() const {return m_data;}
117142

118143
ValueData& data() {return m_data;}
119144

120145
bool isString() const
121146
{
122-
return boost::get<std::string>(&m_data) != nullptr;
147+
return nonstd::get_if<std::string>(&m_data) != nullptr;
123148
}
124149
auto& asString()
125150
{
126-
return boost::get<std::string>(m_data);
151+
return nonstd::get<std::string>(m_data);
127152
}
128153
auto& asString() const
129154
{
130-
return boost::get<std::string>(m_data);
155+
return nonstd::get<std::string>(m_data);
131156
}
132157

133158
bool isList() const
134159
{
135-
return boost::get<ValuesList>(&m_data) != nullptr || boost::get<GenericList>(&m_data) != nullptr;
160+
return nonstd::get_if<RecWrapper<ValuesList>>(&m_data) != nullptr || nonstd::get_if<GenericList>(&m_data) != nullptr;
136161
}
137162
auto& asList()
138163
{
139-
return boost::get<ValuesList>(m_data);
164+
return *nonstd::get<RecWrapper<ValuesList>>(m_data).get();
140165
}
141166
auto& asList() const
142167
{
143-
return boost::get<ValuesList>(m_data);
168+
return *nonstd::get<RecWrapper<ValuesList>>(m_data).get();
144169
}
145170
bool isMap() const
146171
{
147-
return boost::get<ValuesMap>(&m_data) != nullptr || boost::get<GenericMap>(&m_data) != nullptr;
172+
return nonstd::get_if<RecWrapper<ValuesMap>>(&m_data) != nullptr || nonstd::get_if<GenericMap>(&m_data) != nullptr;
148173
}
149174
auto& asMap()
150175
{
151-
return boost::get<ValuesMap>(m_data);
176+
return *nonstd::get<RecWrapper<ValuesMap>>(m_data).get();
152177
}
153178
auto& asMap() const
154179
{
155-
return boost::get<ValuesMap>(m_data);
180+
return *nonstd::get<RecWrapper<ValuesMap>>(m_data).get();
156181
}
157182
bool isEmpty() const
158183
{
159-
return boost::get<EmptyValue>(&m_data) != nullptr;
184+
return nonstd::get_if<EmptyValue>(&m_data) != nullptr;
160185
}
161186

162187
Value subscript(const Value& index) const;
@@ -165,6 +190,12 @@ class Value {
165190
ValueData m_data;
166191
};
167192

193+
struct FunctionCallParams
194+
{
195+
ValuesMap kwParams;
196+
ValuesList posParams;
197+
};
198+
168199
inline Value GenericMap::GetValueByName(const std::string& name) const
169200
{
170201
return m_accessor()->GetValueByName(name);

src/error_info.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace jinja2
77
namespace
88
{
99
template<typename CharT>
10-
struct ValueRenderer : boost::static_visitor<void>
10+
struct ValueRenderer
1111
{
1212
std::basic_ostream<CharT>& os;
1313

@@ -37,7 +37,7 @@ struct ValueRenderer : boost::static_visitor<void>
3737
else
3838
os << UNIVERSAL_STR(", ");
3939

40-
boost::apply_visitor(ValueRenderer<CharT>(os), val.data());
40+
nonstd::visit(ValueRenderer<CharT>(os), val.data());
4141
}
4242
os << '}';
4343
}
@@ -54,12 +54,19 @@ struct ValueRenderer : boost::static_visitor<void>
5454
os << UNIVERSAL_STR(", ");
5555

5656
os << '{' << '"' << ConvertString<std::basic_string<CharT>>(val.first) << '"' << ',';
57-
boost::apply_visitor(ValueRenderer<CharT>(os), val.second.data());
57+
nonstd::visit(ValueRenderer<CharT>(os), val.second.data());
5858
os << '}';
5959
}
6060
os << '}';
6161
}
6262

63+
64+
template<typename T>
65+
void operator()(const RecWrapper<T>& val) const
66+
{
67+
return this->operator()(const_cast<const T&>(*val.get()));
68+
}
69+
6370
void operator() (const GenericMap& /*val*/) const
6471
{
6572
}
@@ -68,6 +75,11 @@ struct ValueRenderer : boost::static_visitor<void>
6875
{
6976
}
7077

78+
79+
void operator() (const UserFunction& val) const
80+
{
81+
}
82+
7183
template<typename T>
7284
void operator() (const T& val) const
7385
{
@@ -78,7 +90,7 @@ struct ValueRenderer : boost::static_visitor<void>
7890
template<typename CharT>
7991
std::basic_ostream<CharT>& operator << (std::basic_ostream<CharT>& os, Value val)
8092
{
81-
boost::apply_visitor(ValueRenderer<CharT>(os), val.data());
93+
nonstd::visit(ValueRenderer<CharT>(os), val.data());
8294
return os;
8395
}
8496
}

src/expression_evaluator.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -89,15 +89,15 @@ InternalValue BinaryExpression::Evaluate(RenderContext& context)
8989
bool left = ConvertToBool(leftVal);
9090
if (left)
9191
left = ConvertToBool(rightVal);
92-
result = left;
92+
result = static_cast<bool>(left);
9393
break;
9494
}
9595
case jinja2::BinaryExpression::LogicalOr:
9696
{
9797
bool left = ConvertToBool(leftVal);
9898
if (!left)
9999
left = ConvertToBool(rightVal);
100-
result = left;
100+
result = static_cast<bool>(left);
101101
break;
102102
}
103103
case jinja2::BinaryExpression::LogicalEq:
@@ -125,16 +125,16 @@ InternalValue BinaryExpression::Evaluate(RenderContext& context)
125125
auto leftStr = context.GetRendererCallback()->GetAsTargetString(leftVal);
126126
auto rightStr = context.GetRendererCallback()->GetAsTargetString(rightVal);
127127
TargetString resultStr;
128-
std::string* nleftStr = boost::get<std::string>(&leftStr);
128+
std::string* nleftStr = GetIf<std::string>(&leftStr);
129129
if (nleftStr != nullptr)
130130
{
131-
auto* nrightStr = boost::get<std::string>(&rightStr);
131+
auto* nrightStr = GetIf<std::string>(&rightStr);
132132
resultStr = *nleftStr + *nrightStr;
133133
}
134134
else
135135
{
136-
auto* wleftStr = boost::get<std::wstring>(&leftStr);
137-
auto* wrightStr = boost::get<std::wstring>(&rightStr);
136+
auto* wleftStr = GetIf<std::wstring>(&leftStr);
137+
auto* wrightStr = GetIf<std::wstring>(&rightStr);
138138
resultStr = *wleftStr + *wrightStr;
139139
}
140140
result = InternalValue(std::move(resultStr));
@@ -252,11 +252,11 @@ InternalValue CallExpression::Evaluate(RenderContext& values)
252252
void CallExpression::Render(OutStream& stream, RenderContext& values)
253253
{
254254
auto fnVal = m_valueRef->Evaluate(values);
255-
Callable* callable = boost::get<Callable>(&fnVal);
255+
Callable* callable = GetIf<Callable>(&fnVal);
256256
if (callable == nullptr)
257257
{
258258
fnVal = Subscript(fnVal, std::string("operator()"));
259-
callable = boost::get<Callable>(&fnVal);
259+
callable = GetIf<Callable>(&fnVal);
260260
if (callable == nullptr)
261261
{
262262
Expression::Render(stream, values);
@@ -342,7 +342,7 @@ InternalValue CallExpression::CallLoopCycle(RenderContext& values)
342342
if (!loopFound)
343343
return InternalValue();
344344

345-
auto loop = boost::get<MapAdapter>(&loopValP->second);
345+
auto loop = GetIf<MapAdapter>(&loopValP->second);
346346
int64_t baseIdx = Apply<visitors::IntegerEvaluator>(loop->GetValueByName("index0"));
347347
auto idx = static_cast<size_t>(baseIdx % m_params.posParams.size());
348348
return m_params.posParams[idx]->Evaluate(values);

src/filesystem_handler.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
namespace jinja2
99
{
1010

11-
using TargetFileStream = boost::variant<CharFileStreamPtr*, WCharFileStreamPtr*>;
11+
using TargetFileStream = nonstd::variant<CharFileStreamPtr*, WCharFileStreamPtr*>;
1212

13-
struct FileContentConverter : public boost::static_visitor<void>
13+
struct FileContentConverter
1414
{
1515
void operator() (const std::string& content, CharFileStreamPtr* sPtr) const
1616
{
@@ -52,7 +52,7 @@ CharFileStreamPtr MemoryFileSystem::OpenStream(const std::string& name) const
5252
return result;
5353

5454
TargetFileStream targetStream(&result);
55-
boost::apply_visitor(FileContentConverter(), p->second, targetStream);
55+
visit(FileContentConverter(), p->second, targetStream);
5656

5757
return result;
5858
}
@@ -65,7 +65,7 @@ WCharFileStreamPtr MemoryFileSystem::OpenWStream(const std::string& name) const
6565
return result;
6666

6767
TargetFileStream targetStream(&result);
68-
boost::apply_visitor(FileContentConverter(), p->second, targetStream);
68+
visit(FileContentConverter(), p->second, targetStream);
6969

7070
return result;
7171
}

0 commit comments

Comments
 (0)