GRASS 8 Programmer's Manual  8.5.0dev(2025)-d272f2f102
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 int dig_Rd_P_node(struct Plus_head *Plus, int n, struct gvfile *fp)
52 {
53  int cnt, n_edges;
54  struct P_node *ptr;
55 
56  G_debug(4, "dig_Rd_P_node()");
57 
58  if (0 >= dig__fread_port_P(&cnt, 1, fp))
59  return (-1);
60 
61  if (cnt == 0) { /* dead */
62  G_debug(4, " node is dead");
63  Plus->Node[n] = NULL;
64  return 0;
65  }
66 
67  ptr = dig_alloc_node();
68  ptr->n_lines = cnt;
69 
70  if (dig_node_alloc_line(ptr, ptr->n_lines) == -1) {
71  dig_free_node(ptr);
72  return -1;
73  }
74 
75  if (ptr->n_lines) {
76  if (0 >= dig__fread_port_P(ptr->lines, ptr->n_lines, fp)) {
77  dig_free_node(ptr);
78  return (-1);
79  }
80  if (0 >= dig__fread_port_F(ptr->angles, ptr->n_lines, fp)) {
81  dig_free_node(ptr);
82  return (-1);
83  }
84  }
85 
86  if (Plus->with_z) {
87  if (0 >= dig__fread_port_P(&n_edges, 1, fp)) { /* reserved for edges */
88  dig_free_node(ptr);
89  return (-1);
90  }
91  }
92  /* here will be edges */
93 
94  if (0 >= dig__fread_port_D(&(ptr->x), 1, fp)) {
95  dig_free_node(ptr);
96  return (-1);
97  }
98  if (0 >= dig__fread_port_D(&(ptr->y), 1, fp)) {
99  dig_free_node(ptr);
100  return (-1);
101  }
102 
103  if (Plus->with_z) {
104  if (0 >= dig__fread_port_D(&(ptr->z), 1, fp)) {
105  dig_free_node(ptr);
106  return (-1);
107  }
108  }
109  else
110  ptr->z = 0;
111 
112  Plus->Node[n] = ptr;
113 
114  return (0);
115 }
116 
117 int dig_Wr_P_node(struct Plus_head *Plus, int n, struct gvfile *fp)
118 {
119  int i, n_edges = 0;
120  struct P_node *ptr;
121 
122  G_debug(4, "dig_Wr_P_node()");
123  ptr = Plus->Node[n];
124 
125  /* If NULL i.e. dead write just 0 instead of number of lines */
126  if (ptr == NULL) {
127  G_debug(4, " node is dead -> write 0 only");
128  i = 0;
129  if (0 >= dig__fwrite_port_P(&i, 1, fp))
130  return (-1);
131  return 0;
132  }
133 
134  if (0 >= dig__fwrite_port_P(&(ptr->n_lines), 1, fp))
135  return (-1);
136 
137  if (ptr->n_lines) {
138  if (0 >= dig__fwrite_port_P(ptr->lines, ptr->n_lines, fp))
139  return (-1);
140  if (0 >= dig__fwrite_port_F(ptr->angles, ptr->n_lines, fp))
141  return (-1);
142  }
143 
144  if (Plus->with_z)
145  if (0 >= dig__fwrite_port_P(&n_edges, 1, fp)) /* reserved for edges */
146  return (-1);
147 
148  /* here will be edges */
149 
150  if (0 >= dig__fwrite_port_D(&(ptr->x), 1, fp))
151  return (-1);
152  if (0 >= dig__fwrite_port_D(&(ptr->y), 1, fp))
153  return (-1);
154 
155  if (Plus->with_z)
156  if (0 >= dig__fwrite_port_D(&(ptr->z), 1, fp))
157  return (-1);
158 
159  return (0);
160 }
161 
162 int dig_Rd_P_line(struct Plus_head *Plus, int n, struct gvfile *fp)
163 {
164  int n_edges;
165  char tp;
166  struct P_line *ptr;
167 
168  G_debug(4, "dig_Rd_P_line()");
169 
170  if (0 >= dig__fread_port_C(&tp, 1, fp))
171  return (-1);
172 
173  if (tp == 0) { /* dead */
174  G_debug(4, " line is dead");
175  Plus->Line[n] = NULL;
176  return 0;
177  }
178 
179  ptr = dig_alloc_line();
180 
181  /* type */
182  ptr->type = dig_type_from_store(tp);
183  G_debug(5, " line type %d -> %d", tp, ptr->type);
184 
185  /* offset */
186  if (0 >= dig__fread_port_O(&(ptr->offset), 1, fp, Plus->off_t_size))
187  goto free_exit_failure;
188 
189  if (ptr->type == GV_POINT) {
190  ptr->topo = NULL;
191  }
192  else {
193  ptr->topo = dig_alloc_topo(ptr->type);
194  }
195 
196  /* centroids */
197  if (ptr->type & GV_CENTROID) {
198  struct P_topo_c *topo = (struct P_topo_c *)ptr->topo;
199 
200  if (0 >= dig__fread_port_P(&(topo->area), 1, fp))
201  goto free_exit_failure;
202  }
203  /* lines */
204  else if (ptr->type & GV_LINE) {
205  struct P_topo_l *topo = (struct P_topo_l *)ptr->topo;
206 
207  if (0 >= dig__fread_port_P(&(topo->N1), 1, fp))
208  goto free_exit_failure;
209  if (0 >= dig__fread_port_P(&(topo->N2), 1, fp))
210  goto free_exit_failure;
211  }
212  /* boundaries */
213  else if (ptr->type & GV_BOUNDARY) {
214  struct P_topo_b *topo = (struct P_topo_b *)ptr->topo;
215 
216  if (0 >= dig__fread_port_P(&(topo->N1), 1, fp))
217  goto free_exit_failure;
218  if (0 >= dig__fread_port_P(&(topo->N2), 1, fp))
219  goto free_exit_failure;
220  if (0 >= dig__fread_port_P(&(topo->left), 1, fp))
221  goto free_exit_failure;
222  if (0 >= dig__fread_port_P(&(topo->right), 1, fp))
223  goto free_exit_failure;
224  }
225  /* faces */
226  else if ((ptr->type & GV_FACE) &&
227  Plus->with_z) { /* reserved for face edges */
228  struct P_topo_f *topo = (struct P_topo_f *)ptr->topo;
229 
230  if (0 >= dig__fread_port_I(&n_edges, 1, fp))
231  goto free_exit_failure;
232 
233  /* here will be list of edges */
234 
235  /* left / right volume */
236  if (0 >= dig__fread_port_P(&(topo->left), 1, fp))
237  goto free_exit_failure;
238  if (0 >= dig__fread_port_P(&(topo->left), 1, fp))
239  goto free_exit_failure;
240  }
241  /* kernels */
242  else if ((ptr->type & GV_KERNEL) &&
243  Plus->with_z) { /* reserved for kernel (volume number) */
244  struct P_topo_k *topo = (struct P_topo_k *)ptr->topo;
245 
246  if (0 >= dig__fread_port_P(&(topo->volume), 1, fp))
247  goto free_exit_failure;
248  }
249 
250  Plus->Line[n] = ptr;
251 
252  return (0);
253 
254 free_exit_failure:
255  dig_free_line(ptr);
256  return -1;
257 }
258 
259 int dig_Wr_P_line(struct Plus_head *Plus, int n, struct gvfile *fp)
260 {
261  int n_edges = 0;
262  char ch;
263  struct P_line *ptr;
264 
265  G_debug(4, "dig_Wr_P_line() line = %d", n);
266 
267  ptr = Plus->Line[n];
268 
269  /* if NULL i.e. dead write just 0 instead of type */
270  if (ptr == NULL) {
271  G_debug(4, " line is dead -> write 0 only");
272  ch = 0;
273  if (0 >= dig__fwrite_port_C(&ch, 1, fp))
274  return (-1);
275  return 0;
276  }
277 
278  /* type */
279  ch = (char)dig_type_to_store(ptr->type);
280  G_debug(5, " line type %d -> %d", ptr->type, ch);
281  if (0 >= dig__fwrite_port_C(&ch, 1, fp))
282  return (-1);
283 
284  /* offset */
285  if (0 >= dig__fwrite_port_O(&(ptr->offset), 1, fp, Plus->off_t_size))
286  return (-1);
287 
288  if (!ptr->topo)
289  return (0);
290 
291  /* nothing else for points */
292 
293  /* centroids */
294  if (ptr->type & GV_CENTROID) {
295  struct P_topo_c *topo = (struct P_topo_c *)ptr->topo;
296 
297  if (0 >= dig__fwrite_port_P(&(topo->area), 1, fp))
298  return (-1);
299  }
300  /* lines */
301  else if (ptr->type & GV_LINE) {
302  struct P_topo_l *topo = (struct P_topo_l *)ptr->topo;
303 
304  if (0 >= dig__fwrite_port_P(&(topo->N1), 1, fp))
305  return (-1);
306  if (0 >= dig__fwrite_port_P(&(topo->N2), 1, fp))
307  return (-1);
308  }
309  /* boundaries */
310  else if (ptr->type & GV_BOUNDARY) {
311  struct P_topo_b *topo = (struct P_topo_b *)ptr->topo;
312 
313  if (0 >= dig__fwrite_port_P(&(topo->N1), 1, fp))
314  return (-1);
315  if (0 >= dig__fwrite_port_P(&(topo->N2), 1, fp))
316  return (-1);
317  if (0 >= dig__fwrite_port_P(&(topo->left), 1, fp))
318  return (-1);
319  if (0 >= dig__fwrite_port_P(&(topo->right), 1, fp))
320  return (-1);
321  }
322  /* faces */
323  else if ((ptr->type & GV_FACE) && Plus->with_z) { /* reserved for face */
324  struct P_topo_f *topo = (struct P_topo_f *)ptr->topo;
325 
326  if (0 >= dig__fwrite_port_I(&n_edges, 1, fp))
327  return (-1);
328 
329  /* here will be list of edges */
330 
331  /* left / right volume / hole */
332  if (0 >= dig__fwrite_port_P(&(topo->left), 1, fp))
333  return (-1);
334  if (0 >= dig__fwrite_port_P(&(topo->right), 1, fp))
335  return (-1);
336  }
337  /* kernels */
338  else if ((ptr->type & GV_KERNEL) &&
339  Plus->with_z) { /* reserved for kernel (volume number) */
340  struct P_topo_k *topo = (struct P_topo_k *)ptr->topo;
341 
342  /* volume */
343  if (0 >= dig__fwrite_port_P(&(topo->volume), 1, fp))
344  return (-1);
345  }
346 
347  return (0);
348 }
349 
350 int dig_Rd_P_area(struct Plus_head *Plus, int n, struct gvfile *fp)
351 {
352  int cnt;
353  struct P_area *ptr;
354 
355  G_debug(4, "dig_Rd_P_area(): n = %d", n);
356 
357  if (0 >= dig__fread_port_P(&cnt, 1, fp))
358  return (-1);
359 
360  if (cnt == 0) { /* dead */
361  Plus->Area[n] = NULL;
362  return 0;
363  }
364 
365  ptr = dig_alloc_area();
366 
367  /* boundaries */
368  ptr->n_lines = cnt;
369 
370  if (dig_area_alloc_line(ptr, ptr->n_lines) == -1) {
371  dig_free_area(ptr);
372  return -1;
373  }
374 
375  if (ptr->n_lines) {
376  if (0 >= dig__fread_port_P(ptr->lines, ptr->n_lines, fp)) {
377  dig_free_area(ptr);
378  return -1;
379  }
380  }
381 
382  /* isles */
383  if (0 >= dig__fread_port_P(&(ptr->n_isles), 1, fp)) {
384  dig_free_area(ptr);
385  return -1;
386  }
387 
388  if (dig_area_alloc_isle(ptr, ptr->n_isles) == -1) {
389  dig_free_area(ptr);
390  return -1;
391  }
392 
393  if (ptr->n_isles) {
394  if (0 >= dig__fread_port_P(ptr->isles, ptr->n_isles, fp)) {
395  dig_free_area(ptr);
396  return -1;
397  }
398  }
399  /* centroid */
400  if (0 >= dig__fread_port_P(&(ptr->centroid), 1, fp)) {
401  dig_free_area(ptr);
402  return -1;
403  }
404 
405  Plus->Area[n] = ptr;
406 
407  return (0);
408 }
409 
410 int dig_Wr_P_area(struct Plus_head *Plus, int n, struct gvfile *fp)
411 {
412  int i;
413  struct P_area *ptr;
414 
415  ptr = Plus->Area[n];
416 
417  /* If NULL i.e. dead write just 0 instead of number of lines */
418  if (ptr == NULL) {
419  i = 0;
420  if (0 >= dig__fwrite_port_P(&i, 1, fp))
421  return (-1);
422  return 0;
423  }
424 
425  /* boundaries */
426  if (0 >= dig__fwrite_port_P(&(ptr->n_lines), 1, fp))
427  return (-1);
428 
429  if (ptr->n_lines)
430  if (0 >= dig__fwrite_port_P(ptr->lines, ptr->n_lines, fp))
431  return -1;
432 
433  /* isles */
434  if (0 >= dig__fwrite_port_P(&(ptr->n_isles), 1, fp))
435  return (-1);
436 
437  if (ptr->n_isles)
438  if (0 >= dig__fwrite_port_P(ptr->isles, ptr->n_isles, fp))
439  return -1;
440 
441  /* centroid */
442  if (0 >= dig__fwrite_port_P(&(ptr->centroid), 1, fp))
443  return (-1);
444 
445  return (0);
446 }
447 
448 int dig_Rd_P_isle(struct Plus_head *Plus, int n, struct gvfile *fp)
449 {
450  int cnt;
451  struct P_isle *ptr;
452 
453  G_debug(4, "dig_Rd_P_isle()");
454 
455  if (0 >= dig__fread_port_P(&cnt, 1, fp))
456  return (-1);
457 
458  if (cnt == 0) { /* dead */
459  Plus->Isle[n] = NULL;
460  return 0;
461  }
462 
463  ptr = dig_alloc_isle();
464 
465  /* boundaries */
466  ptr->n_lines = cnt;
467 
468  if (dig_isle_alloc_line(ptr, ptr->n_lines) == -1) {
469  dig_free_isle(ptr);
470  return -1;
471  }
472 
473  if (ptr->n_lines) {
474  if (0 >= dig__fread_port_P(ptr->lines, ptr->n_lines, fp)) {
475  dig_free_isle(ptr);
476  return -1;
477  }
478  }
479 
480  /* area */
481  if (0 >= dig__fread_port_P(&(ptr->area), 1, fp)) {
482  dig_free_isle(ptr);
483  return -1;
484  }
485 
486  Plus->Isle[n] = ptr;
487 
488  return (0);
489 }
490 
491 int dig_Wr_P_isle(struct Plus_head *Plus, int n, struct gvfile *fp)
492 {
493  int i;
494  struct P_isle *ptr;
495 
496  ptr = Plus->Isle[n];
497 
498  /* If NULL i.e. dead write just 0 instead of number of lines */
499  if (ptr == NULL) {
500  i = 0;
501  if (0 >= dig__fwrite_port_P(&i, 1, fp))
502  return (-1);
503  return 0;
504  }
505 
506  /* lines */
507  if (0 >= dig__fwrite_port_P(&(ptr->n_lines), 1, fp))
508  return (-1);
509 
510  if (ptr->n_lines)
511  if (0 >= dig__fwrite_port_P(ptr->lines, ptr->n_lines, fp))
512  return -1;
513 
514  /* area */
515  if (0 >= dig__fwrite_port_P(&(ptr->area), 1, fp))
516  return (-1);
517 
518  return (0);
519 }
520 
521 /*!
522  \brief Read Plus_head from file
523 
524  \param fp pointer to gvfile structure
525  \param[in,out] ptr pointer to Plus_head structure
526 
527  \return -1 error
528  \return 0 OK
529  */
530 int dig_Rd_Plus_head(struct gvfile *fp, struct Plus_head *ptr)
531 {
532  unsigned char buf[5];
533  int byte_order;
534 
535  dig_rewind(fp);
536 
537  /* bytes 1 - 5 */
538  if (0 >= dig__fread_port_C((char *)buf, 5, fp))
539  return (-1);
540  ptr->version.topo.major = buf[0];
541  ptr->version.topo.minor = buf[1];
542  ptr->version.topo.back_major = buf[2];
543  ptr->version.topo.back_minor = buf[3];
544  byte_order = buf[4];
545 
546  G_debug(
547  2,
548  "Topo header: file version %d.%d , supported from GRASS version %d.%d",
549  ptr->version.topo.major, ptr->version.topo.minor,
551 
552  G_debug(2, " byte order %d", byte_order);
553 
554  /* check version numbers */
555  if (ptr->version.topo.major > GV_TOPO_VER_MAJOR ||
557  /* The file was created by GRASS library with higher version than this
558  * one */
559 
562  /* This version of GRASS lib is lower than the oldest which can read
563  * this format */
564  G_debug(1, "Topology format version %d.%d", ptr->version.topo.major,
565  ptr->version.topo.minor);
566  G_fatal_error(_("This version of GRASS (%d.%d) is too old to read "
567  "this topology format."
568  " Try to rebuild topology or upgrade GRASS to at "
569  "least version %d."),
571  GRASS_VERSION_MAJOR + 1);
572  return (-1);
573  }
574 
575  G_warning(_("Your GRASS version does not fully support topology format "
576  "%d.%d of the vector."
577  " Consider to rebuild topology or upgrade GRASS."),
578  ptr->version.topo.major, ptr->version.topo.minor);
579  }
580  if (ptr->version.topo.major < GV_TOPO_VER_MAJOR ||
581  (ptr->version.topo.major == GV_TOPO_VER_MAJOR &&
583  /* The file was created by GRASS library with lower version than this
584  * one */
585 
586  /* This version of GRASS lib can not read this old format */
587  G_warning(
588  _("Old topology format version %d.%d is not supported by this "
589  "release."
590  " Try to rebuild topology using v.build or v.build.all module."),
591  ptr->version.topo.major, ptr->version.topo.minor);
592  return (-1);
593  }
594 
595  /* init Port_info structure and set as default */
596  dig_init_portable(&(ptr->port), byte_order);
597  dig_set_cur_port(&(ptr->port));
598 
599  /* bytes 6 - 9 : header size */
600  if (0 >= dig__fread_port_L(&(ptr->head_size), 1, fp))
601  return (-1);
602  G_debug(2, " header size %ld", ptr->head_size);
603 
604  /* determine required offset size from header size */
605  /* this is not safe in case new fields get added in later versions */
606  /* better: add a new field with off_t_size after byte_order? */
607  if (ptr->head_size >= 142 + 32) /* keep in sync with dig_Wr_Plus_head() */
608  ptr->off_t_size = 8;
609  else
610  ptr->off_t_size = 4;
611 
612  if (sizeof(off_t) < (size_t)ptr->off_t_size) {
613  G_warning(_("Vector exceeds supported file size limit"));
614  return (-1);
615  }
616 
617  G_debug(2, "topo off_t size = %d", ptr->off_t_size);
618 
619  /* byte 10 : dimension 2D or 3D */
620  if (0 >= dig__fread_port_C((char *)buf, 1, fp))
621  return (-1);
622  ptr->with_z = buf[0];
623  G_debug(2, " with_z %d", ptr->with_z);
624 
625  /* bytes 11 - 58 : bound box */
626  if (0 >= dig__fread_port_D(&(ptr->box.N), 1, fp))
627  return (-1);
628  if (0 >= dig__fread_port_D(&(ptr->box.S), 1, fp))
629  return (-1);
630  if (0 >= dig__fread_port_D(&(ptr->box.E), 1, fp))
631  return (-1);
632  if (0 >= dig__fread_port_D(&(ptr->box.W), 1, fp))
633  return (-1);
634  if (0 >= dig__fread_port_D(&(ptr->box.T), 1, fp))
635  return (-1);
636  if (0 >= dig__fread_port_D(&(ptr->box.B), 1, fp))
637  return (-1);
638 
639  /* bytes 59 - 86 : number of structures */
640  if (0 >= dig__fread_port_P(&(ptr->n_nodes), 1, fp))
641  return (-1);
642  if (0 >= dig__fread_port_P(&(ptr->n_edges), 1, fp))
643  return (-1);
644  if (0 >= dig__fread_port_P(&(ptr->n_lines), 1, fp))
645  return (-1);
646  if (0 >= dig__fread_port_P(&(ptr->n_areas), 1, fp))
647  return (-1);
648  if (0 >= dig__fread_port_P(&(ptr->n_isles), 1, fp))
649  return (-1);
650  if (0 >= dig__fread_port_P(&(ptr->n_volumes), 1, fp))
651  return (-1);
652  if (0 >= dig__fread_port_P(&(ptr->n_holes), 1, fp))
653  return (-1);
654 
655  /* bytes 87 - 110 : number of line types */
656  if (0 >= dig__fread_port_P(&(ptr->n_plines), 1, fp))
657  return (-1);
658  if (0 >= dig__fread_port_P(&(ptr->n_llines), 1, fp))
659  return (-1);
660  if (0 >= dig__fread_port_P(&(ptr->n_blines), 1, fp))
661  return (-1);
662  if (0 >= dig__fread_port_P(&(ptr->n_clines), 1, fp))
663  return (-1);
664  if (0 >= dig__fread_port_P(&(ptr->n_flines), 1, fp))
665  return (-1);
666  if (0 >= dig__fread_port_P(&(ptr->n_klines), 1, fp))
667  return (-1);
668 
669  /* bytes 111 - 138 : Offset */
670  if (0 >= dig__fread_port_O(&(ptr->Node_offset), 1, fp, ptr->off_t_size))
671  return (-1);
672  if (0 >= dig__fread_port_O(&(ptr->Edge_offset), 1, fp, ptr->off_t_size))
673  return (-1);
674  if (0 >= dig__fread_port_O(&(ptr->Line_offset), 1, fp, ptr->off_t_size))
675  return (-1);
676  if (0 >= dig__fread_port_O(&(ptr->Area_offset), 1, fp, ptr->off_t_size))
677  return (-1);
678  if (0 >= dig__fread_port_O(&(ptr->Isle_offset), 1, fp, ptr->off_t_size))
679  return (-1);
680  if (0 >= dig__fread_port_O(&(ptr->Volume_offset), 1, fp, ptr->off_t_size))
681  return (-1);
682  if (0 >= dig__fread_port_O(&(ptr->Hole_offset), 1, fp, ptr->off_t_size))
683  return (-1);
684 
685  /* bytes 139 - 142 : Coor size and time */
686  if (0 >= dig__fread_port_O(&(ptr->coor_size), 1, fp, ptr->off_t_size))
687  return (-1);
688 
689  G_debug(2, " coor size %" PRId64, ptr->coor_size);
690 
691  dig_fseek(fp, ptr->head_size, SEEK_SET);
692 
693  return (0);
694 }
695 
696 /*!
697  \brief Write Plus_head to file
698 
699  ptr->off_t_size is used for both coor and topo files, but their sizes
700  (ptr->coor_size for coor and no variable for topo) can be different. If
701  either file is greater than PORT_LONG_MAX, ptr->off_t_size must be 8. This
702  function determines this value of ptr->off_t_size and writes it to the file.
703 
704  \param fp pointer to gvfile structure
705  \param[in,out] ptr pointer to Plus_head structure
706 
707  \return -1 error
708  \return 0 OK
709  */
710 int dig_Wr_Plus_head(struct gvfile *fp, struct Plus_head *ptr)
711 {
712  unsigned char buf[10];
713  long length = 142;
714 
715  dig_rewind(fp);
716  dig_set_cur_port(&(ptr->port));
717 
718  /* bytes 1 - 5 */
719  buf[0] = GV_TOPO_VER_MAJOR;
720  buf[1] = GV_TOPO_VER_MINOR;
721  buf[2] = GV_TOPO_EARLIEST_MAJOR;
722  buf[3] = GV_TOPO_EARLIEST_MINOR;
723  buf[4] = ptr->port.byte_order;
724  if (0 >= dig__fwrite_port_C((char *)buf, 5, fp))
725  return (-1);
726 
727  /* determine required offset size from coor file size */
728  if (ptr->coor_size > (off_t)PORT_LONG_MAX) {
729  /* can only happen when sizeof(off_t) == 8 */
730  ptr->off_t_size = 8;
731  }
732  else if (ptr->off_t_size == 0) {
733  /* calculate the total size of topo file to get the correct off_t_size
734  * if coor file is less than PORT_LONG_MAX */
735  off_t size = length;
736  int i;
737 
738  for (i = 1; i <= ptr->n_nodes; i++) {
739  /* from dig_Wr_P_node() */
740  struct P_node *p = ptr->Node[i];
741 
742  if (p == NULL)
743  size += 4;
744  else {
745  size += 20 + 8 * p->n_lines;
746  if (ptr->with_z)
747  size += 12;
748  }
749  }
750 
751  for (i = 1; i <= ptr->n_lines; i++) {
752  /* from dig_Wr_P_line() */
753  struct P_line *p = ptr->Line[i];
754 
755  if (p == NULL)
756  size += 1;
757  else {
758  /* for now, off_t_size = 4 */
759  size += 5;
760  if (p->type & GV_CENTROID)
761  size += 4;
762  else if (p->type & GV_LINE)
763  size += 8;
764  else if (p->type & GV_BOUNDARY)
765  size += 16;
766  else if ((p->type & GV_FACE) && ptr->with_z)
767  size += 12;
768  else if ((p->type & GV_KERNEL) && ptr->with_z)
769  size += 4;
770  }
771  }
772 
773  for (i = 1; i <= ptr->n_areas; i++) {
774  /* from dig_Wr_P_area() */
775  struct P_area *p = ptr->Area[i];
776 
777  if (p == NULL)
778  size += 4;
779  else
780  size += 12 + 4 * p->n_lines + 4 * p->n_isles;
781  }
782 
783  for (i = 1; i <= ptr->n_isles; i++) {
784  /* from dig_Wr_P_isle() */
785  struct P_isle *p = ptr->Isle[i];
786 
787  if (p == NULL)
788  size += 4;
789  else
790  size += 8 + 4 * p->n_lines;
791  }
792 
793  ptr->off_t_size = size > (off_t)PORT_LONG_MAX ? 8 : 4;
794  }
795 
796  /* add a new field with off_t_size after byte_order? */
797 
798  /* adjust header size for large files */
799  if (ptr->off_t_size == 8) {
800  /* 7 offset values and coor file size: add 8 * 4 */
801  length += 32;
802  }
803 
804  /* bytes 6 - 9 : header size */
805  if (0 >= dig__fwrite_port_L(&length, 1, fp))
806  return (0);
807 
808  /* byte 10 : dimension 2D or 3D */
809  buf[0] = ptr->with_z;
810  if (0 >= dig__fwrite_port_C((char *)buf, 1, fp))
811  return (0);
812 
813  /* bytes 11 - 58 : bound box */
814  if (0 >= dig__fwrite_port_D(&(ptr->box.N), 1, fp))
815  return (-1);
816  if (0 >= dig__fwrite_port_D(&(ptr->box.S), 1, fp))
817  return (-1);
818  if (0 >= dig__fwrite_port_D(&(ptr->box.E), 1, fp))
819  return (-1);
820  if (0 >= dig__fwrite_port_D(&(ptr->box.W), 1, fp))
821  return (-1);
822  if (0 >= dig__fwrite_port_D(&(ptr->box.T), 1, fp))
823  return (-1);
824  if (0 >= dig__fwrite_port_D(&(ptr->box.B), 1, fp))
825  return (-1);
826 
827  /* bytes 59 - 86 : number of structures */
828  if (0 >= dig__fwrite_port_P(&(ptr->n_nodes), 1, fp))
829  return (-1);
830  if (0 >= dig__fwrite_port_P(&(ptr->n_edges), 1, fp))
831  return (-1);
832  if (0 >= dig__fwrite_port_P(&(ptr->n_lines), 1, fp))
833  return (-1);
834  if (0 >= dig__fwrite_port_P(&(ptr->n_areas), 1, fp))
835  return (-1);
836  if (0 >= dig__fwrite_port_P(&(ptr->n_isles), 1, fp))
837  return (-1);
838  if (0 >= dig__fwrite_port_P(&(ptr->n_volumes), 1, fp))
839  return (-1);
840  if (0 >= dig__fwrite_port_P(&(ptr->n_holes), 1, fp))
841  return (-1);
842 
843  /* bytes 87 - 110 : number of line types */
844  if (0 >= dig__fwrite_port_P(&(ptr->n_plines), 1, fp))
845  return (-1);
846  if (0 >= dig__fwrite_port_P(&(ptr->n_llines), 1, fp))
847  return (-1);
848  if (0 >= dig__fwrite_port_P(&(ptr->n_blines), 1, fp))
849  return (-1);
850  if (0 >= dig__fwrite_port_P(&(ptr->n_clines), 1, fp))
851  return (-1);
852  if (0 >= dig__fwrite_port_P(&(ptr->n_flines), 1, fp))
853  return (-1);
854  if (0 >= dig__fwrite_port_P(&(ptr->n_klines), 1, fp))
855  return (-1);
856 
857  /* bytes 111 - 138 : Offset */
858  if (0 >= dig__fwrite_port_O(&(ptr->Node_offset), 1, fp, ptr->off_t_size))
859  return (-1);
860  if (0 >= dig__fwrite_port_O(&(ptr->Edge_offset), 1, fp, ptr->off_t_size))
861  return (-1);
862  if (0 >= dig__fwrite_port_O(&(ptr->Line_offset), 1, fp, ptr->off_t_size))
863  return (-1);
864  if (0 >= dig__fwrite_port_O(&(ptr->Area_offset), 1, fp, ptr->off_t_size))
865  return (-1);
866  if (0 >= dig__fwrite_port_O(&(ptr->Isle_offset), 1, fp, ptr->off_t_size))
867  return (-1);
868  if (0 >= dig__fwrite_port_O(&(ptr->Volume_offset), 1, fp, ptr->off_t_size))
869  return (-1);
870  if (0 >= dig__fwrite_port_O(&(ptr->Hole_offset), 1, fp, ptr->off_t_size))
871  return (-1);
872 
873  /* bytes 139 - 142 : Coor size and time */
874  if (0 >= dig__fwrite_port_O(&(ptr->coor_size), 1, fp, ptr->off_t_size))
875  return (-1);
876 
877  G_debug(2, "topo body offset %" PRId64, dig_ftell(fp));
878 
879  return (0);
880 }
#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:530
int dig_Rd_P_node(struct Plus_head *Plus, int n, struct gvfile *fp)
Definition: plus_struct.c:51
int dig_Wr_P_isle(struct Plus_head *Plus, int n, struct gvfile *fp)
Definition: plus_struct.c:491
int dig_Rd_P_isle(struct Plus_head *Plus, int n, struct gvfile *fp)
Definition: plus_struct.c:448
int dig_Wr_P_node(struct Plus_head *Plus, int n, struct gvfile *fp)
Definition: plus_struct.c:117
int dig_Rd_P_line(struct Plus_head *Plus, int n, struct gvfile *fp)
Definition: plus_struct.c:162
int dig_Rd_P_area(struct Plus_head *Plus, int n, struct gvfile *fp)
Definition: plus_struct.c:350
int dig_Wr_Plus_head(struct gvfile *fp, struct Plus_head *ptr)
Write Plus_head to file.
Definition: plus_struct.c:710
int dig_Wr_P_line(struct Plus_head *Plus, int n, struct gvfile *fp)
Definition: plus_struct.c:259
int dig_Wr_P_area(struct Plus_head *Plus, int n, struct gvfile *fp)
Definition: plus_struct.c:410
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