put_row.c

Go to the documentation of this file.
00001 /*
00002  * $Id: put_row.c,v 2.4 2006/06/06 20:01:19 brad Exp $
00003  */
00004 /**********************************************************************
00005  *
00006  *   G_zeros_r_nulls(zeros_r_nulls)
00007  *      int zeros_r_nulls       the last argument of put_data()
00008  *
00009  *   zeros_r_nulls > 0          zero values of buf to be written into files
00010  *                              are null values by default.
00011  *
00012  *   zeros_r_nulls == 0         zero values are just zero itself.
00013  *
00014  *   zeros_r_nulls < 0          do not set. return current setting.
00015  *                              1: set
00016  *                              0: not set
00017  *
00018  *   Return setting values in all cases.
00019  *
00020  *   *** NOTE *** 
00021  *   Use only to change a default behavior for zero of G_put_map_row[_random].
00022  *
00023  ********************************************************************** 
00024  *
00025  *   G_put_[c/f/d]_raster_row(fd, buf)
00026  *      int fd           file descriptor of the opened map
00027  *      [F/D]CELL *buf   buffer holding row info to be written
00028  *
00029  *   Writes the next row for the cell file opened on 'fd' from 'buf'
00030  *   All writes go into NEW files that exactly match the current window.
00031  *   The file must have been opened with G_open_cell_new()
00032  *   and be written sequentially, ie no skipping rows
00033  *
00034  *   when the null values are embeded into the data, corresponding cells are 
00035  *   changed to 0's and the corresponding null value row is written into null 
00036  *   file.
00037  *
00038  *   *** NOTE *** 
00039  *   A map cannot be copied using G_get_raster_row() and G_put_raster_row().
00040  *   The former resamples the data of the original map into a row buffer
00041  *   that matches the current window.  The later writes out rows associated
00042  *   with the window.
00043  *
00044  *   returns:    1  if successful
00045  *              -1  on fail
00046  *
00047  *  Keeps track of the minimum and maximum cell value  for use in updating
00048  *  the range file upon close of the cell file.
00049  *  HOWEVER when nulls are not embeded, the cells are considered 0's as far
00050  *  as updating range is concerned, even if the corresponding cell is null
00051  *  in the resulting null file, so programmer should be carefult to set all 
00052  *  the null values using G_set_null_value() or G_insert_[d/f_]null_values()
00053  *
00054  ********************************************************************** 
00055  *
00056  *   G_put_map_row(fd, buf)
00057  *      int fd           file descriptor of the opened map
00058  *      CELL *buf        buffer holding row info to be written
00059  *
00060  *   Writes the next row for the cell file opened on 'fd' from 'buf'
00061  *   All writes go into NEW files that exactly match the current window.
00062  *   The file must have been opened with G_open_cell_new()
00063  *   and be written sequentially, ie no skipping rows
00064  *
00065  *   NULLS are written into null bitmap file for all cells which are zero,
00066  *   and cells which have null value (these cells are converted to 0's before
00067  *   writing) 
00068  *
00069  *   *** NOTE *** 
00070  *   A map cannot be copied using G_get_map_row() and G_put_map_row().
00071  *   The former resamples the data of the original map into a row buffer
00072  *   that matches the current window.  The later writes out rows associated
00073  *   with the window.
00074  *
00075  *   returns:    1  if successful
00076  *              -1  on fail
00077  *
00078  *  Keeps track of the minimum and maximum cell value  for use in updating
00079  *  the range file upon close of the cell file.
00080  *
00081  ********************************************************************** 
00082  *
00083  *  G_put_map_row_random(fd, buf, row, col, ncells)
00084  *      int fd                  File descriptor where data is to be written
00085  *      CELL *buf               Buffer holding data
00086  *      int row                 Map row where data is to be written
00087  *      int col                 Column where data begins
00088  *      int ncells              Number of columns of data to be written
00089  *
00090  *   Writes parts of rows into open cell file.
00091  *
00092  *   Cell file must have been opened with G_open_cell_new_random()
00093  *   except it can't write null file.
00094  *
00095  *   returns:    0  if successful
00096  *              -1  on fail
00097  *
00098  *   behaves the same as G_put_map_row()
00099  *
00100  **********************************************************************
00101  *
00102  *  Note: there is no G_put_[c/f/d]_raster_row_random() because even though
00103  *  it is possible to randomly write floating and integer rows, it is not
00104  *  possible to rand. write null data, so the null file can't
00105  *  be updated correctly.
00106  *
00107  ***********************************************************************
00108  *
00109  *  G__put_null_value_row(fd, buf, row, col, ncells)
00110  *      int fd                  File descriptor where data is to be written
00111  *      char *buf               Buffer holding null data
00112  *      int row                 Map row where data is to be written
00113  *      int col                 Column where data begins
00114  *      int ncells              Number of columns of data to be written
00115  *
00116  *   converts a buffer of zero's and ones to bitstream and stores this 
00117  *   bitstream in memory. (the null rows from memory are written into null
00118  *   file after the limit is reached, and the place for new null rows
00119  *   to be kept in memory is freed. Should not be used by application
00120  *   programs.
00121  *
00122  *   returns:    0  if successful
00123  *              -1  on fail
00124  **********************************************************************/
00125 
00126 #include <string.h>
00127 
00128 #include <sys/types.h>
00129 #include <sys/stat.h>
00130 #include <unistd.h>
00131 #include <fcntl.h>
00132 
00133 #include <grass/config.h>
00134 
00135 #include "G.h"
00136 #include <grass/glocale.h>
00137 
00138 static int _zeros_r_nulls = 1;
00139 
00140 static int put_raster_data(int,void *,int,int,int,int,RASTER_MAP_TYPE);
00141 static int put_data(int,CELL *,int, int,int,int);
00142 static int check_open(const char *,int,int);
00143 static int adjust(int, int *, int *);
00144 static void write_error(int,int);
00145 static int same(const unsigned char *, const unsigned char *, int);
00146 static int seek_random(int, int, int);
00147 static void set_file_pointer(int,int);
00148 static int put_fp_data(int,void *,int,int,int,RASTER_MAP_TYPE);
00149 static int put_null_data(int,char *, int);
00150 static int convert_and_write_if(int, CELL *);
00151 static int convert_and_write_id(int, CELL *);
00152 static int convert_and_write_df(int, DCELL *);
00153 static int convert_and_write_fd(int, FCELL *);
00154 static int put_raster_row(int fd, void *buf, RASTER_MAP_TYPE data_type, int zeros_r_nulls);
00155 
00156 /*--------------------------------------------------------------------------*/
00157 /*--------------------------------------------------------------------------*/
00158 /*--------------------------------------------------------------------------*/
00159 
00160 int G_zeros_r_nulls(int zeros_r_nulls)
00161 {
00162     if (zeros_r_nulls >= 0)
00163         _zeros_r_nulls = zeros_r_nulls > 0;
00164 
00165     return _zeros_r_nulls;
00166 }
00167 
00168 int G_put_map_row_random(int fd, CELL *buf, int row, int col, int n)
00169 {
00170     struct fileinfo *fcb = &G__.fileinfo[fd];
00171 
00172     if (!check_open("G_put_map_row_random", fd, 1))
00173         return -1;
00174 
00175     buf += adjust(fd, &col, &n);
00176     switch (put_data(fd, buf, row, col, n, _zeros_r_nulls))
00177     {
00178     case -1: return -1;
00179     case  0: return  1;
00180     }
00181 
00182     /* only for integer maps */
00183     if (fcb->want_histogram)
00184         G_update_cell_stats (buf, n, &fcb->statf);
00185 
00186     G_row_update_range (buf, n, &fcb->range);
00187 
00188     return 1;
00189 }
00190 
00191 int G__put_null_value_row(int fd, char *buf)
00192 {
00193     struct fileinfo *fcb = &G__.fileinfo[fd];
00194 
00195     switch (put_null_data(fd, buf, fcb->null_cur_row))
00196     {
00197     case -1: return -1;
00198     case  0: return  1;
00199     }
00200 
00201     fcb->null_cur_row++;
00202 
00203     return 1;
00204 }
00205 
00206 int G_put_map_row(int fd, CELL *buf)
00207 {
00208     struct fileinfo *fcb = &G__.fileinfo[fd];
00209 
00210     if (fcb->map_type != CELL_TYPE)
00211     {
00212         G_fatal_error(_("G_put_map_row: %s is not integer! Use G_put_[f/d]_raster_row()!"),
00213                       fcb->name);
00214         return -1;
00215     }
00216 
00217     return put_raster_row(fd, buf, CELL_TYPE, _zeros_r_nulls);
00218 }
00219 
00220 int G_put_raster_row(int fd, void *buf, RASTER_MAP_TYPE data_type)
00221 {
00222     return put_raster_row(fd, buf, data_type, 0);
00223 }
00224 
00225 int G_put_c_raster_row(int fd, CELL *buf)
00226 {
00227     return G_put_raster_row(fd, buf, CELL_TYPE);
00228 }
00229 
00230 int G_put_f_raster_row(int fd, FCELL *buf)
00231 {
00232     return G_put_raster_row(fd, buf, FCELL_TYPE);
00233 }
00234 
00235 int G_put_d_raster_row(int fd, DCELL *buf)
00236 {
00237     return G_put_raster_row(fd, buf, DCELL_TYPE);
00238 }
00239 
00240 /*--------------------------------------------------------------------------*/
00241 
00242 static int check_open(const char *me, int fd, int random)
00243 {
00244     struct fileinfo *fcb = &G__.fileinfo[fd];
00245 
00246     switch (fcb->open_mode)
00247     {
00248     case OPEN_OLD:
00249         G_warning(_("%s: map [%s] not open for write - request ignored"), me, fcb->name);
00250         break;
00251     case OPEN_NEW_COMPRESSED:
00252     case OPEN_NEW_UNCOMPRESSED:
00253         if (!random)
00254             return 1;
00255 
00256         G_warning(_("%s: map [%s] not open for random write - request ignored"),
00257             me, fcb->name);
00258         break;
00259     case OPEN_NEW_RANDOM:
00260         if (random)
00261             return 1;
00262 
00263         G_warning(_("%s: map [%s] not open for sequential write - request ignored"),
00264             me, fcb->name);
00265         break;
00266     default:
00267         G_warning(_("%s: unopened file descriptor - request ignored"), me);
00268         break;
00269     }
00270 
00271     return 0;
00272 }
00273 
00274 /*******************************************************
00275 *  adjust the column,n so that it is within the window
00276 *  returns the adjustment to buffer that must be made
00277 *  if col,n is adjusted
00278 *
00279 *  if n comes back <= zero, do not write
00280 *******************************************************/
00281 static int adjust(int fd, int *col, int *n)
00282 {
00283     struct fileinfo *fcb = &G__.fileinfo[fd];
00284     int adj = 0;
00285     int last = *col + *n;
00286 
00287     if (*col < 0)
00288     {
00289         adj = -(*col);
00290         *col = 0;
00291     }
00292 
00293     if (last > fcb->cellhd.cols)
00294         last = fcb->cellhd.cols;
00295 
00296     *n = last - *col;
00297 
00298     return adj;
00299 }
00300 
00301 static void write_error(int fd,int row)
00302 {
00303     struct fileinfo *fcb = &G__.fileinfo[fd];
00304 
00305     if (fcb->io_error)
00306         return;
00307 
00308     G_warning(_("map [%s] - unable to write row %d"), fcb->name, row);
00309 
00310     fcb->io_error = 1;
00311 
00312     return;
00313 }
00314 
00315 /*--------------------------------------------------------------------------*/
00316 
00317 int G__write_data(int fd, int row, int n)
00318 
00319 {
00320     struct fileinfo *fcb = &G__.fileinfo[fd];
00321     ssize_t nwrite = fcb->nbytes * n;
00322 
00323     if (write(fd, G__.work_buf, nwrite) != nwrite)
00324     {
00325         write_error(fd, row);
00326         return -1;
00327     }
00328 
00329     return 0;
00330 }
00331 
00332 int G__write_data_compressed(int fd, int row, int n)
00333 {
00334     struct fileinfo *fcb = &G__.fileinfo[fd];
00335     int nwrite = fcb->nbytes * n;
00336 
00337     if (G_zlib_write(fd, G__.work_buf, nwrite) < 0)
00338     {
00339         write_error(fd, row);
00340         return -1;
00341     }
00342   
00343     return 0;
00344 }
00345 
00346 /*--------------------------------------------------------------------------*/
00347 
00348 static int seek_random(int fd, int row, int col)
00349 {
00350     struct fileinfo *fcb = &G__.fileinfo[fd];
00351     off_t offset = ((off_t) fcb->cellhd.cols * row + col) * fcb->nbytes;
00352 
00353     if (lseek(fd, offset, SEEK_SET) < 0)
00354     {
00355         write_error(fd, row);
00356         return -1;
00357     }
00358 
00359     return 0;
00360 }
00361 
00362 /*--------------------------------------------------------------------------*/
00363 
00364 static void set_file_pointer(int fd, int row)
00365 {
00366     struct fileinfo *fcb = &G__.fileinfo[fd];
00367 
00368     fcb->row_ptr[row] = lseek(fd, 0L, SEEK_CUR);
00369 }
00370 
00371 /*--------------------------------------------------------------------------*/
00372 /*--------------------------------------------------------------------------*/
00373 /*--------------------------------------------------------------------------*/
00374 
00375 static int convert_float(
00376         XDR *xdrs, const FCELL *rast, int row, int col, int n, int random)
00377 {
00378     int i;
00379 
00380     for (i = 0; i < n; i++) 
00381     {
00382         FCELL f;
00383 
00384         /* substitute embeded null vals by 0's */
00385         if (G_is_f_null_value(&rast[i]))
00386         {
00387             f = 0.;
00388             if (!random)
00389                 G__.null_buf[col + i] = 1;
00390         }
00391         else 
00392             f = rast[i];
00393 
00394         if (!xdr_float(xdrs, &f)) 
00395         {
00396             G_warning(_("xdr_float failed for index %d of row %d"),  i, row);
00397             return -1;
00398         }
00399     }
00400 
00401     return 0;
00402 }
00403 
00404 static int convert_double(
00405         XDR *xdrs, const DCELL *rast, int row, int col, int n, int random)
00406 {
00407     int i;
00408 
00409     for (i = 0; i < n; i++) 
00410     {
00411         DCELL d;
00412 
00413         /* substitute embeded null vals by 0's */
00414         if (G_is_d_null_value(&rast[i]))
00415         {
00416             d = 0.;
00417             if (!random)
00418                 G__.null_buf[col + i] = 1;
00419         }
00420         else
00421             d = rast[i];
00422 
00423         if (!xdr_double(xdrs, &d)) 
00424         {
00425             G_warning(_("xdr_double failed for index %d of row %d"), i, row);
00426             return -1;
00427         }
00428     }
00429 
00430     return 0;
00431 }
00432 
00433 /*--------------------------------------------------------------------------*/
00434 
00435 /* writes data to fcell file for either full or partial rows */
00436 
00437 static int put_fp_data(int fd, void *rast, int row, int col, int n, RASTER_MAP_TYPE data_type)
00438 {
00439     struct fileinfo *fcb = &G__.fileinfo[fd];
00440     int random     = (fcb->open_mode == OPEN_NEW_RANDOM);
00441     int compressed = (fcb->open_mode == OPEN_NEW_COMPRESSED);
00442     XDR *xdrs = &fcb->xdrstream;
00443 
00444     if (row < 0 || row >= fcb->cellhd.rows)
00445         return 0;
00446   
00447     if (n <= 0)
00448         return 0;
00449   
00450     if (random)
00451     {
00452         if (seek_random(fd, row, col) == -1)
00453             return -1;
00454     }
00455     else if (compressed)
00456         set_file_pointer(fd, row);
00457   
00458     xdrmem_create(xdrs, (caddr_t) G__.work_buf,
00459                   (u_int) (fcb->nbytes * fcb->cellhd.cols), XDR_ENCODE);
00460     xdr_setpos (xdrs, 0);
00461   
00462     if (data_type == FCELL_TYPE)
00463     {
00464         if (convert_float(xdrs, rast, row, col, n, random) < 0)
00465             return -1;
00466     }
00467     else
00468     {
00469         if (convert_double(xdrs, rast, row, col, n, random) < 0)
00470             return -1;
00471     }
00472 
00473     xdr_destroy(&fcb->xdrstream);
00474   
00475     if (compressed)
00476     {
00477         if (G__write_data_compressed(fd, row, n) == -1)
00478             return -1;
00479     }
00480     else
00481         if (G__write_data(fd, row, n) == -1)
00482             return -1;
00483   
00484     return 1;
00485 }
00486 
00487 /*--------------------------------------------------------------------------*/
00488 /*--------------------------------------------------------------------------*/
00489 /*--------------------------------------------------------------------------*/
00490 
00491 static void convert_int(
00492     unsigned char *wk, const CELL *rast, int col, int n,
00493     int random, int len, int zeros_r_nulls)
00494 {
00495     int i;
00496 
00497     /* transform CELL data into non-machine dependent multi-byte format */
00498 
00499     for (i = 0; i < n; i++)
00500     {
00501         CELL v = rast[i];
00502         int neg;
00503         int k;
00504 
00505         /* substitute embeded null vals by 0's */
00506         if (G_is_c_null_value(&v))
00507         {
00508             v = 0;
00509             if (!random)
00510                 G__.null_buf[col + i] = 1;
00511         }
00512         else if (!random && zeros_r_nulls && !v)
00513             G__.null_buf[col + i] = 1;
00514 
00515         /* negatives */
00516         if (v < 0)
00517         {
00518             neg = 1;
00519             v = -v;
00520         }
00521         else
00522             neg = 0;
00523 
00524         /* copy byte by byte */
00525         for (k = len - 1; k >= 0; k--)
00526         {
00527             wk[k] = v & 0xff;
00528             v >>= 8;
00529         }
00530 
00531         /* set negative bit in first byte */
00532         if (neg)
00533             wk[0] |= 0x80 ;
00534 
00535         wk += len;
00536     }
00537 }
00538 
00539 static int count_bytes(const unsigned char *wk, int n, int len)
00540 {
00541     int i, j;
00542 
00543     for (i = 0; i < len - 1; i++)
00544         for (j = 0; j < n; j++)
00545             if (wk[j * len + i] != 0)
00546                 return len - i;
00547 
00548     return 1;
00549 }
00550 
00551 static void trim_bytes(unsigned char *wk, int n, int slen, int trim)
00552 {
00553     unsigned char *wk2 = wk;
00554     int i, j;
00555 
00556     for (i = 0; i < n; i++)
00557     {
00558         for (j = 0; j < trim; j++)
00559             wk++;
00560         for ( ; j < slen; j++)
00561             *wk2++ = *wk++;
00562     }
00563 }
00564 
00565 static int same(const unsigned char *x, const unsigned char *y, int n)
00566 {
00567     return (memcmp(x, y, n) == 0);
00568 }
00569 
00570 static int count_run(const unsigned char *src, int n, int nbytes)
00571 {
00572     const unsigned char *cur = src + nbytes;
00573     int i;
00574 
00575     for (i = 1; i < n; i++)
00576     {
00577         if (i == 255 || !same(cur, src, nbytes))
00578             return i;
00579 
00580         cur += nbytes;
00581     }
00582 
00583     return n;
00584 }
00585 
00586 static int rle_compress(unsigned char *dst, unsigned char *src, int n, int nbytes)
00587 {
00588     int nwrite = 0;
00589     int total = nbytes * n;
00590 
00591     while (n > 0)
00592     {
00593         int count;
00594 
00595         nwrite += nbytes + 1;
00596         if (nwrite >= total)
00597             return 0;
00598 
00599         count = count_run(src, n, nbytes);
00600 
00601         *dst++ = count;
00602         memcpy(dst, src, nbytes);
00603         dst += nbytes;
00604 
00605         src += count * nbytes;
00606         n -= count;
00607     }
00608 
00609     return nwrite;
00610 }
00611 
00612 static int zlib_compress(unsigned char *dst, unsigned char *src, int n, int nbytes)
00613 {
00614     int total = nbytes * n;
00615     int nwrite = G_zlib_compress(G__.work_buf + 1, total,
00616                                  G__.compressed_buf + 1, G__.compressed_buf_size - 1);
00617 
00618     return (nwrite >= total) ? 0 : nwrite;
00619 }
00620 
00621 /*--------------------------------------------------------------------------*/
00622 
00623 static int put_data(int fd, CELL *cell, int row, int col, int n, int zeros_r_nulls)
00624 {
00625     struct fileinfo *fcb = &G__.fileinfo[fd];
00626     int random     = (fcb->open_mode == OPEN_NEW_RANDOM);
00627     int compressed = fcb->cellhd.compressed;
00628     int len = compressed ? sizeof(CELL) : fcb->nbytes;
00629     unsigned char *wk = G__.work_buf;
00630     ssize_t nwrite;
00631 
00632     if (row < 0 || row >= fcb->cellhd.rows)
00633         return 0;
00634 
00635     if (n <= 0)
00636         return 0;
00637 
00638     if (random)
00639     {
00640         if (seek_random(fd, row, col) == -1)
00641             return -1;
00642     }
00643     else if (compressed)
00644         set_file_pointer(fd, row);
00645 
00646     if (compressed)
00647         wk++;
00648 
00649     convert_int(wk, cell, col, n, random, len, zeros_r_nulls);
00650 
00651     if (compressed)
00652     {
00653         unsigned char *wk = G__.work_buf + 1;
00654         int nbytes = count_bytes(wk, n, len);
00655 
00656         if (fcb->nbytes < nbytes)
00657             fcb->nbytes = nbytes;
00658 
00659         /* first trim away zero high bytes */
00660         if (nbytes < len)
00661             trim_bytes(wk, n, len, len - nbytes);
00662 
00663         G__.compressed_buf[0] = G__.work_buf[0] = nbytes;
00664 
00665         /* then compress the data */
00666         nwrite = compressed == 1
00667             ? rle_compress(G__.compressed_buf + 1, G__.work_buf + 1, n, nbytes)
00668             : zlib_compress(G__.compressed_buf + 1, G__.work_buf + 1, n, nbytes);
00669 
00670         if (nwrite > 0)
00671         {
00672             nwrite++;
00673 
00674             if (write(fd, G__.compressed_buf, nwrite) != nwrite)
00675             {
00676                 write_error(fd, row);
00677                 return -1;
00678             }
00679         }
00680         else
00681         {
00682             nwrite = nbytes * n + 1;
00683             if (write(fd, G__.work_buf, nwrite) != nwrite)
00684             {
00685                 write_error(fd, row);
00686                 return -1;
00687             }
00688         }
00689     }
00690     else
00691     {
00692         nwrite = fcb->nbytes * n;
00693 
00694         if (write(fd, G__.work_buf, nwrite) != nwrite)
00695         {
00696             write_error(fd, row);
00697             return -1;
00698         }
00699     }
00700 
00701     return 1;
00702 }
00703 
00704 /*--------------------------------------------------------------------------*/
00705 /*--------------------------------------------------------------------------*/
00706 /*--------------------------------------------------------------------------*/
00707 
00708 static int put_raster_data(int fd, void *rast, int row, int col, int n, int zeros_r_nulls, RASTER_MAP_TYPE map_type)
00709 {
00710     return (map_type == CELL_TYPE)
00711         ? put_data(fd, rast, row, col, n, zeros_r_nulls)
00712         : put_fp_data(fd, rast, row, col, n, map_type);
00713 }
00714 
00715 /*--------------------------------------------------------------------------*/
00716 /*--------------------------------------------------------------------------*/
00717 /*--------------------------------------------------------------------------*/
00718 
00719 static int put_null_data(int fd, char *flags, int row)
00720 {
00721     struct fileinfo *fcb = &G__.fileinfo[fd];
00722     int null_fd, i;
00723 
00724     if (fcb->min_null_row + NULL_ROWS_INMEM <= row)
00725     {
00726         /* the row is out of the range of rows stored in memory */
00727         /* write out all the rows kept in memory, and initialize memory
00728            for keeping new NULL_ROWS_INMEM rows */
00729 
00730         if (fcb->min_null_row >= 0)
00731         {
00732             null_fd = G__open_null_write(fd);
00733             if (null_fd < 0)
00734                 return -1;
00735 
00736             for (i = 0; i < NULL_ROWS_INMEM; i++)
00737             {
00738                 /* fcb->cellhd.rows doesn't have to be a miultiple of NULL_ROWS_INMEM */
00739                 if (i + fcb->min_null_row >= fcb->cellhd.rows)
00740                     break;
00741 
00742                 if (G__write_null_bits(null_fd, fcb->NULL_ROWS[i], 
00743                                        i+fcb->min_null_row, fcb->cellhd.cols, fd) < 0)
00744                     return -1;
00745 
00746             } /* done writing out memory rows */
00747             if (null_fd >= 0)
00748                 close(null_fd);
00749         }
00750 
00751         /* now initialize memory to store new NULL_ROWS_INMEM rows */
00752         fcb->min_null_row = fcb->min_null_row + NULL_ROWS_INMEM;
00753         /* init memory to store next NULL_ROWS_INMEM rows */
00754     }
00755 
00756     /* remember the null row for i for the future writing */
00757     G__convert_01_flags(flags, fcb->NULL_ROWS[row - fcb->min_null_row], fcb->cellhd.cols);
00758 
00759     return 1;
00760 }
00761 
00762 int G__open_null_write(int fd)
00763 {
00764     struct fileinfo *fcb = &G__.fileinfo[fd];
00765     int null_fd;
00766 
00767     if (access(fcb->null_temp_name, 0) != 0) 
00768     {
00769         G_warning(_("unable to find a temporary null file %s"), fcb->null_temp_name);
00770         return -1;
00771     }
00772 
00773     null_fd = open(fcb->null_temp_name, O_WRONLY);
00774     if (null_fd < 0)
00775         return -1;
00776 
00777     return null_fd;
00778 }
00779 
00780 int G__write_null_bits(int null_fd, unsigned char *flags, int row, int cols, int fd)
00781 {
00782     off_t offset;
00783     size_t size;
00784 
00785     size = G__null_bitstream_size(cols);
00786     offset = (off_t) size * row;
00787 
00788     if (lseek(null_fd, offset, SEEK_SET) < 0)
00789     {
00790         G_warning(_("error writing null row %d"), row);
00791         return -1;
00792     }
00793 
00794     if (write(null_fd, flags, size) != size)
00795     {
00796         G_warning(_("error writing null row %d"), row);
00797         return -1;
00798     }
00799 
00800     return 1;
00801 }
00802 
00803 /*--------------------------------------------------------------------------*/
00804 /*--------------------------------------------------------------------------*/
00805 /*--------------------------------------------------------------------------*/
00806 
00807 static int convert_and_write_if(int fd, CELL *buf)
00808 {
00809     struct fileinfo *fcb = &G__.fileinfo[fd];
00810     FCELL *p = (FCELL *) fcb->data;
00811     int i;
00812 
00813     for (i = 0; i < fcb->cellhd.cols; i++)
00814         if (G_is_c_null_value(&buf[i]))
00815             G_set_f_null_value(&p[i], 1);
00816         else
00817             p[i] = (FCELL) buf[i];
00818 
00819     return G_put_f_raster_row(fd, p);
00820 }
00821 
00822 static int convert_and_write_df(int fd, DCELL *buf)
00823 {
00824     struct fileinfo *fcb = &G__.fileinfo[fd];
00825     FCELL *p = (FCELL *) fcb->data;
00826     int i;
00827 
00828     for (i = 0; i < fcb->cellhd.cols; i++)
00829         if (G_is_d_null_value(&buf[i]))
00830             G_set_f_null_value(&p[i], 1);
00831         else
00832             p[i] = (FCELL) buf[i];
00833 
00834     return G_put_f_raster_row(fd, p);
00835 }
00836 
00837 static int convert_and_write_id(int fd, CELL *buf)
00838 {
00839     struct fileinfo *fcb = &G__.fileinfo[fd];
00840     DCELL *p = (DCELL *) fcb->data;
00841     int i;
00842 
00843     for (i = 0; i < fcb->cellhd.cols; i++)
00844         if (G_is_c_null_value(&buf[i]))
00845             G_set_d_null_value(&p[i], 1);
00846         else
00847             p[i] = (DCELL) buf[i];
00848 
00849     return G_put_d_raster_row(fd, p);
00850 }
00851 
00852 static int convert_and_write_fd(int fd, FCELL *buf)
00853 {
00854     struct fileinfo *fcb = &G__.fileinfo[fd];
00855     DCELL *p = (DCELL *) fcb->data;
00856     int i;
00857 
00858     for (i = 0; i < fcb->cellhd.cols; i++)
00859         if (G_is_f_null_value(&buf[i]))
00860             G_set_d_null_value(&p[i], 1);
00861         else
00862             p[i] = (DCELL) buf[i];
00863 
00864     return G_put_d_raster_row(fd, p);
00865 }
00866 
00867 static int convert_and_write_fi(int fd, FCELL *buf)
00868 {
00869     struct fileinfo *fcb = &G__.fileinfo[fd];
00870     CELL *p = (CELL *) fcb->data;
00871     int i;
00872 
00873     for (i = 0; i < fcb->cellhd.cols; i++)
00874         if (G_is_f_null_value(&buf[i]))
00875             G_set_c_null_value(&p[i], 1);
00876         else
00877             p[i] = (CELL) buf[i];
00878 
00879     return G_put_c_raster_row(fd, p);
00880 }
00881 
00882 static int convert_and_write_di(int fd, DCELL *buf)
00883 {
00884     struct fileinfo *fcb = &G__.fileinfo[fd];
00885     CELL *p = (CELL *) fcb->data;
00886     int i;
00887 
00888     for (i = 0; i < fcb->cellhd.cols; i++)
00889         if (G_is_d_null_value(&buf[i]))
00890             G_set_c_null_value(&p[i], 1);
00891         else
00892             p[i] = (CELL) buf[i];
00893 
00894     return G_put_c_raster_row(fd, p);
00895 }
00896 
00897 /*--------------------------------------------------------------------------*/
00898 
00899 static int put_raster_row(
00900     int fd, void *buf, RASTER_MAP_TYPE data_type, int zeros_r_nulls)
00901 {
00902     struct fileinfo *fcb = &G__.fileinfo[fd];
00903 
00904     static int (*convert_and_write_FtypeOtype[3][3])() = {
00905         {NULL                , convert_and_write_if, convert_and_write_id},
00906         {convert_and_write_fi, NULL                , convert_and_write_fd},
00907         {convert_and_write_di, convert_and_write_df, NULL                }
00908     };
00909 
00910     if (!check_open("put_raster_row", fd, 0))
00911         return -1;
00912 
00913     if (fcb->map_type != data_type)
00914         return convert_and_write_FtypeOtype[data_type][fcb->map_type](fd, buf);
00915 
00916     G_zero(G__.null_buf, fcb->cellhd.cols * sizeof(char));
00917 
00918     switch (put_raster_data(fd, buf, fcb->cur_row, 0, fcb->cellhd.cols, zeros_r_nulls, data_type))
00919     {
00920     case -1: return -1;
00921     case  0: return  1;
00922     }
00923 
00924     /* only for integer maps */
00925     if (data_type == CELL_TYPE)
00926     {
00927         if (fcb->want_histogram)
00928             G_update_cell_stats(buf, fcb->cellhd.cols, &fcb->statf);
00929         G__row_update_range(buf, fcb->cellhd.cols, &fcb->range, zeros_r_nulls);
00930     }
00931     else
00932         G_row_update_fp_range (buf, fcb->cellhd.cols, &fcb->fp_range, data_type);
00933 
00934     fcb->cur_row++;
00935 
00936     /* write the null row for the data row */
00937     return G__put_null_value_row(fd, G__.null_buf);
00938 }

Generated on Wed Dec 19 14:59:06 2007 for GRASS by  doxygen 1.5.4