Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WString: unify numeric conversion and fix assignments #8526

Merged
merged 9 commits into from
Apr 5, 2022
Prev Previous commit
Next Next commit
trying to reduce the instances of where we specify the default base /…
… decimalPlaces

branch via if (base == 10) { sprintf(...) } else { ... } instead of separate funcs
reuse the constructor for numeric types where it's possible
mcspr committed Mar 30, 2022
commit 4206518be226a95d34b2038a0dd78e28a648fe5e
133 changes: 22 additions & 111 deletions cores/esp8266/WString.cpp
Original file line number Diff line number Diff line change
@@ -45,10 +45,6 @@ static String toString(unsigned char value, unsigned char base) {
return out;
}

static String toString(unsigned char value) {
return toString(value, 10);
}

static String toString(int value, unsigned char base) {
String out;

@@ -63,10 +59,6 @@ static String toString(int value, unsigned char base) {
return out;
}

static String toString(int value) {
return toString(value, 10);
}

static String toString(unsigned int value, unsigned char base) {
String out;

@@ -77,10 +69,6 @@ static String toString(unsigned int value, unsigned char base) {
return out;
}

static String toString(unsigned int value) {
return toString(value, 10);
}

static String toString(long value, unsigned char base) {
String out;

@@ -95,10 +83,6 @@ static String toString(long value, unsigned char base) {
return out;
}

static String toString(long value) {
return toString(value, 10);
}

static String toString(unsigned long value, unsigned char base) {
String out;

@@ -109,25 +93,18 @@ static String toString(unsigned long value, unsigned char base) {
return out;
}

static String toString(unsigned long value) {
return toString(value, 10);
}
// TODO: {u,}lltoa don't guarantee that the buffer is usable directly, one should always use the returned pointer

static String toString(long long value, unsigned char base) {
String out;

char buf[2 + 8 * sizeof(long long)];
out = lltoa(value, buf, sizeof(buf), base);

return out;
}

static String toString(long long value) {
String out;

char buf[2 + 8 * sizeof(long long)];
sprintf(buf, "%lld", value);
out = buf;
if (base == 10) {
sprintf(buf, "%lld", value);
out = buf;
} else {
out = lltoa(value, buf, sizeof(buf), base);
}

return out;
}
@@ -136,17 +113,12 @@ static String toString(unsigned long long value, unsigned char base) {
String out;

char buf[1 + 8 * sizeof(unsigned long long)];
out = ulltoa(value, buf, sizeof(buf), base);

return out;
}

static String toString(unsigned long long value) {
String out;

char buf[1 + 8 * sizeof(unsigned long long)];
sprintf(buf, "%llu", value);
out = buf;
if (base == 10) {
sprintf(buf, "%llu", value);
out = buf;
} else {
out = ulltoa(value, buf, sizeof(buf), base);
}

return out;
}
@@ -160,10 +132,6 @@ static String toString(float value, unsigned char decimalPlaces) {
return out;
}

static String toString(float value) {
return toString(value, 2);
}

static String toString(double value, unsigned char decimalPlaces) {
String out;

@@ -173,10 +141,6 @@ static String toString(double value, unsigned char decimalPlaces) {
return out;
}

static String toString(double value) {
return toString(value, 2);
}

/*********************************************/
/* Constructors */
/*********************************************/
@@ -226,18 +190,10 @@ String::String(long long value, unsigned char base) :
String(toString(value, base))
{}

String::String(long long value) :
String(toString(value))
{}

String::String(unsigned long long value, unsigned char base) :
String(toString(value, base))
{}

String::String(unsigned long long value) :
String(toString(value))
{}

String::String(float value, unsigned char decimalPlaces) :
String(toString(value, decimalPlaces))
{}
@@ -388,51 +344,6 @@ String &String::operator =(char c) {
return *this;
}

String &String::operator =(unsigned char value) {
*this = toString(value);
return *this;
}

String &String::operator =(int value) {
*this = toString(value);
return *this;
}

String &String::operator =(unsigned int value) {
*this = toString(value);
return *this;
}

String &String::operator =(long value) {
*this = toString(value);
return *this;
}

String &String::operator =(unsigned long value) {
*this = toString(value);
return *this;
}

String &String::operator =(long long value) {
*this = toString(value);
return *this;
}

String &String::operator =(unsigned long long value) {
*this = toString(value);
return *this;
}

String &String::operator =(float value) {
*this = toString(value);
return *this;
}

String &String::operator =(double value) {
*this = toString(value);
return *this;
}

/*********************************************/
/* concat */
/*********************************************/
@@ -482,39 +393,39 @@ bool String::concat(char c) {
}

bool String::concat(unsigned char num) {
return concat(toString(num));
return concat(String(num));
}

bool String::concat(int num) {
return concat(toString(num));
return concat(String(num));
}

bool String::concat(unsigned int num) {
return concat(toString(num));
return concat(String(num));
}

bool String::concat(long num) {
return concat(toString(num));
return concat(String(num));
}

bool String::concat(unsigned long num) {
return concat(toString(num));
return concat(String(num));
}

bool String::concat(long long num) {
return concat(toString(num));
return concat(String(num));
}

bool String::concat(unsigned long long num) {
return concat(toString(num));
return concat(String(num));
}

bool String::concat(float num) {
return concat(toString(num));
return concat(String(num));
}

bool String::concat(double num) {
return concat(toString(num));
return concat(String(num));
}

bool String::concat(const __FlashStringHelper *str) {
114 changes: 92 additions & 22 deletions cores/esp8266/WString.h
Original file line number Diff line number Diff line change
@@ -64,17 +64,52 @@ class String {
sso.len = 1;
sso.isHeap = 0;
}
explicit String(unsigned char, unsigned char base = 10);
explicit String(int, unsigned char base = 10);
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);
Comment on lines -67 to -77
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is mostly for verbosity. Due to the amount of magic ctors we have... we can't really have std::initializer_list<char> ctor as well, since everything would be converted into it

e.g.

String(std::initializer_list<char> data) {
    concat(data.begin(), data.size());
}

So only purpose of the below is to allow to omit String{...} in front of the arguments list. Where we suppose to have explicit for String(int, base) overload

core/test_string.cpp:620:51: error: converting to ‘String’ from initializer list would use explicit constructor ‘String::String(int, unsigned char)’
  620 |     String strings[] {{62, 10}, {63, 10}, {64, 10}};
      |                                                   ^

Could be reverted though.


String(unsigned char, unsigned char base);
explicit String(unsigned char value) :
String(value, 10)
{}

String(int, unsigned char base);
explicit String(int value) :
String(value, 10)
{}

String(unsigned int, unsigned char base);
explicit String(unsigned int value) :
String(value, 10)
{}

String(long, unsigned char base);
explicit String(long value) :
String(value, 10)
{}

String(unsigned long, unsigned char base);
explicit String(unsigned long value) :
String(value, 10)
{}

String(long long, unsigned char base);
explicit String(long long value) :
String(value, 10)
{}

String(unsigned long long, unsigned char base);
explicit String(unsigned long long value) :
String(value, 10)
{}

String(float, unsigned char decimalPlaces);
explicit String(float value) :
String(value, 2)
{}

String(double, unsigned char decimalPlaces);
explicit String(double value) :
String(value, 2)
{}

~String() {
invalidate();
}
@@ -99,17 +134,52 @@ class String {
String &operator =(String &&rval) noexcept;
String &operator =(const char *cstr);
String &operator =(const __FlashStringHelper *str);

String &operator =(char c);
String &operator =(unsigned char c);
String &operator =(int num);
String &operator =(unsigned int num);
String &operator =(long num);
String &operator =(unsigned long num);
String &operator =(long long num);
String &operator =(unsigned long long num);
String &operator =(float num);
String &operator =(double num);

String &operator =(unsigned char value) {
*this = String(value);
return *this;
}

String &operator =(int value) {
*this = String(value);
return *this;
}

String &operator =(unsigned int value) {
*this = String(value);
return *this;
}

String &operator =(long value) {
*this = String(value);
return *this;
}

String &operator =(unsigned long value) {
*this = String(value);
return *this;
}

String &operator =(long long value) {
*this = String(value);
return *this;
}

String &operator =(unsigned long long value) {
*this = String(value);
return *this;
}

String &operator =(float value) {
*this = String(value);
return *this;
}

String &operator =(double value) {
*this = String(value);
return *this;
}

// concatenate (works w/ built-in types, same as assignment)

@@ -120,8 +190,8 @@ class String {
bool concat(const char *cstr);
bool concat(const char *cstr, unsigned int length);
bool concat(const __FlashStringHelper *str);

bool concat(char c);

bool concat(unsigned char c);
bool concat(int num);
bool concat(unsigned int num);