Using visitors for serialization, deserialization, deserialization from json and debug print. And some review fixes.

This commit is contained in:
Vladimir Byko-Ianko 2017-09-29 11:50:49 +03:00 committed by Tatiana Yan
parent 735166790e
commit 289c4d10d8
17 changed files with 475 additions and 348 deletions

View file

@ -21,6 +21,7 @@ set(
srtm_parser_test.cpp
tag_admixer_test.cpp
tesselator_test.cpp
transit_test.cpp
triangles_tree_coding_test.cpp
types_helper.hpp
ugc_test.cpp

View file

@ -23,6 +23,8 @@ win32*|linux* {
QT *= network
}
INCLUDEPATH += $$ROOT_DIR/3party/jansson/src
HEADERS += \
source_data.hpp \
types_helper.hpp \
@ -47,5 +49,6 @@ SOURCES += \
srtm_parser_test.cpp \
tag_admixer_test.cpp \
tesselator_test.cpp \
transit_test.cpp \
triangles_tree_coding_test.cpp \
ugc_test.cpp \

View file

@ -0,0 +1,69 @@
#include "testing/testing.hpp"
#include "generator/transit_generator.hpp"
#include "routing_common/transit_types.hpp"
#include "base/assert.hpp"
#include <string>
#include <vector>
using namespace routing;
using namespace routing::transit;
using namespace std;
namespace
{
UNIT_TEST(DeserializerFromJson_Stops)
{
string const jsonBuffer = R"(
{
"stops": [{
"id": 343259523,
"line_ids": [
19207936,
19207937
],
"osm_id": 1234,
"point": {
"x": 27.4970954,
"y": 64.20146835878187
},
"title_anchors": []
},
{
"id": 266680843,
"transfer_id" : 5,
"line_ids": [
19213568,
19213569
],
"osm_id": 2345,
"point": {
"x": 27.5227942,
"y": 64.25206634443111
},
"title_anchors": []
}
]})";
my::Json root(jsonBuffer.c_str());
CHECK(root.get() != nullptr, ("Cannot parse the json."));
DeserializerFromJson deserializer(root.get());
vector<Stop> stops;
deserializer(stops, "stops");
vector<Stop> const expected = {
Stop(343259523 /* id */, 1234 /* featureId */, kTransferIdInvalid /* transfer id */,
{19207936, 19207937} /* lineIds */, {27.4970954, 64.20146835878187} /* point */),
Stop(266680843 /* id */, 2345 /* featureId */, 5 /* transfer id */,
{19213568, 19213569} /* lineIds */, {27.5227942, 64.25206634443111} /* point */)};
TEST_EQUAL(stops.size(), expected.size(), ());
for (size_t i = 0; i < stops.size(); ++i)
TEST(stops[i].IsEqualForTesting(expected[i]), (stops[i], "is not equal to", expected[i]));
}
} // namespace

View file

