Skip to content

Commit

Permalink
[api] [map] Moved the ge0 parser from map/ to api/.
Browse files Browse the repository at this point in the history
  • Loading branch information
mpimenov authored and maksimandrianov committed Jan 31, 2020
1 parent 42c2c32 commit 96b20d9
Show file tree
Hide file tree
Showing 11 changed files with 85 additions and 96 deletions.
2 changes: 2 additions & 0 deletions api/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ set(
SRC
ge0_generator.cpp
ge0_generator.hpp
ge0_parser.cpp
ge0_parser.hpp
)

omim_add_library(${PROJECT_NAME} ${SRC})
Expand Down
1 change: 1 addition & 0 deletions api/api_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ project(api_tests)
set(
SRC
ge0_generator_tests.cpp
ge0_parser_tests.cpp
)

omim_add_test(${PROJECT_NAME} ${SRC})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
#include "testing/testing.hpp"

#include "map/ge0_parser.hpp"
#include "map/mwm_url.hpp"

#include "api/ge0_generator.hpp"
#include "api/ge0_parser.hpp"

#include "base/macros.hpp"

#include <algorithm>
#include <string>

using namespace std;

using url_scheme::Ge0Parser;
using url_scheme::ApiPoint;

namespace
{
double const kZoomEps = 1e-10;
} // namespace

namespace ge0
{
class Ge0ParserForTest : public Ge0Parser
{
public:
Expand All @@ -28,46 +31,44 @@ double GetLatEpsilon(size_t coordBytes)
{
// Should be / 2.0 but probably because of accumulates loss of precision, 1.77 works but 2.0
// doesn't.
double infelicity = 1 << ((ge0::kMaxPointBytes - coordBytes) * 3);
return infelicity / ((1 << ge0::kMaxCoordBits) - 1) * 180 / 1.77;
double infelicity = 1 << ((kMaxPointBytes - coordBytes) * 3);
return infelicity / ((1 << kMaxCoordBits) - 1) * 180 / 1.77;
}

double GetLonEpsilon(size_t coordBytes)
{
// Should be / 2.0 but probably because of accumulates loss of precision, 1.77 works but 2.0
// doesn't.
double infelicity = 1 << ((ge0::kMaxPointBytes - coordBytes) * 3);
return (infelicity / ((1 << ge0::kMaxCoordBits) - 1)) * 360 / 1.77;
double infelicity = 1 << ((kMaxPointBytes - coordBytes) * 3);
return (infelicity / ((1 << kMaxCoordBits) - 1)) * 360 / 1.77;
}

void TestSuccess(char const * s, double lat, double lon, double zoom, char const * name)
{
Ge0Parser parser;
ApiPoint apiPoint;
double parsedLat;
double parsedLon;
string parsedName;
double parsedZoomLevel;
bool const result = parser.Parse(s, apiPoint, parsedZoomLevel);
bool const result = parser.Parse(s, parsedLat, parsedLon, parsedName, parsedZoomLevel);

TEST(result, (s, zoom, lat, lon, name));

TEST_EQUAL(apiPoint.m_name, string(name), (s));
TEST_EQUAL(apiPoint.m_id, string(), (s));
TEST_EQUAL(parsedName, string(name), (s));
double const latEps = GetLatEpsilon(9);
double const lonEps = GetLonEpsilon(9);
TEST(fabs(apiPoint.m_lat - lat) <= latEps, (s, zoom, lat, lon, name));
TEST(fabs(apiPoint.m_lon - lon) <= lonEps, (s, zoom, lat, lon, name));

TEST(fabs(apiPoint.m_lat - lat) <= latEps, (s, zoom, lat, lon, name));
TEST(fabs(apiPoint.m_lon - lon) <= lonEps, (s, zoom, lat, lon, name));
TEST_ALMOST_EQUAL_ULPS(parsedZoomLevel, zoom, (s, zoom, lat, lon, name));
double const lonEps = GetLonEpsilon(9);
TEST_ALMOST_EQUAL_ABS(parsedLat, lat, latEps, (s, zoom, lat, lon, name));
TEST_ALMOST_EQUAL_ABS(parsedLon, lon, lonEps, (s, zoom, lat, lon, name));
TEST_ALMOST_EQUAL_ABS(parsedZoomLevel, zoom, kZoomEps, (s, zoom, lat, lon, name));
}

void TestFailure(char const * s)
{
Ge0Parser parser;
ApiPoint apiPoint;
double zoomLevel;
bool const result = parser.Parse(s, apiPoint, zoomLevel);
TEST_EQUAL(result, false, (s));
string name;
double lat, lon, zoomLevel;
bool const result = parser.Parse(s, lat, lon, name, zoomLevel);
TEST(!result, (s));
}

bool ConvergenceTest(double lat, double lon, double latEps, double lonEps)
Expand All @@ -84,7 +85,6 @@ bool ConvergenceTest(double lat, double lon, double latEps, double lonEps)
return true;
return false;
}
} // namespace

