FastLED 3.10.6
Loading...
Searching...
No Matches
fs.cpp.hpp
Go to the documentation of this file.
1#include "fl/fs/fs.h"
2#include "fl/fled/fled.h"
4#include "fl/log/log.h"
5#include "fl/stl/vector.h"
6#include "fl/math/math.h"
7
8// NOTE: SD card support (FileSystem::beginSd and make_sdcard_filesystem)
9// lives in a SEPARATE translation unit at
10// `src/fl/fs/sd/file_system_sd.cpp.hpp`, compiled into
11// `fl.system.sd+.cpp.o` via `src/fl/build/fl.system.sd+.cpp`.
12//
13// This split lets the linker tree-shake the entire SD chain (libSD.a,
14// libFS.a, Arduino's VFSImpl, the printf engine VFSFileImpl drags in
15// via snprintf) AUTOMATICALLY when the user never calls
16// `FileSystem::beginSd()` -- no FASTLED_USE_SDCARD opt-in required, and
17// the macro that the earlier macro-gate PR (#2778 v1) shipped is
18// removed by this PR. See FastLED #2773 item 1.2 and the SD TU header
19// for the mechanism.
20//
21// All other FileSystem methods (begin, openRead, readText, ...) and the
22// NullFileSystem stub stay here, so existing sketches that use only
23// `FileSystem::begin(platform_filesystem)` are unaffected.
24
25#include "fl/stl/json.h"
26#include "fl/math/screenmap.h"
27#include "fl/math/math.h" // for min
28#include "fl/stl/cstring.h"
29#include "fl/stl/noexcept.h"
30
31// Codec-dependent methods (openMp3, loadJpeg, openMpeg1Video, Mpeg1FileHandle)
32// moved to fl/codec/file_system_codecs.cpp.hpp to break fl.system+ -> fl.codec+ chain.
33
34namespace fl {
35
36class NullFileHandle : public filebuf {
37 public:
40
41 bool is_open() const override { return false; }
42 fl::size_t size() const override { return 0; }
43 fl::size_t read(char *dst, fl::size_t bytesToRead) override {
44 FASTLED_UNUSED(dst);
45 FASTLED_UNUSED(bytesToRead);
46 return 0;
47 }
48 fl::size_t write(const char *data, fl::size_t count) override {
49 FASTLED_UNUSED(data);
50 FASTLED_UNUSED(count);
51 return 0;
52 }
53 fl::size_t tell() override { return 0; }
54 const char *path() const override { return "nullptr filebuf"; }
55 bool seek(fl::size_t pos, seek_dir dir) override {
57 FASTLED_UNUSED(dir);
58 return false;
59 }
60 using filebuf::seek; // single-arg overload
61 void close() override {}
62 bool is_eof() const override { return true; }
63 bool has_error() const override { return false; }
64 void clear_error() override {}
65 int error_code() const override { return 0; }
66 const char *error_message() const override { return "NullFileHandle"; }
67};
68
69class NullFileSystem : public FsImpl {
70 public:
72 FL_WARN("NullFileSystem instantiated as a placeholder, please "
73 "implement a file system for your platform.");
74 }
76
77 bool begin() override { return true; }
78 void end() override {}
79
80 filebuf_ptr openRead(const char *_path) override {
81 FASTLED_UNUSED(_path);
83 filebuf_ptr out = ptr;
84 return out;
85 }
86};
87
88
89// FileSystem::beginSd() is intentionally NOT defined in this TU. The
90// definition lives in `fl/fs/sd/file_system_sd.cpp.hpp` which is
91// compiled into its own `.o` (`fl.system.sd+.cpp.o`). The linker only
92// pulls that `.o` when the user actually calls `fs.beginSd(...)`,
93// keeping all SD library code (~15 KB on ESP32-S3) out of sketches that
94// don't use it. See FastLED #2773 item 1.2.
95
96bool FileSystem::begin(FsImplPtr platform_filesystem) {
97 mFs = platform_filesystem;
98 if (!mFs) {
99 return false;
100 }
101 mFs->begin();
102 return true;
103}
104
106 return Fled::load(*this, path);
107}
108
110
112 if (mFs) {
113 mFs->end();
114 }
115}
116
117bool FileSystem::readJson(const char *path, json *doc) {
118 string text;
119 if (!readText(path, &text)) {
120 return false;
121 }
122
123 // Parse using the new json class
124 *doc = fl::json::parse(text);
125 return !doc->is_null();
126}
127
128bool FileSystem::readScreenMaps(const char *path,
129 fl::flat_map<string, ScreenMap> *out, string *error) {
130 string text;
131 if (!readText(path, &text)) {
132 FL_WARN("Failed to read file: %s", path);
133 if (error) {
134 *error = "Failed to read file: ";
135 error->append(path);
136 }
137 return false;
138 }
139 string err;
140 bool ok = ScreenMap::ParseJson(text.c_str(), out, &err);
141 if (!ok) {
142 FL_WARN("Failed to parse screen map: %s", err.c_str());
143 *error = err;
144 return false;
145 }
146 return true;
147}
148
149bool FileSystem::readScreenMap(const char *path, const char *name,
150 ScreenMap *out, string *error) {
151 string text;
152 if (!readText(path, &text)) {
153 FL_WARN("Failed to read file: %s", path);
154 if (error) {
155 *error = "Failed to read file: ";
156 error->append(path);
157 }
158 return false;
159 }
160 string err;
161 bool ok = ScreenMap::ParseJson(text.c_str(), name, out, &err);
162 if (!ok) {
163 FL_WARN("Failed to parse screen map: %s", err.c_str());
164 *error = err;
165 return false;
166 }
167 return true;
168}
169
171 if (!mFs) {
172 // Defensive: default-constructed FileSystem or one whose begin*()
173 // call failed has a null backend. Returning a closed ifstream
174 // lets downstream code branch on is_open() rather than crash.
175 return fl::ifstream();
176 }
177 return fl::ifstream(mFs->openRead(path));
178}
179Video FileSystem::openVideo(const char *path, fl::size pixelsPerFrame, float fps,
180 fl::size nFrameHistory) {
181 Video video(pixelsPerFrame, fps, nFrameHistory);
182 fl::ifstream file = openRead(path);
183 if (!file.is_open()) {
184 video.setError(fl::string("Could not open file: ").append(path));
185 return video;
186 }
187 video.begin(file.rdbuf());
188 return video;
189}
190
191bool FileSystem::readText(const char *path, fl::string *out) {
192 fl::ifstream file = openRead(path);
193 if (!file.is_open()) {
194 FL_WARN("Failed to open file: %s", path);
195 return false;
196 }
197 fl::size size = file.size();
198 out->reserve(size + out->size());
199 bool wrote = false;
200 while (file.available()) {
201 u8 buf[64];
202 fl::size n = file.read(buf, sizeof(buf));
203 out->append((const char *)buf, n);
204 wrote = true;
205 }
206 file.close();
207 FL_DBG_IF(!wrote, "Failed to write any data to the output string.");
208 return wrote;
209}
210
211
212// Convenience wrapper: mount an SD card and decode a JPEG in one call.
213// Out of line because the API header wraps, it does not implement
214// (agents/docs/cpp-standards.md -> API Object Pattern, rule 2; FastLED #4003).
215FramePtr loadJpegFromSD(int cs_pin, const char *filepath,
216 const JpegConfig &config,
217 fl::string *error_message) FL_NO_EXCEPT {
218 FileSystem fs;
219 if (!fs.beginSd(cs_pin)) {
220 if (error_message) {
221 *error_message = "Failed to initialize SD card on CS pin ";
222 error_message->append(static_cast<fl::u32>(cs_pin));
223 }
224 return FramePtr();
225 }
226 return fs.loadJpeg(filepath, config, error_message);
227}
228
229} // namespace fl
230
231// `make_sdcard_filesystem(int cs_pin)` is defined in the separate SD TU
232// (`fl/fs/sd/file_system_sd.cpp.hpp`). When the SD TU is not linked
233// (the user never calls `fs.beginSd()`), the symbol is also dead-stripped
234// alongside `FileSystem::beginSd` itself.
bool readText(const char *path, string *out)
Definition fs.cpp.hpp:191
bool beginSd(int cs_pin) FL_NO_EXCEPT
bool readJson(const char *path, json *doc)
Definition fs.cpp.hpp:117
fl::ifstream openRead(const char *path)
Definition fs.cpp.hpp:170
bool readScreenMap(const char *path, const char *name, ScreenMap *out, string *error=nullptr)
Definition fs.cpp.hpp:149
bool begin(FsImplPtr platform_filesystem)
Definition fs.cpp.hpp:96
Video openVideo(const char *path, fl::size pixelsPerFrame, float fps=30.0f, fl::size nFrameHistory=0)
Definition fs.cpp.hpp:179
FramePtr loadJpeg(const char *path, const JpegConfig &config=JpegConfig(), fl::string *error_message=nullptr)
FsImplPtr mFs
Definition fs.h:106
bool readScreenMaps(const char *path, fl::flat_map< string, ScreenMap > *out, string *error=nullptr)
Definition fs.cpp.hpp:128
FileSystem() FL_NO_EXCEPT
Definition fs.cpp.hpp:109
fl::Fled loadFled(const char *path) FL_NO_EXCEPT
Definition fs.cpp.hpp:105
static Fled load(FileSystem &fs, const char *path) FL_NO_EXCEPT
Definition fled.cpp.hpp:31
FsImpl() FL_NO_EXCEPT=default
int error_code() const override
Definition fs.cpp.hpp:65
const char * path() const override
Definition fs.cpp.hpp:54
bool is_eof() const override
Definition fs.cpp.hpp:62
fl::size_t tell() override
Definition fs.cpp.hpp:53
bool is_open() const override
Definition fs.cpp.hpp:41
fl::size_t size() const override
Definition fs.cpp.hpp:42
fl::size_t read(char *dst, fl::size_t bytesToRead) override
Definition fs.cpp.hpp:43
bool seek(fl::size_t pos, seek_dir dir) override
Definition fs.cpp.hpp:55
void clear_error() override
Definition fs.cpp.hpp:64
const char * error_message() const override
Definition fs.cpp.hpp:66
void close() override
Definition fs.cpp.hpp:61
NullFileHandle() FL_NO_EXCEPT=default
bool has_error() const override
Definition fs.cpp.hpp:63
fl::size_t write(const char *data, fl::size_t count) override
Definition fs.cpp.hpp:48
NullFileSystem() FL_NO_EXCEPT
Definition fs.cpp.hpp:71
void end() override
Unmount. Must be safe to call on a backend that never mounted.
Definition fs.cpp.hpp:78
bool begin() override
Mount. False if the medium is absent, unformatted, or unreadable.
Definition fs.cpp.hpp:77
~NullFileSystem() FL_NO_EXCEPT override
Definition fs.cpp.hpp:75
filebuf_ptr openRead(const char *_path) override
Null handle if the file does not exist or cannot be opened.
Definition fs.cpp.hpp:80
static bool ParseJson(const char *jsonStrScreenMap, fl::flat_map< string, ScreenMap > *segmentMaps, string *err=nullptr) FL_NO_EXCEPT
void reserve(fl::size newCapacity) FL_NO_EXCEPT
const char * c_str() const FL_NO_EXCEPT
fl::size size() const FL_NO_EXCEPT
virtual bool seek(fl::size_t pos, seek_dir dir)=0
fl::size_t pos() const
bool available() const
Definition fstream.h:161
fl::size_t size() const
Definition fstream.h:146
ifstream & read(char *buffer, fl::size_t count)
bool is_open() const
Definition fstream.h:111
filebuf_ptr rdbuf() const
Definition fstream.h:143
bool is_null() const FL_NO_EXCEPT
Definition json.h:381
static json parse(const fl::string &txt) FL_NO_EXCEPT
Definition json.h:842
string & append(const bitset_fixed< N > &bs) FL_NO_EXCEPT
Definition string.h:293
#define FASTLED_UNUSED(x)
FastLED's Elegant JSON Library: fl::json
#define FL_DBG_IF
Definition log.h:565
#define FL_WARN(...)
Definition log.h:440
Centralized logging categories for FastLED hardware interfaces and subsystems.
__SIZE_TYPE__ size_t
Definition s16x16x4.h:16
FramePtr loadJpegFromSD(int cs_pin, const char *filepath, const JpegConfig &config, fl::string *error_message) FL_NO_EXCEPT
Definition fs.cpp.hpp:215
unsigned char u8
Definition stdint.h:131
seek_dir
Definition file_handle.h:20
shared_ptr< T > make_shared(Args &&... args) FL_NO_EXCEPT
Definition shared_ptr.h:414
fl::shared_ptr< filebuf > filebuf_ptr
Definition idecoder.h:15
InputGamut g FL_NO_EXCEPT
Definition rgbw.h:121
Base definition for an LED controller.
Definition crgb.hpp:179