FastLED 3.10.8
Loading...
Searching...
No Matches
file_io.h
Go to the documentation of this file.
1#pragma once
2
3#include "fl/stl/noexcept.h"
4
5#include "fl/stl/cstddef.h" // fl::size_t
6#include "fl/stl/int.h"
7#include "platforms/is_platform.h"
8#include "fl/stl/cerrno.h" // For fl::get_errno()
9#include "fl/stl/cstring.h" // For fl::strerror()
10
11#ifdef FASTLED_TESTING
12// IWYU pragma: begin_keep
13#include <cstdio>
14// IWYU pragma: end_keep // For ::FILE*, ::fopen, ::fclose, etc.
15#endif
16
17// Platform-agnostic file I/O abstraction
18// Provides fl::FILE* and fl::fopen/fclose/etc. functions that platforms can implement
19//
20// Supported platforms:
21// - POSIX/Testing (FASTLED_TESTING): Maps to standard FILE* and libc functions
22// - Embedded (future): Can map to LittleFS, SPIFFS, SD card APIs, etc.
23
24namespace fl {
25
26// ============================================================================
27// Opaque File Handle Type
28// ============================================================================
29
30// Forward declare the platform-specific file handle structure
31// Each platform defines this in their implementation
32struct FILE_impl;
33
34// Opaque file handle pointer (like standard FILE*)
36
37// ============================================================================
38// File I/O Constants
39// ============================================================================
40
41namespace io {
42 // Seek origin constants (match SEEK_SET, SEEK_CUR, SEEK_END)
43 constexpr int seek_set = 0;
44 constexpr int seek_cur = 1;
45 constexpr int seek_end = 2;
46
47 // Error code for "bad file descriptor" (matches EBADF = 9 on POSIX)
48 constexpr int err_bad_file = 9;
49}
50
51// ============================================================================
52// Platform-Agnostic File I/O Functions
53// ============================================================================
54// These functions provide a consistent interface across all platforms.
55// Each platform implements these in their own way.
56
61FILE* fopen(const char* path, const char* mode) FL_NO_EXCEPT;
62
66int fclose(FILE* file) FL_NO_EXCEPT;
67
74fl::size_t fread(void* buffer, fl::size_t size, fl::size_t count, FILE* file) FL_NO_EXCEPT;
75
82fl::size_t fwrite(const void* data, fl::size_t size, fl::size_t count, FILE* file) FL_NO_EXCEPT;
83
87long ftell(FILE* file) FL_NO_EXCEPT;
88
94int fseek(FILE* file, long offset, int origin) FL_NO_EXCEPT;
95
99int fflush(FILE* file) FL_NO_EXCEPT;
100
101// On some platforms (e.g., AVR), feof, ferror, and clearerr are macros
102// Save them only if they exist, undefine temporarily to declare our functions
103// Only needed on platforms where they are actually macros (AVR)
104#ifdef FL_IS_AVR
105#ifdef feof
106#define FL_MACRO_NEEDS_RESTORE_feof
107#pragma push_macro("feof")
108#undef feof
109#endif
110#ifdef ferror
111#define FL_MACRO_NEEDS_RESTORE_ferror
112#pragma push_macro("ferror")
113#undef ferror
114#endif
115#ifdef clearerr
116#define FL_MACRO_NEEDS_RESTORE_clearerr
117#pragma push_macro("clearerr")
118#undef clearerr
119#endif
120#endif // FL_IS_AVR
121
125#ifdef FL_IS_AVR
126int (feof)(FILE* file) FL_NO_EXCEPT;
127#else
128int feof(FILE* file) FL_NO_EXCEPT;
129#endif
130
134#ifdef FL_IS_AVR
135int (ferror)(FILE* file) FL_NO_EXCEPT;
136#else
137int ferror(FILE* file) FL_NO_EXCEPT;
138#endif
139
142#ifdef FL_IS_AVR
143void (clearerr)(FILE* file) FL_NO_EXCEPT;
144#else
145void clearerr(FILE* file) FL_NO_EXCEPT;
146#endif
147
148// Note: On AVR, we use parentheses around function names to prevent macro expansion
149// and we do NOT restore the macros (see comment at end of file for rationale)
150
151// Note: fl::get_errno() and fl::strerror() are already defined in fl/stl/cerrno.h and fl/stl/cstring.h
152// We don't redeclare them here to avoid conflicts
153
154} // namespace fl
155
156// ============================================================================
157// Platform-Specific Implementations
158// ============================================================================
159
160#ifdef FASTLED_TESTING
161// POSIX/Testing platform: Use standard C FILE* and libc functions
162
163namespace fl {
164
165// On POSIX platforms, fl::FILE is just the standard FILE
166struct FILE_impl : public ::FILE {};
167
168// Map fl:: functions to standard libc functions
169// Note: static_cast is safe here because FILE_impl inherits from ::FILE
170// This is a platform abstraction layer that wraps the POSIX FILE* API
171inline FILE* fopen(const char* path, const char* mode) FL_NO_EXCEPT {
172 return static_cast<FILE*>(::fopen(path, mode));
173}
174
175inline int fclose(FILE* file) FL_NO_EXCEPT {
176 return ::fclose(static_cast<::FILE*>(file));
177}
178
179inline fl::size_t fread(void* buffer, fl::size_t size, fl::size_t count, FILE* file) FL_NO_EXCEPT {
180 return ::fread(buffer, size, count, static_cast<::FILE*>(file));
181}
182
183inline fl::size_t fwrite(const void* data, fl::size_t size, fl::size_t count, FILE* file) FL_NO_EXCEPT {
184 return ::fwrite(data, size, count, static_cast<::FILE*>(file));
185}
186
187inline long ftell(FILE* file) FL_NO_EXCEPT {
188 return ::ftell(static_cast<::FILE*>(file));
189}
190
191inline int fseek(FILE* file, long offset, int origin) FL_NO_EXCEPT {
192 return ::fseek(static_cast<::FILE*>(file), offset, origin);
193}
194
195inline int fflush(FILE* file) FL_NO_EXCEPT {
196 return ::fflush(static_cast<::FILE*>(file));
197}
198
199#ifdef FL_IS_AVR
200inline int (feof)(FILE* file) FL_NO_EXCEPT {
201 return ::feof(static_cast<::FILE*>(file));
202}
203#else
204inline int feof(FILE* file) FL_NO_EXCEPT {
205 return ::feof(static_cast<::FILE*>(file));
206}
207#endif
208
209#ifdef FL_IS_AVR
210inline int (ferror)(FILE* file) FL_NO_EXCEPT {
211 return ::ferror(static_cast<::FILE*>(file));
212}
213#else
214inline int ferror(FILE* file) FL_NO_EXCEPT {
215 return ::ferror(static_cast<::FILE*>(file));
216}
217#endif
218
219#ifdef FL_IS_AVR
220inline void (clearerr)(FILE* file) FL_NO_EXCEPT {
221 ::clearerr(static_cast<::FILE*>(file));
222}
223#else
224inline void clearerr(FILE* file) FL_NO_EXCEPT {
225 ::clearerr(static_cast<::FILE*>(file));
226}
227#endif
228
229// Note: fl::get_errno() and fl::strerror() are defined in fl/stl/cerrno.h and fl/stl/cstring.h
230// No implementation needed here - those files provide them
231
232} // namespace fl
233
234#else // !FASTLED_TESTING
235
236// ============================================================================
237// Embedded Platform (No File System)
238// ============================================================================
239// Provides no-op implementations that fail gracefully
240
241namespace fl {
242
243// Minimal stub structure for embedded platforms
244struct FILE_impl {
245 int dummy; // Placeholder to make it a valid type
246};
247
248// No-op implementations
249inline FILE* fopen(const char* /*path*/, const char* /*mode*/) FL_NO_EXCEPT {
250 return nullptr;
251}
252
253inline int fclose(FILE* /*file*/) FL_NO_EXCEPT {
254 return -1;
255}
256
257inline fl::size_t fread(void* /*buffer*/, fl::size_t /*size*/, fl::size_t /*count*/, FILE* /*file*/) FL_NO_EXCEPT {
258 return 0;
259}
260
261inline fl::size_t fwrite(const void* /*data*/, fl::size_t /*size*/, fl::size_t /*count*/, FILE* /*file*/) FL_NO_EXCEPT {
262 return 0;
263}
264
265inline long ftell(FILE* /*file*/) FL_NO_EXCEPT {
266 return -1;
267}
268
269inline int fseek(FILE* /*file*/, long /*offset*/, int /*origin*/) FL_NO_EXCEPT {
270 return -1;
271}
272
273inline int fflush(FILE* /*file*/) FL_NO_EXCEPT {
274 return -1;
275}
276
277#ifdef FL_IS_AVR
278inline int (feof)(FILE* /*file*/) FL_NO_EXCEPT {
279 return 0;
280}
281#else
282inline int feof(FILE* /*file*/) FL_NO_EXCEPT {
283 return 0;
284}
285#endif
286
287#ifdef FL_IS_AVR
288inline int (ferror)(FILE* /*file*/) FL_NO_EXCEPT {
289 return 1;
290}
291#else
292inline int ferror(FILE* /*file*/) FL_NO_EXCEPT {
293 return 1;
294}
295#endif
296
297#ifdef FL_IS_AVR
298inline void (clearerr)(FILE* /*file*/) FL_NO_EXCEPT {
299}
300#else
301inline void clearerr(FILE* /*file*/) FL_NO_EXCEPT {
302}
303#endif
304
305// Note: fl::get_errno() and fl::strerror() are defined in fl/stl/cerrno.h and fl/stl/cstring.h
306// We use those implementations instead of defining our own here
307
308} // namespace fl
309
310#endif // FASTLED_TESTING
311
312// DO NOT restore the feof/ferror/clearerr macros on AVR
313// Rationale: Even with parentheses in function declarations, restoring these macros causes
314// them to expand at call sites like `fl::feof(file)`, which breaks compilation.
315// Macro expansion happens before namespace resolution, so `fl::feof(x)` becomes
316// `fl::((x)->flags & _FEOF)` on AVR, which is invalid syntax.
317//
318// Solution: We only undefine these macros on AVR (where they exist as macros), and we
319// use parentheses around function names `(feof)`, `(ferror)`, `(clearerr)` in declarations
320// and definitions to prevent macro expansion. We do NOT restore the macros.
321//
322// On non-AVR platforms where these are regular functions (not macros), we use normal
323// function syntax without parentheses.
fl::UISlider offset("Offset", 0.0f, 0.0f, 1.0f, 0.01f)
__SIZE_TYPE__ size_t
Definition s16x16x4.h:16
constexpr int seek_cur
Definition file_io.h:44
constexpr int err_bad_file
Definition file_io.h:48
constexpr int seek_set
Definition file_io.h:43
constexpr int seek_end
Definition file_io.h:45
u8 u8 fract8 blur_amount FL_NO_EXCEPT
Definition blur.h:186
int ferror(FILE *file) FL_NO_EXCEPT
Check for file error.
Definition file_io.h:292
int fseek(FILE *file, long offset, int origin) FL_NO_EXCEPT
Set file position.
Definition file_io.h:269
long ftell(FILE *file) FL_NO_EXCEPT
Get current file position.
Definition file_io.h:265
int feof(FILE *file) FL_NO_EXCEPT
Check for end-of-file.
Definition file_io.h:282
FILE_impl FILE
Definition file_io.h:35
FILE * fopen(const char *path, const char *mode) FL_NO_EXCEPT
Open a file.
Definition file_io.h:249
int fclose(FILE *file) FL_NO_EXCEPT
Close a file.
Definition file_io.h:253
int fflush(FILE *file) FL_NO_EXCEPT
Flush file buffers.
Definition file_io.h:273
fl::size_t fread(void *buffer, fl::size_t size, fl::size_t count, FILE *file) FL_NO_EXCEPT
Read from file.
Definition file_io.h:257
fl::size_t fwrite(const void *data, fl::size_t size, fl::size_t count, FILE *file) FL_NO_EXCEPT
Write to file.
Definition file_io.h:261
void clearerr(FILE *file) FL_NO_EXCEPT
Clear file error indicators.
Definition file_io.h:301
Base definition for an LED controller.
Definition crgb.hpp:179
#define FL_NO_EXCEPT