Explorar o código

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.
Ibrahn Sahir %!s(int64=6) %!d(string=hai) anos
pai
achega
cbb396c006
Modificáronse 5 ficheiros con 105 adicións e 19 borrados
  1. 20 0
      core/cowdata.h
  2. 6 2
      core/ustring.cpp
  3. 2 1
      core/ustring.h
  4. 1 16
      core/vector.h
  5. 76 0
      main/tests/test_string.cpp

+ 20 - 0
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<T> &p_from) { _ref(p_from); };
@@ -315,6 +317,24 @@ Error CowData<T>::resize(int p_size) {
 	return OK;
 }
 
+template <class T>
+int CowData<T>::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 <class T>
 void CowData<T>::_ref(const CowData *p_from) {
 	_ref(*p_from);

+ 6 - 2
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<String> &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;
 	}
 

+ 2 - 1
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

+ 1 - 16
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<T> &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) {

+ 76 - 0
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
 
 };