@ -2,8 +2,8 @@
#include "generator/osm_id.hpp"
#include "routing_common/transit_header.hpp"
#include "routing_common/transit_stop.hpp"
#include "routing_common/transit_serdes.hpp"
#include "routing_common/transit_types.hpp"
#include "coding/file_container.hpp"
#include "coding/file_name_utils.hpp"
@ -11,6 +11,7 @@
#include "platform/platform.hpp"
#include "base/checked_cast.hpp"
#include "base/logging.hpp"
#include "base/macros.hpp"
@ -24,52 +25,6 @@ namespace
using namespace routing;
using namespace routing::transit;
/// \brief Fills Stop instance based on a json field. |node| should point at jansson item at
/// array:
/// "stops": [
/// {
/// "id": 343259523,
/// "line_ids": [
/// 19207936,
/// 19207937
/// ],
/// "osm_id": 4611686018770647427,
/// "point": {
/// "x": 27.4970954,
/// "y": 64.20146835878187
/// },
/// "title_anchors": []
/// },
/// ...
/// ]
void ReadJsonArrayItem(json_struct_t * node, Stop & stop)
{
json_t * idItem = my::GetJSONObligatoryField(node, "id");
StopId id;
FromJSON(idItem, id);
json_t * osmIdItem = my::GetJSONObligatoryField(node, "osm_id");
json_int_t osmId;
FromJSON(osmIdItem, osmId);
// @TODO(bykoianko) |osmId| should be converted to feature id here.
FeatureId const featureId = 0;
vector<LineId> lineIds;
FromJSONObject(node, "line_ids", lineIds);
json_t * pointItem = my::GetJSONObligatoryField(node, "point");
CHECK(json_is_object(pointItem), ());
json_t * xItem = my::GetJSONObligatoryField(pointItem, "x");
m2::PointD point;
FromJSON(xItem, point.x);
json_t * yItem = my::GetJSONObligatoryField(pointItem, "y");
FromJSON(yItem, point.y);
stop = Stop(id, featureId, lineIds, point);
}
// @TODO(bykoianko) ReadJsonArrayItem(...) methods for the other transit graph structures should be added here.
/// \returns file name without extension by a file path if a file name which have zero, one of several extensions.
/// For example,
/// GetFileName("Russia_Nizhny Novgorod Oblast.transit.json") returns "Russia_Nizhny Novgorod Oblast"
@ -90,18 +45,17 @@ string GetFileName(string const & filePath)
return name;
}
template <class Item, class Sink>
void SerializeObject(my::Json const & root, string const & key, Sink & sink)
/// \brief Reads from |root| (json) and serialize an array to |serializer|.
template <class Item>
void SerializeObject(my::Json const & root, string const & key, Serializer<FileWriter> & serializer)
{
json_t const * const stops = json_object_get(root.get(), key.c_str());
CHECK(stops, ());
size_t const sz = json_array_size(stops);
for (size_t i = 0; i < sz; ++i)
{
Item item;
ReadJsonArrayItem(json_array_get(stops, i), item);
item.Serialize(sink);
}
vector<Item> items;
DeserializerFromJson deserializer(root.get());
deserializer(items, key.c_str());
for (auto const & s : items)
s.Visit(serializer);
}
} // namespace
@ -109,84 +63,84 @@ namespace routing
{
namespace transit
{
string GetCountryId(string & graphCountryId);
// DeserializerFromJson ---------------------------------------------------------------------------
void DeserializerFromJson::operator()(m2::PointD & p, char const * name)
{
json_t * pointItem = my::GetJSONOptionalField(m_node, name);
if (pointItem == nullptr)
return;
CHECK(json_is_object(pointItem), ());
FromJSONObject(pointItem, "x", p.x);
FromJSONObject(pointItem, "y", p.y);
}
void BuildTransit(string const & mwmPath, string const & transitDir)
{
// This method is under construction and should not be used for building production mwm sections.
LOG(LERROR, ("This method is under construction and should not be used for building production mwm "
"sections."));
NOTIMPLEMENTED();
string const countryId = GetFileName(mwmPath);
LOG(LINFO, ("countryId:", countryId));
Platform::FilesList filesList;
Platform::GetFilesByExt(transitDir, ".json", filesList);
string const graphFullPath = my::JoinFoldersToPath(transitDir, countryId + ".transit.json");
LOG(LINFO,
("mwm path:", mwmPath, ", directory with transit:", transitDir, "filesList:", filesList));
for (string const & graphFileName : filesList)
Platform::EFileType fileType;
Platform::EError const errCode = Platform::GetFileType(graphFullPath, fileType);
if (errCode != Platform::EError::ERR_OK || fileType != Platform::EFileType::FILE_TYPE_REGULAR)
{
string const graphFullPath = my::JoinFoldersToPath(transitDir, graphFileName);
Platform::EFileType fileType;
Platform::EError errCode = Platform::GetFileType(graphFullPath, fileType);
CHECK_EQUAL(errCode, Platform::EError::ERR_OK,
("File is not found:", graphFullPath, ", errCode:", errCode));
CHECK_EQUAL(fileType, Platform::EFileType::FILE_TYPE_REGULAR,
("File is not found:", graphFullPath, ", fileType:", fileType));
// @TODO(bykoianko) In the future transit edges which cross mwm border will be split in the generator. Then
// routing will support cross mwm transit routing. In current version every json with transit graph
// should have a special name: <country id>.transit.json.
string const graphCountryId = GetFileName(graphFileName);
LOG(LINFO, ("graphCountryId:", graphCountryId));
if (graphCountryId != countryId)
continue;
LOG(LINFO, ("Creating", TRANSIT_FILE_TAG, "section for:", countryId, "based on", graphFullPath));
string jsonBuffer;
try
{
GetPlatform().GetReader(graphFullPath)->ReadAsString(jsonBuffer);
}
catch (RootException const & ex)
{
LOG(LCRITICAL, ("Can't open", graphFullPath, ex.what()));
}
// @TODO(bykoianko) If it's necessary to parse an integer jansson parser keeps it to time long long value.
// It's not good because osm id and stop id are uint64_t. This should be solve before continue writing
// transit jansson parsing. According to C++ signed long long is not smaller than long and at least 64 bits.
// So as a variant before saving to json osm id and stop id should be converted to signed long long and
// then after reading at generator they should be converted back.
my::Json root(jsonBuffer.c_str());
CHECK(root.get() != nullptr, ("Cannot parse the json file:", graphFullPath));
FilesContainerW cont(mwmPath, FileWriter::OP_WRITE_EXISTING);
FileWriter w = cont.GetWriter(TRANSIT_FILE_TAG);
TransitHeader header;
auto const startOffset = w.Pos();
header.Serialize(w);
SerializeObject<Stop>(root, "stops", w);
header.m_gatesOffset = base::checked_cast<uint32_t>(w.Pos() - startOffset);
// @TODO(bykoianko) It's necessary to serialize other transit graph data here.
w.WritePaddingByEnd(8);
header.m_endOffset = base::checked_cast<uint32_t>(w.Pos() - startOffset);
// Rewriting header info.
auto const endOffset = w.Pos();
w.Seek(startOffset);
header.Serialize(w);
w.Seek(endOffset);
LOG(LINFO, (TRANSIT_FILE_TAG, "section is ready. The size is", header.m_endOffset));
LOG(LINFO, ("For mwm:", mwmPath, ".transit.json file not found"));
return;
}
// @TODO(bykoianko) In the future transit edges which cross mwm border will be split in the generator. Then
// routing will support cross mwm transit routing. In current version every json with transit graph
// should have a special name: <country id>.transit.json.
LOG(LINFO, ("Creating", TRANSIT_FILE_TAG, "section for:", countryId, "based on", graphFullPath));
string jsonBuffer;
try
{
GetPlatform().GetReader(graphFullPath)->ReadAsString(jsonBuffer);
}
catch (RootException const & ex)
{
LOG(LCRITICAL, ("Can't open", graphFullPath, ex.what()));
}
// @TODO(bykoianko) If it's necessary to parse an integer jansson parser keeps it to time long long value.
// It's not good because osm id and stop id are uint64_t. This should be solve before continue writing
// transit jansson parsing. According to C++ signed long long is not smaller than long and at least 64 bits.
// So as a variant before saving to json osm id and stop id should be converted to signed long long and
// then after reading at generator they should be converted back.
// @TODO(bykoianko) |osmId| should be converted to feature id while deserialing from json.
my::Json root(jsonBuffer.c_str());
CHECK(root.get() != nullptr, ("Cannot parse the json file:", graphFullPath));
FilesContainerW cont(mwmPath, FileWriter::OP_WRITE_EXISTING);
FileWriter w = cont.GetWriter(TRANSIT_FILE_TAG);
TransitHeader header;
auto const startOffset = w.Pos();
Serializer<FileWriter> serializer(w);
header.Visit(serializer);
SerializeObject<Stop>(root, "stops", serializer);
header.m_gatesOffset = base::checked_cast<uint32_t>(w.Pos() - startOffset);
// @TODO(bykoianko) It's necessary to serialize other transit graph data here.
w.WritePaddingByEnd(8);
header.m_endOffset = base::checked_cast<uint32_t>(w.Pos() - startOffset);
// Rewriting header info.
auto const endOffset = w.Pos();
w.Seek(startOffset);
header.Visit(serializer);
w.Seek(endOffset);
LOG(LINFO, (TRANSIT_FILE_TAG, "section is ready. The size is", header.m_endOffset));
}
} // namespace transit
} // namespace routing

View file

@ -1,11 +1,75 @@
#pragma once
#include "geometry/point2d.hpp"
#include "3party/jansson/myjansson.hpp"
#include <cstdint>
#include <string>
#include <vector>
namespace routing
{
namespace transit
{
class DeserializerFromJson
{
public:
DeserializerFromJson(json_struct_t * node) : m_node(node) {}
void operator()(uint8_t & d, char const * name = nullptr) { GetField(d, name); }
void operator()(uint16_t & d, char const * name = nullptr) { GetField(d, name); }
void operator()(uint32_t & d, char const * name = nullptr) { GetField(d, name); }
void operator()(uint64_t & d, char const * name = nullptr) { GetField(d, name); }
void operator()(double & d, char const * name = nullptr) { GetField(d, name); }
void operator()(std::string & s, char const * name = nullptr) { GetField(s, name); }
void operator()(m2::PointD & p, char const * name = nullptr);
template <typename R>
void operator()(R & r, char const * name = nullptr)
{
r.Visit(*this);
}
template <typename T>
void operator()(std::vector<T> & vs, char const * name = nullptr)
{
auto * arr = my::GetJSONOptionalField(m_node, name);
if (arr == nullptr)
return;
if (!json_is_array(arr))
MYTHROW(my::Json::Exception, ("The field", name, "must contain a json array."));
size_t const sz = json_array_size(arr);
vs.resize(sz);
for (size_t i = 0; i < sz; ++i)
{
DeserializerFromJson arrayItem(json_array_get(arr, i));
arrayItem(vs[i]);
}
}
private:
template <typename T>
void GetField(T & t, char const * name = nullptr)
{
if (name == nullptr)
{
// |name| is not set in case of array items
FromJSON(m_node, t);
}
else
{
json_struct_t * field = my::GetJSONOptionalField(m_node, name);
if (field == nullptr)
return; // No field |name| at |m_node|.
FromJSON(field, t);
}
}
json_struct_t * m_node;
};
/// \brief Builds transit section at mwm.
/// \param mwmPath relative or full path to built mwm. The name of mwm without extension is considered
/// as country id.

View file

@ -8,11 +8,10 @@ set(
car_model.hpp
pedestrian_model.cpp
pedestrian_model.hpp
transit_header.cpp
transit_header.hpp
transit_max_speed.hpp
transit_stop.cpp
transit_stop.hpp
transit_serdes.cpp
transit_serdes.hpp
transit_types.cpp
transit_types.hpp
vehicle_model.cpp
vehicle_model.hpp

View file

@ -16,8 +16,7 @@ SOURCES += \
bicycle_model.cpp \
car_model.cpp \
pedestrian_model.cpp \
transit_header.cpp \
transit_stop.cpp \
transit_types.cpp \
vehicle_model.cpp \
@ -25,8 +24,6 @@ HEADERS += \
bicycle_model.hpp \
car_model.hpp \
pedestrian_model.hpp \
transit_header.hpp \
transit_max_speed.hpp \
transit_stop.hpp \
transit_types.hpp \
vehicle_model.hpp \

View file

@ -3,8 +3,7 @@
#include "coding/reader.hpp"
#include "coding/writer.hpp"
#include "routing_common/transit_header.hpp"
#include "routing_common/transit_stop.hpp"
#include "routing_common/transit_serdes.hpp"
#include "routing_common/transit_types.hpp"
#include <cstdint>
@ -21,14 +20,17 @@ void TestSerialization(Obj const & obj)
{
vector<uint8_t> buffer;
MemWriter<vector<uint8_t>> writer(buffer);
obj.Serialize(writer);
Serializer<MemWriter<vector<uint8_t>>> serializer(writer);
obj.Visit(serializer);
MemReader reader(buffer.data(), buffer.size());
ReaderSource<MemReader> src(reader);
Obj deserializedHeader;
deserializedHeader.Deserialize(src);
Obj deserializedObj;
Deserializer<ReaderSource<MemReader>> deserializer(src);
deserializedObj.Visit(deserializer);
TEST(obj.IsEqualForTesting(deserializedHeader), (obj, "is not equal to", deserializedHeader));
TEST(obj.IsEqualForTesting(deserializedObj), ());
}
UNIT_TEST(ZeroTransitHeaderSerialization)
@ -53,7 +55,7 @@ UNIT_TEST(ZeroTransitStopSerialization)
UNIT_TEST(TransitStopSerialization)
{
Stop stop(1234 /* id */, 5678 /* feature id */, {7, 8, 9, 10} /* line id */, {55.0, 37.0});
Stop stop(1234 /* id */, 5678 /* feature id */, 7 /* transfer id */, {7, 8, 9, 10} /* line id */, {55.0, 37.0});
TestSerialization(stop);
}
} // namespace

View file

@ -1,64 +0,0 @@
#pragma once
#include "coding/reader.hpp"
#include "coding/write_to_sink.hpp"
#include <cstdint>
namespace routing
{
namespace transit
{
struct TransitHeader final
{
TransitHeader() { Reset(); }
TransitHeader(uint16_t version, uint32_t gatesOffset, uint32_t edgesOffset,
uint32_t transfersOffset, uint32_t linesOffset, uint32_t shapesOffset,
uint32_t networksOffset, uint32_t endOffset);
void Reset();
bool IsEqualForTesting(TransitHeader const & header) const;
template <class TSink>
void Serialize(TSink & sink) const
{
WriteToSink(sink, m_version);
WriteToSink(sink, m_reserve);
WriteToSink(sink, m_gatesOffset);
WriteToSink(sink, m_edgesOffset);
WriteToSink(sink, m_transfersOffset);
WriteToSink(sink, m_linesOffset);
WriteToSink(sink, m_shapesOffset);
WriteToSink(sink, m_networksOffset);
WriteToSink(sink, m_endOffset);
}
template <class TSource>
void Deserialize(TSource & src)
{
m_version = ReadPrimitiveFromSource<uint16_t>(src);
m_reserve = ReadPrimitiveFromSource<uint16_t>(src);
m_gatesOffset = ReadPrimitiveFromSource<uint32_t>(src);
m_edgesOffset = ReadPrimitiveFromSource<uint32_t>(src);
m_transfersOffset = ReadPrimitiveFromSource<uint32_t>(src);
m_linesOffset = ReadPrimitiveFromSource<uint32_t>(src);
m_shapesOffset = ReadPrimitiveFromSource<uint32_t>(src);
m_networksOffset = ReadPrimitiveFromSource<uint32_t>(src);
m_endOffset = ReadPrimitiveFromSource<uint32_t>(src);
}
uint16_t m_version;
uint16_t m_reserve;
uint32_t m_gatesOffset;
uint32_t m_edgesOffset;
uint32_t m_transfersOffset;
uint32_t m_linesOffset;
uint32_t m_shapesOffset;
uint32_t m_networksOffset;
uint32_t m_endOffset;
};
static_assert(sizeof(TransitHeader) == 32, "Wrong header size of transit section.");
string DebugPrint(TransitHeader const & turnItem);
} // namespace transit
} // namespace routing

View file

@ -0,0 +1,13 @@
#include "routing_common/transit_serdes.hpp"
#include "coding/point_to_integer.hpp"
namespace routing
{
namespace transit
{
// DeserializerToString ---------------------------------------------------------------------------
} // namespace transit
} // namespace routing

View file

@ -0,0 +1,136 @@
#pragma once
#include "geometry/point2d.hpp"
#include "coding/point_to_integer.hpp"
#include "coding/read_write_utils.hpp"
#include "coding/reader.hpp"
#include "coding/varint.hpp"
#include "coding/write_to_sink.hpp"
#include "base/assert.hpp"
#include "base/exception.hpp"
#include "base/macros.hpp"
#include <cmath>
#include <cstdint>
#include <limits>
#include <sstream>
#include <string>
#include <vector>
namespace routing
{
namespace transit
{
template <typename Sink>
class Serializer
{
public:
Serializer(Sink & sink) : m_sink(sink) {}
void operator()(uint8_t const d, char const * /* name */ = nullptr) { WriteToSink(m_sink, d); }
void operator()(uint16_t const d, char const * /* name */ = nullptr) { WriteToSink(m_sink, d); }
void operator()(uint32_t const d, char const * /* name */ = nullptr) { WriteToSink(m_sink, d); }
void operator()(uint64_t const d, char const * /* name */ = nullptr) { WriteToSink(m_sink, d); }
void operator()(double const d, char const * /* name */ = nullptr)
{
NOTIMPLEMENTED();
}
void operator()(std::string const & s, char const * /* name */ = nullptr)
{
rw::Write(m_sink, s);
}
void operator()(m2::PointD const & p, char const * /* name */ = nullptr)
{
m2::PointU const pointU = PointD2PointU(p, POINT_COORD_BITS);
(*this)(pointU.x);
(*this)(pointU.y);
}
template <typename R>
void operator()(R const & r, char const * /* name */ = nullptr)
{
r.Visit(*this);
}
template <typename T>
void operator()(std::vector<T> const & vs, char const * /* name */ = nullptr)
{
CHECK_LESS(vs.size(), std::numeric_limits<uint32_t>::max(), ());
WriteVarUint(m_sink, static_cast<uint32_t>(vs.size()));
for (auto const & v : vs)
(*this)(v);
}
private:
Sink & m_sink;
};
template <typename Source>
class Deserializer
{
public:
Deserializer(Source & source) : m_source(source) {}
void operator()(uint8_t & d, char const * /* name */ = nullptr)
{
ReadPrimitiveFromSource(m_source, d);
}
void operator()(uint16_t & d, char const * /* name */ = nullptr)
{
ReadPrimitiveFromSource(m_source, d);
}
void operator()(uint32_t & d, char const * /* name */ = nullptr)
{
ReadPrimitiveFromSource(m_source, d);
}
void operator()(uint64_t & d, char const * /* name */ = nullptr)
{
ReadPrimitiveFromSource(m_source, d);
}
void operator()(double & d, char const * /* name */ = nullptr)
{
NOTIMPLEMENTED();
}
void operator()(std::string & s, char const * /* name */ = nullptr)
{
rw::Read(m_source, s);
}
void operator()(m2::PointD & p, char const * /* name */ = nullptr)
{
m2::PointU pointU;
(*this)(pointU.x);
(*this)(pointU.y);
p = PointU2PointD(pointU, POINT_COORD_BITS);
}
template <typename R>
void operator()(R & r, char const * /* name */ = nullptr)
{
r.Visit(*this);
}
template <typename T>
void operator()(vector<T> & vs, char const * /* name */ = nullptr)
{
auto const size = ReadVarUint<uint32_t, Source>(m_source);
vs.resize(size);
for (auto & v : vs)
(*this)(v);
}
private:
Source & m_source;
};
} // namespace transit
} // namespace routing

View file

@ -1,33 +0,0 @@
#include "routing_common/transit_stop.hpp"
#include <sstream>
namespace routing
{
namespace transit
{
Stop::Stop(StopId id, FeatureId featureId, std::vector<LineId> const & lineIds,
m2::PointD const & point)
: m_id(id), m_featureId(featureId), m_lineIds(lineIds), m_point(point)
{
}
bool Stop::IsEqualForTesting(Stop const & stop) const
{
double constexpr kPointsEqualEpsilon = 1e-6;
return m_id == stop.m_id && m_featureId == stop.m_featureId && m_lineIds == stop.m_lineIds &&
my::AlmostEqualAbs(m_point, stop.m_point, kPointsEqualEpsilon);
}
std::string DebugPrint(Stop const & stop)
{
std::stringstream out;
out << "Stop [ m_id = " << stop.m_id
<< ", m_featureId = " << stop.m_featureId
<< ", m_lineIds = " << ::DebugPrint(stop.m_lineIds)
<< ", m_point = " << DebugPrint(stop.m_point)
<< " ]" << endl;
return out.str();
}
} // namespace transit
} // namespace routing

View file

@ -1,74 +0,0 @@
#pragma once
#include "routing_common/transit_types.hpp"
#include "coding/point_to_integer.hpp"
#include "coding/reader.hpp"
#include "coding/write_to_sink.hpp"
#include "geometry/point2d.hpp"
#include <cstdint>
#include <string>
#include <vector>
namespace routing
{
namespace transit
{
class Stop final
{
friend std::string DebugPrint(Stop const & stop);
public:
Stop() = default;
Stop(StopId id, FeatureId featureId, std::vector<LineId> const & lineIds, m2::PointD const & point);
bool IsEqualForTesting(Stop const & stop) const;
template <class TSink>
void Serialize(TSink & sink) const
{
WriteToSink(sink, m_id);
WriteToSink(sink, m_featureId);
WriteToSink(sink, static_cast<uint32_t>(m_lineIds.size()));
for (LineId lineId : m_lineIds)
WriteToSink(sink, lineId);
m2::PointU const pointU = PointD2PointU(m_point, POINT_COORD_BITS);
WriteToSink(sink, pointU.x);
WriteToSink(sink, pointU.y);
}
template <class TSource>
void Deserialize(TSource & src)
{
m_id = ReadPrimitiveFromSource<StopId>(src);
m_featureId = ReadPrimitiveFromSource<FeatureId>(src);
uint32_t const lineIdsSize = ReadPrimitiveFromSource<uint32_t>(src);
m_lineIds.resize(lineIdsSize);
for (uint32_t i = 0; i < lineIdsSize; ++i)
m_lineIds[i] = ReadPrimitiveFromSource<LineId>(src);
m2::PointU pointU;
pointU.x = ReadPrimitiveFromSource<uint32_t>(src);
pointU.y = ReadPrimitiveFromSource<uint32_t>(src);
m_point = PointU2PointD(pointU, POINT_COORD_BITS);
}
private:
StopId m_id = kStopIdInvalid;
FeatureId m_featureId = kFeatureIdInvalid;
std::vector<LineId> m_lineIds;
m2::PointD m_point;
// @TODO(bykoianko) It's necessary to add field m_titleAnchors here and implement serialization
// and deserialization.
};
std::string DebugPrint(Stop const & stop);
// @TODO(bykoianko) Method bool DeserializeStops(Stops const & stops) should be implemented here.
// This method will parse table "stops" at TRANSIT_FILE_TAG mwm section and fills its parameter.
// @TODO(bykoianko) Data structures and methods for other transit data should be implemented in
// separate units.
} // namespace transit
} // namespace routing

View file

@ -1,13 +1,12 @@
#include "routing_common/transit_header.hpp"
#include "routing_common/transit_types.hpp"
#include <sstream>
#include "routing_common/transit_serdes.hpp"
namespace routing
{
namespace transit
{
using namespace std;
// TransitHeader ----------------------------------------------------------------------------------
TransitHeader::TransitHeader(uint16_t version, uint32_t gatesOffset, uint32_t edgesOffset,
uint32_t transfersOffset, uint32_t linesOffset, uint32_t shapesOffset,
uint32_t networksOffset, uint32_t endOffset)
@ -45,20 +44,18 @@ bool TransitHeader::IsEqualForTesting(TransitHeader const & header) const
m_endOffset == header.m_endOffset;
}
string DebugPrint(TransitHeader const & header)
// Stop -------------------------------------------------------------------------------------------
Stop::Stop(StopId id, FeatureId featureId, TransferId transferId, std::vector<LineId> const & lineIds,
m2::PointD const & point)
: m_id(id), m_featureId(featureId), m_transferId(transferId), m_lineIds(lineIds), m_point(point)
{
stringstream out;
out << "TransitHeader [ m_version = " << header.m_version
<< ", m_reserve = " << header.m_reserve
<< ", m_gatesOffset = " << header.m_gatesOffset
<< ", m_edgesOffset = " << header.m_edgesOffset
<< ", m_transfersOffset = " << header.m_transfersOffset
<< ", m_linesOffset = " << header.m_linesOffset
<< ", m_shapesOffset = " << header.m_shapesOffset
<< ", m_networksOffset = " << header.m_networksOffset
<< ", m_endOffset = " << header.m_endOffset
<< " ]" << endl;
return out.str();
}
bool Stop::IsEqualForTesting(Stop const & stop) const
{
double constexpr kPointsEqualEpsilon = 1e-6;
return m_id == stop.m_id && m_featureId == stop.m_featureId && m_transferId == stop.m_transferId &&
m_lineIds == stop.m_lineIds && my::AlmostEqualAbs(m_point, stop.m_point, kPointsEqualEpsilon);
}
} // namespace transit
} // namespace routing
} // namespace routing

