OsmAnd/Osmand-kernel/osmand/src/binaryRead.cpp

879 lines
26 KiB
C++
Raw Normal View History

2011-10-28 16:01:18 +02:00
#ifndef _OSMAND_BINARY_READ
#define _OSMAND_BINARY_READ
2012-05-01 01:43:09 +02:00
#include "binaryRead.h"
2012-05-01 20:49:45 +02:00
#include <algorithm>
2011-10-28 16:01:00 +02:00
#include "google/protobuf/wire_format_lite.h"
2012-05-01 20:49:45 +02:00
#include "google/protobuf/io/zero_copy_stream_impl.h"
2011-10-28 16:01:00 +02:00
#include "google/protobuf/wire_format_lite.cc"
#include "proto/osmand_odb.pb.h"
2012-05-01 20:49:45 +02:00
#include "osmand_log.h"
2011-10-28 16:01:00 +02:00
2012-05-01 20:49:45 +02:00
using namespace std;
2011-10-29 16:57:27 +02:00
#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
2012-05-01 20:49:45 +02:00
using google::protobuf::io::CodedInputStream;
using google::protobuf::io::FileInputStream;
using google::protobuf::internal::WireFormatLite;
//using namespace google::protobuf::internal;
2011-10-28 16:01:00 +02:00
2012-05-01 20:49:45 +02:00
std::map< std::string, BinaryMapFile* > openFiles;
2011-10-28 16:01:00 +02:00
2012-05-01 20:49:45 +02:00
inline bool readInt(CodedInputStream* input, uint32* sz ){
2011-10-28 16:01:00 +02:00
uint8 buf[4];
2011-10-29 16:57:27 +02:00
if (!input->ReadRaw(buf, 4)) {
2011-10-28 16:01:00 +02:00
return false;
}
*sz = ((buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + (buf[3] << 0));
return true;
}
2012-05-01 20:49:45 +02:00
bool skipFixed32(CodedInputStream* input) {
2011-10-28 16:01:00 +02:00
uint32 sz;
2011-10-29 16:57:27 +02:00
if (!readInt(input, &sz)) {
2011-10-28 16:01:00 +02:00
return false;
}
return input->Skip(sz);
}
2012-05-01 20:49:45 +02:00
bool skipUnknownFields(CodedInputStream* input, int tag) {
2011-10-28 16:56:27 +02:00
if (WireFormatLite::GetTagWireType(tag) == WireFormatLite::WIRETYPE_FIXED32_LENGTH_DELIMITED) {
if (!skipFixed32(input)) {
return false;
}
2011-10-29 16:57:27 +02:00
} else if (!WireFormatLite::SkipField(input, tag)) {
2011-10-28 16:56:27 +02:00
return false;
}
return true;
}
2011-10-28 16:01:00 +02:00
2011-10-29 16:57:27 +02:00
2012-05-01 20:49:45 +02:00
bool readMapTreeBounds(CodedInputStream* input, MapTreeBounds* tree, MapRoot* root) {
2011-10-29 16:57:27 +02:00
int init = 0;
int tag;
2012-04-17 23:56:41 +02:00
int32 si;
2011-10-29 16:57:27 +02:00
while ((tag = input->ReadTag()) != 0) {
switch (WireFormatLite::GetTagFieldNumber(tag)) {
2012-04-17 23:56:41 +02:00
case OsmAndMapIndex_MapDataBox::kLeftFieldNumber: {
DO_((WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_SINT32>(input, &si)));
tree->left = si + root->left;
break;
}
case OsmAndMapIndex_MapDataBox::kRightFieldNumber: {
DO_((WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_SINT32>(input, &si)));
tree->right = si + root->right;
2011-10-29 16:57:27 +02:00
break;
}
2012-04-17 23:56:41 +02:00
case OsmAndMapIndex_MapDataBox::kTopFieldNumber: {
DO_((WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_SINT32>(input, &si)));
tree->top = si + root->top;
2011-10-29 16:57:27 +02:00
break;
}
2012-04-17 23:56:41 +02:00
case OsmAndMapIndex_MapDataBox::kBottomFieldNumber: {
DO_((WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_SINT32>(input, &si)));
tree->bottom = si + root->bottom;
2011-10-29 16:57:27 +02:00
break;
}
2012-04-17 23:56:41 +02:00
case OsmAndMapIndex_MapDataBox::kOceanFieldNumber: {
DO_((WireFormatLite::ReadPrimitive<bool, WireFormatLite::TYPE_BOOL>(input, &tree->ocean)));
2011-10-29 16:57:27 +02:00
break;
}
default: {
if (WireFormatLite::GetTagWireType(tag) == WireFormatLite::WIRETYPE_END_GROUP) {
return true;
}
if (!skipUnknownFields(input, tag)) {
return false;
}
break;
}
}
if (init == 0xf) {
return true;
}
}
return true;
}
2012-05-01 20:49:45 +02:00
bool readMapLevel(CodedInputStream* input, MapRoot* root) {
2011-10-29 16:57:27 +02:00
int tag;
2012-04-17 23:56:41 +02:00
int si;
2011-10-29 16:57:27 +02:00
while ((tag = input->ReadTag()) != 0) {
switch (WireFormatLite::GetTagFieldNumber(tag)) {
2012-04-17 23:56:41 +02:00
case OsmAndMapIndex_MapRootLevel::kMaxZoomFieldNumber: {
2011-10-29 16:57:27 +02:00
DO_((WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_INT32>(input, &root->maxZoom)));
break;
}
2012-04-17 23:56:41 +02:00
case OsmAndMapIndex_MapRootLevel::kMinZoomFieldNumber: {
2011-10-29 16:57:27 +02:00
DO_((WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_INT32>(input, &root->minZoom)));
break;
}
2012-04-17 23:56:41 +02:00
case OsmAndMapIndex_MapRootLevel::kBottomFieldNumber: {
DO_((WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_INT32>(input, &si)));
root->bottom = si;
2011-10-29 16:57:27 +02:00
break;
}
2012-04-17 23:56:41 +02:00
case OsmAndMapIndex_MapRootLevel::kTopFieldNumber: {
DO_((WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_INT32>(input, &si)));
root->top = si;
2011-10-29 16:57:27 +02:00
break;
}
2012-04-17 23:56:41 +02:00
case OsmAndMapIndex_MapRootLevel::kLeftFieldNumber: {
DO_((WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_INT32>(input, &si)));
root->left = si;
2011-10-29 16:57:27 +02:00
break;
}
2012-04-17 23:56:41 +02:00
case OsmAndMapIndex_MapRootLevel::kRightFieldNumber: {
DO_((WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_INT32>(input, &si)));
root->right = si;
2011-10-29 16:57:27 +02:00
break;
}
2012-04-17 23:56:41 +02:00
case OsmAndMapIndex_MapRootLevel::kBoxesFieldNumber: {
MapTreeBounds bounds;
2012-04-18 23:26:57 +02:00
readInt(input, &bounds.length);
bounds.filePointer = input->getTotalBytesRead();
int oldLimit = input->PushLimit(bounds.length);
2012-04-17 23:56:41 +02:00
readMapTreeBounds(input, &bounds, root);
root->bounds.push_back(bounds);
2011-10-29 16:57:27 +02:00
input->Skip(input->BytesUntilLimit());
input->PopLimit(oldLimit);
2012-04-17 23:56:41 +02:00
break;
}
case OsmAndMapIndex_MapRootLevel::kBlocksFieldNumber: {
input->Skip(input->BytesUntilLimit());
2011-10-29 16:57:27 +02:00
break;
}
default: {
if (WireFormatLite::GetTagWireType(tag) == WireFormatLite::WIRETYPE_END_GROUP) {
return true;
}
if (!skipUnknownFields(input, tag)) {
return false;
}
break;
}
}
}
return true;
}
2012-05-01 20:49:45 +02:00
bool readMapEncodingRule(CodedInputStream* input, MapIndex* index, uint32 id) {
2011-10-29 16:57:27 +02:00
int tag;
std::string tagS;
std::string value;
uint32 type = 0;
while ((tag = input->ReadTag()) != 0) {
switch (WireFormatLite::GetTagFieldNumber(tag)) {
2012-04-17 23:56:41 +02:00
case OsmAndMapIndex_MapEncodingRule::kValueFieldNumber: {
2011-10-29 16:57:27 +02:00
DO_((WireFormatLite::ReadString(input, &value)));
break;
}
2012-04-17 23:56:41 +02:00
case OsmAndMapIndex_MapEncodingRule::kTagFieldNumber: {
2011-10-29 16:57:27 +02:00
DO_((WireFormatLite::ReadString(input, &tagS)));
break;
}
2012-04-17 23:56:41 +02:00
case OsmAndMapIndex_MapEncodingRule::kTypeFieldNumber: {
2011-10-29 16:57:27 +02:00
DO_((WireFormatLite::ReadPrimitive<uint32, WireFormatLite::TYPE_UINT32>(input, &type)));
break;
}
2012-04-17 23:56:41 +02:00
case OsmAndMapIndex_MapEncodingRule::kIdFieldNumber: {
DO_((WireFormatLite::ReadPrimitive<uint32, WireFormatLite::TYPE_UINT32>(input, &id)));
2011-10-29 16:57:27 +02:00
break;
}
default: {
if (WireFormatLite::GetTagWireType(tag) == WireFormatLite::WIRETYPE_END_GROUP) {
return true;
}
if (!skipUnknownFields(input, tag)) {
return false;
}
break;
}
}
}
// Special case for check to not replace primary with primary_link
2012-04-17 23:56:41 +02:00
index->initMapEncodingRule(type, id, tagS, value);
2011-10-29 16:57:27 +02:00
return true;
}
2012-05-01 20:49:45 +02:00
bool readMapIndex(CodedInputStream* input, MapIndex* mapIndex) {
2011-10-29 16:57:27 +02:00
uint32 tag;
2012-04-17 23:56:41 +02:00
uint32 defaultId = 1;
2011-10-29 16:57:27 +02:00
while ((tag = input->ReadTag()) != 0) {
switch (WireFormatLite::GetTagFieldNumber(tag)) {
case OsmAndMapIndex::kNameFieldNumber: {
DO_((WireFormatLite::ReadString(input, &mapIndex->name)));
break;
}
case OsmAndMapIndex::kRulesFieldNumber: {
int len;
WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_INT32>(input, &len);
int oldLimit = input->PushLimit(len);
2012-04-17 23:56:41 +02:00
readMapEncodingRule(input, mapIndex, defaultId++);
2011-10-29 16:57:27 +02:00
input->PopLimit(oldLimit);
break;
}
case OsmAndMapIndex::kLevelsFieldNumber: {
MapRoot mapLevel;
readInt(input, &mapLevel.length);
mapLevel.filePointer = input->getTotalBytesRead();
int oldLimit = input->PushLimit(mapLevel.length);
readMapLevel(input, &mapLevel);
input->PopLimit(oldLimit);
input->Seek(mapLevel.filePointer + mapLevel.length);
mapIndex->levels.push_back(mapLevel);
break;
}
default: {
if (WireFormatLite::GetTagWireType(tag) == WireFormatLite::WIRETYPE_END_GROUP) {
return true;
}
if (!skipUnknownFields(input, tag)) {
return false;
}
break;
}
}
}
2012-04-17 23:56:41 +02:00
mapIndex->finishInitializingTags();
2011-10-29 16:57:27 +02:00
return true;
}
2011-10-28 16:56:27 +02:00
//display google::protobuf::internal::WireFormatLite::GetTagWireType(tag)
// display google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)
2012-05-01 20:49:45 +02:00
bool initMapStructure(CodedInputStream* input, BinaryMapFile* file) {
2011-10-28 16:01:00 +02:00
uint32 tag;
uint32 versionConfirm = -2;
while ((tag = input->ReadTag()) != 0) {
switch (WireFormatLite::GetTagFieldNumber(tag)) {
2011-10-28 16:56:27 +02:00
// required uint32 version = 1;
case OsmAndStructure::kVersionFieldNumber: {
2012-05-02 00:43:51 +02:00
DO_((WireFormatLite::ReadPrimitive<uint32, WireFormatLite::TYPE_UINT32>(input, &file->version)));
break;
}
case OsmAndStructure::kDateCreatedFieldNumber: {
DO_((WireFormatLite::ReadPrimitive<uint64, WireFormatLite::TYPE_UINT64>(input, &file->dateCreated)));
2011-10-28 16:56:27 +02:00
break;
}
2011-10-29 16:57:27 +02:00
case OsmAndStructure::kMapIndexFieldNumber: {
MapIndex mapIndex;
readInt(input, &mapIndex.length);
mapIndex.filePointer = input->getTotalBytesRead();
int oldLimit = input->PushLimit(mapIndex.length);
readMapIndex(input, &mapIndex);
input->PopLimit(oldLimit);
input->Seek(mapIndex.filePointer + mapIndex.length);
file->mapIndexes.push_back(mapIndex);
file->indexes.push_back(&file->mapIndexes.back());
2012-04-28 18:37:20 +02:00
file->basemap = file->basemap || mapIndex.name.find("basemap") != string::npos;
2011-10-29 16:57:27 +02:00
break;
}
2011-10-28 16:56:27 +02:00
case OsmAndStructure::kVersionConfirmFieldNumber: {
DO_((WireFormatLite::ReadPrimitive<uint32, WireFormatLite::TYPE_UINT32>(input, &versionConfirm)));
break;
}
default: {
if (WireFormatLite::GetTagWireType(tag) == WireFormatLite::WIRETYPE_END_GROUP) {
return true;
2011-10-28 16:01:00 +02:00
}
2011-10-28 16:56:27 +02:00
if (!skipUnknownFields(input, tag)) {
return false;
2011-10-28 16:01:00 +02:00
}
2011-10-28 16:56:27 +02:00
break;
}
2011-10-28 16:01:00 +02:00
}
}
2012-05-02 00:43:51 +02:00
if (file->version != versionConfirm) {
2012-04-30 11:30:04 +02:00
osmand_log_print(LOG_ERROR, "Corrupted file. It should be ended as it starts with version");
2011-10-28 16:01:00 +02:00
return false;
}
2012-05-02 00:43:51 +02:00
if (file->version != MAP_VERSION) {
2012-04-30 11:30:04 +02:00
osmand_log_print(LOG_ERROR, "Version of the file is not supported.");
2012-04-17 23:56:41 +02:00
return false;
}
2011-10-28 16:01:00 +02:00
return true;
}
2011-10-29 16:57:27 +02:00
2012-05-01 20:49:45 +02:00
bool readStringTable(CodedInputStream* input, std::vector<std::string>& list) {
2011-10-29 16:57:27 +02:00
uint32 tag;
while ((tag = input->ReadTag()) != 0) {
switch (WireFormatLite::GetTagFieldNumber(tag)) {
case StringTable::kSFieldNumber: {
std::string s;
WireFormatLite::ReadString(input, &s);
list.push_back(s);
break;
}
default: {
if (WireFormatLite::GetTagWireType(tag) == WireFormatLite::WIRETYPE_END_GROUP) {
return false;
}
if (!skipUnknownFields(input, tag)) {
return false;
}
break;
}
}
}
return true;
}
static const int SHIFT_COORDINATES = 5;
static const int MASK_TO_READ = ~((1 << SHIFT_COORDINATES) - 1);
2012-04-17 23:56:41 +02:00
bool acceptTypes(SearchQuery* req, std::vector<tag_value>& types, MapIndex* root) {
RenderingRuleSearchRequest* r = req->req;
bool accept = true;
for (std::vector<tag_value>::iterator type = types.begin(); type != types.end(); type++) {
for (int i = 1; i <= 3; i++) {
r->setIntFilter(r->props()->R_MINZOOM, req->zoom);
r->setStringFilter(r->props()->R_TAG, type->first);
r->setStringFilter(r->props()->R_VALUE, type->second);
if (r->search(i, false)) {
return true;
}
}
r->setStringFilter(r->props()->R_TAG, type->first);
r->setStringFilter(r->props()->R_VALUE, type->second);
if (r->search(RenderingRulesStorage::TEXT_RULES, false)) {
return true;
}
}
2012-05-09 23:53:37 +02:00
2012-04-17 23:56:41 +02:00
return false;
}
2012-05-01 20:49:45 +02:00
MapDataObject* readMapDataObject(CodedInputStream* input, MapTreeBounds* tree, SearchQuery* req,
2011-10-29 16:57:27 +02:00
MapIndex* root) {
2012-04-18 23:26:57 +02:00
uint32 tag = WireFormatLite::GetTagFieldNumber(input->ReadTag());
2012-04-17 23:56:41 +02:00
bool area = MapData::kAreaCoordinatesFieldNumber == tag;
if(!area && MapData::kCoordinatesFieldNumber != tag) {
2011-10-29 16:57:27 +02:00
return NULL;
}
req->cacheCoordinates.clear();
uint32 size;
input->ReadVarint32(&size);
int old = input->PushLimit(size);
2012-04-17 23:56:41 +02:00
int px = tree->left & MASK_TO_READ;
int py = tree->top & MASK_TO_READ;
2011-10-29 16:57:27 +02:00
bool contains = false;
int64 id = 0;
2011-10-29 16:57:27 +02:00
int minX = INT_MAX;
int maxX = 0;
int minY = INT_MAX;
int maxY = 0;
req->numberOfVisitedObjects++;
int x;
int y;
while (input->BytesUntilLimit() > 0) {
if (!WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_SINT32>(input, &x)) {
return NULL;
}
if (!WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_SINT32>(input, &y)) {
return NULL;
}
x = (x << SHIFT_COORDINATES) + px;
y = (y << SHIFT_COORDINATES) + py;
req->cacheCoordinates.push_back(std::pair<int, int>(x, y));
px = x;
py = y;
if (!contains && req->left <= x && req->right >= x && req->top <= y && req->bottom >= y) {
contains = true;
}
if (!contains) {
2012-04-30 15:58:02 +02:00
minX = std::min(minX, x);
maxX = std::max(maxX, x);
minY = std::min(minY, y);
maxY = std::max(maxY, y);
2011-10-29 16:57:27 +02:00
}
}
if (!contains) {
if (maxX >= req->left && minX <= req->right && minY <= req->bottom && maxY >= req->top) {
contains = true;
}
}
input->PopLimit(old);
if (!contains) {
return NULL;
}
// READ types
2012-04-30 15:58:02 +02:00
std::vector< coordinates > innercoordinates;
std::vector< tag_value > additionalTypes;
std::vector< tag_value > types;
HMAP::hash_map< std::string, unsigned int> stringIds;
2012-04-17 23:56:41 +02:00
bool loop = true;
while (loop) {
uint32 t = input->ReadTag();
switch (WireFormatLite::GetTagFieldNumber(t)) {
case 0:
loop = false;
break;
case MapData::kPolygonInnerCoordinatesFieldNumber: {
coordinates polygon;
px = tree->left & MASK_TO_READ;
py = tree->top & MASK_TO_READ;
input->ReadVarint32(&size);
old = input->PushLimit(size);
while (input->BytesUntilLimit() > 0) {
WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_SINT32>(input, &x);
WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_SINT32>(input, &y);
x = (x << SHIFT_COORDINATES) + px;
y = (y << SHIFT_COORDINATES) + py;
polygon.push_back(std::pair<int, int>(x, y));
px = x;
py = y;
2011-10-29 16:57:27 +02:00
}
2012-04-17 23:56:41 +02:00
input->PopLimit(old);
innercoordinates.push_back(polygon);
break;
}
case MapData::kAdditionalTypesFieldNumber: {
input->ReadVarint32(&size);
old = input->PushLimit(size);
while (input->BytesUntilLimit() > 0) {
WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_INT32>(input, &x);
if (root->decodingRules.find(x) != root->decodingRules.end()) {
tag_value t = root->decodingRules[x];
additionalTypes.push_back(t);
}
}
input->PopLimit(old);
2011-10-29 16:57:27 +02:00
break;
2012-04-17 23:56:41 +02:00
}
case MapData::kTypesFieldNumber: {
input->ReadVarint32(&size);
old = input->PushLimit(size);
while (input->BytesUntilLimit() > 0) {
WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_INT32>(input, &x);
if (root->decodingRules.find(x) != root->decodingRules.end()) {
tag_value t = root->decodingRules[x];
types.push_back(t);
}
}
input->PopLimit(old);
bool acceptTps = acceptTypes(req, types, root);
if (!acceptTps) {
return NULL;
}
2011-10-29 16:57:27 +02:00
break;
2012-04-17 23:56:41 +02:00
}
case MapData::kIdFieldNumber:
WireFormatLite::ReadPrimitive<int64, WireFormatLite::TYPE_SINT64>(input, &id);
break;
case MapData::kStringNamesFieldNumber:
input->ReadVarint32(&size);
old = input->PushLimit(size);
while (input->BytesUntilLimit() > 0) {
WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_INT32>(input, &x);
WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_INT32>(input, &y);
if (root->decodingRules.find(x) != root->decodingRules.end()) {
tag_value t = root->decodingRules[x];
stringIds[t.first] = y;
}
}
input->PopLimit(old);
2011-10-29 16:57:27 +02:00
break;
default: {
2012-04-17 23:56:41 +02:00
if (WireFormatLite::GetTagWireType(t) == WireFormatLite::WIRETYPE_END_GROUP) {
2012-05-12 18:13:29 +02:00
return NULL;
2011-10-29 16:57:27 +02:00
}
2012-04-17 23:56:41 +02:00
if (!skipUnknownFields(input, t)) {
2012-05-12 18:13:29 +02:00
return NULL;
2011-10-29 16:57:27 +02:00
}
break;
}
}
}
2012-04-17 23:56:41 +02:00
req->numberOfAcceptedObjects++;
MapDataObject* dataObject = new MapDataObject();
dataObject->points = req->cacheCoordinates;
dataObject->additionalTypes = additionalTypes;
dataObject->types = types;
dataObject->id = id;
dataObject->stringIds = stringIds;
dataObject->polygonInnerCoordinates = innercoordinates;
2011-10-29 16:57:27 +02:00
return dataObject;
}
2012-04-17 23:56:41 +02:00
2012-05-01 20:49:45 +02:00
bool searchMapTreeBounds(CodedInputStream* input, MapTreeBounds* current, MapTreeBounds* parent,
2012-04-17 23:56:41 +02:00
SearchQuery* req, std::vector<MapTreeBounds>* foundSubtrees) {
2011-10-29 16:57:27 +02:00
int init = 0;
int tag;
2012-04-17 23:56:41 +02:00
int si;
2011-10-29 16:57:27 +02:00
req->numberOfReadSubtrees++;
while ((tag = input->ReadTag()) != 0) {
2012-05-04 13:13:00 +02:00
if (req->publisher->isCancelled()) {
2011-10-29 16:57:27 +02:00
return false;
}
if (init == 0xf) {
init = 0;
// coordinates are init
2012-04-17 23:56:41 +02:00
if (current->right < req->left || current->left > req->right || current->top > req->bottom || current->bottom < req->top) {
2011-10-29 16:57:27 +02:00
return false;
} else {
req->numberOfAcceptedSubtrees++;
}
}
switch (WireFormatLite::GetTagFieldNumber(tag)) {
// required uint32 version = 1;
2012-04-17 23:56:41 +02:00
case OsmAndMapIndex_MapDataBox::kLeftFieldNumber: {
DO_((WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_SINT32>(input, &si)));
current->left = si + parent->left;
2011-10-29 16:57:27 +02:00
init |= 1;
break;
}
2012-04-17 23:56:41 +02:00
case OsmAndMapIndex_MapDataBox::kRightFieldNumber: {
DO_((WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_SINT32>(input, &si)));
current->right = si + parent->right;
2011-10-29 16:57:27 +02:00
init |= 2;
break;
}
2012-04-17 23:56:41 +02:00
case OsmAndMapIndex_MapDataBox::kTopFieldNumber: {
DO_((WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_SINT32>(input, &si)));
current->top = si + parent->top;
2011-10-29 16:57:27 +02:00
init |= 4;
break;
}
2012-04-17 23:56:41 +02:00
case OsmAndMapIndex_MapDataBox::kBottomFieldNumber : {
DO_((WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_SINT32>(input, &si)));
current->bottom = si + parent->bottom;
2011-10-29 16:57:27 +02:00
init |= 8;
break;
}
2012-04-17 23:56:41 +02:00
case OsmAndMapIndex_MapDataBox::kShiftToMapDataFieldNumber : {
readInt(input, &current->mapDataBlock);
current->mapDataBlock += current->filePointer;
foundSubtrees->push_back(*current);
break;
}
case OsmAndMapIndex_MapDataBox::kOceanFieldNumber : {
DO_((WireFormatLite::ReadPrimitive<bool, WireFormatLite::TYPE_BOOL>(input, &current->ocean)));
if(current->ocean){
req->ocean = true;
} else {
req->land = true;
2011-10-29 16:57:27 +02:00
}
2012-04-17 23:56:41 +02:00
break;
}
case OsmAndMapIndex_MapDataBox::kBoxesFieldNumber: {
MapTreeBounds* child = new MapTreeBounds();
readInt(input, &child->length);
child->filePointer = input->getTotalBytesRead();
int oldLimit = input->PushLimit(child->length);
2012-04-29 15:43:43 +02:00
if (current->ocean) {
2012-04-17 23:56:41 +02:00
child->ocean = current->ocean;
2011-10-29 16:57:27 +02:00
}
2012-04-17 23:56:41 +02:00
searchMapTreeBounds(input, child, current, req, foundSubtrees);
2011-10-29 16:57:27 +02:00
input->PopLimit(oldLimit);
2012-04-17 23:56:41 +02:00
input->Seek(child->filePointer + child->length);
2012-04-18 23:26:57 +02:00
delete child;
2011-10-29 16:57:27 +02:00
break;
}
2012-04-17 23:56:41 +02:00
default: {
if (WireFormatLite::GetTagWireType(tag) == WireFormatLite::WIRETYPE_END_GROUP) {
return true;
}
if (!skipUnknownFields(input, tag)) {
2011-10-29 16:57:27 +02:00
return false;
}
break;
}
2012-04-17 23:56:41 +02:00
}
}
return true;
}
2012-05-01 20:49:45 +02:00
bool readMapDataBlocks(CodedInputStream* input, SearchQuery* req, MapTreeBounds* tree, MapIndex* root) {
int64 baseId = 0;
2012-04-17 23:56:41 +02:00
int tag;
std::vector< MapDataObject* > results;
while ((tag = input->ReadTag()) != 0) {
2012-05-04 13:13:00 +02:00
if (req->publisher->isCancelled()) {
2012-04-17 23:56:41 +02:00
return false;
}
switch (WireFormatLite::GetTagFieldNumber(tag)) {
// required uint32 version = 1;
case MapDataBlock::kBaseIdFieldNumber : {
WireFormatLite::ReadPrimitive<int64, WireFormatLite::TYPE_SINT64>(input, &baseId);
2011-10-29 16:57:27 +02:00
break;
}
2012-04-17 23:56:41 +02:00
case MapDataBlock::kStringTableFieldNumber: {
2011-10-29 16:57:27 +02:00
uint32 length;
2012-04-17 23:56:41 +02:00
DO_((WireFormatLite::ReadPrimitive<uint32, WireFormatLite::TYPE_UINT32>(input, &length)));
2011-10-29 16:57:27 +02:00
int oldLimit = input->PushLimit(length);
2012-04-17 23:56:41 +02:00
if(results.size() > 0) {
2012-04-30 15:58:02 +02:00
std::vector<std::string> stringTable;
2012-04-17 23:56:41 +02:00
readStringTable(input, stringTable);
MapDataObject* o;
for (std::vector<MapDataObject*>::iterator obj = results.begin(); obj != results.end(); obj++) {
if ((*obj)->stringIds.size() > 0) {
2012-04-30 15:58:02 +02:00
HMAP::hash_map<std::string, unsigned int >::iterator val=(*obj)->stringIds.begin();
2012-04-17 23:56:41 +02:00
while(val != (*obj)->stringIds.end()){
2012-04-30 13:33:05 +02:00
(*obj)->objectNames[val->first]=stringTable[val->second];
2012-04-17 23:56:41 +02:00
val++;
}
2011-10-29 16:57:27 +02:00
}
}
}
2012-04-17 23:56:41 +02:00
input->Skip(input->BytesUntilLimit());
input->PopLimit(oldLimit);
2011-10-29 16:57:27 +02:00
break;
2012-04-17 23:56:41 +02:00
}
case MapDataBlock::kDataObjectsFieldNumber: {
uint32 length;
DO_((WireFormatLite::ReadPrimitive<uint32, WireFormatLite::TYPE_UINT32>(input, &length)));
int oldLimit = input->PushLimit(length);
MapDataObject* mapObject = readMapDataObject(input, tree, req, root);
if (mapObject != NULL) {
mapObject->id += baseId;
2012-05-04 13:13:00 +02:00
req->publish(mapObject);
2012-04-17 23:56:41 +02:00
results.push_back(mapObject);
}
input->Skip(input->BytesUntilLimit());
input->PopLimit(oldLimit);
break;
2011-10-29 16:57:27 +02:00
}
default: {
if (WireFormatLite::GetTagWireType(tag) == WireFormatLite::WIRETYPE_END_GROUP) {
return true;
}
if (!skipUnknownFields(input, tag)) {
return false;
}
break;
}
}
}
return true;
}
2012-04-17 23:56:41 +02:00
bool sortTreeBounds (const MapTreeBounds& i,const MapTreeBounds& j) { return (i.mapDataBlock<j.mapDataBlock); }
2011-10-29 16:57:27 +02:00
2012-05-01 20:49:45 +02:00
void searchMapData(CodedInputStream* input, MapRoot* root, MapIndex* ind, SearchQuery* req) {
2011-10-29 16:57:27 +02:00
// search
for (std::vector<MapTreeBounds>::iterator i = root->bounds.begin();
i != root->bounds.end(); i++) {
2012-05-04 13:13:00 +02:00
if (req->publisher->isCancelled()) {
2011-10-29 16:57:27 +02:00
return;
}
if (i->right < req->left || i->left > req->right || i->top > req->bottom || i->bottom < req->top) {
continue;
}
2012-04-30 15:58:02 +02:00
std::vector<MapTreeBounds> foundSubtrees;
2011-10-29 16:57:27 +02:00
input->Seek(i->filePointer);
int oldLimit = input->PushLimit(i->length);
2012-04-30 15:58:02 +02:00
searchMapTreeBounds(input, &(*i), root, req, &foundSubtrees);
2011-10-29 16:57:27 +02:00
input->PopLimit(oldLimit);
2012-04-17 23:56:41 +02:00
2012-04-18 23:26:57 +02:00
2012-04-17 23:56:41 +02:00
sort(foundSubtrees.begin(), foundSubtrees.end(), sortTreeBounds);
uint32 length;
for (std::vector<MapTreeBounds>::iterator tree = foundSubtrees.begin();
tree != foundSubtrees.end(); tree++) {
2012-05-04 13:13:00 +02:00
if (req->publisher->isCancelled()) {
2012-04-17 23:56:41 +02:00
return;
}
input->Seek(tree->mapDataBlock);
2012-04-18 23:26:57 +02:00
WireFormatLite::ReadPrimitive<uint32, WireFormatLite::TYPE_UINT32>(input, &length);
2012-04-17 23:56:41 +02:00
int oldLimit = input->PushLimit(length);
2012-04-30 15:58:02 +02:00
readMapDataBlocks(input, req, &(*tree), ind);
2012-04-17 23:56:41 +02:00
input->PopLimit(oldLimit);
}
2011-10-29 16:57:27 +02:00
}
}
2012-04-28 18:37:20 +02:00
2012-05-01 20:49:45 +02:00
2012-05-09 13:31:58 +02:00
ResultPublisher* searchObjectsForRendering(SearchQuery* q, bool skipDuplicates, std::string msgNothingFound) {
2012-04-30 13:33:05 +02:00
map<std::string, BinaryMapFile*>::iterator i = openFiles.begin();
2012-04-30 15:58:02 +02:00
HMAP::hash_set<long long> ids;
2012-04-28 18:37:20 +02:00
int count = 0;
bool ocean = false;
2012-04-28 21:43:14 +02:00
std::vector<MapDataObject*> basemapResult;
std::vector<MapDataObject*> tempResult;
std::vector<MapDataObject*> coastLines;
std::vector<MapDataObject*> basemapCoastLines;
2012-04-28 18:37:20 +02:00
2012-05-04 13:13:00 +02:00
for (; i != openFiles.end() && !q->publisher->isCancelled(); i++) {
2012-04-28 18:37:20 +02:00
BinaryMapFile* file = i->second;
fseek(file->f, 0, 0);
2012-05-01 20:49:45 +02:00
FileInputStream input(fileno(file->f));
2012-04-28 18:37:20 +02:00
input.SetCloseOnDelete(false);
2012-05-01 20:49:45 +02:00
CodedInputStream cis(&input);
2012-04-28 18:37:20 +02:00
cis.SetTotalBytesLimit(INT_MAX, INT_MAX >> 2);
2012-05-08 00:50:47 +02:00
if (q->req != NULL) {
q->req->clearState();
2012-04-28 18:37:20 +02:00
}
2012-05-04 13:13:00 +02:00
q->publisher->result.clear();
2012-04-30 15:58:02 +02:00
for (std::vector<MapIndex>::iterator mapIndex = file->mapIndexes.begin(); mapIndex != file->mapIndexes.end();
2012-04-28 18:37:20 +02:00
mapIndex++) {
2012-04-30 15:58:02 +02:00
for (std::vector<MapRoot>::iterator mapLevel = mapIndex->levels.begin(); mapLevel != mapIndex->levels.end();
2012-04-28 18:37:20 +02:00
mapLevel++) {
2012-05-04 13:13:00 +02:00
if (q->publisher->isCancelled()) {
2012-04-28 18:37:20 +02:00
break;
}
2012-05-01 20:49:45 +02:00
if (mapLevel->minZoom <= q->zoom && mapLevel->maxZoom >= q->zoom) {
if (mapLevel->right >= q->left && q->right >= mapLevel->left && mapLevel->bottom >= q->top
&& q->bottom >= mapLevel->top) {
2012-04-30 11:30:04 +02:00
osmand_log_print(LOG_INFO, "Search map %s", mapIndex->name.c_str());
2012-05-01 20:49:45 +02:00
searchMapData(&cis, &(*mapLevel), &(*mapIndex), q);
2012-04-28 18:37:20 +02:00
}
2011-10-29 16:57:27 +02:00
}
}
}
2012-05-01 20:49:45 +02:00
if (q->ocean) {
2012-04-29 15:43:43 +02:00
ocean = true;
}
2012-05-04 13:13:00 +02:00
if (!q->publisher->isCancelled()) {
std::vector<MapDataObject*>::iterator r = q->publisher->result.begin();
tempResult.reserve((size_t)(q->publisher->result.size() + tempResult.size()));
for (; r != q->publisher->result.end(); r++) {
2012-04-28 21:43:14 +02:00
// TODO skip duplicates doesn't work correctly with basemap (id < 0?)
if (skipDuplicates && (*r)->id > 0 && false) {
2012-04-28 18:37:20 +02:00
if (ids.find((*r)->id) != ids.end()) {
continue;
}
ids.insert((*r)->id);
}
2012-04-28 21:43:14 +02:00
count++;
if ((*r)->contains("natural", "coastline")) {
if (i->second->isBasemap()) {
basemapCoastLines.push_back(*r);
} else {
coastLines.push_back(*r);
}
2012-04-28 18:37:20 +02:00
} else {
2012-04-28 21:43:14 +02:00
// do not mess coastline and other types
if (i->second->isBasemap()) {
basemapResult.push_back(*r);
} else {
tempResult.push_back(*r);
}
2012-04-28 18:37:20 +02:00
}
}
}
}
2012-05-04 13:13:00 +02:00
// sort results/ analyze coastlines and publish back to publisher
if (q->publisher->isCancelled()) {
2012-04-28 18:37:20 +02:00
deleteObjects(coastLines);
deleteObjects(tempResult);
deleteObjects(basemapCoastLines);
deleteObjects(basemapResult);
} else {
bool addBasemapCoastlines = true;
2012-05-01 20:49:45 +02:00
bool emptyData = q->zoom > BASEMAP_ZOOM && tempResult.empty() && coastLines.empty();
2012-04-28 18:37:20 +02:00
if (!coastLines.empty()) {
2012-05-27 12:18:46 +02:00
bool coastlinesWereAdded = processCoastlines(coastLines, q->left, q->right, q->bottom, q->top, q->zoom,
basemapCoastLines.empty(), true, tempResult);
addBasemapCoastlines = !coastlinesWereAdded || q->zoom <= BASEMAP_ZOOM;
2012-04-28 18:37:20 +02:00
}
if (addBasemapCoastlines) {
addBasemapCoastlines = false;
2012-05-27 12:18:46 +02:00
bool coastlinesWereAdded = processCoastlines(basemapCoastLines, q->left, q->right, q->bottom, q->top, q->zoom,
true, true, tempResult);
addBasemapCoastlines = !coastlinesWereAdded;
2012-04-28 18:37:20 +02:00
}
2012-04-28 21:43:14 +02:00
// processCoastlines always create new objects
deleteObjects(basemapCoastLines);
deleteObjects(coastLines);
2012-04-28 18:37:20 +02:00
if (addBasemapCoastlines) {
MapDataObject* o = new MapDataObject();
2012-05-01 20:49:45 +02:00
o->points.push_back(int_pair(q->left, q->top));
o->points.push_back(int_pair(q->right, q->top));
o->points.push_back(int_pair(q->right, q->bottom));
o->points.push_back(int_pair(q->left, q->bottom));
o->points.push_back(int_pair(q->left, q->top));
2012-04-28 18:37:20 +02:00
if (ocean) {
o->types.push_back(tag_value("natural", "coastline"));
} else {
o->types.push_back(tag_value("natural", "land"));
}
tempResult.push_back(o);
}
if (emptyData) {
// message
// avoid overflow int errors
MapDataObject* o = new MapDataObject();
2012-05-01 20:49:45 +02:00
o->points.push_back(int_pair(q->left + (q->right - q->left) / 2, q->top + (q->bottom - q->top) / 2));
2012-04-28 18:37:20 +02:00
o->types.push_back(tag_value("natural", "coastline"));
2012-05-01 20:49:45 +02:00
o->objectNames["name"] = msgNothingFound;
2012-04-28 18:37:20 +02:00
tempResult.push_back(o);
}
2012-05-01 20:49:45 +02:00
if (q->zoom <= BASEMAP_ZOOM || emptyData) {
2012-04-28 18:37:20 +02:00
tempResult.insert(tempResult.end(), basemapResult.begin(), basemapResult.end());
2012-05-13 16:52:58 +02:00
} else {
deleteObjects(basemapResult);
2012-04-28 18:37:20 +02:00
}
2012-05-04 13:13:00 +02:00
q->publisher->result.clear();
q->publisher->publish(tempResult);
2012-04-30 11:30:04 +02:00
osmand_log_print(LOG_INFO,
2012-04-28 18:37:20 +02:00
"Search : tree - read( %d), accept( %d), objs - visit( %d), accept(%d), in result(%d) ",
2012-05-01 20:49:45 +02:00
q->numberOfReadSubtrees, q->numberOfAcceptedSubtrees, q->numberOfVisitedObjects, q->numberOfAcceptedObjects,
2012-05-04 13:13:00 +02:00
q->publisher->result.size());
2011-10-30 00:57:40 +02:00
}
2012-05-04 13:13:00 +02:00
return q->publisher;
2011-10-29 16:57:27 +02:00
}
2012-05-02 19:35:36 +02:00
bool closeBinaryMapFile(std::string inputName) {
2012-04-28 15:20:51 +02:00
std::map<std::string, BinaryMapFile*>::iterator iterator;
if ((iterator = openFiles.find(inputName)) != openFiles.end()) {
delete iterator->second;
openFiles.erase(iterator);
2012-05-04 13:13:00 +02:00
return true;
2012-04-28 15:20:51 +02:00
}
2012-05-04 13:13:00 +02:00
return false;
2012-04-28 15:20:51 +02:00
}
2012-05-01 09:47:20 +02:00
BinaryMapFile* initBinaryMapFile(std::string inputName) {
2011-10-28 16:01:00 +02:00
GOOGLE_PROTOBUF_VERIFY_VERSION;
std::map<std::string, BinaryMapFile*>::iterator iterator;
if ((iterator = openFiles.find(inputName)) != openFiles.end()) {
delete iterator->second;
openFiles.erase(iterator);
}
FILE* file = fopen(inputName.c_str(), "r");
if (file == NULL) {
2012-04-30 11:30:04 +02:00
osmand_log_print(LOG_ERROR, "File could not be open to read from C : %s", inputName.c_str());
2012-05-01 09:47:20 +02:00
return NULL;
2011-10-28 16:01:00 +02:00
}
BinaryMapFile* mapFile = new BinaryMapFile();
2011-10-29 16:57:27 +02:00
mapFile->f = file;
2012-05-01 20:49:45 +02:00
FileInputStream input(fileno(file));
2011-10-29 16:57:27 +02:00
input.SetCloseOnDelete(false);
2012-05-01 20:49:45 +02:00
CodedInputStream cis(&input);
2011-10-28 16:56:27 +02:00
cis.SetTotalBytesLimit(INT_MAX, INT_MAX >> 2);
2011-10-28 16:01:00 +02:00
if (!initMapStructure(&cis, mapFile)) {
2012-04-30 11:30:04 +02:00
osmand_log_print(LOG_ERROR, "File not initialised : %s", inputName.c_str());
2011-10-28 16:01:00 +02:00
delete mapFile;
2012-05-01 09:47:20 +02:00
return NULL;
2011-10-28 16:01:00 +02:00
}
mapFile->inputName = inputName;
openFiles.insert(std::pair<std::string, BinaryMapFile*>(inputName, mapFile));
2012-05-01 09:47:20 +02:00
return mapFile;
2011-10-28 16:01:00 +02:00
}
2011-10-29 16:57:27 +02:00
#undef DO_
2011-10-28 16:01:18 +02:00
#endif