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