Skip to content

Commit 02f54e8

Browse files
Reimplement SD.h write methods exactly in File (#5861)
* Reimplement SD.h write methods exactly in File Replace the individual override with the existing SD.h File's implementation for all methods of File::write. Fixes #5846 * Add add'l tests * Fix Print and File incompatible writes w/casts Print and File have ambiguous resolutions for single-argument write(0)s. Fix by adding explicit methods. A write of any integer will not be a const char* write (i.e. won't write a string) but will instead just write the integer truncated to 8 bits (as makes sense). * Use 256byte chunks in ::write template Reduce stack requirements for templated writes to 256bytes, matching the size uses in WiFiClient/etc. (from 512bytes). Reduces the chance of stack overflow. * Move write(int) methods up to Print.h Remove some technical debt by moving the ::write(int/short/long) methods out of FS and HardwareSerial and up into Print.h.
1 parent 192aaa4 commit 02f54e8

File tree

4 files changed

+58
-17
lines changed

4 files changed

+58
-17
lines changed

cores/esp8266/FS.h

+23-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,29 @@ class File : public Stream
8080
bool isDirectory() const;
8181

8282
// Arduino "class SD" methods for compatibility
83-
size_t write(const char *str) { return write((const uint8_t*)str, strlen(str)); }
83+
template<typename T> size_t write(T &src){
84+
uint8_t obuf[256];
85+
size_t doneLen = 0;
86+
size_t sentLen;
87+
int i;
88+
89+
while (src.available() > sizeof(obuf)){
90+
src.read(obuf, sizeof(obuf));
91+
sentLen = write(obuf, sizeof(obuf));
92+
doneLen = doneLen + sentLen;
93+
if(sentLen != sizeof(obuf)){
94+
return doneLen;
95+
}
96+
}
97+
98+
size_t leftLen = src.available();
99+
src.read(obuf, leftLen);
100+
sentLen = write(obuf, leftLen);
101+
doneLen = doneLen + sentLen;
102+
return doneLen;
103+
}
104+
using Print::write;
105+
84106
void rewindDirectory();
85107
File openNextFile();
86108

cores/esp8266/HardwareSerial.h

-16
Original file line numberDiff line numberDiff line change
@@ -152,22 +152,6 @@ class HardwareSerial: public Stream
152152
{
153153
return uart_write_char(_uart, c);
154154
}
155-
inline size_t write(unsigned long n)
156-
{
157-
return write((uint8_t) n);
158-
}
159-
inline size_t write(long n)
160-
{
161-
return write((uint8_t) n);
162-
}
163-
inline size_t write(unsigned int n)
164-
{
165-
return write((uint8_t) n);
166-
}
167-
inline size_t write(int n)
168-
{
169-
return write((uint8_t) n);
170-
}
171155
size_t write(const uint8_t *buffer, size_t size) override
172156
{
173157
return uart_write(_uart, (const char*)buffer, size);

cores/esp8266/Print.h

+7
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,13 @@ class Print {
6262
size_t write(const char *buffer, size_t size) {
6363
return write((const uint8_t *) buffer, size);
6464
}
65+
// These handle ambiguity for write(0) case, because (0) can be a pointer or an integer
66+
size_t write(short t) { return write((uint8_t)t); }
67+
size_t write(unsigned short t) { return write((uint8_t)t); }
68+
size_t write(int t) { return write((uint8_t)t); }
69+
size_t write(unsigned int t) { return write((uint8_t)t); }
70+
size_t write(long t) { return write((uint8_t)t); }
71+
size_t write(unsigned long t) { return write((uint8_t)t); }
6572

6673
size_t printf(const char * format, ...) __attribute__ ((format (printf, 2, 3)));
6774
size_t printf_P(PGM_P format, ...) __attribute__((format(printf, 2, 3)));

tests/host/fs/test_fs.cpp

+28
Original file line numberDiff line numberDiff line change
@@ -331,3 +331,31 @@ TEST_CASE("Listfiles.ino example", "[sd]")
331331
REQUIRE(readFileSD("/dir2/dir3/file4") == "bonjour");
332332
}
333333

334+
TEST_CASE("Multisplendored File::writes", "[fs]")
335+
{
336+
SDFS_MOCK_DECLARE();
337+
SDFS.end();
338+
SDFS.setConfig(SDFSConfig(0, SD_SCK_MHZ(1)));
339+
REQUIRE(SDFS.format());
340+
REQUIRE(SD.begin(4));
341+
342+
File f = SD.open("/file.txt", FILE_WRITE);
343+
f.write('a');
344+
f.write(65);
345+
f.write("bbcc");
346+
f.write("theend", 6);
347+
char block[3]={'x','y','z'};
348+
f.write(block, 3);
349+
uint32_t bigone = 0x40404040;
350+
f.write((const uint8_t*)&bigone, 4);
351+
f.close();
352+
REQUIRE(readFileSD("/file.txt") == "aAbbcctheendxyz@@@@");
353+
File g = SD.open("/file.txt", FILE_WRITE);
354+
g.write(0);
355+
g.close();
356+
g = SD.open("/file.txt", FILE_READ);
357+
uint8_t u = 0x66;
358+
g.read(&u, 1);
359+
g.close();
360+
REQUIRE(u == 0);
361+
}

0 commit comments

Comments
 (0)