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;
      }
    }
  }
 private RouteBorderLine readBorderLine() throws IOException {
   Builder bld = RouteBorderLine.newBuilder();
   while (true) {
     int t = codedIS.readTag();
     int tag = WireFormat.getTagFieldNumber(t);
     switch (tag) {
       case 0:
         return bld.build();
       case RouteBorderLine.X_FIELD_NUMBER:
         bld.setX(codedIS.readInt32());
         break;
       case RouteBorderLine.Y_FIELD_NUMBER:
         bld.setY(codedIS.readInt32());
         break;
       case RouteBorderLine.TOX_FIELD_NUMBER:
         bld.setTox(codedIS.readInt32());
         break;
       case RouteBorderLine.TOY_FIELD_NUMBER:
         bld.setToy(codedIS.readInt32());
         break;
       case RouteBorderLine.SHIFTTOPOINTSBLOCK_FIELD_NUMBER:
         bld.setShiftToPointsBlock(readInt());
         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;
     }
   }
 }
 private void readRouteEncodingRule(RouteRegion index, int id) throws IOException {
   String tags = null;
   String val = null;
   while (true) {
     int t = codedIS.readTag();
     int tag = WireFormat.getTagFieldNumber(t);
     switch (tag) {
       case 0:
         index.initRouteEncodingRule(id, tags, val);
         return;
       case RouteEncodingRule.VALUE_FIELD_NUMBER:
         val = codedIS.readString().intern();
         break;
       case RouteEncodingRule.TAG_FIELD_NUMBER:
         tags = codedIS.readString().intern();
         break;
       case RouteEncodingRule.ID_FIELD_NUMBER:
         id = codedIS.readUInt32();
         break;
       default:
         skipUnknownField(t);
         break;
     }
   }
 }
  private void readBorderLines(
      SearchRequest<RouteDataBorderLinePoint> req, TIntArrayList blocksToRead) throws IOException {
    while (true) {
      int t = codedIS.readTag();
      int tag = WireFormat.getTagFieldNumber(t);
      switch (tag) {
        case 0:
          return;
        case RouteBorderBox.BORDERLINES_FIELD_NUMBER:
          {
            int fp = codedIS.getTotalBytesRead();
            int length = codedIS.readRawVarint32();
            int old = codedIS.pushLimit(length);

            RouteBorderLine ln = readBorderLine();
            if (ln.hasTox() && req.intersects(ln.getX(), ln.getY(), ln.getTox(), ln.getY())) {
              blocksToRead.add(ln.getShiftToPointsBlock() + fp);
              // FIXME borders approach
              //				} else if(ln.hasToy() && req.intersects(ln.getX(), ln.getY(), ln.getX(),
              // ln.getToy())) {
              //					blocksToRead.add(ln.getShiftToPointsBlock() + fp);
            }
            codedIS.popLimit(old);
            break;
          }
        case RouteBorderBox.BLOCKS_FIELD_NUMBER:
          return;
        default:
          skipUnknownField(t);
          break;
      }
    }
  }
 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;
     }
   }
 }
 /**
  * Cheap test to see if input stream is a wallet. This checks for a magic value at the beginning
  * of the stream.
  *
  * @param is input stream to test
  * @return true if input stream is a wallet
  */
 public static boolean isWallet(InputStream is) {
   try {
     final CodedInputStream cis = CodedInputStream.newInstance(is);
     final int tag = cis.readTag();
     final int field = WireFormat.getTagFieldNumber(tag);
     if (field != 1) // network_identifier
     return false;
     final String network = cis.readString();
     return NetworkParameters.fromID(network) != null;
   } catch (IOException x) {
     return false;
   }
 }
 private void readBorderLinePoints(SearchRequest<RouteDataBorderLinePoint> req, RouteRegion r)
     throws IOException {
   int x = 0;
   int y = 0;
   long id = 0;
   while (true) {
     int t = codedIS.readTag();
     int tag = WireFormat.getTagFieldNumber(t);
     switch (tag) {
       case 0:
         return;
       case RouteBorderPointsBlock.X_FIELD_NUMBER:
         {
           x = codedIS.readInt32();
           break;
         }
       case RouteBorderPointsBlock.Y_FIELD_NUMBER:
         {
           y = codedIS.readInt32();
           break;
         }
       case RouteBorderPointsBlock.BASEID_FIELD_NUMBER:
         {
           id = codedIS.readInt64();
           break;
         }
       case RouteBorderPointsBlock.POINTS_FIELD_NUMBER:
         int len = codedIS.readRawVarint32();
         int oldLimit = codedIS.pushLimit(len);
         RouteDataBorderLinePoint p =
             readBorderLinePoint(new RouteDataBorderLinePoint(r), x, y, id);
         codedIS.popLimit(oldLimit);
         x = p.x;
         y = p.y;
         id = p.id;
         req.publish(p);
         break;
       default:
         skipUnknownField(t);
         break;
     }
   }
 }
 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;
 }
  // 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;
  }
 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);
   }
 }
 private RouteDataBorderLinePoint readBorderLinePoint(
     RouteDataBorderLinePoint p, int x, int y, long id) throws IOException {
   while (true) {
     int t = codedIS.readTag();
     int tag = WireFormat.getTagFieldNumber(t);
     switch (tag) {
       case 0:
         return p;
       case RouteBorderPoint.DX_FIELD_NUMBER:
         p.x = x + codedIS.readInt32();
         break;
       case RouteBorderPoint.DY_FIELD_NUMBER:
         p.y = y + codedIS.readInt32();
         break;
       case RouteBorderPoint.ROADID_FIELD_NUMBER:
         p.id = id + codedIS.readSInt64();
         break;
       case RouteBorderPoint.DIRECTION_FIELD_NUMBER:
         p.direction = codedIS.readBool();
         break;
       case RouteBorderPoint.TYPES_FIELD_NUMBER:
         TIntArrayList types = new TIntArrayList();
         int len = codedIS.readRawVarint32();
         int oldLimit = codedIS.pushLimit(len);
         while (codedIS.getBytesUntilLimit() > 0) {
           types.add(codedIS.readRawVarint32());
         }
         codedIS.popLimit(oldLimit);
         p.types = types.toArray();
         break;
       default:
         skipUnknownField(t);
         break;
     }
   }
 }
  protected void readRouteIndex(RouteRegion region) throws IOException {
    int routeEncodingRule = 1;
    while (true) {
      int t = codedIS.readTag();
      int tag = WireFormat.getTagFieldNumber(t);
      switch (tag) {
        case 0:
          return;
        case OsmandOdb.OsmAndRoutingIndex.NAME_FIELD_NUMBER:
          region.name = codedIS.readString();
          break;
        case OsmandOdb.OsmAndRoutingIndex.RULES_FIELD_NUMBER:
          {
            int len = codedIS.readInt32();
            int oldLimit = codedIS.pushLimit(len);
            readRouteEncodingRule(region, routeEncodingRule++);
            codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
            codedIS.popLimit(oldLimit);
          }
          break;
        case OsmandOdb.OsmAndRoutingIndex.ROOTBOXES_FIELD_NUMBER:
        case OsmandOdb.OsmAndRoutingIndex.BASEMAPBOXES_FIELD_NUMBER:
          {
            RouteSubregion subregion = new RouteSubregion(region);
            subregion.length = readInt();
            subregion.filePointer = codedIS.getTotalBytesRead();
            int oldLimit = codedIS.pushLimit(subregion.length);
            readRouteTree(subregion, null, 0, true);
            if (tag == OsmandOdb.OsmAndRoutingIndex.ROOTBOXES_FIELD_NUMBER) {
              region.subregions.add(subregion);
            } else {
              region.basesubregions.add(subregion);
            }
            codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
            codedIS.popLimit(oldLimit);
            break;
          }
        case OsmandOdb.OsmAndRoutingIndex.BASEBORDERBOX_FIELD_NUMBER:
        case OsmandOdb.OsmAndRoutingIndex.BORDERBOX_FIELD_NUMBER:
          {
            int length = readInt();
            int filePointer = codedIS.getTotalBytesRead();
            if (tag == OsmandOdb.OsmAndRoutingIndex.BORDERBOX_FIELD_NUMBER) {
              region.borderBoxLength = length;
              region.borderBoxPointer = filePointer;
            } else {
              region.baseBorderBoxLength = length;
              region.baseBorderBoxPointer = filePointer;
            }
            codedIS.skipRawBytes(length);
            break;
          }
        case OsmandOdb.OsmAndRoutingIndex.BLOCKS_FIELD_NUMBER:
          {
            // Finish reading file!
            codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
            break;
          }

        default:
          skipUnknownField(t);
          break;
      }
    }
  }
 private void readRouteTreeData(
     RouteSubregion routeTree,
     TLongArrayList idTables,
     TLongObjectHashMap<TLongArrayList> restrictions)
     throws IOException {
   routeTree.dataObjects = new ArrayList<RouteDataObject>();
   idTables.clear();
   restrictions.clear();
   List<String> stringTable = null;
   while (true) {
     int t = codedIS.readTag();
     int tag = WireFormat.getTagFieldNumber(t);
     switch (tag) {
       case 0:
         TLongObjectIterator<TLongArrayList> it = restrictions.iterator();
         while (it.hasNext()) {
           it.advance();
           int from = (int) it.key();
           RouteDataObject fromr = routeTree.dataObjects.get(from);
           fromr.restrictions = new long[it.value().size()];
           for (int k = 0; k < fromr.restrictions.length; k++) {
             int to = (int) (it.value().get(k) >> RouteDataObject.RESTRICTION_SHIFT);
             long valto =
                 (idTables.get(to) << RouteDataObject.RESTRICTION_SHIFT)
                     | ((long) it.value().get(k) & RouteDataObject.RESTRICTION_MASK);
             fromr.restrictions[k] = valto;
           }
         }
         for (RouteDataObject o : routeTree.dataObjects) {
           if (o != null) {
             if (o.id < idTables.size()) {
               o.id = idTables.get((int) o.id);
             }
             if (o.names != null && stringTable != null) {
               int[] keys = o.names.keys();
               for (int j = 0; j < keys.length; j++) {
                 o.names.put(keys[j], stringTable.get(o.names.get(keys[j]).charAt(0)));
               }
             }
           }
         }
         return;
       case RouteDataBlock.DATAOBJECTS_FIELD_NUMBER:
         int length = codedIS.readRawVarint32();
         int oldLimit = codedIS.pushLimit(length);
         RouteDataObject obj =
             readRouteDataObject(routeTree.routeReg, routeTree.left, routeTree.top);
         while (obj.id >= routeTree.dataObjects.size()) {
           routeTree.dataObjects.add(null);
         }
         routeTree.dataObjects.set((int) obj.id, obj);
         codedIS.popLimit(oldLimit);
         break;
       case RouteDataBlock.IDTABLE_FIELD_NUMBER:
         long routeId = 0;
         length = codedIS.readRawVarint32();
         oldLimit = codedIS.pushLimit(length);
         idLoop:
         while (true) {
           int ts = codedIS.readTag();
           int tags = WireFormat.getTagFieldNumber(ts);
           switch (tags) {
             case 0:
               break idLoop;
             case IdTable.ROUTEID_FIELD_NUMBER:
               routeId += codedIS.readSInt64();
               idTables.add(routeId);
               break;
             default:
               skipUnknownField(ts);
               break;
           }
         }
         codedIS.popLimit(oldLimit);
         break;
       case RouteDataBlock.RESTRICTIONS_FIELD_NUMBER:
         length = codedIS.readRawVarint32();
         oldLimit = codedIS.pushLimit(length);
         long from = 0;
         long to = 0;
         long type = 0;
         idLoop:
         while (true) {
           int ts = codedIS.readTag();
           int tags = WireFormat.getTagFieldNumber(ts);
           switch (tags) {
             case 0:
               break idLoop;
             case RestrictionData.FROM_FIELD_NUMBER:
               from = codedIS.readInt32();
               break;
             case RestrictionData.TO_FIELD_NUMBER:
               to = codedIS.readInt32();
               break;
             case RestrictionData.TYPE_FIELD_NUMBER:
               type = codedIS.readInt32();
               break;
             default:
               skipUnknownField(ts);
               break;
           }
         }
         if (!restrictions.containsKey(from)) {
           restrictions.put(from, new TLongArrayList());
         }
         restrictions.get(from).add((to << RouteDataObject.RESTRICTION_SHIFT) + type);
         codedIS.popLimit(oldLimit);
         break;
       case RouteDataBlock.STRINGTABLE_FIELD_NUMBER:
         length = codedIS.readRawVarint32();
         oldLimit = codedIS.pushLimit(length);
         stringTable = map.readStringTable();
         //				codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
         codedIS.popLimit(oldLimit);
         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;
  }
  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;
      }
    }
  }
 private RouteSubregion readRouteTree(
     RouteSubregion thisTree, RouteSubregion parentTree, int depth, boolean readCoordinates)
     throws IOException {
   boolean readChildren = depth != 0;
   if (readChildren) {
     thisTree.subregions = new ArrayList<BinaryMapRouteReaderAdapter.RouteSubregion>();
   }
   thisTree.routeReg.regionsRead++;
   while (true) {
     int t = codedIS.readTag();
     int tag = WireFormat.getTagFieldNumber(t);
     switch (tag) {
       case 0:
         return thisTree;
       case RouteDataBox.LEFT_FIELD_NUMBER:
         int i = codedIS.readSInt32();
         if (readCoordinates) {
           thisTree.left = i + (parentTree != null ? parentTree.left : 0);
         }
         break;
       case RouteDataBox.RIGHT_FIELD_NUMBER:
         i = codedIS.readSInt32();
         if (readCoordinates) {
           thisTree.right = i + (parentTree != null ? parentTree.right : 0);
         }
         break;
       case RouteDataBox.TOP_FIELD_NUMBER:
         i = codedIS.readSInt32();
         if (readCoordinates) {
           thisTree.top = i + (parentTree != null ? parentTree.top : 0);
         }
         break;
       case RouteDataBox.BOTTOM_FIELD_NUMBER:
         i = codedIS.readSInt32();
         if (readCoordinates) {
           thisTree.bottom = i + (parentTree != null ? parentTree.bottom : 0);
         }
         break;
       case RouteDataBox.SHIFTTODATA_FIELD_NUMBER:
         thisTree.shiftToData = readInt();
         if (!readChildren) {
           // usually 0
           thisTree.subregions = new ArrayList<BinaryMapRouteReaderAdapter.RouteSubregion>();
           readChildren = true;
         }
         break;
       case RouteDataBox.BOXES_FIELD_NUMBER:
         if (readChildren) {
           RouteSubregion subregion = new RouteSubregion(thisTree.routeReg);
           subregion.length = readInt();
           subregion.filePointer = codedIS.getTotalBytesRead();
           int oldLimit = codedIS.pushLimit(subregion.length);
           readRouteTree(subregion, thisTree, depth - 1, true);
           thisTree.subregions.add(subregion);
           codedIS.popLimit(oldLimit);
           codedIS.seek(subregion.filePointer + subregion.length);
         } else {
           codedIS.seek(thisTree.filePointer + thisTree.length);
           // skipUnknownField(t);
         }
         break;
       default:
         skipUnknownField(t);
         break;
     }
   }
 }
 private RouteDataObject readRouteDataObject(RouteRegion reg, int pleftx, int ptopy)
     throws IOException {
   RouteDataObject o = new RouteDataObject(reg);
   TIntArrayList pointsX = new TIntArrayList();
   TIntArrayList pointsY = new TIntArrayList();
   TIntArrayList types = new TIntArrayList();
   List<TIntArrayList> globalpointTypes = new ArrayList<TIntArrayList>();
   while (true) {
     int ts = codedIS.readTag();
     int tags = WireFormat.getTagFieldNumber(ts);
     switch (tags) {
       case 0:
         o.pointsX = pointsX.toArray();
         o.pointsY = pointsY.toArray();
         o.types = types.toArray();
         if (globalpointTypes.size() > 0) {
           o.pointTypes = new int[globalpointTypes.size()][];
           for (int k = 0; k < o.pointTypes.length; k++) {
             TIntArrayList l = globalpointTypes.get(k);
             if (l != null) {
               o.pointTypes[k] = l.toArray();
             }
           }
         }
         return o;
       case RouteData.TYPES_FIELD_NUMBER:
         int len = codedIS.readRawVarint32();
         int oldLimit = codedIS.pushLimit(len);
         while (codedIS.getBytesUntilLimit() > 0) {
           types.add(codedIS.readRawVarint32());
         }
         codedIS.popLimit(oldLimit);
         break;
       case RouteData.STRINGNAMES_FIELD_NUMBER:
         o.names = new TIntObjectHashMap<String>();
         int sizeL = codedIS.readRawVarint32();
         int old = codedIS.pushLimit(sizeL);
         while (codedIS.getBytesUntilLimit() > 0) {
           int stag = codedIS.readRawVarint32();
           int pId = codedIS.readRawVarint32();
           o.names.put(stag, ((char) pId) + "");
         }
         codedIS.popLimit(old);
         break;
       case RouteData.POINTS_FIELD_NUMBER:
         len = codedIS.readRawVarint32();
         oldLimit = codedIS.pushLimit(len);
         int px = pleftx >> SHIFT_COORDINATES;
         int py = ptopy >> SHIFT_COORDINATES;
         while (codedIS.getBytesUntilLimit() > 0) {
           int x = (codedIS.readSInt32()) + px;
           int y = (codedIS.readSInt32()) + py;
           pointsX.add(x << SHIFT_COORDINATES);
           pointsY.add(y << SHIFT_COORDINATES);
           px = x;
           py = y;
         }
         codedIS.popLimit(oldLimit);
         break;
       case RouteData.POINTTYPES_FIELD_NUMBER:
         len = codedIS.readRawVarint32();
         oldLimit = codedIS.pushLimit(len);
         while (codedIS.getBytesUntilLimit() > 0) {
           int pointInd = codedIS.readRawVarint32();
           TIntArrayList pointTypes = new TIntArrayList();
           int lens = codedIS.readRawVarint32();
           int oldLimits = codedIS.pushLimit(lens);
           while (codedIS.getBytesUntilLimit() > 0) {
             pointTypes.add(codedIS.readRawVarint32());
           }
           codedIS.popLimit(oldLimits);
           while (pointInd >= globalpointTypes.size()) {
             globalpointTypes.add(null);
           }
           globalpointTypes.set(pointInd, pointTypes);
         }
         codedIS.popLimit(oldLimit);
         break;
       case RouteData.ROUTEID_FIELD_NUMBER:
         o.id = codedIS.readInt32();
         break;
       default:
         skipUnknownField(ts);
         break;
     }
   }
 }