8000 Implemented 'abs', 'int', 'float', 'list' and 'round' filters (#17) · jinja2cpp/Jinja2Cpp@252ee3b · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit 252ee3b

Browse files
authored
Implemented 'abs', 'int', 'float', 'list' and 'round' filters (#17)
* Start implementing conversion filters * Almost implemented 'abs', 'int', 'float', 'list' and 'round' filters * Fix build under gcc * Bugfix and filter tests
1 parent 86c7c20 commit 252ee3b

File tree

4 files changed

+303
-43
lines changed

4 files changed

+303
-43
lines changed

src/filters.cpp

Lines changed: 243 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
#include <algorithm>
77
#include <numeric>
88
#include <sstream>
9+
#include <string>
10+
11+
using namespace std::string_literals;
912

1013
namespace jinja2
1114
{
@@ -26,6 +29,7 @@ struct FilterFactory
2629
};
2730

2831
std::unordered_map<std::string, ExpressionFilter::FilterFactoryFn> s_filters = {
32+
{"abs", FilterFactory<filters::ValueConverter>::MakeCreator(filters::ValueConverter::AbsMode)},
2933
{"attr", &FilterFactory<filters::Attribute>::Create},
3034
{"batch", FilterFactory<filters::Slice>::MakeCreator(filters::Slice::BatchMode)},
3135
{"camelize", FilterFactory<filters::StringConverter>::MakeCreator(filters::StringConverter::CamelMode)},
@@ -177,7 +181,7 @@ InternalValue Attribute::Filter(const InternalValue& baseVal, RenderContext& con
177181

178182
Default::Default(FilterParams params)
179183
{
180-
ParseParams({{"default_value", false, InternalValue(std::string(""))}, {"boolean", false, InternalValue(false)}}, params);
184+
ParseParams({{"default_value", false, InternalValue(""s)}, {"boolean", false, InternalValue(false)}}, params);
181185
}
182186

183187
InternalValue Default::Filter(const InternalValue& baseVal, RenderContext& context)
@@ -196,7 +200,7 @@ InternalValue Default::Filter(const InternalValue& baseVal, RenderContext& conte
196200

197201
DictSort::DictSort(FilterParams params)
198202
{
199-
ParseParams({{"case_sensitive", false}, {"by", false, std::string("key")}, {"reverse", false}}, params);
203+
ParseParams({{"case_sensitive", false}, {"by", false, "key"s}, {"reverse", false}}, params);
200204
}
201205

202206
InternalValue DictSort::Filter(const InternalValue& baseVal, RenderContext& context)
@@ -205,9 +209,9 @@ InternalValue DictSort::Filter(const InternalValue& baseVal, RenderContext& cont
205209
if (map == nullptr)
206210
return InternalValue();
207211

208-
InternalValue isReverseVal = GetArgumentValue("reverse", context, InternalValue(false));
209-
InternalValue isCsVal = GetArgumentValue("case_sensitive", context, InternalValue(false));
210-
InternalValue byVal = GetArgumentValue("by", context, InternalValue(std::string("key")));
212+
InternalValue isReverseVal = GetArgumentValue("reverse", context);
213+
InternalValue isCsVal = GetArgumentValue("case_sensitive", context);
214+
InternalValue byVal = GetArgumentValue("by", context);
211215

212216
bool (*comparator)(const KeyValuePair& left, const KeyValuePair& right);
213217

@@ -284,7 +288,7 @@ Map::Map(FilterParams params)
284288
if (params.kwParams.size() == 1 && params.posParams.empty() && params.kwParams.count("attribute") == 1)
285289
{
286290
newParams.kwParams["name"] = params.kwParams["attribute"];
287-
newParams.kwParams["filter"] = std::make_shared<ConstantExpression>(std::string("attr"));
291+
newParams.kwParams["filter"] = std::make_shared<ConstantExpression>("attr"s);
288292
}
289293
else
290294
{
@@ -382,22 +386,22 @@ struct PrettyPrinter : visitors::BaseVisitor<InternalValue>
382386

383387
InternalValue operator()(const std::string& str) const
384388
{
385-
return "'" + str + "'";
389+
return "'"s + str + "'"s;
386390
}
387391

388392
InternalValue operator()(const std::wstring& str) const
389393
{
390-
return std::string("'<wchar_string>'");
394+
return "'<wchar_string>'"s;
391395
}
392396

393397
InternalValue operator()(bool val) const
394398
{
395-
return std::string(val ? "true" : "false");
399+
return val ? "true"s : "false"s;
396400
}
397401

398402
InternalValue operator()(EmptyValue val) const
399403
{
400-
return std::string("none");
404+
return "none"s;
401405
}
402406

403407
InternalValue operator()(double val) const
@@ -703,15 +707,241 @@ InternalValue Tester::Filter(const InternalValue& baseVal, RenderContext& contex
703707
}
704708

705709
ValueConverter::ValueConverter(FilterParams params, ValueConverter::Mode mode)
710+
: m_mode(mode)
706711
{
712+
switch (mode)
713+
{
714+
case ToFloatMode:
715+
ParseParams({{"default", false}}, params);
716+
break;
717+
case ToIntMode:
718+
ParseParams({{"default", false}, {"base", false, static_cast<int64_t>(10)}}, params);
719+
break;
720+
case ToListMode:
721+
case AbsMode:
722+
break;
723+
case RoundMode:
724+
ParseParams({{"precision", false}, {"method", false, "common"s}}, params);
725+
break;
707726

727+
}
708728
}
709729

710-
InternalValue ValueConverter::Filter(const InternalValue& baseVal, RenderContext& context)
730+
struct ConverterParams
711731
{
712-
return InternalValue();
713-
}
732+
ValueConverter::Mode mode;
733+
InternalValue defValule;
734+
InternalValue base;
735+
InternalValue prec;
736+
InternalValue roundMethod;
737+
};
738+
739+
struct ValueConverterImpl : visitors::BaseVisitor<>
740+
{
741+
using BaseVisitor::operator();
742+
743+
ValueConverterImpl(ConverterParams params)
744+
: m_params(std::move(params))
745+
{
746+
}
747+
748+
InternalValue operator()(int64_t val) const
749+
{
750+
InternalValue result;
751+
switch (m_params.mode)
752+
{
753+
case ValueConverter::ToFloatMode:
754+
result = InternalValue(static_cast<double>(val));
755+
break;
756+
case ValueConverter::AbsMode:
757+
result = InternalValue(static_cast<int64_t>(abs(val)));
758+
break;
759+
case ValueConverter::ToIntMode:
760+
case ValueConverter::RoundMode:
761+
result = val;
762+
break;
763+
default:
764+
break;
765+
}
766+
767+
return result;
768+
}
769+
770+
InternalValue operator()(double val) const
771+
{
772+
InternalValue result;
773+
switch (m_params.mode)
774+
{
775+
case ValueConverter::ToFloatMode:
776+
result = val;
777+
break;
778+
case ValueConverter::ToIntMode:
779+
result = static_cast<int64_t>(val);
780+
break;
781+
case ValueConverter::AbsMode:
782+
result = InternalValue(fabs(val));
783+
break;
784+
case ValueConverter::RoundMode:
785+
{
786+
auto method = AsString(m_params.roundMethod);
787+
auto prec = GetAs<int64_t>(m_params.prec);
788+
double pow10 = std::pow(10, static_cast<int>(prec));
789+
val *= pow10;
790+
if (method == "ceil")
791+
val = val < 0 ? std::floor(val) : std::ceil(val);
792+
else if (method == "floor")
793+
val = val > 0 ? std::floor(val) : std::ceil(val);
794+
else if (method == "common")
795+
val = std::round(val);
796+
result = InternalValue(val / pow10);
797+
break;
798+
}
799+
default:
800+
break;
801+
}
802+
803+
return result;
804+
}
805+
806+
template<typename CharT>
807+
struct StringAdapter : public IListAccessor
808+
{
809+
using string = std::basic_string<CharT>;
810+
StringAdapter(const string* str)
811+
: m_str(str)
812+
{
813+
}
814+
815+
size_t GetSize() const override {return m_str->size();}
816+
InternalValue GetValueByIndex(int64_t idx) const override {return m_str->substr(static_cast<size_t>(idx), 1);}
817+
818+
const string* m_str;
819+
};
820+
821+
struct Map2ListAdapter : public IListAccessor
822+
{
823+
Map2ListAdapter(const MapAdapter* map)
824+
: m_map(map)
825+
{
826+
}
827+
828+
size_t GetSize() const override {return m_map->GetSize();}
829+
InternalValue GetValueByIndex(int64_t idx) const override {return m_map->GetValueByIndex(idx);}
830+
831+
const MapAdapter* m_map;
832+
};
833+
834+
InternalValue operator()(const std::string& val) const
835+
{
836+
InternalValue result;
837+
switch (m_params.mode)
838+
{
839+
case ValueConverter::ToFloatMode:
840+
{
841+
char* endBuff = nullptr;
842+
double dblVal = strtod(val.c_str(), &endBuff);
843+
if (*endBuff != 0)
844+
result = m_params.defValule;
845+
else
846+
result = dblVal;
847+
break;
848+
}
849+
case ValueConverter::ToIntMode:
850+
{
851+
char* endBuff = nullptr;
852+
int base = static_cast<int>(GetAs<int64_t>(m_params.base));
853+
int64_t dblVal = strtoll(val.c_str(), &endBuff, base);
854+
if (*endBuff != 0)
855+
result = m_params.defValule;
856+
else
857+
result = dblVal;
858+
break;
859+
}
860+
case ValueConverter::ToListMode:
861+
result = ListAdapter([adapter = StringAdapter<char>(&val)]() {return &adapter;});
862+
default:
863+
break;
864+
}
865+
866+
return result;
867+
}
868+
869+
InternalValue operator()(const std::wstring& val) const
870+
{
871+
InternalValue result;
872+
switch (m_params.mode)
873+
{
874+
case ValueConverter::ToFloatMode:
875+
{
876+
wchar_t* endBuff = nullptr;
877+
double dblVal = wcstod(val.c_str(), &endBuff);
878+
if (*endBuff != 0)
879+
result = m_params.defValule;
880+
else
881+
result = dblVal;
882+
break;
883+
}
884+
case ValueConverter::ToIntMode:
885+
{
886+
wchar_t* endBuff = nullptr;
887+
int64_t dblVal = wcstoll(val.c_str(), &endBuff, static_cast<int>(GetAs<int64_t>(m_params.base)));
888+
if (*endBuff != 0)
889+
result = m_params.defValule;
890+
else
891+
result = dblVal;
892+
break;
893+
}
894+
case ValueConverter::ToListMode:
895+
result = ListAdapter([adapter = StringAdapter<wchar_t>(&val)]() {return &adapter;});
896+
default:
897+
break;
898+
}
899+
900+
return result;
901+
}
902+
903+
InternalValue operator()(const ListAdapter& val) const
904+
{
905+
if (m_params.mode == ValueConverter::ToListMode)
906+
return InternalValue(val);
907+
908+
return InternalValue();
909+
}
714910

911+
InternalValue operator()(const MapAdapter& val) const
912+
{
913+
if (m_params.mode == ValueConverter::ToListMode)
914+
return ListAdapter([adapter = Map2ListAdapter(&val)]() {return &adapter;});
915+
916+
return InternalValue();
917+
}
918+
919+
template<typename T>
920+
static T GetAs(const InternalValue& val, T defValue = 0)
921+
{
922+
ConverterParams params;
923+
params.mode = ValueConverter::ToIntMode;
924+
params.base = static_cast<int64_t>(10);
925+
InternalValue intVal = Apply<ValueConverterImpl>(val, params);
926+
T* result = boost::get<int64_t>(&intVal);
927+
if (result == nullptr)
928+
return defValue;
929+
930+
return *result;
931+
}
932+
933+
ConverterParams m_params;
934+
};
715935

936+
InternalValue ValueConverter::Filter(const InternalValue& baseVal, RenderContext& context)
937+
{
938+
ConverterParams params;
939+
params.mode = m_mode;
940+
params.defValule = GetArgumentValue("default", context);
941+
params.base = GetArgumentValue("base", context);
942+
params.prec = GetArgumentValue("precision", context);
943+
params.roundMethod = GetArgumentValue("method", context);
944+
return Apply<ValueConverterImpl>(baseVal, params);
945+
}
716946
} // filters
717947
} // jinja2

src/filters.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ class StringConverter : public FilterBase
179179
StringConverter(FilterParams params, Mode mode);
180180

181181
InternalValue Filter(const InternalValue& baseVal, RenderContext& context);
182-
182+
183183
private:
184184
Mode m_mode;
185185
};
@@ -226,13 +226,16 @@ class ValueConverter : public FilterBase
226226
ToFloatMode,
227227
ToIntMode,
228228
ToListMode,
229+
AbsMode,
229230
RoundMode,
230-
231231
};
232232

233233
ValueConverter(FilterParams params, Mode mode);
234234

235235
InternalValue Filter(const InternalValue& baseVal, RenderContext& context);
236+
237+
private:
238+
Mode m_mode;
236239
};
237240
} // filters
238241
} // jinja2

