From 115afe3b10b2f84a48665d5810feea2b8ab50963 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Thu, 8 May 2014 13:03:59 +0200 Subject: [PATCH] add relaxed comparsion function + tests --- include/llmr/style/value.hpp | 62 ++++++++++++++- test/variant.cpp | 148 +++++++++++++++++++++++++++++++++++ 2 files changed, 209 insertions(+), 1 deletion(-) diff --git a/include/llmr/style/value.hpp b/include/llmr/style/value.hpp index 0ff6e7b20..051f061d3 100644 --- a/include/llmr/style/value.hpp +++ b/include/llmr/style/value.hpp @@ -8,10 +8,70 @@ namespace llmr { typedef util::variant Value; -std::string toString(const Value& value); +std::string toString(const Value &value); Value parseValue(pbf data); +namespace util { + +template +struct string_to_number {}; + +template <> struct string_to_number { + bool operator()(std::string str) const { + std::transform(str.begin(), str.end(), str.begin(), ::tolower); + str.erase(std::remove_if(str.begin(), str.end(), ::isspace), str.end()); + return !(str == "false" || str == "null" || !str.length()); + } +}; + +template <> struct string_to_number { + double operator()(std::string const &str) const try { return std::stod(str); } + catch (...) { return string_to_number()(str); } +}; + +template <> struct string_to_number { + int64_t operator()(std::string const &str) const try { return std::stoll(str); } + catch (...) { return string_to_number()(str); } +}; + +template <> struct string_to_number { + uint64_t operator()(std::string const &str) const try { return std::stoull(str); } + catch (...) { return string_to_number()(str); } +}; + +struct relaxed_equal_visitor { + bool operator()(bool lhs, bool rhs) const { return lhs == rhs; } + + template ::value>::type> + bool operator()(bool lhs, T rhs) const { return lhs == bool(rhs); } + + template ::value>::type> + bool operator()(T lhs, bool rhs) const { return bool(lhs) == rhs; } + + bool operator()(int64_t lhs, uint64_t rhs) const { return lhs < 0 ? false : uint64_t(lhs) == rhs; } + bool operator()(uint64_t lhs, int64_t rhs) const { return rhs < 0 ? false : lhs == uint64_t(rhs); } + + template ::value>::type> + bool operator()(T lhs, const std::string &rhs) const { return lhs == string_to_number()(rhs); } + + template ::value>::type> + bool operator()(const std::string &lhs, T rhs) const { return string_to_number()(lhs) == rhs; } + + template + bool operator()(T0 lhs, T1 rhs) const { return lhs == rhs; } +}; + +template +struct relaxed_equal { + relaxed_equal(T const &lhs) : lhs(lhs) {} + + bool operator()(T const &rhs) const { + return apply_visitor(lhs, rhs, relaxed_equal_visitor()); + } + T const &lhs; +}; +} } #endif diff --git a/test/variant.cpp b/test/variant.cpp index 8d5fd7327..b3f225f65 100644 --- a/test/variant.cpp +++ b/test/variant.cpp @@ -16,3 +16,151 @@ TEST(Variant, toString) { EXPECT_EQ("true", llmr::toString( true )); EXPECT_EQ("false", llmr::toString( false )); } + + +TEST(Variant, RelaxedEquality) { + // Compare to bool + EXPECT_TRUE(util::relaxed_equal(bool(true))(int64_t(386))); + EXPECT_TRUE(util::relaxed_equal(bool(true))(int64_t(-7042))); + EXPECT_TRUE(util::relaxed_equal(bool(false))(int64_t(0))); + EXPECT_TRUE(util::relaxed_equal(bool(true))(uint64_t(386))); + EXPECT_TRUE(util::relaxed_equal(bool(false))(uint64_t(0))); + EXPECT_TRUE(util::relaxed_equal(bool(true))(double(386))); + EXPECT_TRUE(util::relaxed_equal(bool(false))(double(0))); + EXPECT_TRUE(util::relaxed_equal(bool(true))(std::string("386"))); + EXPECT_TRUE(util::relaxed_equal(bool(false))(std::string(""))); + EXPECT_TRUE(util::relaxed_equal(bool(false))(std::string("\t"))); + EXPECT_TRUE(util::relaxed_equal(bool(false))(std::string(" "))); + EXPECT_TRUE(util::relaxed_equal(bool(false))(std::string("false"))); + EXPECT_TRUE(util::relaxed_equal(bool(false))(std::string(" false"))); + EXPECT_TRUE(util::relaxed_equal(bool(false))(std::string("False"))); + EXPECT_TRUE(util::relaxed_equal(bool(false))(std::string("null"))); + EXPECT_TRUE(util::relaxed_equal(bool(false))(std::string("nuLL"))); + EXPECT_TRUE(util::relaxed_equal(bool(false))(std::string("NULL"))); + EXPECT_TRUE(util::relaxed_equal(bool(false))(std::string(" NULL "))); + EXPECT_TRUE(util::relaxed_equal(bool(true))(bool(true))); + EXPECT_TRUE(util::relaxed_equal(bool(false))(bool(false))); + + EXPECT_FALSE(util::relaxed_equal(bool(true))(int64_t(0))); + EXPECT_FALSE(util::relaxed_equal(bool(true))(uint64_t(0))); + EXPECT_FALSE(util::relaxed_equal(bool(true))(double(0))); + EXPECT_FALSE(util::relaxed_equal(bool(true))(std::string(""))); + EXPECT_FALSE(util::relaxed_equal(bool(true))(std::string("false"))); + EXPECT_FALSE(util::relaxed_equal(bool(true))(std::string("FALSE"))); + EXPECT_FALSE(util::relaxed_equal(bool(true))(std::string("null"))); + EXPECT_FALSE(util::relaxed_equal(bool(true))(std::string("Null"))); + EXPECT_FALSE(util::relaxed_equal(bool(false))(int64_t(-754))); + EXPECT_FALSE(util::relaxed_equal(bool(false))(uint64_t(3))); + EXPECT_FALSE(util::relaxed_equal(bool(false))(double(3.145))); + EXPECT_FALSE(util::relaxed_equal(bool(false))(std::string("test"))); + EXPECT_FALSE(util::relaxed_equal(bool(true))(bool(false))); + EXPECT_FALSE(util::relaxed_equal(bool(false))(bool(true))); + + + // Compare to int64_t + EXPECT_TRUE(util::relaxed_equal(int64_t(386))(int64_t(386))); + 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_TRUE(util::relaxed_equal(int64_t(1))(std::string("true"))); + EXPECT_TRUE(util::relaxed_equal(int64_t(0))(std::string("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))); + EXPECT_FALSE(util::relaxed_equal(int64_t(386))(double(387))); + EXPECT_FALSE(util::relaxed_equal(int64_t(386))(std::string("387"))); + EXPECT_FALSE(util::relaxed_equal(int64_t(1))(bool(false))); + EXPECT_FALSE(util::relaxed_equal(int64_t(0))(bool(true))); + 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_TRUE(util::relaxed_equal(uint64_t(1))(std::string("true"))); + EXPECT_TRUE(util::relaxed_equal(uint64_t(0))(std::string("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))); + EXPECT_FALSE(util::relaxed_equal(uint64_t(386))(double(387))); + EXPECT_FALSE(util::relaxed_equal(uint64_t(386))(std::string("387"))); + EXPECT_FALSE(util::relaxed_equal(uint64_t(1))(bool(false))); + EXPECT_FALSE(util::relaxed_equal(uint64_t(0))(bool(true))); + EXPECT_FALSE(util::relaxed_equal(uint64_t(1))(std::string("false"))); + EXPECT_FALSE(util::relaxed_equal(uint64_t(0))(std::string("true"))); + 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_TRUE(util::relaxed_equal(double(1))(std::string("true"))); + EXPECT_TRUE(util::relaxed_equal(double(1))(std::string("TRue"))); + EXPECT_TRUE(util::relaxed_equal(double(0))(std::string("false"))); + EXPECT_TRUE(util::relaxed_equal(double(0))(std::string("FALSe"))); + EXPECT_TRUE(util::relaxed_equal(double(0))(std::string("null"))); + EXPECT_TRUE(util::relaxed_equal(double(0))(std::string("Null"))); + EXPECT_TRUE(util::relaxed_equal(double(0))(std::string(" Null "))); + + 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))); + EXPECT_FALSE(util::relaxed_equal(double(0))(uint64_t(1))); + EXPECT_FALSE(util::relaxed_equal(double(386))(double(387))); + EXPECT_FALSE(util::relaxed_equal(double(386))(std::string("387"))); + EXPECT_FALSE(util::relaxed_equal(double(1))(bool(false))); + EXPECT_FALSE(util::relaxed_equal(double(0))(bool(true))); + EXPECT_FALSE(util::relaxed_equal(double(1))(std::string("false"))); + EXPECT_FALSE(util::relaxed_equal(double(1))(std::string("False"))); + EXPECT_FALSE(util::relaxed_equal(double(1))(std::string("null"))); + EXPECT_FALSE(util::relaxed_equal(double(1))(std::string("NULL"))); + 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("true"))(bool(true))); + EXPECT_TRUE(util::relaxed_equal(std::string("True"))(bool(true))); + EXPECT_TRUE(util::relaxed_equal(std::string("some string"))(bool(true))); + EXPECT_TRUE(util::relaxed_equal(std::string("false"))(bool(false))); + EXPECT_TRUE(util::relaxed_equal(std::string("fAlse"))(bool(false))); + EXPECT_TRUE(util::relaxed_equal(std::string("null"))(bool(false))); + EXPECT_TRUE(util::relaxed_equal(std::string("NULl"))(bool(false))); + EXPECT_TRUE(util::relaxed_equal(std::string(""))(bool(false))); + + 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))); + EXPECT_FALSE(util::relaxed_equal(std::string("386"))(uint64_t(387))); + EXPECT_FALSE(util::relaxed_equal(std::string("386.36"))(double(386.37))); + EXPECT_FALSE(util::relaxed_equal(std::string("true"))(bool(false))); + EXPECT_FALSE(util::relaxed_equal(std::string("TRUE"))(bool(false))); + EXPECT_FALSE(util::relaxed_equal(std::string("some string"))(bool(false))); + EXPECT_FALSE(util::relaxed_equal(std::string("false"))(bool(true))); + EXPECT_FALSE(util::relaxed_equal(std::string("FALSE"))(bool(true))); + EXPECT_FALSE(util::relaxed_equal(std::string("null"))(bool(true))); + EXPECT_FALSE(util::relaxed_equal(std::string("NULl"))(bool(true))); + EXPECT_FALSE(util::relaxed_equal(std::string(""))(bool(true))); +}