00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
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 "config.h"
00134
00135 #include "G.h"
00136 #include "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
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 return 1;
00203 }
00204
00205 int G_put_map_row(int fd, CELL *buf)
00206 {
00207 struct fileinfo *fcb = &G__.fileinfo[fd];
00208
00209 if (fcb->map_type != CELL_TYPE)
00210 {
00211 G_fatal_error("G_put_map_row: %s is not integer! Use G_put_[f/d]_raster_row()!",
00212 fcb->name);
00213 return -1;
00214 }
00215
00216 return put_raster_row(fd, buf, CELL_TYPE, _zeros_r_nulls);
00217 }
00218
00219 int G_put_raster_row(int fd, void *buf, RASTER_MAP_TYPE data_type)
00220 {
00221 return put_raster_row(fd, buf, data_type, 0);
00222 }
00223
00224 int G_put_c_raster_row(int fd, CELL *buf)
00225 {
00226 return G_put_raster_row(fd, buf, CELL_TYPE);
00227 }
00228
00229 int G_put_f_raster_row(int fd, FCELL *buf)
00230 {
00231 return G_put_raster_row(fd, buf, FCELL_TYPE);
00232 }
00233
00234 int G_put_d_raster_row(int fd, DCELL *buf)
00235 {
00236 return G_put_raster_row(fd, buf, DCELL_TYPE);
00237 }
00238
00239
00240
00241 static int check_open(const char *me, int fd, int random)
00242 {
00243 struct fileinfo *fcb = &G__.fileinfo[fd];
00244
00245 switch (fcb->open_mode)
00246 {
00247 case OPEN_OLD:
00248 G_warning(
00249 "%s: map [%s] not open for write - request ignored",
00250 me, fcb->name);
00251 break;
00252 case OPEN_NEW_COMPRESSED:
00253 case OPEN_NEW_UNCOMPRESSED:
00254 if (!random)
00255 return 1;
00256 G_warning(
00257 "%s: map [%s] not open for random write - request ignored",
00258 me, fcb->name);
00259 break;
00260 case OPEN_NEW_RANDOM:
00261 if (random)
00262 return 1;
00263 G_warning(
00264 "%s: map [%s] not open for sequential write - request ignored",
00265 me, fcb->name);
00266 break;
00267 default:
00268 G_warning(
00269 "%s: unopened file descriptor - request ignored",
00270 me);
00271 break;
00272 }
00273
00274 return 0;
00275 }
00276
00277
00278
00279
00280
00281
00282
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 {
00292 adj = -(*col);
00293 *col = 0;
00294 }
00295
00296 if (last > fcb->cellhd.cols)
00297 last = fcb->cellhd.cols;
00298
00299 *n = last - *col;
00300
00301 return adj;
00302 }
00303
00304 static void write_error(int fd,int row)
00305 {
00306 struct fileinfo *fcb = &G__.fileinfo[fd];
00307
00308 if (fcb->io_error)
00309 return;
00310
00311 G_warning(_("map [%s] - unable to write row %d"), fcb->name, row);
00312
00313 fcb->io_error = 1;
00314
00315 return;
00316 }
00317
00318
00319
00320 int G__write_data(int fd, int row, int n)
00321
00322 {
00323 struct fileinfo *fcb = &G__.fileinfo[fd];
00324 int nwrite = fcb->nbytes * n;
00325
00326 if (write(fd, G__.work_buf, nwrite) != nwrite)
00327 {
00328 write_error(fd, row);
00329 return -1;
00330 }
00331
00332 return 0;
00333 }
00334
00335 int G__write_data_compressed(int fd, int row, int n)
00336 {
00337 struct fileinfo *fcb = &G__.fileinfo[fd];
00338 int nwrite = fcb->nbytes * n;
00339
00340 if (G_zlib_write(fd, G__.work_buf, nwrite) < 0)
00341 {
00342 write_error(fd, row);
00343 return -1;
00344 }
00345
00346 return 0;
00347 }
00348
00349
00350
00351 static int seek_random(int fd, int row, int col)
00352 {
00353 struct fileinfo *fcb = &G__.fileinfo[fd];
00354 off_t offset = ((off_t) fcb->cellhd.cols * row + col) * fcb->nbytes;
00355
00356 if (lseek(fd, offset, 0) < 0)
00357 {
00358 write_error(fd, row);
00359 return -1;
00360 }
00361
00362 return 0;
00363 }
00364
00365
00366
00367 static void set_file_pointer(int fd, int row)
00368 {
00369 struct fileinfo *fcb = &G__.fileinfo[fd];
00370
00371 fcb->row_ptr[row] = lseek(fd, (off_t) 0, 1);
00372 }
00373
00374
00375
00376
00377
00378 static int convert_float(
00379 XDR *xdrs, const FCELL *rast, int row, int col, int n, int random)
00380 {
00381 int i;
00382
00383 for (i = 0; i < n; i++)
00384 {
00385 FCELL f;
00386
00387
00388 if (G_is_f_null_value(&rast[i]))
00389 {
00390 f = 0.;
00391 if (!random)
00392 G__.null_buf[col + i] = 1;
00393 }
00394 else
00395 f = rast[i];
00396
00397 if (!xdr_float(xdrs, &f))
00398 {
00399 G_warning("xdr_float failed for index %d of row %d.", i, row);
00400 return -1;
00401 }
00402 }
00403
00404 return 0;
00405 }
00406
00407 static int convert_double(
00408 XDR *xdrs, const DCELL *rast, int row, int col, int n, int random)
00409 {
00410 int i;
00411
00412 for (i = 0; i < n; i++)
00413 {
00414 DCELL d;
00415
00416
00417 if (G_is_d_null_value(&rast[i]))
00418 {
00419 d = 0.;
00420 if (!random)
00421 G__.null_buf[col + i] = 1;
00422 }
00423 else
00424 d = rast[i];
00425
00426 if (!xdr_double(xdrs, &d))
00427 {
00428 G_warning("xdr_double failed for index %d of row %d.", i, row);
00429 return -1;
00430 }
00431 }
00432
00433 return 0;
00434 }
00435
00436
00437
00438
00439
00440 static int put_fp_data(int fd, void *rast, int row, int col, int n, RASTER_MAP_TYPE data_type)
00441 {
00442 struct fileinfo *fcb = &G__.fileinfo[fd];
00443 int random = (fcb->open_mode == OPEN_NEW_RANDOM);
00444 int compressed = (fcb->open_mode == OPEN_NEW_COMPRESSED);
00445 XDR *xdrs = &fcb->xdrstream;
00446
00447 if (row < 0 || row >= fcb->cellhd.rows)
00448 return 0;
00449
00450 if (n <= 0)
00451 return 0;
00452
00453 if (random)
00454 {
00455 if (seek_random(fd, row, col) == -1)
00456 return -1;
00457 }
00458 else if (compressed)
00459 set_file_pointer(fd, row);
00460
00461 xdrmem_create(xdrs, (caddr_t) G__.work_buf,
00462 (u_int) (fcb->nbytes * fcb->cellhd.cols), XDR_ENCODE);
00463 xdr_setpos (xdrs, 0);
00464
00465 if (data_type == FCELL_TYPE)
00466 {
00467 if (convert_float(xdrs, rast, row, col, n, random) < 0)
00468 return -1;
00469 }
00470 else
00471 {
00472 if (convert_double(xdrs, rast, row, col, n, random) < 0)
00473 return -1;
00474 }
00475
00476 xdr_destroy(&fcb->xdrstream);
00477
00478 if (compressed)
00479 {
00480 if (G__write_data_compressed(fd, row, n) == -1)
00481 return -1;
00482 }
00483 else
00484 if (G__write_data(fd, row, n) == -1)
00485 return -1;
00486
00487 return 1;
00488 }
00489
00490
00491
00492
00493
00494 static void convert_int(
00495 unsigned char *wk, const CELL *rast, int col, int n,
00496 int random, int len, int zeros_r_nulls)
00497 {
00498 int i;
00499
00500
00501
00502 for (i = 0; i < n; i++)
00503 {
00504 CELL v = rast[i];
00505 int neg;
00506 int k;
00507
00508
00509 if (G_is_c_null_value(&v))
00510 {
00511 v = 0;
00512 if (!random)
00513 G__.null_buf[col + i] = 1;
00514 }
00515 else if (!random && zeros_r_nulls && !v)
00516 G__.null_buf[col + i] = 1;
00517
00518
00519 if (v < 0)
00520 {
00521 neg = 1;
00522 v = -v;
00523 }
00524 else
00525 neg = 0;
00526
00527
00528 for (k = len - 1; k >= 0; k--)
00529 {
00530 wk[k] = v & 0xff;
00531 v >>= 8;
00532 }
00533
00534
00535 if (neg)
00536 wk[0] |= 0x80 ;
00537
00538 wk += len;
00539 }
00540 }
00541
00542 static int count_bytes(const unsigned char *wk, int n, int len)
00543 {
00544 int i, j;
00545
00546 for (i = 0; i < len - 1; i++)
00547 for (j = 0; j < n; j++)
00548 if (wk[j * len + i] != 0)
00549 return len - i;
00550
00551 return 1;
00552 }
00553
00554 static void trim_bytes(unsigned char *wk, int n, int slen, int trim)
00555 {
00556 unsigned char *wk2 = wk;
00557 int i, j;
00558
00559 for (i = 0; i < n; i++)
00560 {
00561 for (j = 0; j < trim; j++)
00562 wk++;
00563 for ( ; j < slen; j++)
00564 *wk2++ = *wk++;
00565 }
00566 }
00567
00568 static int same(const unsigned char *x, const unsigned char *y, int n)
00569 {
00570 return memcmp(x, y, n) == 0;
00571 }
00572
00573 static int count_run(const unsigned char *src, int n, int nbytes)
00574 {
00575 const unsigned char *cur = src + nbytes;
00576 int i;
00577
00578 for (i = 1; i < n; i++)
00579 {
00580 if (i == 255 || !same(cur, src, nbytes))
00581 return i;
00582
00583 cur += nbytes;
00584 }
00585
00586 return n;
00587 }
00588
00589 static int rle_compress(unsigned char *dst, unsigned char *src, int n, int nbytes)
00590 {
00591 int nwrite = 0;
00592 int total = nbytes * n;
00593
00594 while (n > 0)
00595 {
00596 int count;
00597
00598 nwrite += nbytes + 1;
00599 if (nwrite >= total)
00600 return 0;
00601
00602 count = count_run(src, n, nbytes);
00603
00604 *dst++ = count;
00605 memcpy(dst, src, nbytes);
00606 dst += nbytes;
00607
00608 src += count * nbytes;
00609 n -= count;
00610 }
00611
00612 return nwrite;
00613 }
00614
00615 static int zlib_compress(unsigned char *dst, unsigned char *src, int n, int nbytes)
00616 {
00617 int total = nbytes * n;
00618 int nwrite = G_zlib_compress(G__.work_buf + 1, total,
00619 G__.compressed_buf + 1, G__.compressed_buf_size - 1);
00620
00621 return (nwrite >= total) ? 0 : nwrite;
00622 }
00623
00624
00625
00626 static int put_data(int fd, CELL *cell, int row, int col, int n, int zeros_r_nulls)
00627 {
00628 struct fileinfo *fcb = &G__.fileinfo[fd];
00629 int random = (fcb->open_mode == OPEN_NEW_RANDOM);
00630 int compressed = fcb->cellhd.compressed;
00631 int len = compressed ? sizeof(CELL) : fcb->nbytes;
00632 unsigned char *wk = G__.work_buf;
00633 int nwrite;
00634
00635 if (row < 0 || row >= fcb->cellhd.rows)
00636 return 0;
00637
00638 if (n <= 0)
00639 return 0;
00640
00641 if (random)
00642 {
00643 if (seek_random(fd, row, col) == -1)
00644 return -1;
00645 }
00646 else if (compressed)
00647 set_file_pointer(fd, row);
00648
00649 if (compressed)
00650 wk++;
00651
00652 convert_int(wk, cell, col, n, random, len, zeros_r_nulls);
00653
00654 if (compressed)
00655 {
00656 unsigned char *wk = G__.work_buf + 1;
00657 int nbytes = count_bytes(wk, n, len);
00658
00659 if (fcb->nbytes < nbytes)
00660 fcb->nbytes = nbytes;
00661
00662
00663 if (nbytes < len)
00664 trim_bytes(wk, n, len, len - nbytes);
00665
00666 G__.compressed_buf[0] = G__.work_buf[0] = nbytes;
00667
00668
00669 nwrite = compressed == 1
00670 ? rle_compress(G__.compressed_buf + 1, G__.work_buf + 1, n, nbytes)
00671 : zlib_compress(G__.compressed_buf + 1, G__.work_buf + 1, n, nbytes);
00672
00673 if (nwrite > 0)
00674 {
00675 nwrite++;
00676
00677 if (write(fd, G__.compressed_buf, nwrite) != nwrite)
00678 {
00679 write_error(fd, row);
00680 return -1;
00681 }
00682 }
00683 else
00684 {
00685 nwrite = nbytes * n + 1;
00686 if (write(fd, G__.work_buf, nwrite) != nwrite)
00687 {
00688 write_error(fd, row);
00689 return -1;
00690 }
00691 }
00692 }
00693 else
00694 {
00695 nwrite = fcb->nbytes * n;
00696
00697 if (write(fd, G__.work_buf, nwrite) != nwrite)
00698 {
00699 write_error(fd, row);
00700 return -1;
00701 }
00702 }
00703
00704 return 1;
00705 }
00706
00707
00708
00709
00710
00711 static int put_raster_data(int fd, void *rast, int row, int col, int n, int zeros_r_nulls, RASTER_MAP_TYPE map_type)
00712 {
00713 return (map_type == CELL_TYPE)
00714 ? put_data(fd, rast, row, col, n, zeros_r_nulls)
00715 : put_fp_data(fd, rast, row, col, n, map_type);
00716 }
00717
00718
00719
00720
00721
00722 static int put_null_data(int fd, char *flags, int row)
00723 {
00724 struct fileinfo *fcb = &G__.fileinfo[fd];
00725 int null_fd, i;
00726
00727 if (fcb->min_null_row + NULL_ROWS_INMEM <= row)
00728 {
00729
00730
00731
00732
00733 if (fcb->min_null_row >= 0)
00734 {
00735 null_fd = G__open_null_write(fd);
00736 if (null_fd < 0)
00737 return -1;
00738
00739 for (i = 0; i < NULL_ROWS_INMEM; i++)
00740 {
00741
00742 if (i + fcb->min_null_row >= fcb->cellhd.rows)
00743 break;
00744
00745 if (G__write_null_bits(null_fd, fcb->NULL_ROWS[i],
00746 i+fcb->min_null_row, fcb->cellhd.cols, fd) < 0)
00747 return -1;
00748
00749 }
00750 if (null_fd >= 0)
00751 close(null_fd);
00752 }
00753
00754
00755 fcb->min_null_row = fcb->min_null_row + NULL_ROWS_INMEM;
00756
00757 }
00758
00759
00760 G__convert_01_flags(flags, fcb->NULL_ROWS[row - fcb->min_null_row], fcb->cellhd.cols);
00761 return 1;
00762 }
00763
00764 int G__open_null_write(int fd)
00765 {
00766 struct fileinfo *fcb = &G__.fileinfo[fd];
00767 int null_fd;
00768
00769 if (access(fcb->null_temp_name, 0) != 0)
00770 {
00771 G_warning("unable to find a temporary null file %s",
00772 fcb->null_temp_name);
00773 return -1;
00774 }
00775
00776 null_fd = open(fcb->null_temp_name, O_WRONLY);
00777 if (null_fd < 0)
00778 return -1;
00779
00780 return null_fd;
00781 }
00782
00783 int G__write_null_bits(int null_fd, unsigned char *flags, int row, int cols, int fd)
00784 {
00785 off_t offset;
00786 int size;
00787
00788 size = G__null_bitstream_size(cols);
00789 offset = (off_t) size * row;
00790
00791 if (lseek(null_fd, offset, 0) < 0)
00792 {
00793 G_warning(_("error writing null row %d"),row);
00794 return -1;
00795 }
00796
00797 if (write(null_fd, flags, size) != size)
00798 {
00799 G_warning(_("error writing null row %d"),row);
00800 return -1;
00801 }
00802 return 1;
00803 }
00804
00805
00806
00807
00808
00809 static int convert_and_write_if(int fd, CELL *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_c_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_df(int fd, DCELL *buf)
00825 {
00826 struct fileinfo *fcb = &G__.fileinfo[fd];
00827 FCELL *p = (FCELL *) fcb->data;
00828 int i;
00829
00830 for (i = 0; i < fcb->cellhd.cols; i++)
00831 if (G_is_d_null_value(&buf[i]))
00832 G_set_f_null_value(&p[i], 1);
00833 else
00834 p[i] = (FCELL) buf[i];
00835
00836 return G_put_f_raster_row(fd, p);
00837 }
00838
00839 static int convert_and_write_id(int fd, CELL *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_c_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_fd(int fd, FCELL *buf)
00855 {
00856 struct fileinfo *fcb = &G__.fileinfo[fd];
00857 DCELL *p = (DCELL *) 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_d_null_value(&p[i], 1);
00863 else
00864 p[i] = (DCELL) buf[i];
00865
00866 return G_put_d_raster_row(fd, p);
00867 }
00868
00869 static int convert_and_write_fi(int fd, FCELL *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_f_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 static int convert_and_write_di(int fd, DCELL *buf)
00885 {
00886 struct fileinfo *fcb = &G__.fileinfo[fd];
00887 CELL *p = (CELL *) fcb->data;
00888 int i;
00889
00890 for (i = 0; i < fcb->cellhd.cols; i++)
00891 if (G_is_d_null_value(&buf[i]))
00892 G_set_c_null_value(&p[i], 1);
00893 else
00894 p[i] = (CELL) buf[i];
00895
00896 return G_put_c_raster_row(fd, p);
00897 }
00898
00899
00900
00901 static int put_raster_row(
00902 int fd, void *buf, RASTER_MAP_TYPE data_type, int zeros_r_nulls)
00903 {
00904 struct fileinfo *fcb = &G__.fileinfo[fd];
00905
00906 static int (*convert_and_write_FtypeOtype[3][3])() = {
00907 {NULL , convert_and_write_if, convert_and_write_id},
00908 {convert_and_write_fi, NULL , convert_and_write_fd},
00909 {convert_and_write_di, convert_and_write_df, NULL }
00910 };
00911
00912 if (!check_open("put_raster_row", fd, 0))
00913 return -1;
00914
00915 if (fcb->map_type != data_type)
00916 return convert_and_write_FtypeOtype[data_type][fcb->map_type](fd, buf);
00917
00918 G_zero(G__.null_buf, fcb->cellhd.cols * sizeof(char));
00919
00920 switch (put_raster_data(fd, buf, fcb->cur_row, 0, fcb->cellhd.cols, zeros_r_nulls, data_type))
00921 {
00922 case -1: return -1;
00923 case 0: return 1;
00924 }
00925
00926
00927 if (data_type == CELL_TYPE)
00928 {
00929 if (fcb->want_histogram)
00930 G_update_cell_stats(buf, fcb->cellhd.cols, &fcb->statf);
00931 G__row_update_range(buf, fcb->cellhd.cols, &fcb->range, zeros_r_nulls);
00932 }
00933 else
00934 G_row_update_fp_range (buf, fcb->cellhd.cols, &fcb->fp_range, data_type);
00935
00936 fcb->cur_row++;
00937
00938
00939 return G__put_null_value_row(fd, G__.null_buf);
00940 }
00941
00942
00943
00944
00945