GRASS GIS 7 Programmer's Manual  7.9.dev(2021)-e5379bbd7
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 */
36 off_t dig_ftell(struct gvfile *file)
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 */
60 int 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 */
87 void 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 */
104 int dig_fflush(struct gvfile * file)
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  */
124 size_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  */
156 size_t dig_fwrite(const void *ptr, size_t size, size_t nmemb, struct gvfile *file)
157 {
158  if (file->loaded) { /* using memory */
159  G_fatal_error(_("Writing to file loaded to memory not supported"));
160  }
161 
162  return fwrite(ptr, size, nmemb, file->file);
163 }
164 
165 /*!
166  \brief Initialize gvfile strcuture
167 
168  \param[in,out] file pointer to gvfile structure
169 */
170 void dig_file_init(struct gvfile *file)
171 {
172  G_zero(file, sizeof(struct gvfile));
173 }
174 
175 /*!
176  \brief Load opened struct gvfile to memory.
177 
178  Warning: position in file is set to the beginning.
179 
180  \param file pointer to struct gvfile structure
181 
182  \return 1 loaded
183  \return 0 not loaded
184  \return -1 error
185 */
186 /* unused, coor file is never loaded to memory. Remove ? MM 2010 */
187 int dig_file_load(struct gvfile * file)
188 {
189  int ret, mode, load;
190  const char *cmode;
191  size_t size;
192  struct stat sbuf;
193 
194  G_debug(2, "dig_file_load ()");
195 
196  if (file->file == NULL) {
197  G_warning(_("Unable to load file to memory, file not open"));
198  return -1;
199  }
200 
201  /* Get mode */
202  mode = GV_MEMORY_NEVER;
203  cmode = G_getenv_nofatal("GV_MEMORY");
204  if (cmode != NULL) {
205  if (G_strcasecmp(cmode, "ALWAYS") == 0)
206  mode = GV_MEMORY_ALWAYS;
207  else if (G_strcasecmp(cmode, "NEVER") == 0)
208  mode = GV_MEMORY_NEVER;
209  else if (G_strcasecmp(cmode, "AUTO") == 0)
210  mode = GV_MEMORY_AUTO;
211  else
212  G_warning(_("Vector memory mode not supported, using 'AUTO'"));
213  }
214  G_debug(2, " requested mode = %d", mode);
215 
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 if load or not for auto */
224  if (mode == GV_MEMORY_AUTO)
225  mode = GV_MEMORY_NEVER;
226  if (mode == GV_MEMORY_ALWAYS)
227  load = 1;
228  else
229  load = 0;
230 
231  if (load) {
232  file->start = G_malloc(size);
233  if (file->start == NULL)
234  return -1;
235 
236  G_fseek(file->file, 0L, 0);
237  ret = fread(file->start, size, 1, 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 */
266 void dig_file_free(struct gvfile * file)
267 {
268  if (file->loaded) {
269  G_free(file->start);
270  file->loaded = 0;
271  file->alloc = 0;
272  }
273 }
size_t dig_fread(void *ptr, size_t size, size_t nmemb, struct gvfile *file)
Read struct gvfile.
Definition: file.c:124
#define G_malloc(n)
Definition: defs/gis.h:112
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
#define GV_MEMORY_NEVER
Definition: dig_defines.h:140
void dig_file_init(struct gvfile *file)
Initialize gvfile strcuture.
Definition: file.c:170
char * current
Current position set by dig_seek()
Definition: dig_structs.h:109
char * end
End of file in the memory (pointer to first byte after)
Definition: dig_structs.h:113
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:149
off_t alloc
Allocated space.
Definition: dig_structs.h:121
#define NULL
Definition: ccmath.h:32
int dig_file_load(struct gvfile *file)
Load opened struct gvfile to memory.
Definition: file.c:187
#define GV_MEMORY_ALWAYS
Memory mode.
Definition: dig_defines.h:139
void dig_rewind(struct gvfile *file)
Rewind file position.
Definition: file.c:87
int loaded
Is file loaded?
Definition: dig_structs.h:128
int int G_strcasecmp(const char *, const char *)
String compare ignoring case (upper or lower)
Definition: strings.c:47
int dig_fseek(struct gvfile *file, off_t offset, int whence)
Set struct gvfile position.
Definition: file.c:60
void G_fseek(FILE *, off_t, int)
Change the file position of the stream.
Definition: gis/seek.c:50
off_t size
Size of the file loaded to memory.
Definition: dig_structs.h:117
off_t G_ftell(FILE *)
Get the current file position of the stream.
Definition: gis/seek.c:29
off_t dig_ftell(struct gvfile *file)
Get struct gvfile position.
Definition: file.c:36
FILE * file
File descriptor.
Definition: dig_structs.h:101
int dig_fflush(struct gvfile *file)
Flush struct gvfile.
Definition: file.c:104
void dig_file_free(struct gvfile *file)
Free struct gvfile.
Definition: file.c:266
void G_zero(void *, int)
Zero out a buffer, buf, of length i.
Definition: gis/zero.c:23
void G_warning(const char *,...) __attribute__((format(printf
#define file
#define _(str)
Definition: glocale.h:10
char * start
Pointer to beginning of the file in the memory.
Definition: dig_structs.h:105
const char * G_getenv_nofatal(const char *)
Get environment variable.
Definition: env.c:383
#define GV_MEMORY_AUTO
Definition: dig_defines.h:141
File definition.
Definition: dig_structs.h:96
size_t dig_fwrite(const void *ptr, size_t size, size_t nmemb, struct gvfile *file)
Write struct gvfile.
Definition: file.c:156
int G_debug(int, const char *,...) __attribute__((format(printf