Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion include/jinja2cpp/reflected_value.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,11 @@ class ReflectedMapImplBase : public MapItemAccessor
auto p = accessors.begin();
std::advance(p, idx);

return static_cast<const Derived*>(this)->GetField(p->second);
ValuesMap result;
result["key"] = p->first;
result["value"] = static_cast<const Derived*>(this)->GetField(p->second);

return result;
}
};

Expand Down
2 changes: 2 additions & 0 deletions src/expression_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,8 @@ ExpressionEvaluatorPtr<ExpressionFilter> ExpressionParser::ParseFilterExpression

if (lexer.NextToken() == '(')
params = ParseCallParams(lexer, valid);
else
lexer.ReturnToken();

if (!valid)
return empty;
Expand Down
176 changes: 172 additions & 4 deletions src/filters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include <algorithm>
#include <numeric>
#include <sstream>

namespace jinja2
{
Expand Down Expand Up @@ -194,12 +195,75 @@ InternalValue Default::Filter(const InternalValue& baseVal, RenderContext& conte

DictSort::DictSort(FilterParams params)
{

ParseParams({{"case_sensitive", false}, {"by", false, std::string("key")}, {"reverse", false}}, params);
}

InternalValue DictSort::Filter(const InternalValue& baseVal, RenderContext& context)
{
return InternalValue();
const MapAdapter* map = boost::get<MapAdapter>(&baseVal);
if (map == nullptr)
return InternalValue();

InternalValue isReverseVal = GetArgumentValue("reverse", context, InternalValue(false));
InternalValue isCsVal = GetArgumentValue("case_sensitive", context, InternalValue(false));
InternalValue byVal = GetArgumentValue("by", context, InternalValue(std::string("key")));

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

if (AsString(byVal) == "key") // Sort by key
{
if (ConvertToBool(isCsVal))
{
comparator = [](const KeyValuePair& left, const KeyValuePair& right)
{
return left.key < right.key;
};
}
else
{
comparator = [](const KeyValuePair& left, const KeyValuePair& right)
{
return boost::lexicographical_compare(left.key, right.key, boost::algorithm::is_iless());
};
}
}
else if (AsString(byVal) == "value")
{
if (ConvertToBool(isCsVal))
{
comparator = [](const KeyValuePair& left, const KeyValuePair& right)
{
return ConvertToBool(Apply2<visitors::BinaryMathOperation>(left.value, right.value, BinaryExpression::LogicalLt, BinaryExpression::CaseSensitive));
};
}
else
{
comparator = [](const KeyValuePair& left, const KeyValuePair& right)
{
return ConvertToBool(Apply2<visitors::BinaryMathOperation>(left.value, right.value, BinaryExpression::LogicalLt, BinaryExpression::CaseInsensitive));
};
}
}
else
return InternalValue();

std::vector<KeyValuePair> tempVector;
tempVector.reserve(map->GetSize());
for (int64_t idx = 0; idx < map->GetSize(); ++ idx)
{
auto val = map->GetValueByIndex(idx);
auto& kvVal = boost::get<KeyValuePair>(val);
tempVector.push_back(std::move(kvVal));
}

if (ConvertToBool(isReverseVal))
std::sort(tempVector.begin(), tempVector.end(), [comparator](auto& l, auto& r) {return comparator(r, l);});
else
std::sort(tempVector.begin(), tempVector.end(), [comparator](auto& l, auto& r) {return comparator(l, r);});

InternalValueList resultList(tempVector.begin(), tempVector.end());

return InternalValue(ListAdapter::CreateAdapter(std::move(resultList)));
}

GroupBy::GroupBy(FilterParams params)
Expand Down Expand Up @@ -253,14 +317,118 @@ InternalValue Map::Filter(const InternalValue& baseVal, RenderContext& context)
return ListAdapter::CreateAdapter(std::move(resultList));
}

PrettyPrint::PrettyPrint(FilterParams params)
struct PrettyPrinter : visitors::BaseVisitor<InternalValue>
{
using BaseVisitor::operator();

PrettyPrinter(const RenderContext* context)
: m_context(context)
{}

InternalValue operator()(const ListAdapter& list) const
{
std::ostringstream os;

os << "[";
bool isFirst = true;

for (auto& v : list)
{
if (isFirst)
isFirst = false;
else
os << ", ";
os << AsString(Apply<PrettyPrinter>(v, m_context));
}
os << "]";

return InternalValue(os.str());
}

InternalValue operator()(const MapAdapter& map) const
{
std::ostringstream os;
os << "{";

const auto& keys = map.GetKeys();

bool isFirst = true;
for (auto& k : keys)
{
if (isFirst)
isFirst = false;
else
os << ", ";

os << "'" << k << "': ";
os << AsString(Apply<PrettyPrinter>(map.GetValueByName(k), m_context));
}

os << "}";

return InternalValue(os.str());
}

InternalValue operator() (const KeyValuePair& kwPair) const
{
std::ostringstream os;

os << "'" << kwPair.key << "': ";
os << AsString(Apply<PrettyPrinter>(kwPair.value, m_context));

return InternalValue(os.str());
}

InternalValue operator()(const std::string& str) const
{
return "'" + str + "'";
}

InternalValue operator()(const std::wstring& str) const
{
return std::string("'<wchar_string>'");
}

InternalValue operator()(bool val) const
{
return std::string(val ? "true" : "false");
}

InternalValue operator()(EmptyValue val) const
{
return std::string("none");
}

InternalValue operator()(double val) const
{
std::ostringstream os;
os << val;
return InternalValue(os.str());
}

InternalValue operator()(int64_t val) const
{
std::ostringstream os;
os << val;
return InternalValue(os.str());
}
//
// template<typename U>
// InternalValue operator()(U&& val) const
// {
// return InternalValue();
// }

const RenderContext* m_context;
};

PrettyPrint::PrettyPrint(FilterParams params)
{
}

InternalValue PrettyPrint::Filter(const InternalValue& baseVal, RenderContext& context)
{
return InternalValue();
return Apply<PrettyPrinter>(baseVal, &context);
}

Random::Random(FilterParams params)
Expand Down
33 changes: 23 additions & 10 deletions src/internal_value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,17 @@ struct SubscriptionVisitor : public visitors::BaseVisitor<>
std::basic_string<CharT> result(1, str[static_cast<size_t>(index)]);
return TargetString(std::move(result));
}
};

