forked from organicmaps/organicmaps
Parsing big url API
This commit is contained in:
parent
d58c23e529
commit
4ae7f95bad
5 changed files with 300 additions and 9 deletions
|
@ -838,6 +838,7 @@ void Framework::DrawAdditionalInfo(shared_ptr<PaintEvent> const & e)
|
|||
m_informationDisplay.drawPlacemark(pDrawer, DEFAULT_BOOKMARK_TYPE, m_navigator.GtoP(m_placemark));
|
||||
|
||||
m_bmManager.DrawBookmarks(e);
|
||||
DrawMapApiPoints(e);
|
||||
|
||||
pScreen->endFrame();
|
||||
|
||||
|
@ -1449,6 +1450,10 @@ bool Framework::SetViewportByURL(string const & url, url_api::Request & request)
|
|||
return true;
|
||||
}
|
||||
}
|
||||
else if (strings::StartsWith(url, "mapswithme://") || strings::StartsWith(url, "mwm://"))
|
||||
{
|
||||
m_ParsedMapApi.SetUriAndParse(url);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1614,3 +1619,58 @@ string Framework::CodeGe0url(double const lat, double const lon, double const zo
|
|||
|
||||
return res;
|
||||
}
|
||||
|
||||
void Framework::DrawMapApiPoints(shared_ptr<PaintEvent> const & e)
|
||||
{
|
||||
Navigator & navigator = GetNavigator();
|
||||
InformationDisplay & informationDisplay = GetInformationDisplay();
|
||||
// get viewport limit rect
|
||||
m2::AnyRectD const & glbRect = navigator.Screen().GlobalRect();
|
||||
Drawer * pDrawer = e->drawer();
|
||||
|
||||
vector<url_scheme::ApiPoint> const & v = GetMapApiPoints();
|
||||
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
{
|
||||
m2::PointD const & org = m2::PointD(MercatorBounds::LonToX(v[i].m_lon),
|
||||
MercatorBounds::LatToY(v[i].m_lat));
|
||||
if (glbRect.IsPointInside(org))
|
||||
//ToDo Use Custom Pins
|
||||
//super magic hack!!! Only purple! Only hardcore
|
||||
informationDisplay.drawPlacemark(pDrawer, "placemark-purple", navigator.GtoP(org));
|
||||
}
|
||||
}
|
||||
|
||||
void Framework::MapApiSetUriAndParse(string const & url)
|
||||
{
|
||||
m_ParsedMapApi.SetUriAndParse(url);
|
||||
}
|
||||
|
||||
//Dummy method. TODO create method that will run all layers without copy/past
|
||||
bool Framework::GetMapApiPoint(m2::PointD const & pxPoint, url_scheme::ApiPoint & point)
|
||||
{
|
||||
int const sm = TOUCH_PIXEL_RADIUS * GetVisualScale();
|
||||
m2::RectD const rect(PtoG(m2::PointD(pxPoint.x - sm, pxPoint.y - sm)),
|
||||
PtoG(m2::PointD(pxPoint.x + sm, pxPoint.y + sm)));
|
||||
double minD = numeric_limits<double>::max();
|
||||
bool result = false;
|
||||
|
||||
vector <url_scheme::ApiPoint> const & vect = m_ParsedMapApi.GetPoints();
|
||||
|
||||
for (size_t i = 0; i < vect.size();++i)
|
||||
{
|
||||
m2::PointD const pt = m2::PointD(m2::PointD(MercatorBounds::LonToX(vect[i].m_lon),
|
||||
MercatorBounds::LatToY(vect[i].m_lat)));
|
||||
if (rect.IsPointInside(pt))
|
||||
{
|
||||
double const d = rect.Center().SquareLength(pt);
|
||||
if (d < minD)
|
||||
{
|
||||
point = vect[i];
|
||||
minD = d;
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "bookmark.hpp"
|
||||
#include "bookmark_manager.hpp"
|
||||
#include "url_api.hpp"
|
||||
#include "mwm_url.hpp"
|
||||
|
||||
#include "../defines.hpp"
|
||||
|
||||
|
@ -451,4 +452,18 @@ public:
|
|||
public:
|
||||
string CodeGe0url(Bookmark const * bmk, bool const addName);
|
||||
string CodeGe0url(double const lat, double const lon, double const zoomLevel, string const & name);
|
||||
|
||||
private:
|
||||
url_scheme::ParsedMapApi m_ParsedMapApi;
|
||||
void DrawMapApiPoints(shared_ptr<PaintEvent> const & e);
|
||||
|
||||
public:
|
||||
void MapApiSetUriAndParse(string const & url);
|
||||
bool GetMapApiPoint(m2::PointD const & pxPoint, url_scheme::ApiPoint & point);
|
||||
vector<url_scheme::ApiPoint> const & GetMapApiPoints() { return m_ParsedMapApi.GetPoints(); }
|
||||
void ClearMapApiPoints() { m_ParsedMapApi.Clear(); }
|
||||
int GetMapApiVersion() const { return m_ParsedMapApi.GetApiversion(); }
|
||||
string const & GetMapApiAppTitle() const { return m_ParsedMapApi.GetAppTitle(); }
|
||||
string const & GetMapApiBackUrl() const { return m_ParsedMapApi.GetGlobalBackUrl(); }
|
||||
m2::RectD GetMapApiRect() const { return m_ParsedMapApi.GetRect(); }
|
||||
};
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
#include "../mwm_url.hpp"
|
||||
#include "../../coding/uri.hpp"
|
||||
|
||||
#include "../../base/string_format.hpp"
|
||||
#include "../../base/pseudo_random.hpp"
|
||||
#include "../../base/logging.hpp"
|
||||
|
||||
using namespace url_scheme;
|
||||
|
||||
|
@ -18,6 +21,7 @@ UNIT_TEST(MapApiSmoke)
|
|||
TEST_EQUAL(api.GetPoints()[0].m_lon, -9.419289, ());
|
||||
TEST_EQUAL(api.GetPoints()[0].m_title, "Point Name", ());
|
||||
TEST_EQUAL(api.GetPoints()[0].m_url, "", ());
|
||||
TEST_EQUAL(api.GetGlobalBackUrl(), "", ());
|
||||
}
|
||||
|
||||
UNIT_TEST(MapApiInvalidUrl)
|
||||
|
@ -88,3 +92,184 @@ UNIT_TEST(MapApiPointURLEncoded)
|
|||
TEST_EQUAL(api.GetPoints()[0].m_title, "\xd0\x9c\xd0\xb8\xd0\xbd\xd1\x81\xd0\xba", ());
|
||||
TEST_EQUAL(api.GetPoints()[0].m_url, "http://map?ll=1,2&n=test", ());
|
||||
}
|
||||
|
||||
UNIT_TEST(GlobalBackUrl)
|
||||
{
|
||||
{
|
||||
ParsedMapApi api(Uri("mwm://map?ll=1,2&n=PointName&backurl=ge0://"));
|
||||
TEST_EQUAL(api.GetGlobalBackUrl(), "ge0://", ());
|
||||
}
|
||||
{
|
||||
ParsedMapApi api(Uri("mwm://map?ll=1,2&n=PointName&backurl=ge0%3A%2F%2F"));
|
||||
TEST_EQUAL(api.GetGlobalBackUrl(), "ge0://", ());
|
||||
}
|
||||
{
|
||||
ParsedMapApi api(Uri("mwm://map?ll=1,2&n=PointName&backurl=http://mapswithme.com"));
|
||||
TEST_EQUAL(api.GetGlobalBackUrl(), "http://mapswithme.com", ());
|
||||
}
|
||||
{
|
||||
ParsedMapApi api(Uri("mwm://map?ll=1,2&n=PointName&backurl=someapp://%D0%9C%D0%BE%D0%B1%D0%B8%D0%BB%D1%8C%D0%BD%D1%8B%D0%B5%20%D0%9A%D0%B0%D1%80%D1%82%D1%8B"));
|
||||
TEST_EQUAL(api.GetGlobalBackUrl(), "someapp://\xd0\x9c\xd0\xbe\xd0\xb1\xd0\xb8\xd0\xbb\xd1\x8c\xd0\xbd\xd1\x8b\xd0\xb5 \xd0\x9a\xd0\xb0\xd1\x80\xd1\x82\xd1\x8b", ());
|
||||
}
|
||||
{
|
||||
ParsedMapApi api(Uri("mwm://map?ll=1,2&n=PointName"));
|
||||
TEST_EQUAL(api.GetGlobalBackUrl(), "", ());
|
||||
}
|
||||
{
|
||||
ParsedMapApi api(Uri("mwm://map?ll=1,2&n=PointName&backurl=%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5%3A%2F%2F%D0%BE%D1%82%D0%BA%D1%80%D0%BE%D0%B9%D0%A1%D1%81%D1%8B%D0%BB%D0%BA%D1%83"));
|
||||
TEST_EQUAL(api.GetGlobalBackUrl(), "приложение://откройСсылку", ());
|
||||
}
|
||||
{
|
||||
ParsedMapApi api(Uri("mwm://map?ll=1,2&n=PointName&backurl=%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5%3A%2F%2F%D0%BE%D1%82%D0%BA%D1%80%D0%BE%D0%B9%D0%A1%D1%81%D1%8B%D0%BB%D0%BA%D1%83"));
|
||||
TEST_EQUAL(api.GetGlobalBackUrl(), "приложение://откройСсылку", ());
|
||||
}
|
||||
{
|
||||
ParsedMapApi api(Uri("mwm://map?ll=1,2&n=PointName&backurl=%E6%88%91%E6%84%9Bmapswithme"));
|
||||
TEST_EQUAL(api.GetGlobalBackUrl(), "我愛mapswithme", ());
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(VersionTest)
|
||||
{
|
||||
{
|
||||
ParsedMapApi api(Uri("mwm://map?ll=1,2&v=1&n=PointName"));
|
||||
TEST_EQUAL(api.GetApiversion(), 1, ());
|
||||
}
|
||||
{
|
||||
ParsedMapApi api(Uri("mwm://map?ll=1,2&v=kotik&n=PointName"));
|
||||
TEST_EQUAL(api.GetApiversion(), 0, ());
|
||||
}
|
||||
{
|
||||
ParsedMapApi api(Uri("mwm://map?ll=1,2&v=APacanyVoobsheKotjata&n=PointName"));
|
||||
TEST_EQUAL(api.GetApiversion(), 0, ());
|
||||
}
|
||||
{
|
||||
ParsedMapApi api(Uri("mwm://map?ll=1,2&n=PointName"));
|
||||
TEST_EQUAL(api.GetApiversion(), 0, ());
|
||||
}
|
||||
{
|
||||
ParsedMapApi api(Uri("mwm://map?v=666&ll=1,2&n=PointName"));
|
||||
TEST_EQUAL(api.GetApiversion(), 666, ());
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(AppNameTest)
|
||||
{
|
||||
{
|
||||
ParsedMapApi api(Uri("mwm://map?ll=1,2&v=1&n=PointName&appname=Google"));
|
||||
TEST_EQUAL(api.GetAppTitle(), "Google", ());
|
||||
}
|
||||
{
|
||||
ParsedMapApi api(Uri("mwm://map?ll=1,2&v=1&n=PointName&appname=%D0%AF%D0%BD%D0%B4%D0%B5%D0%BA%D1%81"));
|
||||
TEST_EQUAL(api.GetAppTitle(), "Яндекс", ());
|
||||
}
|
||||
{
|
||||
ParsedMapApi api(Uri("mwm://map?ll=1,2&v=1&n=PointName"));
|
||||
TEST_EQUAL(api.GetAppTitle(), "", ());
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(RectTest)
|
||||
{
|
||||
{
|
||||
ParsedMapApi api(Uri("mwm://map?ll=0,0"));
|
||||
m2::RectD rect = api.GetRect();
|
||||
TEST_EQUAL(rect.maxX(), 0, ());
|
||||
TEST_EQUAL(rect.maxY(), 0, ());
|
||||
TEST_EQUAL(rect.minX(), 0, ());
|
||||
TEST_EQUAL(rect.minX(), 0, ());
|
||||
}
|
||||
{
|
||||
ParsedMapApi api(Uri("mwm://map?ll=0,0&ll=1,1&ll=2,2&ll=3,3&ll=4,4&ll=5,5&"));
|
||||
m2::RectD rect = api.GetRect();
|
||||
TEST_EQUAL(rect.maxX(), 5, ());
|
||||
TEST_EQUAL(rect.maxY(), 5, ());
|
||||
TEST_EQUAL(rect.minX(), 0, ());
|
||||
TEST_EQUAL(rect.minX(), 0, ());
|
||||
}
|
||||
{
|
||||
ParsedMapApi api(Uri("mwm://map?ll=-90,90&ll=90,-90"));
|
||||
m2::RectD rect = api.GetRect();
|
||||
TEST_EQUAL(rect.maxX(), 90, ());
|
||||
TEST_EQUAL(rect.maxY(), 90, ());
|
||||
TEST_EQUAL(rect.minX(), -90, ());
|
||||
TEST_EQUAL(rect.minX(), -90, ());
|
||||
}
|
||||
{
|
||||
ParsedMapApi api(Uri("mwm://map?ll=180,180&ll=0,0&ll=-180,-180"));
|
||||
m2::RectD rect = api.GetRect();
|
||||
TEST_EQUAL(rect.maxX(), 0, ());
|
||||
TEST_EQUAL(rect.maxY(), 0, ());
|
||||
TEST_EQUAL(rect.minX(), 0, ());
|
||||
TEST_EQUAL(rect.minX(), 0, ());
|
||||
}
|
||||
{
|
||||
ParsedMapApi api(Uri("mwm://"));
|
||||
m2::RectD rect = api.GetRect();
|
||||
TEST(!rect.IsValid(), ());
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
string generatePartOfUrl(url_scheme::ApiPoint const & point)
|
||||
{
|
||||
stringstream stream;
|
||||
stream << "&ll=" << strings::ToString(point.m_lat) << "," << strings::ToString(point.m_lon)
|
||||
<< "&n=" << point.m_title
|
||||
<< "&u=" << point.m_title;
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
string randomString(size_t size, size_t seed)
|
||||
{
|
||||
string result(size, '0');
|
||||
LCG32 random(seed);
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
result[i] = 'a' + random.Generate() % 26;
|
||||
return result;
|
||||
}
|
||||
|
||||
void generateRandomTest(size_t numberOfPoints, size_t stringLength)
|
||||
{
|
||||
vector <url_scheme::ApiPoint> vect(numberOfPoints);
|
||||
for (size_t i = 0; i < numberOfPoints; ++i)
|
||||
{
|
||||
url_scheme::ApiPoint point;
|
||||
LCG32 random(i);
|
||||
point.m_lat = random.Generate() % 90;
|
||||
point.m_lat *= random.Generate() % 2 == 0 ? 1 : -1;
|
||||
point.m_lon = random.Generate() % 180;
|
||||
point.m_lon *= random.Generate() % 2 == 0 ? 1 : -1;
|
||||
point.m_title = randomString(stringLength, i);
|
||||
point.m_url = randomString(stringLength, i);
|
||||
vect[i] = point;
|
||||
}
|
||||
string result = "mapswithme://map?v=1";
|
||||
for (size_t i = 0; i < vect.size(); ++i)
|
||||
result += generatePartOfUrl(vect[i]);
|
||||
Uri uri(result);
|
||||
ParsedMapApi api(uri);
|
||||
vector <url_scheme::ApiPoint> const & points = api.GetPoints();
|
||||
TEST_EQUAL(points.size(), vect.size(), ());
|
||||
for (size_t i = 0; i < vect.size();++i)
|
||||
{
|
||||
TEST_EQUAL(points[i].m_lat, vect[i].m_lat, ());
|
||||
TEST_EQUAL(points[i].m_lon, vect[i].m_lon, ());
|
||||
TEST_EQUAL(points[i].m_title, vect[i].m_title, ());
|
||||
TEST_EQUAL(points[i].m_url, vect[i].m_url, ());
|
||||
}
|
||||
TEST_EQUAL(api.GetApiversion(), 1, ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
UNIT_TEST(100FullEnteriesRandomTest)
|
||||
{
|
||||
generateRandomTest(100, 10);
|
||||
}
|
||||
|
||||
UNIT_TEST(StressTestRandomTest)
|
||||
{
|
||||
generateRandomTest(10000, 100);
|
||||
}
|
||||
|
|
|
@ -21,7 +21,10 @@ bool IsInvalidApiPoint(ApiPoint const & p) { return p.m_lat == INVALID_LAT_VALUE
|
|||
|
||||
} // unnames namespace
|
||||
|
||||
ParsedMapApi::ParsedMapApi(Uri const & uri)
|
||||
ParsedMapApi::ParsedMapApi():m_id(0)
|
||||
{}
|
||||
|
||||
ParsedMapApi::ParsedMapApi(Uri const & uri):m_id(0)
|
||||
{
|
||||
if (!Parse(uri))
|
||||
{
|
||||
|
@ -29,6 +32,12 @@ ParsedMapApi::ParsedMapApi(Uri const & uri)
|
|||
}
|
||||
}
|
||||
|
||||
void ParsedMapApi::SetUriAndParse(string const & url)
|
||||
{
|
||||
Clear();
|
||||
Parse(url_scheme::Uri(url));
|
||||
}
|
||||
|
||||
bool ParsedMapApi::IsValid() const
|
||||
{
|
||||
return !m_points.empty();
|
||||
|
@ -48,6 +57,15 @@ bool ParsedMapApi::Parse(Uri const & uri)
|
|||
|
||||
void ParsedMapApi::AddKeyValue(string const & key, string const & value)
|
||||
{
|
||||
if (key == "backurl")
|
||||
m_globalBackUrl = value;
|
||||
if (key == "v")
|
||||
{
|
||||
if (!strings::to_int(value, m_id))
|
||||
m_id = 0;
|
||||
}
|
||||
if (key == "appname")
|
||||
m_appTitle = value;
|
||||
if (key == "ll")
|
||||
{
|
||||
m_points.push_back(ApiPoint());
|
||||
|
@ -82,6 +100,7 @@ void ParsedMapApi::AddKeyValue(string const & key, string const & value)
|
|||
|
||||
m_points.back().m_lat = lat;
|
||||
m_points.back().m_lon = lon;
|
||||
m_showRect = m2::Add(m_showRect, m2::PointD(lat, lon));
|
||||
}
|
||||
else if (key == "n")
|
||||
{
|
||||
|
@ -98,3 +117,12 @@ void ParsedMapApi::AddKeyValue(string const & key, string const & value)
|
|||
LOG(LWARNING, ("Map API: Point url with no point. 'll' should come first!"));
|
||||
}
|
||||
}
|
||||
|
||||
void ParsedMapApi::Clear()
|
||||
{
|
||||
m_points.clear();
|
||||
m_globalBackUrl.clear();
|
||||
m_appTitle.clear();
|
||||
m_id = 0;
|
||||
m_showRect = m2::RectD();
|
||||
}
|
||||
|
|
|
@ -19,23 +19,26 @@ class ParsedMapApi
|
|||
{
|
||||
public:
|
||||
ParsedMapApi(Uri const & uri);
|
||||
ParsedMapApi();
|
||||
void SetUriAndParse(string const & url);
|
||||
bool IsValid() const;
|
||||
vector<ApiPoint> const & GetPoints() const { return m_points; }
|
||||
string const & GetGlobalBackUrl() const { return m_globalBackUrl; }
|
||||
string const & GetAppTitle() const { return m_appTitle; }
|
||||
int GetApiversion() const { return m_id; }
|
||||
m2::RectD GetRect() const { return m_showRect; }
|
||||
void Clear();
|
||||
|
||||
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
|
||||
string m_globalBackUrl;
|
||||
string m_appTitle;
|
||||
int m_id;
|
||||
//Lon Lat coordinates
|
||||
m2::RectD m_showRect;
|
||||
|
||||
// vector<char> m_iconData;
|
||||
*/
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue