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