forked from organicmaps/organicmaps
Maps URL Scheme API base parser
This commit is contained in:
parent
f93a18c9bd
commit
9dd1d67db4
4 changed files with 215 additions and 0 deletions
|
@ -50,6 +50,7 @@ HEADERS += \
|
|||
move_screen_task.hpp \
|
||||
change_viewport_task.hpp \
|
||||
dialog_settings.hpp \
|
||||
mwm_url.hpp \
|
||||
|
||||
SOURCES += \
|
||||
feature_vec_model.cpp \
|
||||
|
@ -91,6 +92,7 @@ SOURCES += \
|
|||
move_screen_task.cpp \
|
||||
change_viewport_task.cpp \
|
||||
dialog_settings.cpp \
|
||||
mwm_url.cpp \
|
||||
|
||||
!iphone*:!bada*:!android* {
|
||||
HEADERS += qgl_render_context.hpp
|
||||
|
|
80
map/map_tests/mwm_url_tests.cpp
Normal file
80
map/map_tests/mwm_url_tests.cpp
Normal file
|
@ -0,0 +1,80 @@
|
|||
#include "../../testing/testing.hpp"
|
||||
|
||||
#include "../mwm_url.hpp"
|
||||
#include "../../coding/uri.hpp"
|
||||
|
||||
|
||||
using namespace url_scheme;
|
||||
|
||||
UNIT_TEST(MapApiSmoke)
|
||||
{
|
||||
Uri uri("mapswithme://map?ll=38.970559,-9.419289&ignoreThisParam=Yes&z=17&n=Point%20Name");
|
||||
TEST(uri.IsValid(), ());
|
||||
|
||||
ParsedMapApi api(uri);
|
||||
TEST(api.IsValid(), ());
|
||||
TEST_EQUAL(api.GetPoints().size(), 1, ());
|
||||
TEST_EQUAL(api.GetPoints()[0].m_lat, 38.970559, ());
|
||||
TEST_EQUAL(api.GetPoints()[0].m_lon, -9.419289, ());
|
||||
TEST_EQUAL(api.GetPoints()[0].m_title, "Point Name", ());
|
||||
}
|
||||
|
||||
UNIT_TEST(MapApiInvalidUrl)
|
||||
{
|
||||
TEST(!ParsedMapApi(Uri("competitors://map?ll=12.3,34.54")).IsValid(), ());
|
||||
TEST(!ParsedMapApi(Uri("mapswithme://ggg?ll=12.3,34.54")).IsValid(), ());
|
||||
TEST(!ParsedMapApi(Uri("mapswithme://")).IsValid(), ("No path"));
|
||||
TEST(!ParsedMapApi(Uri("mapswithme://map?")).IsValid(), ("No parameters"));
|
||||
TEST(!ParsedMapApi(Uri("mapswithme://map?ll=23.55")).IsValid(), ("No longtitude"));
|
||||
TEST(!ParsedMapApi(Uri("mapswithme://map?ll=1,2,3")).IsValid(), ("Too many values for ll"));
|
||||
}
|
||||
|
||||
UNIT_TEST(MapApiLatLonLimits)
|
||||
{
|
||||
TEST(!ParsedMapApi(Uri("mapswithme://map?ll=-91,10")).IsValid(), ("Invalid latitude"));
|
||||
TEST(!ParsedMapApi(Uri("mapswithme://map?ll=523.55,10")).IsValid(), ("Invalid latitude"));
|
||||
TEST(ParsedMapApi(Uri("mapswithme://map?ll=23.55,450")).IsValid(), ("But valid longtitude"));
|
||||
TEST(ParsedMapApi(Uri("mapswithme://map?ll=23.55,-450")).IsValid(), ("But valid longtitude"));
|
||||
}
|
||||
|
||||
UNIT_TEST(MapApiPointNameBeforeLatLon)
|
||||
{
|
||||
ParsedMapApi api(Uri("mapswithme://map?n=Name&ll=1,2"));
|
||||
TEST(api.IsValid(), ());
|
||||
TEST_EQUAL(api.GetPoints().size(), 1, ());
|
||||
TEST_EQUAL(api.GetPoints()[0].m_title, "", ());
|
||||
}
|
||||
|
||||
UNIT_TEST(MapApiPointNameOverwritten)
|
||||
{
|
||||
ParsedMapApi api(Uri("mapswithme://map?ll=1,2&n=A&n=B"));
|
||||
TEST(api.IsValid(), ());
|
||||
TEST_EQUAL(api.GetPoints().size(), 1, ());
|
||||
TEST_EQUAL(api.GetPoints()[0].m_title, "B", ());
|
||||
}
|
||||
|
||||
UNIT_TEST(MapApiMultiplePoints)
|
||||
{
|
||||
ParsedMapApi api(Uri("mapswithme://map?ll=1.1,1.2&n=A&ll=2.1,2.2&ll=-3.1,-3.2&n=C"));
|
||||
TEST(api.IsValid(), ());
|
||||
TEST_EQUAL(api.GetPoints().size(), 3, ());
|
||||
TEST_EQUAL(api.GetPoints()[0].m_lat, 1.1, ());
|
||||
TEST_EQUAL(api.GetPoints()[0].m_lon, 1.2, ());
|
||||
TEST_EQUAL(api.GetPoints()[0].m_title, "A", ());
|
||||
TEST_EQUAL(api.GetPoints()[1].m_title, "", ());
|
||||
TEST_EQUAL(api.GetPoints()[1].m_lat, 2.1, ());
|
||||
TEST_EQUAL(api.GetPoints()[1].m_lon, 2.2, ());
|
||||
TEST_EQUAL(api.GetPoints()[2].m_title, "C", ());
|
||||
TEST_EQUAL(api.GetPoints()[2].m_lat, -3.1, ());
|
||||
TEST_EQUAL(api.GetPoints()[2].m_lon, -3.2, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(MapApiInvalidPointLatLonButValidOtherParts)
|
||||
{
|
||||
ParsedMapApi api(Uri("mapswithme://map?ll=1,1,1&n=A&ll=2,2&n=B&ll=3,3,3&n=C"));
|
||||
TEST(api.IsValid(), ());
|
||||
TEST_EQUAL(api.GetPoints().size(), 1, ());
|
||||
TEST_EQUAL(api.GetPoints()[0].m_lat, 2, ());
|
||||
TEST_EQUAL(api.GetPoints()[0].m_lon, 2, ());
|
||||
TEST_EQUAL(api.GetPoints()[0].m_title, "B", ());
|
||||
}
|
92
map/mwm_url.cpp
Normal file
92
map/mwm_url.cpp
Normal file
|
@ -0,0 +1,92 @@
|
|||
#include "mwm_url.hpp"
|
||||
|
||||
#include "../indexer/mercator.hpp"
|
||||
|
||||
#include "../coding/uri.hpp"
|
||||
|
||||
#include "../base/logging.hpp"
|
||||
#include "../base/string_utils.hpp"
|
||||
|
||||
#include "../std/algorithm.hpp"
|
||||
#include "../std/bind.hpp"
|
||||
|
||||
using namespace url_scheme;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
static int const INVALID_LAT_VALUE = -1000;
|
||||
|
||||
bool IsInvalidApiPoint(ApiPoint const & p) { return p.m_lat == INVALID_LAT_VALUE; }
|
||||
|
||||
} // unnames namespace
|
||||
|
||||
ParsedMapApi::ParsedMapApi(Uri const & uri)
|
||||
{
|
||||
if (!Parse(uri))
|
||||
{
|
||||
m_points.clear();
|
||||
}
|
||||
}
|
||||
|
||||
bool ParsedMapApi::IsValid() const
|
||||
{
|
||||
return !m_points.empty();
|
||||
}
|
||||
|
||||
bool ParsedMapApi::Parse(Uri const & uri)
|
||||
{
|
||||
if (uri.GetScheme() != "mapswithme" || uri.GetPath() != "map")
|
||||
return false;
|
||||
|
||||
uri.ForEachKeyValue(bind(&ParsedMapApi::AddKeyValue, this, _1, _2));
|
||||
m_points.erase(remove_if(m_points.begin(), m_points.end(), &IsInvalidApiPoint), m_points.end());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ParsedMapApi::AddKeyValue(string const & key, string const & value)
|
||||
{
|
||||
if (key == "ll")
|
||||
{
|
||||
m_points.push_back(ApiPoint());
|
||||
m_points.back().m_lat = INVALID_LAT_VALUE;
|
||||
|
||||
size_t const firstComma = value.find(',');
|
||||
if (firstComma == string::npos)
|
||||
{
|
||||
LOG(LWARNING, ("Map API: no comma between lat and lon for 'll' key", key, value));
|
||||
return;
|
||||
}
|
||||
|
||||
if (value.find(',', firstComma + 1) != string::npos)
|
||||
{
|
||||
LOG(LWARNING, ("Map API: more than one comma in a value for 'll' key", key, value));
|
||||
return;
|
||||
}
|
||||
|
||||
double lat, lon;
|
||||
if (!strings::to_double(value.substr(0, firstComma), lat) ||
|
||||
!strings::to_double(value.substr(firstComma + 1), lon))
|
||||
{
|
||||
LOG(LWARNING, ("Map API: can't parse lat,lon for 'll' key", key, value));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!MercatorBounds::ValidLat(lat) || !MercatorBounds::ValidLon(lon))
|
||||
{
|
||||
LOG(LWARNING, ("Map API: incorrect value for lat and/or lon", key, value, lat, lon));
|
||||
return;
|
||||
}
|
||||
|
||||
m_points.back().m_lat = lat;
|
||||
m_points.back().m_lon = lon;
|
||||
}
|
||||
else if (key == "n")
|
||||
{
|
||||
if (!m_points.empty())
|
||||
m_points.back().m_title = value;
|
||||
else
|
||||
LOG(LWARNING, ("Map API: Point name with no point. 'll' should come first!"));
|
||||
}
|
||||
}
|
41
map/mwm_url.hpp
Normal file
41
map/mwm_url.hpp
Normal file
|
@ -0,0 +1,41 @@
|
|||
#include "../geometry/rect2d.hpp"
|
||||
#include "../std/string.hpp"
|
||||
|
||||
namespace url_scheme
|
||||
{
|
||||
|
||||
class Uri;
|
||||
|
||||
struct ApiPoint
|
||||
{
|
||||
double m_lat;
|
||||
double m_lon;
|
||||
string m_title;
|
||||
string m_url;
|
||||
};
|
||||
|
||||
/// Handles mapswithme://map?params - everything related to displaying info on a map
|
||||
class ParsedMapApi
|
||||
{
|
||||
public:
|
||||
ParsedMapApi(Uri const & uri);
|
||||
bool IsValid() const;
|
||||
vector<ApiPoint> const & GetPoints() const { return m_points; }
|
||||
|
||||
private:
|
||||
bool Parse(Uri const & uri);
|
||||
void AddKeyValue(string const & key, string const & value);
|
||||
|
||||
vector<ApiPoint> m_points;
|
||||
/*
|
||||
string m_title;
|
||||
string m_backTitle;
|
||||
string m_backUrl;
|
||||
// Calculated from zoom parameter or from m_points
|
||||
m2::RectD m_showRect;
|
||||
|
||||
// vector<char> m_iconData;
|
||||
*/
|
||||
};
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue