forked from organicmaps/organicmaps
[routing] The simplest version of MaxspeedSerializer and tests on it.
This commit is contained in:
parent
f17783b6e4
commit
f9d11319ab
4 changed files with 258 additions and 12 deletions
|
@ -9,16 +9,16 @@ namespace routing
|
|||
using namespace measurement_utils;
|
||||
|
||||
// SpeedInUnits ------------------------------------------------------------------------------------
|
||||
bool SpeedInUnits::operator==(SpeedInUnits const & s) const
|
||||
bool SpeedInUnits::operator==(SpeedInUnits const & rhs) const
|
||||
{
|
||||
return m_speed == s.m_speed && m_units == s.m_units;
|
||||
return m_speed == rhs.m_speed && m_units == rhs.m_units;
|
||||
}
|
||||
|
||||
bool SpeedInUnits::operator<(SpeedInUnits const & s) const
|
||||
bool SpeedInUnits::operator<(SpeedInUnits const & rhs) const
|
||||
{
|
||||
if (m_speed != s.m_speed)
|
||||
return m_speed < s.m_speed;
|
||||
return m_units < s.m_units;
|
||||
if (m_speed != rhs.m_speed)
|
||||
return m_speed < rhs.m_speed;
|
||||
return m_units < rhs.m_units;
|
||||
}
|
||||
|
||||
bool SpeedInUnits::IsNumeric() const
|
||||
|
@ -26,6 +26,18 @@ bool SpeedInUnits::IsNumeric() const
|
|||
return m_speed != kNoneMaxSpeed && m_speed != kWalkMaxSpeed && m_speed != kInvalidSpeed;
|
||||
}
|
||||
|
||||
// FeatureMaxspeed ---------------------------------------------------------------------------------
|
||||
FeatureMaxspeed::FeatureMaxspeed(uint32_t fid, SpeedInUnits const & forward,
|
||||
SpeedInUnits const & backward /* = SpeedInUnits() */)
|
||||
: m_featureId(fid), m_forward(forward), m_backward(backward)
|
||||
{
|
||||
}
|
||||
|
||||
bool FeatureMaxspeed::operator==(FeatureMaxspeed const & rhs) const
|
||||
{
|
||||
return m_featureId == rhs.m_featureId && m_forward == rhs.m_forward && m_backward == rhs.m_backward;
|
||||
}
|
||||
|
||||
// MaxspeedConverter -------------------------------------------------------------------------------
|
||||
MaxspeedConverter::MaxspeedConverter()
|
||||
{
|
||||
|
@ -205,6 +217,14 @@ MaxspeedConverter const & GetMaxspeedConverter()
|
|||
return inst;
|
||||
}
|
||||
|
||||
std::string DebugPrint(Maxspeed maxspeed)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Maxspeed:" << static_cast<int>(maxspeed) << " Decoded:"
|
||||
<< DebugPrint(GetMaxspeedConverter().MacroToSpeed(maxspeed));
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::string DebugPrint(SpeedInUnits const & speed)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
|
@ -213,11 +233,12 @@ std::string DebugPrint(SpeedInUnits const & speed)
|
|||
return oss.str();
|
||||
}
|
||||
|
||||
std::string DebugPrint(Maxspeed maxspeed)
|
||||
std::string DebugPrint(FeatureMaxspeed const & featureMaxspeed)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Maxspeed:" << static_cast<int>(maxspeed) << " Decoded:"
|
||||
<< DebugPrint(GetMaxspeedConverter().MacroToSpeed(maxspeed));
|
||||
oss << "FeatureMaxspeed [ m_featureId:" << featureMaxspeed.GetFeatureId()
|
||||
<< " m_forward:" << DebugPrint(featureMaxspeed.GetForward())
|
||||
<< " m_backward:" << DebugPrint(featureMaxspeed.GetBackward()) << " ]";
|
||||
return oss.str();
|
||||
}
|
||||
} // namespace routing
|
||||
|
|
|
@ -165,10 +165,10 @@ struct SpeedInUnits
|
|||
SpeedInUnits() = default;
|
||||
SpeedInUnits(uint16_t speed, measurement_utils::Units units) noexcept : m_speed(speed), m_units(units) {}
|
||||
|
||||
bool operator==(SpeedInUnits const & s) const;
|
||||
bool operator==(SpeedInUnits const & rhs) const;
|
||||
/// \note While comparing speeds are not converted to the same units. So according to
|
||||
/// this compare operator 80 km per hour is more then 79 mile per hour.
|
||||
bool operator<(SpeedInUnits const & s) const;
|
||||
bool operator<(SpeedInUnits const & rhs) const;
|
||||
|
||||
bool IsNumeric() const;
|
||||
bool IsValid() const { return m_speed != kInvalidSpeed; }
|
||||
|
@ -177,6 +177,33 @@ struct SpeedInUnits
|
|||
measurement_utils::Units m_units = measurement_utils::Units::Metric;
|
||||
};
|
||||
|
||||
/// \breif Maxspeed tag value for feature id. |m_forward| and |m_backward| fields reflect the fact
|
||||
/// that a feature may have different maxspeed tag value for different directions.
|
||||
/// If |m_backward| is invalid it means that |m_forward| tag contains maxspeed for the both
|
||||
/// directions.
|
||||
class FeatureMaxspeed
|
||||
{
|
||||
public:
|
||||
FeatureMaxspeed(uint32_t fid, SpeedInUnits const & forward,
|
||||
SpeedInUnits const & backward = SpeedInUnits());
|
||||
|
||||
/// \note operator==() and operator<() do not correspond to each other.
|
||||
bool operator==(FeatureMaxspeed const & rhs) const;
|
||||
bool operator<(FeatureMaxspeed const & rhs) const { return m_featureId < rhs.m_featureId; }
|
||||
|
||||
bool IsValid() const { return m_forward.IsValid(); }
|
||||
bool IsBidirectional() const { return IsValid() && m_backward.IsValid(); }
|
||||
|
||||
uint32_t GetFeatureId() const { return m_featureId; }
|
||||
SpeedInUnits const & GetForward() const { return m_forward; }
|
||||
SpeedInUnits const & GetBackward() const { return m_backward; }
|
||||
|
||||
private:
|
||||
uint32_t m_featureId = 0;
|
||||
SpeedInUnits m_forward;
|
||||
SpeedInUnits m_backward;
|
||||
};
|
||||
|
||||
class MaxspeedConverter
|
||||
{
|
||||
friend MaxspeedConverter const & GetMaxspeedConverter();
|
||||
|
@ -198,6 +225,7 @@ private:
|
|||
|
||||
MaxspeedConverter const & GetMaxspeedConverter();
|
||||
|
||||
std::string DebugPrint(SpeedInUnits const & speed);
|
||||
std::string DebugPrint(Maxspeed maxspeed);
|
||||
std::string DebugPrint(SpeedInUnits const & speed);
|
||||
std::string DebugPrint(FeatureMaxspeed const & featureMaxspeed);
|
||||
} // namespace routing
|
||||
|
|
|
@ -1,5 +1,97 @@
|
|||
#pragma once
|
||||
|
||||
#include "routing/maxspeed_conversion.hpp"
|
||||
|
||||
#include "coding/reader.hpp"
|
||||
#include "coding/write_to_sink.hpp"
|
||||
|
||||
#include "base/assert.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace routing
|
||||
{
|
||||
class MaxspeedSerializer
|
||||
{
|
||||
public:
|
||||
MaxspeedSerializer() = delete;
|
||||
|
||||
template <class Sink>
|
||||
static void Serialize(std::vector<FeatureMaxspeed> const & speeds, Sink & sink)
|
||||
{
|
||||
CHECK(std::is_sorted(speeds.cbegin(), speeds.cend()), ());
|
||||
|
||||
// @TODO(bykoianko) Now serialization is implemented in the simplest way for research purposes.
|
||||
// It should be rewrite in a better way using MaxspeedConverter before before the PR is merged.
|
||||
Header header(static_cast<uint32_t>(speeds.size()));
|
||||
header.Serialize(sink);
|
||||
|
||||
for (auto const & s : speeds)
|
||||
{
|
||||
WriteToSink(sink, s.GetFeatureId());
|
||||
WriteToSink(sink, s.GetForward().m_speed);
|
||||
WriteToSink(sink, static_cast<uint8_t>(s.GetForward().m_units));
|
||||
WriteToSink(sink, s.GetBackward().m_speed);
|
||||
WriteToSink(sink, static_cast<uint8_t>(s.GetBackward().m_units));
|
||||
}
|
||||
}
|
||||
|
||||
template <class Source>
|
||||
static void Deserialize(Source & src, std::vector<FeatureMaxspeed> & speeds)
|
||||
{
|
||||
Header header;
|
||||
header.Deserialize(src);
|
||||
|
||||
speeds.clear();
|
||||
for (size_t i = 0; i < header.GetSize(); ++i)
|
||||
{
|
||||
auto const fid = ReadPrimitiveFromSource<uint32_t>(src);
|
||||
|
||||
SpeedInUnits forward;
|
||||
forward.m_speed = ReadPrimitiveFromSource<decltype(forward.m_speed)>(src);
|
||||
forward.m_units = static_cast<measurement_utils::Units>(ReadPrimitiveFromSource<uint8_t>(src));
|
||||
|
||||
SpeedInUnits backward;
|
||||
backward.m_speed = ReadPrimitiveFromSource<decltype(backward.m_speed)>(src);
|
||||
backward.m_units = static_cast<measurement_utils::Units>(ReadPrimitiveFromSource<uint8_t>(src));
|
||||
|
||||
speeds.emplace_back(fid, forward, backward);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static uint8_t constexpr kLastVersion = 0;
|
||||
|
||||
class Header final
|
||||
{
|
||||
public:
|
||||
Header() = default;
|
||||
explicit Header(uint32_t size) : m_size(size) {}
|
||||
|
||||
template <class Sink>
|
||||
void Serialize(Sink & sink) const
|
||||
{
|
||||
WriteToSink(sink, m_version);
|
||||
WriteToSink(sink, m_reserved);
|
||||
WriteToSink(sink, m_size);
|
||||
}
|
||||
|
||||
template <class Source>
|
||||
void Deserialize(Source & src)
|
||||
{
|
||||
m_version = ReadPrimitiveFromSource<decltype(m_version)>(src);
|
||||
m_reserved = ReadPrimitiveFromSource<decltype(m_reserved)>(src);
|
||||
m_size = ReadPrimitiveFromSource<decltype(m_size)>(src);
|
||||
}
|
||||
|
||||
uint32_t GetSize() const { return m_size; }
|
||||
|
||||
private:
|
||||
uint8_t m_version = kLastVersion;
|
||||
uint8_t m_reserved = 0;
|
||||
uint32_t m_size = 0;
|
||||
};
|
||||
};
|
||||
} // namespace routing
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "routing/maxspeed_conversion.hpp"
|
||||
#include "routing/maxspeed_serialization.hpp"
|
||||
|
||||
#include "coding/reader.hpp"
|
||||
#include "coding/writer.hpp"
|
||||
|
||||
#include "platform/measurement_utils.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -13,6 +18,23 @@ using namespace measurement_utils;
|
|||
using namespace routing;
|
||||
using namespace std;
|
||||
|
||||
void TestMaxspeedSerialization(std::vector<FeatureMaxspeed> const & speed)
|
||||
{
|
||||
vector<char> buffer;
|
||||
MemWriter<vector<char> > w(buffer);
|
||||
|
||||
MaxspeedSerializer::Serialize(speed, w);
|
||||
|
||||
size_t const sz = buffer.size();
|
||||
|
||||
MemReader r(buffer.data(), sz);
|
||||
ReaderSource<MemReader> src(r);
|
||||
std::vector<FeatureMaxspeed> result;
|
||||
MaxspeedSerializer::Deserialize(src, result);
|
||||
|
||||
TEST_EQUAL(speed, result, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(MaxspeedConverter)
|
||||
{
|
||||
auto const & conv = GetMaxspeedConverter();
|
||||
|
@ -51,4 +73,87 @@ UNIT_TEST(MaxspeedConverter)
|
|||
TEST(conv.IsValidMacro(1), ()); // static_cast<uint8_t>(None) == 1
|
||||
TEST(!conv.IsValidMacro(9), ()); // A value which is undefined in Maxspeed enum class.
|
||||
}
|
||||
|
||||
UNIT_TEST(MaxspeedSerializer_Smoke)
|
||||
{
|
||||
TestMaxspeedSerialization({});
|
||||
}
|
||||
|
||||
UNIT_TEST(MaxspeedSerializer_OneForwardMetric)
|
||||
{
|
||||
TestMaxspeedSerialization(
|
||||
{FeatureMaxspeed(0 /* feature id */, SpeedInUnits(20 /* speed */, Units::Metric))});
|
||||
}
|
||||
|
||||
UNIT_TEST(MaxspeedSerializer_OneNone)
|
||||
{
|
||||
TestMaxspeedSerialization(
|
||||
{FeatureMaxspeed(0 /* feature id */, SpeedInUnits(kNoneMaxSpeed, Units::Metric))});
|
||||
}
|
||||
|
||||
UNIT_TEST(MaxspeedSerializer_OneWalk)
|
||||
{
|
||||
TestMaxspeedSerialization(
|
||||
{FeatureMaxspeed(0 /* feature id */, SpeedInUnits(kWalkMaxSpeed, Units::Metric))});
|
||||
}
|
||||
|
||||
UNIT_TEST(MaxspeedSerializer_OneBidirectionalMetric_1)
|
||||
{
|
||||
TestMaxspeedSerialization(
|
||||
{FeatureMaxspeed(0 /* feature id */, SpeedInUnits(20 /* speed */, Units::Metric),
|
||||
SpeedInUnits(40 /* speed */, Units::Metric))});
|
||||
}
|
||||
|
||||
UNIT_TEST(MaxspeedSerializer_OneBidirectionalMetric_2)
|
||||
{
|
||||
TestMaxspeedSerialization(
|
||||
{FeatureMaxspeed(0 /* feature id */, SpeedInUnits(10 /* speed */, Units::Metric),
|
||||
SpeedInUnits(kWalkMaxSpeed, Units::Metric))});
|
||||
}
|
||||
|
||||
UNIT_TEST(MaxspeedSerializer_OneBidirectionalImperial)
|
||||
{
|
||||
TestMaxspeedSerialization(
|
||||
{FeatureMaxspeed(0 /* feature id */, SpeedInUnits(30 /* speed */, Units::Imperial),
|
||||
SpeedInUnits(50 /* speed */, Units::Imperial))});
|
||||
}
|
||||
|
||||
UNIT_TEST(MaxspeedSerializer_BigMetric)
|
||||
{
|
||||
std::vector<FeatureMaxspeed> const maxspeeds = {
|
||||
FeatureMaxspeed(0 /* feature id */, SpeedInUnits(20 /* speed */, Units::Metric)),
|
||||
FeatureMaxspeed(1 /* feature id */, SpeedInUnits(60 /* speed */, Units::Metric)),
|
||||
FeatureMaxspeed(4 /* feature id */, SpeedInUnits(90 /* speed */, Units::Metric)),
|
||||
FeatureMaxspeed(5 /* feature id */, SpeedInUnits(5 /* speed */, Units::Metric)),
|
||||
FeatureMaxspeed(7 /* feature id */, SpeedInUnits(70 /* speed */, Units::Metric),
|
||||
SpeedInUnits(90 /* speed */, Units::Metric)),
|
||||
FeatureMaxspeed(8 /* feature id */, SpeedInUnits(100 /* speed */, Units::Metric)),
|
||||
FeatureMaxspeed(9 /* feature id */, SpeedInUnits(60 /* speed */, Units::Metric)),
|
||||
FeatureMaxspeed(10 /* feature id */, SpeedInUnits(kNoneMaxSpeed, Units::Metric)),
|
||||
FeatureMaxspeed(11 /* feature id */, SpeedInUnits(40 /* speed */, Units::Metric),
|
||||
SpeedInUnits(50 /* speed */, Units::Metric)),
|
||||
FeatureMaxspeed(12 /* feature id */, SpeedInUnits(40 /* speed */, Units::Metric),
|
||||
SpeedInUnits(60 /* speed */, Units::Metric)),
|
||||
};
|
||||
TestMaxspeedSerialization(maxspeeds);
|
||||
}
|
||||
|
||||
UNIT_TEST(MaxspeedSerializer_BigImperial)
|
||||
{
|
||||
std::vector<FeatureMaxspeed> const maxspeeds = {
|
||||
FeatureMaxspeed(0 /* feature id */, SpeedInUnits(30 /* speed */, Units::Imperial)),
|
||||
FeatureMaxspeed(1 /* feature id */, SpeedInUnits(5 /* speed */, Units::Imperial)),
|
||||
FeatureMaxspeed(4 /* feature id */, SpeedInUnits(1 /* speed */, Units::Imperial)),
|
||||
FeatureMaxspeed(5 /* feature id */, SpeedInUnits(5 /* speed */, Units::Imperial)),
|
||||
FeatureMaxspeed(7 /* feature id */, SpeedInUnits(30 /* speed */, Units::Imperial),
|
||||
SpeedInUnits(50 /* speed */, Units::Imperial)),
|
||||
FeatureMaxspeed(8 /* feature id */, SpeedInUnits(70 /* speed */, Units::Imperial)),
|
||||
FeatureMaxspeed(9 /* feature id */, SpeedInUnits(50 /* speed */, Units::Imperial)),
|
||||
FeatureMaxspeed(10 /* feature id */, SpeedInUnits(40 /* speed */, Units::Imperial),
|
||||
SpeedInUnits(50 /* speed */, Units::Metric)),
|
||||
FeatureMaxspeed(11 /* feature id */, SpeedInUnits(30 /* speed */, Units::Imperial),
|
||||
SpeedInUnits(50 /* speed */, Units::Metric)),
|
||||
};
|
||||
TestMaxspeedSerialization(maxspeeds);
|
||||
}
|
||||
} // namespace
|
||||
|
|
Loading…
Add table
Reference in a new issue