View file

@ -1,7 +1,12 @@
#pragma once
#include "geometry/point2d.hpp"
#include "base/visitor.hpp"
#include <cstdint>
#include <limits>
#include <string>
namespace routing
{
@ -9,15 +14,70 @@ namespace transit
{
using LineId = uint32_t;
using StopId = uint64_t;
using TransfersId = uint64_t;
using TransferId = uint64_t;
using NetworkId = uint32_t;
using FeatureId = uint32_t;
LineId constexpr kLineIdInvalid = std::numeric_limits<LineId>::max();
StopId constexpr kStopIdInvalid = std::numeric_limits<StopId>::max();
TransfersId constexpr kTransferIdInvalid = std::numeric_limits<TransfersId>::max();
TransferId constexpr kTransferIdInvalid = std::numeric_limits<TransferId>::max();
NetworkId constexpr kNetworkIdInvalid = std::numeric_limits<NetworkId>::max();
FeatureId constexpr kFeatureIdInvalid = std::numeric_limits<FeatureId>::max();
struct TransitHeader
{
TransitHeader() { Reset(); }
TransitHeader(uint16_t version, uint32_t gatesOffset, uint32_t edgesOffset,
uint32_t transfersOffset, uint32_t linesOffset, uint32_t shapesOffset,
uint32_t networksOffset, uint32_t endOffset);
void Reset();
bool IsEqualForTesting(TransitHeader const & header) const;
DECLARE_VISITOR(visitor(m_version, "m_version"), visitor(m_reserve, "m_reserve"),
visitor(m_gatesOffset, "m_gatesOffset"), visitor(m_edgesOffset, "m_edgesOffset"),
visitor(m_transfersOffset, "m_transfersOffset"),
visitor(m_linesOffset, "m_linesOffset"),
visitor(m_shapesOffset, "m_shapesOffset"),
visitor(m_networksOffset, "m_networksOffset"),
visitor(m_endOffset, "m_endOffset"))
DECLARE_DEBUG_PRINT(TransitHeader)
uint16_t m_version;
uint16_t m_reserve;
uint32_t m_gatesOffset;
uint32_t m_edgesOffset;
uint32_t m_transfersOffset;
uint32_t m_linesOffset;
uint32_t m_shapesOffset;
uint32_t m_networksOffset;
uint32_t m_endOffset;
};
static_assert(sizeof(TransitHeader) == 32, "Wrong header size of transit section.");
class Stop
{
public:
Stop() = default;
Stop(StopId id, FeatureId featureId, TransferId m_transferId, std::vector<LineId> const & lineIds,
m2::PointD const & point);
bool IsEqualForTesting(Stop const & stop) const;
DECLARE_VISITOR(visitor(m_id, "id"), visitor(m_featureId, "osm_id"),
visitor(m_transferId, "transfer_id"), visitor(m_lineIds, "line_ids"),
visitor(m_point, "point"))
DECLARE_DEBUG_PRINT(Stop)
private:
StopId m_id = kStopIdInvalid;
FeatureId m_featureId = kFeatureIdInvalid;
TransferId m_transferId = kTransferIdInvalid;
std::vector<LineId> m_lineIds;
m2::PointD m_point;
// @TODO(bykoianko) It's necessary to add field m_titleAnchors here and implement serialization
// and deserialization.
};
// @TODO(bykoianko) Data structures and methods for other transit data should be implemented in here.
} // namespace transit
} // namespace routing

