From cbb396c0064d77ec50a524241d22746c8b69bbdb Mon Sep 17 00:00:00 2001 From: Ibrahn Sahir Date: Mon, 7 Jan 2019 17:02:55 +0000 Subject: [PATCH] Repair String lstrip and rstrip. Background: lstrip and rstrip were broken by changes to String in: 0e29f7974b59e4440cf02e1388fb9d8ab2b5c5fd which removed it's access to Vector::find(CharType). Moved Vector's find up into CowData so it can be shared by Vector and String. Added String::find_char using CowData::find. Implemented rstrip and lstrip using find_char. Added a few tests for String rstrip and lstrip. --- core/cowdata.h | 20 ++++++++++ core/ustring.cpp | 8 +++- core/ustring.h | 3 +- core/vector.h | 17 +-------- main/tests/test_string.cpp | 76 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 105 insertions(+), 19 deletions(-) diff --git a/core/cowdata.h b/core/cowdata.h index 319e61d261e..3e40ad0f4b5 100644 --- a/core/cowdata.h +++ b/core/cowdata.h @@ -179,6 +179,8 @@ public: return OK; }; + int find(const T &p_val, int p_from = 0) const; + _FORCE_INLINE_ CowData(); _FORCE_INLINE_ ~CowData(); _FORCE_INLINE_ CowData(CowData &p_from) { _ref(p_from); }; @@ -315,6 +317,24 @@ Error CowData::resize(int p_size) { return OK; } +template +int CowData::find(const T &p_val, int p_from) const { + int ret = -1; + + if (p_from < 0 || size() == 0) { + return ret; + } + + for (int i = p_from; i < size(); i++) { + if (get(i) == p_val) { + ret = i; + break; + } + } + + return ret; +} + template void CowData::_ref(const CowData *p_from) { _ref(*p_from); diff --git a/core/ustring.cpp b/core/ustring.cpp index 311aa52d402..c1888c87a7b 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -2393,6 +2393,10 @@ int String::find(const char *p_str, int p_from) const { return -1; } +int String::find_char(CharType p_char, int p_from) const { + return _cowdata.find(p_char, p_from); +} + int String::findmk(const Vector &p_keys, int p_from, int *r_key) const { if (p_from < 0) @@ -3063,7 +3067,7 @@ String String::lstrip(const String &p_chars) const { for (beg = 0; beg < len; beg++) { - if (p_chars.find(&ptr()[beg]) == -1) + if (p_chars.find_char(get(beg)) == -1) break; } @@ -3080,7 +3084,7 @@ String String::rstrip(const String &p_chars) const { for (end = len - 1; end >= 0; end--) { - if (p_chars.find(&ptr()[end]) == -1) + if (p_chars.find_char(get(end)) == -1) break; } diff --git a/core/ustring.h b/core/ustring.h index 1773e94b0e3..5ec5c79e2d6 100644 --- a/core/ustring.h +++ b/core/ustring.h @@ -196,7 +196,8 @@ public: /* complex helpers */ String substr(int p_from, int p_chars) const; int find(const String &p_str, int p_from = 0) const; ///< return <0 if failed - int find(const char *p_str, int p_from) const; ///< return <0 if failed + int find(const char *p_str, int p_from = 0) const; ///< return <0 if failed + int find_char(CharType p_char, int p_from = 0) const; ///< return <0 if failed int find_last(const String &p_str) const; ///< return <0 if failed int findn(const String &p_str, int p_from = 0) const; ///< return <0 if failed, case insensitive int rfind(const String &p_str, int p_from = -1) const; ///< return <0 if failed diff --git a/core/vector.h b/core/vector.h index 74dc9191d81..90b3d908268 100644 --- a/core/vector.h +++ b/core/vector.h @@ -84,6 +84,7 @@ public: Error resize(int p_size) { return _cowdata.resize(p_size); } _FORCE_INLINE_ const T &operator[](int p_index) const { return _cowdata.get(p_index); } Error insert(int p_pos, const T &p_val) { return _cowdata.insert(p_pos, p_val); } + int find(const T &p_val, int p_from = 0) const { return _cowdata.find(p_val, p_from); } void append_array(const Vector &p_other); @@ -115,22 +116,6 @@ public: insert(i, p_val); } - int find(const T &p_val, int p_from = 0) const { - int ret = -1; - if (p_from < 0 || size() == 0) - return ret; - - for (int i = p_from; i < size(); i++) { - - if (ptr()[i] == p_val) { - ret = i; - break; - }; - }; - - return ret; - } - _FORCE_INLINE_ Vector() {} _FORCE_INLINE_ Vector(const Vector &p_from) { _cowdata._ref(p_from._cowdata); } inline Vector &operator=(const Vector &p_from) { diff --git a/main/tests/test_string.cpp b/main/tests/test_string.cpp index b4aeb4d2154..511646db0a5 100644 --- a/main/tests/test_string.cpp +++ b/main/tests/test_string.cpp @@ -971,6 +971,81 @@ bool test_31() { return state; }; +bool test_32() { + +#define STRIP_TEST(x) \ + { \ + bool success = x; \ + state = state && success; \ + if (!success) { \ + OS::get_singleton()->print("\tfailed at: %s\n", #x); \ + } \ + } + + OS::get_singleton()->print("\n\nTest 32: lstrip and rstrip\n"); + bool state = true; + + // strip none + STRIP_TEST(String("abc").lstrip("") == "abc"); + STRIP_TEST(String("abc").rstrip("") == "abc"); + // strip one + STRIP_TEST(String("abc").lstrip("a") == "bc"); + STRIP_TEST(String("abc").rstrip("c") == "ab"); + // strip lots + STRIP_TEST(String("bababbababccc").lstrip("ab") == "ccc"); + STRIP_TEST(String("aaabcbcbcbbcbbc").rstrip("cb") == "aaa"); + // strip empty string + STRIP_TEST(String("").lstrip("") == ""); + STRIP_TEST(String("").rstrip("") == ""); + // strip to empty string + STRIP_TEST(String("abcabcabc").lstrip("bca") == ""); + STRIP_TEST(String("abcabcabc").rstrip("bca") == ""); + // don't strip wrong end + STRIP_TEST(String("abc").lstrip("c") == "abc"); + STRIP_TEST(String("abca").lstrip("a") == "bca"); + STRIP_TEST(String("abc").rstrip("a") == "abc"); + STRIP_TEST(String("abca").rstrip("a") == "abc"); + // in utf-8 "¿" has the same first byte as "µ" + // and the same second as "ÿ" + STRIP_TEST(String::utf8("¿").lstrip(String::utf8("µÿ")) == String::utf8("¿")); + STRIP_TEST(String::utf8("¿").rstrip(String::utf8("µÿ")) == String::utf8("¿")); + STRIP_TEST(String::utf8("µ¿ÿ").lstrip(String::utf8("µÿ")) == String::utf8("¿ÿ")); + STRIP_TEST(String::utf8("µ¿ÿ").rstrip(String::utf8("µÿ")) == String::utf8("µ¿")); + + // the above tests repeated with additional superfluous strip chars + + // strip none + STRIP_TEST(String("abc").lstrip("qwjkl") == "abc"); + STRIP_TEST(String("abc").rstrip("qwjkl") == "abc"); + // strip one + STRIP_TEST(String("abc").lstrip("qwajkl") == "bc"); + STRIP_TEST(String("abc").rstrip("qwcjkl") == "ab"); + // strip lots + STRIP_TEST(String("bababbababccc").lstrip("qwabjkl") == "ccc"); + STRIP_TEST(String("aaabcbcbcbbcbbc").rstrip("qwcbjkl") == "aaa"); + // strip empty string + STRIP_TEST(String("").lstrip("qwjkl") == ""); + STRIP_TEST(String("").rstrip("qwjkl") == ""); + // strip to empty string + STRIP_TEST(String("abcabcabc").lstrip("qwbcajkl") == ""); + STRIP_TEST(String("abcabcabc").rstrip("qwbcajkl") == ""); + // don't strip wrong end + STRIP_TEST(String("abc").lstrip("qwcjkl") == "abc"); + STRIP_TEST(String("abca").lstrip("qwajkl") == "bca"); + STRIP_TEST(String("abc").rstrip("qwajkl") == "abc"); + STRIP_TEST(String("abca").rstrip("qwajkl") == "abc"); + // in utf-8 "¿" has the same first byte as "µ" + // and the same second as "ÿ" + STRIP_TEST(String::utf8("¿").lstrip(String::utf8("qwaµÿjkl")) == String::utf8("¿")); + STRIP_TEST(String::utf8("¿").rstrip(String::utf8("qwaµÿjkl")) == String::utf8("¿")); + STRIP_TEST(String::utf8("µ¿ÿ").lstrip(String::utf8("qwaµÿjkl")) == String::utf8("¿ÿ")); + STRIP_TEST(String::utf8("µ¿ÿ").rstrip(String::utf8("qwaµÿjkl")) == String::utf8("µ¿")); + + return state; + +#undef STRIP_TEST +} + typedef bool (*TestFunc)(void); TestFunc test_funcs[] = { @@ -1006,6 +1081,7 @@ TestFunc test_funcs[] = { test_29, test_30, test_31, + test_32, 0 };