index.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sys/types.h>
  4. #include <unistd.h>
  5. #include <grass/raster3d.h>
  6. #include "raster3d_intern.h"
  7. /*---------------------------------------------------------------------------*/
  8. static int Rast3d_readIndex(RASTER3D_Map * map)
  9. {
  10. unsigned char *tmp, *tmp2;
  11. int dummy1, dummy2, indexLength, tileIndex;
  12. long indexLast;
  13. indexLast = lseek(map->data_fd, (long)0, SEEK_END);
  14. if (indexLast == -1) {
  15. Rast3d_error("Rast3d_readIndex: can't position file");
  16. return 0;
  17. }
  18. indexLength = indexLast - map->indexOffset;
  19. if (lseek(map->data_fd, map->indexOffset, SEEK_SET) == -1) {
  20. Rast3d_error("Rast3d_readIndex: can't position file");
  21. return 0;
  22. }
  23. tmp = Rast3d_malloc(map->indexLongNbytes * map->nTiles);
  24. if (tmp == NULL) {
  25. Rast3d_error("Rast3d_readIndex: error in Rast3d_malloc");
  26. return 0;
  27. }
  28. /* The size of the tile index array in the map file */
  29. if(indexLength == map->indexLongNbytes * map->nTiles) {
  30. if (read(map->data_fd, tmp, indexLength) != indexLength) {
  31. Rast3d_error("Rast3d_readIndex: can't read file");
  32. return 0;
  33. }
  34. } else
  35. /* ATTENTION: RLE encoded reading is only supported for backward compatibility */
  36. if (indexLength < map->indexLongNbytes * map->nTiles) { /* RLE encoded? */
  37. if (indexLength > sizeof(long) * map->nTiles) {
  38. /*->index large enough? */
  39. tmp2 = Rast3d_malloc(indexLength);
  40. if (tmp2 == NULL) {
  41. Rast3d_error("Rast3d_readIndex: error in Rast3d_malloc");
  42. return 0;
  43. }
  44. }
  45. else /* YES */
  46. tmp2 = (unsigned char *)map->index;
  47. if (read(map->data_fd, tmp2, indexLength) != indexLength) {
  48. Rast3d_error("Rast3d_readIndex: can't read file");
  49. return 0;
  50. }
  51. Rast3d_rle_decode((char *)tmp2, (char *)tmp, map->indexLongNbytes * map->nTiles, 1,
  52. &dummy1, &dummy2);
  53. if (indexLength > sizeof(long) * map->nTiles)
  54. Rast3d_free(tmp2);
  55. } /* END RLE */
  56. Rast3d_long_decode(tmp, map->index, map->nTiles, map->indexLongNbytes);
  57. for (tileIndex = 0; tileIndex < map->nTiles; tileIndex++)
  58. if (map->index[tileIndex] == 0)
  59. map->index[tileIndex] = -1;
  60. Rast3d_free(tmp);
  61. return 1;
  62. }
  63. /*---------------------------------------------------------------------------*/
  64. int Rast3d_flush_index(RASTER3D_Map * map)
  65. {
  66. int indexLength, tileIndex;
  67. unsigned char *tmp;
  68. long ldummy;
  69. if (!map->hasIndex)
  70. return 1;
  71. map->indexOffset = lseek(map->data_fd, (long)0, SEEK_END);
  72. if (map->indexOffset == -1) {
  73. Rast3d_error("Rast3d_flush_index: can't rewind file");
  74. return 0;
  75. }
  76. map->indexNbytesUsed = Rast3d_long_encode(&(map->indexOffset),
  77. (unsigned char *)&ldummy, 1);
  78. tmp = Rast3d_malloc(sizeof(long) * map->nTiles);
  79. if (tmp == NULL) {
  80. Rast3d_error("Rast3d_flush_index: error in Rast3d_malloc");
  81. return 0;
  82. }
  83. for (tileIndex = 0; tileIndex < map->nTiles; tileIndex++)
  84. if (map->index[tileIndex] == -1)
  85. map->index[tileIndex] = 0;
  86. (void)Rast3d_long_encode(map->index, tmp, map->nTiles);
  87. indexLength = map->nTiles * sizeof(long);
  88. if (write(map->data_fd, tmp, indexLength) != indexLength) {
  89. Rast3d_error("Rast3d_flush_index: can't write file");
  90. return 0;
  91. }
  92. Rast3d_free(tmp);
  93. if (!Rast3d_readIndex(map)) {
  94. Rast3d_error("Rast3d_flush_index: error in Rast3d_readIndex");
  95. return 0;
  96. }
  97. return 1;
  98. }
  99. /*---------------------------------------------------------------------------*/
  100. static long *cmpIndex;
  101. static int indexSortCompare(const void *a, const void *b)
  102. {
  103. long offset1, offset2;
  104. offset1 = cmpIndex[*((const long *)a)];
  105. offset2 = cmpIndex[*((const long *)b)];
  106. if (offset1 > offset2)
  107. return 1;
  108. if (offset1 < offset2)
  109. return -1;
  110. return 0;
  111. }
  112. /*---------------------------------------------------------------------------*/
  113. int Rast3d_init_index(RASTER3D_Map * map, int hasIndex)
  114. {
  115. int tile;
  116. int i0, i1, i2, i3, i4, i5, nofElts;
  117. long offset;
  118. long *offsetP;
  119. map->hasIndex = hasIndex;
  120. map->index = Rast3d_malloc(sizeof(long) * map->nTiles);
  121. map->tileLength = Rast3d_malloc(sizeof(int) * map->nTiles);
  122. if ((map->index == NULL) || (map->tileLength == NULL)) {
  123. Rast3d_error("Rast3d_init_index: error in Rast3d_malloc");
  124. return 0;
  125. }
  126. if (map->operation == RASTER3D_WRITE_DATA) {
  127. for (tile = 0; tile < map->nTiles; tile++)
  128. map->index[tile] = -1;
  129. return 1;
  130. }
  131. if (!map->hasIndex) {
  132. offset = 0;
  133. for (tile = 0; tile < map->nTiles; tile++) {
  134. map->index[tile] = offset * map->numLengthExtern + map->offset;
  135. nofElts = Rast3d_compute_clipped_tile_dimensions
  136. (map, tile, &i0, &i1, &i2, &i3, &i4, &i5);
  137. map->tileLength[tile] = nofElts * map->numLengthExtern;
  138. offset += nofElts;
  139. }
  140. return 1;
  141. }
  142. if (!Rast3d_readIndex(map)) {
  143. Rast3d_error("Rast3d_init_index: error in Rast3d_readIndex");
  144. return 0;
  145. }
  146. offsetP = Rast3d_malloc(sizeof(long) * map->nTiles);
  147. if (offsetP == NULL) {
  148. Rast3d_error("Rast3d_init_index: error in Rast3d_malloc");
  149. return 0;
  150. }
  151. for (tile = 0; tile < map->nTiles; tile++)
  152. offsetP[tile] = tile;
  153. cmpIndex = map->index;
  154. qsort(offsetP, map->nTiles, sizeof(long), indexSortCompare);
  155. for (tile = 0; tile < map->nTiles - 1; tile++) {
  156. if (map->index[offsetP[tile]] == -1) {
  157. map->tileLength[offsetP[tile]] = 0;
  158. continue;
  159. }
  160. map->tileLength[offsetP[tile]] = map->index[offsetP[tile + 1]] -
  161. map->index[offsetP[tile]];
  162. }
  163. if (map->index[offsetP[map->nTiles - 1]] == -1)
  164. map->tileLength[offsetP[map->nTiles - 1]] = 0;
  165. else
  166. map->tileLength[offsetP[map->nTiles - 1]] =
  167. map->indexOffset - map->index[offsetP[map->nTiles - 1]];
  168. Rast3d_free(offsetP);
  169. return 1;
  170. }