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