void OsmAnd::ObfMapSectionReader_P::readTreeNodeChildren( const std::unique_ptr<ObfReader_P>& reader, const std::shared_ptr<const ObfMapSectionInfo>& section, const std::shared_ptr<ObfMapSectionLevelTreeNode>& treeNode, MapFoundationType& foundation, QList< std::shared_ptr<ObfMapSectionLevelTreeNode> >* nodesWithData, const AreaI* bbox31, IQueryController* controller) { auto cis = reader->_codedInputStream.get(); for(;;) { auto tag = cis->ReadTag(); switch(gpb::internal::WireFormatLite::GetTagFieldNumber(tag)) { case 0: return; case OBF::OsmAndMapIndex_MapDataBox::kBoxesFieldNumber: { auto length = ObfReaderUtilities::readBigEndianInt(cis); auto offset = cis->CurrentPosition(); auto oldLimit = cis->PushLimit(length); std::shared_ptr<ObfMapSectionLevelTreeNode> childNode(new ObfMapSectionLevelTreeNode()); childNode->_foundation = treeNode->_foundation; childNode->_offset = offset; childNode->_length = length; readTreeNode(reader, section, treeNode->_area31, childNode); if(bbox31 && !bbox31->intersects(childNode->_area31)) { cis->Skip(cis->BytesUntilLimit()); cis->PopLimit(oldLimit); break; } cis->PopLimit(oldLimit); if(childNode->_foundation != MapFoundationType::Undefined) { if(foundation == MapFoundationType::Undefined) foundation = childNode->_foundation; else if(foundation != childNode->_foundation) foundation = MapFoundationType::Mixed; } if(nodesWithData && childNode->_dataOffset > 0) nodesWithData->push_back(childNode); cis->Seek(offset); oldLimit = cis->PushLimit(length); cis->Skip(childNode->_childrenInnerOffset); readTreeNodeChildren(reader, section, childNode, foundation, nodesWithData, bbox31, controller); assert(cis->BytesUntilLimit() == 0); cis->PopLimit(oldLimit); } break; default: ObfReaderUtilities::skipUnknownField(cis, tag); break; } } }
void OsmAnd::ObfPoiSectionReader_P::readCategories( const std::unique_ptr<ObfReader_P>& reader, const std::shared_ptr<const ObfPoiSectionInfo>& section, QList< std::shared_ptr<const Model::AmenityCategory> >& categories ) { auto cis = reader->_codedInputStream.get(); for(;;) { auto tag = cis->ReadTag(); switch(gpb::internal::WireFormatLite::GetTagFieldNumber(tag)) { case 0: return; case OBF::OsmAndPoiIndex::kCategoriesTableFieldNumber: { gpb::uint32 length; cis->ReadVarint32(&length); auto oldLimit = cis->PushLimit(length); std::shared_ptr<Model::AmenityCategory> category(new Model::AmenityCategory()); readCategory(reader, category); cis->PopLimit(oldLimit); categories.push_back(category); } break; case OBF::OsmAndPoiIndex::kNameIndexFieldNumber: cis->Skip(cis->BytesUntilLimit()); return; default: ObfReaderUtilities::skipUnknownField(cis, tag); break; } } }
void OsmAnd::ObfPoiSectionReader_P::read( const std::unique_ptr<ObfReader_P>& reader, const std::shared_ptr<ObfPoiSectionInfo>& section ) { auto cis = reader->_codedInputStream.get(); for(;;) { auto tag = cis->ReadTag(); switch(gpb::internal::WireFormatLite::GetTagFieldNumber(tag)) { case 0: return; case OBF::OsmAndPoiIndex::kNameFieldNumber: ObfReaderUtilities::readQString(cis, section->_name); break; case OBF::OsmAndPoiIndex::kBoundariesFieldNumber: { gpb::uint32 length; cis->ReadVarint32(&length); auto oldLimit = cis->PushLimit(length); readBoundaries(reader, section); cis->PopLimit(oldLimit); } break; case OBF::OsmAndPoiIndex::kCategoriesTableFieldNumber: cis->Skip(cis->BytesUntilLimit()); return; default: ObfReaderUtilities::skipUnknownField(cis, tag); break; } } }
void OsmAnd::ObfPoiSectionReader_P::readAmenities( const std::unique_ptr<ObfReader_P>& reader, const std::shared_ptr<const ObfPoiSectionInfo>& section, QSet<uint32_t>* desiredCategories, QList< std::shared_ptr<const Model::Amenity> >* amenitiesOut, const ZoomLevel& zoom, uint32_t zoomDepth, const AreaI* bbox31, std::function<bool (const std::shared_ptr<const Model::Amenity>&)> visitor, IQueryController* controller) { auto cis = reader->_codedInputStream.get(); QList< std::shared_ptr<Tile> > tiles; for(;;) { auto tag = cis->ReadTag(); switch(gpb::internal::WireFormatLite::GetTagFieldNumber(tag)) { case 0: return; case OBF::OsmAndPoiIndex::kBoxesFieldNumber: { auto length = ObfReaderUtilities::readBigEndianInt(cis); auto oldLimit = cis->PushLimit(length); readTile(reader, section, tiles, nullptr, desiredCategories, zoom, zoomDepth, bbox31, controller, nullptr); cis->PopLimit(oldLimit); if(controller && controller->isAborted()) return; } break; case OBF::OsmAndPoiIndex::kPoiDataFieldNumber: { // Sort tiles byte data offset, to all cache-friendly with I/O system qSort(tiles.begin(), tiles.end(), [](const std::shared_ptr<Tile>& l, const std::shared_ptr<Tile>& r) -> bool { return l->_hash < r->_hash; }); for(auto itTile = tiles.begin(); itTile != tiles.end(); ++itTile) { const auto& tile = *itTile; cis->Seek(section->_offset + tile->_offset); auto length = ObfReaderUtilities::readBigEndianInt(cis); auto oldLimit = cis->PushLimit(length); readAmenitiesFromTile(reader, section, tile.get(), desiredCategories, amenitiesOut, zoom, zoomDepth, bbox31, visitor, controller, nullptr); cis->PopLimit(oldLimit); if(controller && controller->isAborted()) return; } cis->Skip(cis->BytesUntilLimit()); } return; default: ObfReaderUtilities::skipUnknownField(cis, tag); break; } } }
void OsmAnd::ObfRoutingSectionReader_P::readBorderLinePoint( const std::unique_ptr<ObfReader_P>& reader, const std::shared_ptr<ObfRoutingBorderLinePoint>& point) { auto cis = reader->_codedInputStream.get(); for(;;) { auto tag = cis->ReadTag(); switch(gpb::internal::WireFormatLite::GetTagFieldNumber(tag)) { case 0: return; case OBF::OsmAndRoutingIndex_RouteBorderPoint::kDxFieldNumber: cis->ReadVarint32(reinterpret_cast<gpb::uint32*>(&point->_location.x)); break; case OBF::OsmAndRoutingIndex_RouteBorderPoint::kDyFieldNumber: cis->ReadVarint32(reinterpret_cast<gpb::uint32*>(&point->_location.y)); break; case OBF::OsmAndRoutingIndex_RouteBorderPoint::kRoadIdFieldNumber: cis->ReadVarint64(&point->_id); break; case OBF::OsmAndRoutingIndex_RouteBorderPoint::kDirectionFieldNumber: { gpb::uint32 value; cis->ReadVarint32(&value); //TODO:p.direction = codedIS.readBool(); } break; case OBF::OsmAndRoutingIndex_RouteBorderPoint::kTypesFieldNumber: { gpb::uint32 length; cis->ReadVarint32(&length); auto oldLimit = cis->PushLimit(length); while(cis->BytesUntilLimit() > 0) { gpb::uint32 value; cis->ReadVarint32(&value); point->_types.push_back(value); } cis->PopLimit(oldLimit); } break; default: ObfReaderUtilities::skipUnknownField(cis, tag); break; } } }
void OsmAnd::ObfMapSectionReader_P::readMapLevelHeader( const std::unique_ptr<ObfReader_P>& reader, const std::shared_ptr<const ObfMapSectionInfo>& section, const std::shared_ptr<ObfMapSectionLevel>& level ) { auto cis = reader->_codedInputStream.get(); for(;;) { const auto tagPos = cis->CurrentPosition(); const auto tag = cis->ReadTag(); switch(gpb::internal::WireFormatLite::GetTagFieldNumber(tag)) { case 0: return; case OBF::OsmAndMapIndex_MapRootLevel::kMaxZoomFieldNumber: cis->ReadVarint32(reinterpret_cast<gpb::uint32*>(&level->_maxZoom)); break; case OBF::OsmAndMapIndex_MapRootLevel::kMinZoomFieldNumber: cis->ReadVarint32(reinterpret_cast<gpb::uint32*>(&level->_minZoom)); break; case OBF::OsmAndMapIndex_MapRootLevel::kLeftFieldNumber: cis->ReadVarint32(reinterpret_cast<gpb::uint32*>(&level->_area31.left)); break; case OBF::OsmAndMapIndex_MapRootLevel::kRightFieldNumber: cis->ReadVarint32(reinterpret_cast<gpb::uint32*>(&level->_area31.right)); break; case OBF::OsmAndMapIndex_MapRootLevel::kTopFieldNumber: cis->ReadVarint32(reinterpret_cast<gpb::uint32*>(&level->_area31.top)); break; case OBF::OsmAndMapIndex_MapRootLevel::kBottomFieldNumber: cis->ReadVarint32(reinterpret_cast<gpb::uint32*>(&level->_area31.bottom)); break; case OBF::OsmAndMapIndex_MapRootLevel::kBoxesFieldNumber: { // Save boxes offset level->_boxesInnerOffset = tagPos - level->_offset; // Skip reading boxes and surely, following blocks cis->Skip(cis->BytesUntilLimit()); } return; default: ObfReaderUtilities::skipUnknownField(cis, tag); break; } } }
void OsmAnd::ObfRoutingSectionReader_P::readSubsectionChildrenHeaders( const std::unique_ptr<ObfReader_P>& reader, const std::shared_ptr<ObfRoutingSubsectionInfo>& subsection, uint32_t depth /*= std::numeric_limits<uint32_t>::max()*/ ) { if(!subsection->_subsectionsOffset) return; const auto shouldReadSubsections = (depth > 0 || subsection->_dataOffset != 0); if(!shouldReadSubsections) return; auto cis = reader->_codedInputStream.get(); for(;;) { auto lastPos = cis->CurrentPosition(); auto tag = cis->ReadTag(); switch(gpb::internal::WireFormatLite::GetTagFieldNumber(tag)) { case 0: return; case OBF::OsmAndRoutingIndex_RouteDataBox::kBoxesFieldNumber: { if(!shouldReadSubsections) { cis->Skip(cis->BytesUntilLimit()); break; } const std::shared_ptr<ObfRoutingSubsectionInfo> childSubsection(new ObfRoutingSubsectionInfo(subsection)); childSubsection->_length = ObfReaderUtilities::readBigEndianInt(cis); childSubsection->_offset = cis->CurrentPosition(); auto oldLimit = cis->PushLimit(childSubsection->_length); readSubsectionHeader(reader, childSubsection, subsection, depth - 1); cis->PopLimit(oldLimit); subsection->_subsections.push_back(qMove(childSubsection)); } break; default: ObfReaderUtilities::skipUnknownField(cis, tag); break; } } }
void OsmAnd::ObfPoiSection::readCategories( ObfReader* reader, ObfPoiSection* section, QList< std::shared_ptr<OsmAnd::Model::Amenity::Category> >& categories ) { auto cis = reader->_codedInputStream.get(); for(;;) { auto tag = cis->ReadTag(); switch(gpb::internal::WireFormatLite::GetTagFieldNumber(tag)) { case 0: return; case OBF::OsmAndPoiIndex::kNameFieldNumber: ObfReader::readQString(cis, section->_name); break; case OBF::OsmAndPoiIndex::kBoundariesFieldNumber: { gpb::uint32 length; cis->ReadVarint32(&length); auto oldLimit = cis->PushLimit(length); readBoundaries(reader, section); cis->PopLimit(oldLimit); } break; case OBF::OsmAndPoiIndex::kCategoriesTableFieldNumber: { gpb::uint32 length; cis->ReadVarint32(&length); auto oldLimit = cis->PushLimit(length); std::shared_ptr<Model::Amenity::Category> category(new Model::Amenity::Category()); readCategory(reader, category.get()); cis->PopLimit(oldLimit); categories.push_back(category); } break; case OBF::OsmAndPoiIndex::kNameIndexFieldNumber: cis->Skip(cis->BytesUntilLimit()); return; default: ObfReader::skipUnknownField(cis, tag); break; } } }
void OsmAnd::ObfPoiSectionReader_P::readCategories( const ObfReader_P& reader, const std::shared_ptr<const ObfPoiSectionInfo>& section, QList< std::shared_ptr<const AmenityCategory> >& categories ) { const auto cis = reader.getCodedInputStream().get(); for(;;) { const auto tag = cis->ReadTag(); switch(gpb::internal::WireFormatLite::GetTagFieldNumber(tag)) { case 0: if (!ObfReaderUtilities::reachedDataEnd(cis)) return; return; case OBF::OsmAndPoiIndex::kCategoriesTableFieldNumber: { gpb::uint32 length; cis->ReadVarint32(&length); const auto offset = cis->CurrentPosition(); auto oldLimit = cis->PushLimit(length); std::shared_ptr<AmenityCategory> category(new AmenityCategory()); readCategory(reader, category); ObfReaderUtilities::ensureAllDataWasRead(cis); cis->PopLimit(oldLimit); categories.push_back(qMove(category)); } break; case OBF::OsmAndPoiIndex::kNameIndexFieldNumber: cis->Skip(cis->BytesUntilLimit()); return; default: ObfReaderUtilities::skipUnknownField(cis, tag); break; } } }
void OsmAnd::ObfMapSectionReader_P::readMapLevelTreeNodes( const std::unique_ptr<ObfReader_P>& reader, const std::shared_ptr<const ObfMapSectionInfo>& section, const std::shared_ptr<const ObfMapSectionLevel>& level, QList< std::shared_ptr<ObfMapSectionLevelTreeNode> >& trees ) { auto cis = reader->_codedInputStream.get(); for(;;) { gpb::uint32 tag = cis->ReadTag(); switch(gpb::internal::WireFormatLite::GetTagFieldNumber(tag)) { case 0: return; case OBF::OsmAndMapIndex_MapRootLevel::kBoxesFieldNumber: { const auto length = ObfReaderUtilities::readBigEndianInt(cis); const auto offset = cis->CurrentPosition(); const auto oldLimit = cis->PushLimit(length); std::shared_ptr<ObfMapSectionLevelTreeNode> levelTree(new ObfMapSectionLevelTreeNode(level)); levelTree->_offset = offset; levelTree->_length = length; readTreeNode(reader, section, level->area31, levelTree); cis->PopLimit(oldLimit); trees.push_back(qMove(levelTree)); } break; case OBF::OsmAndMapIndex_MapRootLevel::kBlocksFieldNumber: cis->Skip(cis->BytesUntilLimit()); return; default: ObfReaderUtilities::skipUnknownField(cis, tag); break; } } }
void OsmAnd::ObfRoutingSectionReader_P::readRoad( const std::unique_ptr<ObfReader_P>& reader, const std::shared_ptr<const ObfRoutingSubsectionInfo>& subsection, const QList<uint64_t>& idsTable, uint32_t& internalId, const std::shared_ptr<Model::Road>& road ) { auto cis = reader->_codedInputStream.get(); for(;;) { auto tag = cis->ReadTag(); switch(gpb::internal::WireFormatLite::GetTagFieldNumber(tag)) { case 0: return; case OBF::RouteData::kPointsFieldNumber: { gpb::uint32 length; cis->ReadVarint32(&length); auto oldLimit = cis->PushLimit(length); auto dx = subsection->_area31.left >> ShiftCoordinates; auto dy = subsection->_area31.top >> ShiftCoordinates; while(cis->BytesUntilLimit() > 0) { const uint32_t x = ObfReaderUtilities::readSInt32(cis) + dx; const uint32_t y = ObfReaderUtilities::readSInt32(cis) + dy; road->_points.push_back(qMove(PointI( x << ShiftCoordinates, y << ShiftCoordinates ))); dx = x; dy = y; } cis->PopLimit(oldLimit); } break; case OBF::RouteData::kPointTypesFieldNumber: { gpb::uint32 length; cis->ReadVarint32(&length); auto oldLimit = cis->PushLimit(length); while(cis->BytesUntilLimit() > 0) { gpb::uint32 pointIdx; cis->ReadVarint32(&pointIdx); gpb::uint32 innerLength; cis->ReadVarint32(&innerLength); auto innerOldLimit = cis->PushLimit(innerLength); auto& pointTypes = road->_pointsTypes.insert(pointIdx, QVector<uint32_t>()).value(); while(cis->BytesUntilLimit() > 0) { gpb::uint32 pointType; cis->ReadVarint32(&pointType); pointTypes.push_back(pointType); } cis->PopLimit(innerOldLimit); } cis->PopLimit(oldLimit); } break; case OBF::RouteData::kTypesFieldNumber: { gpb::uint32 length; cis->ReadVarint32(&length); auto oldLimit = cis->PushLimit(length); while(cis->BytesUntilLimit() > 0) { gpb::uint32 type; cis->ReadVarint32(&type); road->_types.push_back(type); } cis->PopLimit(oldLimit); } break; case OBF::RouteData::kRouteIdFieldNumber: { gpb::uint32 id; cis->ReadVarint32(&id); internalId = id; if(id < idsTable.size()) road->_id = idsTable[id]; else road->_id = id; } break; case OBF::RouteData::kStringNamesFieldNumber: { gpb::uint32 length; cis->ReadVarint32(&length); auto oldLimit = cis->PushLimit(length); while(cis->BytesUntilLimit() > 0) { gpb::uint32 stringTag; cis->ReadVarint32(&stringTag); gpb::uint32 stringId; cis->ReadVarint32(&stringId); road->_names.insert(stringTag, ObfReaderUtilities::encodeIntegerToString(stringId)); } cis->PopLimit(oldLimit); } break; default: ObfReaderUtilities::skipUnknownField(cis, tag); break; } } }
bool OsmAnd::ObfPoiSectionReader_P::readTile( const std::unique_ptr<ObfReader_P>& reader, const std::shared_ptr<const ObfPoiSectionInfo>& section, QList< std::shared_ptr<Tile> >& tiles, Tile* parent, QSet<uint32_t>* desiredCategories, uint32_t zoom, uint32_t zoomDepth, const AreaI* bbox31, IQueryController* controller, QSet< uint64_t >* tilesToSkip) { auto cis = reader->_codedInputStream.get(); const auto zoomToSkip = zoom + zoomDepth; QSet< uint64_t > tilesToSkip_; if(parent == nullptr && !tilesToSkip) tilesToSkip = &tilesToSkip_; std::shared_ptr<Tile> tile(new Tile()); gpb::uint32 lzoom; for(;;) { if(controller && controller->isAborted()) return false; auto tag = cis->ReadTag(); switch(gpb::internal::WireFormatLite::GetTagFieldNumber(tag)) { case 0: tiles.push_back(tile); return true; case OBF::OsmAndPoiBox::kZoomFieldNumber: { cis->ReadVarint32(&lzoom); tile->_zoom = lzoom; if(parent) tile->_zoom += parent->_zoom; } break; case OBF::OsmAndPoiBox::kLeftFieldNumber: { auto x = ObfReaderUtilities::readSInt32(cis); if(parent) tile->_x = x + (parent->_x << lzoom); else tile->_x = x; } break; case OBF::OsmAndPoiBox::kTopFieldNumber: { auto y = ObfReaderUtilities::readSInt32(cis); if(parent) tile->_y = y + (parent->_y << lzoom); else tile->_y = y; // Check that we're inside bounding box, if requested if(bbox31) { AreaI area31; area31.left = tile->_x << (31 - tile->_zoom); area31.right = (tile->_x + 1) << (31 - tile->_zoom); area31.top = tile->_y << (31 - tile->_zoom); area31.bottom = (tile->_y + 1) << (31 - tile->_zoom); if(!bbox31->intersects(area31)) { // This tile is outside of bounding box cis->Skip(cis->BytesUntilLimit()); return false; } } } break; case OBF::OsmAndPoiBox::kCategoriesFieldNumber: { if(!desiredCategories) { ObfReaderUtilities::skipUnknownField(cis, tag); break; } gpb::uint32 length; cis->ReadLittleEndian32(&length); auto oldLimit = cis->PushLimit(length); const auto containsDesired = checkTileCategories(reader, section, desiredCategories); cis->PopLimit(oldLimit); if(!containsDesired) { cis->Skip(cis->BytesUntilLimit()); return false; } } break; case OBF::OsmAndPoiBox::kSubBoxesFieldNumber: { auto length = ObfReaderUtilities::readBigEndianInt(cis); auto oldLimit = cis->PushLimit(length); auto tileOmitted = readTile(reader, section, tiles, tile.get(), desiredCategories, zoom, zoomDepth, bbox31, controller, tilesToSkip); cis->PopLimit(oldLimit); if(tilesToSkip && tile->_zoom >= zoomToSkip && tileOmitted) { auto skipHash = (static_cast<uint64_t>(tile->_x) >> (tile->_zoom - zoomToSkip)) << zoomToSkip; skipHash |= static_cast<uint64_t>(tile->_y) >> (tile->_zoom - zoomToSkip); if(tilesToSkip->contains(skipHash)) { cis->Skip(cis->BytesUntilLimit()); return true; } } } break; case OBF::OsmAndPoiBox::kShiftToDataFieldNumber: { tile->_offset = ObfReaderUtilities::readBigEndianInt(cis); tile->_hash = static_cast<uint64_t>(tile->_x) << tile->_zoom; tile->_hash |= static_cast<uint64_t>(tile->_y); tile->_hash |= tile->_zoom; // skipTiles - these tiles are going to be ignored, since we need only 1 POI object (x;y)@zoom if(tilesToSkip && tile->_zoom >= zoomToSkip) { auto skipHash = (static_cast<uint64_t>(tile->_x) >> (tile->_zoom - zoomToSkip)) << zoomToSkip; skipHash |= static_cast<uint64_t>(tile->_y) >> (tile->_zoom - zoomToSkip); tilesToSkip->insert(skipHash); } } break; default: ObfReaderUtilities::skipUnknownField(cis, tag); break; }
void OsmAnd::ObfMapSectionReader_P::readTreeNode( const std::unique_ptr<ObfReader_P>& reader, const std::shared_ptr<const ObfMapSectionInfo>& section, const AreaI& parentArea, const std::shared_ptr<ObfMapSectionLevelTreeNode>& treeNode ) { auto cis = reader->_codedInputStream.get(); for(;;) { const auto tagPos = cis->CurrentPosition(); auto tag = cis->ReadTag(); switch(gpb::internal::WireFormatLite::GetTagFieldNumber(tag)) { case 0: return; case OBF::OsmAndMapIndex_MapDataBox::kLeftFieldNumber: { auto d = ObfReaderUtilities::readSInt32(cis); treeNode->_area31.left = d + parentArea.left; } break; case OBF::OsmAndMapIndex_MapDataBox::kRightFieldNumber: { auto d = ObfReaderUtilities::readSInt32(cis); treeNode->_area31.right = d + parentArea.right; } break; case OBF::OsmAndMapIndex_MapDataBox::kTopFieldNumber: { auto d = ObfReaderUtilities::readSInt32(cis); treeNode->_area31.top = d + parentArea.top; } break; case OBF::OsmAndMapIndex_MapDataBox::kBottomFieldNumber: { auto d = ObfReaderUtilities::readSInt32(cis); treeNode->_area31.bottom = d + parentArea.bottom; } break; case OBF::OsmAndMapIndex_MapDataBox::kShiftToMapDataFieldNumber: treeNode->_dataOffset = ObfReaderUtilities::readBigEndianInt(cis) + treeNode->_offset; break; case OBF::OsmAndMapIndex_MapDataBox::kOceanFieldNumber: { gpb::uint32 value; cis->ReadVarint32(&value); treeNode->_foundation = (value != 0) ? MapFoundationType::FullWater : MapFoundationType::FullLand; } break; case OBF::OsmAndMapIndex_MapDataBox::kBoxesFieldNumber: { // Save children relative offset and skip their data treeNode->_childrenInnerOffset = tagPos - treeNode->_offset; cis->Skip(cis->BytesUntilLimit()); } return; default: ObfReaderUtilities::skipUnknownField(cis, tag); break; } } }
void OsmAnd::ObfMapSectionReader_P::readTreeNodeChildren( const std::unique_ptr<ObfReader_P>& reader, const std::shared_ptr<const ObfMapSectionInfo>& section, const std::shared_ptr<ObfMapSectionLevelTreeNode>& treeNode, MapFoundationType& foundation, QList< std::shared_ptr<ObfMapSectionLevelTreeNode> >* nodesWithData, const AreaI* bbox31, const IQueryController* const controller, ObfMapSectionReader_Metrics::Metric_loadMapObjects* const metric) { auto cis = reader->_codedInputStream.get(); foundation = MapFoundationType::Undefined; for(;;) { auto tag = cis->ReadTag(); switch(gpb::internal::WireFormatLite::GetTagFieldNumber(tag)) { case 0: return; case OBF::OsmAndMapIndex_MapDataBox::kBoxesFieldNumber: { auto length = ObfReaderUtilities::readBigEndianInt(cis); auto offset = cis->CurrentPosition(); auto oldLimit = cis->PushLimit(length); std::shared_ptr<ObfMapSectionLevelTreeNode> childNode(new ObfMapSectionLevelTreeNode(treeNode->level)); childNode->_foundation = treeNode->_foundation; childNode->_offset = offset; childNode->_length = length; readTreeNode(reader, section, treeNode->_area31, childNode); // Update metric if(metric) metric->visitedNodes++; if(bbox31) { const auto shouldSkip = !bbox31->contains(childNode->_area31) && !childNode->_area31.contains(*bbox31) && !bbox31->intersects(childNode->_area31); if(shouldSkip) { cis->Skip(cis->BytesUntilLimit()); cis->PopLimit(oldLimit); break; } } cis->PopLimit(oldLimit); // Update metric if(metric) metric->acceptedNodes++; if(nodesWithData && childNode->_dataOffset > 0) nodesWithData->push_back(childNode); auto childrenFoundation = MapFoundationType::Undefined; if(childNode->_childrenInnerOffset > 0) { cis->Seek(offset); oldLimit = cis->PushLimit(length); cis->Skip(childNode->_childrenInnerOffset); readTreeNodeChildren(reader, section, childNode, childrenFoundation, nodesWithData, bbox31, controller, metric); assert(cis->BytesUntilLimit() == 0); cis->PopLimit(oldLimit); } const auto foundationToMerge = (childrenFoundation != MapFoundationType::Undefined) ? childrenFoundation : childNode->_foundation; if(foundationToMerge != MapFoundationType::Undefined) { if(foundation == MapFoundationType::Undefined) foundation = foundationToMerge; else if(foundation != foundationToMerge) foundation = MapFoundationType::Mixed; } } break; default: ObfReaderUtilities::skipUnknownField(cis, tag); break; } } }
void OsmAnd::ObfMapSectionReader_P::readMapObject( const ObfReader_P& reader, const std::shared_ptr<const ObfMapSectionInfo>& section, uint64_t baseId, const std::shared_ptr<const ObfMapSectionLevelTreeNode>& treeNode, std::shared_ptr<OsmAnd::BinaryMapObject>& mapObject, const AreaI* bbox31, ObfMapSectionReader_Metrics::Metric_loadMapObjects* const metric) { const auto cis = reader.getCodedInputStream().get(); const auto baseOffset = cis->CurrentPosition(); for (;;) { const auto tag = cis->ReadTag(); const auto tgn = gpb::internal::WireFormatLite::GetTagFieldNumber(tag); switch (tgn) { case 0: { if (!ObfReaderUtilities::reachedDataEnd(cis)) return; if (mapObject && mapObject->points31.isEmpty()) { LogPrintf(LogSeverityLevel::Warning, "Empty BinaryMapObject %s detected in section '%s'", qPrintable(mapObject->id.toString()), qPrintable(section->name)); mapObject.reset(); } return; } case OBF::MapData::kAreaCoordinatesFieldNumber: case OBF::MapData::kCoordinatesFieldNumber: { const Stopwatch mapObjectPointsStopwatch(metric != nullptr); gpb::uint32 length; cis->ReadVarint32(&length); const auto oldLimit = cis->PushLimit(length); PointI p; p.x = treeNode->area31.left() & MaskToRead; p.y = treeNode->area31.top() & MaskToRead; AreaI objectBBox; objectBBox.top() = objectBBox.left() = std::numeric_limits<int32_t>::max(); objectBBox.bottom() = objectBBox.right() = 0; auto lastUnprocessedVertexForBBox = 0; // In protobuf, a sint32 can be encoded using [1..4] bytes, // so try to guess size of array, and preallocate it. // (BytesUntilLimit/2) is ~= number of vertices, and is always larger than needed. // So it's impossible that a buffer overflow will ever happen. But assert on that. const auto probableVerticesCount = (cis->BytesUntilLimit() / 2); QVector< PointI > points31(probableVerticesCount); auto pPoint = points31.data(); auto verticesCount = 0; bool shouldNotSkip = (bbox31 == nullptr); while (cis->BytesUntilLimit() > 0) { PointI d; d.x = (ObfReaderUtilities::readSInt32(cis) << ShiftCoordinates); d.y = (ObfReaderUtilities::readSInt32(cis) << ShiftCoordinates); p += d; // Save point into storage assert(points31.size() > verticesCount); *(pPoint++) = p; verticesCount++; // Check if map object should be maintained if (!shouldNotSkip && bbox31) { const Stopwatch mapObjectBboxStopwatch(metric != nullptr); shouldNotSkip = bbox31->contains(p); objectBBox.enlargeToInclude(p); if (metric) metric->elapsedTimeForMapObjectsBbox += mapObjectBboxStopwatch.elapsed(); lastUnprocessedVertexForBBox = verticesCount; } } cis->PopLimit(oldLimit); // Since reserved space may be larger than actual amount of data, // shrink the vertices array points31.resize(verticesCount); // If map object has no vertices, retain it in a special way to report later, when // it's identifier will be known if (points31.isEmpty()) { // Fake that this object is inside bbox shouldNotSkip = true; objectBBox = treeNode->area31; } // Even if no vertex lays inside bbox, an edge // may intersect the bbox if (!shouldNotSkip && bbox31) { assert(lastUnprocessedVertexForBBox == points31.size()); shouldNotSkip = objectBBox.contains(*bbox31) || bbox31->intersects(objectBBox); } // If map object didn't fit, skip it's entire content if (!shouldNotSkip) { if (metric) { metric->elapsedTimeForSkippedMapObjectsPoints += mapObjectPointsStopwatch.elapsed(); metric->skippedMapObjectsPoints += points31.size(); } cis->Skip(cis->BytesUntilLimit()); break; } // Update metric if (metric) { metric->elapsedTimeForNotSkippedMapObjectsPoints += mapObjectPointsStopwatch.elapsed(); metric->notSkippedMapObjectsPoints += points31.size(); } // In case bbox is not fully calculated, complete this task auto pPointForBBox = points31.data() + lastUnprocessedVertexForBBox; while (lastUnprocessedVertexForBBox < points31.size()) { const Stopwatch mapObjectBboxStopwatch(metric != nullptr); objectBBox.enlargeToInclude(*pPointForBBox); if (metric) metric->elapsedTimeForMapObjectsBbox += mapObjectBboxStopwatch.elapsed(); lastUnprocessedVertexForBBox++; pPointForBBox++; } // Finally, create the object if (!mapObject) mapObject.reset(new OsmAnd::BinaryMapObject(section, treeNode->level)); mapObject->isArea = (tgn == OBF::MapData::kAreaCoordinatesFieldNumber); mapObject->points31 = qMove(points31); mapObject->bbox31 = objectBBox; assert(treeNode->area31.top() - mapObject->bbox31.top() <= 32); assert(treeNode->area31.left() - mapObject->bbox31.left() <= 32); assert(mapObject->bbox31.bottom() - treeNode->area31.bottom() <= 1); assert(mapObject->bbox31.right() - treeNode->area31.right() <= 1); assert(mapObject->bbox31.right() >= mapObject->bbox31.left()); assert(mapObject->bbox31.bottom() >= mapObject->bbox31.top()); break; } case OBF::MapData::kPolygonInnerCoordinatesFieldNumber: { if (!mapObject) mapObject.reset(new OsmAnd::BinaryMapObject(section, treeNode->level)); gpb::uint32 length; cis->ReadVarint32(&length); auto oldLimit = cis->PushLimit(length); PointI p; p.x = treeNode->area31.left() & MaskToRead; p.y = treeNode->area31.top() & MaskToRead; // Preallocate memory const auto probableVerticesCount = (cis->BytesUntilLimit() / 2); mapObject->innerPolygonsPoints31.push_back(qMove(QVector< PointI >(probableVerticesCount))); auto& polygon = mapObject->innerPolygonsPoints31.last(); auto pPoint = polygon.data(); auto verticesCount = 0; while (cis->BytesUntilLimit() > 0) { PointI d; d.x = (ObfReaderUtilities::readSInt32(cis) << ShiftCoordinates); d.y = (ObfReaderUtilities::readSInt32(cis) << ShiftCoordinates); p += d; // Save point into storage assert(polygon.size() > verticesCount); *(pPoint++) = p; verticesCount++; } // Shrink memory polygon.resize(verticesCount); cis->PopLimit(oldLimit); break; } case OBF::MapData::kAdditionalTypesFieldNumber: case OBF::MapData::kTypesFieldNumber: { if (!mapObject) mapObject.reset(new OsmAnd::BinaryMapObject(section, treeNode->level)); auto& attributeIds = (tgn == OBF::MapData::kAdditionalTypesFieldNumber) ? mapObject->additionalAttributeIds : mapObject->attributeIds; gpb::uint32 length; cis->ReadVarint32(&length); auto oldLimit = cis->PushLimit(length); // Preallocate space attributeIds.reserve(cis->BytesUntilLimit()); while (cis->BytesUntilLimit() > 0) { gpb::uint32 attributeId; cis->ReadVarint32(&attributeId); attributeIds.push_back(attributeId); } // Shrink preallocated space attributeIds.squeeze(); cis->PopLimit(oldLimit); break; } case OBF::MapData::kStringNamesFieldNumber: { gpb::uint32 length; cis->ReadVarint32(&length); auto oldLimit = cis->PushLimit(length); while (cis->BytesUntilLimit() > 0) { bool ok; gpb::uint32 stringRuleId; ok = cis->ReadVarint32(&stringRuleId); assert(ok); gpb::uint32 stringId; ok = cis->ReadVarint32(&stringId); assert(ok); mapObject->captions.insert(stringRuleId, qMove(ObfReaderUtilities::encodeIntegerToString(stringId))); mapObject->captionsOrder.push_back(stringRuleId); } cis->PopLimit(oldLimit); break; } case OBF::MapData::kIdFieldNumber: { const auto d = ObfReaderUtilities::readSInt64(cis); const auto rawId = static_cast<uint64_t>(d + baseId); mapObject->id = ObfObjectId::generateUniqueId(rawId, baseOffset, section); ////////////////////////////////////////////////////////////////////////// //if (mapObject->id.getOsmId() == 49048972u) //{ // int i = 5; //} ////////////////////////////////////////////////////////////////////////// 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::readTreeNode( const ObfReader_P& reader, const std::shared_ptr<const ObfMapSectionInfo>& section, const AreaI& parentArea, const std::shared_ptr<ObfMapSectionLevelTreeNode>& treeNode) { const auto cis = reader.getCodedInputStream().get(); uint64_t fieldsMask = 0u; const auto safeToSkipFieldsMask = (1ull << OBF::OsmAndMapIndex_MapDataBox::kLeftFieldNumber) | (1ull << OBF::OsmAndMapIndex_MapDataBox::kRightFieldNumber) | (1ull << OBF::OsmAndMapIndex_MapDataBox::kTopFieldNumber) | (1ull << OBF::OsmAndMapIndex_MapDataBox::kBottomFieldNumber); bool kBoxesFieldNumberProcessed = false; for (;;) { const auto tagPos = cis->CurrentPosition(); const auto tag = cis->ReadTag(); const auto tfn = gpb::internal::WireFormatLite::GetTagFieldNumber(tag); switch (tfn) { case 0: if (!ObfReaderUtilities::reachedDataEnd(cis)) return; return; case OBF::OsmAndMapIndex_MapDataBox::kLeftFieldNumber: { const auto d = ObfReaderUtilities::readSInt32(cis); treeNode->area31.left() = d + parentArea.left(); fieldsMask |= (1ull << tfn); break; } case OBF::OsmAndMapIndex_MapDataBox::kRightFieldNumber: { const auto d = ObfReaderUtilities::readSInt32(cis); treeNode->area31.right() = d + parentArea.right(); fieldsMask |= (1ull << tfn); break; } case OBF::OsmAndMapIndex_MapDataBox::kTopFieldNumber: { const auto d = ObfReaderUtilities::readSInt32(cis); treeNode->area31.top() = d + parentArea.top(); fieldsMask |= (1ull << tfn); break; } case OBF::OsmAndMapIndex_MapDataBox::kBottomFieldNumber: { const auto d = ObfReaderUtilities::readSInt32(cis); treeNode->area31.bottom() = d + parentArea.bottom(); fieldsMask |= (1ull << tfn); break; } case OBF::OsmAndMapIndex_MapDataBox::kShiftToMapDataFieldNumber: { const auto offset = ObfReaderUtilities::readBigEndianInt(cis); treeNode->dataOffset = offset + treeNode->offset; fieldsMask |= (1ull << tfn); break; } case OBF::OsmAndMapIndex_MapDataBox::kOceanFieldNumber: { gpb::uint32 value; cis->ReadVarint32(&value); treeNode->surfaceType = (value != 0) ? MapSurfaceType::FullWater : MapSurfaceType::FullLand; assert( (treeNode->surfaceType != MapSurfaceType::FullWater) || (treeNode->surfaceType == MapSurfaceType::FullWater && section->isBasemapWithCoastlines)); fieldsMask |= (1ull << tfn); break; } case OBF::OsmAndMapIndex_MapDataBox::kBoxesFieldNumber: { if (!kBoxesFieldNumberProcessed) { treeNode->hasChildrenDataBoxes = true; treeNode->firstDataBoxInnerOffset = tagPos - treeNode->offset; kBoxesFieldNumberProcessed = true; if (fieldsMask == safeToSkipFieldsMask) { cis->Skip(cis->BytesUntilLimit()); return; } } ObfReaderUtilities::skipUnknownField(cis, tag); fieldsMask |= (1ull << tfn); break; } default: ObfReaderUtilities::skipUnknownField(cis, tag); break; } } }
void OsmAnd::ObfMapSectionReader_P::readMapLevelHeader( const ObfReader_P& reader, const std::shared_ptr<ObfMapSectionLevel>& level) { const auto cis = reader.getCodedInputStream().get(); uint64_t fieldsMask = 0u; const auto safeToSkipFieldsMask = (1ull << OBF::OsmAndMapIndex_MapRootLevel::kMaxZoomFieldNumber) | (1ull << OBF::OsmAndMapIndex_MapRootLevel::kMinZoomFieldNumber) | (1ull << OBF::OsmAndMapIndex_MapRootLevel::kLeftFieldNumber) | (1ull << OBF::OsmAndMapIndex_MapRootLevel::kRightFieldNumber) | (1ull << OBF::OsmAndMapIndex_MapRootLevel::kTopFieldNumber) | (1ull << OBF::OsmAndMapIndex_MapRootLevel::kBottomFieldNumber); bool kBoxesFieldNumberProcessed = false; for (;;) { const auto tagPos = cis->CurrentPosition(); const auto tag = cis->ReadTag(); const auto tfn = gpb::internal::WireFormatLite::GetTagFieldNumber(tag); switch (tfn) { case 0: if (!ObfReaderUtilities::reachedDataEnd(cis)) return; return; case OBF::OsmAndMapIndex_MapRootLevel::kMaxZoomFieldNumber: cis->ReadVarint32(reinterpret_cast<gpb::uint32*>(&level->maxZoom)); fieldsMask |= (1ull << tfn); break; case OBF::OsmAndMapIndex_MapRootLevel::kMinZoomFieldNumber: cis->ReadVarint32(reinterpret_cast<gpb::uint32*>(&level->minZoom)); fieldsMask |= (1ull << tfn); break; case OBF::OsmAndMapIndex_MapRootLevel::kLeftFieldNumber: cis->ReadVarint32(reinterpret_cast<gpb::uint32*>(&level->area31.left())); fieldsMask |= (1ull << tfn); break; case OBF::OsmAndMapIndex_MapRootLevel::kRightFieldNumber: cis->ReadVarint32(reinterpret_cast<gpb::uint32*>(&level->area31.right())); fieldsMask |= (1ull << tfn); break; case OBF::OsmAndMapIndex_MapRootLevel::kTopFieldNumber: cis->ReadVarint32(reinterpret_cast<gpb::uint32*>(&level->area31.top())); fieldsMask |= (1ull << tfn); break; case OBF::OsmAndMapIndex_MapRootLevel::kBottomFieldNumber: cis->ReadVarint32(reinterpret_cast<gpb::uint32*>(&level->area31.bottom())); fieldsMask |= (1ull << tfn); break; case OBF::OsmAndMapIndex_MapRootLevel::kBoxesFieldNumber: if (!kBoxesFieldNumberProcessed) { level->firstDataBoxInnerOffset = tagPos - level->offset; kBoxesFieldNumberProcessed = true; if (fieldsMask == safeToSkipFieldsMask) { cis->Skip(cis->BytesUntilLimit()); return; } } ObfReaderUtilities::skipUnknownField(cis, tag); fieldsMask |= (1ull << tfn); 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, 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 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; } }
void OsmAnd::ObfRoutingSectionReader_P::readSubsectionHeader( const std::unique_ptr<ObfReader_P>& reader, const std::shared_ptr<ObfRoutingSubsectionInfo>& subsection, const std::shared_ptr<ObfRoutingSubsectionInfo>& parent, uint32_t depth /*= std::numeric_limits<uint32_t>::max()*/) { auto shouldReadSubsections = (depth > 0); auto cis = reader->_codedInputStream.get(); for(;;) { auto lastPos = cis->CurrentPosition(); auto tag = cis->ReadTag(); switch(gpb::internal::WireFormatLite::GetTagFieldNumber(tag)) { case 0: return; case OBF::OsmAndRoutingIndex_RouteDataBox::kLeftFieldNumber: { auto dleft = ObfReaderUtilities::readSInt32(cis); subsection->_area31.left = dleft + (parent ? parent->_area31.left : 0); } break; case OBF::OsmAndRoutingIndex_RouteDataBox::kRightFieldNumber: { auto dright = ObfReaderUtilities::readSInt32(cis); subsection->_area31.right = dright + (parent ? parent->_area31.right : 0); } break; case OBF::OsmAndRoutingIndex_RouteDataBox::kTopFieldNumber: { auto dtop = ObfReaderUtilities::readSInt32(cis); subsection->_area31.top = dtop + (parent ? parent->_area31.top : 0); } break; case OBF::OsmAndRoutingIndex_RouteDataBox::kBottomFieldNumber: { auto dbottom = ObfReaderUtilities::readSInt32(cis); subsection->_area31.bottom = dbottom + (parent ? parent->_area31.bottom : 0); } break; case OBF::OsmAndRoutingIndex_RouteDataBox::kShiftToDataFieldNumber: { subsection->_dataOffset = ObfReaderUtilities::readBigEndianInt(cis); // In case we have data, we must read all subsections shouldReadSubsections = true; } break; case OBF::OsmAndRoutingIndex_RouteDataBox::kBoxesFieldNumber: { if(subsection->_subsectionsOffset == 0) subsection->_subsectionsOffset = lastPos; if(!shouldReadSubsections) { cis->Skip(cis->BytesUntilLimit()); break; } const std::shared_ptr<ObfRoutingSubsectionInfo> childSubsection(new ObfRoutingSubsectionInfo(subsection)); childSubsection->_length = ObfReaderUtilities::readBigEndianInt(cis); childSubsection->_offset = cis->CurrentPosition(); auto oldLimit = cis->PushLimit(childSubsection->_length); readSubsectionHeader(reader, childSubsection, subsection, depth - 1); cis->PopLimit(oldLimit); subsection->_subsections.push_back(qMove(childSubsection)); } break; default: ObfReaderUtilities::skipUnknownField(cis, tag); break; } } }
void OsmAnd::ObfRoutingSectionReader_P::read( const std::unique_ptr<ObfReader_P>& reader, const std::shared_ptr<ObfRoutingSectionInfo>& section ) { auto cis = reader->_codedInputStream.get(); uint32_t routeEncodingRuleId = 1; for(;;) { auto tag = cis->ReadTag(); auto tfn = gpb::internal::WireFormatLite::GetTagFieldNumber(tag); switch(tfn) { case 0: return; case OBF::OsmAndRoutingIndex::kNameFieldNumber: ObfReaderUtilities::readQString(cis, section->_name); break; case OBF::OsmAndRoutingIndex::kRulesFieldNumber: { gpb::uint32 length; cis->ReadVarint32(&length); auto oldLimit = cis->PushLimit(length); const std::shared_ptr<ObfRoutingSectionInfo_P::EncodingRule> encodingRule(new ObfRoutingSectionInfo_P::EncodingRule()); encodingRule->_id = routeEncodingRuleId++; readEncodingRule(reader, section, encodingRule); cis->PopLimit(oldLimit); while((unsigned)section->_d->_encodingRules.size() < encodingRule->_id) section->_d->_encodingRules.push_back(qMove(std::shared_ptr<ObfRoutingSectionInfo_P::EncodingRule>())); section->_d->_encodingRules.push_back(qMove(encodingRule)); } break; case OBF::OsmAndRoutingIndex::kRootBoxesFieldNumber: case OBF::OsmAndRoutingIndex::kBasemapBoxesFieldNumber: { const std::shared_ptr<ObfRoutingSubsectionInfo> subsection(new ObfRoutingSubsectionInfo(section)); subsection->_length = ObfReaderUtilities::readBigEndianInt(cis); subsection->_offset = cis->CurrentPosition(); auto oldLimit = cis->PushLimit(subsection->_length); readSubsectionHeader(reader, subsection, nullptr, 0); cis->PopLimit(oldLimit); if(tfn == OBF::OsmAndRoutingIndex::kRootBoxesFieldNumber) section->_subsections.push_back(qMove(subsection)); else section->_baseSubsections.push_back(qMove(subsection)); } break; case OBF::OsmAndRoutingIndex::kBorderBoxFieldNumber: case OBF::OsmAndRoutingIndex::kBaseBorderBoxFieldNumber: { auto length = ObfReaderUtilities::readBigEndianInt(cis); auto offset = cis->CurrentPosition(); if(tfn == OBF::OsmAndRoutingIndex::kBorderBoxFieldNumber) { section->_d->_borderBoxLength = length; section->_d->_borderBoxOffset = offset; } else { section->_d->_baseBorderBoxLength = length; section->_d->_baseBorderBoxOffset = offset; } cis->Skip(length); } break; case OBF::OsmAndRoutingIndex::kBlocksFieldNumber: cis->Skip(cis->BytesUntilLimit()); break; default: ObfReaderUtilities::skipUnknownField(cis, tag); break; } } }