diff options
Diffstat (limited to 'src/style/style_parser.cpp')
-rw-r--r-- | src/style/style_parser.cpp | 165 |
1 files changed, 87 insertions, 78 deletions
diff --git a/src/style/style_parser.cpp b/src/style/style_parser.cpp index 390096e9de..34aa7f2228 100644 --- a/src/style/style_parser.cpp +++ b/src/style/style_parser.cpp @@ -622,7 +622,7 @@ void StyleParser::parseBucket(JSVal value, std::shared_ptr<StyleLayer> &layer) { if (value.HasMember("filter")) { JSVal value_filter = replaceConstant(value["filter"]); - parseFilter(value_filter, layer); + layer->bucket->filter = parseFilter(value_filter); } if (value.HasMember("render")) { @@ -631,8 +631,92 @@ void StyleParser::parseBucket(JSVal value, std::shared_ptr<StyleLayer> &layer) { } } -void StyleParser::parseFilter(JSVal value, std::shared_ptr<StyleLayer> &layer) { - // TODO +FilterExpression StyleParser::parseFilter(JSVal value) { + return parseFilter(value, value.IsArray() ? FilterExpression::Operator::Or : FilterExpression::Operator::And); +} + +FilterExpression StyleParser::parseFilter(JSVal value, FilterExpression::Operator op) { + FilterExpression expression(op); + if (value.IsObject()) { + rapidjson::Value::ConstMemberIterator itr = value.MemberBegin(); + for (; itr != value.MemberEnd(); ++itr) { + const std::string name { itr->name.GetString(), itr->name.GetStringLength() }; + if (name == "&") { + expression.add(parseFilter(replaceConstant(itr->value), FilterExpression::Operator::And)); + } else if (name == "|") { + expression.add(parseFilter(replaceConstant(itr->value), FilterExpression::Operator::Or)); + } else if (name == "^") { + expression.add(parseFilter(replaceConstant(itr->value), FilterExpression::Operator::Xor)); + } else if (name == "!") { + expression.add(parseFilter(replaceConstant(itr->value), FilterExpression::Operator::Nor)); + } else if (name == "$type") { + JSVal type = replaceConstant(itr->value); + if (type.IsString()) { + expression.setGeometryType(parseGeometryType({ type.GetString(), type.GetStringLength() })); + } + } else { + FilterComparison comparison(name); + JSVal filterValue = replaceConstant(itr->value); + if (filterValue.IsObject()) { + rapidjson::Value::ConstMemberIterator itr = filterValue.MemberBegin(); + for (; itr != filterValue.MemberEnd(); ++itr) { + comparison.add( + parseFilterComparisonOperator({ itr->name.GetString(), itr->name.GetStringLength() }), + parseValues(replaceConstant(itr->value)) + ); + } + } else if (filterValue.IsArray()) { + comparison.add(FilterComparison::Operator::In, parseValues(filterValue)); + } else { + comparison.add(FilterComparison::Operator::Equal, std::forward_list<Value>({ parseValue(filterValue) })); + } + expression.add(comparison); + } + } + } else if (value.IsArray()) { + for (rapidjson::SizeType i = 0; i < value.Size(); i++) { + expression.add(parseFilter(replaceConstant(value[i]))); + } + } else { + fprintf(stderr, "[WARNING] expression must be either an array or an object\n"); + } + + return expression; +} + +Value StyleParser::parseValue(JSVal value) { + switch (value.GetType()) { + case rapidjson::kNullType: + case rapidjson::kFalseType: + return false; + + case rapidjson::kTrueType: + return true; + + case rapidjson::kStringType: + return std::string { value.GetString(), value.GetStringLength() }; + + case rapidjson::kNumberType: + if (value.IsUint64()) return value.GetUint64(); + if (value.IsInt64()) return value.GetInt64(); + return value.GetDouble(); + + default: + return false; + } +} + +std::forward_list<Value> StyleParser::parseValues(JSVal value) { + std::forward_list<Value> values; + if (value.IsArray()) { + auto it = values.before_begin(); + for (rapidjson::SizeType i = 0; i < value.Size(); i++) { + it = values.emplace_after(it, parseValue(replaceConstant(value[i]))); + } + } else { + values.emplace_front(parseValue(value)); + } + return values; } void StyleParser::parseRender(JSVal value, std::shared_ptr<StyleLayer> &layer) { @@ -724,79 +808,4 @@ void StyleParser::parseRender(JSVal value, std::shared_ptr<StyleLayer> &layer) { } } -//PropertyFilterExpression StyleParser::parseFilterOrExpression(JSVal value) { -// if (value.IsArray()) { -// // This is an expression. -// util::recursive_wrapper<PropertyExpression> expression; -// for (rapidjson::SizeType i = 0; i < value.Size(); ++i) { -// JSVal filter_item = value[i]; -// -// if (filter_item.IsString()) { -// expression.get().op = expressionOperatorType({ filter_item.GetString(), filter_item.GetStringLength() }); -// } else { -// expression.get().operands.emplace_back(parseFilterOrExpression(filter_item)); -// } -// } -// return std::move(expression); -// } else if (value.IsObject() && value.HasMember("field") && value.HasMember("value")) { -// // This is a filter. -// JSVal field = value["field"]; -// JSVal val = value["value"]; -// -// if (!field.IsString()) { -// throw Style::exception("field name must be a string"); -// } -// -// const std::string field_name { field.GetString(), field.GetStringLength() }; -// const FilterOperator op = [&]{ -// if (value.HasMember("operator")) { -// JSVal op_val = value["operator"]; -// return filterOperatorType({ op_val.GetString(), op_val.GetStringLength() }); -// } else { -// return FilterOperator::Equal; -// } -// }(); -// -// if (val.IsArray()) { -// // The filter has several values, so it's an OR sub-expression. -// util::recursive_wrapper<PropertyExpression> expression; -// for (rapidjson::SizeType i = 0; i < val.Size(); ++i) { -// expression.get().operands.emplace_back(util::recursive_wrapper<PropertyFilter>(PropertyFilter { field_name, op, parseValue(val[i]) })); -// } -// -// return std::move(expression); -// } else { -// // The filter only has a single value, so it is a real filter. -// return std::move(util::recursive_wrapper<PropertyFilter>(PropertyFilter { field_name, op, parseValue(val) })); -// } -// } -// -// return std::true_type(); - -//Value StyleParser::parseValue(JSVal value) { -// switch (value.GetType()) { -// case rapidjson::kNullType: -// case rapidjson::kFalseType: -// return false; -// -// case rapidjson::kTrueType: -// return true; -// -// case rapidjson::kStringType: -// return std::string { value.GetString(), value.GetStringLength() }; -// -// case rapidjson::kNumberType: -// if (value.IsUint64()) return value.GetUint64(); -// if (value.IsInt64()) return value.GetInt64(); -// return value.GetDouble(); -// -// case rapidjson::kObjectType: -// case rapidjson::kArrayType: -// throw Style::exception("value cannot be an object or array"); -// return false; -// } -// throw Style::exception("unhandled value type in style"); -// return false; -//} - } |