FastLED 3.9.15
Loading...
Searching...
No Matches
fstream.h
Go to the documentation of this file.
1#pragma once
2
3#include "fl/stl/int.h"
4#include "fl/stl/bit_cast.h"
6#include "fl/stl/shared_ptr.h"
7
8// Platform-aware file stream implementation (analogous to std::ifstream / std::ofstream)
9// - Host/Testing platforms (FASTLED_TESTING): Full file I/O implementation via posix_filebuf
10// - Embedded platforms (ESP32, Uno, etc.): No-op stubs (no file system support)
11//
12// These stream classes accept any filebuf subclass via shared_ptr,
13// enabling polymorphic dispatch to different backends (POSIX, SD card, WASM, memory).
14
15#ifdef FASTLED_TESTING
16#include "fl/stl/cstring.h" // For fl::strerror
17#include "fl/stl/noexcept.h"
18#endif
19
20namespace fl {
21
22// Shared pointer to the polymorphic backend
23using filebuf_ptr = fl::shared_ptr<filebuf>;
24
25// File stream mode flags and seek directions
26namespace ios {
27 // Mode flags (bitmask)
28 using openmode = unsigned int;
29 static constexpr openmode binary = 0x01; // Binary mode
30 static constexpr openmode ate = 0x02; // Seek to end after opening
31 static constexpr openmode in = 0x04; // Open for reading
32 static constexpr openmode out = 0x08; // Open for writing
33 static constexpr openmode trunc = 0x10; // Truncate file if exists
34 static constexpr openmode app = 0x20; // Append mode
35
36 // Seek direction
37 enum class seekdir {
38 beg = 0, // Beginning of file
39 cur = 1, // Current position
40 end = 2 // End of file
41 };
42}
43
44// ============================================================================
45// Input file stream (analogous to std::ifstream)
46// ============================================================================
47
48class ifstream {
49private:
52 bool mGood;
53 bool mEof;
54 bool mFail;
55
56 void updateState() {
57 if (mHandle && mHandle->is_open()) {
58 mEof = mHandle->is_eof();
59 mFail = mHandle->has_error();
60 mGood = !mEof && !mFail;
61 } else {
62 mGood = false;
63 mEof = false;
64 mFail = true;
65 }
66 }
67
68public:
69 ifstream() FL_NOEXCEPT : mLastRead(0), mGood(false), mEof(false), mFail(true) {}
70
71 explicit ifstream(const char* path, ios::openmode mode = ios::in);
72
73 explicit ifstream(filebuf_ptr handle);
74
76
77 // Non-copyable
78 ifstream(const ifstream&) FL_NOEXCEPT = delete;
79 ifstream& operator=(const ifstream&) = delete;
80
81 // Moveable
83 : mHandle(other.mHandle), mLastRead(other.mLastRead),
84 mGood(other.mGood), mEof(other.mEof), mFail(other.mFail) {
85 other.mHandle.reset();
86 other.mLastRead = 0;
87 other.mGood = false;
88 other.mEof = false;
89 other.mFail = true;
90 }
91
93 if (this != &other) {
94 close();
95 mHandle = other.mHandle;
96 mLastRead = other.mLastRead;
97 mGood = other.mGood;
98 mEof = other.mEof;
99 mFail = other.mFail;
100 other.mHandle.reset();
101 other.mLastRead = 0;
102 other.mGood = false;
103 other.mEof = false;
104 other.mFail = true;
105 }
106 return *this;
107 }
108
109 void open(const char* path, ios::openmode mode = ios::in);
110
111 bool is_open() const {
112 return mHandle && mHandle->is_open();
113 }
114
115 void close();
116
117 ifstream& read(char* buffer, fl::size_t count);
118
120 return mLastRead;
121 }
122
124
126
127 bool good() const { return mGood; }
128 bool eof() const { return mEof; }
129 bool fail() const { return mFail; }
130
131 // Get last error code (0 if no error)
132 int error() const;
133
134 // Get human-readable error message
135 const char* error_message() const;
136
137 // Manually clear error state (for retry scenarios)
138 void clear_error();
139
140 // --- Enriched API (forwarded from filebuf) ---
141
142 // Access the underlying buffer (like std::ifstream::rdbuf())
143 filebuf_ptr rdbuf() const { return mHandle; }
144
145 // Total file size in bytes
146 fl::size_t size() const {
147 return mHandle ? mHandle->size() : 0;
148 }
149
150 // Bytes remaining from current position to end
152 return mHandle ? mHandle->bytes_left() : 0;
153 }
154
155 // File path (or description for non-file buffers)
156 const char* path() const {
157 return mHandle ? mHandle->path() : "";
158 }
159
160 // Check if data is available for reading
161 bool available() const {
162 return mHandle ? mHandle->available() : false;
163 }
164
165 // Check if at least n bytes are available
166 bool available(fl::size_t n) const {
167 return mHandle ? mHandle->available(n) : false;
168 }
169
170 // Convenience: read into u8 buffer
173 return mLastRead;
174 }
175
176 // Convenience: read into u8 span
178 return read(dst.data(), dst.size());
179 }
180
181 // Convenience: read RGB8 pixels (3 bytes per pixel)
183 read(fl::reinterpret_cast_<char*>(dst.data()), dst.size() * 3);
184 return mLastRead / 3;
185 }
186
187 // Backward-compat aliases
188 bool valid() const { return is_open(); }
189 fl::size_t pos() const { return mHandle ? mHandle->pos() : 0; }
190 fl::size_t bytesLeft() const { return bytes_left(); }
191 bool seek(fl::size_t p) {
193 return good();
194 }
195 bool seek(fl::size_t p, seek_dir dir) {
198 seekg(p, d);
199 return good();
200 }
201};
202
203// ============================================================================
204// Output file stream (analogous to std::ofstream)
205// ============================================================================
206
207class ofstream {
208private:
210 bool mGood;
211 bool mEof;
212 bool mFail;
214
215 void updateState() {
216 if (mHandle && mHandle->is_open()) {
217 mEof = mHandle->is_eof();
218 mFail = mHandle->has_error() || (mLocalError != 0);
219 mGood = !mEof && !mFail;
220 } else {
221 mGood = false;
222 mEof = false;
223 mFail = true;
224 }
225 }
226
227public:
228 ofstream() FL_NOEXCEPT : mGood(false), mEof(false), mFail(true), mLocalError(0) {}
229
230 explicit ofstream(const char* path, ios::openmode mode = ios::out);
231
232 explicit ofstream(filebuf_ptr handle);
233
235
236 // Non-copyable
237 ofstream(const ofstream&) FL_NOEXCEPT = delete;
238 ofstream& operator=(const ofstream&) = delete;
239
240 // Moveable
242 : mHandle(other.mHandle), mGood(other.mGood), mEof(other.mEof),
243 mFail(other.mFail), mLocalError(other.mLocalError) {
244 other.mHandle.reset();
245 other.mGood = false;
246 other.mEof = false;
247 other.mFail = true;
248 other.mLocalError = 0;
249 }
250
252 if (this != &other) {
253 close();
254 mHandle = other.mHandle;
255 mGood = other.mGood;
256 mEof = other.mEof;
257 mFail = other.mFail;
258 mLocalError = other.mLocalError;
259 other.mHandle.reset();
260 other.mGood = false;
261 other.mEof = false;
262 other.mFail = true;
263 other.mLocalError = 0;
264 }
265 return *this;
266 }
267
268 void open(const char* path, ios::openmode mode = ios::out);
269
270 bool is_open() const {
271 return mHandle && mHandle->is_open();
272 }
273
274 void close();
275
276 ofstream& write(const char* data, fl::size_t count);
277
278 bool good() const { return mGood; }
279 bool eof() const { return mEof; }
280 bool fail() const { return mFail; }
281
282 // Get last error code (0 if no error)
283 int error() const;
284
285 // Get human-readable error message
286 const char* error_message() const;
287
288 // Manually clear error state (for retry scenarios)
289 void clear_error();
290
291 // Access the underlying buffer
292 filebuf_ptr rdbuf() const { return mHandle; }
293};
294
295// ============================================================================
296// Generic file stream (supports both reading and writing)
297// ============================================================================
298
299class fstream {
300private:
303 bool mGood;
304 bool mEof;
305 bool mFail;
307
308 void updateState() {
309 if (mHandle && mHandle->is_open()) {
310 mEof = mHandle->is_eof();
311 mFail = mHandle->has_error() || (mLocalError != 0);
312 mGood = !mEof && !mFail;
313 } else {
314 mGood = false;
315 mEof = false;
316 mFail = true;
317 }
318 }
319
320public:
321 fstream() FL_NOEXCEPT : mLastRead(0), mGood(false), mEof(false), mFail(true), mLocalError(0) {}
322
323 explicit fstream(const char* path, ios::openmode mode = ios::in | ios::out);
324
325 explicit fstream(filebuf_ptr handle);
326
328
329 // Non-copyable
330 fstream(const fstream&) FL_NOEXCEPT = delete;
331 fstream& operator=(const fstream&) = delete;
332
333 // Moveable
335 : mHandle(other.mHandle), mLastRead(other.mLastRead),
336 mGood(other.mGood), mEof(other.mEof), mFail(other.mFail),
337 mLocalError(other.mLocalError) {
338 other.mHandle.reset();
339 other.mLastRead = 0;
340 other.mGood = false;
341 other.mEof = false;
342 other.mFail = true;
343 other.mLocalError = 0;
344 }
345
347 if (this != &other) {
348 close();
349 mHandle = other.mHandle;
350 mLastRead = other.mLastRead;
351 mGood = other.mGood;
352 mEof = other.mEof;
353 mFail = other.mFail;
354 mLocalError = other.mLocalError;
355 other.mHandle.reset();
356 other.mLastRead = 0;
357 other.mGood = false;
358 other.mEof = false;
359 other.mFail = true;
360 other.mLocalError = 0;
361 }
362 return *this;
363 }
364
365 void open(const char* path, ios::openmode mode = ios::in | ios::out);
366
367 bool is_open() const {
368 return mHandle && mHandle->is_open();
369 }
370
371 void close();
372
373 fstream& read(char* buffer, fl::size_t count);
374
376 return mLastRead;
377 }
378
379 fstream& write(const char* data, fl::size_t count);
380
382
384
385 bool good() const { return mGood; }
386 bool eof() const { return mEof; }
387 bool fail() const { return mFail; }
388
389 // Get last error code (0 if no error)
390 int error() const;
391
392 // Get human-readable error message
393 const char* error_message() const;
394
395 // Manually clear error state (for retry scenarios)
396 void clear_error();
397
398 // Access the underlying buffer
399 filebuf_ptr rdbuf() const { return mHandle; }
400};
401
402} // namespace fl
uint8_t pos
Definition Blur.ino:11
const char * error_message() const
bool eof() const
Definition fstream.h:386
fstream & write(const char *data, fl::size_t count)
bool mGood
Definition fstream.h:303
bool mEof
Definition fstream.h:304
~fstream() FL_NOEXCEPT
fl::size_t tellg()
fstream & seekg(fl::size_t pos, ios::seekdir dir=ios::seekdir::beg)
void updateState()
Definition fstream.h:308
filebuf_ptr mHandle
Definition fstream.h:301
fstream() FL_NOEXCEPT
Definition fstream.h:321
void clear_error()
fl::size_t gcount() const
Definition fstream.h:375
bool good() const
Definition fstream.h:385
bool fail() const
Definition fstream.h:387
bool mFail
Definition fstream.h:305
void open(const char *path, ios::openmode mode=ios::in|ios::out)
bool is_open() const
Definition fstream.h:367
fstream & operator=(fstream &&other) FL_NOEXCEPT
Definition fstream.h:346
fl::size_t mLastRead
Definition fstream.h:302
filebuf_ptr rdbuf() const
Definition fstream.h:399
int mLocalError
Definition fstream.h:306
int error() const
bool available() const
Definition fstream.h:161
filebuf_ptr mHandle
Definition fstream.h:50
bool eof() const
Definition fstream.h:128
void open(const char *path, ios::openmode mode=ios::in)
bool mEof
Definition fstream.h:53
const char * error_message() const
~ifstream() FL_NOEXCEPT
bool seek(fl::size_t p, seek_dir dir)
Definition fstream.h:195
fl::size_t size() const
Definition fstream.h:146
ifstream & operator=(ifstream &&other) FL_NOEXCEPT
Definition fstream.h:92
bool is_open() const
Definition fstream.h:111
const char * path() const
Definition fstream.h:156
int error() const
bool available(fl::size_t n) const
Definition fstream.h:166
bool good() const
Definition fstream.h:127
fl::size_t mLastRead
Definition fstream.h:51
fl::size_t read(fl::u8 *dst, fl::size_t n)
Definition fstream.h:171
bool mFail
Definition fstream.h:54
ifstream & seekg(fl::size_t pos, ios::seekdir dir=ios::seekdir::beg)
fl::size_t read(fl::span< fl::u8 > dst)
Definition fstream.h:177
bool seek(fl::size_t p)
Definition fstream.h:191
fl::size_t pos() const
Definition fstream.h:189
bool mGood
Definition fstream.h:52
filebuf_ptr rdbuf() const
Definition fstream.h:143
fl::size_t bytes_left() const
Definition fstream.h:151
ifstream() FL_NOEXCEPT
Definition fstream.h:69
bool fail() const
Definition fstream.h:129
fl::size_t readRGB8(fl::span< CRGB > dst)
Definition fstream.h:182
fl::size_t tellg()
fl::size_t gcount() const
Definition fstream.h:119
bool valid() const
Definition fstream.h:188
fl::size_t bytesLeft() const
Definition fstream.h:190
void updateState()
Definition fstream.h:56
bool fail() const
Definition fstream.h:280
ofstream & operator=(ofstream &&other) FL_NOEXCEPT
Definition fstream.h:251
filebuf_ptr rdbuf() const
Definition fstream.h:292
ofstream & write(const char *data, fl::size_t count)
bool eof() const
Definition fstream.h:279
const char * error_message() const
ofstream() FL_NOEXCEPT
Definition fstream.h:228
void open(const char *path, ios::openmode mode=ios::out)
int error() const
bool is_open() const
Definition fstream.h:270
int mLocalError
Definition fstream.h:213
~ofstream() FL_NOEXCEPT
void updateState()
Definition fstream.h:215
filebuf_ptr mHandle
Definition fstream.h:209
bool good() const
Definition fstream.h:278
const T * data() const FL_NOEXCEPT
Definition span.h:461
constexpr fl::size size() const FL_NOEXCEPT
Definition span.h:458
unsigned char u8
Definition s16x16x4.h:132
__SIZE_TYPE__ size_t
Definition s16x16x4.h:16
static constexpr openmode in
Definition fstream.h:31
static constexpr openmode ate
Definition fstream.h:30
static constexpr openmode trunc
Definition fstream.h:33
static constexpr openmode out
Definition fstream.h:32
static constexpr openmode binary
Definition fstream.h:29
static constexpr openmode app
Definition fstream.h:34
unsigned int openmode
Definition fstream.h:28
seek_dir
Definition file_handle.h:19
int read()
To reinterpret_cast_(const From &from) FL_NOEXCEPT
Definition bit_cast.h:88
fl::shared_ptr< filebuf > filebuf_ptr
Definition idecoder.h:15
Base definition for an LED controller.
Definition crgb.hpp:179
#define FL_NOEXCEPT