View file

@ -29,6 +29,7 @@
34F558571DBF3CD800A4FC11 /* libstdc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 34F558561DBF3CD800A4FC11 /* libstdc++.tbd */; };
562147271F6AA36A002D2214 /* libbsdiff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 562147261F6AA36A002D2214 /* libbsdiff.a */; };
562147291F6AA37E002D2214 /* libmwm_diff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 562147281F6AA37E002D2214 /* libmwm_diff.a */; };
56E2EDAA1F7E3FBB0092E9C2 /* transit_test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 56E2EDA91F7E3FBB0092E9C2 /* transit_test.cpp */; };
670E7BBC1EF9832200A8E9ED /* libicu.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 670E7BBB1EF9832200A8E9ED /* libicu.a */; };
670E7BBE1EF9839C00A8E9ED /* librouting_common.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 670E7BBD1EF9839C00A8E9ED /* librouting_common.a */; };
670E7BC01EF983A400A8E9ED /* libtraffic.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 670E7BBF1EF983A400A8E9ED /* libtraffic.a */; };
@ -203,6 +204,7 @@
34F558561DBF3CD800A4FC11 /* libstdc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libstdc++.tbd"; path = "usr/lib/libstdc++.tbd"; sourceTree = SDKROOT; };
562147261F6AA36A002D2214 /* libbsdiff.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libbsdiff.a; path = ../bsdiff/build/Debug/libbsdiff.a; sourceTree = "<group>"; };
562147281F6AA37E002D2214 /* libmwm_diff.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libmwm_diff.a; path = "../../../../Library/Developer/Xcode/DerivedData/omim-gsfdicnjgjjbizhdmwedavcucpok/Build/Products/Debug/libmwm_diff.a"; sourceTree = "<group>"; };
56E2EDA91F7E3FBB0092E9C2 /* transit_test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = transit_test.cpp; sourceTree = "<group>"; };
670E7BBB1EF9832200A8E9ED /* libicu.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libicu.a; path = "../../../../Library/Developer/Xcode/DerivedData/omim-gzleizqujktwggdwiejzkgjrsgvp/Build/Products/Debug/libicu.a"; sourceTree = "<group>"; };
670E7BBD1EF9839C00A8E9ED /* librouting_common.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = librouting_common.a; path = "../../../../Library/Developer/Xcode/DerivedData/omim-gzleizqujktwggdwiejzkgjrsgvp/Build/Products/Debug/librouting_common.a"; sourceTree = "<group>"; };
670E7BBF1EF983A400A8E9ED /* libtraffic.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libtraffic.a; path = "../../../../Library/Developer/Xcode/DerivedData/omim-gzleizqujktwggdwiejzkgjrsgvp/Build/Products/Debug/libtraffic.a"; sourceTree = "<group>"; };
@ -451,6 +453,7 @@
6726C1D71A4C27A5005EEA39 /* generator_tests */ = {
isa = PBXGroup;
children = (
56E2EDA91F7E3FBB0092E9C2 /* transit_test.cpp */,
677E2A0B1CAAC7CB001DC42A /* osm2meta_test.cpp */,
677E2A0C1CAAC7CB001DC42A /* tag_admixer_test.cpp */,
677792501C1B2E9300EC9499 /* metadata_parser_test.cpp */,
@ -711,6 +714,7 @@
buildActionMask = 2147483647;
files = (
675341631A3F54F600A0A8C3 /* generator_tool.cpp in Sources */,
56E2EDAA1F7E3FBB0092E9C2 /* transit_test.cpp in Sources */,
677E2A0D1CAAC7CB001DC42A /* osm2meta_test.cpp in Sources */,
677E2A0E1CAAC7CB001DC42A /* tag_admixer_test.cpp in Sources */,
);

View file

@ -11,10 +11,9 @@
40FF45D01F388EF80046BD40 /* vehicle_model_for_country_test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 40FF45CF1F388EF80046BD40 /* vehicle_model_for_country_test.cpp */; };
5647A4511F72BEB600DE1125 /* libicu.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5647A4521F72BEB600DE1125 /* libicu.a */; };
5667C1DD1F751F2700C6B31B /* transit_test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5647A4531F72BF2B00DE1125 /* transit_test.cpp */; };
5667C1E11F751F4200C6B31B /* transit_header.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5667C1DF1F751F4200C6B31B /* transit_header.cpp */; };
5667C1E21F751F4200C6B31B /* transit_stop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5667C1E01F751F4200C6B31B /* transit_stop.cpp */; };
56E41D841F72A64B00E28E2D /* transit_stop.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 56E41D831F72A64B00E28E2D /* transit_stop.hpp */; };
56E41D871F72B42F00E28E2D /* transit_header.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 56E41D851F72B42F00E28E2D /* transit_header.hpp */; };
56E2EDA61F7E3F8A0092E9C2 /* transit_serdes.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 56E2EDA31F7E3F890092E9C2 /* transit_serdes.hpp */; };
56E2EDA71F7E3F8A0092E9C2 /* transit_serdes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 56E2EDA41F7E3F890092E9C2 /* transit_serdes.cpp */; };
56E2EDA81F7E3F8A0092E9C2 /* transit_types.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 56E2EDA51F7E3F8A0092E9C2 /* transit_types.cpp */; };
56E41D881F72B42F00E28E2D /* transit_types.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 56E41D861F72B42F00E28E2D /* transit_types.hpp */; };
671E78881E6A3C5D00B2859B /* bicycle_model.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 671E78801E6A3C5D00B2859B /* bicycle_model.cpp */; };
671E78891E6A3C5D00B2859B /* bicycle_model.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 671E78811E6A3C5D00B2859B /* bicycle_model.hpp */; };
@ -48,10 +47,9 @@
5647A4521F72BEB600DE1125 /* libicu.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libicu.a; sourceTree = BUILT_PRODUCTS_DIR; };
5647A4531F72BF2B00DE1125 /* transit_test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = transit_test.cpp; sourceTree = "<group>"; };
5667C1DE1F751F4200C6B31B /* routing_common.pro */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = routing_common.pro; sourceTree = "<group>"; };
5667C1DF1F751F4200C6B31B /* transit_header.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = transit_header.cpp; sourceTree = "<group>"; };
5667C1E01F751F4200C6B31B /* transit_stop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = transit_stop.cpp; sourceTree = "<group>"; };
56E41D831F72A64B00E28E2D /* transit_stop.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = transit_stop.hpp; sourceTree = "<group>"; };
56E41D851F72B42F00E28E2D /* transit_header.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = transit_header.hpp; sourceTree = "<group>"; };
56E2EDA31F7E3F890092E9C2 /* transit_serdes.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = transit_serdes.hpp; sourceTree = "<group>"; };
56E2EDA41F7E3F890092E9C2 /* transit_serdes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = transit_serdes.cpp; sourceTree = "<group>"; };
56E2EDA51F7E3F8A0092E9C2 /* transit_types.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = transit_types.cpp; sourceTree = "<group>"; };
56E41D861F72B42F00E28E2D /* transit_types.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = transit_types.hpp; sourceTree = "<group>"; };
671E78721E6A3BE200B2859B /* librouting_common.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = librouting_common.a; sourceTree = BUILT_PRODUCTS_DIR; };
671E78801E6A3C5D00B2859B /* bicycle_model.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bicycle_model.cpp; sourceTree = "<group>"; };
@ -140,12 +138,11 @@
671E78741E6A3BE200B2859B /* routing_common */ = {
isa = PBXGroup;
children = (
56E2EDA41F7E3F890092E9C2 /* transit_serdes.cpp */,
56E2EDA31F7E3F890092E9C2 /* transit_serdes.hpp */,
56E2EDA51F7E3F8A0092E9C2 /* transit_types.cpp */,
5667C1DE1F751F4200C6B31B /* routing_common.pro */,
5667C1DF1F751F4200C6B31B /* transit_header.cpp */,
5667C1E01F751F4200C6B31B /* transit_stop.cpp */,
56E41D851F72B42F00E28E2D /* transit_header.hpp */,
56E41D861F72B42F00E28E2D /* transit_types.hpp */,
56E41D831F72A64B00E28E2D /* transit_stop.hpp */,
671E78801E6A3C5D00B2859B /* bicycle_model.cpp */,
671E78811E6A3C5D00B2859B /* bicycle_model.hpp */,
671E78821E6A3C5D00B2859B /* car_model.cpp */,
@ -202,8 +199,8 @@
buildActionMask = 2147483647;
files = (
671E788D1E6A3C5D00B2859B /* pedestrian_model.hpp in Headers */,
56E41D871F72B42F00E28E2D /* transit_header.hpp in Headers */,
56E41D881F72B42F00E28E2D /* transit_types.hpp in Headers */,
56E2EDA61F7E3F8A0092E9C2 /* transit_serdes.hpp in Headers */,
671E78891E6A3C5D00B2859B /* bicycle_model.hpp in Headers */,
40576F7A1F7AA1B4000B593B /* transit_max_speed.hpp in Headers */,
56E41D841F72A64B00E28E2D /* transit_stop.hpp in Headers */,
@ -302,12 +299,12 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
5667C1E11F751F4200C6B31B /* transit_header.cpp in Sources */,
56E2EDA81F7E3F8A0092E9C2 /* transit_types.cpp in Sources */,
671E788A1E6A3C5D00B2859B /* car_model.cpp in Sources */,
56E2EDA71F7E3F8A0092E9C2 /* transit_serdes.cpp in Sources */,
671E78881E6A3C5D00B2859B /* bicycle_model.cpp in Sources */,
671E788E1E6A3C5D00B2859B /* vehicle_model.cpp in Sources */,
40FF45D01F388EF80046BD40 /* vehicle_model_for_country_test.cpp in Sources */,
5667C1E21F751F4200C6B31B /* transit_stop.cpp in Sources */,
671E788C1E6A3C5D00B2859B /* pedestrian_model.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -392,6 +389,7 @@
671E787F1E6A3BE200B2859B /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
671E78AA1E6A3DA800B2859B /* Build configuration list for PBXNativeTarget "routing_common_tests" */ = {
isa = XCConfigurationList;
@ -400,6 +398,7 @@
671E78AC1E6A3DA800B2859B /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};