GRASS Programmer's Manual
6.4.2(2012)
|
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 }