simplification binary map index reader (functionally no changes)
git-svn-id: https://osmand.googlecode.com/svn/trunk@839 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
parent
55dc0e2a76
commit
1d9d4cf8b6
4 changed files with 1216 additions and 1108 deletions
|
@ -13,10 +13,10 @@ import java.util.Locale;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import net.osmand.binary.BinaryMapIndexReader.AddressRegion;
|
||||
import net.osmand.binary.BinaryMapAddressReaderAdapter.AddressRegion;
|
||||
import net.osmand.binary.BinaryMapIndexReader.MapIndex;
|
||||
import net.osmand.binary.BinaryMapIndexReader.MapRoot;
|
||||
import net.osmand.binary.BinaryMapIndexReader.TransportIndex;
|
||||
import net.osmand.binary.BinaryMapTransportReaderAdapter.TransportIndex;
|
||||
import net.osmand.osm.MapUtils;
|
||||
|
||||
import com.google.protobuf.CodedOutputStream;
|
||||
|
|
|
@ -0,0 +1,504 @@
|
|||
package net.osmand.binary;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import net.osmand.data.Building;
|
||||
import net.osmand.data.City;
|
||||
import net.osmand.data.PostCode;
|
||||
import net.osmand.data.Street;
|
||||
import net.osmand.data.City.CityType;
|
||||
import net.osmand.osm.LatLon;
|
||||
import net.osmand.osm.MapUtils;
|
||||
import net.sf.junidecode.Junidecode;
|
||||
|
||||
import com.google.protobuf.CodedInputStreamRAF;
|
||||
import com.google.protobuf.WireFormat;
|
||||
|
||||
public class BinaryMapAddressReaderAdapter {
|
||||
|
||||
public static class AddressRegion extends BinaryIndexPart {
|
||||
String enName;
|
||||
|
||||
int postcodesOffset = -1;
|
||||
int villagesOffset = -1;
|
||||
int citiesOffset = -1;
|
||||
}
|
||||
|
||||
private CodedInputStreamRAF codedIS;
|
||||
private final BinaryMapIndexReader map;
|
||||
|
||||
protected BinaryMapAddressReaderAdapter(BinaryMapIndexReader map){
|
||||
this.codedIS = map.codedIS;
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
private void skipUnknownField(int t) throws IOException {
|
||||
map.skipUnknownField(t);
|
||||
}
|
||||
|
||||
private int readInt() throws IOException {
|
||||
return map.readInt();
|
||||
}
|
||||
|
||||
|
||||
protected void readAddressIndex(AddressRegion region) throws IOException {
|
||||
while(true){
|
||||
int t = codedIS.readTag();
|
||||
int tag = WireFormat.getTagFieldNumber(t);
|
||||
switch (tag) {
|
||||
case 0:
|
||||
return;
|
||||
case OsmandOdb.OsmAndAddressIndex.NAME_FIELD_NUMBER :
|
||||
region.name = codedIS.readString();
|
||||
if(region.enName == null){
|
||||
region.enName = Junidecode.unidecode(region.name);
|
||||
}
|
||||
break;
|
||||
case OsmandOdb.OsmAndAddressIndex.NAME_EN_FIELD_NUMBER :
|
||||
region.enName = codedIS.readString();
|
||||
break;
|
||||
case OsmandOdb.OsmAndAddressIndex.CITIES_FIELD_NUMBER :
|
||||
region.citiesOffset = codedIS.getTotalBytesRead();
|
||||
int length = readInt();
|
||||
codedIS.seek(region.citiesOffset + length + 4);
|
||||
break;
|
||||
case OsmandOdb.OsmAndAddressIndex.VILLAGES_FIELD_NUMBER :
|
||||
region.villagesOffset = codedIS.getTotalBytesRead();
|
||||
length = readInt();
|
||||
codedIS.seek(region.villagesOffset + length + 4);
|
||||
break;
|
||||
case OsmandOdb.OsmAndAddressIndex.POSTCODES_FIELD_NUMBER :
|
||||
region.postcodesOffset = codedIS.getTotalBytesRead();
|
||||
length = readInt();
|
||||
codedIS.seek(region.postcodesOffset + length + 4);
|
||||
break;
|
||||
default:
|
||||
skipUnknownField(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void readCities(List<City> cities, String nameContains, boolean useEn) throws IOException {
|
||||
while(true){
|
||||
int t = codedIS.readTag();
|
||||
int tag = WireFormat.getTagFieldNumber(t);
|
||||
switch (tag) {
|
||||
case 0:
|
||||
return;
|
||||
case OsmandOdb.CitiesIndex.CITIES_FIELD_NUMBER :
|
||||
int offset = codedIS.getTotalBytesRead();
|
||||
int length = codedIS.readRawVarint32();
|
||||
|
||||
int oldLimit = codedIS.pushLimit(length);
|
||||
if(nameContains != null){
|
||||
String name = null;
|
||||
int read = 0;
|
||||
int toRead = useEn ? 3 : 2;
|
||||
int seek = codedIS.getTotalBytesRead();
|
||||
while(read++ < toRead){
|
||||
int ts = codedIS.readTag();
|
||||
int tags = WireFormat.getTagFieldNumber(ts);
|
||||
switch (tags) {
|
||||
case OsmandOdb.CityIndex.NAME_EN_FIELD_NUMBER :
|
||||
name = codedIS.readString();
|
||||
break;
|
||||
case OsmandOdb.CityIndex.NAME_FIELD_NUMBER :
|
||||
name = codedIS.readString();
|
||||
if(useEn){
|
||||
name = Junidecode.unidecode(name);
|
||||
}
|
||||
break;
|
||||
case OsmandOdb.CityIndex.CITY_TYPE_FIELD_NUMBER :
|
||||
codedIS.readUInt32();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(name == null || !name.toLowerCase().contains(nameContains)){
|
||||
codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
|
||||
codedIS.popLimit(oldLimit);
|
||||
break;
|
||||
}
|
||||
codedIS.seek(seek);
|
||||
}
|
||||
|
||||
City c = readCity(null, offset, false);
|
||||
if(c != null){
|
||||
cities.add(c);
|
||||
}
|
||||
codedIS.popLimit(oldLimit);
|
||||
break;
|
||||
default:
|
||||
skipUnknownField(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected PostCode readPostcode(PostCode p, int fileOffset, boolean loadStreets, String postcodeFilter) throws IOException{
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
while(true){
|
||||
int t = codedIS.readTag();
|
||||
int tag = WireFormat.getTagFieldNumber(t);
|
||||
switch (tag) {
|
||||
case 0:
|
||||
p.setLocation(MapUtils.get31LatitudeY(y), MapUtils.get31LongitudeX(x));
|
||||
p.setFileOffset(fileOffset);
|
||||
return p;
|
||||
case OsmandOdb.PostcodeIndex.POSTCODE_FIELD_NUMBER :
|
||||
String name = codedIS.readString();
|
||||
if(postcodeFilter != null && !postcodeFilter.equalsIgnoreCase(name)){
|
||||
codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
|
||||
return null;
|
||||
}
|
||||
if(p == null){
|
||||
p = new PostCode(name);
|
||||
}
|
||||
p.setName(name);
|
||||
break;
|
||||
case OsmandOdb.PostcodeIndex.X_FIELD_NUMBER :
|
||||
x = codedIS.readFixed32();
|
||||
break;
|
||||
case OsmandOdb.PostcodeIndex.Y_FIELD_NUMBER :
|
||||
y = codedIS.readFixed32();
|
||||
break;
|
||||
case OsmandOdb.PostcodeIndex.STREETS_FIELD_NUMBER :
|
||||
int offset = codedIS.getTotalBytesRead();
|
||||
int length = codedIS.readRawVarint32();
|
||||
if(loadStreets){
|
||||
Street s = new Street(null);
|
||||
int oldLimit = codedIS.pushLimit(length);
|
||||
s.setFileOffset(offset);
|
||||
readStreet(s, true, x >> 7, y >> 7, p.getName());
|
||||
p.registerStreet(s, false);
|
||||
codedIS.popLimit(oldLimit);
|
||||
} else {
|
||||
codedIS.skipRawBytes(length);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
skipUnknownField(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected City readCity(City c, int fileOffset, boolean loadStreets) throws IOException{
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int streetInd = 0;
|
||||
while(true){
|
||||
int t = codedIS.readTag();
|
||||
int tag = WireFormat.getTagFieldNumber(t);
|
||||
switch (tag) {
|
||||
case 0:
|
||||
c.setLocation(MapUtils.get31LatitudeY(y), MapUtils.get31LongitudeX(x));
|
||||
return c;
|
||||
case OsmandOdb.CityIndex.CITY_TYPE_FIELD_NUMBER :
|
||||
int type = codedIS.readUInt32();
|
||||
if(c == null){
|
||||
c = new City(CityType.values()[type]);
|
||||
c.setFileOffset(fileOffset);
|
||||
}
|
||||
break;
|
||||
case OsmandOdb.CityIndex.ID_FIELD_NUMBER :
|
||||
c.setId(codedIS.readUInt64());
|
||||
break;
|
||||
case OsmandOdb.CityIndex.NAME_EN_FIELD_NUMBER :
|
||||
c.setEnName(codedIS.readString());
|
||||
break;
|
||||
case OsmandOdb.CityIndex.NAME_FIELD_NUMBER :
|
||||
c.setName(codedIS.readString());
|
||||
if(c.getEnName().length() == 0){
|
||||
c.setEnName(Junidecode.unidecode(c.getName()));
|
||||
}
|
||||
break;
|
||||
case OsmandOdb.CityIndex.X_FIELD_NUMBER :
|
||||
x = codedIS.readFixed32();
|
||||
break;
|
||||
case OsmandOdb.CityIndex.Y_FIELD_NUMBER :
|
||||
y = codedIS.readFixed32();
|
||||
break;
|
||||
case OsmandOdb.CityIndex.INTERSECTIONS_FIELD_NUMBER :
|
||||
codedIS.skipRawBytes(codedIS.readRawVarint32());
|
||||
break;
|
||||
case OsmandOdb.CityIndex.STREETS_FIELD_NUMBER :
|
||||
int offset = codedIS.getTotalBytesRead();
|
||||
int length = codedIS.readRawVarint32();
|
||||
if(loadStreets){
|
||||
Street s = new Street(c);
|
||||
int oldLimit = codedIS.pushLimit(length);
|
||||
s.setFileOffset(offset);
|
||||
s.setIndexInCity(streetInd++);
|
||||
readStreet(s, false, x >> 7, y >> 7, null);
|
||||
c.registerStreet(s);
|
||||
codedIS.popLimit(oldLimit);
|
||||
} else {
|
||||
codedIS.skipRawBytes(length);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
skipUnknownField(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Street readStreet(Street s, boolean loadBuildings, int city24X, int city24Y, String postcodeFilter) throws IOException{
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
boolean loadLocation = city24X != 0 || city24Y != 0;
|
||||
while(true){
|
||||
int t = codedIS.readTag();
|
||||
int tag = WireFormat.getTagFieldNumber(t);
|
||||
switch (tag) {
|
||||
case 0:
|
||||
if(loadLocation){
|
||||
s.setLocation(MapUtils.getLatitudeFromTile(24, y), MapUtils.getLongitudeFromTile(24, x));
|
||||
}
|
||||
return s;
|
||||
case OsmandOdb.StreetIndex.ID_FIELD_NUMBER :
|
||||
s.setId(codedIS.readUInt64());
|
||||
break;
|
||||
case OsmandOdb.StreetIndex.NAME_EN_FIELD_NUMBER :
|
||||
s.setEnName(codedIS.readString());
|
||||
break;
|
||||
case OsmandOdb.StreetIndex.NAME_FIELD_NUMBER :
|
||||
s.setName(codedIS.readString());
|
||||
if(s.getEnName().length() == 0){
|
||||
s.setEnName(Junidecode.unidecode(s.getName()));
|
||||
}
|
||||
break;
|
||||
case OsmandOdb.StreetIndex.X_FIELD_NUMBER :
|
||||
int sx = codedIS.readSInt32();
|
||||
if(loadLocation){
|
||||
x = sx + city24X;
|
||||
} else {
|
||||
x = (int) MapUtils.getTileNumberX(24, s.getLocation().getLongitude());
|
||||
}
|
||||
break;
|
||||
case OsmandOdb.StreetIndex.Y_FIELD_NUMBER :
|
||||
int sy = codedIS.readSInt32();
|
||||
if(loadLocation){
|
||||
y = sy + city24Y;
|
||||
} else {
|
||||
y = (int) MapUtils.getTileNumberY(24, s.getLocation().getLatitude());
|
||||
}
|
||||
break;
|
||||
case OsmandOdb.StreetIndex.BUILDINGS_FIELD_NUMBER :
|
||||
int offset = codedIS.getTotalBytesRead();
|
||||
int length = codedIS.readRawVarint32();
|
||||
if(loadBuildings){
|
||||
int oldLimit = codedIS.pushLimit(length);
|
||||
Building b = readBuilding(offset, x, y);
|
||||
if (postcodeFilter == null || postcodeFilter.equalsIgnoreCase(b.getPostcode())) {
|
||||
s.registerBuilding(b);
|
||||
}
|
||||
codedIS.popLimit(oldLimit);
|
||||
} else {
|
||||
codedIS.skipRawBytes(length);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
skipUnknownField(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Building readBuilding(int fileOffset, int street24X, int street24Y) throws IOException{
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
Building b = new Building();
|
||||
b.setFileOffset(fileOffset);
|
||||
while(true){
|
||||
int t = codedIS.readTag();
|
||||
int tag = WireFormat.getTagFieldNumber(t);
|
||||
switch (tag) {
|
||||
case 0:
|
||||
b.setLocation(MapUtils.getLatitudeFromTile(24, y), MapUtils.getLongitudeFromTile(24, x));
|
||||
return b;
|
||||
case OsmandOdb.BuildingIndex.ID_FIELD_NUMBER :
|
||||
b.setId(codedIS.readUInt64());
|
||||
break;
|
||||
case OsmandOdb.BuildingIndex.NAME_EN_FIELD_NUMBER :
|
||||
b.setEnName(codedIS.readString());
|
||||
break;
|
||||
case OsmandOdb.BuildingIndex.NAME_FIELD_NUMBER :
|
||||
b.setName(codedIS.readString());
|
||||
if(b.getEnName().length() == 0){
|
||||
b.setEnName(Junidecode.unidecode(b.getName()));
|
||||
}
|
||||
break;
|
||||
case OsmandOdb.BuildingIndex.X_FIELD_NUMBER :
|
||||
x = codedIS.readSInt32() + street24X;
|
||||
break;
|
||||
case OsmandOdb.BuildingIndex.Y_FIELD_NUMBER :
|
||||
y = codedIS.readSInt32() + street24Y;
|
||||
break;
|
||||
case OsmandOdb.BuildingIndex.POSTCODE_FIELD_NUMBER :
|
||||
b.setPostcode(codedIS.readString());
|
||||
break;
|
||||
default:
|
||||
skipUnknownField(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2 different quires : s2 == null -> fill possible streets, s2 != null return LatLon intersection
|
||||
private LatLon readIntersectedStreets(Street[] cityStreets, Street s, Street s2, LatLon parent, List<Street> streets) throws IOException {
|
||||
int size = codedIS.readRawVarint32();
|
||||
int old = codedIS.pushLimit(size);
|
||||
boolean e = false;
|
||||
while(!e){
|
||||
int t = codedIS.readTag();
|
||||
int tag = WireFormat.getTagFieldNumber(t);
|
||||
switch (tag) {
|
||||
case 0:
|
||||
e = true;
|
||||
break;
|
||||
case OsmandOdb.InteresectedStreets.INTERSECTIONS_FIELD_NUMBER:
|
||||
int nsize = codedIS.readRawVarint32();
|
||||
int nold = codedIS.pushLimit(nsize);
|
||||
int st1 = -1;
|
||||
int st2 = -1;
|
||||
int cx = 0;
|
||||
int cy = 0;
|
||||
boolean end = false;
|
||||
while (!end) {
|
||||
int nt = codedIS.readTag();
|
||||
int ntag = WireFormat.getTagFieldNumber(nt);
|
||||
switch (ntag) {
|
||||
case 0:
|
||||
end = true;
|
||||
break;
|
||||
case OsmandOdb.StreetIntersection.INTERSECTEDSTREET1_FIELD_NUMBER:
|
||||
st1 = codedIS.readUInt32();
|
||||
break;
|
||||
case OsmandOdb.StreetIntersection.INTERSECTEDSTREET2_FIELD_NUMBER:
|
||||
st2 = codedIS.readUInt32();
|
||||
break;
|
||||
case OsmandOdb.StreetIntersection.INTERSECTEDX_FIELD_NUMBER:
|
||||
cx = codedIS.readSInt32();
|
||||
break;
|
||||
case OsmandOdb.StreetIntersection.INTERSECTEDY_FIELD_NUMBER:
|
||||
cy = codedIS.readSInt32();
|
||||
break;
|
||||
default:
|
||||
skipUnknownField(nt);
|
||||
}
|
||||
}
|
||||
codedIS.popLimit(nold);
|
||||
if (s2 == null) {
|
||||
// find all intersections
|
||||
if (st1 == s.getIndexInCity() && st2 != -1 && st2 < cityStreets.length && cityStreets[st2] != null) {
|
||||
streets.add(cityStreets[st2]);
|
||||
} else if (st2 == s.getIndexInCity() && st1 != -1 && st1 < cityStreets.length && cityStreets[st1] != null) {
|
||||
streets.add(cityStreets[st1]);
|
||||
}
|
||||
} else {
|
||||
if((st1 == s.getIndexInCity() && st2 == s2.getIndexInCity() ) ||
|
||||
(st2 == s.getIndexInCity() && st1 == s2.getIndexInCity())) {
|
||||
int x = (int) (MapUtils.getTileNumberX(24, parent.getLongitude()) + cx);
|
||||
int y = (int) (MapUtils.getTileNumberY(24, parent.getLatitude()) + cy);
|
||||
codedIS.popLimit(old);
|
||||
return new LatLon(MapUtils.getLatitudeFromTile(24, y), MapUtils.getLongitudeFromTile(24, x));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
skipUnknownField(t);
|
||||
}
|
||||
}
|
||||
codedIS.popLimit(old);
|
||||
return null;
|
||||
}
|
||||
|
||||
// do not preload streets in city
|
||||
protected LatLon findIntersectedStreets(City c, Street s, Street s2, List<Street> streets) throws IOException {
|
||||
if(s.getIndexInCity() == -1){
|
||||
return null;
|
||||
}
|
||||
codedIS.seek(c.getFileOffset());
|
||||
int size = codedIS.readRawVarint32();
|
||||
int old = codedIS.pushLimit(size);
|
||||
while(true){
|
||||
int t = codedIS.readTag();
|
||||
int tag = WireFormat.getTagFieldNumber(t);
|
||||
switch (tag) {
|
||||
case 0:
|
||||
codedIS.popLimit(old);
|
||||
return null;
|
||||
case OsmandOdb.CityIndex.INTERSECTIONS_FIELD_NUMBER :
|
||||
Street[] cityStreets = new Street[c.getStreets().size()];
|
||||
for(Street st : c.getStreets()){
|
||||
if(st.getIndexInCity() >= 0 && st.getIndexInCity() < cityStreets.length){
|
||||
cityStreets[st.getIndexInCity()] = st;
|
||||
}
|
||||
}
|
||||
LatLon ret = readIntersectedStreets(cityStreets, s, s2, c.getLocation(), streets);
|
||||
codedIS.popLimit(old);
|
||||
return ret;
|
||||
default:
|
||||
skipUnknownField(t);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void readPostcodes(List<PostCode> postcodes) throws IOException{
|
||||
while(true){
|
||||
int t = codedIS.readTag();
|
||||
int tag = WireFormat.getTagFieldNumber(t);
|
||||
switch (tag) {
|
||||
case 0:
|
||||
return;
|
||||
case OsmandOdb.PostcodesIndex.POSTCODES_FIELD_NUMBER :
|
||||
int offset = codedIS.getTotalBytesRead();
|
||||
int length = codedIS.readRawVarint32();
|
||||
int oldLimit = codedIS.pushLimit(length);
|
||||
postcodes.add(readPostcode(null, offset, false, null));
|
||||
codedIS.popLimit(oldLimit);
|
||||
break;
|
||||
default:
|
||||
skipUnknownField(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PostCode findPostcode(String name) throws IOException{
|
||||
while(true){
|
||||
int t = codedIS.readTag();
|
||||
int tag = WireFormat.getTagFieldNumber(t);
|
||||
switch (tag) {
|
||||
case 0:
|
||||
return null;
|
||||
case OsmandOdb.PostcodesIndex.POSTCODES_FIELD_NUMBER :
|
||||
int offset = codedIS.getTotalBytesRead();
|
||||
int length = codedIS.readRawVarint32();
|
||||
int oldLimit = codedIS.pushLimit(length);
|
||||
PostCode p = readPostcode(null, offset, true, name);
|
||||
codedIS.popLimit(oldLimit);
|
||||
if(p != null){
|
||||
return p;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
skipUnknownField(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,536 @@
|
|||
package net.osmand.binary;
|
||||
|
||||
import gnu.trove.list.array.TIntArrayList;
|
||||
import static net.osmand.binary.BinaryMapIndexReader.TRANSPORT_STOP_ZOOM;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.osmand.binary.BinaryMapIndexReader.SearchRequest;
|
||||
import net.osmand.data.TransportStop;
|
||||
import net.osmand.osm.MapUtils;
|
||||
import net.sf.junidecode.Junidecode;
|
||||
|
||||
import com.google.protobuf.CodedInputStreamRAF;
|
||||
import com.google.protobuf.WireFormat;
|
||||
|
||||
public class BinaryMapTransportReaderAdapter {
|
||||
private CodedInputStreamRAF codedIS;
|
||||
private final BinaryMapIndexReader map;
|
||||
|
||||
protected BinaryMapTransportReaderAdapter(BinaryMapIndexReader map){
|
||||
this.codedIS = map.codedIS;
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
private void skipUnknownField(int t) throws IOException {
|
||||
map.skipUnknownField(t);
|
||||
}
|
||||
|
||||
private int readInt() throws IOException {
|
||||
return map.readInt();
|
||||
}
|
||||
|
||||
public static class TransportIndex extends BinaryIndexPart {
|
||||
|
||||
int left = 0;
|
||||
int right = 0;
|
||||
int top = 0;
|
||||
int bottom = 0;
|
||||
|
||||
int stopsFileOffset = 0;
|
||||
int stopsFileLength = 0;
|
||||
|
||||
public int getLeft() {
|
||||
return left;
|
||||
}
|
||||
|
||||
public int getRight() {
|
||||
return right;
|
||||
}
|
||||
|
||||
public int getTop() {
|
||||
return top;
|
||||
}
|
||||
|
||||
public int getBottom() {
|
||||
return bottom;
|
||||
}
|
||||
|
||||
IndexStringTable stringTable = null;
|
||||
}
|
||||
|
||||
private static class IndexStringTable {
|
||||
private static final int SIZE_OFFSET_ARRAY = 100;
|
||||
private static final int WINDOW_SIZE = 25;
|
||||
int fileOffset = 0;
|
||||
int length = 0;
|
||||
|
||||
// offset from start for each SIZE_OFFSET_ARRAY elements
|
||||
// (SIZE_OFFSET_ARRAY + 1) offset = offsets[0] + skipOneString()
|
||||
TIntArrayList offsets = new TIntArrayList();
|
||||
Map<Integer, String> cacheOfStrings = new LinkedHashMap<Integer, String>();
|
||||
|
||||
int windowOffset = 0;
|
||||
List<String> window = new ArrayList<String>();
|
||||
}
|
||||
|
||||
|
||||
protected void readTransportIndex(TransportIndex ind) throws IOException {
|
||||
while(true){
|
||||
int t = codedIS.readTag();
|
||||
int tag = WireFormat.getTagFieldNumber(t);
|
||||
switch (tag) {
|
||||
case 0:
|
||||
return;
|
||||
case OsmandOdb.OsmAndTransportIndex.ROUTES_FIELD_NUMBER :
|
||||
skipUnknownField(t);
|
||||
break;
|
||||
case OsmandOdb.OsmAndTransportIndex.NAME_FIELD_NUMBER :
|
||||
ind.setName(codedIS.readString());
|
||||
break;
|
||||
case OsmandOdb.OsmAndTransportIndex.STOPS_FIELD_NUMBER :
|
||||
ind.stopsFileLength = readInt();
|
||||
ind.stopsFileOffset = codedIS.getTotalBytesRead();
|
||||
int old = codedIS.pushLimit(ind.stopsFileLength);
|
||||
readTransportBounds(ind);
|
||||
codedIS.popLimit(old);
|
||||
break;
|
||||
case OsmandOdb.OsmAndTransportIndex.STRINGTABLE_FIELD_NUMBER :
|
||||
IndexStringTable st = new IndexStringTable();
|
||||
st.length = codedIS.readRawVarint32();
|
||||
st.fileOffset = codedIS.getTotalBytesRead();
|
||||
readStringTable(st, 0, 20, true);
|
||||
ind.stringTable = st;
|
||||
codedIS.seek(st.length + st.fileOffset);
|
||||
break;
|
||||
default:
|
||||
skipUnknownField(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void readTransportBounds(TransportIndex ind) throws IOException {
|
||||
while(true){
|
||||
int t = codedIS.readTag();
|
||||
int tag = WireFormat.getTagFieldNumber(t);
|
||||
switch (tag) {
|
||||
case 0:
|
||||
return;
|
||||
case OsmandOdb.TransportStopsTree.LEFT_FIELD_NUMBER :
|
||||
ind.left = codedIS.readSInt32();
|
||||
break;
|
||||
case OsmandOdb.TransportStopsTree.RIGHT_FIELD_NUMBER :
|
||||
ind.right = codedIS.readSInt32();
|
||||
break;
|
||||
case OsmandOdb.TransportStopsTree.TOP_FIELD_NUMBER :
|
||||
ind.top = codedIS.readSInt32();
|
||||
break;
|
||||
case OsmandOdb.TransportStopsTree.BOTTOM_FIELD_NUMBER :
|
||||
ind.bottom = codedIS.readSInt32();
|
||||
break;
|
||||
default:
|
||||
skipUnknownField(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// if cache false put into window
|
||||
private int readStringTable(IndexStringTable st, int startOffset, int length, boolean cache) throws IOException {
|
||||
|
||||
int toSkip = seekUsingOffsets(st, startOffset);
|
||||
if(!cache){
|
||||
st.window.clear();
|
||||
st.windowOffset = startOffset;
|
||||
}
|
||||
int old = codedIS.pushLimit(st.fileOffset + st.length - codedIS.getTotalBytesRead());
|
||||
while (length > 0) {
|
||||
int t = codedIS.readTag();
|
||||
int tag = WireFormat.getTagFieldNumber(t);
|
||||
switch (tag) {
|
||||
case 0:
|
||||
length = 0;
|
||||
break;
|
||||
case OsmandOdb.StringTable.S_FIELD_NUMBER:
|
||||
if (toSkip > 0) {
|
||||
toSkip--;
|
||||
skipUnknownField(t);
|
||||
} else {
|
||||
String string = codedIS.readString();
|
||||
if(cache){
|
||||
st.cacheOfStrings.put(startOffset, string);
|
||||
} else {
|
||||
st.window.add(string);
|
||||
}
|
||||
startOffset++;
|
||||
length--;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
skipUnknownField(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
codedIS.popLimit(old);
|
||||
return startOffset;
|
||||
}
|
||||
|
||||
protected String getStringFromStringTable(IndexStringTable st, int ind) throws IOException {
|
||||
int lastRead = Integer.MAX_VALUE;
|
||||
while (lastRead >= ind) {
|
||||
if (st.cacheOfStrings.containsKey(ind)) {
|
||||
return st.cacheOfStrings.get(ind);
|
||||
}
|
||||
if (ind >= st.windowOffset && (ind - st.windowOffset) < st.window.size()) {
|
||||
return st.window.get(ind - st.windowOffset);
|
||||
}
|
||||
lastRead = readStringTable(st, ind - IndexStringTable.WINDOW_SIZE / 4, IndexStringTable.WINDOW_SIZE, false);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private int seekUsingOffsets(IndexStringTable st, int index) throws IOException {
|
||||
initStringOffsets(st, index);
|
||||
int shift = 0;
|
||||
int a = index / IndexStringTable.SIZE_OFFSET_ARRAY;
|
||||
if (a > st.offsets.size()) {
|
||||
a = st.offsets.size();
|
||||
}
|
||||
if (a > 0) {
|
||||
shift = st.offsets.get(a - 1);
|
||||
}
|
||||
codedIS.seek(st.fileOffset + shift);
|
||||
return index - a * IndexStringTable.SIZE_OFFSET_ARRAY;
|
||||
}
|
||||
|
||||
private void initStringOffsets(IndexStringTable st, int index) throws IOException {
|
||||
if (index > IndexStringTable.SIZE_OFFSET_ARRAY * (st.offsets.size() + 1)) {
|
||||
int shift = 0;
|
||||
if (!st.offsets.isEmpty()) {
|
||||
shift = st.offsets.get(st.offsets.size() - 1);
|
||||
}
|
||||
codedIS.seek(st.fileOffset + shift);
|
||||
int old = codedIS.pushLimit(st.length - shift);
|
||||
while (index > IndexStringTable.SIZE_OFFSET_ARRAY * (st.offsets.size() + 1)) {
|
||||
int ind = 0;
|
||||
while (ind < IndexStringTable.SIZE_OFFSET_ARRAY && ind != -1) {
|
||||
int t = codedIS.readTag();
|
||||
int tag = WireFormat.getTagFieldNumber(t);
|
||||
switch (tag) {
|
||||
case 0:
|
||||
ind = -1;
|
||||
break;
|
||||
case OsmandOdb.StringTable.S_FIELD_NUMBER:
|
||||
skipUnknownField(t);
|
||||
ind++;
|
||||
break;
|
||||
default:
|
||||
skipUnknownField(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(ind == IndexStringTable.SIZE_OFFSET_ARRAY){
|
||||
st.offsets.add(codedIS.getTotalBytesRead() - st.fileOffset);
|
||||
} else {
|
||||
// invalid index
|
||||
break;
|
||||
}
|
||||
}
|
||||
codedIS.popLimit(old);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void searchTransportTreeBounds(int pleft, int pright, int ptop, int pbottom,
|
||||
SearchRequest<TransportStop> req) throws IOException {
|
||||
int init = 0;
|
||||
int lastIndexResult = -1;
|
||||
int cright = 0;
|
||||
int cleft = 0;
|
||||
int ctop = 0;
|
||||
int cbottom = 0;
|
||||
req.numberOfReadSubtrees++;
|
||||
while(true){
|
||||
if(req.isInterrupted()){
|
||||
return;
|
||||
}
|
||||
int t = codedIS.readTag();
|
||||
int tag = WireFormat.getTagFieldNumber(t);
|
||||
if(init == 0xf){
|
||||
// coordinates are init
|
||||
init = 0;
|
||||
if(cright < req.left || cleft > req.right || ctop > req.bottom || cbottom < req.top){
|
||||
return;
|
||||
} else {
|
||||
req.numberOfAcceptedSubtrees++;
|
||||
}
|
||||
}
|
||||
switch (tag) {
|
||||
case 0:
|
||||
return;
|
||||
case OsmandOdb.TransportStopsTree.BOTTOM_FIELD_NUMBER :
|
||||
cbottom = codedIS.readSInt32() + pbottom;
|
||||
init |= 1;
|
||||
break;
|
||||
case OsmandOdb.TransportStopsTree.LEFT_FIELD_NUMBER :
|
||||
cleft = codedIS.readSInt32() + pleft;
|
||||
init |= 2;
|
||||
break;
|
||||
case OsmandOdb.TransportStopsTree.RIGHT_FIELD_NUMBER :
|
||||
cright = codedIS.readSInt32() + pright;
|
||||
init |= 4;
|
||||
break;
|
||||
case OsmandOdb.TransportStopsTree.TOP_FIELD_NUMBER :
|
||||
ctop = codedIS.readSInt32() + ptop;
|
||||
init |= 8;
|
||||
break;
|
||||
case OsmandOdb.TransportStopsTree.LEAFS_FIELD_NUMBER :
|
||||
int stopOffset = codedIS.getTotalBytesRead();
|
||||
int length = codedIS.readRawVarint32();
|
||||
int oldLimit = codedIS.pushLimit(length);
|
||||
if(lastIndexResult == -1){
|
||||
lastIndexResult = req.searchResults.size();
|
||||
}
|
||||
req.numberOfVisitedObjects++;
|
||||
TransportStop transportStop = readTransportStop(stopOffset, cleft, cright, ctop, cbottom, req);
|
||||
if(transportStop != null){
|
||||
req.searchResults.add(transportStop);
|
||||
|
||||
}
|
||||
codedIS.popLimit(oldLimit);
|
||||
break;
|
||||
case OsmandOdb.TransportStopsTree.SUBTREES_FIELD_NUMBER :
|
||||
// left, ... already initialized
|
||||
length = readInt();
|
||||
int filePointer = codedIS.getTotalBytesRead();
|
||||
if (req.limit == -1 || req.limit >= req.searchResults.size()) {
|
||||
oldLimit = codedIS.pushLimit(length);
|
||||
searchTransportTreeBounds(cleft, cright, ctop, cbottom, req);
|
||||
codedIS.popLimit(oldLimit);
|
||||
}
|
||||
codedIS.seek(filePointer + length);
|
||||
|
||||
if(lastIndexResult >= 0){
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
break;
|
||||
case OsmandOdb.TransportStopsTree.BASEID_FIELD_NUMBER :
|
||||
long baseId = codedIS.readUInt64();
|
||||
if (lastIndexResult != -1) {
|
||||
for (int i = lastIndexResult; i < req.searchResults.size(); i++) {
|
||||
TransportStop rs = req.searchResults.get(i);
|
||||
rs.setId(rs.getId() + baseId);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
skipUnknownField(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public net.osmand.data.TransportRoute getTransportRoute(int filePointer, TransportIndex ind) throws IOException {
|
||||
codedIS.seek(filePointer);
|
||||
int routeLength = codedIS.readRawVarint32();
|
||||
int old = codedIS.pushLimit(routeLength);
|
||||
net.osmand.data.TransportRoute dataObject = new net.osmand.data.TransportRoute();
|
||||
boolean end = false;
|
||||
int name = -1;
|
||||
int nameEn = -1;
|
||||
int operator = -1;
|
||||
int type = -1;
|
||||
long rid = 0;
|
||||
int rx = 0;
|
||||
int ry = 0;
|
||||
long did = 0;
|
||||
int dx = 0;
|
||||
int dy = 0;
|
||||
while(!end){
|
||||
int t = codedIS.readTag();
|
||||
int tag = WireFormat.getTagFieldNumber(t);
|
||||
switch (tag) {
|
||||
case 0:
|
||||
end = true;
|
||||
break;
|
||||
case OsmandOdb.TransportRoute.DISTANCE_FIELD_NUMBER :
|
||||
dataObject.setDistance(codedIS.readUInt32());
|
||||
break;
|
||||
case OsmandOdb.TransportRoute.ID_FIELD_NUMBER :
|
||||
dataObject.setId(codedIS.readUInt64());
|
||||
break;
|
||||
case OsmandOdb.TransportRoute.REF_FIELD_NUMBER :
|
||||
dataObject.setRef(codedIS.readString());
|
||||
break;
|
||||
case OsmandOdb.TransportRoute.TYPE_FIELD_NUMBER :
|
||||
type = codedIS.readUInt32();
|
||||
break;
|
||||
case OsmandOdb.TransportRoute.NAME_EN_FIELD_NUMBER :
|
||||
nameEn = codedIS.readUInt32();
|
||||
break;
|
||||
case OsmandOdb.TransportRoute.NAME_FIELD_NUMBER :
|
||||
name = codedIS.readUInt32();
|
||||
break;
|
||||
case OsmandOdb.TransportRoute.OPERATOR_FIELD_NUMBER:
|
||||
operator = codedIS.readUInt32();
|
||||
break;
|
||||
case OsmandOdb.TransportRoute.REVERSESTOPS_FIELD_NUMBER:
|
||||
int length = codedIS.readRawVarint32();
|
||||
int olds = codedIS.pushLimit(length);
|
||||
TransportStop stop = readTransportRouteStop(dx, dy, did);
|
||||
dataObject.getBackwardStops().add(stop);
|
||||
did = stop.getId();
|
||||
dx = (int) MapUtils.getTileNumberX(TRANSPORT_STOP_ZOOM, stop.getLocation().getLongitude());
|
||||
dy = (int) MapUtils.getTileNumberY(TRANSPORT_STOP_ZOOM, stop.getLocation().getLatitude());
|
||||
codedIS.popLimit(olds);
|
||||
break;
|
||||
case OsmandOdb.TransportRoute.DIRECTSTOPS_FIELD_NUMBER:
|
||||
length = codedIS.readRawVarint32();
|
||||
olds = codedIS.pushLimit(length);
|
||||
stop = readTransportRouteStop(rx, ry, rid);
|
||||
dataObject.getForwardStops().add(stop);
|
||||
rid = stop.getId();
|
||||
rx = (int) MapUtils.getTileNumberX(TRANSPORT_STOP_ZOOM, stop.getLocation().getLongitude());
|
||||
ry = (int) MapUtils.getTileNumberY(TRANSPORT_STOP_ZOOM, stop.getLocation().getLatitude());
|
||||
codedIS.popLimit(olds);
|
||||
break;
|
||||
default:
|
||||
skipUnknownField(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
codedIS.popLimit(old);
|
||||
if(name != -1){
|
||||
dataObject.setName(getStringFromStringTable(ind.stringTable, name));
|
||||
}
|
||||
if(nameEn != -1){
|
||||
dataObject.setEnName(getStringFromStringTable(ind.stringTable, nameEn));
|
||||
} else {
|
||||
dataObject.setEnName(Junidecode.unidecode(dataObject.getName()));
|
||||
}
|
||||
|
||||
if(operator != -1){
|
||||
dataObject.setOperator(getStringFromStringTable(ind.stringTable, operator));
|
||||
}
|
||||
if(type != -1){
|
||||
dataObject.setType(getStringFromStringTable(ind.stringTable, type));
|
||||
}
|
||||
for (int i = 0; i < 2; i++) {
|
||||
List<TransportStop> stops = i == 0 ? dataObject.getForwardStops() : dataObject.getBackwardStops();
|
||||
for (TransportStop s : stops) {
|
||||
if (s.getName().length() > 0) {
|
||||
s.setName(getStringFromStringTable(ind.stringTable, s.getName().charAt(0)));
|
||||
}
|
||||
if (s.getEnName().length() > 0) {
|
||||
s.setEnName(getStringFromStringTable(ind.stringTable, s.getEnName().charAt(0)));
|
||||
} else {
|
||||
s.setEnName(Junidecode.unidecode(s.getName()));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return dataObject;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private TransportStop readTransportRouteStop(int dx, int dy, long did) throws IOException {
|
||||
TransportStop dataObject = new TransportStop();
|
||||
boolean end = false;
|
||||
while(!end){
|
||||
int t = codedIS.readTag();
|
||||
int tag = WireFormat.getTagFieldNumber(t);
|
||||
switch (tag) {
|
||||
case 0:
|
||||
if(dataObject.getEnName().length() == 0){
|
||||
dataObject.setEnName(Junidecode.unidecode(dataObject.getName()));
|
||||
}
|
||||
end = true;
|
||||
break;
|
||||
case OsmandOdb.TransportRouteStop.NAME_EN_FIELD_NUMBER :
|
||||
dataObject.setEnName(""+((char) codedIS.readUInt32())); //$NON-NLS-1$
|
||||
break;
|
||||
case OsmandOdb.TransportRouteStop.NAME_FIELD_NUMBER :
|
||||
dataObject.setName(""+((char) codedIS.readUInt32())); //$NON-NLS-1$
|
||||
break;
|
||||
case OsmandOdb.TransportRouteStop.ID_FIELD_NUMBER :
|
||||
did += codedIS.readSInt64();
|
||||
break;
|
||||
case OsmandOdb.TransportRouteStop.DX_FIELD_NUMBER :
|
||||
dx += codedIS.readSInt32();
|
||||
break;
|
||||
case OsmandOdb.TransportRouteStop.DY_FIELD_NUMBER :
|
||||
dy += codedIS.readSInt32();
|
||||
break;
|
||||
default:
|
||||
skipUnknownField(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
dataObject.setId(did);
|
||||
dataObject.setLocation(MapUtils.getLatitudeFromTile(TRANSPORT_STOP_ZOOM, dy), MapUtils.getLongitudeFromTile(TRANSPORT_STOP_ZOOM, dx));
|
||||
return dataObject;
|
||||
}
|
||||
|
||||
private TransportStop readTransportStop(int shift, int cleft, int cright, int ctop, int cbottom, SearchRequest<TransportStop> req) throws IOException {
|
||||
int tag = WireFormat.getTagFieldNumber(codedIS.readTag());
|
||||
if(OsmandOdb.TransportStop.DX_FIELD_NUMBER != tag) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
int x = codedIS.readSInt32() + cleft;
|
||||
|
||||
tag = WireFormat.getTagFieldNumber(codedIS.readTag());
|
||||
if(OsmandOdb.TransportStop.DY_FIELD_NUMBER != tag) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
int y = codedIS.readSInt32() + ctop;
|
||||
if(req.right < x || req.left > x || req.top > y || req.bottom < y){
|
||||
codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
|
||||
return null;
|
||||
}
|
||||
|
||||
req.numberOfAcceptedObjects++;
|
||||
req.cacheTypes.clear();
|
||||
|
||||
TransportStop dataObject = new TransportStop();
|
||||
dataObject.setLocation(MapUtils.getLatitudeFromTile(TRANSPORT_STOP_ZOOM, y), MapUtils.getLongitudeFromTile(TRANSPORT_STOP_ZOOM, x));
|
||||
dataObject.setFileOffset(shift);
|
||||
while(true){
|
||||
int t = codedIS.readTag();
|
||||
tag = WireFormat.getTagFieldNumber(t);
|
||||
switch (tag) {
|
||||
case 0:
|
||||
dataObject.setReferencesToRoutes(req.cacheTypes.toArray());
|
||||
if(dataObject.getEnName().length() == 0){
|
||||
dataObject.setEnName(Junidecode.unidecode(dataObject.getName()));
|
||||
}
|
||||
return dataObject;
|
||||
case OsmandOdb.TransportStop.ROUTES_FIELD_NUMBER :
|
||||
req.cacheTypes.add(shift - codedIS.readUInt32());
|
||||
break;
|
||||
case OsmandOdb.TransportStop.NAME_EN_FIELD_NUMBER :
|
||||
dataObject.setEnName(""+((char) codedIS.readUInt32())); //$NON-NLS-1$
|
||||
break;
|
||||
case OsmandOdb.TransportStop.NAME_FIELD_NUMBER :
|
||||
int i = codedIS.readUInt32();
|
||||
dataObject.setName(""+((char) i)); //$NON-NLS-1$
|
||||
break;
|
||||
case OsmandOdb.TransportStop.ID_FIELD_NUMBER :
|
||||
dataObject.setId(codedIS.readSInt64());
|
||||
break;
|
||||
default:
|
||||
skipUnknownField(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue