1+ #include " MockSPIFFS.h"
2+
3+ // global instance
4+ MockSPIFFSClass MockSPIFFS;
5+
6+ // ---------------- MockFile ----------------
7+ MockFile::MockFile (MockSPIFFSClass* owner_, int index, bool writable_, bool isDir_)
8+ : owner(owner_), idx(index), isDir(isDir_), pos(0 ), writable(writable_), valid(true )
9+ {
10+ if (!owner_) { valid = false ; return ; }
11+ if (!isDir_ && (idx < 0 || idx >= (int )owner_->files .size ())) { valid = false ; }
12+ }
13+
14+ size_t MockFile::print (const String& s) {
15+ if (!valid || !writable) return 0 ;
16+ owner->files [idx].content += s;
17+ return s.length ();
18+ }
19+
20+ size_t MockFile::println (const String& s) {
21+ return print (s + " \n " );
22+ }
23+
24+ String MockFile::readString () {
25+ if (!valid) return String ();
26+ String &c = owner->files [idx].content ;
27+ String out = c.substring (pos);
28+ pos = c.length ();
29+ return out;
30+ }
31+
32+ String MockFile::readStringUntil (char c) {
33+ if (!valid) return String ();
34+ String &ct = owner->files [idx].content ;
35+ int idxFound = ct.indexOf (c, pos);
36+ if (idxFound < 0 ) {
37+ String res = ct.substring (pos);
38+ pos = ct.length ();
39+ return res;
40+ }
41+ String res = ct.substring (pos, idxFound);
42+ pos = idxFound + 1 ;
43+ return res;
44+ }
45+
46+ int MockFile::available () {
47+ if (!valid) return 0 ;
48+ return (int )owner->files [idx].content .length () - pos;
49+ }
50+
51+ size_t MockFile::size () const {
52+ if (!valid) return 0 ;
53+ return owner->files [idx].content .length ();
54+ }
55+
56+ void MockFile::close () {
57+ // no-op
58+ }
59+
60+ bool MockFile::isDirectory () const {
61+ return isDir;
62+ }
63+
64+ MockFile MockFile::openNextFile () {
65+ if (!isDir) return MockFile ();
66+ int total = (int )owner->files .size ();
67+ if (pos >= total) return MockFile ();
68+ int fileIdx = pos++;
69+ return MockFile (owner, fileIdx, false , false );
70+ }
71+
72+ const char * MockFile::name () const {
73+ if (!valid) return " " ;
74+ return owner->files [idx].path .c_str ();
75+ }
76+
77+ size_t MockFile::read (uint8_t * buffer, size_t len) {
78+ if (!valid) return 0 ;
79+ String &c = owner->files [idx].content ;
80+ if (pos >= (int )c.length ()) return 0 ;
81+ size_t toRead = len;
82+ if (pos + (int )toRead > (int )c.length ()) toRead = c.length () - pos;
83+ for (size_t i = 0 ; i < toRead; ++i) buffer[i] = (uint8_t )c[pos + i];
84+ pos += toRead;
85+ return toRead;
86+ }
87+
88+ size_t MockFile::write (const uint8_t * buffer, size_t len) {
89+ if (!valid || !writable) return 0 ;
90+ String &c = owner->files [idx].content ;
91+ for (size_t i = 0 ; i < len; ++i) c += (char )buffer[i];
92+ return len;
93+ }
94+
95+ // ---------------- MockSPIFFSClass ----------------
96+ int MockSPIFFSClass::indexOf (const String& path) const {
97+ for (size_t i = 0 ; i < files.size (); ++i) if (files[i].path == path) return (int )i;
98+ return -1 ;
99+ }
100+
101+ bool MockSPIFFSClass::begin (bool formatOnFail){return true ;}
102+ bool MockSPIFFSClass::format (){return true ;}
103+
104+ MockFile MockSPIFFSClass::open (const String& path, const char * mode) {
105+ char m = (mode && mode[0 ]) ? mode[0 ] : ' r' ;
106+ if (path == " /" ) {
107+ MockFile dir (this , -2 , false , true );
108+ return dir;
109+ }
110+ int idx = indexOf (path);
111+ if (m == ' r' ) {
112+ if (idx < 0 ) return MockFile ();
113+ return MockFile (this , idx, false , false );
114+ } else if (m == ' w' ) {
115+ if (idx < 0 ) { files.push_back ({path, " " }); idx = (int )files.size () - 1 ; }
116+ else files[idx].content = " " ;
117+ return MockFile (this , idx, true , false );
118+ } else if (m == ' a' ) {
119+ if (idx < 0 ) { files.push_back ({path, " " }); idx = (int )files.size () - 1 ; }
120+ return MockFile (this , idx, true , false );
121+ }
122+ return MockFile ();
123+ }
124+
125+ MockFile MockSPIFFSClass::open (const String& path, int flags) {
126+ #if defined(FILE_APPEND) && defined(FILE_WRITE)
127+ if (flags == FILE_APPEND) return open (path, " a" );
128+ if (flags == FILE_WRITE) return open (path, " w" );
129+ #endif
130+ if (flags != 0 ) return open (path, " w" );
131+ return open (path, " r" );
132+ }
133+
134+ bool MockSPIFFSClass::exists (const String& path) const {
135+ return indexOf (path) >= 0 ;
136+ }
137+
138+ bool MockSPIFFSClass::remove (const String& path) {
139+ int idx = indexOf (path);
140+ if (idx < 0 ) return false ;
141+ files.erase (files.begin () + idx);
142+ return true ;
143+ }
144+
145+ bool MockSPIFFSClass::rename (const String& from, const String& to) {
146+ int idx = indexOf (from);
147+ if (idx < 0 ) return false ;
148+ int idxTo = indexOf (to);
149+ if (idxTo >= 0 ) {
150+ files[idxTo].content = files[idx].content ;
151+ files.erase (files.begin () + idx);
152+ } else {
153+ files[idx].path = to;
154+ }
155+ return true ;
156+ }
157+
158+ void MockSPIFFSClass::preload (const String& path, const String& content) {
159+ int idx = indexOf (path);
160+ if (idx < 0 ) files.push_back ({path, content});
161+ else files[idx].content = content;
162+ }
163+
164+ // preload only texte.txt
165+ static bool _mockspiffs_preload = []() {
166+ MockSPIFFS.preload (" texte.txt" , " Hello World\n " );
167+ String map_json = R"(
168+ {
169+ "map": {
170+ "color": "jaune",
171+ "vertices": [
172+ { "id": 0, "point": { "x": 0, "y": 0 } },
173+ { "id": 1, "point": { "x": 250, "y": 250 } },
174+ { "id": 2, "point": { "x": 500, "y": 250 } }
175+ ],
176+ "segments": [
177+ { "id": 0, "start": { "x": 0, "y": 1500 }, "end": { "x": 1500, "y": 1500 } },
178+ { "id": 1, "start": { "x": 1500, "y": 1500 }, "end": { "x": 1500, "y": 0 } }
179+ ],
180+ "circles": [
181+ { "id": 0, "center": { "x": 750, "y": 750 }, "radius": 100 },
182+ { "id": 1, "center": { "x": 1200, "y": 300 }, "radius": 150 }
183+ ]
184+ }
185+ }
186+ )" ;
187+ MockSPIFFS.preload (" map.json" , map_json);
188+
189+ return true ;
190+ }();
0 commit comments