From 02ed4f0ebb1595724bcf9521f1de03afe3b70c2f Mon Sep 17 00:00:00 2001 From: Billy Donahue Date: Tue, 6 Feb 2018 01:02:43 -0500 Subject: [PATCH] String relational operators The String class has an incomplete set of relational operators with `const char*`. The 6 operators `==`,`!=`,`<`,`>`,`<=`,`>=` must be defined between String and String, but also between String and `const char*`. The motivation is to treat left and right operands symmetrically. str == "hello" works, but swapping arguments to "hello" == str doesn't, which is a potential user surprise. As String is implicitly convertible from `const char*`, but this incurs a "strdup". So it also makes sense to provide relational operators directly with const char* to avoid the expensive promotion of const char* to temporary String, just to do a string value comparison. Resolves: #7139 --- .../arduino/avr/cores/arduino/WString.cpp | 30 +++++++------------ hardware/arduino/avr/cores/arduino/WString.h | 30 ++++++++++++++----- 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/hardware/arduino/avr/cores/arduino/WString.cpp b/hardware/arduino/avr/cores/arduino/WString.cpp index f2572d60883..a7c4e6cf444 100644 --- a/hardware/arduino/avr/cores/arduino/WString.cpp +++ b/hardware/arduino/avr/cores/arduino/WString.cpp @@ -441,6 +441,16 @@ int String::compareTo(const String &s) const return strcmp(buffer, s.buffer); } +int String::compareTo(const char *cstr) const +{ + if (!buffer || !cstr) { + if (cstr && !*cstr) return 0 - *(unsigned char *)cstr; + if (buffer && len > 0) return *(unsigned char *)buffer; + return 0; + } + return strcmp(buffer, cstr); +} + unsigned char String::equals(const String &s2) const { return (len == s2.len && compareTo(s2) == 0); @@ -453,26 +463,6 @@ unsigned char String::equals(const char *cstr) const return strcmp(buffer, cstr) == 0; } -unsigned char String::operator<(const String &rhs) const -{ - return compareTo(rhs) < 0; -} - -unsigned char String::operator>(const String &rhs) const -{ - return compareTo(rhs) > 0; -} - -unsigned char String::operator<=(const String &rhs) const -{ - return compareTo(rhs) <= 0; -} - -unsigned char String::operator>=(const String &rhs) const -{ - return compareTo(rhs) >= 0; -} - unsigned char String::equalsIgnoreCase( const String &s2 ) const { if (this == &s2) return 1; diff --git a/hardware/arduino/avr/cores/arduino/WString.h b/hardware/arduino/avr/cores/arduino/WString.h index 77709c3ba42..047a2e3cd21 100644 --- a/hardware/arduino/avr/cores/arduino/WString.h +++ b/hardware/arduino/avr/cores/arduino/WString.h @@ -137,16 +137,30 @@ class String // comparison (only works w/ Strings and "strings") operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; } int compareTo(const String &s) const; + int compareTo(const char *cstr) const; unsigned char equals(const String &s) const; unsigned char equals(const char *cstr) const; - unsigned char operator == (const String &rhs) const {return equals(rhs);} - unsigned char operator == (const char *cstr) const {return equals(cstr);} - unsigned char operator != (const String &rhs) const {return !equals(rhs);} - unsigned char operator != (const char *cstr) const {return !equals(cstr);} - unsigned char operator < (const String &rhs) const; - unsigned char operator > (const String &rhs) const; - unsigned char operator <= (const String &rhs) const; - unsigned char operator >= (const String &rhs) const; + + friend unsigned char operator == (const String &a, const String &b) { return a.equals(b); } + friend unsigned char operator == (const String &a, const char *b) { return a.equals(b); } + friend unsigned char operator == (const char *a, const String &b) { return b == a; } + friend unsigned char operator < (const String &a, const String &b) { return a.compareTo(b) < 0; } + friend unsigned char operator < (const String &a, const char *b) { return a.compareTo(b) < 0; } + friend unsigned char operator < (const char *a, const String &b) { return b.compareTo(a) > 0; } + + friend unsigned char operator != (const String &a, const String &b) { return !(a == b); } + friend unsigned char operator != (const String &a, const char *b) { return !(a == b); } + friend unsigned char operator != (const char *a, const String &b) { return !(a == b); } + friend unsigned char operator > (const String &a, const String &b) { return b < a; } + friend unsigned char operator > (const String &a, const char *b) { return b < a; } + friend unsigned char operator > (const char *a, const String &b) { return b < a; } + friend unsigned char operator <= (const String &a, const String &b) { return !(b < a); } + friend unsigned char operator <= (const String &a, const char *b) { return !(b < a); } + friend unsigned char operator <= (const char *a, const String &b) { return !(b < a); } + friend unsigned char operator >= (const String &a, const String &b) { return !(a < b); } + friend unsigned char operator >= (const String &a, const char *b) { return !(a < b); } + friend unsigned char operator >= (const char *a, const String &b) { return !(a < b); } + unsigned char equalsIgnoreCase(const String &s) const; unsigned char startsWith( const String &prefix) const; unsigned char startsWith(const String &prefix, unsigned int offset) const;