void OsmAnd::ObfMapSectionReader_P::readMapObjectsBlock( const std::unique_ptr<ObfReader_P>& reader, const std::shared_ptr<const ObfMapSectionInfo>& section, const std::shared_ptr<ObfMapSectionLevelTreeNode>& tree, QList< std::shared_ptr<const OsmAnd::Model::MapObject> >* resultOut, const AreaI* bbox31, const FilterMapObjectsByIdSignature filterById, std::function<bool (const std::shared_ptr<const OsmAnd::Model::MapObject>&)> visitor, const IQueryController* const controller, ObfMapSectionReader_Metrics::Metric_loadMapObjects* const metric) { auto cis = reader->_codedInputStream.get(); QList< std::shared_ptr<Model::MapObject> > intermediateResult; QStringList mapObjectsNamesTable; gpb::uint64 baseId = 0; for(;;) { if(controller && controller->isAborted()) return; auto tag = cis->ReadTag(); switch(gpb::internal::WireFormatLite::GetTagFieldNumber(tag)) { case 0: for(const auto& mapObject : constOf(intermediateResult)) { // Fill mapObject names from stringtable for(auto& nameValue : mapObject->_names) { const auto stringId = ObfReaderUtilities::decodeIntegerFromString(nameValue); if(stringId >= mapObjectsNamesTable.size()) { LogPrintf(LogSeverityLevel::Error, "Data mismatch: string #%d (map object #%" PRIu64 " (%" PRIi64 ") not found in string table (size %d) in section '%s'", stringId, mapObject->id >> 1, static_cast<int64_t>(mapObject->id) / 2, mapObjectsNamesTable.size(), qPrintable(section->name)); nameValue = QString::fromLatin1("#%1 NOT FOUND").arg(stringId); continue; } nameValue = mapObjectsNamesTable[stringId]; } if(!visitor || visitor(mapObject)) { if(resultOut) resultOut->push_back(qMove(mapObject)); } } return; case OBF::MapDataBlock::kBaseIdFieldNumber: cis->ReadVarint64(&baseId); break; case OBF::MapDataBlock::kDataObjectsFieldNumber: { gpb::uint32 length; cis->ReadVarint32(&length); // Update metric std::chrono::high_resolution_clock::time_point readMapObject_begin; if(metric) readMapObject_begin = std::chrono::high_resolution_clock::now(); // Read map object content std::shared_ptr<OsmAnd::Model::MapObject> mapObject; { auto oldLimit = cis->PushLimit(length); readMapObject(reader, section, baseId, tree, mapObject, bbox31); assert(cis->BytesUntilLimit() == 0); // Update metric if(metric) metric->visitedMapObjects++; cis->PopLimit(oldLimit); } // If map object was not read, skip it if(!mapObject) { // Update metric if(metric) { const std::chrono::duration<float> readMapObject_elapsed = std::chrono::high_resolution_clock::now() - readMapObject_begin; metric->elapsedTimeForOnlyVisitedMapObjects += readMapObject_elapsed.count(); } break; } // Update metric if(metric) { const std::chrono::duration<float> readMapObject_elapsed = std::chrono::high_resolution_clock::now() - readMapObject_begin; metric->elapsedTimeForOnlyAcceptedMapObjects += readMapObject_elapsed.count(); metric->acceptedMapObjects++; } // Make unique map object identifier mapObject->_id = Model::MapObject::getUniqueId(mapObject->_id, section); // Check if map object is desired if(filterById && !filterById(section, mapObject->id, mapObject->bbox31, mapObject->level->minZoom, mapObject->level->maxZoom)) break; // Save object mapObject->_foundation = tree->_foundation; intermediateResult.push_back(qMove(mapObject)); } break; case OBF::MapDataBlock::kStringTableFieldNumber: { gpb::uint32 length; cis->ReadVarint32(&length); auto oldLimit = cis->PushLimit(length); if(intermediateResult.isEmpty()) { cis->Skip(cis->BytesUntilLimit()); cis->PopLimit(oldLimit); break; } ObfReaderUtilities::readStringTable(cis, mapObjectsNamesTable); assert(cis->BytesUntilLimit() == 0); cis->PopLimit(oldLimit); } break; default: ObfReaderUtilities::skipUnknownField(cis, tag); break; } }
void OsmAnd::ObfMapSectionReader_P::readMapObjectsBlock( const ObfReader_P& reader, const std::shared_ptr<const ObfMapSectionInfo>& section, const std::shared_ptr<const ObfMapSectionLevelTreeNode>& tree, QList< std::shared_ptr<const OsmAnd::BinaryMapObject> >* resultOut, const AreaI* bbox31, const FilterReadingByIdFunction filterById, const VisitorFunction visitor, const std::shared_ptr<const IQueryController>& queryController, ObfMapSectionReader_Metrics::Metric_loadMapObjects* const metric) { const auto cis = reader.getCodedInputStream().get(); QList< std::shared_ptr<BinaryMapObject> > intermediateResult; QStringList mapObjectsCaptionsTable; gpb::uint64 baseId = 0; for (;;) { const auto tag = cis->ReadTag(); switch (gpb::internal::WireFormatLite::GetTagFieldNumber(tag)) { case 0: { if (!ObfReaderUtilities::reachedDataEnd(cis)) return; for (const auto& mapObject : constOf(intermediateResult)) { // Fill mapObject captions from string-table for (auto& caption : mapObject->captions) { const auto stringId = ObfReaderUtilities::decodeIntegerFromString(caption); if (stringId >= mapObjectsCaptionsTable.size()) { LogPrintf(LogSeverityLevel::Error, "Data mismatch: string #%d (map object %s not found in string table (size %d) in section '%s'", stringId, qPrintable(mapObject->id.toString()), mapObjectsCaptionsTable.size(), qPrintable(section->name)); caption = QString::fromLatin1("#%1 NOT FOUND").arg(stringId); continue; } caption = mapObjectsCaptionsTable[stringId]; } ////////////////////////////////////////////////////////////////////////// //if (mapObject->id.getOsmId() == 49048972u) //{ // int i = 5; //} ////////////////////////////////////////////////////////////////////////// if (!visitor || visitor(mapObject)) { if (resultOut) resultOut->push_back(qMove(mapObject)); } } return; } case OBF::MapDataBlock::kBaseIdFieldNumber: { cis->ReadVarint64(&baseId); ////////////////////////////////////////////////////////////////////////// //if (bbox31) // LogPrintf(LogSeverityLevel::Debug, "BBOX %d %d %d %d - MAP BLOCK %" PRIi64, bbox31->top, bbox31->left, bbox31->bottom, bbox31->right, baseId); ////////////////////////////////////////////////////////////////////////// break; } case OBF::MapDataBlock::kDataObjectsFieldNumber: { gpb::uint32 length; cis->ReadVarint32(&length); const auto offset = cis->CurrentPosition(); // Read map object content const Stopwatch readMapObjectStopwatch(metric != nullptr); std::shared_ptr<OsmAnd::BinaryMapObject> mapObject; auto oldLimit = cis->PushLimit(length); readMapObject(reader, section, baseId, tree, mapObject, bbox31, metric); ObfReaderUtilities::ensureAllDataWasRead(cis); cis->PopLimit(oldLimit); // Update metric if (metric) metric->visitedMapObjects++; // If map object was not read, skip it if (!mapObject) { if (metric) metric->elapsedTimeForOnlyVisitedMapObjects += readMapObjectStopwatch.elapsed(); break; } // Update metric if (metric) { metric->elapsedTimeForOnlyAcceptedMapObjects += readMapObjectStopwatch.elapsed(); metric->acceptedMapObjects++; } ////////////////////////////////////////////////////////////////////////// //if (mapObject->id.getOsmId() == 49048972u) //{ // int i = 5; //} ////////////////////////////////////////////////////////////////////////// // Check if map object is desired const auto shouldReject = filterById && !filterById( section, mapObject->id, mapObject->bbox31, mapObject->level->minZoom, mapObject->level->maxZoom); if (shouldReject) break; // Save object intermediateResult.push_back(qMove(mapObject)); break; } case OBF::MapDataBlock::kStringTableFieldNumber: { gpb::uint32 length; cis->ReadVarint32(&length); const auto offset = cis->CurrentPosition(); auto oldLimit = cis->PushLimit(length); if (intermediateResult.isEmpty()) { cis->Skip(cis->BytesUntilLimit()); cis->PopLimit(oldLimit); break; } ObfReaderUtilities::readStringTable(cis, mapObjectsCaptionsTable); ObfReaderUtilities::ensureAllDataWasRead(cis); cis->PopLimit(oldLimit); break; } default: ObfReaderUtilities::skipUnknownField(cis, tag); break; } } }
void OsmAnd::ObfMapSectionReader_P::readMapObjectsBlock( const std::unique_ptr<ObfReader_P>& reader, const std::shared_ptr<const ObfMapSectionInfo>& section, const std::shared_ptr<ObfMapSectionLevelTreeNode>& tree, QList< std::shared_ptr<const OsmAnd::Model::MapObject> >* resultOut, const AreaI* bbox31, std::function<bool (const std::shared_ptr<const OsmAnd::Model::MapObject>&)> visitor, IQueryController* controller) { auto cis = reader->_codedInputStream.get(); QList< std::shared_ptr<OsmAnd::Model::MapObject> > intermediateResult; QStringList mapObjectsNamesTable; gpb::uint64 baseId = 0; for(;;) { if(controller && controller->isAborted()) return; auto tag = cis->ReadTag(); switch(gpb::internal::WireFormatLite::GetTagFieldNumber(tag)) { case 0: for(auto itEntry = intermediateResult.begin(); itEntry != intermediateResult.end(); ++itEntry) { const auto& entry = *itEntry; // Fill names of roads from stringtable for(auto itNameEntry = entry->_names.begin(); itNameEntry != entry->_names.end(); ++itNameEntry) { const auto& encodedId = itNameEntry.value(); uint32_t stringId = 0; stringId |= (encodedId.at(1 + 0).unicode() & 0xff) << 8*0; stringId |= (encodedId.at(1 + 1).unicode() & 0xff) << 8*1; stringId |= (encodedId.at(1 + 2).unicode() & 0xff) << 8*2; stringId |= (encodedId.at(1 + 3).unicode() & 0xff) << 8*3; if(stringId >= mapObjectsNamesTable.size()) { LogPrintf(LogSeverityLevel::Error, "Data mismatch: string #%d (map object #%" PRIu64 " (%" PRIi64 ") not found in string table(%d) in section '%s'", stringId, entry->id >> 1, static_cast<int64_t>(entry->id) / 2, mapObjectsNamesTable.size(), qPrintable(section->name)); itNameEntry.value() = QString::fromLatin1("#%1 NOT FOUND").arg(stringId); continue; } itNameEntry.value() = mapObjectsNamesTable[stringId]; } if(!visitor || visitor(entry)) { if(resultOut) resultOut->push_back(entry); } } return; case OBF::MapDataBlock::kBaseIdFieldNumber: cis->ReadVarint64(&baseId); break; case OBF::MapDataBlock::kDataObjectsFieldNumber: { gpb::uint32 length; cis->ReadVarint32(&length); auto oldLimit = cis->PushLimit(length); auto pos = cis->CurrentPosition(); std::shared_ptr<OsmAnd::Model::MapObject> mapObject; readMapObject(reader, section, tree, baseId, mapObject, bbox31); if(mapObject) { mapObject->_foundation = tree->_foundation; intermediateResult.push_back(mapObject); } cis->PopLimit(oldLimit); } break; case OBF::MapDataBlock::kStringTableFieldNumber: { gpb::uint32 length; cis->ReadVarint32(&length); auto oldLimit = cis->PushLimit(length); if(intermediateResult.isEmpty()) { cis->Skip(cis->BytesUntilLimit()); cis->PopLimit(oldLimit); break; } ObfReaderUtilities::readStringTable(cis, mapObjectsNamesTable); cis->PopLimit(oldLimit); } break; default: ObfReaderUtilities::skipUnknownField(cis, tag); break; } }