Merge branch 'master' of github.com:mapbox/mapbox-gl-native into android-mason
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
#include <mbgl/style/value.hpp>
|
||||
#include <mbgl/text/glyph.hpp>
|
||||
#include <mbgl/util/pbf.hpp>
|
||||
#include <mbgl/util/optional.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <iosfwd>
|
||||
@@ -44,14 +45,14 @@ public:
|
||||
VectorTileTagExtractor(const VectorTileLayer &layer);
|
||||
|
||||
void setTags(const pbf &pbf);
|
||||
std::vector<Value> getValues(const std::string &key) const;
|
||||
void setType(FilterExpression::GeometryType type);
|
||||
FilterExpression::GeometryType getType() const;
|
||||
mapbox::util::optional<Value> getValue(const std::string &key) const;
|
||||
void setType(FeatureType type);
|
||||
FeatureType getType() const;
|
||||
|
||||
private:
|
||||
const VectorTileLayer &layer_;
|
||||
pbf tags_;
|
||||
FilterExpression::GeometryType type_ = FilterExpression::GeometryType::Any;
|
||||
FeatureType type_ = FeatureType::Unknown;
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
#ifndef MBGL_STYLE_FILTER_COMPARISON
|
||||
#define MBGL_STYLE_FILTER_COMPARISON
|
||||
|
||||
#include <mbgl/style/value.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iosfwd>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class FilterComparison {
|
||||
public:
|
||||
enum class Operator : uint8_t {
|
||||
Equal,
|
||||
NotEqual,
|
||||
Greater,
|
||||
GreaterEqual,
|
||||
Less,
|
||||
LessEqual,
|
||||
In,
|
||||
NotIn
|
||||
};
|
||||
|
||||
class Instance {
|
||||
public:
|
||||
Instance(Operator op_, std::vector<Value> &&values_)
|
||||
: op(op_), values(values_) {}
|
||||
|
||||
bool compare(const std::vector<Value> &property_values) const;
|
||||
|
||||
private:
|
||||
Operator op = Operator::Equal;
|
||||
std::vector<Value> values;
|
||||
|
||||
friend std::ostream& operator <<(std::ostream &, const Instance &);
|
||||
};
|
||||
|
||||
public:
|
||||
FilterComparison(const std::string &field_) : field(field_) {};
|
||||
|
||||
const std::string &getField() const;
|
||||
template <typename Extractor> inline bool compare(const Extractor &extractor) const;
|
||||
|
||||
template <typename ...Args>
|
||||
inline void add(Args&& ...args) {
|
||||
instances.emplace_back(::std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
private:
|
||||
std::string field;
|
||||
std::vector<Instance> instances;
|
||||
|
||||
friend std::ostream& operator <<(std::ostream &, const FilterComparison &);
|
||||
};
|
||||
|
||||
std::ostream& operator <<(std::ostream &s, const FilterComparison &comparison);
|
||||
std::ostream& operator <<(std::ostream &s, const FilterComparison::Instance &instance);
|
||||
|
||||
|
||||
FilterComparison::Operator parseFilterComparisonOperator(const std::string &op);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,23 +0,0 @@
|
||||
#ifndef MBGL_STYLE_FILTER_COMPARISON_PRIVATE
|
||||
#define MBGL_STYLE_FILTER_COMPARISON_PRIVATE
|
||||
|
||||
#include "filter_comparison.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
template <typename Extractor>
|
||||
inline bool FilterComparison::compare(const Extractor &extractor) const {
|
||||
const std::vector<Value> values = extractor.getValues(field);
|
||||
|
||||
// All instances are ANDed together.
|
||||
for (const Instance &instance : instances) {
|
||||
if (!instance.compare(values)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,54 +1,125 @@
|
||||
#ifndef MBGL_STYLE_FILTER_EXPRESSION
|
||||
#define MBGL_STYLE_FILTER_EXPRESSION
|
||||
|
||||
#include <mbgl/style/filter_comparison.hpp>
|
||||
#include <mbgl/util/recursive_wrapper.hpp>
|
||||
#include <mbgl/style/value.hpp>
|
||||
|
||||
#include <iosfwd>
|
||||
#include <rapidjson/document.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class FilterExpression {
|
||||
public:
|
||||
typedef mapbox::util::recursive_wrapper<FilterExpression> Wrapper;
|
||||
typedef mapbox::util::variant<
|
||||
struct NullExpression,
|
||||
struct EqualsExpression,
|
||||
struct NotEqualsExpression,
|
||||
struct LessThanExpression,
|
||||
struct LessThanEqualsExpression,
|
||||
struct GreaterThanExpression,
|
||||
struct GreaterThanEqualsExpression,
|
||||
struct InExpression,
|
||||
struct NotInExpression,
|
||||
struct AnyExpression,
|
||||
struct AllExpression,
|
||||
struct NoneExpression
|
||||
> FilterExpression;
|
||||
|
||||
enum class Operator : uint8_t {
|
||||
And,
|
||||
Or,
|
||||
Xor,
|
||||
Nor
|
||||
};
|
||||
FilterExpression parseFilterExpression(const rapidjson::Value&);
|
||||
|
||||
enum class GeometryType : uint8_t {
|
||||
Any,
|
||||
Point,
|
||||
LineString,
|
||||
Polygon
|
||||
};
|
||||
template <class Extractor>
|
||||
bool evaluate(const FilterExpression&, const Extractor&);
|
||||
|
||||
public:
|
||||
FilterExpression() = default;
|
||||
FilterExpression(Operator op_) : op(op_) {};
|
||||
|
||||
bool empty() const;
|
||||
|
||||
template <typename Extractor> bool compare(const Extractor &extractor) const;
|
||||
void add(const FilterComparison &comparison);
|
||||
void add(const FilterExpression &expression);
|
||||
void setGeometryType(GeometryType g);
|
||||
|
||||
private:
|
||||
Operator op = Operator::And;
|
||||
GeometryType type = GeometryType::Any;
|
||||
std::vector<FilterComparison> comparisons;
|
||||
std::vector<FilterExpression::Wrapper> expressions;
|
||||
|
||||
friend std::ostream& operator <<(std::ostream &, const FilterExpression &);
|
||||
struct NullExpression {
|
||||
template <class Extractor>
|
||||
bool evaluate(const Extractor&) const { return true; }
|
||||
};
|
||||
|
||||
std::ostream& operator <<(std::ostream &s, const FilterExpression &expression);
|
||||
struct EqualsExpression {
|
||||
std::string key;
|
||||
Value value;
|
||||
|
||||
template <class Extractor>
|
||||
bool evaluate(const Extractor&) const;
|
||||
};
|
||||
|
||||
struct NotEqualsExpression {
|
||||
std::string key;
|
||||
Value value;
|
||||
|
||||
template <class Extractor>
|
||||
bool evaluate(const Extractor&) const;
|
||||
};
|
||||
|
||||
struct LessThanExpression {
|
||||
std::string key;
|
||||
Value value;
|
||||
|
||||
template <class Extractor>
|
||||
bool evaluate(const Extractor&) const;
|
||||
};
|
||||
|
||||
struct LessThanEqualsExpression {
|
||||
std::string key;
|
||||
Value value;
|
||||
|
||||
template <class Extractor>
|
||||
bool evaluate(const Extractor&) const;
|
||||
};
|
||||
|
||||
struct GreaterThanExpression {
|
||||
std::string key;
|
||||
Value value;
|
||||
|
||||
template <class Extractor>
|
||||
bool evaluate(const Extractor&) const;
|
||||
};
|
||||
|
||||
struct GreaterThanEqualsExpression {
|
||||
std::string key;
|
||||
Value value;
|
||||
|
||||
template <class Extractor>
|
||||
bool evaluate(const Extractor&) const;
|
||||
};
|
||||
|
||||
struct InExpression {
|
||||
std::string key;
|
||||
std::vector<Value> values;
|
||||
|
||||
template <class Extractor>
|
||||
bool evaluate(const Extractor&) const;
|
||||
};
|
||||
|
||||
struct NotInExpression {
|
||||
std::string key;
|
||||
std::vector<Value> values;
|
||||
|
||||
template <class Extractor>
|
||||
bool evaluate(const Extractor&) const;
|
||||
};
|
||||
|
||||
struct AnyExpression {
|
||||
std::vector<FilterExpression> expressions;
|
||||
|
||||
template <class Extractor>
|
||||
bool evaluate(const Extractor&) const;
|
||||
};
|
||||
|
||||
struct AllExpression {
|
||||
std::vector<FilterExpression> expressions;
|
||||
|
||||
template <class Extractor>
|
||||
bool evaluate(const Extractor&) const;
|
||||
};
|
||||
|
||||
struct NoneExpression {
|
||||
std::vector<FilterExpression> expressions;
|
||||
|
||||
template <class Extractor>
|
||||
bool evaluate(const Extractor&) const;
|
||||
};
|
||||
|
||||
FilterExpression::GeometryType parseGeometryType(const std::string &geometry);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,75 +1,118 @@
|
||||
#ifndef MBGL_STYLE_FILTER_EXPRESSION_PRIVATE
|
||||
#define MBGL_STYLE_FILTER_EXPRESSION_PRIVATE
|
||||
|
||||
#include "filter_expression.hpp"
|
||||
#include "filter_comparison_private.hpp"
|
||||
#include <mbgl/util/optional.hpp>
|
||||
#include <mbgl/style/value_comparison.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
template <typename Extractor>
|
||||
bool FilterExpression::compare(const Extractor &extractor) const {
|
||||
if (type != GeometryType::Any && extractor.getType() != type && extractor.getType() != GeometryType::Any) {
|
||||
return false;
|
||||
}
|
||||
template <class Extractor>
|
||||
struct Evaluator : public mapbox::util::static_visitor<bool>
|
||||
{
|
||||
const Extractor& extractor;
|
||||
|
||||
switch (op) {
|
||||
case Operator::And:
|
||||
for (const FilterComparison &comparison : comparisons) {
|
||||
if (!comparison.compare(extractor)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (const FilterExpression &expression: expressions) {
|
||||
if (!expression.compare(extractor)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
case Operator::Or:
|
||||
for (const FilterComparison &comparison : comparisons) {
|
||||
if (comparison.compare(extractor)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (const FilterExpression &expression: expressions) {
|
||||
if (expression.compare(extractor)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Evaluator(const Extractor& extractor_)
|
||||
: extractor(extractor_) {}
|
||||
|
||||
template <class E>
|
||||
bool operator()(const E& e) const { return e.evaluate(extractor); }
|
||||
};
|
||||
|
||||
template <class Extractor>
|
||||
bool evaluate(const FilterExpression& expression, const Extractor& extractor) {
|
||||
return mapbox::util::apply_visitor(Evaluator<Extractor>(extractor), expression);
|
||||
};
|
||||
|
||||
template <class Extractor>
|
||||
bool EqualsExpression::evaluate(const Extractor& extractor) const {
|
||||
mapbox::util::optional<Value> actual = extractor.getValue(key);
|
||||
return actual && util::relaxed_equal(*actual, value);
|
||||
}
|
||||
|
||||
template <class Extractor>
|
||||
bool NotEqualsExpression::evaluate(const Extractor& extractor) const {
|
||||
mapbox::util::optional<Value> actual = extractor.getValue(key);
|
||||
return !actual || util::relaxed_not_equal(*actual, value);
|
||||
}
|
||||
|
||||
template <class Extractor>
|
||||
bool LessThanExpression::evaluate(const Extractor& extractor) const {
|
||||
mapbox::util::optional<Value> actual = extractor.getValue(key);
|
||||
return actual && util::relaxed_less(*actual, value);
|
||||
}
|
||||
|
||||
template <class Extractor>
|
||||
bool LessThanEqualsExpression::evaluate(const Extractor& extractor) const {
|
||||
mapbox::util::optional<Value> actual = extractor.getValue(key);
|
||||
return actual && util::relaxed_less_equal(*actual, value);
|
||||
}
|
||||
|
||||
template <class Extractor>
|
||||
bool GreaterThanExpression::evaluate(const Extractor& extractor) const {
|
||||
mapbox::util::optional<Value> actual = extractor.getValue(key);
|
||||
return actual && util::relaxed_greater(*actual, value);
|
||||
}
|
||||
|
||||
template <class Extractor>
|
||||
bool GreaterThanEqualsExpression::evaluate(const Extractor& extractor) const {
|
||||
mapbox::util::optional<Value> actual = extractor.getValue(key);
|
||||
return actual && util::relaxed_greater_equal(*actual, value);
|
||||
}
|
||||
|
||||
template <class Extractor>
|
||||
bool InExpression::evaluate(const Extractor& extractor) const {
|
||||
mapbox::util::optional<Value> actual = extractor.getValue(key);
|
||||
if (!actual)
|
||||
return false;
|
||||
case Operator::Xor: {
|
||||
int count = 0;
|
||||
for (const FilterComparison &comparison : comparisons) {
|
||||
count += comparison.compare(extractor);
|
||||
if (count > 1) {
|
||||
return false;
|
||||
}
|
||||
for (const auto& v: values) {
|
||||
if (util::relaxed_equal(*actual, v)) {
|
||||
return true;
|
||||
}
|
||||
for (const FilterExpression &expression: expressions) {
|
||||
count += expression.compare(extractor);
|
||||
if (count > 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return count == 1;
|
||||
}
|
||||
case Operator::Nor:
|
||||
for (const FilterComparison &comparison : comparisons) {
|
||||
if (comparison.compare(extractor)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (const FilterExpression &expression: expressions) {
|
||||
if (expression.compare(extractor)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class Extractor>
|
||||
bool NotInExpression::evaluate(const Extractor& extractor) const {
|
||||
mapbox::util::optional<Value> actual = extractor.getValue(key);
|
||||
if (!actual)
|
||||
return true;
|
||||
for (const auto& v: values) {
|
||||
if (util::relaxed_equal(*actual, v)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class Extractor>
|
||||
bool AnyExpression::evaluate(const Extractor& extractor) const {
|
||||
Evaluator<Extractor> evaluator(extractor);
|
||||
for (const auto& e: expressions) {
|
||||
if (mapbox::util::apply_visitor(evaluator, e)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class Extractor>
|
||||
bool AllExpression::evaluate(const Extractor& extractor) const {
|
||||
Evaluator<Extractor> evaluator(extractor);
|
||||
for (const auto& e: expressions) {
|
||||
if (!mapbox::util::apply_visitor(evaluator, e)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class Extractor>
|
||||
bool NoneExpression::evaluate(const Extractor& extractor) const {
|
||||
Evaluator<Extractor> evaluator(extractor);
|
||||
for (const auto& e: expressions) {
|
||||
if (mapbox::util::apply_visitor(evaluator, e)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -21,7 +21,7 @@ enum class PropertyKey {
|
||||
LineTranslateY,
|
||||
LineTranslateAnchor,
|
||||
LineWidth,
|
||||
LineOffset,
|
||||
LineGapWidth,
|
||||
LineBlur,
|
||||
LineDashArray, // for transitions only
|
||||
LineDashLand,
|
||||
|
||||
@@ -64,8 +64,7 @@ public:
|
||||
float line_height = 1.2f * 24 /* em */;
|
||||
float letter_spacing = 0.0f * 24 /* em */;
|
||||
TextJustifyType justify = TextJustifyType::Center;
|
||||
TextHorizontalAlignType horizontal_align = TextHorizontalAlignType::Center;
|
||||
TextVerticalAlignType vertical_align = TextVerticalAlignType::Center;
|
||||
TextAnchorType anchor = TextAnchorType::Center;
|
||||
float max_angle = 45.0f /* degrees */;
|
||||
float rotate = 0.0f;
|
||||
float slant = 0.0f;
|
||||
|
||||
@@ -49,11 +49,11 @@ private:
|
||||
util::ptr<StyleLayer> createLayer(JSVal value);
|
||||
void parseLayers();
|
||||
void parseLayer(std::pair<JSVal, util::ptr<StyleLayer>> &pair);
|
||||
void parseStyles(JSVal value, std::map<ClassID, ClassProperties> &styles);
|
||||
void parseStyle(JSVal, ClassProperties &properties);
|
||||
void parsePaints(JSVal value, std::map<ClassID, ClassProperties> &paints);
|
||||
void parsePaint(JSVal, ClassProperties &properties);
|
||||
void parseReference(JSVal value, util::ptr<StyleLayer> &layer);
|
||||
void parseBucket(JSVal value, util::ptr<StyleLayer> &layer);
|
||||
void parseRender(JSVal value, util::ptr<StyleLayer> &layer);
|
||||
void parseLayout(JSVal value, util::ptr<StyleLayer> &layer);
|
||||
void parseSprite(JSVal value);
|
||||
void parseGlyphURL(JSVal value);
|
||||
|
||||
@@ -85,11 +85,7 @@ private:
|
||||
template <typename T>
|
||||
T parseFunctionArgument(JSVal value);
|
||||
|
||||
|
||||
FilterExpression parseFilter(JSVal, FilterExpression::Operator op);
|
||||
FilterExpression parseFilter(JSVal);
|
||||
Value parseValue(JSVal value);
|
||||
std::vector<Value> parseValues(JSVal values);
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, const rapidjson::Value *> constants;
|
||||
|
||||
@@ -34,7 +34,7 @@ struct LineProperties {
|
||||
std::array<float, 2> translate = {{ 0, 0 }};
|
||||
TranslateAnchorType translateAnchor = TranslateAnchorType::Map;
|
||||
float width = 1;
|
||||
float offset = 0;
|
||||
float gap_width = 0;
|
||||
float blur = 0;
|
||||
std::array<float, 2> dash_array = {{ 1, -1 }};
|
||||
std::string image;
|
||||
|
||||
@@ -152,30 +152,28 @@ MBGL_DEFINE_ENUM_CLASS(TextJustifyTypeClass, TextJustifyType, {
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
enum class TextHorizontalAlignType : uint8_t {
|
||||
enum class TextAnchorType : uint8_t {
|
||||
Center,
|
||||
Left,
|
||||
Center,
|
||||
Right,
|
||||
};
|
||||
|
||||
MBGL_DEFINE_ENUM_CLASS(TextHorizontalAlignTypeClass, TextHorizontalAlignType, {
|
||||
{ TextHorizontalAlignType::Left, "left" },
|
||||
{ TextHorizontalAlignType::Center, "center" },
|
||||
{ TextHorizontalAlignType::Right, "right" },
|
||||
});
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
enum class TextVerticalAlignType : uint8_t {
|
||||
Top,
|
||||
Center,
|
||||
Bottom,
|
||||
TopLeft,
|
||||
TopRight,
|
||||
BottomLeft,
|
||||
BottomRight
|
||||
};
|
||||
|
||||
MBGL_DEFINE_ENUM_CLASS(TextVerticalAlignTypeClass, TextVerticalAlignType, {
|
||||
{ TextVerticalAlignType::Top, "top" },
|
||||
{ TextVerticalAlignType::Center, "center" },
|
||||
{ TextVerticalAlignType::Bottom, "bottom" },
|
||||
MBGL_DEFINE_ENUM_CLASS(TextAnchorTypeClass, TextAnchorType, {
|
||||
{ TextAnchorType::Center, "center" },
|
||||
{ TextAnchorType::Left, "left" },
|
||||
{ TextAnchorType::Right, "right" },
|
||||
{ TextAnchorType::Top, "top" },
|
||||
{ TextAnchorType::Bottom, "bottom" },
|
||||
{ TextAnchorType::TopLeft, "top-left" },
|
||||
{ TextAnchorType::TopRight, "top-right" },
|
||||
{ TextAnchorType::BottomLeft, "bottom-left" },
|
||||
{ TextAnchorType::BottomRight, "bottom-right" }
|
||||
});
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <mbgl/util/variant.hpp>
|
||||
#include <mbgl/util/pbf.hpp>
|
||||
#include <rapidjson/document.h>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cerrno>
|
||||
@@ -14,6 +15,7 @@ typedef mapbox::util::variant<bool, int64_t, uint64_t, double, std::string> Valu
|
||||
std::string toString(const Value &value);
|
||||
|
||||
Value parseValue(pbf data);
|
||||
Value parseValue(const rapidjson::Value&);
|
||||
|
||||
namespace util {
|
||||
inline bool parseNumericString(const std::string &str, double &result) {
|
||||
|
||||
@@ -15,35 +15,35 @@ template <typename Operator>
|
||||
struct relaxed_operator_visitor {
|
||||
typedef bool result_type;
|
||||
|
||||
inline bool operator()(bool lhs, bool rhs) const { return Operator()(lhs, rhs); }
|
||||
template <typename T0, typename T1>
|
||||
inline bool operator()(T0, T1) const { return false; }
|
||||
|
||||
template <typename T, class = typename std::enable_if<std::is_arithmetic<T>::value>::type>
|
||||
inline bool operator()(bool lhs, T rhs) const { return Operator()(T(lhs), rhs); }
|
||||
|
||||
template <typename T, class = typename std::enable_if<std::is_arithmetic<T>::value>::type>
|
||||
inline bool operator()(T lhs, bool rhs) const { return Operator()(lhs, T(rhs)); }
|
||||
template <typename T>
|
||||
inline bool operator()(T lhs, T rhs) const { return Operator()(lhs, rhs); }
|
||||
|
||||
inline bool operator()(int64_t lhs, uint64_t rhs) const {
|
||||
return lhs < 0 ? false : Operator()(uint64_t(lhs), rhs);
|
||||
return Operator()(double(lhs), double(rhs));
|
||||
}
|
||||
|
||||
inline bool operator()(int64_t lhs, double rhs) const {
|
||||
return Operator()(double(lhs), rhs);
|
||||
}
|
||||
|
||||
inline bool operator()(uint64_t lhs, int64_t rhs) const {
|
||||
return rhs < 0 ? false : Operator()(lhs, uint64_t(rhs));
|
||||
return Operator()(double(lhs), double(rhs));
|
||||
}
|
||||
|
||||
template <typename T, class = typename std::enable_if<std::is_arithmetic<T>::value>::type>
|
||||
inline bool operator()(const std::string &lhs, T rhs) const {
|
||||
double value;
|
||||
return parseNumericString(lhs, value) ? Operator()(value, double(rhs)) : false;
|
||||
inline bool operator()(uint64_t lhs, double rhs) const {
|
||||
return Operator()(double(lhs), rhs);
|
||||
}
|
||||
|
||||
template <typename T, class = typename std::enable_if<std::is_arithmetic<T>::value>::type>
|
||||
inline bool operator()(T lhs, const std::string &rhs) const {
|
||||
double value;
|
||||
return parseNumericString(rhs, value) ? Operator()(double(lhs), value) : false;
|
||||
inline bool operator()(double lhs, uint64_t rhs) const {
|
||||
return Operator()(lhs, double(rhs));
|
||||
}
|
||||
|
||||
template <typename T0, typename T1>
|
||||
inline bool operator()(T0 lhs, T1 rhs) const { return Operator()(lhs, rhs); }
|
||||
inline bool operator()(double lhs, int64_t rhs) const {
|
||||
return Operator()(lhs, double(rhs));
|
||||
}
|
||||
};
|
||||
|
||||
struct relaxed_equal_operator {
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#ifndef MBGL_UTIL_TIME
|
||||
#define MBGL_UTIL_TIME
|
||||
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include <ctime>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
@@ -15,6 +17,10 @@ namespace util {
|
||||
// comparisons between different timestamps produce meaningful values.
|
||||
timestamp now();
|
||||
|
||||
|
||||
// Returns the RFC1123 formatted date. E.g. "Tue, 04 Nov 2014 02:13:24 GMT"
|
||||
std::string rfc1123(std::time_t time);
|
||||
|
||||
}
|
||||
|
||||
// used for time conversions
|
||||
|
||||
@@ -11,8 +11,7 @@ namespace util {
|
||||
|
||||
class utf8_to_utf32 {
|
||||
public:
|
||||
explicit utf8_to_utf32() {}
|
||||
std::u32string convert(std::string const& utf8)
|
||||
static std::u32string convert(std::string const& utf8)
|
||||
{
|
||||
boost::u8_to_u32_iterator<std::string::const_iterator> begin(utf8.begin());
|
||||
boost::u8_to_u32_iterator<std::string::const_iterator> end(utf8.end());
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <sstream>
|
||||
|
||||
|
||||
|
||||
GLFWView *view = nullptr;
|
||||
|
||||
void quit_handler(int) {
|
||||
@@ -28,16 +27,32 @@ int main(int argc, char *argv[]) {
|
||||
mbgl::Log::Set<mbgl::StderrLogBackend>();
|
||||
|
||||
int fullscreen_flag = 0;
|
||||
std::string style;
|
||||
|
||||
const struct option long_options[] = {
|
||||
{"fullscreen", no_argument, &fullscreen_flag, 1},
|
||||
{"fullscreen", no_argument, &fullscreen_flag, 'f'},
|
||||
{"style", required_argument, 0, 's'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
while (true) {
|
||||
int option_index = 0;
|
||||
int c = getopt_long(argc, argv, "f", long_options, &option_index);
|
||||
if (c == -1) break;
|
||||
int opt = getopt_long(argc, argv, "fs:", long_options, &option_index);
|
||||
if (opt == -1) break;
|
||||
switch (opt)
|
||||
{
|
||||
case 0:
|
||||
if (long_options[option_index].flag != 0)
|
||||
break;
|
||||
case 'f':
|
||||
// handle fullscreen_flag
|
||||
break;
|
||||
case 's':
|
||||
style = std::string("file://") + std::string(optarg);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// sigint handling
|
||||
@@ -65,7 +80,9 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
// Load style
|
||||
const std::string style = std::string("file://") + uv::cwd() + std::string("/../../styles/styles/bright-v5.json");
|
||||
if (style.empty())
|
||||
style = std::string("file://") + uv::cwd() + std::string("/../../styles/styles/bright-v6.json");
|
||||
|
||||
map.setStyleURL(style);
|
||||
|
||||
int ret = view->run();
|
||||
|
||||
@@ -100,7 +100,7 @@ int main() {
|
||||
if (accessToken) map.setAccessToken([accessToken cStringUsingEncoding:[NSString defaultCStringEncoding]]);
|
||||
|
||||
// Load style
|
||||
const std::string path([[[NSBundle mainBundle] pathForResource:@"bright-v5" ofType:@"json" inDirectory:@"styles/"] UTF8String]);
|
||||
const std::string path([[[NSBundle mainBundle] pathForResource:@"bright-v6" ofType:@"json" inDirectory:@"styles/"] UTF8String]);
|
||||
|
||||
map.setStyleURL(std::string("file://") + path);
|
||||
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
#include <mbgl/storage/http_request_baton.hpp>
|
||||
#include <mbgl/util/std.hpp>
|
||||
#include <mbgl/util/parsedate.h>
|
||||
#include <mbgl/util/time.hpp>
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
#include <mbgl/util/uv.hpp>
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#include <ctime>
|
||||
#include <xlocale.h>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
@@ -21,9 +20,6 @@ void HTTPRequestBaton::start(const util::ptr<HTTPRequestBaton> &ptr) {
|
||||
// Starts the request.
|
||||
util::ptr<HTTPRequestBaton> baton = ptr;
|
||||
|
||||
// Create a C locale
|
||||
static locale_t locale = newlocale(LC_ALL_MASK, nullptr, nullptr);
|
||||
|
||||
dispatch_once(&request_initialize, ^{
|
||||
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
|
||||
sessionConfig.timeoutIntervalForResource = 30;
|
||||
@@ -39,11 +35,8 @@ void HTTPRequestBaton::start(const util::ptr<HTTPRequestBaton> &ptr) {
|
||||
if (!baton->response->etag.empty()) {
|
||||
[request addValue:@(baton->response->etag.c_str()) forHTTPHeaderField:@"If-None-Match"];
|
||||
} else if (baton->response->modified) {
|
||||
const time_t modified = baton->response->modified;
|
||||
struct tm *timeinfo = std::gmtime(&modified);
|
||||
char buffer[32];
|
||||
strftime_l(buffer, 32, "%a, %d %b %Y %H:%M:%S GMT", timeinfo, locale);
|
||||
[request addValue:@(buffer) forHTTPHeaderField:@"If-Modified-Since"];
|
||||
const std::string time = util::rfc1123(baton->response->modified);
|
||||
[request addValue:@(time.c_str()) forHTTPHeaderField:@"If-Modified-Since"];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <mbgl/util/uv-messenger.h>
|
||||
#include <mbgl/util/std.hpp>
|
||||
#include <mbgl/util/ptr.hpp>
|
||||
#include <mbgl/util/time.hpp>
|
||||
|
||||
#include <uv.h>
|
||||
#include <curl/curl.h>
|
||||
@@ -9,8 +10,6 @@
|
||||
#include <queue>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <xlocale.h>
|
||||
|
||||
// This file contains code from http://curl.haxx.se/libcurl/c/multi-uv.html:
|
||||
|
||||
@@ -369,9 +368,6 @@ void start_request(void *const ptr) {
|
||||
util::ptr<HTTPRequestBaton> &baton = *baton_guard.get();
|
||||
assert(baton);
|
||||
|
||||
// Create a C locale
|
||||
static locale_t locale = newlocale(LC_ALL_MASK, nullptr, nullptr);
|
||||
|
||||
CURL *handle = nullptr;
|
||||
if (!handles.empty()) {
|
||||
handle = handles.front();
|
||||
@@ -390,11 +386,9 @@ void start_request(void *const ptr) {
|
||||
const std::string header = std::string("If-None-Match: ") + baton->response->etag;
|
||||
context->headers = curl_slist_append(context->headers, header.c_str());
|
||||
} else if (baton->response->modified) {
|
||||
const time_t modified = baton->response->modified;
|
||||
struct tm *timeinfo = std::gmtime(&modified);
|
||||
char buffer[64];
|
||||
strftime_l(buffer, 64, "If-Modified-Since: %a, %d %b %Y %H:%M:%S GMT", timeinfo, locale);
|
||||
context->headers = curl_slist_append(context->headers, buffer);
|
||||
const std::string time = std::string("If-Modified-Since: ") +
|
||||
util::rfc1123(baton->response->modified);
|
||||
context->headers = curl_slist_append(context->headers, time.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include <mbgl/map/vector_tile.hpp>
|
||||
#include <mbgl/style/filter_expression_private.hpp>
|
||||
#include <mbgl/style/filter_comparison_private.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
@@ -123,81 +122,6 @@ FilteredVectorTileLayer::iterator::iterator(const FilteredVectorTileLayer& paren
|
||||
operator++();
|
||||
}
|
||||
|
||||
//bool FilteredVectorTileLayer::iterator::matchesFilterExpression(const FilterExpression &filterExpression, const pbf &tags_pbf) {
|
||||
// if (filterExpression.empty()) {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// if (filterExpression.is<util::recursive_wrapper<PropertyFilter>>()) {
|
||||
// return matchesFilter(filterExpression.get<util::recursive_wrapper<PropertyFilter>>().get(), tags_pbf);
|
||||
// } else if (filterExpression.is<util::recursive_wrapper<PropertyExpression>>()) {
|
||||
// return matchesExpression(filterExpression.get<util::recursive_wrapper<PropertyExpression>>().get(), tags_pbf);
|
||||
// } else if (filterExpression.is<std::true_type>()) {
|
||||
// return true;
|
||||
// } else {
|
||||
// return false;
|
||||
// }
|
||||
// return true;
|
||||
//}
|
||||
|
||||
//
|
||||
//bool FilteredVectorTileLayer::iterator::matchesFilter(const PropertyFilter &filter, const pbf &const_tags_pbf) {
|
||||
// auto field_it = parent.layer.key_index.find(filter.field);
|
||||
// if (field_it != parent.layer.key_index.end()) {
|
||||
// const uint32_t filter_key = field_it->second;
|
||||
//
|
||||
// // Now loop through all the key/value pair tags.
|
||||
// // tags are packed varints. They should have an even length.
|
||||
// pbf tags_pbf = const_tags_pbf;
|
||||
// while (tags_pbf) {
|
||||
// uint32_t tag_key = tags_pbf.varint();
|
||||
// if (!tags_pbf) {
|
||||
// // This should not happen; otherwise the vector tile
|
||||
// // is invalid.
|
||||
// throw std::runtime_error("uneven number of feature tag ids");
|
||||
// }
|
||||
// uint32_t tag_val = tags_pbf.varint();
|
||||
//
|
||||
// if (tag_key == filter_key) {
|
||||
// if (parent.layer.values.size() > tag_val) {
|
||||
// const Value &value = parent.layer.values[tag_val];
|
||||
// return filter.compare(value);
|
||||
// } else {
|
||||
// throw std::runtime_error("feature references out of range value");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // The feature doesn't contain the field that we're looking to compare.
|
||||
// // Depending on the filter, this may still be okay.
|
||||
// return filter.isMissingFieldOkay();
|
||||
//}
|
||||
//
|
||||
//bool FilteredVectorTileLayer::iterator::matchesExpression(const PropertyExpression &expression, const pbf &tags_pbf) {
|
||||
// if (expression.op == ExpressionOperator::Or) {
|
||||
// for (const PropertyFilterExpression &filterExpression : expression.operands) {
|
||||
// if (matchesFilterExpression(filterExpression, tags_pbf)) {
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
// return false;
|
||||
// } else if (expression.op == ExpressionOperator::And) {
|
||||
// for (const PropertyFilterExpression &filterExpression : expression.operands) {
|
||||
// if (!matchesFilterExpression(filterExpression, tags_pbf)) {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// return true;
|
||||
// } else {
|
||||
// return false;
|
||||
// }
|
||||
//}
|
||||
//
|
||||
|
||||
VectorTileTagExtractor::VectorTileTagExtractor(const VectorTileLayer &layer) : layer_(layer) {}
|
||||
|
||||
|
||||
@@ -205,8 +129,12 @@ void VectorTileTagExtractor::setTags(const pbf &pbf) {
|
||||
tags_ = pbf;
|
||||
}
|
||||
|
||||
std::vector<Value> VectorTileTagExtractor::getValues(const std::string &key) const {
|
||||
std::vector<Value> values;
|
||||
mapbox::util::optional<Value> VectorTileTagExtractor::getValue(const std::string &key) const {
|
||||
if (key == "$type") {
|
||||
return Value(uint64_t(type_));
|
||||
}
|
||||
|
||||
mapbox::util::optional<Value> value;
|
||||
|
||||
auto field_it = layer_.key_index.find(key);
|
||||
if (field_it != layer_.key_index.end()) {
|
||||
@@ -221,14 +149,14 @@ std::vector<Value> VectorTileTagExtractor::getValues(const std::string &key) con
|
||||
if (!tags_pbf) {
|
||||
// This should not happen; otherwise the vector tile is invalid.
|
||||
fprintf(stderr, "[WARNING] uneven number of feature tag ids\n");
|
||||
return values;
|
||||
return value;
|
||||
}
|
||||
// Note: We need to run this command in all cases, even if the keys don't match.
|
||||
tag_val = tags_pbf.varint();
|
||||
|
||||
if (tag_key == filter_key) {
|
||||
if (layer_.values.size() > tag_val) {
|
||||
values.emplace_back(layer_.values[tag_val]);
|
||||
value = layer_.values[tag_val];
|
||||
} else {
|
||||
fprintf(stderr, "[WARNING] feature references out of range value\n");
|
||||
break;
|
||||
@@ -237,16 +165,14 @@ std::vector<Value> VectorTileTagExtractor::getValues(const std::string &key) con
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
return value;
|
||||
}
|
||||
|
||||
void VectorTileTagExtractor::setType(FilterExpression::GeometryType type) {
|
||||
void VectorTileTagExtractor::setType(FeatureType type) {
|
||||
type_ = type;
|
||||
}
|
||||
|
||||
FilterExpression::GeometryType VectorTileTagExtractor::getType() const {
|
||||
return type_;
|
||||
}
|
||||
template bool mbgl::evaluate(const FilterExpression&, const VectorTileTagExtractor&);
|
||||
|
||||
void FilteredVectorTileLayer::iterator::operator++() {
|
||||
valid = false;
|
||||
@@ -256,36 +182,21 @@ void FilteredVectorTileLayer::iterator::operator++() {
|
||||
while (data.next(2)) { // feature
|
||||
feature = data.message();
|
||||
pbf feature_pbf = feature;
|
||||
bool matched = false;
|
||||
|
||||
// Treat the absence of any expression filters as a match.
|
||||
if (expression.empty()) {
|
||||
matched = true;
|
||||
}
|
||||
VectorTileTagExtractor extractor(parent.layer);
|
||||
|
||||
if (!matched) {
|
||||
VectorTileTagExtractor extractor(parent.layer);
|
||||
|
||||
// Retrieve the basic information
|
||||
while (feature_pbf.next()) {
|
||||
if (feature_pbf.tag == 2) { // tags
|
||||
extractor.setTags(feature_pbf.message());
|
||||
} else if (feature_pbf.tag == 3) { // geometry type
|
||||
switch (FeatureType(feature_pbf.varint())) {
|
||||
case FeatureType::Point: extractor.setType(FilterExpression::GeometryType::Point); break;
|
||||
case FeatureType::LineString: extractor.setType(FilterExpression::GeometryType::LineString); break;
|
||||
case FeatureType::Polygon: extractor.setType(FilterExpression::GeometryType::Polygon); break;
|
||||
default: break;
|
||||
}
|
||||
} else {
|
||||
feature_pbf.skip();
|
||||
}
|
||||
// Retrieve the basic information
|
||||
while (feature_pbf.next()) {
|
||||
if (feature_pbf.tag == 2) { // tags
|
||||
extractor.setTags(feature_pbf.message());
|
||||
} else if (feature_pbf.tag == 3) { // geometry type
|
||||
extractor.setType(FeatureType(feature_pbf.varint()));
|
||||
} else {
|
||||
feature_pbf.skip();
|
||||
}
|
||||
|
||||
matched = expression.compare(extractor);
|
||||
}
|
||||
|
||||
if (matched) {
|
||||
if (evaluate(expression, extractor)) {
|
||||
valid = true;
|
||||
return; // data loop
|
||||
} else {
|
||||
|
||||
@@ -17,11 +17,9 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c
|
||||
|
||||
float antialiasing = 1 / state.getPixelRatio();
|
||||
float width = properties.width;
|
||||
float offset = properties.offset / 2;
|
||||
float offset = properties.gap_width == 0 ? 0 : (properties.gap_width + width) / 2;
|
||||
float blur = properties.blur + antialiasing;
|
||||
|
||||
// These are the radii of the line. We are limiting it to 16, which will result
|
||||
// in a point size of 64 on retina.
|
||||
float inset = std::fmin((std::fmax(-1, offset - width / 2 - antialiasing / 2) + 1), 16.0f);
|
||||
float outset = std::fmin(offset + width / 2 + antialiasing / 2, 16.0f);
|
||||
|
||||
|
||||
@@ -52,8 +52,6 @@ std::vector<SymbolFeature> SymbolBucket::processFeatures(const VectorTileLayer &
|
||||
return features;
|
||||
}
|
||||
|
||||
util::utf8_to_utf32 ucs4conv;
|
||||
|
||||
// Determine and load glyph ranges
|
||||
std::set<GlyphRange> ranges;
|
||||
|
||||
@@ -72,7 +70,7 @@ std::vector<SymbolFeature> SymbolBucket::processFeatures(const VectorTileLayer &
|
||||
u8string = platform::lowercase(u8string);
|
||||
}
|
||||
|
||||
ft.label = ucs4conv.convert(u8string);
|
||||
ft.label = util::utf8_to_utf32::convert(u8string);
|
||||
|
||||
if (ft.label.size()) {
|
||||
// Loop through all characters of this text and collect unique codepoints.
|
||||
@@ -105,16 +103,41 @@ void SymbolBucket::addFeatures(const VectorTileLayer &layer, const FilterExpress
|
||||
const std::vector<SymbolFeature> features = processFeatures(layer, filter, glyphStore, sprite);
|
||||
|
||||
float horizontalAlign = 0.5;
|
||||
if (properties.text.horizontal_align == TextHorizontalAlignType::Right)
|
||||
horizontalAlign = 1;
|
||||
else if (properties.text.horizontal_align == TextHorizontalAlignType::Left)
|
||||
horizontalAlign = 0;
|
||||
|
||||
float verticalAlign = 0.5;
|
||||
if (properties.text.vertical_align == TextVerticalAlignType::Bottom)
|
||||
verticalAlign = 1;
|
||||
else if (properties.text.vertical_align == TextVerticalAlignType::Top)
|
||||
verticalAlign = 0;
|
||||
|
||||
switch (properties.text.anchor) {
|
||||
case TextAnchorType::Top:
|
||||
case TextAnchorType::Bottom:
|
||||
case TextAnchorType::Center:
|
||||
break;
|
||||
case TextAnchorType::Right:
|
||||
case TextAnchorType::TopRight:
|
||||
case TextAnchorType::BottomRight:
|
||||
horizontalAlign = 1;
|
||||
break;
|
||||
case TextAnchorType::Left:
|
||||
case TextAnchorType::TopLeft:
|
||||
case TextAnchorType::BottomLeft:
|
||||
horizontalAlign = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (properties.text.anchor) {
|
||||
case TextAnchorType::Left:
|
||||
case TextAnchorType::Right:
|
||||
case TextAnchorType::Center:
|
||||
break;
|
||||
case TextAnchorType::Bottom:
|
||||
case TextAnchorType::BottomLeft:
|
||||
case TextAnchorType::BottomRight:
|
||||
verticalAlign = 1;
|
||||
break;
|
||||
case TextAnchorType::Top:
|
||||
case TextAnchorType::TopLeft:
|
||||
case TextAnchorType::TopRight:
|
||||
verticalAlign = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
float justify = 0.5;
|
||||
if (properties.text.justify == TextJustifyType::Right) justify = 1;
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
#include <mbgl/map/vector_tile.hpp>
|
||||
#include <mbgl/style/filter_comparison_private.hpp>
|
||||
|
||||
#include <mbgl/style/value_comparison.hpp>
|
||||
|
||||
#include <ostream>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
|
||||
inline bool includes(const Value &property_value, const std::vector<Value> &filter_values) {
|
||||
for (const Value &filter_value : filter_values) {
|
||||
if (util::relaxed_equal(property_value, filter_value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Comparer>
|
||||
inline bool compare(const Value &property_value, const std::vector<Value> &filter_values, const Comparer &comparer) {
|
||||
for (const Value &filter_value : filter_values) {
|
||||
if (!comparer(property_value, filter_value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Comparer>
|
||||
inline bool all(const std::vector<Value> &property_values, const std::vector<Value> &filter_values, const Comparer &comparer) {
|
||||
for (const Value &property_value : property_values) {
|
||||
if (!compare(property_value, filter_values, comparer)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
inline bool set_equal(const std::vector<Value> &property_values, const std::vector<Value> &filter_values) {
|
||||
for (const Value &property_value : property_values) {
|
||||
if (!includes(property_value, filter_values)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (property_values.size() == filter_values.size()) {
|
||||
// Optimization: When the count is the same, the set is guaranteed to be identical.
|
||||
return true;
|
||||
}
|
||||
// Otherwise, check again for identical reverse-mapped values.
|
||||
for (const Value &filter_value : filter_values) {
|
||||
if (!includes(filter_value, property_values)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool FilterComparison::Instance::compare(const std::vector<Value> &property_values) const {
|
||||
switch (op) {
|
||||
case Operator::Equal:
|
||||
return set_equal(property_values, values);
|
||||
case Operator::NotEqual:
|
||||
return !set_equal(property_values, values);
|
||||
case Operator::In:
|
||||
for (const Value &property_value : property_values) {
|
||||
if (includes(property_value, values)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
case Operator::NotIn:
|
||||
for (const Value &property_value : property_values) {
|
||||
if (!includes(property_value, values)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
case Operator::Greater:
|
||||
return all(property_values, values, util::relaxed_greater);
|
||||
case Operator::GreaterEqual:
|
||||
return all(property_values, values, util::relaxed_greater_equal);
|
||||
case Operator::Less:
|
||||
return all(property_values, values, util::relaxed_less);
|
||||
case Operator::LessEqual:
|
||||
return all(property_values, values, util::relaxed_less_equal);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const std::string &FilterComparison::getField() const {
|
||||
return field;
|
||||
}
|
||||
|
||||
std::ostream& operator <<(std::ostream &s, const FilterComparison &comparison) {
|
||||
s << "comparison" << std::endl;
|
||||
for (const FilterComparison::Instance &instance : comparison.instances) {
|
||||
s << " - " << comparison.field << " " << instance << std::endl;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
std::ostream& operator <<(std::ostream &s, const FilterComparison::Instance &instance) {
|
||||
switch (instance.op) {
|
||||
case FilterComparison::Operator::Equal: s << "=="; break;
|
||||
case FilterComparison::Operator::NotEqual: s << "!="; break;
|
||||
case FilterComparison::Operator::Greater: s << ">"; break;
|
||||
case FilterComparison::Operator::GreaterEqual: s << ">="; break;
|
||||
case FilterComparison::Operator::Less: s << "<"; break;
|
||||
case FilterComparison::Operator::LessEqual: s << "<="; break;
|
||||
case FilterComparison::Operator::In: s << "in"; break;
|
||||
case FilterComparison::Operator::NotIn: s << "!in"; break;
|
||||
}
|
||||
|
||||
s << " [ ";
|
||||
for (const Value &value : instance.values) {
|
||||
s << toString(value) << " ";
|
||||
}
|
||||
s << "]";
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
FilterComparison::Operator parseFilterComparisonOperator(const std::string &op) {
|
||||
if (op == "==") return FilterComparison::Operator::Equal;
|
||||
if (op == "!=") return FilterComparison::Operator::NotEqual;
|
||||
if (op == ">") return FilterComparison::Operator::Greater;
|
||||
if (op == ">=") return FilterComparison::Operator::GreaterEqual;
|
||||
if (op == "<") return FilterComparison::Operator::Less;
|
||||
if (op == "<=") return FilterComparison::Operator::LessEqual;
|
||||
if (op == "in") return FilterComparison::Operator::In;
|
||||
if (op == "!in") return FilterComparison::Operator::NotIn;
|
||||
return FilterComparison::Operator::Equal;
|
||||
}
|
||||
|
||||
template bool FilterComparison::compare(const VectorTileTagExtractor &extractor) const;
|
||||
|
||||
}
|
||||
@@ -1,66 +1,123 @@
|
||||
#include <mbgl/style/filter_expression_private.hpp>
|
||||
#include <mbgl/map/vector_tile.hpp>
|
||||
|
||||
#include <mbgl/style/value_comparison.hpp>
|
||||
|
||||
#include <ostream>
|
||||
#include <mbgl/platform/log.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
std::ostream& operator <<(std::ostream &s, FilterExpression::Operator op) {
|
||||
switch (op) {
|
||||
case FilterExpression::Operator::And: s << "AND"; break;
|
||||
case FilterExpression::Operator::Or: s << "OR"; break;
|
||||
case FilterExpression::Operator::Xor: s << "XOR"; break;
|
||||
case FilterExpression::Operator::Nor: s << "NOR"; break;
|
||||
Value parseFeatureType(const Value& value) {
|
||||
if (value == std::string("Point")) {
|
||||
return Value(uint64_t(FeatureType::Point));
|
||||
} else if (value == std::string("LineString")) {
|
||||
return Value(uint64_t(FeatureType::LineString));
|
||||
} else if (value == std::string("Polygon")) {
|
||||
return Value(uint64_t(FeatureType::Polygon));
|
||||
} else {
|
||||
Log::Warning(Event::ParseStyle, "value for $type filter must be Point, LineString, or Polygon");
|
||||
return Value(uint64_t(FeatureType::Unknown));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
template <class Expression>
|
||||
FilterExpression parseBinaryFilter(const rapidjson::Value& value) {
|
||||
FilterExpression empty;
|
||||
|
||||
std::ostream& operator <<(std::ostream &s, FilterExpression::GeometryType type) {
|
||||
switch (type) {
|
||||
case FilterExpression::GeometryType::Point: s << "Point"; break;
|
||||
case FilterExpression::GeometryType::LineString: s << "LineString"; break;
|
||||
case FilterExpression::GeometryType::Polygon: s << "Polygon"; break;
|
||||
case FilterExpression::GeometryType::Any: s << "<Any>"; break;
|
||||
if (value.Size() < 3) {
|
||||
Log::Warning(Event::ParseStyle, "filter expression must have 3 elements");
|
||||
return empty;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
bool FilterExpression::empty() const {
|
||||
return type == GeometryType::Any && comparisons.empty() && expressions.empty();
|
||||
}
|
||||
|
||||
void FilterExpression::add(const FilterComparison &comparison) {
|
||||
comparisons.emplace_back(comparison);
|
||||
}
|
||||
|
||||
void FilterExpression::add(const FilterExpression &expression) {
|
||||
expressions.emplace_back(expression);
|
||||
}
|
||||
|
||||
void FilterExpression::setGeometryType(GeometryType g) {
|
||||
type = g;
|
||||
}
|
||||
|
||||
FilterExpression::GeometryType parseGeometryType(const std::string &geometry) {
|
||||
if (geometry == "Point") return FilterExpression::GeometryType::Point;
|
||||
if (geometry == "LineString") return FilterExpression::GeometryType::LineString;
|
||||
if (geometry == "Polygon") return FilterExpression::GeometryType::Polygon;
|
||||
return FilterExpression::GeometryType::Any;
|
||||
}
|
||||
|
||||
std::ostream& operator <<(std::ostream &s, const FilterExpression &expression) {
|
||||
s << "expression " << expression.op << std::endl;
|
||||
s << " - $type = " << expression.type << std::endl;
|
||||
for (const FilterComparison &comparison : expression.comparisons) {
|
||||
s << comparison;
|
||||
if (!value[1u].IsString()) {
|
||||
Log::Warning(Event::ParseStyle, "filter expression key must be a string");
|
||||
return empty;
|
||||
}
|
||||
s << "end expression" << std::endl;
|
||||
return s;
|
||||
|
||||
Expression expression;
|
||||
expression.key = { value[1u].GetString(), value[1u].GetStringLength() };
|
||||
expression.value = parseValue(value[2u]);
|
||||
|
||||
if (expression.key == "$type") {
|
||||
expression.value = parseFeatureType(expression.value);
|
||||
}
|
||||
|
||||
return expression;
|
||||
}
|
||||
|
||||
template bool FilterExpression::compare(const VectorTileTagExtractor &extractor) const;
|
||||
template <class Expression>
|
||||
FilterExpression parseSetFilter(const rapidjson::Value& value) {
|
||||
FilterExpression empty;
|
||||
|
||||
if (value.Size() < 2) {
|
||||
Log::Warning(Event::ParseStyle, "filter expression must at least 2 elements");
|
||||
return empty;
|
||||
}
|
||||
|
||||
if (!value[1u].IsString()) {
|
||||
Log::Warning(Event::ParseStyle, "filter expression key must be a string");
|
||||
return empty;
|
||||
}
|
||||
|
||||
Expression expression;
|
||||
expression.key = { value[1u].GetString(), value[1u].GetStringLength() };
|
||||
for (rapidjson::SizeType i = 2; i < value.Size(); ++i) {
|
||||
expression.values.push_back(parseValue(value[i]));
|
||||
}
|
||||
return expression;
|
||||
}
|
||||
|
||||
template <class Expression>
|
||||
FilterExpression parseCompoundFilter(const rapidjson::Value& value) {
|
||||
Expression expression;
|
||||
for (rapidjson::SizeType i = 1; i < value.Size(); ++i) {
|
||||
expression.expressions.push_back(parseFilterExpression(value[i]));
|
||||
}
|
||||
return expression;
|
||||
}
|
||||
|
||||
FilterExpression parseFilterExpression(const rapidjson::Value& value) {
|
||||
FilterExpression empty;
|
||||
|
||||
if (!value.IsArray()) {
|
||||
Log::Warning(Event::ParseStyle, "filter expression must be an array");
|
||||
return empty;
|
||||
}
|
||||
|
||||
if (value.Size() < 1) {
|
||||
Log::Warning(Event::ParseStyle, "filter expression must have at least 1 element");
|
||||
return empty;
|
||||
}
|
||||
|
||||
if (!value[0u].IsString()) {
|
||||
Log::Warning(Event::ParseStyle, "filter operator must be a string");
|
||||
return empty;
|
||||
}
|
||||
|
||||
std::string op = { value[0u].GetString(), value[0u].GetStringLength() };
|
||||
|
||||
if (op == "==") {
|
||||
return parseBinaryFilter<EqualsExpression>(value);
|
||||
} else if (op == "!=") {
|
||||
return parseBinaryFilter<NotEqualsExpression>(value);
|
||||
} else if (op == ">") {
|
||||
return parseBinaryFilter<GreaterThanExpression>(value);
|
||||
} else if (op == ">=") {
|
||||
return parseBinaryFilter<GreaterThanEqualsExpression>(value);
|
||||
} else if (op == "<") {
|
||||
return parseBinaryFilter<LessThanExpression>(value);
|
||||
} else if (op == "<=") {
|
||||
return parseBinaryFilter<LessThanEqualsExpression>(value);
|
||||
} else if (op == "in") {
|
||||
return parseSetFilter<InExpression>(value);
|
||||
} else if (op == "!in") {
|
||||
return parseSetFilter<NotInExpression>(value);
|
||||
} else if (op == "all") {
|
||||
return parseCompoundFilter<AllExpression>(value);
|
||||
} else if (op == "any") {
|
||||
return parseCompoundFilter<AnyExpression>(value);
|
||||
} else if (op == "none") {
|
||||
return parseCompoundFilter<NoneExpression>(value);
|
||||
} else {
|
||||
Log::Warning(Event::ParseStyle, "filter operator must be one of \"==\", \"!=\", \">\", \">=\", \"<\", \"<=\", \"in\", \"!in\", \"all\", \"any\", \"none\"");
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ const std::map<PropertyKey, PropertyValue> PropertyFallbackValue::properties = {
|
||||
{ PropertyKey::LineTranslateY, defaultStyleProperties<LineProperties>().translate[1] },
|
||||
{ PropertyKey::LineTranslateAnchor, defaultStyleProperties<LineProperties>().translateAnchor },
|
||||
{ PropertyKey::LineWidth, defaultStyleProperties<LineProperties>().width },
|
||||
{ PropertyKey::LineOffset, defaultStyleProperties<LineProperties>().offset },
|
||||
{ PropertyKey::LineGapWidth, defaultStyleProperties<LineProperties>().gap_width },
|
||||
{ PropertyKey::LineBlur, defaultStyleProperties<LineProperties>().blur },
|
||||
{ PropertyKey::LineDashLand, defaultStyleProperties<LineProperties>().dash_array[0] },
|
||||
{ PropertyKey::LineDashGap, defaultStyleProperties<LineProperties>().dash_array[1] },
|
||||
|
||||
@@ -183,7 +183,7 @@ void StyleLayer::applyStyleProperties<LineProperties>(const float z, const times
|
||||
applyTransitionedStyleProperty(PropertyKey::LineTranslateY, line.translate[1], z, now);
|
||||
applyStyleProperty(PropertyKey::LineTranslateAnchor, line.translateAnchor, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::LineWidth, line.width, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::LineOffset, line.offset, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::LineGapWidth, line.gap_width, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::LineBlur, line.blur, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::LineDashLand, line.dash_array[0], z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::LineDashGap, line.dash_array[1], z, now);
|
||||
|
||||
@@ -485,12 +485,12 @@ util::ptr<StyleLayer> StyleParser::createLayer(JSVal value) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Parse styles already, as they can't be inherited anyway.
|
||||
std::map<ClassID, ClassProperties> styles;
|
||||
parseStyles(value, styles);
|
||||
// Parse paints already, as they can't be inherited anyway.
|
||||
std::map<ClassID, ClassProperties> paints;
|
||||
parsePaints(value, paints);
|
||||
|
||||
util::ptr<StyleLayer> layer = std::make_shared<StyleLayer>(
|
||||
layer_id, std::move(styles));
|
||||
layer_id, std::move(paints));
|
||||
|
||||
if (value.HasMember("layers")) {
|
||||
layer->layers = createLayers(value["layers"]);
|
||||
@@ -548,21 +548,21 @@ void StyleParser::parseLayer(std::pair<JSVal, util::ptr<StyleLayer>> &pair) {
|
||||
|
||||
#pragma mark - Parse Styles
|
||||
|
||||
void StyleParser::parseStyles(JSVal value, std::map<ClassID, ClassProperties> &styles) {
|
||||
void StyleParser::parsePaints(JSVal value, std::map<ClassID, ClassProperties> &paints) {
|
||||
rapidjson::Value::ConstMemberIterator itr = value.MemberBegin();
|
||||
for (; itr != value.MemberEnd(); ++itr) {
|
||||
const std::string name { itr->name.GetString(), itr->name.GetStringLength() };
|
||||
|
||||
if (name == "style") {
|
||||
parseStyle(replaceConstant(itr->value), styles[ClassID::Default]);
|
||||
} else if (name.compare(0, 6, "style.") == 0 && name.length() > 6) {
|
||||
if (name == "paint") {
|
||||
parsePaint(replaceConstant(itr->value), paints[ClassID::Default]);
|
||||
} else if (name.compare(0, 6, "paint.") == 0 && name.length() > 6) {
|
||||
const ClassID class_id = ClassDictionary::Get().lookup(name.substr(6));
|
||||
parseStyle(replaceConstant(itr->value), styles[class_id]);
|
||||
parsePaint(replaceConstant(itr->value), paints[class_id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StyleParser::parseStyle(JSVal value, ClassProperties &klass) {
|
||||
void StyleParser::parsePaint(JSVal value, ClassProperties &klass) {
|
||||
using Key = PropertyKey;
|
||||
|
||||
parseOptionalProperty<Function<bool>>("fill-antialias", Key::FillAntialias, klass, value);
|
||||
@@ -586,8 +586,8 @@ void StyleParser::parseStyle(JSVal value, ClassProperties &klass) {
|
||||
parseOptionalProperty<TranslateAnchorType>("line-translate-anchor", Key::LineTranslateAnchor, klass, value);
|
||||
parseOptionalProperty<Function<float>>("line-width", Key::LineWidth, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("line-width-transition", Key::LineWidth, klass, value);
|
||||
parseOptionalProperty<Function<float>>("line-offset", Key::LineOffset, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("line-offset-transition", Key::LineOffset, klass, value);
|
||||
parseOptionalProperty<Function<float>>("line-gap-width", Key::LineGapWidth, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("line-gap-width-transition", Key::LineGapWidth, klass, value);
|
||||
parseOptionalProperty<Function<float>>("line-blur", Key::LineBlur, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("line-blur-transition", Key::LineBlur, klass, value);
|
||||
parseOptionalProperty<Function<float>>("line-dasharray", { Key::LineDashLand, Key::LineDashGap }, klass, value);
|
||||
@@ -711,123 +711,36 @@ void StyleParser::parseBucket(JSVal value, util::ptr<StyleLayer> &layer) {
|
||||
|
||||
if (value.HasMember("filter")) {
|
||||
JSVal value_filter = replaceConstant(value["filter"]);
|
||||
layer->bucket->filter = parseFilter(value_filter);
|
||||
layer->bucket->filter = parseFilterExpression(value_filter);
|
||||
}
|
||||
|
||||
if (value.HasMember("render")) {
|
||||
JSVal value_render = replaceConstant(value["render"]);
|
||||
parseRender(value_render, layer);
|
||||
if (value.HasMember("layout")) {
|
||||
JSVal value_render = replaceConstant(value["layout"]);
|
||||
parseLayout(value_render, layer);
|
||||
}
|
||||
|
||||
if (value.HasMember("min-zoom")) {
|
||||
JSVal min_zoom = value["min-zoom"];
|
||||
if (value.HasMember("minzoom")) {
|
||||
JSVal min_zoom = value["minzoom"];
|
||||
if (min_zoom.IsNumber()) {
|
||||
layer->bucket->min_zoom = min_zoom.GetDouble();
|
||||
} else {
|
||||
Log::Warning(Event::ParseStyle, "min-zoom of layer %s must be numeric", layer->id.c_str());
|
||||
Log::Warning(Event::ParseStyle, "minzoom of layer %s must be numeric", layer->id.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (value.HasMember("max-zoom")) {
|
||||
JSVal max_zoom = value["max-zoom"];
|
||||
if (value.HasMember("maxzoom")) {
|
||||
JSVal max_zoom = value["maxzoom"];
|
||||
if (max_zoom.IsNumber()) {
|
||||
layer->bucket->min_zoom = max_zoom.GetDouble();
|
||||
} else {
|
||||
Log::Warning(Event::ParseStyle, "max-zoom of layer %s must be numeric", layer->id.c_str());
|
||||
Log::Warning(Event::ParseStyle, "maxzoom of layer %s must be numeric", layer->id.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 filter_itr = filterValue.MemberBegin();
|
||||
for (; filter_itr != filterValue.MemberEnd(); ++filter_itr) {
|
||||
comparison.add(
|
||||
parseFilterComparisonOperator({ filter_itr->name.GetString(), filter_itr->name.GetStringLength() }),
|
||||
parseValues(replaceConstant(filter_itr->value))
|
||||
);
|
||||
}
|
||||
} else if (filterValue.IsArray()) {
|
||||
comparison.add(FilterComparison::Operator::In, parseValues(filterValue));
|
||||
} else {
|
||||
comparison.add(FilterComparison::Operator::Equal, std::vector<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 {
|
||||
Log::Warning(Event::ParseStyle, "expression must be either an array or an object");
|
||||
}
|
||||
|
||||
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::vector<Value> StyleParser::parseValues(JSVal value) {
|
||||
std::vector<Value> values;
|
||||
if (value.IsArray()) {
|
||||
for (rapidjson::SizeType i = 0; i < value.Size(); i++) {
|
||||
values.emplace_back(parseValue(replaceConstant(value[i])));
|
||||
}
|
||||
} else {
|
||||
values.emplace_back(parseValue(value));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
void StyleParser::parseRender(JSVal value, util::ptr<StyleLayer> &layer) {
|
||||
void StyleParser::parseLayout(JSVal value, util::ptr<StyleLayer> &layer) {
|
||||
if (!value.IsObject()) {
|
||||
Log::Warning(Event::ParseStyle, "render property of layer '%s' must be an object", layer->id.c_str());
|
||||
Log::Warning(Event::ParseStyle, "layout property of layer '%s' must be an object", layer->id.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -888,8 +801,7 @@ void StyleParser::parseRender(JSVal value, util::ptr<StyleLayer> &layer) {
|
||||
render.text.letter_spacing *= 24; // em
|
||||
}
|
||||
parseRenderProperty<TextJustifyTypeClass>(value, render.text.justify, "text-justify");
|
||||
parseRenderProperty<TextHorizontalAlignTypeClass>(value, render.text.horizontal_align, "text-horizontal-align");
|
||||
parseRenderProperty<TextVerticalAlignTypeClass>(value, render.text.vertical_align, "text-vertical-align");
|
||||
parseRenderProperty<TextAnchorTypeClass>(value, render.text.anchor, "text-anchor");
|
||||
parseRenderProperty(value, render.text.max_angle, "text-max-angle");
|
||||
parseRenderProperty(value, render.text.rotate, "text-rotate");
|
||||
parseRenderProperty(value, render.text.slant, "text-slant");
|
||||
|
||||
@@ -42,3 +42,25 @@ std::string mbgl::toString(const mbgl::Value& value) {
|
||||
else if (value.is<double>()) return boost::lexical_cast<std::string>(value.get<double>());
|
||||
else return "null";
|
||||
}
|
||||
|
||||
mbgl::Value mbgl::parseValue(const rapidjson::Value& 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,5 +8,18 @@ timestamp now() {
|
||||
return uv_hrtime();
|
||||
}
|
||||
|
||||
static const char *week[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
|
||||
static const char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
||||
|
||||
std::string rfc1123(std::time_t time) {
|
||||
std::tm info;
|
||||
gmtime_r(&time, &info);
|
||||
char buffer[30];
|
||||
snprintf(buffer, 30, "%s, %02d %s %4d %02d:%02d:%02d GMT", week[info.tm_wday], info.tm_mday,
|
||||
months[info.tm_mon], 1900 + info.tm_year, info.tm_hour, info.tm_min, info.tm_sec);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
2
styles
2
styles
Submodule styles updated: 65dc5c9b7e...225f78f428
@@ -1,306 +1,103 @@
|
||||
#include <iostream>
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <mbgl/style/filter_comparison_private.hpp>
|
||||
#include <mbgl/map/vector_tile.hpp>
|
||||
#include <mbgl/style/filter_expression.hpp>
|
||||
#include <mbgl/style/filter_expression_private.hpp>
|
||||
|
||||
#include <map>
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
typedef std::multimap<std::string, mbgl::Value> Properties;
|
||||
|
||||
class MockExtractor {
|
||||
class Extractor {
|
||||
public:
|
||||
inline MockExtractor(const std::multimap<std::string, mbgl::Value> &values_) : values(values_) {}
|
||||
inline MockExtractor() {}
|
||||
inline Extractor(const Properties& properties_, FeatureType type_)
|
||||
: properties(properties_)
|
||||
, type(type_)
|
||||
{}
|
||||
|
||||
inline std::vector<mbgl::Value> getValues(const std::string &key) const {
|
||||
std::vector<mbgl::Value> result;
|
||||
// Find all values with the requested key.
|
||||
const auto ret = values.equal_range(key);
|
||||
for (auto it = ret.first; it != ret.second; it++) {
|
||||
// Append the newly found value to the forward list.
|
||||
result.emplace_back(it->second);
|
||||
}
|
||||
return result;
|
||||
mapbox::util::optional<Value> getValue(const std::string &key) const {
|
||||
if (key == "$type")
|
||||
return Value(uint64_t(type));
|
||||
auto it = properties.find(key);
|
||||
if (it == properties.end())
|
||||
return mapbox::util::optional<Value>();
|
||||
return it->second;
|
||||
}
|
||||
|
||||
FeatureType getType() const {
|
||||
return type;
|
||||
}
|
||||
|
||||
private:
|
||||
const std::multimap<std::string, mbgl::Value> values;
|
||||
const Properties properties;
|
||||
FeatureType type;
|
||||
};
|
||||
|
||||
|
||||
TEST(FilterComparison, EqualsSingleStringValue) {
|
||||
using namespace mbgl;
|
||||
|
||||
FilterComparison comparison("test");
|
||||
comparison.add(FilterComparison::Operator::Equal, std::vector<Value> { std::string("bar") });
|
||||
// comparison is { "test": { "==": "bar" } }
|
||||
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("bar") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("booz") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", std::string("bar") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", std::string("bar") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor()));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("barst") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(-18932) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(18932) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(32.8) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(false) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(true) }})));
|
||||
FilterExpression parse(const char * expression) {
|
||||
rapidjson::Document doc;
|
||||
doc.Parse<0>(expression);
|
||||
return parseFilterExpression(doc);
|
||||
}
|
||||
|
||||
|
||||
TEST(FilterComparison, EqualsSingleDoubleValue) {
|
||||
using namespace mbgl;
|
||||
|
||||
FilterComparison comparison("test");
|
||||
comparison.add(FilterComparison::Operator::Equal, std::vector<Value> { double(32.8) });
|
||||
// comparison is { "test": { "==": 32.8 } }
|
||||
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(32.8) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("32.8") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", double(32.8) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(32.8) }, { "test", std::string("booz") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", double(32.8) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor()));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(32.9) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(-18932) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(18932) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(false) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(true) }})));
|
||||
bool evaluate(const FilterExpression& expression, const Properties& properties, FeatureType type = FeatureType::Unknown) {
|
||||
return mbgl::evaluate(expression, Extractor(properties, type));
|
||||
}
|
||||
|
||||
TEST(FilterComparison, EqualsSingleUintValue) {
|
||||
using namespace mbgl;
|
||||
TEST(FilterComparison, EqualsString) {
|
||||
FilterExpression f = parse("[\"==\", \"foo\", \"bar\"]");
|
||||
ASSERT_TRUE(evaluate(f, {{ "foo", std::string("bar") }}));
|
||||
ASSERT_FALSE(evaluate(f, {{ "foo", std::string("baz") }}));
|
||||
};
|
||||
|
||||
FilterComparison comparison("test");
|
||||
comparison.add(FilterComparison::Operator::Equal, std::vector<Value> { uint64_t(42) });
|
||||
// comparison is { "test": { "==": 42 } }
|
||||
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", uint64_t(42) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(42) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(42) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("42") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", uint64_t(42) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(42) }, { "test", std::string("booz") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", uint64_t(42) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor()));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(43) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(-18932) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(18932) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(false) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(true) }})));
|
||||
TEST(FilterComparison, EqualsNumber) {
|
||||
FilterExpression f = parse("[\"==\", \"foo\", 0]");
|
||||
ASSERT_TRUE(evaluate(f, {{ "foo", int64_t(0) }}));
|
||||
ASSERT_TRUE(evaluate(f, {{ "foo", uint64_t(0) }}));
|
||||
ASSERT_TRUE(evaluate(f, {{ "foo", double(0) }}));
|
||||
ASSERT_FALSE(evaluate(f, {{ "foo", int64_t(1) }}));
|
||||
ASSERT_FALSE(evaluate(f, {{ "foo", uint64_t(1) }}));
|
||||
ASSERT_FALSE(evaluate(f, {{ "foo", double(1) }}));
|
||||
ASSERT_FALSE(evaluate(f, {{ "foo", std::string("0") }}));
|
||||
ASSERT_FALSE(evaluate(f, {{ "foo", false }}));
|
||||
ASSERT_FALSE(evaluate(f, {{ "foo", true }}));
|
||||
ASSERT_FALSE(evaluate(f, {{}}));
|
||||
}
|
||||
|
||||
TEST(FilterComparison, EqualsSingleIntValue) {
|
||||
using namespace mbgl;
|
||||
|
||||
FilterComparison comparison("test");
|
||||
comparison.add(FilterComparison::Operator::Equal, std::vector<Value> { int64_t(-42) });
|
||||
// comparison is { "test": { "==": -42 } }
|
||||
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(-42) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(-42) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("-42") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", int64_t(-42) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(-42) }, { "test", std::string("booz") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", int64_t(-42) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor()));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(-43) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(-43) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(-42) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(false) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(true) }})));
|
||||
TEST(FilterComparison, EqualsType) {
|
||||
FilterExpression f = parse("[\"==\", \"$type\", \"LineString\"]");
|
||||
ASSERT_FALSE(evaluate(f, {{}}, FeatureType::Point));
|
||||
ASSERT_TRUE(evaluate(f, {{}}, FeatureType::LineString));
|
||||
}
|
||||
|
||||
TEST(FilterComparison, EqualsSingleBoolValue) {
|
||||
using namespace mbgl;
|
||||
|
||||
FilterComparison comparison("test");
|
||||
comparison.add(FilterComparison::Operator::Equal, std::vector<Value> { bool(true) });
|
||||
// comparison is { "test": { "==": true } }
|
||||
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(true) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(1) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", uint64_t(1) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(1) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("1") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", bool(true) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(true) }, { "test", std::string("booz") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", bool(true) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor()));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(false) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(-18932) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(18932) }})));
|
||||
TEST(FilterComparison, Any) {
|
||||
ASSERT_FALSE(evaluate(parse("[\"any\"]"), {{}}));
|
||||
ASSERT_TRUE(evaluate(parse("[\"any\", [\"==\", \"foo\", 1]]"),
|
||||
{{ std::string("foo"), int64_t(1) }}));
|
||||
ASSERT_FALSE(evaluate(parse("[\"any\", [\"==\", \"foo\", 0]]"),
|
||||
{{ std::string("foo"), int64_t(1) }}));
|
||||
ASSERT_TRUE(evaluate(parse("[\"any\", [\"==\", \"foo\", 0], [\"==\", \"foo\", 1]]"),
|
||||
{{ std::string("foo"), int64_t(1) }}));
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST(FilterComparison, EqualsMultipleStringValues) {
|
||||
using namespace mbgl;
|
||||
|
||||
FilterComparison comparison("test");
|
||||
comparison.add(FilterComparison::Operator::Equal, std::vector<Value> { std::string("bar"), std::string("baz") });
|
||||
// comparison is { "test": { "==": ["bar", "baz"]̇ } }
|
||||
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("baz") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("baz") }, { "test", std::string("bar") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("bar") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("baz") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("baz") }, { "test", std::string("boo") }})));
|
||||
TEST(FilterComparison, All) {
|
||||
ASSERT_TRUE(evaluate(parse("[\"all\"]"), {{}}));
|
||||
ASSERT_TRUE(evaluate(parse("[\"all\", [\"==\", \"foo\", 1]]"),
|
||||
{{ std::string("foo"), int64_t(1) }}));
|
||||
ASSERT_FALSE(evaluate(parse("[\"all\", [\"==\", \"foo\", 0]]"),
|
||||
{{ std::string("foo"), int64_t(1) }}));
|
||||
ASSERT_FALSE(evaluate(parse("[\"all\", [\"==\", \"foo\", 0], [\"==\", \"foo\", 1]]"),
|
||||
{{ std::string("foo"), int64_t(1) }}));
|
||||
}
|
||||
|
||||
TEST(FilterComparison, EqualsMultipleIdenticalStringValues) {
|
||||
using namespace mbgl;
|
||||
|
||||
FilterComparison comparison("test");
|
||||
comparison.add(FilterComparison::Operator::Equal, std::vector<Value> { std::string("bar"), std::string("bar") });
|
||||
// comparison is { "test": { "==": ["bar", "bar"]̇ } }
|
||||
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("bar") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("baz") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("baz") }})));
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST(FilterComparison, NotEqualsSingleStringValue) {
|
||||
using namespace mbgl;
|
||||
|
||||
FilterComparison comparison("test");
|
||||
comparison.add(FilterComparison::Operator::NotEqual, std::vector<Value> { std::string("bar") });
|
||||
// comparison is { "test": { "!=": "bar" } }
|
||||
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("bar") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("bar") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", std::string("bar") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("booz") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", std::string("bar") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor()));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("barst") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(-18932) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", uint64_t(18932) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(32.8) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(false) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(true) }})));
|
||||
}
|
||||
|
||||
|
||||
TEST(FilterComparison, NotEqualsSingleDoubleValue) {
|
||||
using namespace mbgl;
|
||||
|
||||
FilterComparison comparison("test");
|
||||
comparison.add(FilterComparison::Operator::NotEqual, std::vector<Value> { double(32.8) });
|
||||
// comparison is { "test": { "!=": 32.8 } }
|
||||
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(32.8) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("32.8") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", double(32.8) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(32.8) }, { "test", std::string("booz") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", double(32.8) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor()));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(32.9) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(-18932) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", uint64_t(18932) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(false) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(true) }})));
|
||||
}
|
||||
|
||||
TEST(FilterComparison, NotEqualsSingleUintValue) {
|
||||
using namespace mbgl;
|
||||
|
||||
FilterComparison comparison("test");
|
||||
comparison.add(FilterComparison::Operator::NotEqual, std::vector<Value> { uint64_t(42) });
|
||||
// comparison is { "test": { "!=": 42 } }
|
||||
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(42) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(42) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(42) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("42") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", uint64_t(42) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", uint64_t(42) }, { "test", std::string("booz") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", uint64_t(42) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor()));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(43) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(-18932) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", uint64_t(18932) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(false) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(true) }})));
|
||||
}
|
||||
|
||||
|
||||
TEST(FilterComparison, NotEqualsSingleIntValue) {
|
||||
using namespace mbgl;
|
||||
|
||||
FilterComparison comparison("test");
|
||||
comparison.add(FilterComparison::Operator::NotEqual, std::vector<Value> { int64_t(-42) });
|
||||
// comparison is { "test": { "!=": -42 } }
|
||||
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(-42) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(-42) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("-42") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", int64_t(-42) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(-42) }, { "test", std::string("booz") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", int64_t(-42) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor()));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(-43) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(-43) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", uint64_t(-42) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(false) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(true) }})));
|
||||
}
|
||||
|
||||
|
||||
TEST(FilterComparison, NotEqualsSingleBoolValue) {
|
||||
using namespace mbgl;
|
||||
|
||||
FilterComparison comparison("test");
|
||||
comparison.add(FilterComparison::Operator::NotEqual, std::vector<Value> { bool(true) });
|
||||
// comparison is { "test": { "!=": true } }
|
||||
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(true) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(1) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(1) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(1) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("1") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", bool(true) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(true) }, { "test", std::string("booz") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", bool(true) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor()));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(false) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(-18932) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", uint64_t(18932) }})));
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST(FilterComparison, NotEqualsMultipleStringValues) {
|
||||
using namespace mbgl;
|
||||
|
||||
FilterComparison comparison("test");
|
||||
comparison.add(FilterComparison::Operator::NotEqual, std::vector<Value> { std::string("bar"), std::string("baz") });
|
||||
// comparison is { "test": { "!=": ["bar", "baz"]̇ } }
|
||||
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("baz") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("baz") }, { "test", std::string("bar") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("baz") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("baz") }, { "test", std::string("boo") }})));
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST(FilterComparison, NotEqualsMultipleIdenticalStringValues) {
|
||||
using namespace mbgl;
|
||||
|
||||
FilterComparison comparison("test");
|
||||
comparison.add(FilterComparison::Operator::NotEqual, std::vector<Value> { std::string("bar"), std::string("bar") });
|
||||
// comparison is { "test": { "!=": ["bar", "bar"]̇ } }
|
||||
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("bar") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("bar") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("baz") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("baz") }})));
|
||||
TEST(FilterComparison, None) {
|
||||
ASSERT_TRUE(evaluate(parse("[\"none\"]"), {{}}));
|
||||
ASSERT_FALSE(evaluate(parse("[\"none\", [\"==\", \"foo\", 1]]"),
|
||||
{{ std::string("foo"), int64_t(1) }}));
|
||||
ASSERT_TRUE(evaluate(parse("[\"none\", [\"==\", \"foo\", 0]]"),
|
||||
{{ std::string("foo"), int64_t(1) }}));
|
||||
ASSERT_FALSE(evaluate(parse("[\"none\", [\"==\", \"foo\", 0], [\"==\", \"foo\", 1]]"),
|
||||
{{ std::string("foo"), int64_t(1) }}));
|
||||
}
|
||||
|
||||
72
test/fixtures/fixture_request.cpp
vendored
72
test/fixtures/fixture_request.cpp
vendored
@@ -1,72 +0,0 @@
|
||||
#include <mbgl/storage/http_request_baton.hpp>
|
||||
#include <mbgl/storage/file_request_baton.hpp>
|
||||
#include <mbgl/storage/response.hpp>
|
||||
#include <mbgl/util/url.hpp>
|
||||
#include <mbgl/util/std.hpp>
|
||||
#include <mbgl/platform/log.hpp>
|
||||
#include <iostream>
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
|
||||
const std::string base_directory = []{
|
||||
std::string fn = __FILE__;
|
||||
fn.erase(fn.find_last_of("/"));
|
||||
fn.erase(fn.find_last_of("/"));
|
||||
fn.erase(fn.find_last_of("/"));
|
||||
return fn + "/test/suite/";
|
||||
}();
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
void HTTPRequestBaton::start(const util::ptr<HTTPRequestBaton> &baton) {
|
||||
assert(uv_thread_self() == baton->thread_id);
|
||||
|
||||
std::string clean_url = util::percentDecode(baton->path);
|
||||
if (clean_url.find("local://") == 0) {
|
||||
clean_url = base_directory + clean_url.substr(8);
|
||||
}
|
||||
|
||||
baton->response = std::make_unique<Response>();
|
||||
FILE *file = fopen(clean_url.c_str(),"rb");
|
||||
if (file != NULL) {
|
||||
fseek(file, 0, SEEK_END);
|
||||
const size_t size = ftell(file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
baton->response->data.resize(size);
|
||||
const size_t read = fread(&baton->response->data[0], 1, size, file);
|
||||
fclose(file);
|
||||
|
||||
if (read == size) {
|
||||
baton->response->code = 200;
|
||||
baton->type = HTTPResponseType::Successful;
|
||||
} else {
|
||||
baton->response->code = 500;
|
||||
baton->type = HTTPResponseType::PermanentError;
|
||||
baton->response->message = "Read bytes differed from file size";
|
||||
}
|
||||
} else {
|
||||
baton->type = HTTPResponseType::PermanentError;
|
||||
baton->response->code = 404;
|
||||
}
|
||||
|
||||
uv_async_send(baton->async);
|
||||
}
|
||||
|
||||
void HTTPRequestBaton::stop(const util::ptr<HTTPRequestBaton> &/*baton*/) {
|
||||
fprintf(stderr, "HTTP request cannot be canceled because it is answered immediately");
|
||||
abort();
|
||||
}
|
||||
|
||||
namespace platform {
|
||||
|
||||
std::string defaultCacheDatabase() {
|
||||
// Disables the cache.
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
28
test/fixtures/style_parser/colors.style.json
vendored
28
test/fixtures/style_parser/colors.style.json
vendored
@@ -1,39 +1,39 @@
|
||||
{
|
||||
"version": 3,
|
||||
"version": 6,
|
||||
"constants": {
|
||||
"@land": "r44,239,225)",
|
||||
"@snow": "f4f8foNGbjf#",
|
||||
"@crop": "#eerLznieed4"
|
||||
},
|
||||
"sources": {
|
||||
"mapbox": {
|
||||
"type": "vector",
|
||||
"url": "mapbox://mapbox.mapbox-terrain-v1,mapbox.mapbox-streets-v5",
|
||||
"maxZoom": 14
|
||||
"maxzoom": 14
|
||||
}
|
||||
},
|
||||
"constants": {
|
||||
"@land":"r44,239,225)",
|
||||
"@snow":"f4f8foNGbjf#",
|
||||
"@crop":"#eerLznieed4"
|
||||
},
|
||||
"layers": [{
|
||||
"id": "background",
|
||||
"type": "background",
|
||||
"style": {
|
||||
"paint": {
|
||||
"background-color": "@land"
|
||||
}
|
||||
}, {
|
||||
"id": "landcover_snow",
|
||||
"type": "fill",
|
||||
"source": "mapbox",
|
||||
"source-layer": "landcover",
|
||||
"filter": { "class": "snow" },
|
||||
"type": "fill",
|
||||
"style": {
|
||||
"filter": ["==", "class", "snow"],
|
||||
"paint": {
|
||||
"fill-color": "@snow"
|
||||
}
|
||||
}, {
|
||||
"id": "landcover_crop",
|
||||
"type": "fill",
|
||||
"source": "mapbox",
|
||||
"source-layer": "landcover",
|
||||
"filter": { "class": "crop" },
|
||||
"type": "fill",
|
||||
"style": {
|
||||
"filter": ["==", "class", "crop"],
|
||||
"paint": {
|
||||
"fill-color": "@crop"
|
||||
}
|
||||
}]
|
||||
|
||||
6
test/fixtures/style_parser/default.info.json
vendored
6
test/fixtures/style_parser/default.info.json
vendored
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"default": {
|
||||
"log": [
|
||||
]
|
||||
}
|
||||
}
|
||||
2244
test/fixtures/style_parser/default.style.json
vendored
2244
test/fixtures/style_parser/default.style.json
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,19 +1,19 @@
|
||||
{
|
||||
"version": 3,
|
||||
"version": 6,
|
||||
"sources": {
|
||||
"mapbox": {
|
||||
"type": "vector",
|
||||
"url": "mapbox://mapbox.mapbox-terrain-v1,mapbox.mapbox-streets-v5",
|
||||
"maxZoom": 14
|
||||
"maxzoom": 14
|
||||
}
|
||||
},
|
||||
"layers": [{
|
||||
"id": "waterway_river_canal",
|
||||
"type": "line",
|
||||
"source": "mapbox",
|
||||
"source-layer": "waterway",
|
||||
"filter": { "type": ["river", "canal"] },
|
||||
"type": "line",
|
||||
"style": {
|
||||
"filter": ["in", "type", "river", "canal"],
|
||||
"paint": {
|
||||
"line-width": {
|
||||
"stops": [0]
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
{
|
||||
"version": 3,
|
||||
"version": 6,
|
||||
"sources": {
|
||||
"mapbox": {
|
||||
"type": "vector",
|
||||
"url": "mapbox://mapbox.mapbox-terrain-v1,mapbox.mapbox-streets-v5",
|
||||
"maxZoom": 14
|
||||
"maxzoom": 14
|
||||
}
|
||||
},
|
||||
"layers": [{
|
||||
"id": "waterway_river_canal",
|
||||
"type": "line",
|
||||
"source": "mapbox",
|
||||
"source-layer": "waterway",
|
||||
"filter": { "type": ["river", "canal"] },
|
||||
"type": "line",
|
||||
"style": {
|
||||
"filter": ["in", "type", "river", "canal"],
|
||||
"paint": {
|
||||
"line-width": {}
|
||||
}
|
||||
}]
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
{
|
||||
"version": 3,
|
||||
"version": 6,
|
||||
"sources": {
|
||||
"mapbox": {
|
||||
"type": "vector",
|
||||
"url": "mapbox://mapbox.mapbox-terrain-v1,mapbox.mapbox-streets-v5",
|
||||
"maxZoom": 14
|
||||
"maxzoom": 14
|
||||
}
|
||||
},
|
||||
"layers": [{
|
||||
"id": "contour_line_loud",
|
||||
"type": "line",
|
||||
"source": "mapbox",
|
||||
"source-layer": "contour",
|
||||
"filter": { "index": 5 },
|
||||
"type": "line",
|
||||
"style": {
|
||||
"filter": ["==", "index", 5],
|
||||
"paint": {
|
||||
"line-color": "#008",
|
||||
"line-width": 0.9,
|
||||
"line-opacity": null
|
||||
|
||||
10
test/fixtures/style_parser/line-width.style.json
vendored
10
test/fixtures/style_parser/line-width.style.json
vendored
@@ -1,19 +1,19 @@
|
||||
{
|
||||
"version": 3,
|
||||
"version": 6,
|
||||
"sources": {
|
||||
"mapbox": {
|
||||
"type": "vector",
|
||||
"url": "mapbox://mapbox.mapbox-terrain-v1,mapbox.mapbox-streets-v5",
|
||||
"maxZoom": 14
|
||||
"maxzoom": 14
|
||||
}
|
||||
},
|
||||
"layers": [{
|
||||
"id": "waterway_river_canal",
|
||||
"type": "line",
|
||||
"source": "mapbox",
|
||||
"source-layer": "waterway",
|
||||
"filter": { "type": ["river", "canal"] },
|
||||
"type": "line",
|
||||
"style": {
|
||||
"filter": ["in", "type", "river", "canal"],
|
||||
"paint": {
|
||||
"line-width": null
|
||||
}
|
||||
}]
|
||||
|
||||
@@ -1,41 +1,41 @@
|
||||
{
|
||||
"version": 3,
|
||||
"version": 6,
|
||||
"sources": {
|
||||
"mapbox": {
|
||||
"type": "vector",
|
||||
"url": "mapbox://mapbox.mapbox-terrain-v1,mapbox.mapbox-streets-v5",
|
||||
"maxZoom": 14
|
||||
"maxzoom": 14
|
||||
}
|
||||
},
|
||||
"layers": [{
|
||||
"id": "landcover_grass",
|
||||
"type": "fill",
|
||||
"source": "mapbox",
|
||||
"source-layer": "landcover",
|
||||
"filter": { "class": "grass" },
|
||||
"type": "fill",
|
||||
"style": {
|
||||
"filter": ["==", "class", "grass"],
|
||||
"paint": {
|
||||
"fill-opacity": {
|
||||
"stops": []
|
||||
}
|
||||
}
|
||||
}, {
|
||||
"id": "landcover_scrub",
|
||||
"type": "fill",
|
||||
"source": "mapbox",
|
||||
"source-layer": "landcover",
|
||||
"filter": { "class": "scrub" },
|
||||
"type": "fill",
|
||||
"style": {
|
||||
"filter": ["==", "class", "scrub"],
|
||||
"paint": {
|
||||
"fill-opacity": {
|
||||
"stops": [[12]]
|
||||
}
|
||||
}
|
||||
}, {
|
||||
"id": "landcover_wood",
|
||||
"type": "fill",
|
||||
"source": "mapbox",
|
||||
"source-layer": "landcover",
|
||||
"filter": { "class": "wood" },
|
||||
"type": "fill",
|
||||
"style": {
|
||||
"filter": ["==", "class", "wood"],
|
||||
"paint": {
|
||||
"fill-color": "@wood",
|
||||
"fill-opacity": {
|
||||
"stops": [[12, 1], [13, 0.8], [16, 0.2]]
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
{
|
||||
"version": 3,
|
||||
"version": 6,
|
||||
"sources": {
|
||||
"mapbox": {
|
||||
"type": "vector",
|
||||
"url": "mapbox://mapbox.mapbox-terrain-v1,mapbox.mapbox-streets-v5",
|
||||
"maxZoom": 14
|
||||
"maxzoom": 14
|
||||
}
|
||||
},
|
||||
"layers": [{
|
||||
"id": "waterway_river_canal",
|
||||
"type": "line",
|
||||
"source": "mapbox",
|
||||
"source-layer": "waterway",
|
||||
"filter": { "type": ["river", "canal"] },
|
||||
"type": "line",
|
||||
"style": {
|
||||
"filter": ["in", "type", "river", "canal"],
|
||||
"paint": {
|
||||
"line-width": {
|
||||
"stops": null
|
||||
}
|
||||
|
||||
10
test/fixtures/style_parser/text-size.style.json
vendored
10
test/fixtures/style_parser/text-size.style.json
vendored
@@ -1,19 +1,19 @@
|
||||
{
|
||||
"version": 3,
|
||||
"version": 6,
|
||||
"sources": {
|
||||
"mapbox": {
|
||||
"type": "vector",
|
||||
"url": "mapbox://mapbox.mapbox-terrain-v1,mapbox.mapbox-streets-v5",
|
||||
"maxZoom": 14
|
||||
"maxzoom": 14
|
||||
}
|
||||
},
|
||||
"layers": [{
|
||||
"id": "country_label",
|
||||
"type": "text",
|
||||
"source": "mapbox",
|
||||
"source-layer": "country_label",
|
||||
"filter": { "$type": "Point" },
|
||||
"type": "text",
|
||||
"style": {
|
||||
"filter": ["==", "$type", "Point"],
|
||||
"paint": {
|
||||
"text-size": null
|
||||
}
|
||||
}]
|
||||
|
||||
@@ -15,26 +15,72 @@
|
||||
#include "./fixtures/fixture_log.hpp"
|
||||
|
||||
#include <dirent.h>
|
||||
#include <signal.h>
|
||||
#include <libgen.h>
|
||||
|
||||
const std::string base_directory = []{
|
||||
std::string fn = __FILE__;
|
||||
fn.erase(fn.find_last_of("/"));
|
||||
fn.erase(fn.find_last_of("/"));
|
||||
return fn + "/test/suite/";
|
||||
}();
|
||||
std::string base_directory;
|
||||
|
||||
auto display_ = std::make_shared<mbgl::HeadlessDisplay>();
|
||||
|
||||
class ServerEnvironment : public ::testing::Environment {
|
||||
public:
|
||||
virtual void SetUp() {
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
throw std::runtime_error("Cannot create web server");
|
||||
} else if (pid == 0) {
|
||||
char *arg[] = { nullptr };
|
||||
int ret = execv((base_directory + "bin/server.py").c_str(), arg);
|
||||
// This call should not return. In case execve failed, we exit anyway.
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Failed to start server: %s\n", strerror(errno));
|
||||
}
|
||||
exit(0);
|
||||
} else {
|
||||
display = std::make_shared<mbgl::HeadlessDisplay>();
|
||||
}
|
||||
}
|
||||
virtual void TearDown() {
|
||||
ASSERT_TRUE(pid);
|
||||
kill(pid, SIGHUP);
|
||||
}
|
||||
|
||||
std::shared_ptr<mbgl::HeadlessDisplay> display;
|
||||
|
||||
private:
|
||||
pid_t pid = 0;
|
||||
};
|
||||
|
||||
|
||||
ServerEnvironment* env = nullptr;
|
||||
|
||||
|
||||
GTEST_API_ int main(int argc, char *argv[]) {
|
||||
// Note: glibc's dirname() **modifies** the argument and can't handle static strings.
|
||||
std::string argv0 { argv[0] }; argv0 = dirname(const_cast<char *>(argv0.c_str()));
|
||||
std::string file { __FILE__ }; file = dirname(const_cast<char *>(file.c_str()));
|
||||
base_directory = argv0 + "/" + file + "/suite/";
|
||||
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
env = new ServerEnvironment();
|
||||
::testing::AddGlobalTestEnvironment(env);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
class HeadlessTest : public ::testing::TestWithParam<std::string> {};
|
||||
|
||||
TEST_P(HeadlessTest, render) {
|
||||
using namespace mbgl;
|
||||
|
||||
const std::string &base = GetParam();
|
||||
const std::string& base = GetParam();
|
||||
|
||||
std::string style = util::read_file(base_directory + "tests/" + base + "/style.json");
|
||||
std::string info = util::read_file(base_directory + "tests/" + base + "/info.json");
|
||||
|
||||
std::size_t pos = 0;
|
||||
while ((pos = style.find("local://", pos)) != std::string::npos) {
|
||||
style.replace(pos, 8, "http://localhost:2900/");
|
||||
}
|
||||
|
||||
// Parse style.
|
||||
rapidjson::Document styleDoc;
|
||||
styleDoc.Parse<0>((const char *const)style.c_str());
|
||||
@@ -55,8 +101,10 @@ TEST_P(HeadlessTest, render) {
|
||||
Log::Set<FixtureLogBackend>();
|
||||
|
||||
for (auto it = infoDoc.MemberBegin(), end = infoDoc.MemberEnd(); it != end; it++) {
|
||||
const std::string name { it->name.GetString(), it->name.GetStringLength() };
|
||||
const rapidjson::Value &value = it->value;
|
||||
const std::string name {
|
||||
it->name.GetString(), it->name.GetStringLength()
|
||||
};
|
||||
const rapidjson::Value& value = it->value;
|
||||
ASSERT_TRUE(value.IsObject());
|
||||
if (value.HasMember("center")) ASSERT_TRUE(value["center"].IsArray());
|
||||
|
||||
@@ -72,16 +120,16 @@ TEST_P(HeadlessTest, render) {
|
||||
|
||||
std::vector<std::string> classes;
|
||||
if (value.HasMember("classes")) {
|
||||
const rapidjson::Value &js_classes = value["classes"];
|
||||
const rapidjson::Value& js_classes = value["classes"];
|
||||
ASSERT_TRUE(js_classes.IsArray());
|
||||
for (rapidjson::SizeType i = 0; i < js_classes.Size(); i++) {
|
||||
const rapidjson::Value &js_class = js_classes[i];
|
||||
const rapidjson::Value& js_class = js_classes[i];
|
||||
ASSERT_TRUE(js_class.IsString());
|
||||
classes.push_back({ js_class.GetString(), js_class.GetStringLength() });
|
||||
}
|
||||
}
|
||||
|
||||
HeadlessView view(display_);
|
||||
HeadlessView view(env->display);
|
||||
Map map(view);
|
||||
|
||||
map.setStyleJSON(style, base_directory);
|
||||
|
||||
Submodule test/suite updated: 1651a3df44...b94ae79bb1
@@ -42,7 +42,7 @@
|
||||
'../mapboxgl.gyp:mbgl-standalone',
|
||||
],
|
||||
'conditions': [
|
||||
['OS == "mac"', { 'xcode_settings': { 'OTHER_LDFLAGS': [ '<@(ldflags)' ] }
|
||||
['OS == "mac"', { 'xcode_settings': { 'OTHER_LDFLAGS': [ '<@(ldflags)'] }
|
||||
}, {
|
||||
'libraries': [ '<@(ldflags)' ],
|
||||
}]
|
||||
@@ -60,7 +60,7 @@
|
||||
'../mapboxgl.gyp:mbgl-standalone',
|
||||
],
|
||||
'conditions': [
|
||||
['OS == "mac"', { 'xcode_settings': { 'OTHER_LDFLAGS': [ '<@(ldflags)' ] }
|
||||
['OS == "mac"', { 'xcode_settings': { 'OTHER_LDFLAGS': [ '<@(ldflags)'] }
|
||||
}, {
|
||||
'libraries': [ '<@(ldflags)' ],
|
||||
}]
|
||||
@@ -162,9 +162,7 @@
|
||||
'product_name': 'test_headless',
|
||||
'type': 'executable',
|
||||
'sources': [
|
||||
'./main.cpp',
|
||||
'./headless.cpp',
|
||||
'./fixtures/fixture_request.cpp',
|
||||
'./fixtures/fixture_log.cpp',
|
||||
],
|
||||
'conditions': [
|
||||
@@ -188,7 +186,25 @@
|
||||
'<(platform_library)',
|
||||
]
|
||||
},
|
||||
|
||||
{ 'target_name': 'text_conversions',
|
||||
'product_name': 'test_text_conversions',
|
||||
'type': 'executable',
|
||||
'sources': [
|
||||
'./main.cpp',
|
||||
'./text_conversions.cpp',
|
||||
],
|
||||
'dependencies': [
|
||||
'../deps/gtest/gtest.gyp:gtest',
|
||||
'../mapboxgl.gyp:mbgl-standalone',
|
||||
'<(platform_library)',
|
||||
],
|
||||
'conditions': [
|
||||
['OS == "mac"', { 'xcode_settings': { 'OTHER_LDFLAGS': [ '<@(ldflags)', '-framework Foundation' ] }
|
||||
}, {
|
||||
'libraries': [ '<@(ldflags)'],
|
||||
}]
|
||||
]
|
||||
},
|
||||
# Build all targets
|
||||
{ 'target_name': 'test',
|
||||
'type': 'none',
|
||||
@@ -202,6 +218,7 @@
|
||||
'headless',
|
||||
'style_parser',
|
||||
'comparisons',
|
||||
'text_conversions',
|
||||
],
|
||||
}
|
||||
]
|
||||
|
||||
37
test/text_conversions.cpp
Normal file
37
test/text_conversions.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#include <iostream>
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <mbgl/util/utf.hpp>
|
||||
#include <mbgl/platform/platform.hpp>
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
TEST(TextConversions, to_upper) {
|
||||
EXPECT_EQ(std::string("STREET"), platform::uppercase("strEEt")); // EN
|
||||
EXPECT_EQ(std::string("ROAD"), platform::uppercase("rOAd")); // EN
|
||||
|
||||
EXPECT_EQ(std::string("STRASSE"), platform::uppercase("straße")); // DE
|
||||
EXPECT_EQ(std::string("MASSE"), platform::uppercase("maße")); // DE
|
||||
EXPECT_EQ(std::string("WEISSKOPFSEEADLER"), platform::uppercase("weißkopfseeadler")); // DE
|
||||
|
||||
EXPECT_EQ(std::string("AZƏRBAYCAN"), platform::uppercase("Azərbaycan")); // AZ
|
||||
|
||||
EXPECT_EQ(std::string("ὈΔΥΣΣΕΎΣ"), platform::uppercase("Ὀδυσσεύς")); // GR
|
||||
}
|
||||
|
||||
|
||||
TEST(TextConversions, to_lower) {
|
||||
EXPECT_EQ(std::string("street"), platform::lowercase("strEEt")); // EN
|
||||
EXPECT_EQ(std::string("road"), platform::lowercase("rOAd")); // EN
|
||||
|
||||
EXPECT_EQ(std::string("straße"), platform::lowercase("Straße")); // DE
|
||||
EXPECT_EQ(std::string("strasse"), platform::lowercase("STRASSE")); // DE
|
||||
EXPECT_EQ(std::string("masse"), platform::lowercase("MASSE")); // DE
|
||||
EXPECT_EQ(std::string("weisskopfseeadler"), platform::lowercase("weiSSkopfseeadler")); // DE
|
||||
|
||||
EXPECT_EQ(std::string("azərbaycan"), platform::lowercase("AZƏRBAYCAN")); // AZ
|
||||
|
||||
//EXPECT_EQ(std::string("ὀδυσσεύσ"), platform::lowercase("ὈΔΥΣΣΕΎΣ")); // GR
|
||||
// nunicode can't map last Σ to word-ending ς
|
||||
|
||||
}
|
||||
345
test/variant.cpp
345
test/variant.cpp
@@ -17,110 +17,26 @@ TEST(Variant, toString) {
|
||||
EXPECT_EQ("false", toString( false ));
|
||||
}
|
||||
|
||||
|
||||
TEST(Variant, RelaxedEqualityStringToBool) {
|
||||
// 1-ish values are true
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string("1"), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string("1.0"), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string(" 1"), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string(" 0x1"), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string(" 0X1"), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string(" 1.0"), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string(" 1 "), bool(true)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(true), std::string("1")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(true), std::string("1.0")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(true), std::string(" 1")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(true), std::string(" 0x1")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(true), std::string(" 0X1")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(true), std::string(" 1.0")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(true), std::string(" 1 ")));
|
||||
|
||||
// 0-ish values are false
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string("0"), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string("0.0"), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string(" 0"), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string(" 0x0"), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string(" 0X0"), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string(" 0.0"), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string(" 0 "), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string(""), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string(" "), bool(false)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), std::string("0")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), std::string("0.0")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(" 0")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(" 0x0")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(" 0X0")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(" 0.0")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(" 0 ")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), std::string("")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(" ")));
|
||||
|
||||
|
||||
// other string values are neither true nor false
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string(" 1.0 g"), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string("foo"), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string("true"), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string("false"), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string(" inf "), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string(" inFINITY "), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string(" nan "), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string(" NAN "), bool(true)));
|
||||
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), std::string(" 1.0 g")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), std::string("foo")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), std::string("true")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), std::string("false")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), std::string(" inf ")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), std::string(" inFINITY ")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), std::string(" nan ")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), std::string(" NAN ")));
|
||||
|
||||
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string(" 1.0 g"), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string("foo"), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string("true"), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string("false"), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string(" inf "), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string(" inFINITY "), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string(" nan "), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string(" NAN "), bool(false)));
|
||||
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), std::string(" 1.0 g")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), std::string("foo")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), std::string("true")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), std::string("false")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), std::string(" inf ")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), std::string(" inFINITY ")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), std::string(" nan ")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), std::string(" NAN ")));
|
||||
}
|
||||
|
||||
TEST(Variant, RelaxedEquality) {
|
||||
// Compare to bool
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), int64_t(0)));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), uint64_t(0)));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), double(0)));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), std::string("0")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), std::string("")));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(true), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(true), int64_t(1)));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(true), uint64_t(1)));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(true), double(1)));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(true), std::string("1")));
|
||||
|
||||
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), int64_t(0)));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), uint64_t(0)));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), double(0)));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), std::string("0")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), std::string("")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), int64_t(386)));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), int64_t(-7042)));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), uint64_t(386)));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), double(3.145)));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), std::string("386")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), std::string("test")));
|
||||
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), int64_t(1)));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), uint64_t(1)));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), double(1)));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), std::string("1")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), int64_t(386)));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), int64_t(-7042)));
|
||||
@@ -135,10 +51,9 @@ TEST(Variant, RelaxedEquality) {
|
||||
EXPECT_TRUE(util::relaxed_equal(int64_t(-7042), int64_t(-7042)));
|
||||
EXPECT_TRUE(util::relaxed_equal(int64_t(386), uint64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_equal(int64_t(386), double(386)));
|
||||
EXPECT_TRUE(util::relaxed_equal(int64_t(386), std::string("386")));
|
||||
EXPECT_TRUE(util::relaxed_equal(int64_t(1), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_equal(int64_t(0), bool(false)));
|
||||
|
||||
EXPECT_FALSE(util::relaxed_equal(int64_t(386), std::string("386")));
|
||||
EXPECT_FALSE(util::relaxed_equal(int64_t(1), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_equal(int64_t(0), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_equal(int64_t(386), int64_t(387)));
|
||||
EXPECT_FALSE(util::relaxed_equal(int64_t(-7042), int64_t(-7043)));
|
||||
EXPECT_FALSE(util::relaxed_equal(int64_t(386), uint64_t(387)));
|
||||
@@ -151,16 +66,14 @@ TEST(Variant, RelaxedEquality) {
|
||||
EXPECT_FALSE(util::relaxed_equal(int64_t(1), std::string("false")));
|
||||
EXPECT_FALSE(util::relaxed_equal(int64_t(0), std::string("true")));
|
||||
|
||||
|
||||
// Compare to uint64_t
|
||||
EXPECT_TRUE(util::relaxed_equal(uint64_t(386), int64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_equal(uint64_t(386), uint64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_equal(uint64_t(0), uint64_t(0)));
|
||||
EXPECT_TRUE(util::relaxed_equal(uint64_t(386), double(386)));
|
||||
EXPECT_TRUE(util::relaxed_equal(uint64_t(386), std::string("386")));
|
||||
EXPECT_TRUE(util::relaxed_equal(uint64_t(1), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_equal(uint64_t(0), bool(false)));
|
||||
|
||||
EXPECT_FALSE(util::relaxed_equal(uint64_t(386), std::string("386")));
|
||||
EXPECT_FALSE(util::relaxed_equal(uint64_t(1), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_equal(uint64_t(0), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_equal(uint64_t(386), int64_t(387)));
|
||||
EXPECT_FALSE(util::relaxed_equal(uint64_t(386), uint64_t(387)));
|
||||
EXPECT_FALSE(util::relaxed_equal(uint64_t(0), uint64_t(1)));
|
||||
@@ -173,17 +86,15 @@ TEST(Variant, RelaxedEquality) {
|
||||
EXPECT_FALSE(util::relaxed_equal(uint64_t(1), std::string("false")));
|
||||
EXPECT_FALSE(util::relaxed_equal(uint64_t(0), std::string("true")));
|
||||
|
||||
|
||||
// Compare to double
|
||||
EXPECT_TRUE(util::relaxed_equal(double(3.159385), double(3.159385)));
|
||||
EXPECT_TRUE(util::relaxed_equal(double(386), int64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_equal(double(386), uint64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_equal(double(0), uint64_t(0)));
|
||||
EXPECT_TRUE(util::relaxed_equal(double(386), double(386)));
|
||||
EXPECT_TRUE(util::relaxed_equal(double(386), std::string("386")));
|
||||
EXPECT_TRUE(util::relaxed_equal(double(1), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_equal(double(0), bool(false)));
|
||||
|
||||
EXPECT_FALSE(util::relaxed_equal(double(386), std::string("386")));
|
||||
EXPECT_FALSE(util::relaxed_equal(double(1), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_equal(double(0), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_equal(double(3.159385), double(3.159383)));
|
||||
EXPECT_FALSE(util::relaxed_equal(double(386), int64_t(387)));
|
||||
EXPECT_FALSE(util::relaxed_equal(double(386), uint64_t(387)));
|
||||
@@ -205,16 +116,14 @@ TEST(Variant, RelaxedEquality) {
|
||||
EXPECT_FALSE(util::relaxed_equal(double(0), std::string("true")));
|
||||
EXPECT_FALSE(util::relaxed_equal(double(0), std::string("TRUE")));
|
||||
|
||||
|
||||
// Compare to string
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string("lord"), std::string("lord")));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string("386"), int64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string("-386"), int64_t(-386)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string("386"), uint64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string("386.36"), double(386.36)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string(""), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string("1"), bool(true)));
|
||||
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string("386"), int64_t(386)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string("-386"), int64_t(-386)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string("386"), uint64_t(386)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string("386.36"), double(386.36)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string(""), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string("1"), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string("lord"), std::string("baron")));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string("386"), int64_t(387)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string("-386"), int64_t(-387)));
|
||||
@@ -239,46 +148,46 @@ TEST(Variant, RelaxedEquality) {
|
||||
|
||||
TEST(Variant, RelaxedGreater) {
|
||||
EXPECT_TRUE(util::relaxed_greater(std::string("387"), std::string("386")));
|
||||
EXPECT_TRUE(util::relaxed_greater(uint64_t(387), std::string("386")));
|
||||
EXPECT_TRUE(util::relaxed_greater(int64_t(387), std::string("386")));
|
||||
EXPECT_TRUE(util::relaxed_greater(double(387), std::string("386")));
|
||||
EXPECT_TRUE(util::relaxed_greater(bool(true), std::string("0")));
|
||||
EXPECT_FALSE(util::relaxed_greater(uint64_t(387), std::string("386")));
|
||||
EXPECT_FALSE(util::relaxed_greater(int64_t(387), std::string("386")));
|
||||
EXPECT_FALSE(util::relaxed_greater(double(387), std::string("386")));
|
||||
EXPECT_FALSE(util::relaxed_greater(bool(true), std::string("0")));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_greater(std::string("387"), uint64_t(386)));
|
||||
EXPECT_FALSE(util::relaxed_greater(std::string("387"), uint64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater(uint64_t(387), uint64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater(int64_t(387), uint64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater(double(387), uint64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater(bool(true), uint64_t(0)));
|
||||
EXPECT_FALSE(util::relaxed_greater(bool(true), uint64_t(0)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_greater(std::string("387"), int64_t(386)));
|
||||
EXPECT_FALSE(util::relaxed_greater(std::string("387"), int64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater(uint64_t(387), int64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater(int64_t(387), int64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater(double(387), int64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater(bool(true), int64_t(0)));
|
||||
EXPECT_FALSE(util::relaxed_greater(bool(true), int64_t(0)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_greater(std::string("387"), double(386.7)));
|
||||
EXPECT_FALSE(util::relaxed_greater(std::string("387"), double(386.7)));
|
||||
EXPECT_TRUE(util::relaxed_greater(uint64_t(387), double(386.7)));
|
||||
EXPECT_TRUE(util::relaxed_greater(int64_t(387), double(386.7)));
|
||||
EXPECT_TRUE(util::relaxed_greater(double(387), double(386.7)));
|
||||
EXPECT_TRUE(util::relaxed_greater(bool(true), double(0)));
|
||||
EXPECT_FALSE(util::relaxed_greater(bool(true), double(0)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_greater(std::string("387"), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_greater(std::string("387"), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_greater(uint64_t(387), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_greater(int64_t(387), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_greater(double(387), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_greater(double(387), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_greater(uint64_t(387), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_greater(int64_t(387), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_greater(double(387), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_greater(double(387), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_greater(std::string("387"), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_greater(std::string("387"), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_greater(uint64_t(387), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_greater(int64_t(387), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_greater(double(387), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_greater(double(387), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_greater(uint64_t(387), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_greater(int64_t(387), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_greater(double(387), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_greater(double(387), bool(true)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_greater(bool(true), double(0)));
|
||||
EXPECT_TRUE(util::relaxed_greater(bool(true), double(0.5)));
|
||||
EXPECT_TRUE(util::relaxed_greater(bool(true), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_greater(bool(true), int64_t(0)));
|
||||
EXPECT_TRUE(util::relaxed_greater(bool(true), uint64_t(0)));
|
||||
EXPECT_FALSE(util::relaxed_greater(bool(true), double(0)));
|
||||
EXPECT_FALSE(util::relaxed_greater(bool(true), double(0.5)));
|
||||
EXPECT_TRUE(util::relaxed_greater(bool(true), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_greater(bool(true), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_greater(bool(true), int64_t(0)));
|
||||
EXPECT_FALSE(util::relaxed_greater(bool(true), uint64_t(0)));
|
||||
|
||||
|
||||
|
||||
@@ -315,52 +224,52 @@ TEST(Variant, RelaxedGreater) {
|
||||
TEST(Variant, RelaxedGreaterEqual) {
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), std::string("386")));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), std::string("387")));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), std::string("386")));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), std::string("387")));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), std::string("386")));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), std::string("387")));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(double(387), std::string("386")));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(double(387), std::string("387")));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(bool(true), std::string("0")));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(uint64_t(387), std::string("386")));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(uint64_t(387), std::string("387")));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(int64_t(387), std::string("386")));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(int64_t(387), std::string("387")));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(double(387), std::string("386")));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(double(387), std::string("387")));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(bool(true), std::string("0")));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), uint64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), uint64_t(387)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(std::string("387"), uint64_t(386)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(std::string("387"), uint64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), uint64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), uint64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), uint64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), uint64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(double(387), uint64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(double(387), uint64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(bool(true), uint64_t(0)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(bool(true), uint64_t(0)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), int64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), int64_t(387)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(std::string("387"), int64_t(386)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(std::string("387"), int64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), int64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), int64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), int64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), int64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(double(387), int64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(double(387), int64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(bool(true), int64_t(0)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(bool(true), int64_t(0)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), double(386.7)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), double(387)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(std::string("387"), double(386.7)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(std::string("387"), double(387)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), double(386.7)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), double(387)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), double(386.7)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), double(387)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(double(387), double(386.7)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(double(387), double(387)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(bool(true), double(0)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(bool(true), double(0)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(double(387), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(double(387), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(std::string("387"), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(std::string("387"), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(uint64_t(387), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(uint64_t(387), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(int64_t(387), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(int64_t(387), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(double(387), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(double(387), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(bool(true), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(bool(true), bool(true)));
|
||||
|
||||
@@ -391,43 +300,43 @@ TEST(Variant, RelaxedGreaterEqual) {
|
||||
|
||||
TEST(Variant, RelaxedLess) {
|
||||
EXPECT_TRUE(util::relaxed_less(std::string("387"), std::string("388")));
|
||||
EXPECT_TRUE(util::relaxed_less(uint64_t(387), std::string("388")));
|
||||
EXPECT_TRUE(util::relaxed_less(int64_t(387), std::string("388")));
|
||||
EXPECT_TRUE(util::relaxed_less(double(387), std::string("388")));
|
||||
EXPECT_TRUE(util::relaxed_less(bool(false), std::string("388")));
|
||||
EXPECT_TRUE(util::relaxed_less(bool(false), std::string("1")));
|
||||
EXPECT_FALSE(util::relaxed_less(uint64_t(387), std::string("388")));
|
||||
EXPECT_FALSE(util::relaxed_less(int64_t(387), std::string("388")));
|
||||
EXPECT_FALSE(util::relaxed_less(double(387), std::string("388")));
|
||||
EXPECT_FALSE(util::relaxed_less(bool(false), std::string("388")));
|
||||
EXPECT_FALSE(util::relaxed_less(bool(false), std::string("1")));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_less(std::string("387"), uint64_t(388)));
|
||||
EXPECT_FALSE(util::relaxed_less(std::string("387"), uint64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less(uint64_t(387), uint64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less(int64_t(387), uint64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less(double(387), uint64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less(bool(false), uint64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less(bool(false), uint64_t(1)));
|
||||
EXPECT_FALSE(util::relaxed_less(bool(false), uint64_t(388)));
|
||||
EXPECT_FALSE(util::relaxed_less(bool(false), uint64_t(1)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_less(std::string("387"), int64_t(388)));
|
||||
EXPECT_FALSE(util::relaxed_less(std::string("387"), int64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less(uint64_t(387), int64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less(int64_t(387), int64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less(double(387), int64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less(bool(false), int64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less(bool(false), int64_t(1)));
|
||||
EXPECT_FALSE(util::relaxed_less(bool(false), int64_t(388)));
|
||||
EXPECT_FALSE(util::relaxed_less(bool(false), int64_t(1)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_less(std::string("387"), double(387.7)));
|
||||
EXPECT_FALSE(util::relaxed_less(std::string("387"), double(387.7)));
|
||||
EXPECT_TRUE(util::relaxed_less(uint64_t(387), double(387.7)));
|
||||
EXPECT_TRUE(util::relaxed_less(int64_t(387), double(387.7)));
|
||||
EXPECT_TRUE(util::relaxed_less(double(387), double(387.7)));
|
||||
EXPECT_TRUE(util::relaxed_less(bool(false), double(387)));
|
||||
EXPECT_TRUE(util::relaxed_less(bool(false), double(1)));
|
||||
EXPECT_FALSE(util::relaxed_less(bool(false), double(387)));
|
||||
EXPECT_FALSE(util::relaxed_less(bool(false), double(1)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_less(std::string("0"), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_less(uint64_t(0), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_less(int64_t(0), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_less(double(0), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_less(std::string("0"), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_less(uint64_t(0), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_less(int64_t(0), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_less(double(0), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_less(bool(false), bool(true)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_less(bool(true), std::string("386")));
|
||||
EXPECT_TRUE(util::relaxed_less(bool(true), uint64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_less(bool(true), int64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_less(bool(true), double(386)));
|
||||
EXPECT_FALSE(util::relaxed_less(bool(true), std::string("386")));
|
||||
EXPECT_FALSE(util::relaxed_less(bool(true), uint64_t(386)));
|
||||
EXPECT_FALSE(util::relaxed_less(bool(true), int64_t(386)));
|
||||
EXPECT_FALSE(util::relaxed_less(bool(true), double(386)));
|
||||
|
||||
|
||||
|
||||
@@ -464,60 +373,60 @@ TEST(Variant, RelaxedLess) {
|
||||
TEST(Variant, RelaxedLessEqual) {
|
||||
EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), std::string("388")));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), std::string("387")));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), std::string("388")));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), std::string("387")));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), std::string("388")));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), std::string("387")));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(double(387), std::string("388")));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(double(387), std::string("387")));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(bool(false), std::string("388")));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(bool(false), std::string("1")));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(bool(false), std::string("0")));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(uint64_t(387), std::string("388")));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(uint64_t(387), std::string("387")));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(int64_t(387), std::string("388")));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(int64_t(387), std::string("387")));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(double(387), std::string("388")));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(double(387), std::string("387")));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(bool(false), std::string("388")));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(bool(false), std::string("1")));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(bool(false), std::string("0")));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), uint64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), uint64_t(387)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(std::string("387"), uint64_t(388)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(std::string("387"), uint64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), uint64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), uint64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), uint64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), uint64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(double(387), uint64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(double(387), uint64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(bool(false), uint64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(bool(false), uint64_t(1)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(bool(false), uint64_t(0)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(bool(false), uint64_t(388)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(bool(false), uint64_t(1)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(bool(false), uint64_t(0)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), int64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), int64_t(387)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(std::string("387"), int64_t(388)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(std::string("387"), int64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), int64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), int64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), int64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), int64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(double(387), int64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(double(387), int64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(bool(false), int64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(bool(false), int64_t(1)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(bool(false), int64_t(0)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(bool(false), int64_t(388)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(bool(false), int64_t(1)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(bool(false), int64_t(0)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), double(387.7)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), double(387)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(std::string("387"), double(387.7)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(std::string("387"), double(387)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), double(387.7)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), double(387)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), double(387.7)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), double(387)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(double(387), double(387.7)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(double(387), double(387)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(bool(false), double(387)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(bool(false), double(1)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(bool(false), double(0)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(bool(false), double(387)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(bool(false), double(1)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(bool(false), double(0)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_less_equal(std::string("0"), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(std::string("0"), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(uint64_t(0), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(uint64_t(0), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(int64_t(0), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(int64_t(0), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(double(0), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(double(0), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(std::string("0"), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(std::string("0"), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(uint64_t(0), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(uint64_t(0), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(int64_t(0), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(int64_t(0), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(double(0), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(double(0), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(bool(false), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(bool(false), bool(false)));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user