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;
     }
   }
 }
  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;
      }
    }
  }