NOTE:
These are a little sketchy...I'll fill in details 'soon'.
short String::compare(const String & other) const { const char *left, *right; short retval; left = string; right = other.string; if ((left == nullptr) || (right == nullptr)) { retval = ((left == nullptr) && (right == nullptr)) ? 0 : (((left == nullptr) && (right != nullptr)) ? -1 : 1); } else { if ((flags & case_on) != 0) // should we consider the other // guy's case sensitivity, too? { while ((*left != EOS) && ((*left-*right)==0)) { left++; right++; } } else { while ((*left != EOS) && ((toupper(*left)-toupper(*right))==0)) { left++; right++; } } retval = ((flags & case_on) != 0) ? (*left-*right) : (tolower(*left)-tolower(*right)); } return retval; }
short String::compare(const char other[]) const { return compare(String(other)); }
short String::compare(const char other) const { return compare(String(other)); }
short compare(const char other[], const String & me) { return String(other).compare(me); }
short compare(const char other, const String & me) { return String(other).compare(me); }
don't forget that there are 5 versions of each operator:
String op String String op Cstring String op char Cstring op String char op String
(just like above for compare)
bool String::operator==(const String & right) const { return ((string == nullptr) && (right.string == nullptr)) || ((string != nullptr) && (right.string != nullptr) && ((flags & case_on) != 0) ? (strcmp(string,right.string) == 0) : (StrCmp(string,right.string) == 0)); }Note that we've only taken account of the left-hand operand's case sensitivity flag. Should the right-hand String's flag be considered? (Food for thought...)
bool String::operator==(const String & right) const { return compare(right) == 0; }
bool String::operator<(const String & right) const { return ((string == nullptr) && (right.string != nullptr)) || ((string != nullptr) && (right.string != nullptr) && ((flags & case_on) != 0) ? (strcmp(string,right.string) < 0) : (StrCmp(string,right.string) < 0)); }
bool String::operator<(const String & right) const { return compare(right) < 0; }
bool String::operator>(const String & right) const { return ((string != nullptr) && (right.string == nullptr)) || ((string != nullptr) && (right.string != nullptr) && ((flags & case_on) != 0) ? (strcmp(string,right.string) > 0) : (StrCmp(string,right.string) > 0)); }
bool String::operator>(const String & right) const { return compare(right) > 0; }
whichever way you go above, this is almost always:
bool String::operator!=(const String & right) const { return !(*this == right); }
reusing the == definition and logically negating the results. This isn't terribly efficient, but it does work and saves programmer time and debugging effort.
and so on through the Cstring and char versions.
likewise with these two:
bool String::operator>=(const String & right) const { return !(*this < right); } bool String::operator<=(const String & right) const { return !(*this > right); }
and so on through the Cstring and char versions. (But you do still need 5 versions of each operator!!!)