From 81bcbd34dea654194fc56dff553d87753c0a6097 Mon Sep 17 00:00:00 2001 From: Constantin Shalnev Date: Thu, 17 Dec 2015 20:12:13 +0300 Subject: [PATCH] Fixed gps track binary file to open on any platform --- map/gps_track_storage.cpp | 95 +++++++++++++++++++----- map/map_tests/gps_track_storage_test.cpp | 1 + map/map_tests/gps_track_test.cpp | 1 + 3 files changed, 77 insertions(+), 20 deletions(-) diff --git a/map/gps_track_storage.cpp b/map/gps_track_storage.cpp index a1dcb68043..ea7ed0a1c3 100644 --- a/map/gps_track_storage.cpp +++ b/map/gps_track_storage.cpp @@ -9,7 +9,46 @@ namespace { + +// Number of items for batch processing size_t constexpr kItemBlockSize = 1000; + +// TODO +// GpsInfo can be compressed + +// Size of point in bytes +size_t const kPointSize = 8 * sizeof(double) + sizeof(uint8_t); + +void Pack(char * p, location::GpsInfo const & info) +{ + memcpy(p + 0 * sizeof(double), &info.m_timestamp, sizeof(double)); + memcpy(p + 1 * sizeof(double), &info.m_latitude, sizeof(double)); + memcpy(p + 2 * sizeof(double), &info.m_longitude, sizeof(double)); + memcpy(p + 3 * sizeof(double), &info.m_altitude, sizeof(double)); + memcpy(p + 4 * sizeof(double), &info.m_speed, sizeof(double)); + memcpy(p + 5 * sizeof(double), &info.m_bearing, sizeof(double)); + memcpy(p + 6 * sizeof(double), &info.m_horizontalAccuracy, sizeof(double)); + memcpy(p + 7 * sizeof(double), &info.m_verticalAccuracy, sizeof(double)); + ASSERT_LESS_OR_EQUAL(static_cast(info.m_source), 255, ()); + uint8_t const source = static_cast(info.m_source); + memcpy(p + 8 * sizeof(double), &source, sizeof(uint8_t)); +} + +void Unpack(char const * p, location::GpsInfo & info) +{ + memcpy(&info.m_timestamp, p + 0 * sizeof(double), sizeof(double)); + memcpy(&info.m_latitude, p + 1 * sizeof(double), sizeof(double)); + memcpy(&info.m_longitude, p + 2 * sizeof(double), sizeof(double)); + memcpy(&info.m_altitude, p + 3 * sizeof(double), sizeof(double)); + memcpy(&info.m_speed, p + 4 * sizeof(double), sizeof(double)); + memcpy(&info.m_bearing, p + 5 * sizeof(double), sizeof(double)); + memcpy(&info.m_horizontalAccuracy, p + 6 * sizeof(double), sizeof(double)); + memcpy(&info.m_verticalAccuracy, p + 7 * sizeof(double), sizeof(double)); + uint8_t source; + memcpy(&source, p + 8 * sizeof(double), sizeof(uint8_t)); + info.m_source = static_cast(source); +} + } // namespace GpsTrackStorage::GpsTrackStorage(string const & filePath, size_t maxItemCount) @@ -25,10 +64,10 @@ GpsTrackStorage::GpsTrackStorage(string const & filePath, size_t maxItemCount) { size_t const fileSize = m_stream.tellp(); - m_itemCount = fileSize / sizeof(TItem); + m_itemCount = fileSize / kPointSize; // Set write position after last item position - m_stream.seekp(m_itemCount * sizeof(TItem), ios::beg); + m_stream.seekp(m_itemCount * kPointSize, ios::beg); if (0 != (m_stream.rdstate() & (ios::failbit | ios::badbit))) MYTHROW(OpenException, ("File:", m_filePath)); } @@ -47,17 +86,31 @@ void GpsTrackStorage::Append(vector const & items) { ASSERT(m_stream.is_open(), ()); + if (items.empty()) + return; + bool const needTrunc = (m_itemCount + items.size()) > (m_maxItemCount * 2); // see NOTE in declaration if (needTrunc) TruncFile(); // Write position must be after last item position - ASSERT_EQUAL(m_stream.tellp(), m_itemCount * sizeof(TItem), ()); + ASSERT_EQUAL(m_stream.tellp(), m_itemCount * kPointSize, ()); - m_stream.write(reinterpret_cast(&items[0]), items.size() * sizeof(TItem)); - if (0 != (m_stream.rdstate() & (ios::failbit | ios::badbit ))) - MYTHROW(WriteException, ("File:", m_filePath)); + vector buff(min(kItemBlockSize, items.size()) * kPointSize); + for (size_t i = 0; i < items.size();) + { + size_t const n = min(items.size() - i, kItemBlockSize); + + for (size_t j = 0; j < n; ++j) + Pack(&buff[0] + j * kPointSize, items[i + j]); + + m_stream.write(&buff[0], n * kPointSize); + if (0 != (m_stream.rdstate() & (ios::failbit | ios::badbit ))) + MYTHROW(WriteException, ("File:", m_filePath)); + + i += n; + } m_stream.flush(); if (0 != (m_stream.rdstate() & (ios::failbit | ios::badbit ))) @@ -89,21 +142,23 @@ void GpsTrackStorage::ForEach(std::function const & fn size_t i = GetFirstItemIndex(); // Set read position to the first item - m_stream.seekg(i * sizeof(TItem), ios::beg); + m_stream.seekg(i * kPointSize, ios::beg); if (0 != (m_stream.rdstate() & (ios::failbit | ios::badbit))) MYTHROW(ReadException, ("File:", m_filePath)); - vector items(kItemBlockSize); + vector buff(min(kItemBlockSize, m_itemCount) * kPointSize); for (; i < m_itemCount;) { - size_t const n = min(m_itemCount - i, items.size()); - m_stream.read(reinterpret_cast(&items[0]), n * sizeof(TItem)); + size_t const n = min(m_itemCount - i, kItemBlockSize); + + m_stream.read(&buff[0], n * kPointSize); if (0 != (m_stream.rdstate() & (ios::failbit | ios::badbit | ios::eofbit))) MYTHROW(ReadException, ("File:", m_filePath)); for (size_t j = 0; j < n; ++j) - { - TItem const & item = items[j]; + { + TItem item; + Unpack(&buff[0] + j * kPointSize, item); if (!fn(item)) return; } @@ -123,31 +178,31 @@ void GpsTrackStorage::TruncFile() size_t i = GetFirstItemIndex(); // Set read position to the first item - m_stream.seekg(i * sizeof(TItem), ios::beg); + m_stream.seekg(i * kPointSize, ios::beg); if (0 != (m_stream.rdstate() & (ios::failbit | ios::badbit))) MYTHROW(ReadException, ("File:", m_filePath)); size_t newItemCount = 0; // Copy items - vector items(kItemBlockSize); + vector buff(min(kItemBlockSize, m_itemCount) * kPointSize); for (; i < m_itemCount;) { - size_t const n = min(m_itemCount - i, items.size()); + size_t const n = min(m_itemCount - i, kItemBlockSize); - m_stream.read(reinterpret_cast(&items[0]), n * sizeof(TItem)); + m_stream.read(&buff[0], n * kPointSize); if (0 != (m_stream.rdstate() & (ios::failbit | ios::badbit | ios::eofbit))) MYTHROW(ReadException, ("File:", m_filePath)); - tmp.write(reinterpret_cast(&items[0]), n * sizeof(TItem)); + tmp.write(&buff[0], n * kPointSize); if (0 != (tmp.rdstate() & (ios::failbit | ios::badbit))) MYTHROW(WriteException, ("File:", tmpFilePath)); i += n; newItemCount += n; } - items.clear(); - items.shrink_to_fit(); + buff.clear(); + buff.shrink_to_fit(); tmp.close(); m_stream.close(); @@ -167,7 +222,7 @@ void GpsTrackStorage::TruncFile() m_itemCount = newItemCount; // Write position must be after last item position (end of file) - ASSERT_EQUAL(m_stream.tellp(), m_itemCount * sizeof(TItem), ()); + ASSERT_EQUAL(m_stream.tellp(), m_itemCount * kPointSize, ()); } size_t GpsTrackStorage::GetFirstItemIndex() const diff --git a/map/map_tests/gps_track_storage_test.cpp b/map/map_tests/gps_track_storage_test.cpp index 9675d7dcd1..e24efd521a 100644 --- a/map/map_tests/gps_track_storage_test.cpp +++ b/map/map_tests/gps_track_storage_test.cpp @@ -24,6 +24,7 @@ location::GpsInfo Make(double timestamp, ms::LatLon const & ll, double speed) info.m_speed = speed; info.m_latitude = ll.lat; info.m_longitude = ll.lon; + info.m_source = location::EAndroidNative; return info; } diff --git a/map/map_tests/gps_track_test.cpp b/map/map_tests/gps_track_test.cpp index c507d08e51..6da0d64e29 100644 --- a/map/map_tests/gps_track_test.cpp +++ b/map/map_tests/gps_track_test.cpp @@ -26,6 +26,7 @@ inline location::GpsInfo Make(double timestamp, ms::LatLon const & ll, double sp info.m_latitude = ll.lat; info.m_longitude = ll.lon; info.m_horizontalAccuracy = 15; + info.m_source = location::EAndroidNative; return info; }