#include #include #include #include #include #include "raster3d_intern.h" /*---------------------------------------------------------------------------*/ static int Rast3d_readIndex(RASTER3D_Map * map) { unsigned char *tmp, *tmp2; int dummy1, dummy2, indexLength, tileIndex; long indexLast; indexLast = lseek(map->data_fd, (long)0, SEEK_END); if (indexLast == -1) { Rast3d_error("Rast3d_readIndex: can't position file"); return 0; } indexLength = indexLast - map->indexOffset; if (lseek(map->data_fd, map->indexOffset, SEEK_SET) == -1) { Rast3d_error("Rast3d_readIndex: can't position file"); return 0; } tmp = Rast3d_malloc(map->indexLongNbytes * map->nTiles); if (tmp == NULL) { Rast3d_error("Rast3d_readIndex: error in Rast3d_malloc"); return 0; } /* The size of the tile index array in the map file */ if(indexLength == map->indexLongNbytes * map->nTiles) { if (read(map->data_fd, tmp, indexLength) != indexLength) { Rast3d_error("Rast3d_readIndex: can't read file"); return 0; } } else /* ATTENTION: RLE encoded reading is only supported for backward compatibility */ if (indexLength < map->indexLongNbytes * map->nTiles) { /* RLE encoded? */ if (indexLength > sizeof(long) * map->nTiles) { /*->index large enough? */ tmp2 = Rast3d_malloc(indexLength); if (tmp2 == NULL) { Rast3d_error("Rast3d_readIndex: error in Rast3d_malloc"); return 0; } } else /* YES */ tmp2 = (unsigned char *)map->index; if (read(map->data_fd, tmp2, indexLength) != indexLength) { Rast3d_error("Rast3d_readIndex: can't read file"); return 0; } Rast3d_rle_decode((char *)tmp2, (char *)tmp, map->indexLongNbytes * map->nTiles, 1, &dummy1, &dummy2); if (indexLength > sizeof(long) * map->nTiles) Rast3d_free(tmp2); } /* END RLE */ Rast3d_long_decode(tmp, map->index, map->nTiles, map->indexLongNbytes); for (tileIndex = 0; tileIndex < map->nTiles; tileIndex++) if (map->index[tileIndex] == 0) map->index[tileIndex] = -1; Rast3d_free(tmp); return 1; } /*---------------------------------------------------------------------------*/ int Rast3d_flush_index(RASTER3D_Map * map) { int indexLength, tileIndex; unsigned char *tmp; long ldummy; if (!map->hasIndex) return 1; map->indexOffset = lseek(map->data_fd, (long)0, SEEK_END); if (map->indexOffset == -1) { Rast3d_error("Rast3d_flush_index: can't rewind file"); return 0; } map->indexNbytesUsed = Rast3d_long_encode(&(map->indexOffset), (unsigned char *)&ldummy, 1); tmp = Rast3d_malloc(sizeof(long) * map->nTiles); if (tmp == NULL) { Rast3d_error("Rast3d_flush_index: error in Rast3d_malloc"); return 0; } for (tileIndex = 0; tileIndex < map->nTiles; tileIndex++) if (map->index[tileIndex] == -1) map->index[tileIndex] = 0; (void)Rast3d_long_encode(map->index, tmp, map->nTiles); indexLength = map->nTiles * sizeof(long); if (write(map->data_fd, tmp, indexLength) != indexLength) { Rast3d_error("Rast3d_flush_index: can't write file"); return 0; } Rast3d_free(tmp); if (!Rast3d_readIndex(map)) { Rast3d_error("Rast3d_flush_index: error in Rast3d_readIndex"); return 0; } return 1; } /*---------------------------------------------------------------------------*/ static long *cmpIndex; static int indexSortCompare(const void *a, const void *b) { long offset1, offset2; offset1 = cmpIndex[*((const long *)a)]; offset2 = cmpIndex[*((const long *)b)]; if (offset1 > offset2) return 1; if (offset1 < offset2) return -1; return 0; } /*---------------------------------------------------------------------------*/ int Rast3d_init_index(RASTER3D_Map * map, int hasIndex) { int tile; int i0, i1, i2, i3, i4, i5, nofElts; long offset; long *offsetP; map->hasIndex = hasIndex; map->index = Rast3d_malloc(sizeof(long) * map->nTiles); map->tileLength = Rast3d_malloc(sizeof(int) * map->nTiles); if ((map->index == NULL) || (map->tileLength == NULL)) { Rast3d_error("Rast3d_init_index: error in Rast3d_malloc"); return 0; } if (map->operation == RASTER3D_WRITE_DATA) { for (tile = 0; tile < map->nTiles; tile++) map->index[tile] = -1; return 1; } if (!map->hasIndex) { offset = 0; for (tile = 0; tile < map->nTiles; tile++) { map->index[tile] = offset * map->numLengthExtern + map->offset; nofElts = Rast3d_compute_clipped_tile_dimensions (map, tile, &i0, &i1, &i2, &i3, &i4, &i5); map->tileLength[tile] = nofElts * map->numLengthExtern; offset += nofElts; } return 1; } if (!Rast3d_readIndex(map)) { Rast3d_error("Rast3d_init_index: error in Rast3d_readIndex"); return 0; } offsetP = Rast3d_malloc(sizeof(long) * map->nTiles); if (offsetP == NULL) { Rast3d_error("Rast3d_init_index: error in Rast3d_malloc"); return 0; } for (tile = 0; tile < map->nTiles; tile++) offsetP[tile] = tile; cmpIndex = map->index; qsort(offsetP, map->nTiles, sizeof(long), indexSortCompare); for (tile = 0; tile < map->nTiles - 1; tile++) { if (map->index[offsetP[tile]] == -1) { map->tileLength[offsetP[tile]] = 0; continue; } map->tileLength[offsetP[tile]] = map->index[offsetP[tile + 1]] - map->index[offsetP[tile]]; } if (map->index[offsetP[map->nTiles - 1]] == -1) map->tileLength[offsetP[map->nTiles - 1]] = 0; else map->tileLength[offsetP[map->nTiles - 1]] = map->indexOffset - map->index[offsetP[map->nTiles - 1]]; Rast3d_free(offsetP); return 1; }