UNIT_TEST(Base64DecodingWorksForAValidChar)
{
Expand Down Expand Up @@ -215,23 +215,21 @@ UNIT_TEST(NameDecoding)
"d0%bd%d0%b8%d1%8e%3F";

Ge0Parser parser;
ApiPoint apiPoint;
double parsedLat;
double parsedLon;
string parsedName;
double parsedZoomLevel;
bool const result = parser.Parse(url.c_str(), apiPoint, parsedZoomLevel);
bool const result = parser.Parse(url.c_str(), parsedLat, parsedLon, parsedName, parsedZoomLevel);

TEST(result, (url, zoom, lat, lon, name));

// Name would be valid but is too long.
TEST_NOT_EQUAL(apiPoint.m_name, string(name), (url));
TEST_EQUAL(apiPoint.m_id, string(), (url));
TEST_NOT_EQUAL(parsedName, string(name), (url));
double const latEps = GetLatEpsilon(9);
double const lonEps = GetLonEpsilon(9);
TEST(fabs(apiPoint.m_lat - lat) <= latEps, (url, zoom, lat, lon, name));
TEST(fabs(apiPoint.m_lon - lon) <= lonEps, (url, zoom, lat, lon, name));

TEST(fabs(apiPoint.m_lat - lat) <= latEps, (url, zoom, lat, lon, name));
TEST(fabs(apiPoint.m_lon - lon) <= lonEps, (url, zoom, lat, lon, name));
TEST_ALMOST_EQUAL_ULPS(parsedZoomLevel, zoom, (url, zoom, lat, lon, name));
TEST_ALMOST_EQUAL_ABS(parsedLat, lat, latEps, (url, zoom, lat, lon, name));
TEST_ALMOST_EQUAL_ABS(parsedLon, lon, lonEps, (url, zoom, lat, lon, name));
TEST_ALMOST_EQUAL_ABS(parsedZoomLevel, zoom, kZoomEps, (url, zoom, lat, lon, name));
}
}

Expand Down Expand Up @@ -293,3 +291,4 @@ UNIT_TEST(ClippedName)
TestSuccess("ge0://AwAAAAAAAA/" , 0, 0, 4, "");
TestSuccess("ge0://AwAAAAAAAA" , 0, 0, 4, "");
}
} // namespace ge0
29 changes: 13 additions & 16 deletions map/ge0_parser.cpp → api/ge0_parser.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
#include "map/ge0_parser.hpp"

#include "map/mwm_url.hpp"
#include "api/ge0_parser.hpp"

#include "geometry/mercator.hpp"

Expand All @@ -15,20 +13,20 @@

using namespace std;

