GRASS 8 Programmer's Manual 8.6.0dev(2026)-1878fdfec5
Loading...
Searching...
No Matches
file.c
Go to the documentation of this file.
1/*!
2 \file diglib/file.c
3
4 \brief Vector library - file management (lower level functions)
5
6 Lower level functions for reading/writing/manipulating vectors.
7
8 Note: seems that the time is almost the same for both cases:
9 - reading from file
10 - load whole file to memory and read from memory
11
12 SPDX-FileCopyrightText: 2001-2009 GRASS Development Team
13 SPDX-License-Identifier: GPL-2.0-or-later
14
15 \author Original author CERL, probably Dave Gerdes
16 \author Update to GRASS 5.7 Radim Blazek
17 */
18
19#include <string.h>
20#include <stdio.h>
21#include <unistd.h>
22#include <sys/types.h>
23#include <sys/stat.h>
24#include <grass/vector.h>
25#include <grass/glocale.h>
26
27/*!
28 \brief Get struct gvfile position.
29
30 \param file pointer to struct gvfile structure
31
32 \return current file position
33 */
35{
36 if (file->loaded) /* using memory */
37 return (file->current - file->start);
38
39 return (G_ftell(file->file));
40}
41
42/*!
43 \brief Set struct gvfile position.
44
45 Start positions:
46
47 - SEEK_SET (start)
48 - SEEK_CUR (current position)
49 - SEEK_END (end)
50
51 \param file pointer to struct gvfile structure
52 \param offset offset position
53 \param whence start position
54
55 \return 0 OK
56 \return -1 error
57 */
58int dig_fseek(struct gvfile *file, off_t offset, int whence)
59{
60 if (file->loaded) { /* using memory */
61 switch (whence) {
62 case SEEK_SET:
63 file->current = file->start + offset;
64 break;
65 case SEEK_CUR:
66 file->current += offset;
67 break;
68 case SEEK_END:
69 file->current = file->start + file->size + offset;
70 break;
71 }
72 return 0;
73 }
74
75 G_fseek(file->file, offset, whence);
76
77 return 0;
78}
79
80/*!
81 \brief Rewind file position.
82
83 \param file pointer to gvfile structure
84 */
85void dig_rewind(struct gvfile *file)
86{
87 if (file->loaded) { /* using memory */
88 file->current = file->start;
89 }
90 else {
91 rewind(file->file);
92 }
93}
94
95/*!
96 \brief Flush struct gvfile.
97
98 \param file pointer to struct gvfile structure
99
100 \return 0
101 */
103{
104 if (file->loaded) { /* using memory */
105 return 0;
106 }
107 else {
108 return (fflush(file->file));
109 }
110}
111
112/*!
113 \brief Read struct gvfile.
114
115 \param[out] ptr data buffer
116 \param size buffer size
117 \param nmemb number of members
118 \param file pointer to struct gvfile structure
119
120 \return number of read members
121 */
122size_t dig_fread(void *ptr, size_t size, size_t nmemb, struct gvfile *file)
123{
124 long tot;
125 size_t cnt;
126
127 if (file->loaded) { /* using memory */
128 if (file->current >= file->end) { /* EOF */
129 return 0;
130 }
131 tot = size * nmemb;
132 cnt = nmemb;
133 if (file->current + tot > file->end) {
134 tot = file->end - file->current;
135 cnt = (int)tot / size;
136 }
137 memcpy(ptr, file->current, tot);
138 file->current += tot;
139 return (cnt);
140 }
141 return (fread(ptr, size, nmemb, file->file));
142}
143
144/*!
145 \brief Write struct gvfile.
146
147 \param ptr data buffer
148 \param size buffer size
149 \param nmemb number of members
150 \param[out] file pointer to struct gvfile structure
151
152 \return number of items written
153 */
154size_t dig_fwrite(const void *ptr, size_t size, size_t nmemb,
155 struct gvfile *file)
156{
157 if (file->loaded) { /* using memory */
158 G_fatal_error(_("Writing to file loaded to memory not supported"));
159 }
160
161 return fwrite(ptr, size, nmemb, file->file);
162}
163
164/*!
165 \brief Initialize gvfile structure
166
167 \param[in,out] file pointer to gvfile structure
168 */
170{
171 G_zero(file, sizeof(struct gvfile));
172}
173
174/*!
175 \brief Load opened struct gvfile to memory.
176
177 Warning: position in file is set to the beginning.
178
179 \param file pointer to struct gvfile structure
180
181 \return 1 loaded
182 \return 0 not loaded
183 \return -1 error
184 */
185/* unused, coor file is never loaded to memory. Remove ? MM 2010 */
187{
188 int ret, mode, load;
189 const char *cmode;
190 size_t size;
191 struct stat sbuf;
192
193 G_debug(2, "dig_file_load ()");
194
195 if (file->file == NULL) {
196 G_warning(_("Unable to load file to memory, file not open"));
197 return -1;
198 }
199
200 /* Get mode */
201 mode = GV_MEMORY_NEVER;
202 cmode = G_getenv_nofatal("GV_MEMORY");
203 if (cmode != NULL) {
204 if (G_strcasecmp(cmode, "ALWAYS") == 0)
205 mode = GV_MEMORY_ALWAYS;
206 else if (G_strcasecmp(cmode, "NEVER") == 0)
207 mode = GV_MEMORY_NEVER;
208 else if (G_strcasecmp(cmode, "AUTO") == 0)
209 mode = GV_MEMORY_AUTO;
210 else
211 G_warning(_("Vector memory mode not supported, using 'AUTO'"));
212 }
213 G_debug(2, " requested mode = %d", mode);
214
215 fstat(fileno(file->file), &sbuf);
216 size = sbuf.st_size;
217
218 G_debug(2, " size = %lu", (long unsigned int)size);
219
220 /* Decide if the file should be loaded */
221 /* TODO: I don't know how to get size of free memory (portability) to decide
222 * if load or not for auto */
223 if (mode == GV_MEMORY_AUTO)
224 mode = GV_MEMORY_NEVER;
225 if (mode == GV_MEMORY_ALWAYS)
226 load = 1;
227 else
228 load = 0;
229
230 if (load) {
231 file->start = G_malloc(size);
232 if (file->start == NULL)
233 return -1;
234
235 G_fseek(file->file, 0L, 0);
236 ret = fread(file->start, size, 1,
237 file->file); /* Better to read in smaller portions? */
238 G_fseek(file->file, 0L, 0); /* reset to the beginning */
239
240 if (ret <= 0) {
241 G_free(file->start);
242 return -1;
243 }
244
245 file->alloc = size;
246 file->size = size;
247 file->current = file->start;
248 file->end = file->start + size;
249
250 file->loaded = 1;
251 G_debug(2, " file was loaded to the memory");
252 return 1;
253 }
254 else {
255 G_debug(2, " file was not loaded to the memory");
256 }
257
258 return 0;
259}
260
261/*!
262 \brief Free struct gvfile.
263
264 \param file pointer to struct gvfile structure
265 */
267{
268 if (file->loaded) {
269 G_free(file->start);
270 file->loaded = 0;
271 file->alloc = 0;
272 }
273}
#define NULL
Definition ccmath.h:32
const char * G_getenv_nofatal(const char *)
Get environment variable.
Definition env.c:403
void G_zero(void *, int)
Zero out a buffer, buf, of length i.
Definition gis/zero.c:21
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:145
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
void G_fseek(FILE *, off_t, int)
Change the file position of the stream.
Definition gis/seek.c:48
off_t G_ftell(FILE *)
Get the current file position of the stream.
Definition gis/seek.c:27
int int G_strcasecmp(const char *, const char *)
String compare ignoring case (upper or lower)
Definition strings.c:45
int G_debug(int, const char *,...) __attribute__((format(printf
#define GV_MEMORY_NEVER
#define GV_MEMORY_AUTO
#define GV_MEMORY_ALWAYS
Memory mode.
int dig_file_load(struct gvfile *file)
Load opened struct gvfile to memory.
Definition file.c:186
size_t dig_fwrite(const void *ptr, size_t size, size_t nmemb, struct gvfile *file)
Write struct gvfile.
Definition file.c:154
size_t dig_fread(void *ptr, size_t size, size_t nmemb, struct gvfile *file)
Read struct gvfile.
Definition file.c:122
off_t dig_ftell(struct gvfile *file)
Get struct gvfile position.
Definition file.c:34
void dig_rewind(struct gvfile *file)
Rewind file position.
Definition file.c:85
int dig_fseek(struct gvfile *file, off_t offset, int whence)
Set struct gvfile position.
Definition file.c:58
int dig_fflush(struct gvfile *file)
Flush struct gvfile.
Definition file.c:102
void dig_file_init(struct gvfile *file)
Initialize gvfile structure.
Definition file.c:169
void dig_file_free(struct gvfile *file)
Free struct gvfile.
Definition file.c:266
#define _(str)
Definition glocale.h:10
#define file
File definition.
Definition dig_structs.h:92