GRASS GIS 7 Programmer's Manual  7.9.dev(2021)-e5379bbd7
cindex_rw.c
Go to the documentation of this file.
1 
2 /****************************************************************************
3 *
4 * MODULE: Vector library
5 *
6 * AUTHOR(S): 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 #include <stdlib.h>
18 #include <sys/types.h>
19 #include <string.h>
20 #include <grass/vector.h>
21 #include <grass/glocale.h>
22 #include <grass/version.h>
23 
24 int dig_write_cidx_head(struct gvfile * fp, struct Plus_head *plus)
25 {
26  int i;
27  unsigned char buf[5];
28  long length = 9;
29 
30  G_debug(3, "dig_write_cidx_head()");
31 
32  dig_rewind(fp);
33  dig_set_cur_port(&(plus->cidx_port));
34 
35  /* Head of header */
36  /* bytes 1 - 5 */
37  buf[0] = GV_CIDX_VER_MAJOR;
38  buf[1] = GV_CIDX_VER_MINOR;
39  buf[2] = GV_CIDX_EARLIEST_MAJOR;
40  buf[3] = GV_CIDX_EARLIEST_MINOR;
41  buf[4] = plus->cidx_port.byte_order;
42  if (0 >= dig__fwrite_port_C((const char *)buf, 5, fp))
43  return (-1);
44 
45  /* get required offset size */
46  if (plus->off_t_size == 0) {
47  /* should not happen, topo is written first */
48  if (plus->coor_size > (off_t)PORT_LONG_MAX)
49  plus->off_t_size = 8;
50  else
51  plus->off_t_size = 4;
52  }
53 
54  /* bytes 6 - 9 : header size */
55  if (0 >= dig__fwrite_port_L(&length, 1, fp))
56  return (0);
57 
58  /* Body of header - info about all fields */
59  /* Number of fields */
60  if (0 >= dig__fwrite_port_I(&(plus->n_cidx), 1, fp))
61  return (-1);
62 
63  for (i = 0; i < plus->n_cidx; i++) {
64  int t;
65  struct Cat_index *ci;
66 
67  ci = &(plus->cidx[i]);
68 
69  G_debug(3, "cidx %d head offset: %"PRI_OFF_T, i, dig_ftell(fp));
70 
71  /* Field number */
72  if (0 >= dig__fwrite_port_I(&(ci->field), 1, fp))
73  return (-1);
74 
75  /* Number of categories */
76  if (0 >= dig__fwrite_port_I(&(ci->n_cats), 1, fp))
77  return (-1);
78 
79  /* Number of unique categories */
80  if (0 >= dig__fwrite_port_I(&(ci->n_ucats), 1, fp))
81  return (-1);
82 
83  /* Number of types */
84  if (0 >= dig__fwrite_port_I(&(ci->n_types), 1, fp))
85  return (-1);
86 
87  /* Types */
88  for (t = 0; t < ci->n_types; t++) {
89  int wtype;
90 
91  /* type */
92  wtype = dig_type_to_store(ci->type[t][0]);
93  if (0 >= dig__fwrite_port_I(&wtype, 1, fp))
94  return (-1);
95 
96  /* number of items */
97  if (0 >= dig__fwrite_port_I(&(ci->type[t][1]), 1, fp))
98  return (-1);
99 
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: %"PRI_OFF_T, i, ci->offset);
106  }
107 
108  G_debug(3, "cidx body offset %"PRI_OFF_T, 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 strcuture
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(3,
139  "Cidx header: file version %d.%d , supported from GRASS version %d.%d",
140  plus->version.cidx.major, plus->version.cidx.minor,
142 
143  G_debug(3, " byte order %d", byte_order);
144 
145  /* check version numbers */
146  if (plus->version.cidx.major > GV_CIDX_VER_MAJOR ||
148  /* The file was created by GRASS library with higher version than this one */
149 
152  /* This version of GRASS lib is lower than the oldest which can read this format */
153  G_debug(1, "Category index format version %d.%d",
154  plus->version.cidx.major, plus->version.cidx.minor);
156  (_("This version of GRASS (%d.%d) is too old to read this category index format."
157  " Try to rebuild topology or upgrade GRASS to at least version %d."),
159  return (-1);
160  }
161 
162  G_warning
163  ("Your GRASS version does not fully support category index format %d.%d of the vector."
164  " Consider to rebuild topology or upgrade GRASS.",
165  plus->version.cidx.major, plus->version.cidx.minor);
166  }
167 
168  dig_init_portable(&(plus->cidx_port), byte_order);
169  dig_set_cur_port(&(plus->cidx_port));
170 
171  /* bytes 6 - 9 : header size */
172  if (0 >= dig__fread_port_L(&(plus->cidx_head_size), 1, fp))
173  return (-1);
174  G_debug(3, " header size %ld", plus->cidx_head_size);
175 
176  /* get required offset size */
177  if (plus->off_t_size == 0) {
178  /* should not happen, topo is opened first */
179  if (plus->coor_size > (off_t)PORT_LONG_MAX)
180  plus->off_t_size = 8;
181  else
182  plus->off_t_size = 4;
183  }
184 
185  /* Body of header - info about all fields */
186  /* Number of fields */
187  if (0 >= dig__fread_port_I(&(plus->n_cidx), 1, fp))
188  return (-1);
189 
190  /* alloc space */
191  if (plus->a_cidx < plus->n_cidx) {
192  plus->a_cidx = plus->n_cidx;
193  plus->cidx =
194  (struct Cat_index *)G_realloc(plus->cidx, plus->a_cidx * sizeof(struct Cat_index));
195  }
196 
197  for (i = 0; i < plus->n_cidx; i++) {
198  int t;
199  struct Cat_index *ci;
200 
201  ci = &(plus->cidx[i]);
202  ci->cat = NULL;
203  ci->a_cats = 0;
204 
205  /* Field number */
206  if (0 >= dig__fread_port_I(&(ci->field), 1, fp))
207  return (-1);
208 
209  /* Number of categories */
210  if (0 >= dig__fread_port_I(&(ci->n_cats), 1, fp))
211  return (-1);
212 
213  /* Number of unique categories */
214  if (0 >= dig__fread_port_I(&(ci->n_ucats), 1, fp))
215  return (-1);
216 
217  /* Number of types */
218  if (0 >= dig__fread_port_I(&(ci->n_types), 1, fp))
219  return (-1);
220 
221  /* Types */
222  for (t = 0; t < ci->n_types; t++) {
223  int rtype;
224 
225  /* type */
226  if (0 >= dig__fread_port_I(&rtype, 1, fp))
227  return (-1);
228  ci->type[t][0] = dig_type_from_store(rtype);
229 
230  /* number of items */
231  if (0 >= dig__fread_port_I(&(ci->type[t][1]), 1, fp))
232  return (-1);
233  }
234 
235  /* Offset */
236  if (0 >= dig__fread_port_O(&(ci->offset), 1, fp, plus->off_t_size))
237  return (0);
238  }
239 
240  if (dig_fseek(fp, plus->cidx_head_size, SEEK_SET) == -1)
241  return (-1);
242 
243  return (0);
244 }
245 
246 /* Write spatial index */
247 int dig_write_cidx(struct gvfile * fp, struct Plus_head *plus)
248 {
249  int i;
250 
251  dig_set_cur_port(&(plus->cidx_port));
252  dig_rewind(fp);
253 
254  dig_write_cidx_head(fp, plus);
255 
256  /* Write category-type-id for each field */
257  for (i = 0; i < plus->n_cidx; i++) {
258  int j;
259  struct Cat_index *ci;
260 
261  ci = &(plus->cidx[i]);
262  ci->offset = dig_ftell(fp);
263 
264  /* convert type */
265  for (j = 0; j < ci->n_cats; j++)
266  ci->cat[j][1] = dig_type_to_store(ci->cat[j][1]);
267 
268  if (0 >= dig__fwrite_port_I((int *)ci->cat, 3 * ci->n_cats, fp))
269  return (-1);
270 
271  /* Return back */
272  for (j = 0; j < ci->n_cats; j++)
273  ci->cat[j][1] = dig_type_from_store(ci->cat[j][1]);
274  }
275 
276  dig_write_cidx_head(fp, plus); /* rewrite with offsets */
277 
278  return 0;
279 }
280 
281 /*!
282  \brief Read spatial index file
283 
284  \param fp pointer to gvfile structure
285  \param[in,out] plus pointer to Plus_head structure
286  \param head_only non-zero to read only head
287 
288  \return 0 OK
289  \return 1 error
290 */
291 int dig_read_cidx(struct gvfile * fp, struct Plus_head *plus, int head_only)
292 {
293  int i;
294 
295  G_debug(3, "dig_read_cidx()");
296 
297  dig_cidx_free(plus);
298  dig_cidx_init(plus);
299 
300  dig_rewind(fp);
301  if (dig_read_cidx_head(fp, plus) == -1) {
302  G_debug(3, "Cannot read cidx head");
303  return 1;
304  }
305 
306  if (head_only) {
307  plus->cidx_up_to_date = 1; /* OK ? */
308  return 0;
309  }
310 
311  dig_set_cur_port(&(plus->cidx_port));
312 
313  /* Read category-type-id for each field */
314  for (i = 0; i < plus->n_cidx; i++) {
315  int j;
316  struct Cat_index *ci;
317 
318  ci = &(plus->cidx[i]);
319  ci->a_cats = ci->n_cats;
320  ci->cat = G_malloc(ci->a_cats * 3 * sizeof(int));
321 
322  if (dig_fseek(fp, ci->offset, 0) == -1)
323  return 1;
324 
325  if (0 >= dig__fread_port_I((int *)ci->cat, 3 * ci->n_cats, fp))
326  return 1;
327 
328  /* convert type */
329  for (j = 0; j < ci->n_cats; j++)
330  ci->cat[j][1] = dig_type_from_store(ci->cat[j][1]);
331  }
332 
333 
334  plus->cidx_up_to_date = 1;
335 
336  return 0;
337 }
#define G_malloc(n)
Definition: defs/gis.h:112
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
off_t coor_size
Size of coor file.
Definition: dig_structs.h:1161
void dig_rewind(struct gvfile *file)
Rewind file position.
Definition: file.c:87
int a_cidx
Allocated space for category indexes.
Definition: dig_structs.h:1145
struct Version_info cidx
Version info for category index file.
Definition: dig_structs.h:793
void dig_init_portable(struct Port_info *, int)
Set Port_info structure to byte order of file.
Definition: portable.c:905
int dig__fwrite_port_I(const int *, size_t, struct gvfile *)
Write integers to the Portable Vector Format.
Definition: portable.c:758
int dig_type_to_store(int)
Convert type to store type.
#define GV_CIDX_EARLIEST_MINOR
Definition: dig_defines.h:167
int n_types
Number of types in type.
Definition: dig_structs.h:757
int back_major
Earliest version that can use this data format (major)
Definition: dig_structs.h:284
int dig__fwrite_port_C(const char *, size_t, struct gvfile *)
Write chars to the Portable Vector Format.
Definition: portable.c:890
int dig__fread_port_I(int *, size_t, struct gvfile *)
Read integers from the Portable Vector Format.
Definition: portable.c:343
int dig__fread_port_C(char *, size_t, struct gvfile *)
Read chars from the Portable Vector Format.
Definition: portable.c:509
off_t offset
Offset of the beginning of this index in cidx file.
Definition: dig_structs.h:773
long cidx_head_size
Category index header size.
Definition: dig_structs.h:832
void dig_cidx_free(struct Plus_head *)
Definition: diglib/cindex.c:44
Category index.
Definition: dig_structs.h:732
#define PORT_LONG_MAX
Definition: dig_defines.h:70
int dig__fread_port_L(long *, size_t, struct gvfile *)
Read longs from the Portable Vector Format.
Definition: portable.c:260
#define PRI_OFF_T
Definition: gis.h:69
int field
Field (layer) number.
Definition: dig_structs.h:737
#define GRASS_VERSION_MINOR
Definition: version.h:3
#define GV_CIDX_VER_MAJOR
Definition: dig_defines.h:155
#define NULL
Definition: ccmath.h:32
off_t dig_ftell(struct gvfile *file)
Get struct gvfile position.
Definition: file.c:36
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_write_cidx(struct gvfile *fp, struct Plus_head *plus)
Definition: cindex_rw.c:247
#define GRASS_VERSION_MAJOR
Definition: version.h:2
int n_ucats
Number of unique cats (not updated)
Definition: dig_structs.h:753
int cidx_up_to_date
Category index to be updated.
Definition: dig_structs.h:1156
double t
Definition: r_raster.c:39
int off_t_size
Offset size.
Definition: dig_structs.h:817
int dig_cidx_init(struct Plus_head *)
Initialize Plus_head structure (cidx)
Definition: diglib/cindex.c:29
#define GV_CIDX_VER_MINOR
Definition: dig_defines.h:156
Basic topology-related info.
Definition: dig_structs.h:784
int major
Current version (major)
Definition: dig_structs.h:280
int n_cats
Number of items in cat array.
Definition: dig_structs.h:741
int dig_read_cidx(struct gvfile *fp, struct Plus_head *plus, int head_only)
Read spatial index file.
Definition: cindex_rw.c:291
int dig_type_from_store(int)
Convert type from store type.
int(* cat)[3]
Array of cats (cat, type, lines/area)
Definition: dig_structs.h:749
int byte_order
File byte order.
Definition: dig_structs.h:191
int type[7][2]
Number of elements for each type.
Definition: dig_structs.h:769
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 a_cats
Allocated space in cat array.
Definition: dig_structs.h:745
int dig_write_cidx_head(struct gvfile *fp, struct Plus_head *plus)
Definition: cindex_rw.c:24
void G_warning(const char *,...) __attribute__((format(printf
#define G_realloc(p, n)
Definition: defs/gis.h:114
#define _(str)
Definition: glocale.h:10
int minor
Current version (minor)
Definition: dig_structs.h:282
int dig_set_cur_port(struct Port_info *)
Set current Port_info structure.
Definition: portable.c:1001
int dig__fwrite_port_L(const long *, size_t, struct gvfile *)
Write longs to the Portable Vector Format.
Definition: portable.c:702
int back_minor
Earliest version that can use this data format (minor)
Definition: dig_structs.h:286
File definition.
Definition: dig_structs.h:96
struct Port_info cidx_port
Portability information for category index.
Definition: dig_structs.h:853
int G_debug(int, const char *,...) __attribute__((format(printf
#define GV_CIDX_EARLIEST_MAJOR
Definition: dig_defines.h:166
int dig_fseek(struct gvfile *file, off_t offset, int whence)
Set struct gvfile position.
Definition: file.c:60
int dig_read_cidx_head(struct gvfile *fp, struct Plus_head *plus)
Read header of cidx file.
Definition: cindex_rw.c:122
struct Plus_head::@9 version
Backward compatibility version info.
int n_cidx
Number of category indexes (one for each field/layer)
Definition: dig_structs.h:1141