bool Area::WriteOptimized(const TypeConfig& typeConfig, FileWriter& writer) const { std::vector<Ring>::const_iterator ring=rings.begin(); bool multipleRings=rings.size()>1; // Outer ring writer.WriteTypeId(ring->GetType()->GetAreaId(), typeConfig.GetAreaTypeIdBytes()); if (!ring->featureValueBuffer.Write(writer, multipleRings)) { return false; } if (multipleRings) { writer.WriteNumber((uint32_t)(rings.size()-1)); } if (!writer.Write(ring->nodes)) { return false; } ++ring; // Potential additional rings while (ring!=rings.end()) { writer.WriteTypeId(ring->GetType()->GetAreaId(), typeConfig.GetAreaTypeIdBytes()); if (ring->GetType()->GetAreaId()!=typeIgnore) { if (!ring->featureValueBuffer.Write(writer)) { return false; } } writer.Write(ring->ring); if (!writer.Write(ring->nodes)) { return false; } ++ring; } return !writer.HasError(); }
bool Area::ReadOptimized(const TypeConfig& typeConfig, FileScanner& scanner) { if (!scanner.GetPos(fileOffset)) { return false; } TypeId ringType; bool multipleRings; uint32_t ringCount=1; FeatureValueBuffer featureValueBuffer; scanner.ReadTypeId(ringType, typeConfig.GetAreaTypeIdBytes()); TypeInfoRef type=typeConfig.GetAreaTypeInfo(ringType); featureValueBuffer.SetType(type); if (!featureValueBuffer.Read(scanner, multipleRings)) { return false; } if (multipleRings) { if (!scanner.ReadNumber(ringCount)) { return false; } ringCount++; } rings.resize(ringCount); rings[0].featureValueBuffer=featureValueBuffer; if (ringCount>1) { rings[0].ring=masterRingId; } else { rings[0].ring=outerRingId; } if (!scanner.Read(rings[0].nodes)) { return false; } for (size_t i=1; i<ringCount; i++) { scanner.ReadTypeId(ringType, typeConfig.GetAreaTypeIdBytes()); type=typeConfig.GetAreaTypeInfo(ringType); rings[i].SetType(type); if (rings[i].featureValueBuffer.GetType()->GetAreaId()!=typeIgnore) { if (!rings[i].featureValueBuffer.Read(scanner)) { return false; } } scanner.Read(rings[i].ring); if (!scanner.Read(rings[i].nodes)) { return false; } } return !scanner.HasError(); }
bool AreaAreaIndex::GetIndexCell(const TypeConfig& typeConfig, uint32_t level, FileOffset offset, IndexCache::CacheRef& cacheRef) const { if (!indexCache.GetEntry(offset,cacheRef)) { IndexCache::CacheEntry cacheEntry(offset); cacheRef=indexCache.SetEntry(cacheEntry); if (!scanner.IsOpen()) { if (!scanner.Open(datafilename,FileScanner::LowMemRandom,true)) { log.Error() << "Error while opening '" << scanner.GetFilename() << "' for reading!"; return false; } } scanner.SetPos(offset); // Read offsets of children if not in the bottom level if (level<maxLevel) { for (size_t c=0; c<4; c++) { if (!scanner.ReadNumber(cacheRef->value.children[c])) { log.Error() << "Cannot read index data at offset " << offset << " in file '" << scanner.GetFilename() << "'"; return false; } } } else { for (size_t c=0; c<4; c++) { cacheRef->value.children[c]=0; } } // Now read the way offsets by type in this index entry uint32_t offsetCount; // Areas if (!scanner.ReadNumber(offsetCount)) { log.Error() << "Cannot read index data for level " << level << " at offset " << offset << " in file '" << scanner.GetFilename() << "'"; return false; } cacheRef->value.areas.resize(offsetCount); FileOffset prevOffset=0; for (size_t c=0; c<offsetCount; c++) { if (!scanner.ReadTypeId(cacheRef->value.areas[c].type, typeConfig.GetAreaTypeIdBytes())) { log.Error() << "Cannot read index data for level " << level << " at offset " << offset << " in file '" << scanner.GetFilename() << "'"; return false; } if (!scanner.ReadNumber(cacheRef->value.areas[c].offset)) { log.Error() << "Cannot read index data for level " << level << " at offset " << offset << " in file '" << scanner.GetFilename() << "'"; return false; } cacheRef->value.areas[c].offset+=prevOffset; prevOffset=cacheRef->value.areas[c].offset; } } return true; }