diff --git a/cores/esp8266/WString.cpp b/cores/esp8266/WString.cpp index 07ab99b2cfa113c6c1163dbca94ae87392d9f1e6..8cff99a21700f24cb366269d8ef06151daafe0fa 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(unsigned long long value) { + init(); + char buf[1 + 8 * sizeof(unsigned long long)]; + sprintf(buf, "%llu", 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, 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 dcb0982387f57130b12c8495d149f5f7e4156c30..beae31a9ab9997cc885ca6edf2507d5553038834 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 eddc7b06fe142e9ca0a98d52082fe8eac207d27b..858f5e1118e02628152438b131c73086ddfed50a 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 0000000000000000000000000000000000000000..2b24681d3d267d52bfb5b3c7feae50f552e1dfff --- /dev/null +++ b/cores/esp8266/stdlib_noniso.cpp @@ -0,0 +1,62 @@ +/* + 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" + +// 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; + *str = 0; + do + { + auto mod = val % radix; + val /= radix; + *--str = mod + ((mod > 9) ? ('a' - 10) : '0'); + } while (--slen && val); + 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; + if (val < 0) + { + val = -val; + neg = true; + } + else + { + neg = false; + } + char* ret = ulltoa(val, str, slen, radix); + if (neg) + { + if (ret == str || ret == nullptr) + return nullptr; + *--ret = '-'; + } + return ret; +} diff --git a/cores/esp8266/stdlib_noniso.h b/cores/esp8266/stdlib_noniso.h index 053ea479489b91218e4c2a854e1b359e57cb101d..2bacc2cb2c086a1c4c53002d6caab1624b24f185 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,10 +36,14 @@ 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 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 int 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 4bb6e83b32b03390c65a55823445b2645b98d042..cc100618581c3ee1d2b1cb51ef0884fb8e3ed107 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 1150ba59134653376adfe86d9a6ece90119416b7..e080be9507ca1aef8ecf4be9d943909e4cc10faf 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");