GRASS Programmer's Manual
6.4.2(2012)
|
00001 #include <stdio.h> 00002 #include <stdlib.h> 00003 #include <sys/types.h> 00004 #include <unistd.h> 00005 #include <grass/G3d.h> 00006 #include "G3d_intern.h" 00007 00008 /*---------------------------------------------------------------------------*/ 00009 00010 static int G3d_readIndex(G3D_Map * map) 00011 { 00012 unsigned char *tmp, *tmp2; 00013 int dummy1, dummy2, indexLength, tileIndex; 00014 long indexLast; 00015 00016 indexLast = lseek(map->data_fd, (long)0, SEEK_END); 00017 if (indexLast == -1) { 00018 G3d_error("G3d_readIndex: can't position file"); 00019 return 0; 00020 } 00021 00022 indexLength = indexLast - map->indexOffset; 00023 00024 if (lseek(map->data_fd, map->indexOffset, SEEK_SET) == -1) { 00025 G3d_error("G3d_readIndex: can't position file"); 00026 return 0; 00027 } 00028 00029 tmp = G3d_malloc(map->indexLongNbytes * map->nTiles); 00030 00031 if (tmp == NULL) { 00032 G3d_error("G3d_readIndex: error in G3d_malloc"); 00033 return 0; 00034 } 00035 00036 if (indexLength < map->indexLongNbytes * map->nTiles) { /* RLE encoded? */ 00037 00038 if (indexLength > sizeof(long) * map->nTiles) { 00039 00040 /*->index large enough? */ 00041 tmp2 = G3d_malloc(indexLength); 00042 if (tmp2 == NULL) { 00043 G3d_error("G3d_readIndex: error in G3d_malloc"); 00044 return 0; 00045 } 00046 } 00047 else /* YES */ 00048 tmp2 = (unsigned char *)map->index; 00049 00050 if (read(map->data_fd, tmp2, indexLength) != indexLength) { 00051 G3d_error("G3d_readIndex: can't read file"); 00052 return 0; 00053 } 00054 00055 G_rle_decode(tmp2, tmp, map->indexLongNbytes * map->nTiles, 1, 00056 &dummy1, &dummy2); 00057 00058 if (indexLength > sizeof(long) * map->nTiles) 00059 G3d_free(tmp2); 00060 } 00061 else /* NO RLE */ if (read(map->data_fd, tmp, indexLength) != indexLength) { 00062 G3d_error("G3d_readIndex: can't read file"); 00063 return 0; 00064 } 00065 00066 G3d_longDecode(tmp, map->index, map->nTiles, map->indexLongNbytes); 00067 00068 for (tileIndex = 0; tileIndex < map->nTiles; tileIndex++) 00069 if (map->index[tileIndex] == 0) 00070 map->index[tileIndex] = -1; 00071 00072 G3d_free(tmp); 00073 00074 return 1; 00075 } 00076 00077 /*---------------------------------------------------------------------------*/ 00078 00079 int G3d_flushIndex(G3D_Map * map) 00080 { 00081 int sizeCompressed, indexLength, tileIndex; 00082 unsigned char *tmp; 00083 long ldummy; 00084 00085 if (!map->hasIndex) 00086 return 1; 00087 00088 map->indexOffset = lseek(map->data_fd, (long)0, SEEK_END); 00089 if (map->indexOffset == -1) { 00090 G3d_error("G3d_flushIndex: can't rewind file"); 00091 return 0; 00092 } 00093 00094 map->indexNbytesUsed = G3d_longEncode(&(map->indexOffset), 00095 (unsigned char *)&ldummy, 1); 00096 00097 tmp = G3d_malloc(sizeof(long) * map->nTiles); 00098 if (tmp == NULL) { 00099 G3d_error("G3d_flushIndex: error in G3d_malloc"); 00100 return 0; 00101 } 00102 00103 for (tileIndex = 0; tileIndex < map->nTiles; tileIndex++) 00104 if (map->index[tileIndex] == -1) 00105 map->index[tileIndex] = 0; 00106 00107 (void)G3d_longEncode(map->index, tmp, map->nTiles); 00108 00109 sizeCompressed = G_rle_count_only(tmp, sizeof(long) * map->nTiles, 1); 00110 00111 if (sizeCompressed >= map->nTiles * sizeof(long)) { 00112 indexLength = map->nTiles * sizeof(long); 00113 if (write(map->data_fd, tmp, indexLength) != indexLength) { 00114 G3d_error("G3d_flushIndex: can't write file"); 00115 return 0; 00116 } 00117 } 00118 else { 00119 indexLength = sizeCompressed; 00120 G_rle_encode(tmp, (char *)map->index, sizeof(long) * map->nTiles, 1); 00121 if (write(map->data_fd, map->index, sizeCompressed) != sizeCompressed) { 00122 G3d_error("G3d_flushIndex: can't write file"); 00123 return 0; 00124 } 00125 } 00126 00127 G3d_free(tmp); 00128 if (!G3d_readIndex(map)) { 00129 G3d_error("G3d_flushIndex: error in G3d_readIndex"); 00130 return 0; 00131 } 00132 00133 return 1; 00134 } 00135 00136 /*---------------------------------------------------------------------------*/ 00137 00138 static long *cmpIndex; 00139 00140 static int indexSortCompare(const void *a, const void *b) 00141 { 00142 long offset1, offset2; 00143 00144 offset1 = cmpIndex[*((const int *)a)]; 00145 offset2 = cmpIndex[*((const int *)b)]; 00146 00147 if (offset1 > offset2) 00148 return 1; 00149 if (offset1 < offset2) 00150 return -1; 00151 return 0; 00152 } 00153 00154 /*---------------------------------------------------------------------------*/ 00155 00156 int G3d_initIndex(G3D_Map * map, int hasIndex) 00157 { 00158 int tile; 00159 int i0, i1, i2, i3, i4, i5, offset, nofElts; 00160 int *offsetP; 00161 00162 map->hasIndex = hasIndex; 00163 map->index = G3d_malloc(sizeof(long) * map->nTiles); 00164 map->tileLength = G3d_malloc(sizeof(int) * map->nTiles); 00165 00166 if ((map->index == NULL) || (map->tileLength == NULL)) { 00167 G3d_error("G3d_initIndex: error in G3d_malloc"); 00168 return 0; 00169 } 00170 00171 if (map->operation == G3D_WRITE_DATA) { 00172 for (tile = 0; tile < map->nTiles; tile++) 00173 map->index[tile] = -1; 00174 return 1; 00175 } 00176 00177 if (!map->hasIndex) { 00178 offset = 0; 00179 for (tile = 0; tile < map->nTiles; tile++) { 00180 map->index[tile] = offset * map->numLengthExtern + map->offset; 00181 nofElts = G3d_computeClippedTileDimensions 00182 (map, tile, &i0, &i1, &i2, &i3, &i4, &i5); 00183 map->tileLength[tile] = nofElts * map->numLengthExtern; 00184 offset += nofElts; 00185 } 00186 return 1; 00187 } 00188 00189 if (!G3d_readIndex(map)) { 00190 G3d_error("G3d_initIndex: error in G3d_readIndex"); 00191 return 0; 00192 } 00193 00194 offsetP = G3d_malloc(sizeof(int) * map->nTiles); 00195 if (offsetP == NULL) { 00196 G3d_error("G3d_initIndex: error in G3d_malloc"); 00197 return 0; 00198 } 00199 00200 for (tile = 0; tile < map->nTiles; tile++) 00201 offsetP[tile] = tile; 00202 cmpIndex = map->index; 00203 qsort(offsetP, map->nTiles, sizeof(int), indexSortCompare); 00204 00205 for (tile = 0; tile < map->nTiles - 1; tile++) { 00206 if (map->index[offsetP[tile]] == -1) { 00207 map->tileLength[offsetP[tile]] = 0; 00208 continue; 00209 } 00210 00211 map->tileLength[offsetP[tile]] = map->index[offsetP[tile + 1]] - 00212 map->index[offsetP[tile]]; 00213 } 00214 00215 if (map->index[offsetP[map->nTiles - 1]] == -1) 00216 map->tileLength[offsetP[map->nTiles - 1]] = 0; 00217 else 00218 map->tileLength[offsetP[map->nTiles - 1]] = 00219 map->indexOffset - map->index[offsetP[map->nTiles - 1]]; 00220 00221 G3d_free(offsetP); 00222 00223 return 1; 00224 }