GRASS GIS 8 Programmer's Manual  8.5.0dev(2024)-602118adcc
cindex_rw.c
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * MODULE: Vector library
4  *
5  * AUTHOR(S): Radim Blazek.
6  *
7  * PURPOSE: Lower level functions for reading/writing/manipulating vectors.
8  *
9  * COPYRIGHT: (C) 2001 by the GRASS Development Team
10  *
11  * This program is free software under the GNU General Public
12  * License (>=v2). Read the file COPYING that comes with
13  * GRASS for details.
14  *
15  *****************************************************************************/
16 
17 #include <inttypes.h>
18 #include <stdlib.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 int dig_write_cidx_head(struct gvfile *fp, struct Plus_head *plus)
26 {
27  int i;
28  unsigned char buf[5];
29  long length = 9;
30 
31  G_debug(3, "dig_write_cidx_head()");
32 
33  dig_rewind(fp);
34  dig_set_cur_port(&(plus->cidx_port));
35 
36  /* Head of header */
37  /* bytes 1 - 5 */
38  buf[0] = GV_CIDX_VER_MAJOR;
39  buf[1] = GV_CIDX_VER_MINOR;
40  buf[2] = GV_CIDX_EARLIEST_MAJOR;
41  buf[3] = GV_CIDX_EARLIEST_MINOR;
42  buf[4] = plus->cidx_port.byte_order;
43  if (0 >= dig__fwrite_port_C((const char *)buf, 5, fp))
44  return (-1);
45 
46  /* get required offset size */
47  if (plus->off_t_size == 0) {
48  /* should not happen, topo is written first */
49  if (plus->coor_size > (off_t)PORT_LONG_MAX)
50  plus->off_t_size = 8;
51  else
52  plus->off_t_size = 4;
53  }
54 
55  /* bytes 6 - 9 : header size */
56  if (0 >= dig__fwrite_port_L(&length, 1, fp))
57  return (0);
58 
59  /* Body of header - info about all fields */
60  /* Number of fields */
61  if (0 >= dig__fwrite_port_I(&(plus->n_cidx), 1, fp))
62  return (-1);
63 
64  for (i = 0; i < plus->n_cidx; i++) {
65  int t;
66  struct Cat_index *ci;
67 
68  ci = &(plus->cidx[i]);
69 
70  G_debug(3, "cidx %d head offset: %" PRId64, i, dig_ftell(fp));
71 
72  /* Field number */
73  if (0 >= dig__fwrite_port_I(&(ci->field), 1, fp))
74  return (-1);
75 
76  /* Number of categories */
77  if (0 >= dig__fwrite_port_I(&(ci->n_cats), 1, fp))
78  return (-1);
79 
80  /* Number of unique categories */
81  if (0 >= dig__fwrite_port_I(&(ci->n_ucats), 1, fp))
82  return (-1);
83 
84  /* Number of types */
85  if (0 >= dig__fwrite_port_I(&(ci->n_types), 1, fp))
86  return (-1);
87 
88  /* Types */
89  for (t = 0; t < ci->n_types; t++) {
90  int wtype;
91 
92  /* type */
93  wtype = dig_type_to_store(ci->type[t][0]);
94  if (0 >= dig__fwrite_port_I(&wtype, 1, fp))
95  return (-1);
96 
97  /* number of items */
98  if (0 >= dig__fwrite_port_I(&(ci->type[t][1]), 1, fp))
99  return (-1);
100  }
101 
102  /* Offset */
103  if (0 >= dig__fwrite_port_O(&(ci->offset), 1, fp, plus->off_t_size))
104  return (0);
105  G_debug(3, "cidx %d offset: %" PRId64, i, ci->offset);
106  }
107 
108  G_debug(3, "cidx body offset %" PRId64, dig_ftell(fp));
109 
110  return (0);
111 }
112 
113 /*!
114  \brief Read header of cidx file
115 
116  \param fp pointer to gvfile structure
117  \param plus pointer to Plus_head structure
118 
119  \return 0 OK
120  \return -1 error
121  */
122 int dig_read_cidx_head(struct gvfile *fp, struct Plus_head *plus)
123 {
124  unsigned char buf[5];
125  int i, byte_order;
126 
127  dig_rewind(fp);
128 
129  /* bytes 1 - 5 */
130  if (0 >= dig__fread_port_C((char *)buf, 5, fp))
131  return (-1);
132  plus->version.cidx.major = buf[0];
133  plus->version.cidx.minor = buf[1];
134  plus->version.cidx.back_major = buf[2];
135  plus->version.cidx.back_minor = buf[3];
136  byte_order = buf[4];
137 
138  G_debug(
139  3,
140  "Cidx header: file version %d.%d , supported from GRASS version %d.%d",
141  plus->version.cidx.major, plus->version.cidx.minor,
143 
144  G_debug(3, " byte order %d", byte_order);
145 
146  /* check version numbers */
147  if (plus->version.cidx.major > GV_CIDX_VER_MAJOR ||
149  /* The file was created by GRASS library with higher version than this
150  * one */
151 
154  /* This version of GRASS lib is lower than the oldest which can read
155  * this format */
156  G_debug(1, "Category index format version %d.%d",
157  plus->version.cidx.major, plus->version.cidx.minor);
158  G_fatal_error(_("This version of GRASS (%d.%d) is too old to read "
159  "this category index format."
160  " Try to rebuild topology or upgrade GRASS to at "
161  "least version %d."),
163  GRASS_VERSION_MAJOR + 1);
164  return (-1);
165  }
166 
167  G_warning("Your GRASS version does not fully support category index "
168  "format %d.%d of the vector."
169  " Consider to rebuild topology or upgrade GRASS.",
170  plus->version.cidx.major, plus->version.cidx.minor);
171  }
172 
173  dig_init_portable(&(plus->cidx_port), byte_order);
174  dig_set_cur_port(&(plus->cidx_port));
175 
176  /* bytes 6 - 9 : header size */
177  if (0 >= dig__fread_port_L(&(plus->cidx_head_size), 1, fp))
178  return (-1);
179  G_debug(3, " header size %ld", plus->cidx_head_size);
180 
181  /* get required offset size */
182  if (plus->off_t_size == 0) {
183  /* should not happen, topo is opened first */
184  if (plus->coor_size > (off_t)PORT_LONG_MAX)
185  plus->off_t_size = 8;
186  else
187  plus->off_t_size = 4;
188  }
189 
190  /* Body of header - info about all fields */
191  /* Number of fields */
192  if (0 >= dig__fread_port_I(&(plus->n_cidx), 1, fp))
193  return (-1);
194 
195  /* alloc space */
196  if (plus->a_cidx < plus->n_cidx) {
197  plus->a_cidx = plus->n_cidx;
198  plus->cidx = (struct Cat_index *)G_realloc(
199  plus->cidx, plus->a_cidx * sizeof(struct Cat_index));
200  }
201 
202  for (i = 0; i < plus->n_cidx; i++) {
203  int t;
204  struct Cat_index *ci;
205 
206  ci = &(plus->cidx[i]);
207  ci->cat = NULL;
208  ci->a_cats = 0;
209 
210  /* Field number */
211  if (0 >= dig__fread_port_I(&(ci->field), 1, fp))
212  return (-1);
213 
214  /* Number of categories */
215  if (0 >= dig__fread_port_I(&(ci->n_cats), 1, fp))
216  return (-1);
217 
218  /* Number of unique categories */
219  if (0 >= dig__fread_port_I(&(ci->n_ucats), 1, fp))
220  return (-1);
221 
222  /* Number of types */
223  if (0 >= dig__fread_port_I(&(ci->n_types), 1, fp))
224  return (-1);
225 
226  /* Types */
227  for (t = 0; t < ci->n_types; t++) {
228  int rtype;
229 
230  /* type */
231  if (0 >= dig__fread_port_I(&rtype, 1, fp))
232  return (-1);
233  ci->type[t][0] = dig_type_from_store(rtype);
234 
235  /* number of items */
236  if (0 >= dig__fread_port_I(&(ci->type[t][1]), 1, fp))
237  return (-1);
238  }
239 
240  /* Offset */
241  if (0 >= dig__fread_port_O(&(ci->offset), 1, fp, plus->off_t_size))
242  return (0);
243  }
244 
245  if (dig_fseek(fp, plus->cidx_head_size, SEEK_SET) == -1)
246  return (-1);
247 
248  return (0);
249 }
250 
251 /* Write spatial index */
252 int dig_write_cidx(struct gvfile *fp, struct Plus_head *plus)
253 {
254  int i;
255 
256  dig_set_cur_port(&(plus->cidx_port));
257  dig_rewind(fp);
258 
259  dig_write_cidx_head(fp, plus);
260 
261  /* Write category-type-id for each field */
262  for (i = 0; i < plus->n_cidx; i++) {
263  int j;
264  struct Cat_index *ci;
265 
266  ci = &(plus->cidx[i]);
267  ci->offset = dig_ftell(fp);
268 
269  /* convert type */
270  for (j = 0; j < ci->n_cats; j++)
271  ci->cat[j][1] = dig_type_to_store(ci->cat[j][1]);
272 
273  if (0 >= dig__fwrite_port_I((int *)ci->cat, 3 * ci->n_cats, fp))
274  return (-1);
275 
276  /* Return back */
277  for (j = 0; j < ci->n_cats; j++)
278  ci->cat[j][1] = dig_type_from_store(ci->cat[j][1]);
279  }
280 
281  dig_write_cidx_head(fp, plus); /* rewrite with offsets */
282 
283  return 0;
284 }
285 
286 /*!
287  \brief Read spatial index file
288 
289  \param fp pointer to gvfile structure
290  \param[in,out] plus pointer to Plus_head structure
291  \param head_only non-zero to read only head
292 
293  \return 0 OK
294  \return 1 error
295  */
296 int dig_read_cidx(struct gvfile *fp, struct Plus_head *plus, int head_only)
297 {
298  int i;
299 
300  G_debug(3, "dig_read_cidx()");
301 
302  dig_cidx_free(plus);
303  dig_cidx_init(plus);
304 
305  dig_rewind(fp);
306  if (dig_read_cidx_head(fp, plus) == -1) {
307  G_debug(3, "Cannot read cidx head");
308  return 1;
309  }
310 
311  if (head_only) {
312  plus->cidx_up_to_date = 1; /* OK ? */
313  return 0;
314  }
315 
316  dig_set_cur_port(&(plus->cidx_port));
317 
318  /* Read category-type-id for each field */
319  for (i = 0; i < plus->n_cidx; i++) {
320  int j;
321  struct Cat_index *ci;
322 
323  ci = &(plus->cidx[i]);
324  ci->a_cats = ci->n_cats;
325  ci->cat = G_malloc(ci->a_cats * 3 * sizeof(int));
326 
327  if (dig_fseek(fp, ci->offset, 0) == -1)
328  return 1;
329 
330  if (0 >= dig__fread_port_I((int *)ci->cat, 3 * ci->n_cats, fp))
331  return 1;
332 
333  /* convert type */
334  for (j = 0; j < ci->n_cats; j++)
335  ci->cat[j][1] = dig_type_from_store(ci->cat[j][1]);
336  }
337 
338  plus->cidx_up_to_date = 1;
339 
340  return 0;
341 }
#define NULL
Definition: ccmath.h:32
int dig_write_cidx(struct gvfile *fp, struct Plus_head *plus)
Definition: cindex_rw.c:252
int dig_read_cidx(struct gvfile *fp, struct Plus_head *plus, int head_only)
Read spatial index file.
Definition: cindex_rw.c:296
int dig_write_cidx_head(struct gvfile *fp, struct Plus_head *plus)
Definition: cindex_rw.c:25
int dig_read_cidx_head(struct gvfile *fp, struct Plus_head *plus)
Read header of cidx file.
Definition: cindex_rw.c:122
#define G_realloc(p, n)
Definition: defs/gis.h:96
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
#define G_malloc(n)
Definition: defs/gis.h:94
int G_debug(int, const char *,...) __attribute__((format(printf
#define GV_CIDX_VER_MINOR
Definition: dig_defines.h:157
#define PORT_LONG_MAX
Definition: dig_defines.h:70
#define GV_CIDX_EARLIEST_MINOR
Definition: dig_defines.h:168
#define GV_CIDX_EARLIEST_MAJOR
Definition: dig_defines.h:167
#define GV_CIDX_VER_MAJOR
Definition: dig_defines.h:156
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
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__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_set_cur_port(struct Port_info *)
Set current Port_info structure.
Definition: portable.c:996
void dig_cidx_free(struct Plus_head *)
Definition: diglib/cindex.c:44
void dig_rewind(struct gvfile *file)
Rewind file position.
Definition: file.c:87
int dig__fread_port_C(char *, size_t, struct gvfile *)
Read chars from the Portable Vector Format.
Definition: portable.c:511
int dig_cidx_init(struct Plus_head *)
Initialize Plus_head structure (cidx)
Definition: diglib/cindex.c:29
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.
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_type_to_store(int)
Convert type to store type.
#define _(str)
Definition: glocale.h:10
double t
Definition: r_raster.c:39
Category index.
Definition: dig_structs.h:718
int n_types
Number of types in type.
Definition: dig_structs.h:742
int(* cat)[3]
Array of cats (cat, type, lines/area)
Definition: dig_structs.h:734
int a_cats
Allocated space in cat array.
Definition: dig_structs.h:730
int n_cats
Number of items in cat array.
Definition: dig_structs.h:726
off_t offset
Offset of the beginning of this index in cidx file.
Definition: dig_structs.h:758
int field
Field (layer) number.
Definition: dig_structs.h:722
int type[7][2]
Number of elements for each type.
Definition: dig_structs.h:754
int n_ucats
Number of unique cats (not updated)
Definition: dig_structs.h:738
Basic topology-related info.
Definition: dig_structs.h:769
int n_cidx
Number of category indexes (one for each field/layer)
Definition: dig_structs.h:1125
struct Port_info cidx_port
Portability information for category index.
Definition: dig_structs.h:837
off_t coor_size
Size of coor file.
Definition: dig_structs.h:1145
struct Plus_head::@9 version
Backward compatibility version info.
int off_t_size
Offset size.
Definition: dig_structs.h:801
int a_cidx
Allocated space for category indexes.
Definition: dig_structs.h:1129
int cidx_up_to_date
Category index to be updated.
Definition: dig_structs.h:1140
struct Version_info cidx
Version info for category index file.
Definition: dig_structs.h:777
long cidx_head_size
Category index header size.
Definition: dig_structs.h:816
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
File definition.
Definition: dig_structs.h:94
#define GRASS_VERSION_MINOR
Definition: version.h:3
#define GRASS_VERSION_MAJOR
Definition: version.h:2