GRASS GIS 8 Programmer's Manual  8.4.0dev(2024)-fe06bd428d
plus_struct.c
Go to the documentation of this file.
1 /*****************************************************************************
2  *
3  * MODULE: Vector library
4  *
5  * AUTHOR(S): Dave Gerdes, CERL.
6  * Update to GRASS 5.7 Radim Blazek.
7  *
8  * PURPOSE: Lower level functions for reading/writing/manipulating vectors.
9  *
10  * COPYRIGHT: (C) 2001 by the GRASS Development Team
11  *
12  * This program is free software under the GNU General Public
13  * License (>=v2). Read the file COPYING that comes with GRASS
14  * for details.
15  *
16  *****************************************************************************/
17 
18 #include <inttypes.h>
19 #include <sys/types.h>
20 #include <string.h>
21 #include <grass/vector.h>
22 #include <grass/glocale.h>
23 #include <grass/version.h>
24 
25 /*
26  * Routines for reading and writing Dig+ structures.
27  * return 0 on success, -1 on failure of whatever kind
28  * if you don't want it written out, then don't call these routines
29  * ie check for deleted status before calling a write routine
30  * in as much as it would be nice to hide that code in here,
31  * this is a library routine and we chose to make it dependent on
32  * as few external files as possible
33  */
34 
35 /* These routines assume ptr->alloc_lines is valid
36  * Make sure it is initialized before calling
37  */
38 
39 /*
40  * Internally, my default variables for lines/areas/nodes/isles are type
41  * plus_t which is typedefed as short. This limits the current version
42  * to no more than 32K lines, nodes etc. (excluding points)
43  * All in the name of future expansion, I have converted these values to
44  * longs in the dig_plus data file.
45  *
46  * NOTE: 3.10 changes plus_t to ints.
47  * This assumes that any reasonable machine will use 4 bytes to
48  * store an int. The mapdev code is not guaranteed to work if
49  * plus_t is changed to a type that is larger than an int.
50  */
51 
52 int dig_Rd_P_node(struct Plus_head *Plus, int n, struct gvfile *fp)
53 {
54  int cnt, n_edges;
55  struct P_node *ptr;
56 
57  G_debug(4, "dig_Rd_P_node()");
58 
59  if (0 >= dig__fread_port_P(&cnt, 1, fp))
60  return (-1);
61 
62  if (cnt == 0) { /* dead */
63  G_debug(4, " node is dead");
64  Plus->Node[n] = NULL;
65  return 0;
66  }
67 
68  ptr = dig_alloc_node();
69  ptr->n_lines = cnt;
70 
71  if (dig_node_alloc_line(ptr, ptr->n_lines) == -1) {
72  dig_free_node(ptr);
73  return -1;
74  }
75 
76  if (ptr->n_lines) {
77  if (0 >= dig__fread_port_P(ptr->lines, ptr->n_lines, fp)) {
78  dig_free_node(ptr);
79  return (-1);
80  }
81  if (0 >= dig__fread_port_F(ptr->angles, ptr->n_lines, fp)) {
82  dig_free_node(ptr);
83  return (-1);
84  }
85  }
86 
87  if (Plus->with_z) {
88  if (0 >= dig__fread_port_P(&n_edges, 1, fp)) { /* reserved for edges */
89  dig_free_node(ptr);
90  return (-1);
91  }
92  }
93  /* here will be edges */
94 
95  if (0 >= dig__fread_port_D(&(ptr->x), 1, fp)) {
96  dig_free_node(ptr);
97  return (-1);
98  }
99  if (0 >= dig__fread_port_D(&(ptr->y), 1, fp)) {
100  dig_free_node(ptr);
101  return (-1);
102  }
103 
104  if (Plus->with_z) {
105  if (0 >= dig__fread_port_D(&(ptr->z), 1, fp)) {
106  dig_free_node(ptr);
107  return (-1);
108  }
109  }
110  else
111  ptr->z = 0;
112 
113  Plus->Node[n] = ptr;
114 
115  return (0);
116 }
117 
118 int dig_Wr_P_node(struct Plus_head *Plus, int n, struct gvfile *fp)
119 {
120  int i, n_edges = 0;
121  struct P_node *ptr;
122 
123  G_debug(4, "dig_Wr_P_node()");
124  ptr = Plus->Node[n];
125 
126  /* If NULL i.e. dead write just 0 instead of number of lines */
127  if (ptr == NULL) {
128  G_debug(4, " node is dead -> write 0 only");
129  i = 0;
130  if (0 >= dig__fwrite_port_P(&i, 1, fp))
131  return (-1);
132  return 0;
133  }
134 
135  if (0 >= dig__fwrite_port_P(&(ptr->n_lines), 1, fp))
136  return (-1);
137 
138  if (ptr->n_lines) {
139  if (0 >= dig__fwrite_port_P(ptr->lines, ptr->n_lines, fp))
140  return (-1);
141  if (0 >= dig__fwrite_port_F(ptr->angles, ptr->n_lines, fp))
142  return (-1);
143  }
144 
145  if (Plus->with_z)
146  if (0 >= dig__fwrite_port_P(&n_edges, 1, fp)) /* reserved for edges */
147  return (-1);
148 
149  /* here will be edges */
150 
151  if (0 >= dig__fwrite_port_D(&(ptr->x), 1, fp))
152  return (-1);
153  if (0 >= dig__fwrite_port_D(&(ptr->y), 1, fp))
154  return (-1);
155 
156  if (Plus->with_z)
157  if (0 >= dig__fwrite_port_D(&(ptr->z), 1, fp))
158  return (-1);
159 
160  return (0);
161 }
162 
163 int dig_Rd_P_line(struct Plus_head *Plus, int n, struct gvfile *fp)
164 {
165  int n_edges;
166  char tp;
167  struct P_line *ptr;
168 
169  G_debug(4, "dig_Rd_P_line()");
170 
171  if (0 >= dig__fread_port_C(&tp, 1, fp))
172  return (-1);
173 
174  if (tp == 0) { /* dead */
175  G_debug(4, " line is dead");
176  Plus->Line[n] = NULL;
177  return 0;
178  }
179 
180  ptr = dig_alloc_line();
181 
182  /* type */
183  ptr->type = dig_type_from_store(tp);
184  G_debug(5, " line type %d -> %d", tp, ptr->type);
185 
186  /* offset */
187  if (0 >= dig__fread_port_O(&(ptr->offset), 1, fp, Plus->off_t_size))
188  goto free_exit_failure;
189 
190  if (ptr->type == GV_POINT) {
191  ptr->topo = NULL;
192  }
193  else {
194  ptr->topo = dig_alloc_topo(ptr->type);
195  }
196 
197  /* centroids */
198  if (ptr->type & GV_CENTROID) {
199  struct P_topo_c *topo = (struct P_topo_c *)ptr->topo;
200 
201  if (0 >= dig__fread_port_P(&(topo->area), 1, fp))
202  goto free_exit_failure;
203  }
204  /* lines */
205  else if (ptr->type & GV_LINE) {
206  struct P_topo_l *topo = (struct P_topo_l *)ptr->topo;
207 
208  if (0 >= dig__fread_port_P(&(topo->N1), 1, fp))
209  goto free_exit_failure;
210  if (0 >= dig__fread_port_P(&(topo->N2), 1, fp))
211  goto free_exit_failure;
212  }
213  /* boundaries */
214  else if (ptr->type & GV_BOUNDARY) {
215  struct P_topo_b *topo = (struct P_topo_b *)ptr->topo;
216 
217  if (0 >= dig__fread_port_P(&(topo->N1), 1, fp))
218  goto free_exit_failure;
219  if (0 >= dig__fread_port_P(&(topo->N2), 1, fp))
220  goto free_exit_failure;
221  if (0 >= dig__fread_port_P(&(topo->left), 1, fp))
222  goto free_exit_failure;
223  if (0 >= dig__fread_port_P(&(topo->right), 1, fp))
224  goto free_exit_failure;
225  }
226  /* faces */
227  else if ((ptr->type & GV_FACE) &&
228  Plus->with_z) { /* reserved for face edges */
229  struct P_topo_f *topo = (struct P_topo_f *)ptr->topo;
230 
231  if (0 >= dig__fread_port_I(&n_edges, 1, fp))
232  goto free_exit_failure;
233 
234  /* here will be list of edges */
235 
236  /* left / right volume */
237  if (0 >= dig__fread_port_P(&(topo->left), 1, fp))
238  goto free_exit_failure;
239  if (0 >= dig__fread_port_P(&(topo->left), 1, fp))
240  goto free_exit_failure;
241  }
242  /* kernels */
243  else if ((ptr->type & GV_KERNEL) &&
244  Plus->with_z) { /* reserved for kernel (volume number) */
245  struct P_topo_k *topo = (struct P_topo_k *)ptr->topo;
246 
247  if (0 >= dig__fread_port_P(&(topo->volume), 1, fp))
248  goto free_exit_failure;
249  }
250 
251  Plus->Line[n] = ptr;
252 
253  return (0);
254 
255 free_exit_failure:
256  dig_free_line(ptr);
257  return -1;
258 }
259 
260 int dig_Wr_P_line(struct Plus_head *Plus, int n, struct gvfile *fp)
261 {
262  int n_edges = 0;
263  char ch;
264  struct P_line *ptr;
265 
266  G_debug(4, "dig_Wr_P_line() line = %d", n);
267 
268  ptr = Plus->Line[n];
269 
270  /* if NULL i.e. dead write just 0 instead of type */
271  if (ptr == NULL) {
272  G_debug(4, " line is dead -> write 0 only");
273  ch = 0;
274  if (0 >= dig__fwrite_port_C(&ch, 1, fp))
275  return (-1);
276  return 0;
277  }
278 
279  /* type */
280  ch = (char)dig_type_to_store(ptr->type);
281  G_debug(5, " line type %d -> %d", ptr->type, ch);
282  if (0 >= dig__fwrite_port_C(&ch, 1, fp))
283  return (-1);
284 
285  /* offset */
286  if (0 >= dig__fwrite_port_O(&(ptr->offset), 1, fp, Plus->off_t_size))
287  return (-1);
288 
289  if (!ptr->topo)
290  return (0);
291 
292  /* nothing else for points */
293 
294  /* centroids */
295  if (ptr->type & GV_CENTROID) {
296  struct P_topo_c *topo = (struct P_topo_c *)ptr->topo;
297 
298  if (0 >= dig__fwrite_port_P(&(topo->area), 1, fp))
299  return (-1);
300  }
301  /* lines */
302  else if (ptr->type & GV_LINE) {
303  struct P_topo_l *topo = (struct P_topo_l *)ptr->topo;
304 
305  if (0 >= dig__fwrite_port_P(&(topo->N1), 1, fp))
306  return (-1);
307  if (0 >= dig__fwrite_port_P(&(topo->N2), 1, fp))
308  return (-1);
309  }
310  /* boundaries */
311  else if (ptr->type & GV_BOUNDARY) {
312  struct P_topo_b *topo = (struct P_topo_b *)ptr->topo;
313 
314  if (0 >= dig__fwrite_port_P(&(topo->N1), 1, fp))
315  return (-1);
316  if (0 >= dig__fwrite_port_P(&(topo->N2), 1, fp))
317  return (-1);
318  if (0 >= dig__fwrite_port_P(&(topo->left), 1, fp))
319  return (-1);
320  if (0 >= dig__fwrite_port_P(&(topo->right), 1, fp))
321  return (-1);
322  }
323  /* faces */
324  else if ((ptr->type & GV_FACE) && Plus->with_z) { /* reserved for face */
325  struct P_topo_f *topo = (struct P_topo_f *)ptr->topo;
326 
327  if (0 >= dig__fwrite_port_I(&n_edges, 1, fp))
328  return (-1);
329 
330  /* here will be list of edges */
331 
332  /* left / right volume / hole */
333  if (0 >= dig__fwrite_port_P(&(topo->left), 1, fp))
334  return (-1);
335  if (0 >= dig__fwrite_port_P(&(topo->right), 1, fp))
336  return (-1);
337  }
338  /* kernels */
339  else if ((ptr->type & GV_KERNEL) &&
340  Plus->with_z) { /* reserved for kernel (volume number) */
341  struct P_topo_k *topo = (struct P_topo_k *)ptr->topo;
342 
343  /* volume */
344  if (0 >= dig__fwrite_port_P(&(topo->volume), 1, fp))
345  return (-1);
346  }
347 
348  return (0);
349 }
350 
351 int dig_Rd_P_area(struct Plus_head *Plus, int n, struct gvfile *fp)
352 {
353  int cnt;
354  struct P_area *ptr;
355 
356  G_debug(4, "dig_Rd_P_area(): n = %d", n);
357 
358  if (0 >= dig__fread_port_P(&cnt, 1, fp))
359  return (-1);
360 
361  if (cnt == 0) { /* dead */
362  Plus->Area[n] = NULL;
363  return 0;
364  }
365 
366  ptr = dig_alloc_area();
367 
368  /* boundaries */
369  ptr->n_lines = cnt;
370 
371  if (dig_area_alloc_line(ptr, ptr->n_lines) == -1) {
372  dig_free_area(ptr);
373  return -1;
374  }
375 
376  if (ptr->n_lines) {
377  if (0 >= dig__fread_port_P(ptr->lines, ptr->n_lines, fp)) {
378  dig_free_area(ptr);
379  return -1;
380  }
381  }
382 
383  /* isles */
384  if (0 >= dig__fread_port_P(&(ptr->n_isles), 1, fp)) {
385  dig_free_area(ptr);
386  return -1;
387  }
388 
389  if (dig_area_alloc_isle(ptr, ptr->n_isles) == -1) {
390  dig_free_area(ptr);
391  return -1;
392  }
393 
394  if (ptr->n_isles) {
395  if (0 >= dig__fread_port_P(ptr->isles, ptr->n_isles, fp)) {
396  dig_free_area(ptr);
397  return -1;
398  }
399  }
400  /* centroid */
401  if (0 >= dig__fread_port_P(&(ptr->centroid), 1, fp)) {
402  dig_free_area(ptr);
403  return -1;
404  }
405 
406  Plus->Area[n] = ptr;
407 
408  return (0);
409 }
410 
411 int dig_Wr_P_area(struct Plus_head *Plus, int n, struct gvfile *fp)
412 {
413  int i;
414  struct P_area *ptr;
415 
416  ptr = Plus->Area[n];
417 
418  /* If NULL i.e. dead write just 0 instead of number of lines */
419  if (ptr == NULL) {
420  i = 0;
421  if (0 >= dig__fwrite_port_P(&i, 1, fp))
422  return (-1);
423  return 0;
424  }
425 
426  /* boundaries */
427  if (0 >= dig__fwrite_port_P(&(ptr->n_lines), 1, fp))
428  return (-1);
429 
430  if (ptr->n_lines)
431  if (0 >= dig__fwrite_port_P(ptr->lines, ptr->n_lines, fp))
432  return -1;
433 
434  /* isles */
435  if (0 >= dig__fwrite_port_P(&(ptr->n_isles), 1, fp))
436  return (-1);
437 
438  if (ptr->n_isles)
439  if (0 >= dig__fwrite_port_P(ptr->isles, ptr->n_isles, fp))
440  return -1;
441 
442  /* centroid */
443  if (0 >= dig__fwrite_port_P(&(ptr->centroid), 1, fp))
444  return (-1);
445 
446  return (0);
447 }
448 
449 int dig_Rd_P_isle(struct Plus_head *Plus, int n, struct gvfile *fp)
450 {
451  int cnt;
452  struct P_isle *ptr;
453 
454  G_debug(4, "dig_Rd_P_isle()");
455 
456  if (0 >= dig__fread_port_P(&cnt, 1, fp))
457  return (-1);
458 
459  if (cnt == 0) { /* dead */
460  Plus->Isle[n] = NULL;
461  return 0;
462  }
463 
464  ptr = dig_alloc_isle();
465 
466  /* boundaries */
467  ptr->n_lines = cnt;
468 
469  if (dig_isle_alloc_line(ptr, ptr->n_lines) == -1) {
470  dig_free_isle(ptr);
471  return -1;
472  }
473 
474  if (ptr->n_lines) {
475  if (0 >= dig__fread_port_P(ptr->lines, ptr->n_lines, fp)) {
476  dig_free_isle(ptr);
477  return -1;
478  }
479  }
480 
481  /* area */
482  if (0 >= dig__fread_port_P(&(ptr->area), 1, fp)) {
483  dig_free_isle(ptr);
484  return -1;
485  }
486 
487  Plus->Isle[n] = ptr;
488 
489  return (0);
490 }
491 
492 int dig_Wr_P_isle(struct Plus_head *Plus, int n, struct gvfile *fp)
493 {
494  int i;
495  struct P_isle *ptr;
496 
497  ptr = Plus->Isle[n];
498 
499  /* If NULL i.e. dead write just 0 instead of number of lines */
500  if (ptr == NULL) {
501  i = 0;
502  if (0 >= dig__fwrite_port_P(&i, 1, fp))
503  return (-1);
504  return 0;
505  }
506 
507  /* lines */
508  if (0 >= dig__fwrite_port_P(&(ptr->n_lines), 1, fp))
509  return (-1);
510 
511  if (ptr->n_lines)
512  if (0 >= dig__fwrite_port_P(ptr->lines, ptr->n_lines, fp))
513  return -1;
514 
515  /* area */
516  if (0 >= dig__fwrite_port_P(&(ptr->area), 1, fp))
517  return (-1);
518 
519  return (0);
520 }
521 
522 /*!
523  \brief Read Plus_head from file
524 
525  \param fp pointer to gvfile structure
526  \param[in,out] ptr pointer to Plus_head structure
527 
528  \return -1 error
529  \return 0 OK
530  */
531 int dig_Rd_Plus_head(struct gvfile *fp, struct Plus_head *ptr)
532 {
533  unsigned char buf[5];
534  int byte_order;
535 
536  dig_rewind(fp);
537 
538  /* bytes 1 - 5 */
539  if (0 >= dig__fread_port_C((char *)buf, 5, fp))
540  return (-1);
541  ptr->version.topo.major = buf[0];
542  ptr->version.topo.minor = buf[1];
543  ptr->version.topo.back_major = buf[2];
544  ptr->version.topo.back_minor = buf[3];
545  byte_order = buf[4];
546 
547  G_debug(
548  2,
549  "Topo header: file version %d.%d , supported from GRASS version %d.%d",
550  ptr->version.topo.major, ptr->version.topo.minor,
552 
553  G_debug(2, " byte order %d", byte_order);
554 
555  /* check version numbers */
556  if (ptr->version.topo.major > GV_TOPO_VER_MAJOR ||
558  /* The file was created by GRASS library with higher version than this
559  * one */
560 
563  /* This version of GRASS lib is lower than the oldest which can read
564  * this format */
565  G_debug(1, "Topology format version %d.%d", ptr->version.topo.major,
566  ptr->version.topo.minor);
567  G_fatal_error(_("This version of GRASS (%d.%d) is too old to read "
568  "this topology format."
569  " Try to rebuild topology or upgrade GRASS to at "
570  "least version %d."),
572  GRASS_VERSION_MAJOR + 1);
573  return (-1);
574  }
575 
576  G_warning(_("Your GRASS version does not fully support topology format "
577  "%d.%d of the vector."
578  " Consider to rebuild topology or upgrade GRASS."),
579  ptr->version.topo.major, ptr->version.topo.minor);
580  }
581  if (ptr->version.topo.major < GV_TOPO_VER_MAJOR ||
582  (ptr->version.topo.major == GV_TOPO_VER_MAJOR &&
584  /* The file was created by GRASS library with lower version than this
585  * one */
586 
587  /* This version of GRASS lib can not read this old format */
588  G_warning(
589  _("Old topology format version %d.%d is not supported by this "
590  "release."
591  " Try to rebuild topology using v.build or v.build.all module."),
592  ptr->version.topo.major, ptr->version.topo.minor);
593  return (-1);
594  }
595 
596  /* init Port_info structure and set as default */
597  dig_init_portable(&(ptr->port), byte_order);
598  dig_set_cur_port(&(ptr->port));
599 
600  /* bytes 6 - 9 : header size */
601  if (0 >= dig__fread_port_L(&(ptr->head_size), 1, fp))
602  return (-1);
603  G_debug(2, " header size %ld", ptr->head_size);
604 
605  /* determine required offset size from header size */
606  /* this is not safe in case new fields get added in later versions */
607  /* better: add a new field with off_t_size after byte_order? */
608  if (ptr->head_size >= 142 + 32) /* keep in sync with dig_Wr_Plus_head() */
609  ptr->off_t_size = 8;
610  else
611  ptr->off_t_size = 4;
612 
613  if (sizeof(off_t) < (size_t)ptr->off_t_size) {
614  G_warning(_("Vector exceeds supported file size limit"));
615  return (-1);
616  }
617 
618  G_debug(2, "topo off_t size = %d", ptr->off_t_size);
619 
620  /* byte 10 : dimension 2D or 3D */
621  if (0 >= dig__fread_port_C((char *)buf, 1, fp))
622  return (-1);
623  ptr->with_z = buf[0];
624  G_debug(2, " with_z %d", ptr->with_z);
625 
626  /* bytes 11 - 58 : bound box */
627  if (0 >= dig__fread_port_D(&(ptr->box.N), 1, fp))
628  return (-1);
629  if (0 >= dig__fread_port_D(&(ptr->box.S), 1, fp))
630  return (-1);
631  if (0 >= dig__fread_port_D(&(ptr->box.E), 1, fp))
632  return (-1);
633  if (0 >= dig__fread_port_D(&(ptr->box.W), 1, fp))
634  return (-1);
635  if (0 >= dig__fread_port_D(&(ptr->box.T), 1, fp))
636  return (-1);
637  if (0 >= dig__fread_port_D(&(ptr->box.B), 1, fp))
638  return (-1);
639 
640  /* bytes 59 - 86 : number of structures */
641  if (0 >= dig__fread_port_P(&(ptr->n_nodes), 1, fp))
642  return (-1);
643  if (0 >= dig__fread_port_P(&(ptr->n_edges), 1, fp))
644  return (-1);
645  if (0 >= dig__fread_port_P(&(ptr->n_lines), 1, fp))
646  return (-1);
647  if (0 >= dig__fread_port_P(&(ptr->n_areas), 1, fp))
648  return (-1);
649  if (0 >= dig__fread_port_P(&(ptr->n_isles), 1, fp))
650  return (-1);
651  if (0 >= dig__fread_port_P(&(ptr->n_volumes), 1, fp))
652  return (-1);
653  if (0 >= dig__fread_port_P(&(ptr->n_holes), 1, fp))
654  return (-1);
655 
656  /* bytes 87 - 110 : number of line types */
657  if (0 >= dig__fread_port_P(&(ptr->n_plines), 1, fp))
658  return (-1);
659  if (0 >= dig__fread_port_P(&(ptr->n_llines), 1, fp))
660  return (-1);
661  if (0 >= dig__fread_port_P(&(ptr->n_blines), 1, fp))
662  return (-1);
663  if (0 >= dig__fread_port_P(&(ptr->n_clines), 1, fp))
664  return (-1);
665  if (0 >= dig__fread_port_P(&(ptr->n_flines), 1, fp))
666  return (-1);
667  if (0 >= dig__fread_port_P(&(ptr->n_klines), 1, fp))
668  return (-1);
669 
670  /* bytes 111 - 138 : Offset */
671  if (0 >= dig__fread_port_O(&(ptr->Node_offset), 1, fp, ptr->off_t_size))
672  return (-1);
673  if (0 >= dig__fread_port_O(&(ptr->Edge_offset), 1, fp, ptr->off_t_size))
674  return (-1);
675  if (0 >= dig__fread_port_O(&(ptr->Line_offset), 1, fp, ptr->off_t_size))
676  return (-1);
677  if (0 >= dig__fread_port_O(&(ptr->Area_offset), 1, fp, ptr->off_t_size))
678  return (-1);
679  if (0 >= dig__fread_port_O(&(ptr->Isle_offset), 1, fp, ptr->off_t_size))
680  return (-1);
681  if (0 >= dig__fread_port_O(&(ptr->Volume_offset), 1, fp, ptr->off_t_size))
682  return (-1);
683  if (0 >= dig__fread_port_O(&(ptr->Hole_offset), 1, fp, ptr->off_t_size))
684  return (-1);
685 
686  /* bytes 139 - 142 : Coor size and time */
687  if (0 >= dig__fread_port_O(&(ptr->coor_size), 1, fp, ptr->off_t_size))
688  return (-1);
689 
690  G_debug(2, " coor size %" PRId64, ptr->coor_size);
691 
692  dig_fseek(fp, ptr->head_size, SEEK_SET);
693 
694  return (0);
695 }
696 
697 /*!
698  \brief Write Plus_head to file
699 
700  ptr->off_t_size is used for both coor and topo files, but their sizes
701  (ptr->coor_size for coor and no variable for topo) can be different. If
702  either file is greater than PORT_LONG_MAX, ptr->off_t_size must be 8. This
703  function determines this value of ptr->off_t_size and writes it to the file.
704 
705  \param fp pointer to gvfile structure
706  \param[in,out] ptr pointer to Plus_head structure
707 
708  \return -1 error
709  \return 0 OK
710  */
711 int dig_Wr_Plus_head(struct gvfile *fp, struct Plus_head *ptr)
712 {
713  unsigned char buf[10];
714  long length = 142;
715 
716  dig_rewind(fp);
717  dig_set_cur_port(&(ptr->port));
718 
719  /* bytes 1 - 5 */
720  buf[0] = GV_TOPO_VER_MAJOR;
721  buf[1] = GV_TOPO_VER_MINOR;
722  buf[2] = GV_TOPO_EARLIEST_MAJOR;
723  buf[3] = GV_TOPO_EARLIEST_MINOR;
724  buf[4] = ptr->port.byte_order;
725  if (0 >= dig__fwrite_port_C((char *)buf, 5, fp))
726  return (-1);
727 
728  /* determine required offset size from coor file size */
729  if (ptr->coor_size > (off_t)PORT_LONG_MAX) {
730  /* can only happen when sizeof(off_t) == 8 */
731  ptr->off_t_size = 8;
732  }
733  else if (ptr->off_t_size == 0) {
734  /* calculate the total size of topo file to get the correct off_t_size
735  * if coor file is less than PORT_LONG_MAX */
736  off_t size = length;
737  int i;
738 
739  for (i = 1; i <= ptr->n_nodes; i++) {
740  /* from dig_Wr_P_node() */
741  struct P_node *p = ptr->Node[i];
742 
743  if (p == NULL)
744  size += 4;
745  else {
746  size += 20 + 8 * p->n_lines;
747  if (ptr->with_z)
748  size += 12;
749  }
750  }
751 
752  for (i = 1; i <= ptr->n_lines; i++) {
753  /* from dig_Wr_P_line() */
754  struct P_line *p = ptr->Line[i];
755 
756  if (p == NULL)
757  size += 1;
758  else {
759  /* for now, off_t_size = 4 */
760  size += 5;
761  if (p->type & GV_CENTROID)
762  size += 4;
763  else if (p->type & GV_LINE)
764  size += 8;
765  else if (p->type & GV_BOUNDARY)
766  size += 16;
767  else if ((p->type & GV_FACE) && ptr->with_z)
768  size += 12;
769  else if ((p->type & GV_KERNEL) && ptr->with_z)
770  size += 4;
771  }
772  }
773 
774  for (i = 1; i <= ptr->n_areas; i++) {
775  /* from dig_Wr_P_area() */
776  struct P_area *p = ptr->Area[i];
777 
778  if (p == NULL)
779  size += 4;
780  else
781  size += 12 + 4 * p->n_lines + 4 * p->n_isles;
782  }
783 
784  for (i = 1; i <= ptr->n_isles; i++) {
785  /* from dig_Wr_P_isle() */
786  struct P_isle *p = ptr->Isle[i];
787 
788  if (p == NULL)
789  size += 4;
790  else
791  size += 8 + 4 * p->n_lines;
792  }
793 
794  ptr->off_t_size = size > (off_t)PORT_LONG_MAX ? 8 : 4;
795  }
796 
797  /* add a new field with off_t_size after byte_order? */
798 
799  /* adjust header size for large files */
800  if (ptr->off_t_size == 8) {
801  /* 7 offset values and coor file size: add 8 * 4 */
802  length += 32;
803  }
804 
805  /* bytes 6 - 9 : header size */
806  if (0 >= dig__fwrite_port_L(&length, 1, fp))
807  return (0);
808 
809  /* byte 10 : dimension 2D or 3D */
810  buf[0] = ptr->with_z;
811  if (0 >= dig__fwrite_port_C((char *)buf, 1, fp))
812  return (0);
813 
814  /* bytes 11 - 58 : bound box */
815  if (0 >= dig__fwrite_port_D(&(ptr->box.N), 1, fp))
816  return (-1);
817  if (0 >= dig__fwrite_port_D(&(ptr->box.S), 1, fp))
818  return (-1);
819  if (0 >= dig__fwrite_port_D(&(ptr->box.E), 1, fp))
820  return (-1);
821  if (0 >= dig__fwrite_port_D(&(ptr->box.W), 1, fp))
822  return (-1);
823  if (0 >= dig__fwrite_port_D(&(ptr->box.T), 1, fp))
824  return (-1);
825  if (0 >= dig__fwrite_port_D(&(ptr->box.B), 1, fp))
826  return (-1);
827 
828  /* bytes 59 - 86 : number of structures */
829  if (0 >= dig__fwrite_port_P(&(ptr->n_nodes), 1, fp))
830  return (-1);
831  if (0 >= dig__fwrite_port_P(&(ptr->n_edges), 1, fp))
832  return (-1);
833  if (0 >= dig__fwrite_port_P(&(ptr->n_lines), 1, fp))
834  return (-1);
835  if (0 >= dig__fwrite_port_P(&(ptr->n_areas), 1, fp))
836  return (-1);
837  if (0 >= dig__fwrite_port_P(&(ptr->n_isles), 1, fp))
838  return (-1);
839  if (0 >= dig__fwrite_port_P(&(ptr->n_volumes), 1, fp))
840  return (-1);
841  if (0 >= dig__fwrite_port_P(&(ptr->n_holes), 1, fp))
842  return (-1);
843 
844  /* bytes 87 - 110 : number of line types */
845  if (0 >= dig__fwrite_port_P(&(ptr->n_plines), 1, fp))
846  return (-1);
847  if (0 >= dig__fwrite_port_P(&(ptr->n_llines), 1, fp))
848  return (-1);
849  if (0 >= dig__fwrite_port_P(&(ptr->n_blines), 1, fp))
850  return (-1);
851  if (0 >= dig__fwrite_port_P(&(ptr->n_clines), 1, fp))
852  return (-1);
853  if (0 >= dig__fwrite_port_P(&(ptr->n_flines), 1, fp))
854  return (-1);
855  if (0 >= dig__fwrite_port_P(&(ptr->n_klines), 1, fp))
856  return (-1);
857 
858  /* bytes 111 - 138 : Offset */
859  if (0 >= dig__fwrite_port_O(&(ptr->Node_offset), 1, fp, ptr->off_t_size))
860  return (-1);
861  if (0 >= dig__fwrite_port_O(&(ptr->Edge_offset), 1, fp, ptr->off_t_size))
862  return (-1);
863  if (0 >= dig__fwrite_port_O(&(ptr->Line_offset), 1, fp, ptr->off_t_size))
864  return (-1);
865  if (0 >= dig__fwrite_port_O(&(ptr->Area_offset), 1, fp, ptr->off_t_size))
866  return (-1);
867  if (0 >= dig__fwrite_port_O(&(ptr->Isle_offset), 1, fp, ptr->off_t_size))
868  return (-1);
869  if (0 >= dig__fwrite_port_O(&(ptr->Volume_offset), 1, fp, ptr->off_t_size))
870  return (-1);
871  if (0 >= dig__fwrite_port_O(&(ptr->Hole_offset), 1, fp, ptr->off_t_size))
872  return (-1);
873 
874  /* bytes 139 - 142 : Coor size and time */
875  if (0 >= dig__fwrite_port_O(&(ptr->coor_size), 1, fp, ptr->off_t_size))
876  return (-1);
877 
878  G_debug(2, "topo body offset %" PRId64, dig_ftell(fp));
879 
880  return (0);
881 }
#define NULL
Definition: ccmath.h:32
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
int G_debug(int, const char *,...) __attribute__((format(printf
#define GV_TOPO_EARLIEST_MAJOR
Definition: dig_defines.h:163
#define GV_TOPO_EARLIEST_MINOR
Definition: dig_defines.h:164
#define GV_CENTROID
Definition: dig_defines.h:186
#define GV_TOPO_VER_MINOR
Definition: dig_defines.h:153
#define GV_LINE
Definition: dig_defines.h:184
#define GV_POINT
Feature types used in memory on run time (may change)
Definition: dig_defines.h:183
#define PORT_LONG_MAX
Definition: dig_defines.h:70
#define GV_BOUNDARY
Definition: dig_defines.h:185
#define GV_TOPO_VER_MAJOR
Definition: dig_defines.h:152
#define GV_FACE
Definition: dig_defines.h:187
#define GV_KERNEL
Definition: dig_defines.h:188
int dig__fread_port_D(double *, size_t, struct gvfile *)
Read doubles from the Portable Vector Format.
Definition: portable.c:79
int dig__fread_port_O(off_t *, size_t, struct gvfile *, size_t)
Read off_ts from the Portable Vector Format.
Definition: portable.c:167
void dig_free_line(struct P_line *)
Free line structure.
Definition: struct_alloc.c:177
void dig_free_node(struct P_node *)
Free node structure.
Definition: struct_alloc.c:48
struct P_isle * dig_alloc_isle(void)
Allocate new isle structure.
Definition: struct_alloc.c:301
int dig__fwrite_port_C(const char *, size_t, struct gvfile *)
Write chars to the Portable Vector Format.
Definition: portable.c:886
void dig_init_portable(struct Port_info *, int)
Set Port_info structure to byte order of file.
Definition: portable.c:900
int dig__fread_port_L(long *, size_t, struct gvfile *)
Read longs from the Portable Vector Format.
Definition: portable.c:262
int dig__fread_port_F(float *, size_t, struct gvfile *)
Read floats from the Portable Vector Format.
Definition: portable.c:123
int dig__fwrite_port_L(const long *, size_t, struct gvfile *)
Write longs to the Portable Vector Format.
Definition: portable.c:703
int dig__fwrite_port_I(const int *, size_t, struct gvfile *)
Write integers to the Portable Vector Format.
Definition: portable.c:758
off_t dig_ftell(struct gvfile *file)
Get struct gvfile position.
Definition: file.c:36
int dig__fwrite_port_F(const float *, size_t, struct gvfile *)
Write floats to the Portable Vector Format.
Definition: portable.c:597
int dig_area_alloc_isle(struct P_area *, int)
Allocate space in P_area for add new isles.
Definition: struct_alloc.c:440
int dig_set_cur_port(struct Port_info *)
Set current Port_info structure.
Definition: portable.c:996
int dig__fwrite_port_D(const double *, size_t, struct gvfile *)
Write doubles to the Portable Vector Format.
Definition: portable.c:559
void dig_rewind(struct gvfile *file)
Rewind file position.
Definition: file.c:87
int dig_node_alloc_line(struct P_node *, int)
Allocate space in P_node struct.
Definition: struct_alloc.c:69
int dig__fread_port_C(char *, size_t, struct gvfile *)
Read chars from the Portable Vector Format.
Definition: portable.c:511
void * dig_alloc_topo(char)
Allocate new topo struct.
Definition: struct_alloc.c:145
int dig__fread_port_I(int *, size_t, struct gvfile *)
Read integers from the Portable Vector Format.
Definition: portable.c:345
int dig_fseek(struct gvfile *file, off_t offset, int whence)
Set struct gvfile position.
Definition: file.c:60
void dig_free_area(struct P_area *)
Free area structure.
Definition: struct_alloc.c:284
int dig_type_from_store(int)
Convert type from store type.
struct P_area * dig_alloc_area(void)
Allocate new area structure.
Definition: struct_alloc.c:266
int dig__fread_port_P(plus_t *, size_t, struct gvfile *)
Read plus_t from the Portable Vector Format.
Definition: portable.c:537
struct P_line * dig_alloc_line(void)
Allocate new line structure.
Definition: struct_alloc.c:127
int dig_isle_alloc_line(struct P_isle *, int)
Allocate space in P_isle for add new lines.
Definition: struct_alloc.c:466
int dig_area_alloc_line(struct P_area *, int)
allocate space in P_area for add new lines
Definition: struct_alloc.c:414
void dig_free_isle(struct P_isle *)
Free isle structure.
Definition: struct_alloc.c:319
int dig__fwrite_port_O(const off_t *, size_t, struct gvfile *, size_t)
Write off_ts to the Portable Vector Format.
Definition: portable.c:636
int dig__fwrite_port_P(const plus_t *, size_t, struct gvfile *)
Write plus_t to the Portable Vector Format.
Definition: portable.c:868
int dig_type_to_store(int)
Convert type to store type.
struct P_node * dig_alloc_node(void)
Allocate new node structure.
Definition: struct_alloc.c:30
#define _(str)
Definition: glocale.h:10
int dig_Rd_Plus_head(struct gvfile *fp, struct Plus_head *ptr)
Read Plus_head from file.
Definition: plus_struct.c:531
int dig_Rd_P_node(struct Plus_head *Plus, int n, struct gvfile *fp)
Definition: plus_struct.c:52
int dig_Wr_P_isle(struct Plus_head *Plus, int n, struct gvfile *fp)
Definition: plus_struct.c:492
int dig_Rd_P_isle(struct Plus_head *Plus, int n, struct gvfile *fp)
Definition: plus_struct.c:449
int dig_Wr_P_node(struct Plus_head *Plus, int n, struct gvfile *fp)
Definition: plus_struct.c:118
int dig_Rd_P_line(struct Plus_head *Plus, int n, struct gvfile *fp)
Definition: plus_struct.c:163
int dig_Rd_P_area(struct Plus_head *Plus, int n, struct gvfile *fp)
Definition: plus_struct.c:351
int dig_Wr_Plus_head(struct gvfile *fp, struct Plus_head *ptr)
Write Plus_head to file.
Definition: plus_struct.c:711
int dig_Wr_P_line(struct Plus_head *Plus, int n, struct gvfile *fp)
Definition: plus_struct.c:260
int dig_Wr_P_area(struct Plus_head *Plus, int n, struct gvfile *fp)
Definition: plus_struct.c:411
if(!(yy_init))
Definition: sqlp.yy.c:775
Area (topology) info.
Definition: dig_structs.h:1583
plus_t n_isles
Number of islands inside.
Definition: dig_structs.h:1609
plus_t * isles
1st generation interior islands
Definition: dig_structs.h:1617
plus_t n_lines
Number of boundary lines.
Definition: dig_structs.h:1587
plus_t * lines
List of boundary lines.
Definition: dig_structs.h:1598
plus_t centroid
Number of first centroid within area.
Definition: dig_structs.h:1605
Isle (topology) info.
Definition: dig_structs.h:1623
plus_t * lines
List of boundary lines.
Definition: dig_structs.h:1638
plus_t n_lines
Number of boundary lines.
Definition: dig_structs.h:1627
plus_t area
Area it exists w/in, if any.
Definition: dig_structs.h:1645
Vector geometry.
Definition: dig_structs.h:1553
char type
Line type.
Definition: dig_structs.h:1564
off_t offset
Offset in coor file for line.
Definition: dig_structs.h:1571
void * topo
Topology info.
Definition: dig_structs.h:1577
Topological feature - node.
Definition: dig_structs.h:1433
double x
X coordinate.
Definition: dig_structs.h:1437
plus_t n_lines
Number of attached lines (size of lines, angle)
Definition: dig_structs.h:1456
float * angles
List of angles of connected lines.
Definition: dig_structs.h:1472
plus_t * lines
List of connected lines.
Definition: dig_structs.h:1463
double z
Z coordinate (used only for 3D data)
Definition: dig_structs.h:1445
double y
Y coordinate.
Definition: dig_structs.h:1441
Boundary topology.
Definition: dig_structs.h:1492
plus_t left
Area number to the left, negative for isle.
Definition: dig_structs.h:1504
plus_t N1
Start node.
Definition: dig_structs.h:1496
plus_t N2
End node.
Definition: dig_structs.h:1500
plus_t right
Area number to the right, negative for isle.
Definition: dig_structs.h:1508
Centroid topology.
Definition: dig_structs.h:1514
plus_t area
Area number, negative for duplicate centroid.
Definition: dig_structs.h:1518
Face topology.
Definition: dig_structs.h:1524
plus_t left
Volume number to the left, negative for hole.
Definition: dig_structs.h:1533
plus_t right
Volume number to the right, negative for hole.
Definition: dig_structs.h:1537
Kernel topology.
Definition: dig_structs.h:1543
plus_t volume
Volume number, negative for duplicate kernel.
Definition: dig_structs.h:1547
Line topology.
Definition: dig_structs.h:1478
plus_t N1
Start node.
Definition: dig_structs.h:1482
plus_t N2
End node.
Definition: dig_structs.h:1486
Basic topology-related info.
Definition: dig_structs.h:769
off_t Hole_offset
Offset of array of holes in topo file.
Definition: dig_structs.h:1029
plus_t n_klines
Current number of kernels.
Definition: dig_structs.h:906
off_t Isle_offset
Offset of array of isles in topo file.
Definition: dig_structs.h:1021
off_t Node_offset
Offset of array of nodes in topo file.
Definition: dig_structs.h:1005
int with_z
2D/3D vector data
Definition: dig_structs.h:786
off_t coor_size
Size of coor file.
Definition: dig_structs.h:1145
struct Plus_head::@9 version
Backward compatibility version info.
struct P_line ** Line
Array of vector geometries.
Definition: dig_structs.h:871
plus_t n_lines
Current number of lines.
Definition: dig_structs.h:931
off_t Volume_offset
Offset of array of volumes in topo file.
Definition: dig_structs.h:1025
plus_t n_plines
Current number of points.
Definition: dig_structs.h:886
off_t Area_offset
Offset of array of areas in topo file.
Definition: dig_structs.h:1017
int off_t_size
Offset size.
Definition: dig_structs.h:801
plus_t n_nodes
Current number of topological features derived from vector geometries.
Definition: dig_structs.h:923
plus_t n_volumes
Current number of volumes.
Definition: dig_structs.h:947
plus_t n_blines
Current number of boundaries.
Definition: dig_structs.h:894
struct P_area ** Area
Array of areas.
Definition: dig_structs.h:875
long head_size
Topo header size.
Definition: dig_structs.h:808
plus_t n_clines
Current number of centroids.
Definition: dig_structs.h:898
struct Version_info topo
Version info for topology file.
Definition: dig_structs.h:773
plus_t n_isles
Current number of isles.
Definition: dig_structs.h:939
plus_t n_holes
Current number of holes.
Definition: dig_structs.h:951
off_t Edge_offset
Offset of array of edges in topo file.
Definition: dig_structs.h:1009
struct bound_box box
Bounding box of features.
Definition: dig_structs.h:861
plus_t n_edges
Current number of edges.
Definition: dig_structs.h:927
struct P_isle ** Isle
Array of isles.
Definition: dig_structs.h:879
struct P_node ** Node
Array of nodes.
Definition: dig_structs.h:867
struct Port_info port
Portability information.
Definition: dig_structs.h:829
plus_t n_areas
Current number of areas.
Definition: dig_structs.h:935
plus_t n_flines
Current number of faces.
Definition: dig_structs.h:902
off_t Line_offset
Offset of array of vector geometries in topo file.
Definition: dig_structs.h:1013
plus_t n_llines
Current number of lines.
Definition: dig_structs.h:890
int byte_order
File byte order.
Definition: dig_structs.h:185
int minor
Current version (minor)
Definition: dig_structs.h:275
int back_major
Earliest version that can use this data format (major)
Definition: dig_structs.h:277
int back_minor
Earliest version that can use this data format (minor)
Definition: dig_structs.h:279
int major
Current version (major)
Definition: dig_structs.h:273
double W
West.
Definition: dig_structs.h:80
double T
Top.
Definition: dig_structs.h:84
double S
South.
Definition: dig_structs.h:72
double N
North.
Definition: dig_structs.h:68
double E
East.
Definition: dig_structs.h:76
double B
Bottom.
Definition: dig_structs.h:88
File definition.
Definition: dig_structs.h:94
#define GRASS_VERSION_MINOR
Definition: version.h:3
#define GRASS_VERSION_MAJOR
Definition: version.h:2