src/internal_value.cpp

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -86,32 +86,16 @@ struct ListConverter : public visitors::BaseVisitor<boost::optional<ListAdapter>
8686
using result_t = boost::optional<ListAdapter>;
8787

8888

89-
template<typename CharT>
90-
struct StringAdapter : public IListAccessor
91-
{
92-
using string = std::basic_string<CharT>;
93-
StringAdapter(const string* str)
94-
: m_str(str)
95-
{
96-
}
97-
98-
size_t GetSize() const override {return m_str->size();}
99-
InternalValue GetValueByIndex(int64_t idx) const override {return m_str->substr(static_cast<size_t>(idx), 1);}
100-
101-
const string* m_str;
102-
};
103-
104-
10589
result_t operator() (const ListAdapter& list) const
10690
{
10791
return list;
10892
}
10993

110-
template<typename CharT>
111-
result_t operator() (const std::basic_string<CharT>& str) const
112-
{
113-
return result_t(ListAdapter([adaptor = StringAdapter<CharT>(&str)]() {return &adaptor;}));
114-
}
94+
// template<typename CharT>
95+
// result_t operator() (const std::basic_string<CharT>& str) const
96+
// {
97+
// return result_t(ListAdapter([adaptor = StringAdapter<CharT>(&str)]() {return &adaptor;}));
98+
// }
11599

116100
};
117101

0 commit comments

Comments
 (0)
0