diff options
Diffstat (limited to 'coding/traffic.hpp')
-rw-r--r-- | coding/traffic.hpp | 140 |
1 files changed, 123 insertions, 17 deletions
diff --git a/coding/traffic.hpp b/coding/traffic.hpp index 7b237082d5..f4e3c0b0db 100644 --- a/coding/traffic.hpp +++ b/coding/traffic.hpp @@ -25,11 +25,16 @@ public: { DataPoint() = default; - DataPoint(uint64_t timestamp, ms::LatLon latLon) : m_timestamp(timestamp), m_latLon(latLon) {} + DataPoint(uint64_t timestamp, ms::LatLon latLon, uint8_t traffic) + : m_timestamp(timestamp), m_latLon(latLon), m_traffic(traffic) + { + } // Uint64 should be enough for all our use cases. // It is expected that |m_timestamp| stores time since epoch in seconds. uint64_t m_timestamp = 0; ms::LatLon m_latLon = ms::LatLon::Zero(); + // TODO: comment the decision + uint8_t m_traffic = 0; bool operator==(DataPoint const & p) const { @@ -43,20 +48,53 @@ public: // Coordinates are truncated and stored as integers. All integers // are written as varints. template <typename Writer, typename Collection> - static size_t SerializeDataPoints(uint32_t version, Writer & writer, - Collection const & points) + static size_t SerializeDataPoints(uint32_t version, Writer & writer, Collection const & points) + { + switch (version) + { + case 0: return SerializeDataPointsV0(writer, points); + case 1: return SerializeDataPointsV1(writer, points); + + default: + ASSERT(false, ("Unexpected serializer version:", version)); + break; + } + return 0; + } + + + // Deserializes the points from |source| and appends them to |result|. + template <typename Source, typename Collection> + static void DeserializeDataPoints(uint32_t version, Source & src, Collection & result) { - ASSERT_LESS_OR_EQUAL(version, kLatestVersion, ()); + switch (version) + { + case 0: return DeserializeDataPointsV0(src, result); + case 1: return DeserializeDataPointsV1(src, result); + + default: + ASSERT(false, ("Unexpected serializer version:", version)); + break; + } + } +private: + static uint32_t DoubleToUint32(double x, double min, double max); + + static double Uint32ToDouble(uint32_t x, double min, double max); + + template <typename Writer, typename Collection> + static size_t SerializeDataPointsV0(Writer & writer, Collection const & points) + { auto const startPos = writer.Pos(); if (!points.empty()) { uint64_t const firstTimestamp = points[0].m_timestamp; uint32_t const firstLat = - DoubleToUint32(points[0].m_latLon.lat, ms::LatLon::kMinLat, ms::LatLon::kMaxLat); + DoubleToUint32(points[0].m_latLon.lat, ms::LatLon::kMinLat, ms::LatLon::kMaxLat); uint32_t const firstLon = - DoubleToUint32(points[0].m_latLon.lon, ms::LatLon::kMinLon, ms::LatLon::kMaxLon); + DoubleToUint32(points[0].m_latLon.lon, ms::LatLon::kMinLon, ms::LatLon::kMaxLon); WriteVarUint(writer, firstTimestamp); WriteVarUint(writer, firstLat); WriteVarUint(writer, firstLon); @@ -82,16 +120,55 @@ public: return static_cast<size_t>(writer.Pos() - startPos); } - // Deserializes the points from |source| and appends them to |result|. - template <typename Source, typename Collection> - static void DeserializeDataPoints(uint32_t version, Source & src, Collection & result) + template <typename Writer, typename Collection> + static size_t SerializeDataPointsV1(Writer & writer, Collection const & points) { - ASSERT_LESS_OR_EQUAL(version, kLatestVersion, ()); + auto const startPos = writer.Pos(); + + if (!points.empty()) + { + uint64_t const firstTimestamp = points[0].m_timestamp; + uint32_t const firstLat = + DoubleToUint32(points[0].m_latLon.lat, ms::LatLon::kMinLat, ms::LatLon::kMaxLat); + uint32_t const firstLon = + DoubleToUint32(points[0].m_latLon.lon, ms::LatLon::kMinLon, ms::LatLon::kMaxLon); + uint32_t const traffic = points[0].m_traffic; + WriteVarUint(writer, firstTimestamp); + WriteVarUint(writer, firstLat); + WriteVarUint(writer, firstLon); + WriteVarUint(writer, traffic); + } + for (size_t i = 1; i < points.size(); ++i) + { + ASSERT_LESS_OR_EQUAL(points[i - 1].m_timestamp, points[i].m_timestamp, ()); + + uint64_t const deltaTimestamp = points[i].m_timestamp - points[i - 1].m_timestamp; + uint32_t deltaLat = DoubleToUint32(points[i].m_latLon.lat - points[i - 1].m_latLon.lat, + kMinDeltaLat, kMaxDeltaLat); + uint32_t deltaLon = DoubleToUint32(points[i].m_latLon.lon - points[i - 1].m_latLon.lon, + kMinDeltaLon, kMaxDeltaLon); + + uint32_t const traffic = points[i - 1].m_traffic; + WriteVarUint(writer, deltaTimestamp); + WriteVarUint(writer, deltaLat); + WriteVarUint(writer, deltaLon); + WriteVarUint(writer, traffic); + } + + ASSERT_LESS_OR_EQUAL(writer.Pos() - startPos, numeric_limits<size_t>::max(), + ("Too much data.")); + return static_cast<size_t>(writer.Pos() - startPos); + } + + template <typename Source, typename Collection> + static void DeserializeDataPointsV0(Source & src, Collection & result) + { bool first = true; uint64_t lastTimestamp = 0; double lastLat = 0.0; double lastLon = 0.0; + uint8_t traffic = 0; while (src.Size() > 0) { @@ -99,10 +176,10 @@ public: { lastTimestamp = ReadVarUint<uint64_t>(src); lastLat = - Uint32ToDouble(ReadVarUint<uint32_t>(src), ms::LatLon::kMinLat, ms::LatLon::kMaxLat); + Uint32ToDouble(ReadVarUint<uint32_t>(src), ms::LatLon::kMinLat, ms::LatLon::kMaxLat); lastLon = - Uint32ToDouble(ReadVarUint<uint32_t>(src), ms::LatLon::kMinLon, ms::LatLon::kMaxLon); - result.push_back(DataPoint(lastTimestamp, ms::LatLon(lastLat, lastLon))); + Uint32ToDouble(ReadVarUint<uint32_t>(src), ms::LatLon::kMinLon, ms::LatLon::kMaxLon); + result.push_back(DataPoint(lastTimestamp, ms::LatLon(lastLat, lastLon), traffic)); first = false; } else @@ -110,14 +187,43 @@ public: lastTimestamp += ReadVarUint<uint64_t>(src); lastLat += Uint32ToDouble(ReadVarUint<uint32_t>(src), kMinDeltaLat, kMaxDeltaLat); lastLon += Uint32ToDouble(ReadVarUint<uint32_t>(src), kMinDeltaLon, kMaxDeltaLon); - result.push_back(DataPoint(lastTimestamp, ms::LatLon(lastLat, lastLon))); + result.push_back(DataPoint(lastTimestamp, ms::LatLon(lastLat, lastLon), traffic)); } } } -private: - static uint32_t DoubleToUint32(double x, double min, double max); + template <typename Source, typename Collection> + static void DeserializeDataPointsV1(Source & src, Collection & result) + { + bool first = true; + uint64_t lastTimestamp = 0; + double lastLat = 0.0; + double lastLon = 0.0; + uint8_t traffic = 0; + + while (src.Size() > 0) + { + if (first) + { + lastTimestamp = ReadVarUint<uint64_t>(src); + lastLat = + Uint32ToDouble(ReadVarUint<uint32_t>(src), ms::LatLon::kMinLat, ms::LatLon::kMaxLat); + lastLon = + Uint32ToDouble(ReadVarUint<uint32_t>(src), ms::LatLon::kMinLon, ms::LatLon::kMaxLon); + traffic = static_cast<uint8_t>(ReadVarUint<uint32_t>(src)); + result.push_back(DataPoint(lastTimestamp, ms::LatLon(lastLat, lastLon), traffic)); + first = false; + } + else + { + lastTimestamp += ReadVarUint<uint64_t>(src); + lastLat += Uint32ToDouble(ReadVarUint<uint32_t>(src), kMinDeltaLat, kMaxDeltaLat); + lastLon += Uint32ToDouble(ReadVarUint<uint32_t>(src), kMinDeltaLon, kMaxDeltaLon); + traffic = static_cast<uint8_t>(ReadVarUint<uint32_t>(src)); + result.push_back(DataPoint(lastTimestamp, ms::LatLon(lastLat, lastLon), traffic)); + } + } + } - static double Uint32ToDouble(uint32_t x, double min, double max); }; } // namespace coding |