index.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sys/types.h>
  4. #include <unistd.h>
  5. #include <grass/G3d.h>
  6. #include "G3d_intern.h"
  7. /*---------------------------------------------------------------------------*/
  8. static int G3d_readIndex(G3D_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. G3d_error("G3d_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. G3d_error("G3d_readIndex: can't position file");
  21. return 0;
  22. }
  23. tmp = G3d_malloc(map->indexLongNbytes * map->nTiles);
  24. if (tmp == NULL) {
  25. G3d_error("G3d_readIndex: error in G3d_malloc");
  26. return 0;
  27. }
  28. if (indexLength < map->indexLongNbytes * map->nTiles) { /* RLE encoded? */
  29. if (indexLength > sizeof(long) * map->nTiles) {
  30. /*->index large enough? */
  31. tmp2 = G3d_malloc(indexLength);
  32. if (tmp2 == NULL) {
  33. G3d_error("G3d_readIndex: error in G3d_malloc");
  34. return 0;
  35. }
  36. }
  37. else /* YES */
  38. tmp2 = (unsigned char *)map->index;
  39. if (read(map->data_fd, tmp2, indexLength) != indexLength) {
  40. G3d_error("G3d_readIndex: can't read file");
  41. return 0;
  42. }
  43. G_rle_decode(tmp2, tmp, map->indexLongNbytes * map->nTiles, 1,
  44. &dummy1, &dummy2);
  45. if (indexLength > sizeof(long) * map->nTiles)
  46. G3d_free(tmp2);
  47. }
  48. else /* NO RLE */ if (read(map->data_fd, tmp, indexLength) != indexLength) {
  49. G3d_error("G3d_readIndex: can't read file");
  50. return 0;
  51. }
  52. G3d_longDecode(tmp, map->index, map->nTiles, map->indexLongNbytes);
  53. for (tileIndex = 0; tileIndex < map->nTiles; tileIndex++)
  54. if (map->index[tileIndex] == 0)
  55. map->index[tileIndex] = -1;
  56. G3d_free(tmp);
  57. return 1;
  58. }
  59. /*---------------------------------------------------------------------------*/
  60. int G3d_flushIndex(G3D_Map * map)
  61. {
  62. int sizeCompressed, indexLength, tileIndex;
  63. unsigned char *tmp;
  64. long ldummy;
  65. if (!map->hasIndex)
  66. return 1;
  67. map->indexOffset = lseek(map->data_fd, (long)0, SEEK_END);
  68. if (map->indexOffset == -1) {
  69. G3d_error("G3d_flushIndex: can't rewind file");
  70. return 0;
  71. }
  72. map->indexNbytesUsed = G3d_longEncode(&(map->indexOffset),
  73. (unsigned char *)&ldummy, 1);
  74. tmp = G3d_malloc(sizeof(long) * map->nTiles);
  75. if (tmp == NULL) {
  76. G3d_error("G3d_flushIndex: error in G3d_malloc");
  77. return 0;
  78. }
  79. for (tileIndex = 0; tileIndex < map->nTiles; tileIndex++)
  80. if (map->index[tileIndex] == -1)
  81. map->index[tileIndex] = 0;
  82. (void)G3d_longEncode(map->index, tmp, map->nTiles);
  83. sizeCompressed = G_rle_count_only(tmp, sizeof(long) * map->nTiles, 1);
  84. if (sizeCompressed >= map->nTiles * sizeof(long)) {
  85. indexLength = map->nTiles * sizeof(long);
  86. if (write(map->data_fd, tmp, indexLength) != indexLength) {
  87. G3d_error("G3d_flushIndex: can't write file");
  88. return 0;
  89. }
  90. }
  91. else {
  92. indexLength = sizeCompressed;
  93. G_rle_encode(tmp, (char *)map->index, sizeof(long) * map->nTiles, 1);
  94. if (write(map->data_fd, map->index, sizeCompressed) != sizeCompressed) {
  95. G3d_error("G3d_flushIndex: can't write file");
  96. return 0;
  97. }
  98. }
  99. G3d_free(tmp);
  100. if (!G3d_readIndex(map)) {
  101. G3d_error("G3d_flushIndex: error in G3d_readIndex");
  102. return 0;
  103. }
  104. return 1;
  105. }
  106. /*---------------------------------------------------------------------------*/
  107. static long *cmpIndex;
  108. static int indexSortCompare(const void *a, const void *b)
  109. {
  110. long offset1, offset2;
  111. offset1 = cmpIndex[*((const int *)a)];
  112. offset2 = cmpIndex[*((const int *)b)];
  113. if (offset1 > offset2)
  114. return 1;
  115. if (offset1 < offset2)
  116. return -1;
  117. return 0;
  118. }
  119. /*---------------------------------------------------------------------------*/
  120. int G3d_initIndex(G3D_Map * map, int hasIndex)
  121. {
  122. int tile;
  123. int i0, i1, i2, i3, i4, i5, offset, nofElts;
  124. int *offsetP;
  125. map->hasIndex = hasIndex;
  126. map->index = G3d_malloc(sizeof(long) * map->nTiles);
  127. map->tileLength = G3d_malloc(sizeof(int) * map->nTiles);
  128. if ((map->index == NULL) || (map->tileLength == NULL)) {
  129. G3d_error("G3d_initIndex: error in G3d_malloc");
  130. return 0;
  131. }
  132. if (map->operation == G3D_WRITE_DATA) {
  133. for (tile = 0; tile < map->nTiles; tile++)
  134. map->index[tile] = -1;
  135. return 1;
  136. }
  137. if (!map->hasIndex) {
  138. offset = 0;
  139. for (tile = 0; tile < map->nTiles; tile++) {
  140. map->index[tile] = offset * map->numLengthExtern + map->offset;
  141. nofElts = G3d_computeClippedTileDimensions
  142. (map, tile, &i0, &i1, &i2, &i3, &i4, &i5);
  143. map->tileLength[tile] = nofElts * map->numLengthExtern;
  144. offset += nofElts;
  145. }
  146. return 1;
  147. }
  148. if (!G3d_readIndex(map)) {
  149. G3d_error("G3d_initIndex: error in G3d_readIndex");
  150. return 0;
  151. }
  152. offsetP = G3d_malloc(sizeof(int) * map->nTiles);
  153. if (offsetP == NULL) {
  154. G3d_error("G3d_initIndex: error in G3d_malloc");
  155. return 0;
  156. }
  157. for (tile = 0; tile < map->nTiles; tile++)
  158. offsetP[tile] = tile;
  159. cmpIndex = map->index;
  160. qsort(offsetP, map->nTiles, sizeof(int), indexSortCompare);
  161. for (tile = 0; tile < map->nTiles - 1; tile++) {
  162. if (map->index[offsetP[tile]] == -1) {
  163. map->tileLength[offsetP[tile]] = 0;
  164. continue;
  165. }
  166. map->tileLength[offsetP[tile]] = map->index[offsetP[tile + 1]] -
  167. map->index[offsetP[tile]];
  168. }
  169. if (map->index[offsetP[map->nTiles - 1]] == -1)
  170. map->tileLength[offsetP[map->nTiles - 1]] = 0;
  171. else
  172. map->tileLength[offsetP[map->nTiles - 1]] =
  173. map->indexOffset - map->index[offsetP[map->nTiles - 1]];
  174. G3d_free(offsetP);
  175. return 1;
  176. }