From bf986ed042a265ebf98fee8d8b1c6cf6a51e1e25 Mon Sep 17 00:00:00 2001 From: Yury Melnichek Date: Tue, 31 May 2011 20:41:44 +0200 Subject: [PATCH] [search] Add search::MatchLatLon(). --- search/latlon_match.cpp | 54 +++++++++++++++++++++++ search/latlon_match.hpp | 10 +++++ search/search.pro | 2 + search/search_tests/latlon_match_test.cpp | 52 ++++++++++++++++++++++ search/search_tests/search_tests.pro | 1 + 5 files changed, 119 insertions(+) create mode 100644 search/latlon_match.cpp create mode 100644 search/latlon_match.hpp create mode 100644 search/search_tests/latlon_match_test.cpp diff --git a/search/latlon_match.cpp b/search/latlon_match.cpp new file mode 100644 index 0000000000..84ddb794ae --- /dev/null +++ b/search/latlon_match.cpp @@ -0,0 +1,54 @@ +#include "latlon_match.hpp" +#include "../std/cstdlib.hpp" + +namespace +{ + +template void Skip(CharT * & s) +{ + // 0xC2 - commond Unicode first byte for ANSI (not ASCII!) symbols. + // 0xC2,0xB0 - degree symbol. + while (*s == ' ' || *s == ',' || *s == ';' || *s == ':' || *s == '.' || *s == '(' || *s == ')' || + *s == char(0xB0) || *s == char(0xC2)) + ++s; +} + +} // unnamed namespace + +bool search::MatchLatLon(string const & str, double & latRes, double & lonRes) +{ + char const * s = str.c_str(); + + Skip(s); + if (!*s) + return false; + + char * s1; + double const lat = strtod(s, &s1); + if (!s1 || !*s1) + return false; + + Skip(s1); + if (!*s1) + return false; + + char * s2; + double lon = strtod(s1, &s2); + if (!s2) + return false; + + Skip(s2); + if (*s2) + return false; + + if (lat < -90 || lat > 90) + return false; + if (lon < -180 || lon > 360) + return false; + if (lon > 180) + lon = lon - 360; + + latRes = lat; + lonRes = lon; + return true; +} diff --git a/search/latlon_match.hpp b/search/latlon_match.hpp new file mode 100644 index 0000000000..a3bd2d0150 --- /dev/null +++ b/search/latlon_match.hpp @@ -0,0 +1,10 @@ +#pragma once +#include "../base/base.hpp" +#include "../std/string.hpp" + +namespace search +{ + +bool MatchLatLon(string const & s, double & lat, double & lon); + +} // namespace search diff --git a/search/search.pro b/search/search.pro index c82a87cedf..3ea2c7a0c8 100644 --- a/search/search.pro +++ b/search/search.pro @@ -17,6 +17,7 @@ HEADERS += \ query.hpp \ result.hpp \ string_match.hpp \ + latlon_match.hpp SOURCES += \ delimiters.cpp \ @@ -26,3 +27,4 @@ SOURCES += \ query.cpp \ result.cpp \ string_match.cpp \ + latlon_match.cpp diff --git a/search/search_tests/latlon_match_test.cpp b/search/search_tests/latlon_match_test.cpp new file mode 100644 index 0000000000..d001f6fc9b --- /dev/null +++ b/search/search_tests/latlon_match_test.cpp @@ -0,0 +1,52 @@ +#include "../../testing/testing.hpp" +#include "../latlon_match.hpp" +#include "../../std/utility.hpp" + +namespace +{ + +pair TestLatLonMatchSuccessful(string const & s) +{ + double lat = -3500; + double lon = -3500; + TEST(search::MatchLatLon(s, lat, lon), (s, lat, lon)); + return make_pair(lat, lon); +} + +void TestLatLonFailed(string const & s) +{ + double lat = -3500; + double lon = -3500; + TEST(!search::MatchLatLon(s, lat, lon), (s, lat, lon)); + TEST_EQUAL(lat, -3500, ()); + TEST_EQUAL(lon, -3500, ()); +} + +} // unnamed namespace + +UNIT_TEST(LatLonMatch) +{ + TestLatLonFailed(""); + TestLatLonFailed("0.0"); + TestLatLonFailed("2.0 sadas 2.0"); + TestLatLonFailed("90.1 0.0"); + TestLatLonFailed("-90.1 0.0"); + TestLatLonFailed("0.0 361"); + TestLatLonFailed("0.0 -181.0"); + + TEST_EQUAL(make_pair(2.0, 3.0), TestLatLonMatchSuccessful("2.0 3.0"), ()); + TEST_EQUAL(make_pair(2.0, 3.0), TestLatLonMatchSuccessful("2.0, 3.0"), ()); + TEST_EQUAL(make_pair(2.0, 3.0), TestLatLonMatchSuccessful("2.0;3.0"), ()); + TEST_EQUAL(make_pair(2.0, 3.0), TestLatLonMatchSuccessful("2;3.0"), ()); + TEST_EQUAL(make_pair(2.0, 3.03232424), TestLatLonMatchSuccessful("2.0;3.03232424"), ()); + TEST_EQUAL(make_pair(2.0, 3.0), TestLatLonMatchSuccessful("2 3"), ()); + TEST_EQUAL(make_pair(2.0, 3.0), TestLatLonMatchSuccessful("2 3."), ()); + TEST_EQUAL(make_pair(2.0, 3.0), TestLatLonMatchSuccessful("(2.0, 3.0)"), ()); + TEST_EQUAL(make_pair(0.0, 0.0), TestLatLonMatchSuccessful("0.0 0.0"), ()); + TEST_EQUAL(make_pair(0.0, 180.0), TestLatLonMatchSuccessful("0.0 180"), ()); + TEST_EQUAL(make_pair(0.0, -179.0), TestLatLonMatchSuccessful("0.0 181"), ()); + TEST_EQUAL(make_pair(0.0, -170.0), TestLatLonMatchSuccessful("0.0 -170"), ()); + TEST_EQUAL(make_pair(0.0, -180.0), TestLatLonMatchSuccessful("0.0 -180"), ()); + TEST_EQUAL(make_pair(0.0, -160.0), TestLatLonMatchSuccessful("0.0 200"), ()); + TEST_EQUAL(make_pair(0.0, 0.0), TestLatLonMatchSuccessful("0.0 360"), ()); +} diff --git a/search/search_tests/search_tests.pro b/search/search_tests/search_tests.pro index b5a30dd80f..67a61e8466 100644 --- a/search/search_tests/search_tests.pro +++ b/search/search_tests/search_tests.pro @@ -22,6 +22,7 @@ SOURCES += \ keyword_matcher_test.cpp \ query_test.cpp \ string_match_test.cpp \ + latlon_match_test.cpp \ HEADERS += \ match_cost_mock.hpp \