From 80ccbaef0dd744dcad1ce7805292be60cb50c143 Mon Sep 17 00:00:00 2001 From: Martin Ayotte Date: Thu, 6 Aug 2015 13:32:02 -0400 Subject: [PATCH 1/5] fix dtostrf() issue using trackerj/odometer fixes along with my own fix for string null character ending --- cores/esp8266/core_esp8266_noniso.c | 37 ++++++++++++++--------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/cores/esp8266/core_esp8266_noniso.c b/cores/esp8266/core_esp8266_noniso.c index 40fe5e6dd4..fecdd33629 100644 --- a/cores/esp8266/core_esp8266_noniso.c +++ b/cores/esp8266/core_esp8266_noniso.c @@ -162,46 +162,45 @@ char * dtostrf(double number, signed char width, unsigned char prec, char *s) { strcpy(s, "ovf"); return s; } - char* out = s; - int signInt_Part = 1; - // Handle negative numbers if (number < 0.0) { - signInt_Part = -1; + *out = '-'; + ++out; number = -number; } - // calc left over digits - if (prec > 0) - { - width -= (prec + 1); - } - // Round correctly so that print(1.999, 2) prints as "2.00" - double rounding = 0.5; + // I optimized out most of the divisions + double rounding = 2.0; for (uint8_t i = 0; i < prec; ++i) - rounding /= 10.0; + rounding *= 10.0; + rounding = 1.0 / rounding; number += rounding; // Extract the integer part of the number and print it unsigned long int_part = (unsigned long)number; double remainder = number - (double)int_part; - out += sprintf(out, "%*ld", width, int_part * signInt_Part); + out += sprintf(out, "%d", int_part); // Print the decimal point, but only if there are digits beyond if (prec > 0) { *out = '.'; ++out; - - - for (unsigned char decShift = prec; decShift > 0; decShift--) { - remainder *= 10.0; - } - sprintf(out, "%0*d", prec, (int)remainder); } + // Print the digits after the decimal point + int8_t digit = 0; + while (prec-- > 0) { + remainder *= 10.0; + digit = (int8_t)remainder; + if (digit > 9) digit = 9; // insurance + *out = (char)('0' | digit); + ++out; + remainder -= digit; + } + *out = 0; return s; } From aa6965c1722327b665c49e337c69874ee56a4449 Mon Sep 17 00:00:00 2001 From: Martin Ayotte Date: Fri, 7 Aug 2015 11:06:06 -0400 Subject: [PATCH 2/5] fix the missing minimum width requirement --- cores/esp8266/core_esp8266_noniso.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/cores/esp8266/core_esp8266_noniso.c b/cores/esp8266/core_esp8266_noniso.c index fecdd33629..7fb4fd66af 100644 --- a/cores/esp8266/core_esp8266_noniso.c +++ b/cores/esp8266/core_esp8266_noniso.c @@ -165,8 +165,7 @@ char * dtostrf(double number, signed char width, unsigned char prec, char *s) { char* out = s; // Handle negative numbers if (number < 0.0) { - *out = '-'; - ++out; + *out++ = '-'; number = -number; } @@ -186,9 +185,12 @@ char * dtostrf(double number, signed char width, unsigned char prec, char *s) { // Print the decimal point, but only if there are digits beyond if (prec > 0) { - *out = '.'; - ++out; + *out++ = '.'; } + // make sure the string is terminated before mesuring it length + *out = 0; + // Reduce minimum width accordingly + width -= strlen(s); // Print the digits after the decimal point int8_t digit = 0; @@ -196,10 +198,13 @@ char * dtostrf(double number, signed char width, unsigned char prec, char *s) { remainder *= 10.0; digit = (int8_t)remainder; if (digit > 9) digit = 9; // insurance - *out = (char)('0' | digit); - ++out; + *out++ = (char)('0' | digit); + width--; remainder -= digit; } + // add '0' to fill minimum width requirement + while (width-- > 0) *out++ = '0'; + // make sure the string is terminated *out = 0; return s; } From 659e467141a9738a883d5cc7e9670a4f1b8934f0 Mon Sep 17 00:00:00 2001 From: Martin Ayotte Date: Fri, 7 Aug 2015 21:55:25 -0400 Subject: [PATCH 3/5] padding should be done with space, not with '0' --- cores/esp8266/core_esp8266_noniso.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cores/esp8266/core_esp8266_noniso.c b/cores/esp8266/core_esp8266_noniso.c index 7fb4fd66af..0b53583fdf 100644 --- a/cores/esp8266/core_esp8266_noniso.c +++ b/cores/esp8266/core_esp8266_noniso.c @@ -203,7 +203,7 @@ char * dtostrf(double number, signed char width, unsigned char prec, char *s) { remainder -= digit; } // add '0' to fill minimum width requirement - while (width-- > 0) *out++ = '0'; + while (width-- > 0) *out++ = ' '; // make sure the string is terminated *out = 0; return s; From 1cd99391c3b31e23a47955e922ffa7a6eac9f867 Mon Sep 17 00:00:00 2001 From: Martin Ayotte Date: Sat, 8 Aug 2015 15:25:08 -0400 Subject: [PATCH 4/5] integrate new version provided by Odometer --- cores/esp8266/core_esp8266_noniso.c | 72 +++++++++++++++++------------ 1 file changed, 42 insertions(+), 30 deletions(-) diff --git a/cores/esp8266/core_esp8266_noniso.c b/cores/esp8266/core_esp8266_noniso.c index 0b53583fdf..d5b9d82f28 100644 --- a/cores/esp8266/core_esp8266_noniso.c +++ b/cores/esp8266/core_esp8266_noniso.c @@ -148,7 +148,8 @@ char* ultoa(unsigned long value, char* result, int base) { } char * dtostrf(double number, signed char width, unsigned char prec, char *s) { - + bool negative = false; + if (isnan(number)) { strcpy(s, "nan"); return s; @@ -158,14 +159,17 @@ char * dtostrf(double number, signed char width, unsigned char prec, char *s) { return s; } - if (number > 4294967040.0 || number < -4294967040.0) { - strcpy(s, "ovf"); - return s; - } char* out = s; + + int fillme = width; // how many cells to fill for the integer part + if (prec > 0) { + fillme -= (prec+1); + } + // Handle negative numbers if (number < 0.0) { - *out++ = '-'; + negative = true; + fillme--; number = -number; } @@ -173,39 +177,47 @@ char * dtostrf(double number, signed char width, unsigned char prec, char *s) { // I optimized out most of the divisions double rounding = 2.0; for (uint8_t i = 0; i < prec; ++i) - rounding *= 10.0; - rounding = 1.0 / rounding; + rounding *= 10.0; + rounding = 1.0 / rounding; number += rounding; - - // Extract the integer part of the number and print it - unsigned long int_part = (unsigned long)number; - double remainder = number - (double)int_part; - out += sprintf(out, "%d", int_part); - - // Print the decimal point, but only if there are digits beyond - if (prec > 0) { - *out++ = '.'; + + // Figure out how big our number really is + double tenpow = 1.0; + int digitcount = 1; + while (number >= 10.0 * tenpow) { + tenpow *= 10.0; + digitcount++; } - // make sure the string is terminated before mesuring it length - *out = 0; - // Reduce minimum width accordingly - width -= strlen(s); - - // Print the digits after the decimal point + + number /= tenpow; + fillme -= digitcount; + + // Pad unused cells with spaces + while (fillme-- > 0) { + *out++ = ' '; + } + + // Handle negative sign + if (negative) *out++ = '-'; + + // Print the digits, and if necessary, the decimal point + digitcount += prec; int8_t digit = 0; - while (prec-- > 0) { - remainder *= 10.0; - digit = (int8_t)remainder; + while (digitcount-- > 0) { + digit = (int8_t)number; if (digit > 9) digit = 9; // insurance *out++ = (char)('0' | digit); - width--; - remainder -= digit; + if ((digitcount == prec) && (prec > 0)) { + *out++ = '.'; + } + number -= digit; + number *= 10.0; } - // add '0' to fill minimum width requirement - while (width-- > 0) *out++ = ' '; + // make sure the string is terminated *out = 0; return s; } + From 568c48b065f3b05f46f4fad3f5dd70d2137be90b Mon Sep 17 00:00:00 2001 From: Martin Ayotte Date: Wed, 12 Aug 2015 22:12:22 -0400 Subject: [PATCH 5/5] add fileSize() method to Dir object --- cores/esp8266/FS.cpp | 8 ++++++++ cores/esp8266/FS.h | 1 + cores/esp8266/FSImpl.h | 1 + cores/esp8266/spiffs_api.cpp | 7 +++++++ 4 files changed, 17 insertions(+) diff --git a/cores/esp8266/FS.cpp b/cores/esp8266/FS.cpp index 7a13dcede8..125ac527cb 100644 --- a/cores/esp8266/FS.cpp +++ b/cores/esp8266/FS.cpp @@ -144,6 +144,14 @@ String Dir::fileName() { return _impl->fileName(); } +size_t Dir::fileSize() { + if (!_impl) { + return 0; + } + + return _impl->fileSize(); +} + bool Dir::next() { if (!_impl) { return false; diff --git a/cores/esp8266/FS.h b/cores/esp8266/FS.h index 3e1b1b4fc1..4009bb2f24 100644 --- a/cores/esp8266/FS.h +++ b/cores/esp8266/FS.h @@ -78,6 +78,7 @@ class Dir { File openFile(const char* mode); String fileName(); + size_t fileSize(); bool next(); protected: diff --git a/cores/esp8266/FSImpl.h b/cores/esp8266/FSImpl.h index 8e48a9fda0..20d886e764 100644 --- a/cores/esp8266/FSImpl.h +++ b/cores/esp8266/FSImpl.h @@ -56,6 +56,7 @@ class DirImpl { virtual ~DirImpl() { } virtual FileImplPtr openFile(OpenMode openMode, AccessMode accessMode) = 0; virtual const char* fileName() = 0; + virtual size_t fileSize() = 0; virtual bool next() = 0; }; diff --git a/cores/esp8266/spiffs_api.cpp b/cores/esp8266/spiffs_api.cpp index 157ae86bcd..d9c7c618f4 100644 --- a/cores/esp8266/spiffs_api.cpp +++ b/cores/esp8266/spiffs_api.cpp @@ -308,6 +308,13 @@ class SPIFFSDirImpl : public DirImpl { return (const char*) _dirent.name; } + size_t fileSize() override { + if (!_valid) + return 0; + + return _dirent.size; + } + bool next() override { spiffs_dirent* result = SPIFFS_readdir(&_dir, &_dirent); _valid = (result != nullptr);