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