InternalValue operator() (const KeyValuePair& values, const std::string& field)
{
if (field == "key")
return InternalValue(values.key);
else if (field == "value")
return values.value;

return InternalValue();
}
};

InternalValue Subscript(const InternalValue& val, const InternalValue& subscript)
{
Expand Down Expand Up @@ -274,14 +283,14 @@ class InternalValueMapAdapter : public IMapAccessor
size_t GetSize() const override {return m_values.Get().size();}
InternalValue GetValueByIndex(int64_t idx) const override
{
InternalValueMap result;
KeyValuePair result;
auto p = m_values.Get().begin();
std::advance(p, idx);

result["key"] = InternalValue(p->first);
result["value"] = p->second;
result.key = p->first;
result.value = p->second;

return MapAdapter::CreateAdapter(std::move(result));
return InternalValue(std::move(result));
}
bool HasValue(const std::string& name) const override
{
Expand Down Expand Up @@ -338,7 +347,11 @@ class GenericMapAdapter : public IMapAccessor
InternalValue GetValueByIndex(int64_t idx) const override
{
auto val = m_values.Get().GetValueByIndex(idx);
return Value2IntValue(std::move(val));
KeyValuePair result;
auto& map = val.asMap();
result.key = map["key"].asString();
result.value = Value2IntValue(std::move(map["value"]));
return result;
}
bool HasValue(const std::string& name) const override
{
Expand Down Expand Up @@ -372,14 +385,14 @@ class ValuesMapAdapter : public IMapAccessor
size_t GetSize() const override {return m_values.Get().size();}
InternalValue GetValueByIndex(int64_t idx) const override
{
InternalValueMap result;
KeyValuePair result;
auto p = m_values.Get().begin();
std::advance(p, idx);

result["key"] = InternalValue(p->first);
result["value"] = Value2IntValue(p->second);
result.key = p->first;
result.value = Value2IntValue(p->second);

return MapAdapter::CreateAdapter(std::move(result));
return result;
}
bool HasValue(const std::string& name) const override
{
Expand Down
9 changes: 8 additions & 1 deletion src/internal_value.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ using TargetString = boost::variant<std::string, std::wstring>;

class ListAdapter;
class MapAdapter;
struct KeyValuePair;

using InternalValue = boost::variant<EmptyValue, bool, std::string, TargetString, int64_t, double, ValueRef, ListAdapter, MapAdapter>;
using InternalValue = boost::variant<EmptyValue, bool, std::string, TargetString, int64_t, double, ValueRef, ListAdapter, MapAdapter, boost::recursive_wrapper<KeyValuePair>>;
using InternalValueRef = ReferenceWrapper<InternalValue>;
using InternalValueMap = std::unordered_map<std::string, InternalValue>;
using InternalValueList = std::vector<InternalValue>;
Expand Down Expand Up @@ -229,6 +230,12 @@ inline ListAdapter::Iterator ListAdapter::begin() const {return Iterator(*this);
inline ListAdapter::Iterator ListAdapter::end() const {return Iterator();}


struct KeyValuePair
{
std::string key;
InternalValue value;
};

inline bool IsEmpty(const InternalValue& val)
{
return boost::get<EmptyValue>(&val) != nullptr;
Expand Down
Loading