put_row.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815
  1. /**********************************************************************
  2. *
  3. * G_put_[c/f/d]_raster_row(fd, buf)
  4. * int fd file descriptor of the opened map
  5. * [F/D]CELL *buf buffer holding row info to be written
  6. *
  7. * Writes the next row for the cell file opened on 'fd' from 'buf'
  8. * All writes go into NEW files that exactly match the current window.
  9. * The file must have been opened with G_open_cell_new()
  10. * and be written sequentially, ie no skipping rows
  11. *
  12. * when the null values are embeded into the data, corresponding cells are
  13. * changed to 0's and the corresponding null value row is written into null
  14. * file.
  15. *
  16. * *** NOTE ***
  17. * A map cannot be copied using G_get_raster_row() and G_put_raster_row().
  18. * The former resamples the data of the original map into a row buffer
  19. * that matches the current window. The later writes out rows associated
  20. * with the window.
  21. *
  22. * returns: 1 if successful
  23. * -1 on fail
  24. *
  25. * Keeps track of the minimum and maximum cell value for use in updating
  26. * the range file upon close of the cell file.
  27. * HOWEVER when nulls are not embeded, the cells are considered 0's as far
  28. * as updating range is concerned, even if the corresponding cell is null
  29. * in the resulting null file, so programmer should be carefult to set all
  30. * the null values using G_set_null_value() or G_insert_[d/f_]null_values()
  31. *
  32. **********************************************************************
  33. *
  34. * G_put_map_row(fd, buf)
  35. * int fd file descriptor of the opened map
  36. * CELL *buf buffer holding row info to be written
  37. *
  38. * Writes the next row for the cell file opened on 'fd' from 'buf'
  39. * All writes go into NEW files that exactly match the current window.
  40. * The file must have been opened with G_open_cell_new()
  41. * and be written sequentially, ie no skipping rows
  42. *
  43. * NULLS are written into null bitmap file for all cells which are zero,
  44. * and cells which have null value (these cells are converted to 0's before
  45. * writing)
  46. *
  47. * *** NOTE ***
  48. * A map cannot be copied using G_get_map_row() and G_put_map_row().
  49. * The former resamples the data of the original map into a row buffer
  50. * that matches the current window. The later writes out rows associated
  51. * with the window.
  52. *
  53. * returns: 1 if successful
  54. * -1 on fail
  55. *
  56. * Keeps track of the minimum and maximum cell value for use in updating
  57. * the range file upon close of the cell file.
  58. *
  59. ***********************************************************************
  60. *
  61. * G__put_null_value_row(fd, buf)
  62. * int fd File descriptor where data is to be written
  63. * char *buf Buffer holding null data
  64. *
  65. * converts a buffer of zero's and ones to bitstream and stores this
  66. * bitstream in memory. (the null rows from memory are written into null
  67. * file after the limit is reached, and the place for new null rows
  68. * to be kept in memory is freed. Should not be used by application
  69. * programs.
  70. *
  71. * returns: 0 if successful
  72. * -1 on fail
  73. **********************************************************************/
  74. #include <string.h>
  75. #include <sys/types.h>
  76. #include <sys/stat.h>
  77. #include <unistd.h>
  78. #include <fcntl.h>
  79. #include <grass/config.h>
  80. #include "G.h"
  81. #include <grass/glocale.h>
  82. static int put_raster_data(int, char *, const void *, int, int, int,
  83. RASTER_MAP_TYPE);
  84. static int put_data(int, char *, const CELL *, int, int, int);
  85. static int check_open(const char *, int);
  86. static void write_error(int, int);
  87. static int same(const unsigned char *, const unsigned char *, int);
  88. static void set_file_pointer(int, int);
  89. static int put_fp_data(int, char *, const void *, int, int, RASTER_MAP_TYPE);
  90. static int put_null_data(int, const char *, int);
  91. static int convert_and_write_if(int, const CELL *);
  92. static int convert_and_write_id(int, const CELL *);
  93. static int convert_and_write_df(int, const DCELL *);
  94. static int convert_and_write_fd(int, const FCELL *);
  95. static int put_raster_row(int fd, const void *buf, RASTER_MAP_TYPE data_type,
  96. int zeros_r_nulls);
  97. /*--------------------------------------------------------------------------*/
  98. /*--------------------------------------------------------------------------*/
  99. /*--------------------------------------------------------------------------*/
  100. int G__put_null_value_row(int fd, const char *buf)
  101. {
  102. struct fileinfo *fcb = &G__.fileinfo[fd];
  103. switch (put_null_data(fd, buf, fcb->null_cur_row)) {
  104. case -1:
  105. return -1;
  106. case 0:
  107. return 1;
  108. }
  109. fcb->null_cur_row++;
  110. return 1;
  111. }
  112. int G_put_map_row(int fd, const CELL * buf)
  113. {
  114. struct fileinfo *fcb = &G__.fileinfo[fd];
  115. if (fcb->map_type != CELL_TYPE) {
  116. G_fatal_error(_("G_put_map_row: %s is not integer! Use G_put_[f/d]_raster_row()!"),
  117. fcb->name);
  118. return -1;
  119. }
  120. return put_raster_row(fd, buf, CELL_TYPE, 1);
  121. }
  122. int G_put_raster_row(int fd, const void *buf, RASTER_MAP_TYPE data_type)
  123. {
  124. return put_raster_row(fd, buf, data_type, 0);
  125. }
  126. int G_put_c_raster_row(int fd, const CELL * buf)
  127. {
  128. return G_put_raster_row(fd, buf, CELL_TYPE);
  129. }
  130. int G_put_f_raster_row(int fd, const FCELL * buf)
  131. {
  132. return G_put_raster_row(fd, buf, FCELL_TYPE);
  133. }
  134. int G_put_d_raster_row(int fd, const DCELL * buf)
  135. {
  136. return G_put_raster_row(fd, buf, DCELL_TYPE);
  137. }
  138. /*--------------------------------------------------------------------------*/
  139. static int check_open(const char *me, int fd)
  140. {
  141. struct fileinfo *fcb = &G__.fileinfo[fd];
  142. switch (fcb->open_mode) {
  143. case OPEN_OLD:
  144. G_warning(_("%s: map [%s] not open for write - request ignored"), me,
  145. fcb->name);
  146. break;
  147. case OPEN_NEW_COMPRESSED:
  148. case OPEN_NEW_UNCOMPRESSED:
  149. return 1;
  150. break;
  151. default:
  152. G_warning(_("%s: unopened file descriptor - request ignored"), me);
  153. break;
  154. }
  155. return 0;
  156. }
  157. static void write_error(int fd, int row)
  158. {
  159. struct fileinfo *fcb = &G__.fileinfo[fd];
  160. if (fcb->io_error)
  161. return;
  162. G_warning(_("map [%s] - unable to write row %d"), fcb->name, row);
  163. fcb->io_error = 1;
  164. }
  165. /*--------------------------------------------------------------------------*/
  166. static int write_data(int fd, int row, unsigned char *buf, int n)
  167. {
  168. struct fileinfo *fcb = &G__.fileinfo[fd];
  169. ssize_t nwrite = fcb->nbytes * n;
  170. if (write(fd, buf, nwrite) != nwrite) {
  171. write_error(fd, row);
  172. return -1;
  173. }
  174. return 0;
  175. }
  176. static int write_data_compressed(int fd, int row, unsigned char *buf, int n)
  177. {
  178. struct fileinfo *fcb = &G__.fileinfo[fd];
  179. int nwrite = fcb->nbytes * n;
  180. if (G_zlib_write(fd, buf, nwrite) < 0) {
  181. write_error(fd, row);
  182. return -1;
  183. }
  184. return 0;
  185. }
  186. /*--------------------------------------------------------------------------*/
  187. static void set_file_pointer(int fd, int row)
  188. {
  189. struct fileinfo *fcb = &G__.fileinfo[fd];
  190. fcb->row_ptr[row] = lseek(fd, 0L, SEEK_CUR);
  191. }
  192. /*--------------------------------------------------------------------------*/
  193. /*--------------------------------------------------------------------------*/
  194. /*--------------------------------------------------------------------------*/
  195. static int convert_float(XDR * xdrs, char *null_buf, const FCELL * rast,
  196. int row, int n)
  197. {
  198. int i;
  199. for (i = 0; i < n; i++) {
  200. FCELL f;
  201. /* substitute embeded null vals by 0's */
  202. if (G_is_f_null_value(&rast[i])) {
  203. f = 0.;
  204. null_buf[i] = 1;
  205. }
  206. else
  207. f = rast[i];
  208. if (!xdr_float(xdrs, &f)) {
  209. G_warning(_("xdr_float failed for index %d of row %d"), i, row);
  210. return -1;
  211. }
  212. }
  213. return 0;
  214. }
  215. static int convert_double(XDR * xdrs, char *null_buf, const DCELL * rast,
  216. int row, int n)
  217. {
  218. int i;
  219. for (i = 0; i < n; i++) {
  220. DCELL d;
  221. /* substitute embeded null vals by 0's */
  222. if (G_is_d_null_value(&rast[i])) {
  223. d = 0.;
  224. null_buf[i] = 1;
  225. }
  226. else
  227. d = rast[i];
  228. if (!xdr_double(xdrs, &d)) {
  229. G_warning(_("xdr_double failed for index %d of row %d"), i, row);
  230. return -1;
  231. }
  232. }
  233. return 0;
  234. }
  235. /*--------------------------------------------------------------------------*/
  236. /* writes data to fcell file for either full or partial rows */
  237. static int put_fp_data(int fd, char *null_buf, const void *rast,
  238. int row, int n, RASTER_MAP_TYPE data_type)
  239. {
  240. struct fileinfo *fcb = &G__.fileinfo[fd];
  241. int compressed = (fcb->open_mode == OPEN_NEW_COMPRESSED);
  242. XDR *xdrs = &fcb->xdrstream;
  243. char *work_buf;
  244. if (row < 0 || row >= fcb->cellhd.rows)
  245. return 0;
  246. if (n <= 0)
  247. return 0;
  248. work_buf = G__alloca(G__.window.cols * fcb->nbytes + 1);
  249. if (compressed)
  250. set_file_pointer(fd, row);
  251. xdrmem_create(xdrs, work_buf,
  252. (unsigned int) fcb->nbytes * fcb->cellhd.cols, XDR_ENCODE);
  253. xdr_setpos(xdrs, 0);
  254. if (data_type == FCELL_TYPE) {
  255. if (convert_float(xdrs, null_buf, rast, row, n) < 0) {
  256. G__freea(work_buf);
  257. return -1;
  258. }
  259. }
  260. else {
  261. if (convert_double(xdrs, null_buf, rast, row, n) < 0) {
  262. G__freea(work_buf);
  263. return -1;
  264. }
  265. }
  266. xdr_destroy(&fcb->xdrstream);
  267. if (compressed) {
  268. if (write_data_compressed(fd, row, work_buf, n) == -1) {
  269. G__freea(work_buf);
  270. return -1;
  271. }
  272. }
  273. else if (write_data(fd, row, work_buf, n) == -1) {
  274. G__freea(work_buf);
  275. return -1;
  276. }
  277. G__freea(work_buf);
  278. return 1;
  279. }
  280. /*--------------------------------------------------------------------------*/
  281. /*--------------------------------------------------------------------------*/
  282. /*--------------------------------------------------------------------------*/
  283. static void convert_int(unsigned char *wk, char *null_buf, const CELL * rast,
  284. int n, int len, int zeros_r_nulls)
  285. {
  286. int i;
  287. /* transform CELL data into non-machine dependent multi-byte format */
  288. for (i = 0; i < n; i++) {
  289. CELL v = rast[i];
  290. int neg;
  291. int k;
  292. /* substitute embeded null vals by 0's */
  293. if (G_is_c_null_value(&v)) {
  294. v = 0;
  295. null_buf[i] = 1;
  296. }
  297. else if (zeros_r_nulls && !v)
  298. null_buf[i] = 1;
  299. /* negatives */
  300. if (v < 0) {
  301. neg = 1;
  302. v = -v;
  303. }
  304. else
  305. neg = 0;
  306. /* copy byte by byte */
  307. for (k = len - 1; k >= 0; k--) {
  308. wk[k] = v & 0xff;
  309. v >>= 8;
  310. }
  311. /* set negative bit in first byte */
  312. if (neg)
  313. wk[0] |= 0x80;
  314. wk += len;
  315. }
  316. }
  317. static int count_bytes(const unsigned char *wk, int n, int len)
  318. {
  319. int i, j;
  320. for (i = 0; i < len - 1; i++)
  321. for (j = 0; j < n; j++)
  322. if (wk[j * len + i] != 0)
  323. return len - i;
  324. return 1;
  325. }
  326. static void trim_bytes(unsigned char *wk, int n, int slen, int trim)
  327. {
  328. unsigned char *wk2 = wk;
  329. int i, j;
  330. for (i = 0; i < n; i++) {
  331. for (j = 0; j < trim; j++)
  332. wk++;
  333. for (; j < slen; j++)
  334. *wk2++ = *wk++;
  335. }
  336. }
  337. static int same(const unsigned char *x, const unsigned char *y, int n)
  338. {
  339. return (memcmp(x, y, n) == 0);
  340. }
  341. static int count_run(const unsigned char *src, int n, int nbytes)
  342. {
  343. const unsigned char *cur = src + nbytes;
  344. int i;
  345. for (i = 1; i < n; i++) {
  346. if (i == 255 || !same(cur, src, nbytes))
  347. return i;
  348. cur += nbytes;
  349. }
  350. return n;
  351. }
  352. static int rle_compress(unsigned char *dst, unsigned char *src, int n,
  353. int nbytes)
  354. {
  355. int nwrite = 0;
  356. int total = nbytes * n;
  357. while (n > 0) {
  358. int count;
  359. nwrite += nbytes + 1;
  360. if (nwrite >= total)
  361. return 0;
  362. count = count_run(src, n, nbytes);
  363. *dst++ = count;
  364. memcpy(dst, src, nbytes);
  365. dst += nbytes;
  366. src += count * nbytes;
  367. n -= count;
  368. }
  369. return nwrite;
  370. }
  371. static int zlib_compress(unsigned char *dst, unsigned char *src, int n,
  372. int nbytes)
  373. {
  374. int total = nbytes * n;
  375. int nwrite = G_zlib_compress(src, total, dst, total);
  376. return (nwrite >= total) ? 0 : nwrite;
  377. }
  378. /*--------------------------------------------------------------------------*/
  379. static int put_data(int fd, char *null_buf, const CELL *cell,
  380. int row, int n, int zeros_r_nulls)
  381. {
  382. struct fileinfo *fcb = &G__.fileinfo[fd];
  383. int compressed = fcb->cellhd.compressed;
  384. int len = compressed ? sizeof(CELL) : fcb->nbytes;
  385. unsigned char *work_buf, *wk;
  386. ssize_t nwrite;
  387. if (row < 0 || row >= fcb->cellhd.rows)
  388. return 0;
  389. if (n <= 0)
  390. return 0;
  391. work_buf = G__alloca(G__.window.cols * sizeof(CELL) + 1);
  392. wk = work_buf;
  393. if (compressed)
  394. set_file_pointer(fd, row);
  395. if (compressed)
  396. wk++;
  397. convert_int(wk, null_buf, cell, n, len, zeros_r_nulls);
  398. if (compressed) {
  399. unsigned char *wk = work_buf + 1;
  400. int nbytes = count_bytes(wk, n, len);
  401. unsigned char *compressed_buf;
  402. int total;
  403. if (fcb->nbytes < nbytes)
  404. fcb->nbytes = nbytes;
  405. /* first trim away zero high bytes */
  406. if (nbytes < len)
  407. trim_bytes(wk, n, len, len - nbytes);
  408. total = nbytes * n;
  409. compressed_buf = G__alloca(total + 1);
  410. compressed_buf[0] = work_buf[0] = nbytes;
  411. /* then compress the data */
  412. nwrite = compressed == 1
  413. ? rle_compress(compressed_buf + 1, work_buf + 1, n,
  414. nbytes)
  415. : zlib_compress(compressed_buf + 1, work_buf + 1, n,
  416. nbytes);
  417. if (nwrite > 0) {
  418. nwrite++;
  419. if (write(fd, compressed_buf, nwrite) != nwrite) {
  420. write_error(fd, row);
  421. G__freea(compressed_buf);
  422. G__freea(work_buf);
  423. return -1;
  424. }
  425. }
  426. else {
  427. nwrite = nbytes * n + 1;
  428. if (write(fd, work_buf, nwrite) != nwrite) {
  429. write_error(fd, row);
  430. G__freea(compressed_buf);
  431. G__freea(work_buf);
  432. return -1;
  433. }
  434. }
  435. G__freea(compressed_buf);
  436. }
  437. else {
  438. nwrite = fcb->nbytes * n;
  439. if (write(fd, work_buf, nwrite) != nwrite) {
  440. write_error(fd, row);
  441. G__freea(work_buf);
  442. return -1;
  443. }
  444. }
  445. G__freea(work_buf);
  446. return 1;
  447. }
  448. /*--------------------------------------------------------------------------*/
  449. /*--------------------------------------------------------------------------*/
  450. /*--------------------------------------------------------------------------*/
  451. static int put_raster_data(int fd, char *null_buf, const void *rast,
  452. int row, int n,
  453. int zeros_r_nulls, RASTER_MAP_TYPE map_type)
  454. {
  455. return (map_type == CELL_TYPE)
  456. ? put_data(fd, null_buf, rast, row, n, zeros_r_nulls)
  457. : put_fp_data(fd, null_buf, rast, row, n, map_type);
  458. }
  459. /*--------------------------------------------------------------------------*/
  460. /*--------------------------------------------------------------------------*/
  461. /*--------------------------------------------------------------------------*/
  462. static int put_null_data(int fd, const char *flags, int row)
  463. {
  464. struct fileinfo *fcb = &G__.fileinfo[fd];
  465. int null_fd, i;
  466. if (fcb->min_null_row + NULL_ROWS_INMEM <= row) {
  467. /* the row is out of the range of rows stored in memory */
  468. /* write out all the rows kept in memory, and initialize memory
  469. for keeping new NULL_ROWS_INMEM rows */
  470. if (fcb->min_null_row >= 0) {
  471. null_fd = G__open_null_write(fd);
  472. if (null_fd < 0)
  473. return -1;
  474. for (i = 0; i < NULL_ROWS_INMEM; i++) {
  475. /* fcb->cellhd.rows doesn't have to be a miultiple of NULL_ROWS_INMEM */
  476. if (i + fcb->min_null_row >= fcb->cellhd.rows)
  477. break;
  478. if (G__write_null_bits(null_fd, fcb->NULL_ROWS[i],
  479. i + fcb->min_null_row,
  480. fcb->cellhd.cols, fd) < 0)
  481. return -1;
  482. } /* done writing out memory rows */
  483. if (null_fd >= 0)
  484. close(null_fd);
  485. }
  486. /* now initialize memory to store new NULL_ROWS_INMEM rows */
  487. fcb->min_null_row = fcb->min_null_row + NULL_ROWS_INMEM;
  488. /* init memory to store next NULL_ROWS_INMEM rows */
  489. }
  490. /* remember the null row for i for the future writing */
  491. G__convert_01_flags(flags, fcb->NULL_ROWS[row - fcb->min_null_row],
  492. fcb->cellhd.cols);
  493. return 1;
  494. }
  495. int G__open_null_write(int fd)
  496. {
  497. struct fileinfo *fcb = &G__.fileinfo[fd];
  498. int null_fd;
  499. if (access(fcb->null_temp_name, 0) != 0) {
  500. G_warning(_("unable to find a temporary null file %s"),
  501. fcb->null_temp_name);
  502. return -1;
  503. }
  504. null_fd = open(fcb->null_temp_name, O_WRONLY);
  505. if (null_fd < 0)
  506. return -1;
  507. return null_fd;
  508. }
  509. int G__write_null_bits(int null_fd, const unsigned char *flags, int row,
  510. int cols, int fd)
  511. {
  512. off_t offset;
  513. size_t size;
  514. size = G__null_bitstream_size(cols);
  515. offset = (off_t) size *row;
  516. if (lseek(null_fd, offset, SEEK_SET) < 0) {
  517. G_warning(_("error writing null row %d"), row);
  518. return -1;
  519. }
  520. if (write(null_fd, flags, size) != size) {
  521. G_warning(_("error writing null row %d"), row);
  522. return -1;
  523. }
  524. return 1;
  525. }
  526. /*--------------------------------------------------------------------------*/
  527. /*--------------------------------------------------------------------------*/
  528. /*--------------------------------------------------------------------------*/
  529. static int convert_and_write_if(int fd, const CELL * buf)
  530. {
  531. struct fileinfo *fcb = &G__.fileinfo[fd];
  532. FCELL *p = (FCELL *) fcb->data;
  533. int i;
  534. for (i = 0; i < fcb->cellhd.cols; i++)
  535. if (G_is_c_null_value(&buf[i]))
  536. G_set_f_null_value(&p[i], 1);
  537. else
  538. p[i] = (FCELL) buf[i];
  539. return G_put_f_raster_row(fd, p);
  540. }
  541. static int convert_and_write_df(int fd, const DCELL * buf)
  542. {
  543. struct fileinfo *fcb = &G__.fileinfo[fd];
  544. FCELL *p = (FCELL *) fcb->data;
  545. int i;
  546. for (i = 0; i < fcb->cellhd.cols; i++)
  547. if (G_is_d_null_value(&buf[i]))
  548. G_set_f_null_value(&p[i], 1);
  549. else
  550. p[i] = (FCELL) buf[i];
  551. return G_put_f_raster_row(fd, p);
  552. }
  553. static int convert_and_write_id(int fd, const CELL * buf)
  554. {
  555. struct fileinfo *fcb = &G__.fileinfo[fd];
  556. DCELL *p = (DCELL *) fcb->data;
  557. int i;
  558. for (i = 0; i < fcb->cellhd.cols; i++)
  559. if (G_is_c_null_value(&buf[i]))
  560. G_set_d_null_value(&p[i], 1);
  561. else
  562. p[i] = (DCELL) buf[i];
  563. return G_put_d_raster_row(fd, p);
  564. }
  565. static int convert_and_write_fd(int fd, const FCELL * buf)
  566. {
  567. struct fileinfo *fcb = &G__.fileinfo[fd];
  568. DCELL *p = (DCELL *) fcb->data;
  569. int i;
  570. for (i = 0; i < fcb->cellhd.cols; i++)
  571. if (G_is_f_null_value(&buf[i]))
  572. G_set_d_null_value(&p[i], 1);
  573. else
  574. p[i] = (DCELL) buf[i];
  575. return G_put_d_raster_row(fd, p);
  576. }
  577. static int convert_and_write_fi(int fd, const FCELL * buf)
  578. {
  579. struct fileinfo *fcb = &G__.fileinfo[fd];
  580. CELL *p = (CELL *) fcb->data;
  581. int i;
  582. for (i = 0; i < fcb->cellhd.cols; i++)
  583. if (G_is_f_null_value(&buf[i]))
  584. G_set_c_null_value(&p[i], 1);
  585. else
  586. p[i] = (CELL) buf[i];
  587. return G_put_c_raster_row(fd, p);
  588. }
  589. static int convert_and_write_di(int fd, const DCELL * buf)
  590. {
  591. struct fileinfo *fcb = &G__.fileinfo[fd];
  592. CELL *p = (CELL *) fcb->data;
  593. int i;
  594. for (i = 0; i < fcb->cellhd.cols; i++)
  595. if (G_is_d_null_value(&buf[i]))
  596. G_set_c_null_value(&p[i], 1);
  597. else
  598. p[i] = (CELL) buf[i];
  599. return G_put_c_raster_row(fd, p);
  600. }
  601. /*--------------------------------------------------------------------------*/
  602. static int put_raster_row(int fd, const void *buf, RASTER_MAP_TYPE data_type,
  603. int zeros_r_nulls)
  604. {
  605. static int (*convert_and_write_FtypeOtype[3][3])() = {
  606. {NULL, convert_and_write_if, convert_and_write_id},
  607. {convert_and_write_fi, NULL, convert_and_write_fd},
  608. {convert_and_write_di, convert_and_write_df, NULL}
  609. };
  610. struct fileinfo *fcb = &G__.fileinfo[fd];
  611. char *null_buf;
  612. int stat;
  613. if (!check_open("put_raster_row", fd))
  614. return -1;
  615. if (fcb->map_type != data_type)
  616. return convert_and_write_FtypeOtype[data_type][fcb->map_type] (fd,
  617. buf);
  618. null_buf = G__alloca(fcb->cellhd.cols);
  619. G_zero(null_buf, fcb->cellhd.cols);
  620. switch (put_raster_data(
  621. fd, null_buf, buf, fcb->cur_row, fcb->cellhd.cols,
  622. zeros_r_nulls, data_type)) {
  623. case -1:
  624. G__freea(null_buf);
  625. return -1;
  626. case 0:
  627. G__freea(null_buf);
  628. return 1;
  629. }
  630. /* only for integer maps */
  631. if (data_type == CELL_TYPE) {
  632. if (fcb->want_histogram)
  633. G_update_cell_stats(buf, fcb->cellhd.cols, &fcb->statf);
  634. G__row_update_range(buf, fcb->cellhd.cols, &fcb->range,
  635. zeros_r_nulls);
  636. }
  637. else
  638. G_row_update_fp_range(buf, fcb->cellhd.cols, &fcb->fp_range,
  639. data_type);
  640. fcb->cur_row++;
  641. /* write the null row for the data row */
  642. stat = G__put_null_value_row(fd, null_buf);
  643. G__freea(null_buf);
  644. return stat;
  645. }