#include #include namespace mbgl { namespace style { namespace expression { template optional checkNumber(T n) { if (n > std::numeric_limits::max()) { return {std::numeric_limits::infinity()}; } else { return {static_cast(n)}; } } using namespace mbgl::style::conversion; optional parseValue(const Convertible& value, ParsingContext& ctx) { if (isUndefined(value)) return {Null}; if (isObject(value)) { std::unordered_map result; bool error = false; eachMember(value, [&] (const std::string& k, const mbgl::style::conversion::Convertible& v) -> optional { if (!error) { optional memberValue = parseValue(v, ctx); if (memberValue) { result.emplace(k, *memberValue); } else { error = true; } } return {}; }); return error ? optional() : optional(result); } if (isArray(value)) { std::vector result; const auto length = arrayLength(value); for(std::size_t i = 0; i < length; i++) { optional item = parseValue(arrayMember(value, i), ctx); if (item) { result.emplace_back(*item); } else { return optional(); } } return optional(result); } optional v = toValue(value); // since value represents a JSON value, if it's not undefined, object, or // array, it must be convertible to mbgl::Value assert(v); return v->match( [&](uint64_t n) { return checkNumber(n); }, [&](int64_t n) { return checkNumber(n); }, [&](double n) { return checkNumber(n); }, [&](const auto&) { return optional(toExpressionValue(*v)); } ); } ParseResult Literal::parse(const Convertible& value, ParsingContext& ctx) { if (isObject(value)) { ctx.error(R"(Bare objects invalid. Use ["literal", {...}] instead.)"); return ParseResult(); } else if (isArray(value)) { // object or array value, quoted with ["literal", value] if (arrayLength(value) != 2) { ctx.error("'literal' expression requires exactly one argument, but found " + util::toString(arrayLength(value) - 1) + " instead."); return ParseResult(); } const optional parsedValue = parseValue(arrayMember(value, 1), ctx); if (!parsedValue) { return ParseResult(); } // special case: infer the item type if possible for zero-length arrays if ( ctx.getExpected() && ctx.getExpected()->template is() && parsedValue->template is>() ) { auto type = typeOf(*parsedValue).template get(); auto expected = ctx.getExpected()->template get(); if ( type.N && (*type.N == 0) && (!expected.N || (*expected.N == 0)) ) { return ParseResult(std::make_unique(expected, parsedValue->template get>())); } } return ParseResult(std::make_unique(*parsedValue)); } else { // bare primitive value (string, number, boolean, null) const optional parsedValue = parseValue(value, ctx); return ParseResult(std::make_unique(*parsedValue)); } } mbgl::Value Literal::serialize() const { if (getType().is() || getType().is()) { return std::vector{{ getOperator(), *fromExpressionValue(value) }}; } else { return *fromExpressionValue(value); } } } // namespace expression } // namespace style } // namespace mbgl