put_row.c 23 KB

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