GRASS Programmer's Manual  6.4.2(2012)
g3d/index.c
Go to the documentation of this file.
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 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines