processBlocks method

Future<DatastoreReadResult> processBlocks(
  1. ReadbufferSource readBufferSource,
  2. QueryParameters queryParameters,
  3. SubFileParameter subFileParameter,
  4. BoundingBox boundingBox,
  5. MapfileSelector selector,
)

don't make this method private since we are using it in the example APP to analyze mapfiles

Implementation

Future<DatastoreReadResult> processBlocks(ReadbufferSource readBufferSource, QueryParameters queryParameters, SubFileParameter subFileParameter,
    BoundingBox boundingBox, MapfileSelector selector) async {
  bool queryIsWater = true;
  bool queryReadWaterInfo = false;

  DatastoreReadResult mapFileReadResult = new DatastoreReadResult(pointOfInterests: [], ways: []);

  // read and process all blocks from top to bottom and from left to right
  for (int row = queryParameters.fromBlockY; row <= queryParameters.toBlockY; ++row) {
    for (int column = queryParameters.fromBlockX; column <= queryParameters.toBlockX; ++column) {
      // calculate the actual block number of the needed block in the file
      int blockNumber = row * subFileParameter.blocksWidth + column;
      // String cacheKey = "$blockNumber-${queryParameters.queryZoomLevel}";
      // PoiWayBundle? bundle = _blockCache.get(cacheKey);
      // if (bundle != null) {
      //   mapFileReadResult.add(bundle);
      //   print(
      //       "from cache: $row/$column/${queryParameters.queryZoomLevel}-${subFileParameter.id} ${subFileParameter.zoomLevelMax}");
      //   continue;
      // }

      // get the current index entry
      int currentBlockIndexEntry = await this._databaseIndexCache.getIndexEntry(subFileParameter, blockNumber, readBufferSource);

      // check if the current query would still return a water tile
      if (queryIsWater) {
        // check the water flag of the current block in its index entry
        queryIsWater &= (currentBlockIndexEntry & BITMASK_INDEX_WATER) != 0;
        queryReadWaterInfo = true;
      }

      // get and check the current block pointer
      int currentBlockPointer = currentBlockIndexEntry & BITMASK_INDEX_OFFSET;
      if (currentBlockPointer < 1 || currentBlockPointer > subFileParameter.subFileSize) {
        _log.warning(
            "invalid current block pointer: 0x${currentBlockPointer.toRadixString(16)} with subFileSize: 0x${subFileParameter.subFileSize.toRadixString(16)} for blocknumber $blockNumber");
        return mapFileReadResult;
      }

      int? nextBlockPointer;
      // check if the current block is the last block in the file
      if (blockNumber + 1 == subFileParameter.numberOfBlocks) {
        // set the next block pointer to the end of the file
        nextBlockPointer = subFileParameter.subFileSize;
      } else {
        // get and check the next block pointer
        nextBlockPointer = (await this._databaseIndexCache.getIndexEntry(subFileParameter, blockNumber + 1, readBufferSource)) & BITMASK_INDEX_OFFSET;
        if (nextBlockPointer > subFileParameter.subFileSize) {
          _log.warning("invalid next block pointer: $nextBlockPointer");
          _log.warning("sub-file size: ${subFileParameter.subFileSize}");
          return mapFileReadResult;
        }
      }

      // calculate the size of the current block
      int currentBlockSize = (nextBlockPointer - currentBlockPointer);
      if (currentBlockSize < 0) {
        _log.warning("current block size must not be negative: $currentBlockSize");
        return mapFileReadResult;
      } else if (currentBlockSize == 0) {
        // the current block is empty, continue with the next block
        continue;
      } else if (currentBlockSize > Parameters.MAXIMUM_BUFFER_SIZE) {
        // the current block is too large, continue with the next block
        _log.warning("current block size too large: $currentBlockSize");
        continue;
      } else if (currentBlockPointer + currentBlockSize > this._fileSize) {
        _log.warning("current block larger than file size: $currentBlockSize");
        return mapFileReadResult;
      }

      String key = "${subFileParameter.startAddress + currentBlockPointer}-$currentBlockSize";
      Readbuffer readbuffer = await _cache.getOrProduce(key, (key) async {
        Readbuffer readBuffer = await readBufferSource.readFromFileAt(subFileParameter.startAddress + currentBlockPointer, currentBlockSize);
        return readBuffer;
      });

      // calculate the top-left coordinates of the underlying tile
      double tileLatitude = subFileParameter.projection.tileYToLatitude((subFileParameter.boundaryTileTop + row));
      double tileLongitude = subFileParameter.projection.tileXToLongitude((subFileParameter.boundaryTileLeft + column));

      PoiWayBundle poiWayBundle =
          _processBlock(queryParameters, subFileParameter, boundingBox, tileLatitude, tileLongitude, selector, Readbuffer.from(readbuffer));
      //_blockCache.set(cacheKey, poiWayBundle);
      mapFileReadResult.add(poiWayBundle);
    }
  }

  // the query is finished, was the water flag set for all blocks?
  if (queryIsWater && queryReadWaterInfo) {
    // Deprecate water tiles rendering
    mapFileReadResult.isWater = true;
  }

  return mapFileReadResult;
}