1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
|
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.io/license.html
*/
/**
* @file src/gfile/gfile.h
* @brief GFILE - File IO Routines header file.
*
* @addtogroup GFILE
*
* @brief Module which contains operating system independent file I/O.
*
* @{
*/
#ifndef _GFILE_H
#define _GFILE_H
#include "../../gfx.h"
#if GFX_USE_GFILE || defined(__DOXYGEN__)
/*===========================================================================*/
/* Type definitions */
/*===========================================================================*/
/**
* @brief A file pointer
*/
typedef struct GFILE GFILE;
typedef struct gfileList gfileList;
extern GFILE *gfileStdIn;
extern GFILE *gfileStdErr;
extern GFILE *gfileStdOut;
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
/**
* @brief Check if file exists
*
* @param[in] fname The file name
*
* @return gTrue if file exists, gFalse otherwise
*
* @api
*/
gBool gfileExists(const char *fname);
/**
* @brief Delete file
*
* @param[in] fname The file name
*
* @return gTrue on success, gFalse otherwise
*
* @api
*/
gBool gfileDelete(const char *fname);
/**
* @brief Get the size of a file
* @note Please use @p gfileGetSize() if the file is opened
*
* @param[in] fname The file name
*
* @return File size on success, (gFileSize)-1 on error
*
* @api
*/
gFileSize gfileGetFilesize(const char *fname);
/**
* @brief Rename file
*
* @param[in] oldname The current file name
* @param[in] newname The new name of the file
*
* @return gTrue on success, gFalse otherwise
*
* @api
*/
gBool gfileRename(const char *oldname, const char *newname);
/**
* @brief Open file
* @details A file must be opened before it can be accessed
* @details The resulting GFILE will be used for all functions that access the file.
*
* @param[in] fname The file name
* @param[in] mode The mode.
*
* @return Valid GFILE on success, 0 otherwise
*
* @note The modes follow the c library fopen() standard.
* The valid modes are:
* <ul><li>r - Open for read, the file must exist</li>
* <li>w - Open for write, the file is truncated if it exists</li>
* <li>wx - Open for write, the file must not exist</li>
* <li>a - Open for append, the file is truncated if it exists</li>
* <li>ax - Open for append, the file must not exists</li>
* </ul>
* The following flags can also be added to the above modes:<br/>
* <ul><li>+ - Open for both read and write</li>
* <li>b - Open as a binary file rather than a text file</li>
* </ul>
* @note Not all file-systems support all modes. For example, write
* is not available with the ROM file-system. Similarly few platforms
* distinguish between binary and text files.
* @note Even though binary vs. text is relevant only for a small number of platforms
* the "b" flag should always be specified for binary files such as images.
* This ensures portability to other platforms. The extra flag will be ignored
* on platforms where it is not relevant.
*
* @api
*/
GFILE * gfileOpen(const char *fname, const char *mode);
/**
* @brief Close file
* @details Closes a file after is has been opened using @p gfileOpen()
*
* @param[in] f The file
*
* @api
*/
void gfileClose(GFILE *f);
/**
* @brief Read from file
* @details Reads a given amount of bytes from the file
* @details The read/write cursor will not be reset when calling this function
*
* @param[in] f The file
* @param[out] buf The buffer in which to save the content that has been read from the file
* @param[in] len Amount of bytes to read
*
* @return Amount of bytes read
*
* @api
*/
gMemSize gfileRead(GFILE *f, void *buf, gMemSize len);
/**
* @brief Write to file
* @details Write a given amount of bytes to the file
* @details The read/write cursor will not be reset when calling this function
*
* @param[in] f The file
* @param[in] buf The buffer which contains the content that will be written to the file
* @param[in] len Amount of bytes to write
*
* @return Amount of bytes written
*
* @api
*/
gMemSize gfileWrite(GFILE *f, const void *buf, gMemSize len);
/**
* @brief Get the current position of the read/write cursor
*
* @param[in] f The file
*
* @return The current position in the file
*
* @api
*/
gFileSize gfileGetPos(GFILE *f);
/**
* @brief Set the position of the read/write cursor
*
* @param[in] f The file
* @param[in] pos The position to which the cursor will be set
*
* @return gTrue on success, gFalse otherwise
*
* @api
*/
gBool gfileSetPos(GFILE *f, gFileSize pos);
/**
* @brief Get the size of file
* @note Please use @p gfileGetFilesize() if the file is not opened
*
* @param[in] f The file
*
* @return The size of the file
*
* @api
*/
gFileSize gfileGetSize(GFILE *f);
/**
* @brief Check for EOF
* @details Checks if the cursor is at the end of the file
*
* @param[in] f The file
*
* @return gTrue if EOF, gFalse otherwise
*
* @api
*/
gBool gfileEOF(GFILE *f);
/**
* @brief Mount a logical drive (aka partition)
*
* @details Not supported by every file system
* @details Currently just one drive at one is supported.
*
* @param[in] fs The file system (F for FatFS)
* @param[in] drive The logical drive prefix
*
* @return gTrue on success, gFalse otherwise
*
* @api
*/
gBool gfileMount(char fs, const char *drive);
/**
* @brief Unmount a logical drive (aka partition)
*
* @details Does have no effect if @p gfileMount() as been called before hand
*
* @param[in] fs The file system (F for FatFS)
* @param[in] drive The logical drive prefix
*
* @return gTrue on success, gFalse otherwise
*
* @api
*/
gBool gfileUnmount(char fs, const char *drive);
/**
* @brief Syncs the file object (flushes the buffer)
*
* @details Not supported by every file system
*
* @param[in] f The file
*
* @return gTrue on success, gFalse otherwise
*
* @api
*/
gBool gfileSync(GFILE *f);
#if GFILE_NEED_FILELISTS || defined(__DOXYGEN__)
/**
* @brief Open a file list
*
* @param[in] fs The file system (F for FatFS)
* @param[in] path Path information to pass to the file system
* @param[in] dirs Pass gTrue to get directories only, gFalse to get files only
*
* @return A pointer to a file list on success, NULL otherwise
*
* @note The path parameter is handled in a file-system specific way. It could be
* treated as a directory name, it may be treated as a file pattern, or it
* may be ignored. Passing NULL will always return the full list of files
* in at least the top level directory.
* @note For file systems that do not support directories, passing gTrue for dirs
* will return an error.
* @note You must call @p gfileCloseFileList() when you have finished with the
* file list in order to free resources.
*
* @api
*/
gfileList *gfileOpenFileList(char fs, const char *path, gBool dirs);
/**
* @brief Get the next file in a file list.
*
* @param[in] pfl Pointer to a file list returned by @p gfileOpenFileList()
*
* @return A pointer to a file (or directory) name. Returns NULL if there are no more.
*
* @note The file name may contain the full directory path or may not depending
* on how the file system treats directories.
* @note The returned buffer may be destroyed by the next call to any of
* @p gfileOpenFileList(), @p gfileReadFileList() or @p gfileCloseFileList().
* Do not use this pointer after one of those calls.
*
* @api
*/
const char *gfileReadFileList(gfileList *pfl);
/**
* @brief Close a file list.
*
* @param[in] pfl Pointer to a file list returned by @p gfileOpenFileList()
*
* @api
*/
void gfileCloseFileList(gfileList *pfl);
#endif
#if (GFILE_NEED_CHIBIOSFS && GFX_USE_OS_CHIBIOS) || defined(__DOXYGEN__)
/**
* @brief Open file from a ChibiOS FileStream
*
* @param[in] FileStreamPtr The BaseFileStream (ChibiOS V2) or FileStream (ChibiOS V3) to open as a GFILE
* @param[in] mode The mode.
*
* @return Valid GFILE on success, 0 otherwise
*
* @note The modes are the same modes as in @p gfileOpen(). The
* open mode is NOT compared against the FileStream capabilities.
* @note Supported operations are: read, write, getpos, setpos, eof and getsize
*
* @api
*/
GFILE * gfileOpenChibiOSFileStream(void *FileStreamPtr, const char *mode);
#define gfileOpenBaseFileStream(f,m) gfileOpenChibiOSFileStream(f,m)
#endif
#if GFILE_NEED_MEMFS || defined(__DOXYGEN__)
/**
* @brief Open file from a memory pointer
*
* @param[in] memptr The pointer to the memory
* @param[in] mode The mode.
*
* @return Valid GFILE on success, 0 otherwise
*
* @note The modes are the same modes as in @p gfileOpen(). Note there is
* no concept of file-size. Be careful not to overwrite other memory or
* to read from inaccessible sections of memory.
* @note Supported operations are: read, write, getpos, setpos
*
* @api
*/
GFILE * gfileOpenMemory(void *memptr, const char *mode);
#endif
#if GFILE_NEED_STRINGS || defined(__DOXYGEN__)
/**
* @brief Open file from a null terminated C string
*
* @param[in] str The pointer to the string or string buffer
* @param[in] mode The mode
*
* @return Valid GFILE on success, 0 otherwise
*
* @note The modes are the same modes as in @p gfileOpen(). Note there is
* no concept of file-size. Be careful not to overwrite other memory or
* to read from inaccessible sections of memory.
* @note Reading will return EOF when the NULL character is reached.
* @note Writing will always place a NULL in the next character effectively terminating the
* string at the character just written.
* @note Supported operations are: read, write, append, getpos, setpos
* @note Be careful with setpos and getpos. They do not check for the end of the string.
* @note Reading and Writing will read/write a maximum of one character at a time.
*
* @api
*/
GFILE * gfileOpenString(char *str, const char *mode);
#endif
#if GFILE_NEED_PRINTG || defined(__DOXYGEN__)
#include <stdarg.h>
int vfnprintg(GFILE *f, int maxlen, const char *fmt, va_list arg);
int fnprintg(GFILE *f, int maxlen, const char *fmt, ...);
#define vfprintg(f,m,a) vfnprintg(f,0,m,a)
#define fprintg(f,m,...) fnprintg(f,0,m,__VA_ARGS__)
#define vprintg(m,a) vfnprintg(gfileStdOut,0,m,a)
#define printg(m,...) fnprintg(gfileStdOut,0,m,__VA_ARGS__)
#if GFILE_NEED_STRINGS
int vsnprintg(char *buf, int maxlen, const char *fmt, va_list arg);
int snprintg(char *buf, int maxlen, const char *fmt, ...);
#define vsprintg(s,m,a) vsnprintg(s,0,m,a)
#define sprintg(s,m,...) snprintg(s,0,m,__VA_ARGS__)
#endif
#endif
#if GFILE_NEED_SCANG || defined(__DOXYGEN__)
#include <stdarg.h>
int vfscang(GFILE *f, const char *fmt, va_list arg);
int fscang(GFILE *f, const char *fmt, ...);
#define vscang(f,a) vfscang(gfileStdIn,f,a)
#define scang(f,...) fscang(gfileStdIn,f,__VA_ARGS__)
#if GFILE_NEED_STRINGS
int vsscang(const char *buf, const char *fmt, va_list arg);
int sscang(const char *buf, const char *fmt, ...);
#endif
#endif
#if GFILE_NEED_STDIO && !defined(GFILE_NEED_STDIO_MUST_BE_OFF)
// Needed routines and definitions
size_t gstdioRead(void * ptr, size_t size, size_t count, GFILE *f);
size_t gstdioWrite(const void * ptr, size_t size, size_t count, GFILE *f);
int gstdioGetpos(GFILE *f, long *pos);
int gstdioSeek(GFILE *f, size_t offset, int origin);
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
// Stdio emulation
#define stdin gfileStdIn
#define stdout gfileStdOut
#define stderr gfileStdErr
#define FOPEN_MAX GFILE_MAX_GFILES
#define TMP_MAX GFILE_MAX_GFILES
#define FILENAME_MAX 256 // Use a relatively small number for an embedded platform
#define L_tmpnam FILENAME_MAX
#define P_tmpdir "/tmp/"
#define FILE GFILE
#define fopen(n,m) gfileOpen(n,m)
#define fclose(f) gfileClose(f)
#define fread(p,sz,cnt,f) gstdioRead(p,sz,cnt,f)
#define fwrite(p,sz,cnt,f) gstdioWrite(p,sz,cnt,f)
#define fseek(f,ofs,org) gstdioSeek(f,ofs,org)
#define remove(n) (!gfileDelete(n))
#define rename(o,n) (!gfileRename(o,n))
#define fflush(f) (0)
#define ftell(f) gfileGetPos(f)
#define fpos_t gFileSize
#define fgetpos(f,pos) gstdioGetpos(f,pos)
#define fsetpos(f, pos) (!gfileSetPos(f, *pos))
#define rewind(f) gfileSetPos(f, 0);
#define feof(f) gfileEOF(f)
#define vfprintf(f,m,a) vfnprintg(f,0,m,a)
#define fprintf(f,m,...) fnprintg(f,0,m,__VA_ARGS__)
#define vprintf(m,a) vfnprintg(gfileStdOut,0,m,a)
#define printf(m,...) fnprintg(gfileStdOut,0,m,__VA_ARGS__)
#define vsnprintf(s,n,m,a) vsnprintg(s,n,m,a)
#define snprintf(s,n,m,...) snprintg(s,n,m,__VA_ARGS__)
#define vsprintf(s,m,a) vsnprintg(s,0,m,a)
#define sprintf(s,m,...) snprintg(s,0,m,__VA_ARGS__)
//TODO
//void clearerr ( FILE * stream );
//int ferror ( FILE * stream );
//FILE * tmpfile ( void ); // Auto-deleting
//char * tmpnam ( char * str );
//char * mktemp (char *template);
//FILE * freopen ( const char * filename, const char * mode, FILE * stream );
//setbuf
//setvbuf
//fflush
//fgetc
//fgets
//fputc
//fputs
//getc
//getchar
//puts
//ungetc
//void perror (const char * str);
#endif
#endif /* GFX_USE_GFILE */
#endif /* _GFILE_H */
/** @} */
|