From 0f3fea5460b99d841a8b7208d0a6df9781d8ec03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Fri, 10 Jun 2022 08:09:07 +0200 Subject: [PATCH] Improved map errors reporting --- src/map/atlas.cpp | 5 +- src/map/mapfile.cpp | 3 +- src/map/maplist.cpp | 13 ++- src/map/mapsforge/mapdata.cpp | 155 ++++++++++++++++++++++------------ src/map/mapsforge/mapdata.h | 5 ++ src/map/ozimap.cpp | 18 ++-- src/map/ozimap.h | 5 +- 7 files changed, 134 insertions(+), 70 deletions(-) diff --git a/src/map/atlas.cpp b/src/map/atlas.cpp index 500032d2..973259ac 100644 --- a/src/map/atlas.cpp +++ b/src/map/atlas.cpp @@ -96,8 +96,7 @@ Atlas::Atlas(const QString &fileName, bool TAR, QObject *parent) } else { QFile tbaFile(fileName); if (!tbaFile.open(QIODevice::ReadOnly)) { - _errorString = QString("Error opening tba file: %1") - .arg(tbaFile.errorString()); + _errorString = tbaFile.errorString(); return; } ba = tbaFile.readAll(); @@ -121,7 +120,7 @@ Atlas::Atlas(const QString &fileName, bool TAR, QObject *parent) if (tar.isOpen()) map = new OziMap(mapFile, tar, this); else - map = new OziMap(mapFile, this); + map = new OziMap(mapFile, TAR, this); if (map->isValid()) _maps.append(map); diff --git a/src/map/mapfile.cpp b/src/map/mapfile.cpp index 617e6507..129f9d15 100644 --- a/src/map/mapfile.cpp +++ b/src/map/mapfile.cpp @@ -148,8 +148,7 @@ bool MapFile::parseMapFile(QIODevice &device, QList &points, int el; if (!device.open(QIODevice::ReadOnly)) { - _errorString = QString("Error opening file: %1") - .arg(device.errorString()); + _errorString = device.errorString(); return false; } diff --git a/src/map/maplist.cpp b/src/map/maplist.cpp index 586f0ac3..9a3b1952 100644 --- a/src/map/maplist.cpp +++ b/src/map/maplist.cpp @@ -25,7 +25,7 @@ MapList::ParserMap MapList::parsers() MapList::ParserMap map; map.insert("tar", &Atlas::createTAR); - map.insert("tar", &OziMap::create); + map.insert("tar", &OziMap::createTAR); map.insert("tba", &Atlas::createTBA); map.insert("xml", &MapSource::create); map.insert("xml", &IMGMap::createGMAP); @@ -37,7 +37,7 @@ MapList::ParserMap MapList::parsers() map.insert("rmap", &RMap::create); map.insert("rtmap", &RMap::create); map.insert("map", &MapsforgeMap::create); - map.insert("map", &OziMap::create); + map.insert("map", &OziMap::createMAP); map.insert("kap", &BSBMap::create); map.insert("kmz", &KMZMap::create); map.insert("aqm", &AQMMap::create); @@ -71,15 +71,24 @@ Map *MapList::loadFile(const QString &path, const Projection &proj, bool *isDir) ++it; } } else { + QStringList errors; + for (it = _parsers.begin(); it != _parsers.end(); it++) { map = it.value()(path, proj, isDir); if (map->isValid()) break; else { + errors.append(it.key() + ": " + map->errorString()); delete map; map = 0; } } + + if (!map) { + qWarning("Error loading map file: %s:", qPrintable(path)); + for (int i = 0; i < errors.size(); i++) + qWarning(qPrintable(errors.at(i))); + } } return map ? map : new InvalidMap(path, "Unknown file format"); diff --git a/src/map/mapsforge/mapdata.cpp b/src/map/mapsforge/mapdata.cpp index 86382e98..594322f4 100644 --- a/src/map/mapsforge/mapdata.cpp +++ b/src/map/mapsforge/mapdata.cpp @@ -10,6 +10,7 @@ using namespace Mapsforge; #define MAGIC "mapsforge binary OSM" +#define MAGIC_SIZE (sizeof(MAGIC) - 1) #define MD(val) ((val) / 1e6) #define OFFSET_MASK 0x7FFFFFFFFFL @@ -282,43 +283,68 @@ bool MapData::readSubFiles() return true; } -bool MapData::readHeader() +bool MapData::readZoomInfo(SubFile &subfile) +{ + quint8 zooms; + + if (!subfile.readByte(zooms)) + return false; + + _subFiles.resize(zooms); + for (quint8 i = 0; i < zooms; i++) { + if (!(subfile.readByte(_subFiles[i].base) + && subfile.readByte(_subFiles[i].min) + && subfile.readByte(_subFiles[i].max) + && subfile.readUInt64(_subFiles[i].offset) + && subfile.readUInt64(_subFiles[i].size))) + return false; + } + + return true; +} + +bool MapData::readTagInfo(SubFile &subfile) { - char magic[sizeof(MAGIC) - 1]; - quint32 hdrSize, version; - quint64 fileSize, date; - qint32 minLat, minLon, maxLat, maxLon; quint16 tags; - quint8 flags, zooms; - QByteArray projection, tag; + QByteArray tag; + if (!subfile.readUInt16(tags)) + return false; + _pointTags.resize(tags); + for (quint16 i = 0; i < tags; i++) { + if (!subfile.readString(tag)) + return false; + _pointTags[i] = tag; + } - if (_file.read(magic, sizeof(magic)) < (int)sizeof(magic) - || memcmp(magic, MAGIC, sizeof(magic))) - return false; - if (_file.read((char*)&hdrSize, sizeof(hdrSize)) < (qint64)sizeof(hdrSize)) + if (!subfile.readUInt16(tags)) return false; + _pathTags.resize(tags); + for (quint16 i = 0; i < tags; i++) { + if (!subfile.readString(tag)) + return false; + _pathTags[i] = tag; + } - SubFile subfile(_file, sizeof(magic) + sizeof(hdrSize), - qFromBigEndian(hdrSize)); - if (!subfile.seek(0)) - return false; - if (!(subfile.readUInt32(version) && subfile.readUInt64(fileSize) + return true; +} + +bool MapData::readMapInfo(SubFile &subfile, QByteArray &projection, + bool &debugMap) +{ + quint64 fileSize, date; + quint32 version; + qint32 minLat, minLon, maxLat, maxLon; + quint8 flags; + + if (!(subfile.seek(MAGIC_SIZE + 4) + && subfile.readUInt32(version) && subfile.readUInt64(fileSize) && subfile.readUInt64(date) && subfile.readInt32(minLat) && subfile.readInt32(minLon) && subfile.readInt32(maxLat) && subfile.readInt32(maxLon) && subfile.readUInt16(_tileSize) && subfile.readString(projection) && subfile.readByte(flags))) return false; - if (projection != "Mercator") { - _errorString = projection + ": invalid/unsupported projection"; - return false; - } - if (flags & 0x80) { - _errorString = "DEBUG maps not supported"; - return false; - } - if (flags & 0x40) { qint32 startLon, startLat; if (!(subfile.readInt32(startLat) && subfile.readInt32(startLon))) @@ -345,39 +371,58 @@ bool MapData::readHeader() return false; } - if (!subfile.readUInt16(tags)) - return false; - _pointTags.resize(tags); - for (quint16 i = 0; i < tags; i++) { - if (!subfile.readString(tag)) - return false; - _pointTags[i] = tag; - } - - if (!subfile.readUInt16(tags)) - return false; - _pathTags.resize(tags); - for (quint16 i = 0; i < tags; i++) { - if (!subfile.readString(tag)) - return false; - _pathTags[i] = tag; - } - - if (!subfile.readByte(zooms)) - return false; - _subFiles.resize(zooms); - for (quint8 i = 0; i < zooms; i++) { - if (!(subfile.readByte(_subFiles[i].base) - && subfile.readByte(_subFiles[i].min) - && subfile.readByte(_subFiles[i].max) - && subfile.readUInt64(_subFiles[i].offset) - && subfile.readUInt64(_subFiles[i].size))) - return false; - } - _bounds = RectC(Coordinates(MD(minLon), MD(maxLat)), Coordinates(MD(maxLon), MD(minLat))); _bounds &= OSM::BOUNDS; + debugMap = flags & 0x80; + + return true; +} + +bool MapData::readHeader() +{ + char magic[MAGIC_SIZE]; + quint32 hdrSize; + QByteArray projection; + bool debugMap; + + + if (_file.read(magic, MAGIC_SIZE) < (qint64)MAGIC_SIZE + || memcmp(magic, MAGIC, MAGIC_SIZE)) { + _errorString = "Not a Mapsforge map"; + return false; + } + + if (_file.read((char*)&hdrSize, sizeof(hdrSize)) < (qint64)sizeof(hdrSize)) { + _errorString = "Unexpected EOF"; + return false; + } + + SubFile subfile(_file, 0, qFromBigEndian(hdrSize)); + + if (!readMapInfo(subfile, projection, debugMap)) { + _errorString = "Error reading map info"; + return false; + } + + if (!readTagInfo(subfile)) { + _errorString = "Error reading tags info"; + return false; + } + + if (!readZoomInfo(subfile)) { + _errorString = "Error reading zooms info"; + return false; + } + + if (projection != "Mercator") { + _errorString = projection + ": invalid/unsupported projection"; + return false; + } + if (debugMap) { + _errorString = "DEBUG maps not supported"; + return false; + } return true; } diff --git a/src/map/mapsforge/mapdata.h b/src/map/mapsforge/mapdata.h index a278ac54..789e922b 100644 --- a/src/map/mapsforge/mapdata.h +++ b/src/map/mapsforge/mapdata.h @@ -13,6 +13,8 @@ namespace Mapsforge { +class SubFile; + class MapData { public: @@ -129,6 +131,9 @@ private: typedef RTree TileTree; + bool readZoomInfo(SubFile &subfile); + bool readTagInfo(SubFile &subfile); + bool readMapInfo(SubFile &subfile, QByteArray &projection, bool &debugMap); bool readHeader(); bool readSubFiles(); void clearTiles(); diff --git a/src/map/ozimap.cpp b/src/map/ozimap.cpp index e8cd901e..efe399e3 100644 --- a/src/map/ozimap.cpp +++ b/src/map/ozimap.cpp @@ -17,15 +17,13 @@ #include "ozimap.h" -OziMap::OziMap(const QString &fileName, QObject *parent) +OziMap::OziMap(const QString &fileName, bool TAR, QObject *parent) : Map(fileName, parent), _img(0), _tar(0), _ozf(0), _zoom(0), _mapRatio(1.0), _valid(false) { QFileInfo fi(fileName); - QString suffix = fi.suffix().toLower(); - - if (suffix == "tar") { + if (TAR) { _tar = new Tar(fileName); if (!_tar->open()) { _errorString = "Error reading tar file"; @@ -380,10 +378,18 @@ void OziMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio) _img->setDevicePixelRatio(_mapRatio); } -Map *OziMap::create(const QString &path, const Projection &, bool *isDir) +Map *OziMap::createTAR(const QString &path, const Projection &, bool *isDir) { if (isDir) *isDir = true; - return new OziMap(path); + return new OziMap(path, true); +} + +Map *OziMap::createMAP(const QString &path, const Projection &, bool *isDir) +{ + if (isDir) + *isDir = true; + + return new OziMap(path, false); } diff --git a/src/map/ozimap.h b/src/map/ozimap.h index b027a534..68b0a002 100644 --- a/src/map/ozimap.h +++ b/src/map/ozimap.h @@ -14,7 +14,7 @@ class OziMap : public Map Q_OBJECT public: - OziMap(const QString &fileName, QObject *parent = 0); + OziMap(const QString &fileName, bool TAR, QObject *parent = 0); OziMap(const QString &fileName, Tar &tar, QObject *parent = 0); ~OziMap(); @@ -47,7 +47,8 @@ public: QPointF pp2xy(const PointD &p) const {return _transform.proj2img(p) / _mapRatio;} - static Map *create(const QString &path, const Projection &, bool *isDir); + static Map *createTAR(const QString &path, const Projection &, bool *isDir); + static Map *createMAP(const QString &path, const Projection &, bool *isDir); private: struct ImageInfo {