namespace url_scheme
namespace ge0
{
Ge0Parser::Ge0Parser()
{
for (size_t i = 0; i < 256; ++i)
m_base64ReverseCharTable[i] = 255;
for (uint8_t i = 0; i < 64; ++i)
{
char c = ge0::Base64Char(i);
char c = Base64Char(i);
m_base64ReverseCharTable[static_cast<uint8_t>(c)] = i;
}
}

bool Ge0Parser::Parse(string const & url, url_scheme::ApiPoint & outPoint, double & outZoomLevel)
bool Ge0Parser::Parse(string const & url, double & outLat, double & outLon, std::string & outName, double & outZoomLevel)
{
// URL format:
//
Expand All @@ -52,14 +50,14 @@ bool Ge0Parser::Parse(string const & url, url_scheme::ApiPoint & outPoint, doubl
return false;
outZoomLevel = DecodeZoom(zoomI);

DecodeLatLon(url.substr(LATLON_POSITION, LATLON_LENGTH), outPoint.m_lat, outPoint.m_lon);
DecodeLatLon(url.substr(LATLON_POSITION, LATLON_LENGTH), outLat, outLon);

ASSERT(mercator::ValidLon(outPoint.m_lon), (outPoint.m_lon));
ASSERT(mercator::ValidLat(outPoint.m_lat), (outPoint.m_lat));
ASSERT(mercator::ValidLon(outLon), (outLon));
ASSERT(mercator::ValidLat(outLat), (outLat));

if (url.size() >= NAME_POSITON_IN_URL)
{
outPoint.m_name = DecodeName(
outName = DecodeName(
url.substr(NAME_POSITON_IN_URL, min(url.size() - NAME_POSITON_IN_URL, MAX_NAME_LENGTH)));
}
return true;
Expand All @@ -80,13 +78,13 @@ void Ge0Parser::DecodeLatLon(string const & url, double & lat, double & lon)
{
int latInt = 0, lonInt = 0;
DecodeLatLonToInt(url, latInt, lonInt, url.size());
lat = DecodeLatFromInt(latInt, (1 << ge0::kMaxCoordBits) - 1);
lon = DecodeLonFromInt(lonInt, (1 << ge0::kMaxCoordBits) - 1);
lat = DecodeLatFromInt(latInt, (1 << kMaxCoordBits) - 1);
lon = DecodeLonFromInt(lonInt, (1 << kMaxCoordBits) - 1);
}

void Ge0Parser::DecodeLatLonToInt(string const & url, int & lat, int & lon, size_t const bytes)
{
int shift = ge0::kMaxCoordBits - 3;
int shift = kMaxCoordBits - 3;
for (size_t i = 0; i < bytes; ++i, shift -= 3)
{
const uint8_t a = DecodeBase64Char(url[i]);
Expand All @@ -95,7 +93,7 @@ void Ge0Parser::DecodeLatLonToInt(string const & url, int & lat, int & lon, size
lat |= lat1 << shift;
lon |= lon1 << shift;
}
const double middleOfSquare = 1 << (3 * (ge0::kMaxPointBytes - bytes) - 1);
const double middleOfSquare = 1 << (3 * (kMaxPointBytes - bytes) - 1);
lat += middleOfSquare;
lon += middleOfSquare;
}
Expand Down Expand Up @@ -151,5 +149,4 @@ bool Ge0Parser::IsHexChar(char const a)
{
return ((a >= '0' && a <= '9') || (a >= 'A' && a <= 'F') || (a >= 'a' && a <= 'f'));
}

} // namespace url_scheme
} // namespace ge0
11 changes: 4 additions & 7 deletions map/ge0_parser.hpp → api/ge0_parser.hpp
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
#pragma once

#include "base/base.hpp"

#include <cstddef>
#include <cstdint>
#include <string>

namespace url_scheme
namespace ge0
{
struct ApiPoint;

class Ge0Parser
{
public:
Ge0Parser();

bool Parse(std::string const & url, url_scheme::ApiPoint & outPoint, double & outZoomLevel);
bool Parse(std::string const & url, double & outLat, double & outLon, std::string & outName, double & outZoomLevel);

protected:
uint8_t DecodeBase64Char(char const c);
Expand All @@ -31,4 +28,4 @@ class Ge0Parser
private:
uint8_t m_base64ReverseCharTable[256];
};
} // namespace url_api
} // namespace ge0
2 changes: 0 additions & 2 deletions map/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,6 @@ set(
framework_light.cpp
framework_light.hpp
framework_light_delegate.hpp
ge0_parser.cpp
ge0_parser.hpp
geourl_process.cpp
geourl_process.hpp
gps_track_collection.cpp
Expand Down
40 changes: 18 additions & 22 deletions map/framework.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#include "map/chart_generator.hpp"
#include "map/displayed_categories_modifiers.hpp"
#include "map/everywhere_search_params.hpp"
#include "map/ge0_parser.hpp"
#include "map/geourl_process.hpp"
#include "map/gps_tracker.hpp"
#include "map/notifications/notification_manager_delegate.hpp"
Expand All @@ -16,6 +15,8 @@
#include "map/utils.hpp"
#include "map/viewport_search_params.hpp"

#include "api/ge0_parser.hpp"

#include "generator/borders.hpp"

#include "routing/city_roads.hpp"
Expand Down Expand Up @@ -436,7 +437,7 @@ Framework::Framework(FrameworkParams const & params)

m_bmManager->InitRegionAddressGetter(m_featuresFetcher.GetDataSource(), *m_infoGetter);

m_ParsedMapApi.SetBookmarkManager(m_bmManager.get());
m_parsedMapApi.SetBookmarkManager(m_bmManager.get());
m_routingManager.SetBookmarkManager(m_bmManager.get());
m_searchMarks.SetBookmarkManager(m_bmManager.get());

Expand Down Expand Up @@ -2135,34 +2136,29 @@ bool Framework::ShowMapForURL(string const & url)
enum ResultT { FAILED, NEED_CLICK, NO_NEED_CLICK };
ResultT result = FAILED;

using namespace url_scheme;
using namespace strings;

if (StartsWith(url, "ge0"))
if (strings::StartsWith(url, "ge0"))
{
Ge0Parser parser;
double zoom;
ApiPoint pt;
ge0::Ge0Parser parser;
double lat, lon, zoom;

if (parser.Parse(url, pt, zoom))
if (parser.Parse(url, lat, lon, name, zoom))
{
point = mercator::FromLatLon(pt.m_lat, pt.m_lon);
point = mercator::FromLatLon(lat, lon);
rect = df::GetRectForDrawScale(zoom, point);
name = pt.m_name;
result = NEED_CLICK;
}
}
else if (m_ParsedMapApi.IsValid())
else if (m_parsedMapApi.IsValid())
{
if (!m_ParsedMapApi.GetViewportRect(rect))
if (!m_parsedMapApi.GetViewportRect(rect))
rect = df::GetWorldRect();

apiMark = m_ParsedMapApi.GetSinglePoint();
apiMark = m_parsedMapApi.GetSinglePoint();
result = apiMark ? NEED_CLICK : NO_NEED_CLICK;
}
else // Actually, we can parse any geo url scheme with correct coordinates.
{
Info info;
url_scheme::Info info;
ParseGeoURL(url, info);
if (info.IsValid())
{
Expand Down Expand Up @@ -2216,23 +2212,23 @@ url_scheme::ParsedMapApi::ParsingResult Framework::ParseAndSetApiURL(string cons
editSession.SetIsVisible(UserMark::Type::API, true);
}

return m_ParsedMapApi.SetUriAndParse(url);
return m_parsedMapApi.SetUriAndParse(url);
}

Framework::ParsedRoutingData Framework::GetParsedRoutingData() const
{
return Framework::ParsedRoutingData(m_ParsedMapApi.GetRoutePoints(),
routing::FromString(m_ParsedMapApi.GetRoutingType()));
return Framework::ParsedRoutingData(m_parsedMapApi.GetRoutePoints(),
routing::FromString(m_parsedMapApi.GetRoutingType()));
}

url_scheme::SearchRequest Framework::GetParsedSearchRequest() const
{
return m_ParsedMapApi.GetSearchRequest();
return m_parsedMapApi.GetSearchRequest();
}

url_scheme::Subscription Framework::GetParsedSubscription() const
{
return m_ParsedMapApi.GetSubscription();
return m_parsedMapApi.GetSubscription();
}

FeatureID Framework::GetFeatureAtPoint(m2::PointD const & mercator,
Expand Down Expand Up @@ -2681,7 +2677,7 @@ string Framework::CodeGe0url(double lat, double lon, double zoomLevel, string co

string Framework::GenerateApiBackUrl(ApiMarkPoint const & point) const
{
string res = m_ParsedMapApi.GetGlobalBackUrl();
string res = m_parsedMapApi.GetGlobalBackUrl();
if (!res.empty())
{
ms::LatLon const ll = point.GetLatLon();
Expand Down
4 changes: 2 additions & 2 deletions map/framework.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -726,10 +726,10 @@ class Framework : public PositionProvider,

/// @name Api
std::string GenerateApiBackUrl(ApiMarkPoint const & point) const;
url_scheme::ParsedMapApi const & GetApiDataHolder() const { return m_ParsedMapApi; }
url_scheme::ParsedMapApi const & GetApiDataHolder() const { return m_parsedMapApi; }

private:
url_scheme::ParsedMapApi m_ParsedMapApi;
url_scheme::ParsedMapApi m_parsedMapApi;

public:
/// @name Data versions
Expand Down
Loading

0 comments on commit 96b20d9

Please sign in to comment.