Fixed gps track binary file to open on any platform

This commit is contained in:
Constantin Shalnev 2015-12-17 20:12:13 +03:00
parent 9a53c3afee
commit 81bcbd34de
3 changed files with 77 additions and 20 deletions

View file

@ -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<int>(info.m_source), 255, ());
uint8_t const source = static_cast<uint8_t>(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<location::TLocationSource>(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<TItem> 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<char const *>(&items[0]), items.size() * sizeof(TItem));
if (0 != (m_stream.rdstate() & (ios::failbit | ios::badbit )))
MYTHROW(WriteException, ("File:", m_filePath));
vector<char> 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<bool(TItem const & item)> 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<TItem> items(kItemBlockSize);
vector<char> 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<char *>(&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<TItem> items(kItemBlockSize);
vector<char> 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<char *>(&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<char const *>(&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

View file

@ -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;
}

View file

@ -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;
}