From fa09a5079d67931c9f23a22b9caa1a78fbef19d1 Mon Sep 17 00:00:00 2001 From: david gauchard Date: Sun, 7 Feb 2021 01:28:13 +0100 Subject: [PATCH 1/7] String: compatibility with 64 bits scalars time_t is now 64 bits. Strig(time_t) was ambiguous tests added --- cores/esp8266/WString.cpp | 36 +++++++++++++++++++++++++++++++ cores/esp8266/WString.h | 22 +++++++++++++++++++ cores/esp8266/debug.cpp | 2 +- cores/esp8266/stdlib_noniso.cpp | 38 +++++++++++++++++++++++++++++++++ cores/esp8266/stdlib_noniso.h | 8 ++++++- tests/host/Makefile | 1 + tests/host/core/test_string.cpp | 10 +++++++++ 7 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 cores/esp8266/stdlib_noniso.cpp diff --git a/cores/esp8266/WString.cpp b/cores/esp8266/WString.cpp index 07ab99b2cf..2cad607117 100644 --- a/cores/esp8266/WString.cpp +++ b/cores/esp8266/WString.cpp @@ -98,6 +98,32 @@ String::String(unsigned long value, unsigned char base) { *this = buf; } +String::String(long long value) { + init(); + char buf[2 + 8 * sizeof(long long)]; + sprintf(buf, "%lld", value); + *this = buf; +} + +String::String(long long value, unsigned char base) { + init(); + char buf[2 + 8 * sizeof(long long)]; + *this = lltoa(value, buf, sizeof(buf), base); +} + +String::String(unsigned long long value) { + init(); + char buf[1 + 8 * sizeof(unsigned long long)]; + sprintf(buf, "%llu", value); + *this = buf; +} + +String::String(unsigned long long value, unsigned char base) { + init(); + char buf[1 + 8 * sizeof(unsigned long long)]; + *this = ulltoa(value, buf, sizeof(buf), base); +} + String::String(float value, unsigned char decimalPlaces) { init(); char buf[33]; @@ -313,6 +339,16 @@ unsigned char String::concat(unsigned long num) { return concat(buf, strlen(buf)); } +unsigned char String::concat(long long num) { + char buf[2 + 3 * sizeof(long long)]; + return concat(buf, sprintf(buf, "%lld", num)); +} + +unsigned char String::concat(unsigned long long num) { + char buf[1 + 3 * sizeof(unsigned long long)]; + return concat(buf, sprintf(buf, "%llu", num)); +} + unsigned char String::concat(float num) { char buf[20]; char *string = dtostrf(num, 4, 2, buf); diff --git a/cores/esp8266/WString.h b/cores/esp8266/WString.h index dcb0982387..beae31a9ab 100644 --- a/cores/esp8266/WString.h +++ b/cores/esp8266/WString.h @@ -72,6 +72,10 @@ class String { explicit String(unsigned int, unsigned char base = 10); explicit String(long, unsigned char base = 10); explicit String(unsigned long, unsigned char base = 10); + explicit String(long long /* base 10 */); + explicit String(long long, unsigned char base); + explicit String(unsigned long long /* base 10 */); + explicit String(unsigned long long, unsigned char base); explicit String(float, unsigned char decimalPlaces = 2); explicit String(double, unsigned char decimalPlaces = 2); ~String() { @@ -117,6 +121,8 @@ class String { unsigned char concat(unsigned int num); unsigned char concat(long num); unsigned char concat(unsigned long num); + unsigned char concat(long long num); + unsigned char concat(unsigned long long num); unsigned char concat(float num); unsigned char concat(double num); unsigned char concat(const __FlashStringHelper *str); @@ -156,6 +162,14 @@ class String { concat(num); return *this; } + String &operator +=(long long num) { + concat(num); + return *this; + } + String &operator +=(unsigned long long num) { + concat(num); + return *this; + } String &operator +=(float num) { concat(num); return *this; @@ -177,6 +191,8 @@ class String { friend StringSumHelper &operator +(const StringSumHelper &lhs, unsigned int num); friend StringSumHelper &operator +(const StringSumHelper &lhs, long num); friend StringSumHelper &operator +(const StringSumHelper &lhs, unsigned long num); + friend StringSumHelper &operator +(const StringSumHelper &lhs, long long num); + friend StringSumHelper &operator +(const StringSumHelper &lhs, unsigned long long num); friend StringSumHelper &operator +(const StringSumHelper &lhs, float num); friend StringSumHelper &operator +(const StringSumHelper &lhs, double num); friend StringSumHelper &operator +(const StringSumHelper &lhs, const __FlashStringHelper *rhs); @@ -375,6 +391,12 @@ class StringSumHelper: public String { StringSumHelper(unsigned long num) : String(num) { } + StringSumHelper(long long num) : + String(num) { + } + StringSumHelper(unsigned long long num) : + String(num) { + } StringSumHelper(float num) : String(num) { } diff --git a/cores/esp8266/debug.cpp b/cores/esp8266/debug.cpp index eddc7b06fe..858f5e1118 100644 --- a/cores/esp8266/debug.cpp +++ b/cores/esp8266/debug.cpp @@ -30,7 +30,7 @@ void hexdump(const void *mem, uint32_t len, uint8_t cols) while (len > 0) { uint32_t linesize = cols > len ? len : cols; - os_printf("\n[%p] 0x%04x: ", src, src - (const char*)mem); + os_printf("\n[%p] 0x%04x: ", src, (int)(src - (const char*)mem)); for (uint32_t i = 0; i < linesize; i++) { os_printf("%02x ", *(src + i)); diff --git a/cores/esp8266/stdlib_noniso.cpp b/cores/esp8266/stdlib_noniso.cpp new file mode 100644 index 0000000000..160c2e35df --- /dev/null +++ b/cores/esp8266/stdlib_noniso.cpp @@ -0,0 +1,38 @@ + +#include "stdlib_noniso.h" + +// fill backwards +char* ulltoa(unsigned long long val, char* str, size_t slen, uint_fast8_t radix) +{ + str += --slen; + *str = 0; + do + { + auto n = val % radix; + val /= radix; + *--str = n + ((n > 9) ? ('a' - 10) : '0'); + } while (--slen && val); + return val? nullptr: str; +} + +char* lltoa (long long val, char* str, size_t slen, uint_fast8_t radix) +{ + bool neg; + if (val < 0) + { + val = -val; + neg = true; + } + else + { + neg = false; + } + char* ret = ulltoa(val, str, slen, radix); + if (neg) + { + if (ret == str) + return nullptr; + *--ret = '-'; + } + return ret; +} diff --git a/cores/esp8266/stdlib_noniso.h b/cores/esp8266/stdlib_noniso.h index 053ea47948..8c2a3485fc 100644 --- a/cores/esp8266/stdlib_noniso.h +++ b/cores/esp8266/stdlib_noniso.h @@ -22,6 +22,8 @@ #ifndef STDLIB_NONISO_H #define STDLIB_NONISO_H +#include + #ifdef __cplusplus extern "C"{ #endif @@ -36,10 +38,14 @@ char* itoa (int val, char *s, int radix); char* ltoa (long val, char *s, int radix); +char* lltoa (long long val, char* str, size_t slen, uint_fast8_t radix); + char* utoa (unsigned int val, char *s, int radix); char* ultoa (unsigned long val, char *s, int radix); - + +char* ulltoa (unsigned long long val, char* str, size_t slen, uint_fast8_t radix); + char* dtostrf (double val, signed char width, unsigned char prec, char *s); void reverse(char* begin, char* end); diff --git a/tests/host/Makefile b/tests/host/Makefile index 4bb6e83b32..cc10061858 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -80,6 +80,7 @@ CORE_CPP_FILES := \ Stream.cpp \ WString.cpp \ Print.cpp \ + stdlib_noniso.cpp \ FS.cpp \ spiffs_api.cpp \ MD5Builder.cpp \ diff --git a/tests/host/core/test_string.cpp b/tests/host/core/test_string.cpp index 1150ba5913..e080be9507 100644 --- a/tests/host/core/test_string.cpp +++ b/tests/host/core/test_string.cpp @@ -132,6 +132,16 @@ TEST_CASE("String concantenation", "[core][String]") REQUIRE(str == "abcdeabcde9872147483647-2147483648691969-123321-1.01"); str += (double)1.01; REQUIRE(str == "abcdeabcde9872147483647-2147483648691969-123321-1.011.01"); + str += LLONG_MIN; + REQUIRE(str == "abcdeabcde9872147483647-2147483648691969-123321-1.011.01-9223372036854775808"); + str += String(LLONG_MIN, 10); + REQUIRE(str == "abcdeabcde9872147483647-2147483648691969-123321-1.011.01-9223372036854775808-9223372036854775808"); + str += LLONG_MAX; + REQUIRE(str == "abcdeabcde9872147483647-2147483648691969-123321-1.011.01-9223372036854775808-92233720368547758089223372036854775807"); + str += ULLONG_MAX; + REQUIRE(str == "abcdeabcde9872147483647-2147483648691969-123321-1.011.01-9223372036854775808-9223372036854775808922337203685477580718446744073709551615"); + str += String(ULLONG_MAX, 16); + REQUIRE(str == "abcdeabcde9872147483647-2147483648691969-123321-1.011.01-9223372036854775808-9223372036854775808922337203685477580718446744073709551615ffffffffffffffff"); str = "clean"; REQUIRE(str.concat(str) == true); REQUIRE(str == "cleanclean"); From 8c4c363491d1703a903d4815c56ffed63fb1adad Mon Sep 17 00:00:00 2001 From: david gauchard Date: Sun, 7 Feb 2021 16:34:50 +0100 Subject: [PATCH 2/7] use a single div+mod facility --- cores/esp8266/stdlib_noniso.cpp | 16 +++++++++---- cores/esp8266/stdlib_noniso.h | 40 +++++++++++++++++++++++++++------ 2 files changed, 45 insertions(+), 11 deletions(-) diff --git a/cores/esp8266/stdlib_noniso.cpp b/cores/esp8266/stdlib_noniso.cpp index 160c2e35df..0eed3a35b7 100644 --- a/cores/esp8266/stdlib_noniso.cpp +++ b/cores/esp8266/stdlib_noniso.cpp @@ -2,20 +2,28 @@ #include "stdlib_noniso.h" // fill backwards -char* ulltoa(unsigned long long val, char* str, size_t slen, uint_fast8_t radix) +char* ulltoa(unsigned long long val, char* str, int slen, unsigned long long radix) { str += --slen; *str = 0; do { - auto n = val % radix; +#if 1 + // using div and mod in a single call + // String(ULLMAX_LONG, 10) => 354us + unsigned long long mod; + val = udivmod(val, radix, mod); +#else + // String(ULLMAX_LONG, 10) => 374us + auto mod = val % radix; val /= radix; - *--str = n + ((n > 9) ? ('a' - 10) : '0'); +#endif + *--str = mod + ((mod > 9) ? ('a' - 10) : '0'); } while (--slen && val); return val? nullptr: str; } -char* lltoa (long long val, char* str, size_t slen, uint_fast8_t radix) +char* lltoa (long long val, char* str, int slen, long long radix) { bool neg; if (val < 0) diff --git a/cores/esp8266/stdlib_noniso.h b/cores/esp8266/stdlib_noniso.h index 8c2a3485fc..6d2bcaa28e 100644 --- a/cores/esp8266/stdlib_noniso.h +++ b/cores/esp8266/stdlib_noniso.h @@ -22,8 +22,6 @@ #ifndef STDLIB_NONISO_H #define STDLIB_NONISO_H -#include - #ifdef __cplusplus extern "C"{ #endif @@ -38,13 +36,13 @@ char* itoa (int val, char *s, int radix); char* ltoa (long val, char *s, int radix); -char* lltoa (long long val, char* str, size_t slen, uint_fast8_t radix); +char* lltoa (long long val, char* str, int slen, unsigned long long radix); char* utoa (unsigned int val, char *s, int radix); char* ultoa (unsigned long val, char *s, int radix); -char* ulltoa (unsigned long long val, char* str, size_t slen, uint_fast8_t radix); +char* ulltoa (unsigned long long val, char* str, int slen, unsigned long long radix); char* dtostrf (double val, signed char width, unsigned char prec, char *s); @@ -54,8 +52,36 @@ const char* strrstr(const char*__restrict p_pcString, const char*__restrict p_pcPattern); #ifdef __cplusplus -} // extern "C" -#endif +} // extern "C" -#endif +// https://gcc.gnu.org/legacy-ml/gcc/2016-02/msg00001.html +extern "C++" { +template +T udivmod(T num, T den, T& mod) +{ + T bit = 1; + T res = 0; + + while (den < num && bit && !(den & (((T)1) << (sizeof(T)*8 - 1)))) + { + den <<= 1; + bit <<= 1; + } + while (bit) + { + if (num >= den) + { + num -= den; + res |= bit; + } + bit >>= 1; + den >>= 1; + } + mod = num; + return res; +} // udivmod +} // "C++" + +#endif // __cplusplus +#endif // STDLIB_NONISO_H From 598491f46cf192ea434811676b2dd1e37349f6c6 Mon Sep 17 00:00:00 2001 From: david gauchard Date: Sun, 7 Feb 2021 17:29:06 +0100 Subject: [PATCH 3/7] fix host tests --- cores/esp8266/stdlib_noniso.cpp | 26 ++++++++++++++++++++++++++ cores/esp8266/stdlib_noniso.h | 17 ++++++++++++----- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/cores/esp8266/stdlib_noniso.cpp b/cores/esp8266/stdlib_noniso.cpp index 0eed3a35b7..851b05d79e 100644 --- a/cores/esp8266/stdlib_noniso.cpp +++ b/cores/esp8266/stdlib_noniso.cpp @@ -1,3 +1,24 @@ +/* + stdlib_noniso.h - nonstandard (but usefull) conversion functions + + Copyright (c) 2021 David Gauchard. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + #include "stdlib_noniso.h" @@ -26,6 +47,11 @@ char* ulltoa(unsigned long long val, char* str, int slen, unsigned long long rad char* lltoa (long long val, char* str, int slen, long long radix) { bool neg; + if (radix < 0) + { + radix = -radix; + val = -val; + } if (val < 0) { val = -val; diff --git a/cores/esp8266/stdlib_noniso.h b/cores/esp8266/stdlib_noniso.h index 6d2bcaa28e..4b66dcb558 100644 --- a/cores/esp8266/stdlib_noniso.h +++ b/cores/esp8266/stdlib_noniso.h @@ -1,9 +1,9 @@ -/* +/* stdlib_noniso.h - nonstandard (but usefull) conversion functions Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. This file is part of the esp8266 core for Arduino environment. - + This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either @@ -36,7 +36,7 @@ char* itoa (int val, char *s, int radix); char* ltoa (long val, char *s, int radix); -char* lltoa (long long val, char* str, int slen, unsigned long long radix); +char* lltoa (long long val, char* str, int slen, long long radix); char* utoa (unsigned int val, char *s, int radix); @@ -55,15 +55,20 @@ const char* strrstr(const char*__restrict p_pcString, } // extern "C" -// https://gcc.gnu.org/legacy-ml/gcc/2016-02/msg00001.html extern "C++" { + +#pragma GCC push_options +#pragma GCC optimize("Os") // Os better than O3 or Ofast + +// RFC PR43721 https://gcc.gnu.org/legacy-ml/gcc/2016-02/msg00001.html +// templatized gcc's https://github.com/gcc-mirror/gcc/blob/master/libgcc/udivmodhi4.c template T udivmod(T num, T den, T& mod) { T bit = 1; T res = 0; - while (den < num && bit && !(den & (((T)1) << (sizeof(T)*8 - 1)))) + while (den < num && bit && !(den & (((T)1) << ((sizeof(T) * 8) - 1)))) { den <<= 1; bit <<= 1; @@ -83,5 +88,7 @@ T udivmod(T num, T den, T& mod) } // udivmod } // "C++" +#pragma GCC pop_options + #endif // __cplusplus #endif // STDLIB_NONISO_H From fe0b14c8419f446a801edc30b70fdd9148a3cc3a Mon Sep 17 00:00:00 2001 From: david gauchard Date: Sun, 7 Feb 2021 22:27:34 +0100 Subject: [PATCH 4/7] remove generic udivmod --- cores/esp8266/stdlib_noniso.cpp | 8 ------- cores/esp8266/stdlib_noniso.h | 41 +++------------------------------ 2 files changed, 3 insertions(+), 46 deletions(-) diff --git a/cores/esp8266/stdlib_noniso.cpp b/cores/esp8266/stdlib_noniso.cpp index 851b05d79e..cc61b54044 100644 --- a/cores/esp8266/stdlib_noniso.cpp +++ b/cores/esp8266/stdlib_noniso.cpp @@ -29,16 +29,8 @@ char* ulltoa(unsigned long long val, char* str, int slen, unsigned long long rad *str = 0; do { -#if 1 - // using div and mod in a single call - // String(ULLMAX_LONG, 10) => 354us - unsigned long long mod; - val = udivmod(val, radix, mod); -#else - // String(ULLMAX_LONG, 10) => 374us auto mod = val % radix; val /= radix; -#endif *--str = mod + ((mod > 9) ? ('a' - 10) : '0'); } while (--slen && val); return val? nullptr: str; diff --git a/cores/esp8266/stdlib_noniso.h b/cores/esp8266/stdlib_noniso.h index 4b66dcb558..faebd0f4d4 100644 --- a/cores/esp8266/stdlib_noniso.h +++ b/cores/esp8266/stdlib_noniso.h @@ -52,43 +52,8 @@ const char* strrstr(const char*__restrict p_pcString, const char*__restrict p_pcPattern); #ifdef __cplusplus - } // extern "C" +#endif -extern "C++" { - -#pragma GCC push_options -#pragma GCC optimize("Os") // Os better than O3 or Ofast - -// RFC PR43721 https://gcc.gnu.org/legacy-ml/gcc/2016-02/msg00001.html -// templatized gcc's https://github.com/gcc-mirror/gcc/blob/master/libgcc/udivmodhi4.c -template -T udivmod(T num, T den, T& mod) -{ - T bit = 1; - T res = 0; - - while (den < num && bit && !(den & (((T)1) << ((sizeof(T) * 8) - 1)))) - { - den <<= 1; - bit <<= 1; - } - while (bit) - { - if (num >= den) - { - num -= den; - res |= bit; - } - bit >>= 1; - den >>= 1; - } - mod = num; - return res; -} // udivmod -} // "C++" - -#pragma GCC pop_options - -#endif // __cplusplus -#endif // STDLIB_NONISO_H + +#endif From 54bbe235cc24e9bfe12dd933b062af497c6b8309 Mon Sep 17 00:00:00 2001 From: david gauchard Date: Wed, 10 Feb 2021 22:54:27 +0100 Subject: [PATCH 5/7] radix type, test with charconv --- cores/esp8266/WString.cpp | 33 ++++++++++++++++++++++++++++++--- cores/esp8266/stdlib_noniso.cpp | 10 ++-------- cores/esp8266/stdlib_noniso.h | 4 ++-- 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/cores/esp8266/WString.cpp b/cores/esp8266/WString.cpp index 2cad607117..2d7b9c9650 100644 --- a/cores/esp8266/WString.cpp +++ b/cores/esp8266/WString.cpp @@ -105,25 +105,52 @@ String::String(long long value) { *this = buf; } +String::String(unsigned long long value) { + init(); + char buf[1 + 8 * sizeof(unsigned long long)]; + sprintf(buf, "%llu", value); + *this = buf; +} + +#if 1 +// slower version (374us vs charconv:230us) +// -880 flash bytes (vs charconv) +// -256 rodata bytes (vs charconv) + String::String(long long value, unsigned char base) { init(); char buf[2 + 8 * sizeof(long long)]; *this = lltoa(value, buf, sizeof(buf), base); } -String::String(unsigned long long value) { +String::String(unsigned long long value, unsigned char base) { init(); char buf[1 + 8 * sizeof(unsigned long long)]; - sprintf(buf, "%llu", value); + *this = ulltoa(value, buf, sizeof(buf), base); +} + +#else +// faster version (230us vs lltoa:374us) +// +880 flash bytes (vs lltoa) +// +256 rodata bytes (vs lltoa) + +#include +String::String(long long value, unsigned char base) { + init(); + char buf[2 + 8 * sizeof(long long)]; + std::to_chars(buf, buf + sizeof(buf) - 1, value, base); *this = buf; } String::String(unsigned long long value, unsigned char base) { init(); char buf[1 + 8 * sizeof(unsigned long long)]; - *this = ulltoa(value, buf, sizeof(buf), base); + std::to_chars(buf, buf + sizeof(buf) - 1, value, base); + *this = buf; } +#endif + String::String(float value, unsigned char decimalPlaces) { init(); char buf[33]; diff --git a/cores/esp8266/stdlib_noniso.cpp b/cores/esp8266/stdlib_noniso.cpp index cc61b54044..6f90306caa 100644 --- a/cores/esp8266/stdlib_noniso.cpp +++ b/cores/esp8266/stdlib_noniso.cpp @@ -19,11 +19,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - #include "stdlib_noniso.h" // fill backwards -char* ulltoa(unsigned long long val, char* str, int slen, unsigned long long radix) +char* ulltoa(unsigned long long val, char* str, int slen, unsigned int radix) { str += --slen; *str = 0; @@ -36,14 +35,9 @@ char* ulltoa(unsigned long long val, char* str, int slen, unsigned long long rad return val? nullptr: str; } -char* lltoa (long long val, char* str, int slen, long long radix) +char* lltoa (long long val, char* str, int slen, unsigned int radix) { bool neg; - if (radix < 0) - { - radix = -radix; - val = -val; - } if (val < 0) { val = -val; diff --git a/cores/esp8266/stdlib_noniso.h b/cores/esp8266/stdlib_noniso.h index faebd0f4d4..2bacc2cb2c 100644 --- a/cores/esp8266/stdlib_noniso.h +++ b/cores/esp8266/stdlib_noniso.h @@ -36,13 +36,13 @@ char* itoa (int val, char *s, int radix); char* ltoa (long val, char *s, int radix); -char* lltoa (long long val, char* str, int slen, long long radix); +char* lltoa (long long val, char* str, int slen, unsigned int radix); char* utoa (unsigned int val, char *s, int radix); char* ultoa (unsigned long val, char *s, int radix); -char* ulltoa (unsigned long long val, char* str, int slen, unsigned long long radix); +char* ulltoa (unsigned long long val, char* str, int slen, unsigned int radix); char* dtostrf (double val, signed char width, unsigned char prec, char *s); From 5c573cc004a395b8b491ecdd7dc0ba6be1a1e18b Mon Sep 17 00:00:00 2001 From: david gauchard Date: Fri, 12 Feb 2021 01:33:20 +0100 Subject: [PATCH 6/7] remove charconv, add comment --- cores/esp8266/WString.cpp | 27 --------------------------- cores/esp8266/stdlib_noniso.cpp | 6 +++++- 2 files changed, 5 insertions(+), 28 deletions(-) diff --git a/cores/esp8266/WString.cpp b/cores/esp8266/WString.cpp index 2d7b9c9650..8cff99a217 100644 --- a/cores/esp8266/WString.cpp +++ b/cores/esp8266/WString.cpp @@ -112,11 +112,6 @@ String::String(unsigned long long value) { *this = buf; } -#if 1 -// slower version (374us vs charconv:230us) -// -880 flash bytes (vs charconv) -// -256 rodata bytes (vs charconv) - String::String(long long value, unsigned char base) { init(); char buf[2 + 8 * sizeof(long long)]; @@ -129,28 +124,6 @@ String::String(unsigned long long value, unsigned char base) { *this = ulltoa(value, buf, sizeof(buf), base); } -#else -// faster version (230us vs lltoa:374us) -// +880 flash bytes (vs lltoa) -// +256 rodata bytes (vs lltoa) - -#include -String::String(long long value, unsigned char base) { - init(); - char buf[2 + 8 * sizeof(long long)]; - std::to_chars(buf, buf + sizeof(buf) - 1, value, base); - *this = buf; -} - -String::String(unsigned long long value, unsigned char base) { - init(); - char buf[1 + 8 * sizeof(unsigned long long)]; - std::to_chars(buf, buf + sizeof(buf) - 1, value, base); - *this = buf; -} - -#endif - String::String(float value, unsigned char decimalPlaces) { init(); char buf[33]; diff --git a/cores/esp8266/stdlib_noniso.cpp b/cores/esp8266/stdlib_noniso.cpp index 6f90306caa..6427547514 100644 --- a/cores/esp8266/stdlib_noniso.cpp +++ b/cores/esp8266/stdlib_noniso.cpp @@ -21,7 +21,10 @@ #include "stdlib_noniso.h" -// fill backwards +// ulltoa() is slower than std::to_char() (1.6 times) +// but is smaller by ~800B/flash and ~250B/rodata + +// ulltoa fills str backwards and can return a pointer different from str char* ulltoa(unsigned long long val, char* str, int slen, unsigned int radix) { str += --slen; @@ -35,6 +38,7 @@ char* ulltoa(unsigned long long val, char* str, int slen, unsigned int radix) return val? nullptr: str; } +// lltoa fills str backwards and can return a pointer different from str char* lltoa (long long val, char* str, int slen, unsigned int radix) { bool neg; From 644ae09789eeebbfc539548834491319818e2e69 Mon Sep 17 00:00:00 2001 From: david gauchard Date: Fri, 12 Feb 2021 01:38:30 +0100 Subject: [PATCH 7/7] fix corner case --- cores/esp8266/stdlib_noniso.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cores/esp8266/stdlib_noniso.cpp b/cores/esp8266/stdlib_noniso.cpp index 6427547514..2b24681d3d 100644 --- a/cores/esp8266/stdlib_noniso.cpp +++ b/cores/esp8266/stdlib_noniso.cpp @@ -54,7 +54,7 @@ char* lltoa (long long val, char* str, int slen, unsigned int radix) char* ret = ulltoa(val, str, slen, radix); if (neg) { - if (ret == str) + if (ret == str || ret == nullptr) return nullptr; *--ret = '-'; }