[Scummvm-git-logs] scummvm master -> f7c2d14587c8ed531acd4765130a22f535183072

sev- noreply at scummvm.org
Mon Jan 8 22:39:30 UTC 2024


This automated email contains information about 8 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
15a96f8c33 COMMON: Modify U32String::itoa() to use value_type instead of char
4abc229268 COMMON: Unify implementations of String::replace()
6c06ae6125 COMMON: Simplify = and += operators for U32String and DBCSString
dce0f057ec COMMON: Optimize U32String::vformat a bit by appending chars instead of inserting them
a8183c7734 COMMON: Insert all characters in one go with String::insertString()
0a4fec83c0 COMMON: Improve removing characters from strings
35125f5509 COMMON: Use more standard library functions in String classes
f7c2d14587 COMMON: Move all find and replace functions into BaseString


Commit: 15a96f8c331daf8404fdc0aa87642164a152720b
    https://github.com/scummvm/scummvm/commit/15a96f8c331daf8404fdc0aa87642164a152720b
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2024-01-08T23:39:22+01:00

Commit Message:
COMMON: Modify U32String::itoa() to use value_type instead of char

Changed paths:
    common/ustr.cpp
    common/ustr.h


diff --git a/common/ustr.cpp b/common/ustr.cpp
index 184a0cacfef..833a4e98c16 100644
--- a/common/ustr.cpp
+++ b/common/ustr.cpp
@@ -186,7 +186,7 @@ int U32String::vformat(const value_type *fmt, const value_type *fmtEnd, U32Strin
 	int pos = 0;
 	int tempPos = 0;
 
-	char buffer[512];
+	value_type buffer[512];
 
 	while (fmt != fmtEnd) {
 		ch = *fmt++;
@@ -215,7 +215,7 @@ int U32String::vformat(const value_type *fmt, const value_type *fmtEnd, U32Strin
 			case 'd':
 				int_temp = va_arg(args, int);
 				itoa(int_temp, buffer, 10);
-				len = strlen(buffer);
+				len = cStrLen(buffer);
 				length += len;
 
 				output.insertString(buffer, pos);
@@ -224,7 +224,7 @@ int U32String::vformat(const value_type *fmt, const value_type *fmtEnd, U32Strin
 			case 'u':
 				uint_temp = va_arg(args, uint);
 				uitoa(uint_temp, buffer, 10);
-				len = strlen(buffer);
+				len = cStrLen(buffer);
 				length += len;
 
 				output.insertString(buffer, pos);
@@ -301,7 +301,7 @@ void U32String::replace(uint32 posOri, uint32 countOri, const u32char_type_t *st
 
 }
 
-char* U32String::itoa(int num, char* str, uint base) {
+U32String::value_type* U32String::itoa(int num, value_type* str, uint base) {
 	if (num < 0) {
 		str[0] = '-';
 		uitoa(-num, str + 1, base);
@@ -312,7 +312,7 @@ char* U32String::itoa(int num, char* str, uint base) {
 	return str;
 }
 
-char* U32String::uitoa(uint num, char* str, uint base) {
+U32String::value_type* U32String::uitoa(uint num, value_type* str, uint base) {
 	int i = 0;
 
 	if (num) {
@@ -333,7 +333,7 @@ char* U32String::uitoa(uint num, char* str, uint base) {
 
 	// reverse the string
 	while (k < j) {
-		char temp = str[k];
+		value_type temp = str[k];
 		str[k] = str[j];
 		str[j] = temp;
 		k++;
diff --git a/common/ustr.h b/common/ustr.h
index 1ffa8fc555e..9d856ac9eed 100644
--- a/common/ustr.h
+++ b/common/ustr.h
@@ -220,13 +220,13 @@ private:
 	 * Helper function for vformat. Convert an int to a string.
 	 * Minimal implementation, only for base 10.
 	 */
-	static char* itoa(int num, char* str, uint base);
+	static value_type* itoa(int num, value_type* str, uint base);
 
 	/**
 	 * Helper function for vformat. Convert an unsigned int to a string.
 	 * Minimal implementation, only for base 10.
 	 */
-	static char* uitoa(uint num, char* str, uint base);
+	static value_type* uitoa(uint num, value_type* str, uint base);
 
 	void decodeInternal(const char *str, uint32 len, CodePage page);
 	void decodeOneByte(const char *str, uint32 len, CodePage page);


Commit: 4abc2292689eccf921cf6a0bdbb674922f82a5a2
    https://github.com/scummvm/scummvm/commit/4abc2292689eccf921cf6a0bdbb674922f82a5a2
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2024-01-08T23:39:22+01:00

Commit Message:
COMMON: Unify implementations of String::replace()

Changed paths:
    common/dbcs-str.cpp
    common/dbcs-str.h
    common/str-base.cpp
    common/str-base.h
    common/str.cpp
    common/str.h
    common/ustr.cpp
    common/ustr.h
    test/common/str.h


diff --git a/common/dbcs-str.cpp b/common/dbcs-str.cpp
index c286872947e..aa7d702d3f4 100644
--- a/common/dbcs-str.cpp
+++ b/common/dbcs-str.cpp
@@ -165,55 +165,6 @@ void DBCSString::insertString(const String &s, uint32 p) {
 	insertString(DBCSString(s), p);
 }
 
-void DBCSString::replace(uint32 pos, uint32 count, const DBCSString &str) {
-	replace(pos, count, str, 0, str._size);
-}
-
-void DBCSString::replace(iterator begin_, iterator end_, const DBCSString &str) {
-	replace(begin_ - _str, end_ - begin_, str._str, 0, str._size);
-}
-
-void DBCSString::replace(uint32 posOri, uint32 countOri, const DBCSString &str,
-					 uint32 posDest, uint32 countDest) {
-	replace(posOri, countOri, str._str, posDest, countDest);
-}
-
-void DBCSString::replace(uint32 posOri, uint32 countOri, const uint16 *str,
-					 uint32 posDest, uint32 countDest) {
-
-	// Prepare string for the replaced text.
-	if (countOri < countDest) {
-		uint32 offset = countDest - countOri; ///< Offset to copy the characters
-		uint32 newSize = _size + offset;
-
-		ensureCapacity(newSize, true);
-
-		_size = newSize;
-
-		// Push the old characters to the end of the string
-		for (uint32 i = _size; i >= posOri + countDest; i--)
-			_str[i] = _str[i - offset];
-
-	} else if (countOri > countDest) {
-		uint32 offset = countOri - countDest; ///< Number of positions that we have to pull back
-
-		makeUnique();
-
-		// Pull the remainder string back
-		for (uint32 i = posOri + countDest; i + offset <= _size; i++)
-			_str[i] = _str[i + offset];
-
-		_size -= offset;
-	} else {
-		makeUnique();
-	}
-
-	// Copy the replaced part of the string
-	for (uint32 i = 0; i < countDest; i++)
-		_str[posOri + i] = str[posDest + i];
-
-}
-
 String DBCSString::convertToString() const {
 	Common::String r;
 	for (uint i = 0; i < size(); i++) {
diff --git a/common/dbcs-str.h b/common/dbcs-str.h
index dc66d555953..18136bd070d 100644
--- a/common/dbcs-str.h
+++ b/common/dbcs-str.h
@@ -125,34 +125,6 @@ public:
 	/** Return a substring of this string */
 	DBCSString substr(size_t pos = 0, size_t len = npos) const;
 
-	/**@{
-	 * Functions to replace some amount of chars with chars from some other string.
-	 *
-	 * @note The implementation follows that of the STL's std::string:
-	 *       http://www.cplusplus.com/reference/string/string/replace/
-	 *
-	 * @param pos Starting position for the replace in the original string.
-	 * @param count Number of chars to replace from the original string.
-	 * @param str Source of the new chars.
-	 * @param posOri Same as pos
-	 * @param countOri Same as count
-	 * @param posDest Initial position to read str from.
-	 * @param countDest Number of chars to read from str. npos by default.
-	 */
-	// Replace 'count' bytes, starting from 'pos' with str.
-	void replace(uint32 pos, uint32 count, const DBCSString &str);
-	// Replace the characters in [begin, end) with str._str.
-	void replace(iterator begin, iterator end, const DBCSString &str);
-	// Replace _str[posOri, posOri + countOri) with
-	// str._str[posDest, posDest + countDest)
-	void replace(uint32 posOri, uint32 countOri, const DBCSString &str,
-					uint32 posDest, uint32 countDest);
-	// Replace _str[posOri, posOri + countOri) with
-	// str[posDest, posDest + countDest)
-	void replace(uint32 posOri, uint32 countOri, const uint16 *str,
-					uint32 posDest, uint32 countDest);
-	/**@}*/
-
 private:
 	void decodeDBCS(const char *str, uint32 len);
 
diff --git a/common/str-base.cpp b/common/str-base.cpp
index b4af5319a79..72d95aab0ff 100644
--- a/common/str-base.cpp
+++ b/common/str-base.cpp
@@ -633,6 +633,63 @@ TEMPLATE size_t BASESTRING::find(const value_type *strP, uint32 pos) const {
 	return npos;
 }
 
+TEMPLATE void BASESTRING::replace(uint32 pos, uint32 count, const BaseString &str) {
+	replace(pos, count, str, 0, str._size);
+}
+
+TEMPLATE void BASESTRING::replace(uint32 pos, uint32 count, const value_type *str) {
+	replace(pos, count, str, 0, cStrLen(str));
+}
+
+TEMPLATE void BASESTRING::replace(iterator begin_, iterator end_, const BaseString &str) {
+	replace(begin_ - _str, end_ - begin_, str._str, 0, str._size);
+}
+
+TEMPLATE void BASESTRING::replace(iterator begin_, iterator end_, const value_type *str) {
+	replace(begin_ - _str, end_ - begin_, str, 0, cStrLen(str));
+}
+
+TEMPLATE void BASESTRING::replace(uint32 posOri, uint32 countOri, const BaseString &str,
+					 uint32 posDest, uint32 countDest) {
+	replace(posOri, countOri, str._str, posDest, countDest);
+}
+
+TEMPLATE void BASESTRING::replace(uint32 posOri, uint32 countOri, const value_type *str,
+					 uint32 posDest, uint32 countDest) {
+
+	// Prepare string for the replaced text.
+	if (countOri < countDest) {
+		uint32 offset = countDest - countOri; ///< Offset to copy the characters
+		uint32 newSize = _size + offset;
+
+		ensureCapacity(newSize, true);
+
+		_size = newSize;
+
+		// Push the old characters to the end of the string
+		for (uint32 i = _size; i >= posOri + countDest; i--)
+			_str[i] = _str[i - offset];
+
+	} else if (countOri > countDest){
+		uint32 offset = countOri - countDest; ///< Number of positions that we have to pull back
+
+		makeUnique();
+
+		// Pull the remainder string back
+		for (uint32 i = posOri + countDest; i + offset <= _size; i++)
+			_str[i] = _str[i + offset];
+
+		_size -= offset;
+	} else {
+		makeUnique();
+	}
+
+	// Copy the replaced part of the string
+	for (uint32 i = 0; i < countDest; i++)
+		_str[posOri + i] = str[posDest + i];
+
+}
+
 TEMPLATE uint64 BASESTRING::asUint64() const {
 	uint64 result = 0;
 	for (uint32 i = 0; i < _size; ++i) {
diff --git a/common/str-base.h b/common/str-base.h
index 9dda1edf8bf..1e5c594a7ea 100644
--- a/common/str-base.h
+++ b/common/str-base.h
@@ -201,6 +201,38 @@ public:
 	size_t find(const value_type *s, uint32 pos = 0) const;
 	uint32 find(const BaseString &str, uint32 pos = 0) const;
 
+	/**@{
+	 * Functions to replace some amount of chars with chars from some other string.
+	 *
+	 * @note The implementation follows that of the STL's std::string:
+	 *       http://www.cplusplus.com/reference/string/string/replace/
+	 *
+	 * @param pos Starting position for the replace in the original string.
+	 * @param count Number of chars to replace from the original string.
+	 * @param str Source of the new chars.
+	 * @param posOri Same as pos
+	 * @param countOri Same as count
+	 * @param posDest Initial position to read str from.
+	 * @param countDest Number of chars to read from str. npos by default.
+	 */
+	// Replace 'count' bytes, starting from 'pos' with str.
+	void replace(uint32 pos, uint32 count, const BaseString &str);
+	// The same as above, but accepts a C-like array of characters.
+	void replace(uint32 pos, uint32 count, const value_type *str);
+	// Replace the characters in [begin, end) with str._str.
+	void replace(iterator begin, iterator end, const BaseString &str);
+	// Replace the characters in [begin, end) with str.
+	void replace(iterator begin, iterator end, const value_type *str);
+	// Replace _str[posOri, posOri + countOri) with
+	// str._str[posDest, posDest + countDest)
+	void replace(uint32 posOri, uint32 countOri, const BaseString &str,
+					uint32 posDest, uint32 countDest);
+	// Replace _str[posOri, posOri + countOri) with
+	// str[posDest, posDest + countDest)
+	void replace(uint32 posOri, uint32 countOri, const value_type *str,
+					uint32 posDest, uint32 countDest);
+	/**@}*/
+
 	/** Appends a string containing the characters between beginP (including) and endP (excluding). */
 	void append(const value_type *begin, const value_type *end);
 
diff --git a/common/str.cpp b/common/str.cpp
index aa124d270eb..e3e2100825e 100644
--- a/common/str.cpp
+++ b/common/str.cpp
@@ -192,63 +192,6 @@ bool String::matchString(const String &pat, bool ignoreCase, const char *wildcar
 
 #endif
 
-void String::replace(uint32 pos, uint32 count, const String &str) {
-	replace(pos, count, str, 0, str._size);
-}
-
-void String::replace(uint32 pos, uint32 count, const char *str) {
-	replace(pos, count, str, 0, strlen(str));
-}
-
-void String::replace(iterator begin_, iterator end_, const String &str) {
-	replace(begin_ - _str, end_ - begin_, str._str, 0, str._size);
-}
-
-void String::replace(iterator begin_, iterator end_, const char *str) {
-	replace(begin_ - _str, end_ - begin_, str, 0, strlen(str));
-}
-
-void String::replace(uint32 posOri, uint32 countOri, const String &str,
-					 uint32 posDest, uint32 countDest) {
-	replace(posOri, countOri, str._str, posDest, countDest);
-}
-
-void String::replace(uint32 posOri, uint32 countOri, const char *str,
-					 uint32 posDest, uint32 countDest) {
-
-	// Prepare string for the replaced text.
-	if (countOri < countDest) {
-		uint32 offset = countDest - countOri; ///< Offset to copy the characters
-		uint32 newSize = _size + offset;
-
-		ensureCapacity(newSize, true);
-
-		_size = newSize;
-
-		// Push the old characters to the end of the string
-		for (uint32 i = _size; i >= posOri + countDest; i--)
-			_str[i] = _str[i - offset];
-
-	} else if (countOri > countDest){
-		uint32 offset = countOri - countDest; ///< Number of positions that we have to pull back
-
-		makeUnique();
-
-		// Pull the remainder string back
-		for (uint32 i = posOri + countDest; i + offset <= _size; i++)
-			_str[i] = _str[i + offset];
-
-		_size -= offset;
-	} else {
-		makeUnique();
-	}
-
-	// Copy the replaced part of the string
-	for (uint32 i = 0; i < countDest; i++)
-		_str[posOri + i] = str[posDest + i];
-
-}
-
 void String::replace(char from, char to) {
 	// Don't allow removing trailing \x00
 	if (from == '\x00') {
diff --git a/common/str.h b/common/str.h
index 18480c04a7b..e515522d699 100644
--- a/common/str.h
+++ b/common/str.h
@@ -149,37 +149,7 @@ public:
 	bool matchString(const char *pat, bool ignoreCase = false, const char *wildcardExclusions = NULL) const;
 	bool matchString(const String &pat, bool ignoreCase = false, const char *wildcardExclusions = NULL) const;
 
-	/**@{
-	 * Functions to replace some amount of chars with chars from some other string.
-	 *
-	 * @note The implementation follows that of the STL's std::string:
-	 *       http://www.cplusplus.com/reference/string/string/replace/
-	 *
-	 * @param pos Starting position for the replace in the original string.
-	 * @param count Number of chars to replace from the original string.
-	 * @param str Source of the new chars.
-	 * @param posOri Same as pos
-	 * @param countOri Same as count
-	 * @param posDest Initial position to read str from.
-	 * @param countDest Number of chars to read from str. npos by default.
-	 */
-	// Replace 'count' bytes, starting from 'pos' with str.
-	void replace(uint32 pos, uint32 count, const String &str);
-	// The same as above, but accepts a C-like array of characters.
-	void replace(uint32 pos, uint32 count, const char *str);
-	// Replace the characters in [begin, end) with str._str.
-	void replace(iterator begin, iterator end, const String &str);
-	// Replace the characters in [begin, end) with str.
-	void replace(iterator begin, iterator end, const char *str);
-	// Replace _str[posOri, posOri + countOri) with
-	// str._str[posDest, posDest + countDest)
-	void replace(uint32 posOri, uint32 countOri, const String &str,
-					uint32 posDest, uint32 countDest);
-	// Replace _str[posOri, posOri + countOri) with
-	// str[posDest, posDest + countDest)
-	void replace(uint32 posOri, uint32 countOri, const char *str,
-					uint32 posDest, uint32 countDest);
-	/**@}*/
+	using BaseString<value_type>::replace;
 
 	/**
 	 * Replace all from characters in object by to character
diff --git a/common/ustr.cpp b/common/ustr.cpp
index 833a4e98c16..d4d3621a747 100644
--- a/common/ustr.cpp
+++ b/common/ustr.cpp
@@ -252,55 +252,6 @@ int U32String::vformat(const value_type *fmt, const value_type *fmtEnd, U32Strin
 	return length;
 }
 
-void U32String::replace(uint32 pos, uint32 count, const U32String &str) {
-	replace(pos, count, str, 0, str._size);
-}
-
-void U32String::replace(iterator begin_, iterator end_, const U32String &str) {
-	replace(begin_ - _str, end_ - begin_, str._str, 0, str._size);
-}
-
-void U32String::replace(uint32 posOri, uint32 countOri, const U32String &str,
-					 uint32 posDest, uint32 countDest) {
-	replace(posOri, countOri, str._str, posDest, countDest);
-}
-
-void U32String::replace(uint32 posOri, uint32 countOri, const u32char_type_t *str,
-					 uint32 posDest, uint32 countDest) {
-
-	// Prepare string for the replaced text.
-	if (countOri < countDest) {
-		uint32 offset = countDest - countOri; ///< Offset to copy the characters
-		uint32 newSize = _size + offset;
-
-		ensureCapacity(newSize, true);
-
-		_size = newSize;
-
-		// Push the old characters to the end of the string
-		for (uint32 i = _size; i >= posOri + countDest; i--)
-			_str[i] = _str[i - offset];
-
-	} else if (countOri > countDest) {
-		uint32 offset = countOri - countDest; ///< Number of positions that we have to pull back
-
-		makeUnique();
-
-		// Pull the remainder string back
-		for (uint32 i = posOri + countDest; i + offset <= _size; i++)
-			_str[i] = _str[i + offset];
-
-		_size -= offset;
-	} else {
-		makeUnique();
-	}
-
-	// Copy the replaced part of the string
-	for (uint32 i = 0; i < countDest; i++)
-		_str[posOri + i] = str[posDest + i];
-
-}
-
 U32String::value_type* U32String::itoa(int num, value_type* str, uint base) {
 	if (num < 0) {
 		str[0] = '-';
diff --git a/common/ustr.h b/common/ustr.h
index 9d856ac9eed..7baead64caf 100644
--- a/common/ustr.h
+++ b/common/ustr.h
@@ -185,34 +185,6 @@ public:
 	/** Transform a U32String into UTF-16 representation (native encoding). The result must be freed. */
 	uint16 *encodeUTF16Native(uint *len = nullptr) const;
 
-	/**@{
-	 * Functions to replace some amount of chars with chars from some other string.
-	 *
-	 * @note The implementation follows that of the STL's std::string:
-	 *       http://www.cplusplus.com/reference/string/string/replace/
-	 *
-	 * @param pos Starting position for the replace in the original string.
-	 * @param count Number of chars to replace from the original string.
-	 * @param str Source of the new chars.
-	 * @param posOri Same as pos
-	 * @param countOri Same as count
-	 * @param posDest Initial position to read str from.
-	 * @param countDest Number of chars to read from str. npos by default.
-	 */
-	// Replace 'count' bytes, starting from 'pos' with str.
-	void replace(uint32 pos, uint32 count, const U32String &str);
-	// Replace the characters in [begin, end) with str._str.
-	void replace(iterator begin, iterator end, const U32String &str);
-	// Replace _str[posOri, posOri + countOri) with
-	// str._str[posDest, posDest + countDest)
-	void replace(uint32 posOri, uint32 countOri, const U32String &str,
-					uint32 posDest, uint32 countDest);
-	// Replace _str[posOri, posOri + countOri) with
-	// str[posDest, posDest + countDest)
-	void replace(uint32 posOri, uint32 countOri, const u32char_type_t *str,
-					uint32 posDest, uint32 countDest);
-	/**@}*/
-
 private:
 	static U32String formatInternal(const U32String *fmt, ...);
 
diff --git a/test/common/str.h b/test/common/str.h
index a6655a74540..02aea1f318c 100644
--- a/test/common/str.h
+++ b/test/common/str.h
@@ -645,9 +645,9 @@ class StringTestSuite : public CxxTest::TestSuite
 		TS_ASSERT_EQUALS(s2, "TestTestTestTestTestTestTestTestTestTestTest");
 
 		// Makes a deep copy when we shorten the string
-		Common::String s3 = "TestTestTestTestTestTestTestTestTestTestTest";
-		Common::String s4(s3);
-		s3.replace(0, 32, Common::U32String(""));
+		Common::U32String s3 = Common::U32String("TestTestTestTestTestTestTestTestTestTestTest");
+		Common::U32String s4(s3);
+		s3.replace(0, 32, Common::U32String());
 		TS_ASSERT_EQUALS(s3, "TestTestTest");
 		TS_ASSERT_EQUALS(s4, "TestTestTestTestTestTestTestTestTestTestTest");
 	}


Commit: 6c06ae6125041ee1168cedcf75e5e33949c7e24f
    https://github.com/scummvm/scummvm/commit/6c06ae6125041ee1168cedcf75e5e33949c7e24f
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2024-01-08T23:39:22+01:00

Commit Message:
COMMON: Simplify = and += operators for U32String and DBCSString

Changed paths:
    common/dbcs-str.cpp
    common/dbcs-str.h
    common/ustr.cpp
    common/ustr.h


diff --git a/common/dbcs-str.cpp b/common/dbcs-str.cpp
index aa7d702d3f4..8ed00c19f32 100644
--- a/common/dbcs-str.cpp
+++ b/common/dbcs-str.cpp
@@ -87,7 +87,8 @@ DBCSString &DBCSString::operator=(const String &str) {
 }
 
 DBCSString &DBCSString::operator=(const value_type *str) {
-	return DBCSString::operator=(DBCSString(str));
+	assign(str);
+	return *this;
 }
 
 DBCSString &DBCSString::operator=(const char *str) {
@@ -96,27 +97,18 @@ DBCSString &DBCSString::operator=(const char *str) {
 	return *this;
 }
 
-DBCSString &DBCSString::operator+=(const DBCSString &str) {
-	if (&str == this) {
-		return operator+=(DBCSString(str));
-	}
-
-	int len = str._size;
-	if (len > 0) {
-		ensureCapacity(_size + len, true);
+DBCSString &DBCSString::operator=(value_type c) {
+	assign(c);
+	return *this;
+}
 
-		memcpy(_str + _size, str._str, (len + 1) * sizeof(value_type));
-		_size += len;
-	}
+DBCSString &DBCSString::operator+=(const DBCSString &str) {
+	assignAppend(str);
 	return *this;
 }
 
 DBCSString &DBCSString::operator+=(value_type c) {
-	ensureCapacity(_size + 1, true);
-
-	_str[_size++] = c;
-	_str[_size] = 0;
-
+	assignAppend(c);
 	return *this;
 }
 
diff --git a/common/dbcs-str.h b/common/dbcs-str.h
index 18136bd070d..48d9ac8f1c6 100644
--- a/common/dbcs-str.h
+++ b/common/dbcs-str.h
@@ -94,9 +94,15 @@ public:
 	/** @overload */
 	DBCSString &operator=(const char *str);
 
+	/** @overload */
+	DBCSString &operator=(value_type c);
+
 	/** Append the given string to this string. */
 	DBCSString &operator+=(const DBCSString &str);
 
+	/** @overload */
+	DBCSString &operator+=(const value_type *str);
+
 	/** @overload */
 	DBCSString &operator+=(value_type c);
 
diff --git a/common/ustr.cpp b/common/ustr.cpp
index d4d3621a747..a07600bc849 100644
--- a/common/ustr.cpp
+++ b/common/ustr.cpp
@@ -72,7 +72,8 @@ U32String &U32String::operator=(const String &str) {
 }
 
 U32String &U32String::operator=(const value_type *str) {
-	return U32String::operator=(U32String(str));
+	assign(str);
+	return *this;
 }
 
 U32String &U32String::operator=(const char *str) {
@@ -81,27 +82,23 @@ U32String &U32String::operator=(const char *str) {
 	return *this;
 }
 
-U32String &U32String::operator+=(const U32String &str) {
-	if (&str == this) {
-		return operator+=(U32String(str));
-	}
+U32String &U32String::operator=(value_type c) {
+	assign(c);
+	return *this;
+}
 
-	int len = str._size;
-	if (len > 0) {
-		ensureCapacity(_size + len, true);
+U32String &U32String::operator+=(const value_type *str) {
+	assignAppend(str);
+	return *this;
+}
 
-		memcpy(_str + _size, str._str, (len + 1) * sizeof(value_type));
-		_size += len;
-	}
+U32String &U32String::operator+=(const U32String &str) {
+	assignAppend(str);
 	return *this;
 }
 
 U32String &U32String::operator+=(value_type c) {
-	ensureCapacity(_size + 1, true);
-
-	_str[_size++] = c;
-	_str[_size] = 0;
-
+	assignAppend(c);
 	return *this;
 }
 
diff --git a/common/ustr.h b/common/ustr.h
index 7baead64caf..d6b35817843 100644
--- a/common/ustr.h
+++ b/common/ustr.h
@@ -110,9 +110,15 @@ public:
 	/** @overload */
 	U32String &operator=(const char *str);
 
+	/** @overload */
+	U32String &operator=(value_type c);
+
 	/** Append the given string to this string. */
 	U32String &operator+=(const U32String &str);
 
+	/** @overload */
+	U32String &operator+=(const value_type *str);
+
 	/** @overload */
 	U32String &operator+=(value_type c);
 


Commit: dce0f057ec7119970765ef683b28e7fb4c499b75
    https://github.com/scummvm/scummvm/commit/dce0f057ec7119970765ef683b28e7fb4c499b75
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2024-01-08T23:39:22+01:00

Commit Message:
COMMON: Optimize U32String::vformat a bit by appending chars instead of inserting them

Changed paths:
    common/ustr.cpp
    engines/engine.cpp


diff --git a/common/ustr.cpp b/common/ustr.cpp
index a07600bc849..7fd22cf0ad6 100644
--- a/common/ustr.cpp
+++ b/common/ustr.cpp
@@ -178,75 +178,68 @@ int U32String::vformat(const value_type *fmt, const value_type *fmtEnd, U32Strin
 
 	value_type ch;
 	value_type *u32string_temp;
-	int length = 0;
-	int len = 0;
-	int pos = 0;
-	int tempPos = 0;
 
 	value_type buffer[512];
 
+	const value_type *start = fmt;
+
 	while (fmt != fmtEnd) {
-		ch = *fmt++;
-		if (ch == '%') {
-			switch (ch = *fmt++) {
+		if (*fmt == '%') {
+			// Copy all characters since the last argument
+			if (fmt != start)
+				output.append(start, fmt);
+
+			switch (ch = *++fmt) {
 			case 'S':
 				u32string_temp = va_arg(args, value_type *);
 
-				tempPos = output.size();
-				output.insertString(u32string_temp, pos);
-				len = output.size() - tempPos;
-				length += len;
-
-				pos += len - 1;
+				output += u32string_temp;
 				break;
 			case 's':
 				string_temp = va_arg(args, char *);
-				tempPos = output.size();
-				output.insertString(string_temp, pos);
-				len = output.size() - tempPos;
-				length += len;
-				pos += len - 1;
+
+				output += Common::U32String(string_temp, kUtf8);
 				break;
 			case 'i':
 			// fallthrough intended
 			case 'd':
 				int_temp = va_arg(args, int);
 				itoa(int_temp, buffer, 10);
-				len = cStrLen(buffer);
-				length += len;
 
-				output.insertString(buffer, pos);
-				pos += len - 1;
+				output += buffer;
 				break;
 			case 'u':
 				uint_temp = va_arg(args, uint);
 				uitoa(uint_temp, buffer, 10);
-				len = cStrLen(buffer);
-				length += len;
 
-				output.insertString(buffer, pos);
-				pos += len - 1;
+				output += buffer;
 				break;
 			case 'c':
 				//char is promoted to int when passed through '...'
 				int_temp = va_arg(args, int);
-				output.insertChar(int_temp, pos);
-				++length;
+
+				output += int_temp;
 				break;
 			case '%':
-				output.insertChar('%', pos);
-				++length;
+				output += '%';
 				break;
 			default:
 				warning("Unexpected formatting type for U32String::Format.");
 				break;
 			}
+
+			start = ++fmt;
 		} else {
-			output += *(fmt - 1);
+			// We attempt to copy as many characters as possible in one go.
+			++fmt;
 		}
-		pos++;
 	}
-	return length;
+
+	// Append any remaining characters
+	if (fmt != start)
+		output.append(start, fmt);
+
+	return output.size();
 }
 
 U32String::value_type* U32String::itoa(int num, value_type* str, uint base) {
diff --git a/engines/engine.cpp b/engines/engine.cpp
index 4e649f57b08..2faf7097dee 100644
--- a/engines/engine.cpp
+++ b/engines/engine.cpp
@@ -509,7 +509,7 @@ void GUIErrorMessageFormat(const char *fmt, ...) {
 }
 
 void GUIErrorMessageFormatU32StringPtr(const Common::U32String *fmt, ...) {
-	Common::U32String msg("");
+	Common::U32String msg;
 
 	va_list va;
 	va_start(va, fmt);


Commit: a8183c773433a67e25f1879b4697282d8b9dfbb2
    https://github.com/scummvm/scummvm/commit/a8183c773433a67e25f1879b4697282d8b9dfbb2
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2024-01-08T23:39:22+01:00

Commit Message:
COMMON: Insert all characters in one go with String::insertString()

Changed paths:
    common/dbcs-str.cpp
    common/dbcs-str.h
    common/str-base.cpp
    common/str-base.h
    common/ustr.cpp
    common/ustr.h
    test/common/str.h


diff --git a/common/dbcs-str.cpp b/common/dbcs-str.cpp
index 8ed00c19f32..57782c43eb4 100644
--- a/common/dbcs-str.cpp
+++ b/common/dbcs-str.cpp
@@ -149,14 +149,6 @@ DBCSString DBCSString::substr(size_t pos, size_t len) const {
 		return DBCSString(_str + pos, MIN((size_t)_size - pos, len));
 }
 
-void DBCSString::insertString(const char *s, uint32 p) {
-	insertString(DBCSString(s), p);
-}
-
-void DBCSString::insertString(const String &s, uint32 p) {
-	insertString(DBCSString(s), p);
-}
-
 String DBCSString::convertToString() const {
 	Common::String r;
 	for (uint i = 0; i < size(); i++) {
diff --git a/common/dbcs-str.h b/common/dbcs-str.h
index 48d9ac8f1c6..b75800ef8cb 100644
--- a/common/dbcs-str.h
+++ b/common/dbcs-str.h
@@ -124,10 +124,6 @@ public:
 	/** Convert the string to the standard String represantation. */
 	String convertToString() const;
 
-	using BaseString<value_type>::insertString;
-	void insertString(const char *s, uint32 p);   /*!< Insert string @p s into this string at position @p p. */
-	void insertString(const String &s, uint32 p); /*!< @overload */
-
 	/** Return a substring of this string */
 	DBCSString substr(size_t pos = 0, size_t len = npos) const;
 
diff --git a/common/str-base.cpp b/common/str-base.cpp
index 72d95aab0ff..7a73c87effb 100644
--- a/common/str-base.cpp
+++ b/common/str-base.cpp
@@ -440,12 +440,7 @@ TEMPLATE bool BASESTRING::contains(const BaseString &otherString) const {
 
 TEMPLATE void BASESTRING::insertChar(value_type c, uint32 p) {
 	assert(p <= _size);
-
-	ensureCapacity(_size + 1, true);
-	_size++;
-	for (uint32 i = _size; i > p; --i)
-		_str[i] = _str[i - 1];
-	_str[p] = c;
+	assignInsert(c, p);
 }
 
 TEMPLATE void BASESTRING::deleteChar(uint32 p) {
@@ -564,15 +559,11 @@ TEMPLATE void BASESTRING::assign(value_type c) {
 }
 
 TEMPLATE void BASESTRING::insertString(const value_type *s, uint32 p) {
-	while (*s != '\0') {
-		BaseString::insertChar(*s++, p++);
-	}
+	assignInsert(s, p);
 }
 
 TEMPLATE void BASESTRING::insertString(const BaseString &s, uint32 p) {
-	for (uint i = 0; i < s._size; i++) {
-		BaseString::insertChar(s[i], p+i);
-	}
+	assignInsert(s, p);
 }
 
 TEMPLATE uint32 BASESTRING::find(value_type x, uint32 pos) const {
@@ -864,6 +855,19 @@ TEMPLATE void BASESTRING::append(const value_type *beginP, const value_type *end
 	_str[_size] = 0;
 }
 
+TEMPLATE void BASESTRING::assignInsert(value_type c, uint32 p) {
+	if (c == 0) {
+#ifndef SCUMMVM_UTIL
+		warning("Inserting \\0 into String. This is permitted, but can have unwanted consequences. (This warning will be removed later.)");
+#endif
+	}
+	ensureCapacity(_size + 1, true);
+
+	memmove(_str + p + 1, _str + p, ((_size - p) + 1) * sizeof(value_type));
+	_str[p] = c;
+	_size++;
+}
+
 TEMPLATE void BASESTRING::assignAppend(value_type c) {
 	if (c == 0) {
 #ifndef SCUMMVM_UTIL
@@ -876,6 +880,22 @@ TEMPLATE void BASESTRING::assignAppend(value_type c) {
 	_str[_size] = 0;
 }
 
+TEMPLATE void BASESTRING::assignInsert(const BaseString &str, uint32 p) {
+	if (&str == this) {
+		assignInsert(BaseString(str), p);
+		return;
+	}
+
+	int len = str._size;
+	if (len > 0) {
+		ensureCapacity(_size + len, true);
+
+		memmove(_str + p + len, _str + p, ((_size - p) + 1) * sizeof(value_type));
+		memcpy(_str + p, str._str, len * sizeof(value_type));
+		_size += len;
+	}
+}
+
 TEMPLATE void BASESTRING::assignAppend(const BaseString &str) {
 	if (&str == this) {
 		assignAppend(BaseString(str));
@@ -901,6 +921,23 @@ TEMPLATE bool BASESTRING::pointerInOwnBuffer(const value_type *str) const {
 	return ownBuffStart <= candidateAddr && candidateAddr <= ownBuffEnd;
 }
 
+TEMPLATE void BASESTRING::assignInsert(const value_type *str, uint32 p) {
+	if (pointerInOwnBuffer(str)) {
+		assignInsert(BaseString(str), p);
+		return;
+	}
+
+	uint32 len;
+	for (len = 0; str[len]; len++);
+	if (len > 0) {
+		ensureCapacity(_size + len, true);
+
+		memmove(_str + p + len, _str + p, ((_size - p) + 1) * sizeof(value_type));
+		memcpy(_str + p, str, len * sizeof(value_type));
+		_size += len;
+	}
+}
+
 TEMPLATE void BASESTRING::assignAppend(const value_type *str) {
 	if (pointerInOwnBuffer(str)) {
 		assignAppend(BaseString(str));
diff --git a/common/str-base.h b/common/str-base.h
index 1e5c594a7ea..77e2cbd21bf 100644
--- a/common/str-base.h
+++ b/common/str-base.h
@@ -289,6 +289,9 @@ protected:
 	void decRefCount(int *oldRefCount);
 	void initWithValueTypeStr(const value_type *str, uint32 len);
 
+	void assignInsert(const value_type *str, uint32 p);
+	void assignInsert(value_type c, uint32 p);
+	void assignInsert(const BaseString &str, uint32 p);
 	void assignAppend(const value_type *str);
 	void assignAppend(value_type c);
 	void assignAppend(const BaseString &str);
diff --git a/common/ustr.cpp b/common/ustr.cpp
index 7fd22cf0ad6..81342c41d7e 100644
--- a/common/ustr.cpp
+++ b/common/ustr.cpp
@@ -139,14 +139,6 @@ U32String U32String::substr(size_t pos, size_t len) const {
 		return U32String(_str + pos, MIN((size_t)_size - pos, len));
 }
 
-void U32String::insertString(const char *s, uint32 p, CodePage page) {
-	insertString(U32String(s, page), p);
-}
-
-void U32String::insertString(const String &s, uint32 p, CodePage page) {
-	insertString(U32String(s, page), p);
-}
-
 U32String U32String::formatInternal(const U32String *fmt, ...) {
 	U32String output;
 
diff --git a/common/ustr.h b/common/ustr.h
index d6b35817843..0909bcc6ea5 100644
--- a/common/ustr.h
+++ b/common/ustr.h
@@ -162,10 +162,6 @@ public:
 	 */
 	static int vformat(const value_type *fmt, const value_type *fmtEnd, U32String &output, va_list args);
 
-	using BaseString<value_type>::insertString;
-	void insertString(const char *s, uint32 p, CodePage page = kUtf8);   /*!< Insert string @p s into this string at position @p p. */
-	void insertString(const String &s, uint32 p, CodePage page = kUtf8); /*!< @overload */
-
 	/** Return a substring of this string */
 	U32String substr(size_t pos = 0, size_t len = npos) const;
 
diff --git a/test/common/str.h b/test/common/str.h
index 02aea1f318c..6658f338317 100644
--- a/test/common/str.h
+++ b/test/common/str.h
@@ -682,6 +682,18 @@ class StringTestSuite : public CxxTest::TestSuite
 		TS_ASSERT(testString == "2123456");
 		testString.insertChar('0', 5);
 		TS_ASSERT(testString == "21234056");
+		testString.insertChar('7', 8);
+		TS_ASSERT(testString == "212340567");
+	}
+
+	void test_insertString() {
+		Common::String testString("123456");
+		testString.insertString("12", 0);
+		TS_ASSERT(testString == "12123456");
+		testString.insertString("01", 6);
+		TS_ASSERT(testString == "1212340156");
+		testString.insertString("78", 10);
+		TS_ASSERT(testString == "121234015678");
 	}
 
 	void test_comparison() {


Commit: 0a4fec83c04b3ca69fc78a5fe2833abcb2051955
    https://github.com/scummvm/scummvm/commit/0a4fec83c04b3ca69fc78a5fe2833abcb2051955
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2024-01-08T23:39:22+01:00

Commit Message:
COMMON: Improve removing characters from strings

Changed paths:
    common/str-base.cpp
    common/str-base.h
    test/common/str.h


diff --git a/common/str-base.cpp b/common/str-base.cpp
index 7a73c87effb..64939645164 100644
--- a/common/str-base.cpp
+++ b/common/str-base.cpp
@@ -445,23 +445,19 @@ TEMPLATE void BASESTRING::insertChar(value_type c, uint32 p) {
 
 TEMPLATE void BASESTRING::deleteChar(uint32 p) {
 	assert(p < _size);
-
-	makeUnique();
-	while (p++ < _size)
-		_str[p - 1] = _str[p];
-	_size--;
-}
-
-TEMPLATE void BASESTRING::deleteLastChar() {
-	if (_size > 0)
-		deleteChar(_size - 1);
+	erase(p, 1);
 }
 
 TEMPLATE void BASESTRING::chop(uint32 len) {
-	uint32 newSize = _size - MIN(_size, len);
+	if (_size > len) {
+		uint32 newSize = _size - len;
 
-	_str[newSize] = 0;
-	_size = newSize;
+		makeUnique();
+		_str[newSize] = 0;
+		_size = newSize;
+	} else if (_size > 0) {
+		clear();
+	}
 }
 
 TEMPLATE void BASESTRING::erase(uint32 p, uint32 len) {
@@ -470,20 +466,24 @@ TEMPLATE void BASESTRING::erase(uint32 p, uint32 len) {
 
 	assert(p < _size);
 
-	makeUnique();
 	// If len == npos or p + len is over the end, remove all the way to the end
 	if (len == npos || p + len >= _size) {
-		// Delete char at p as well. So _size = (p - 1) + 1
-		_size = p;
-		// Null terminate
-		_str[_size] = 0;
+		// If p == 0, remove the entire string
+		if (p == 0) {
+			clear();
+		} else {
+			makeUnique();
+			// Delete char at p as well. So _size = (p - 1) + 1
+			_size = p;
+			// Null terminate
+			_str[_size] = 0;
+		}
 		return;
 	}
 
-	for ( ; p + len <= _size; p++) {
-		_str[p] = _str[p + len];
-	}
+	makeUnique();
 	_size -= len;
+	memmove(_str + p, _str + p + len, ((_size - p) + 1) * sizeof(value_type));
 }
 
 TEMPLATE typename BASESTRING::iterator BASESTRING::erase(iterator it) {
diff --git a/common/str-base.h b/common/str-base.h
index 77e2cbd21bf..2e275521306 100644
--- a/common/str-base.h
+++ b/common/str-base.h
@@ -134,7 +134,7 @@ public:
 	void deleteChar(uint32 p);
 
 	/** Remove the last character from the string. */
-	void deleteLastChar();
+	inline void deleteLastChar() { chop(1); }
 
 	/** Remove all characters from position p to the p + len. If len = String::npos, removes all characters to the end */
 	void erase(uint32 p, uint32 len = npos);
diff --git a/test/common/str.h b/test/common/str.h
index 6658f338317..9ebe42be189 100644
--- a/test/common/str.h
+++ b/test/common/str.h
@@ -29,8 +29,10 @@ class StringTestSuite : public CxxTest::TestSuite
 
 	void test_chop() {
 		Common::String str("test-string");
+		Common::String str2 = str;
 		str.chop();
 		TS_ASSERT_EQUALS(str, "test-strin");
+		TS_ASSERT_EQUALS(str2, "test-string");
 
 		str = "test-string";
 		str.chop(2);


Commit: 35125f5509840920241d85563486ffb34b2ce339
    https://github.com/scummvm/scummvm/commit/35125f5509840920241d85563486ffb34b2ce339
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2024-01-08T23:39:22+01:00

Commit Message:
COMMON: Use more standard library functions in String classes

Changed paths:
    common/str-base.cpp
    common/str-base.h
    common/str.cpp
    common/str.h


diff --git a/common/str-base.cpp b/common/str-base.cpp
index 64939645164..808550a3a84 100644
--- a/common/str-base.cpp
+++ b/common/str-base.cpp
@@ -324,14 +324,10 @@ TEMPLATE bool BASESTRING::operator!=(const value_type *x) const {
 }
 
 TEMPLATE int BASESTRING::compareTo(const BaseString &x) const {
-	for (uint32 i = 0, n = x.size(); i < _size && i < n; ++i) {
-		uint32 sc = _str[i];
-		uint32 xc = x[i];
-		if (sc < xc)
-			return -1;
-		else if (sc > xc)
-			return +1;
-	}
+	int n = cMemCmp(_str, x._str, MIN(_size, x.size()));
+	if (n != 0)
+		return n;
+
 	if (_size < x.size())
 		return -1;
 	if (_size == x.size())
@@ -406,13 +402,7 @@ TEMPLATE bool BASESTRING::operator>=(const value_type *x) const {
 }
 
 TEMPLATE bool BASESTRING::contains(value_type x) const {
-	for (uint32 i = 0; i < _size; ++i) {
-		if (_str[i] == x) {
-			return true;
-		}
-	}
-
-	return false;
+	return cMemChr(_str, x, _size) != nullptr;
 }
 
 TEMPLATE bool BASESTRING::contains(const BaseString &otherString) const {
@@ -567,13 +557,8 @@ TEMPLATE void BASESTRING::insertString(const BaseString &s, uint32 p) {
 }
 
 TEMPLATE uint32 BASESTRING::find(value_type x, uint32 pos) const {
-	for (uint32 i = pos; i < _size; ++i) {
-		if (_str[i] == x) {
-			return i;
-		}
-	}
-
-	return npos;
+	const value_type *p = (pos >= _size) ? nullptr : cMemChr(_str + pos, x, _size - pos);
+	return p ? p - _str : npos;
 }
 
 TEMPLATE uint32 BASESTRING::find(const BaseString &str, uint32 pos) const {
@@ -652,23 +637,25 @@ TEMPLATE void BASESTRING::replace(uint32 posOri, uint32 countOri, const value_ty
 	if (countOri < countDest) {
 		uint32 offset = countDest - countOri; ///< Offset to copy the characters
 		uint32 newSize = _size + offset;
+		uint32 len = _size - posOri;
 
 		ensureCapacity(newSize, true);
 
 		_size = newSize;
 
 		// Push the old characters to the end of the string
-		for (uint32 i = _size; i >= posOri + countDest; i--)
-			_str[i] = _str[i - offset];
+		memmove(_str + posOri + offset, _str + posOri,
+		        (len + 1) * sizeof(value_type));
 
 	} else if (countOri > countDest){
 		uint32 offset = countOri - countDest; ///< Number of positions that we have to pull back
+		uint32 len = _size - (posOri + countDest + offset);
 
 		makeUnique();
 
 		// Pull the remainder string back
-		for (uint32 i = posOri + countDest; i + offset <= _size; i++)
-			_str[i] = _str[i + offset];
+		memmove(_str + posOri + countDest, _str + posOri + countDest + offset,
+			 (len + 1) * sizeof(value_type));
 
 		_size -= offset;
 	} else {
@@ -676,9 +663,7 @@ TEMPLATE void BASESTRING::replace(uint32 posOri, uint32 countOri, const value_ty
 	}
 
 	// Copy the replaced part of the string
-	for (uint32 i = 0; i < countDest; i++)
-		_str[posOri + i] = str[posDest + i];
-
+	memmove(_str + posOri, str + posDest, countDest * sizeof(value_type));
 }
 
 TEMPLATE uint64 BASESTRING::asUint64() const {
@@ -927,8 +912,7 @@ TEMPLATE void BASESTRING::assignInsert(const value_type *str, uint32 p) {
 		return;
 	}
 
-	uint32 len;
-	for (len = 0; str[len]; len++);
+	uint32 len = cStrLen(str);
 	if (len > 0) {
 		ensureCapacity(_size + len, true);
 
@@ -944,8 +928,7 @@ TEMPLATE void BASESTRING::assignAppend(const value_type *str) {
 		return;
 	}
 
-	uint32 len;
-	for (len = 0; str[len]; len++);
+	uint32 len = cStrLen(str);
 	if (len > 0) {
 		ensureCapacity(_size + len, true);
 
@@ -955,8 +938,7 @@ TEMPLATE void BASESTRING::assignAppend(const value_type *str) {
 }
 
 TEMPLATE void BASESTRING::assign(const value_type *str) {
-	uint32 len;
-	for (len = 0; str[len]; len++);
+	uint32 len = cStrLen(str);
 	ensureCapacity(len, false);
 	_size = len;
 	memmove(_str, str, (len + 1) * sizeof(value_type));
@@ -975,6 +957,40 @@ TEMPLATE uint32 BASESTRING::cStrLen(const value_type *str) {
 	return len;
 }
 
+TEMPLATE const T *BASESTRING::cMemChr(const value_type *str, value_type c, size_t count) {
+	for (size_t i = 0; i < count; ++i) {
+		if (str[i] == c) {
+			return str + i;
+		}
+	}
+	return nullptr;
+}
+
+TEMPLATE T *BASESTRING::cMemChr(value_type *str, value_type c, size_t count) {
+	for (size_t i = 0; i < count; ++i) {
+		if (str[i] == c) {
+			return str + i;
+		}
+	}
+	return nullptr;
+}
+
+TEMPLATE int BASESTRING::cMemCmp(const value_type* ptr1, const value_type* ptr2, size_t count) {
+	assert(ptr1);
+	assert(ptr2);
+	assert(count);
+
+	for (size_t i = 0; i < count; ++i) {
+		value_type sc = ptr1[i];
+		value_type xc = ptr2[i];
+		if (sc < xc)
+			return -1;
+		else if (sc > xc)
+			return +1;
+	}
+	return 0;
+}
+
 // Hash function for strings, taken from CPython.
 TEMPLATE uint BASESTRING::hash() const {
 	uint hashResult = getUnsignedValue(0) << 7;
@@ -989,6 +1005,21 @@ uint32 BaseString<char>::cStrLen(const value_type *str) {
 	return static_cast<uint32>(strlen(str));
 }
 
+template<>
+const char *BaseString<char>::cMemChr(const value_type *ptr, value_type c, size_t count) {
+	return static_cast<const char *>(memchr(ptr, c, count));
+}
+
+template<>
+char *BaseString<char>::cMemChr(value_type *ptr, value_type c, size_t count) {
+	return static_cast<char *>(memchr(ptr, c, count));
+}
+
+template<>
+int BaseString<char>::cMemCmp(const value_type* ptr1, const value_type* ptr2, size_t count) {
+	return memcmp(ptr1, ptr2, count);
+}
+
 template class BaseString<char>;
 template class BaseString<uint16>;
 template class BaseString<u32char_type_t>;
diff --git a/common/str-base.h b/common/str-base.h
index 2e275521306..fc7057b88f1 100644
--- a/common/str-base.h
+++ b/common/str-base.h
@@ -307,6 +307,9 @@ protected:
 	void toCase(int (*caseChangeFunc)(int));
 
 	static uint32 cStrLen(const value_type *str);
+	static const value_type *cMemChr(const value_type *ptr, value_type c, size_t count);
+	static       value_type *cMemChr(value_type *ptr,       value_type c, size_t count);
+	static int cMemCmp(const value_type* ptr1, const value_type* ptr2, size_t count);
 };
 }
 #endif
diff --git a/common/str.cpp b/common/str.cpp
index e3e2100825e..d8a8a7e3591 100644
--- a/common/str.cpp
+++ b/common/str.cpp
@@ -121,7 +121,7 @@ bool String::hasSuffix(const String &x) const {
 bool String::hasSuffix(const char *x) const {
 	assert(x != nullptr);
 	// Compare x with the end of _str.
-	const uint32 x_size = strlen(x);
+	const uint32 x_size = cStrLen(x);
 	if (x_size > _size)
 		return false;
 	const char *y = c_str() + _size - x_size;
@@ -141,7 +141,7 @@ bool String::hasSuffixIgnoreCase(const String &x) const {
 bool String::hasSuffixIgnoreCase(const char *x) const {
 	assert(x != nullptr);
 	// Compare x with the end of _str.
-	const uint32 x_size = strlen(x);
+	const uint32 x_size = cStrLen(x);
 	if (x_size > _size)
 		return false;
 	const char *y = c_str() + _size - x_size;
@@ -163,23 +163,6 @@ bool String::contains(const char *x) const {
 	return strstr(c_str(), x) != nullptr;
 }
 
-bool String::contains(char x) const {
-	return strchr(c_str(), x) != nullptr;
-}
-
-bool String::contains(uint32 x) const {
-	for (String::const_iterator itr = begin(); itr != end(); itr++) {
-		if (uint32(*itr) == x) {
-			return true;
-		}
-	}
-	return false;
-}
-
-bool String::contains(char32_t x) const {
-	return contains((uint32)x);
-}
-
 #ifndef SCUMMVM_UTIL
 
 bool String::matchString(const char *pat, bool ignoreCase, const char *wildcardExclusions) const {
@@ -198,7 +181,7 @@ void String::replace(char from, char to) {
 		return;
 	}
 
-	char *next = strchr(_str, from);
+	char *next = (char *)cMemChr(_str, from, _size);
 	if (!next) {
 		// Nothing to do
 		return;
@@ -207,11 +190,12 @@ void String::replace(char from, char to) {
 	size_t off = next - _str;
 	makeUnique();
 
+	char *end = _str + _size;
 	next = _str + off;
 	while(next) {
 		*next = to;
 		next++;
-		next = strchr(next, from);
+		next = (char *)cMemChr(next + 1, from, end - next);
 	}
 }
 
@@ -280,10 +264,10 @@ String String::vformat(const char *fmt, va_list args) {
 }
 
 size_t String::rfind(const char *s) const {
-	int sLen = strlen(s);
+	int sLen = cStrLen(s);
 
 	for (int idx = (int)_size - sLen; idx >= 0; --idx) {
-		if (!strncmp(_str + idx, s, sLen))
+		if (!memcmp(_str + idx, s, sLen * sizeof(value_type)))
 			return idx;
 	}
 
@@ -306,13 +290,15 @@ size_t String::rfind(char c, size_t pos) const {
 }
 
 size_t String::findFirstOf(char c, size_t pos) const {
-	const char *strP = (pos >= _size) ? nullptr : strchr(_str + pos, c);
+	const char *strP = (pos >= _size) ? nullptr : cMemChr(_str + pos, c, _size - pos);
 	return strP ? strP - _str : npos;
 }
 
 size_t String::findFirstOf(const char *chars, size_t pos) const {
+	uint32 charsLen = cStrLen(chars);
+
 	for (uint idx = pos; idx < _size; ++idx) {
-		if (strchr(chars, (*this)[idx]))
+		if (cMemChr(chars, (*this)[idx], charsLen))
 			return idx;
 	}
 
@@ -330,9 +316,11 @@ size_t String::findLastOf(char c, size_t pos) const {
 }
 
 size_t String::findLastOf(const char *chars, size_t pos) const {
+	uint32 charsLen = cStrLen(chars);
+
 	int start = (pos == npos) ? (int)_size - 1 : MIN((int)_size - 1, (int)pos);
 	for (int idx = start; idx >= 0; --idx) {
-		if (strchr(chars, (*this)[idx]))
+		if (cMemChr(chars, (*this)[idx], charsLen))
 			return idx;
 	}
 
@@ -349,8 +337,10 @@ size_t String::findFirstNotOf(char c, size_t pos) const {
 }
 
 size_t String::findFirstNotOf(const char *chars, size_t pos) const {
+	uint32 charsLen = cStrLen(chars);
+
 	for (uint idx = pos; idx < _size; ++idx) {
-		if (!strchr(chars, (*this)[idx]))
+		if (!cMemChr(chars, (*this)[idx], charsLen))
 			return idx;
 	}
 
@@ -367,8 +357,10 @@ size_t String::findLastNotOf(char c) const {
 }
 
 size_t String::findLastNotOf(const char *chars) const {
+	uint32 charsLen = cStrLen(chars);
+
 	for (int idx = (int)_size - 1; idx >= 0; --idx) {
-		if (!strchr(chars, (*this)[idx]))
+		if (!cMemChr(chars, (*this)[idx], charsLen))
 			return idx;
 	}
 
@@ -1010,10 +1002,11 @@ int scumm_compareDictionary(const char *s1, const char *s2) {
 
 //  Portable implementation of strdup.
 char *scumm_strdup(const char *in) {
-	const size_t len = strlen(in) + 1;
-	char *out = (char *)malloc(len);
+	const size_t len = strlen(in);
+	char *out = (char *)malloc(len + 1);
 	if (out) {
-		Common::strcpy_s(out, len, in);
+		memcpy(out, in, len);
+		out[len] = 0;
 	}
 	return out;
 }
diff --git a/common/str.h b/common/str.h
index e515522d699..2e5553ff002 100644
--- a/common/str.h
+++ b/common/str.h
@@ -115,11 +115,9 @@ public:
 	bool hasPrefixIgnoreCase(const String &x) const;
 	bool hasPrefixIgnoreCase(const char *x) const;
 
+	using BaseString<value_type>::contains;
 	bool contains(const String &x) const;
 	bool contains(const char *x) const;
-	bool contains(char x) const;
-	bool contains(uint32 x) const;
-	bool contains(char32_t x) const;
 
 	/**
 	 * Simple DOS-style pattern matching function (understands * and ? like used in DOS).


Commit: f7c2d14587c8ed531acd4765130a22f535183072
    https://github.com/scummvm/scummvm/commit/f7c2d14587c8ed531acd4765130a22f535183072
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2024-01-08T23:39:22+01:00

Commit Message:
COMMON: Move all find and replace functions into BaseString

Changed paths:
    common/str-base.cpp
    common/str-base.h
    common/str.cpp
    common/str.h


diff --git a/common/str-base.cpp b/common/str-base.cpp
index 808550a3a84..b95d54f2b9f 100644
--- a/common/str-base.cpp
+++ b/common/str-base.cpp
@@ -609,6 +609,110 @@ TEMPLATE size_t BASESTRING::find(const value_type *strP, uint32 pos) const {
 	return npos;
 }
 
+TEMPLATE size_t BASESTRING::rfind(const value_type *s) const {
+	int sLen = cStrLen(s);
+
+	for (int idx = (int)_size - sLen; idx >= 0; --idx) {
+		if (!memcmp(_str + idx, s, sLen * sizeof(value_type)))
+			return idx;
+	}
+
+	return npos;
+}
+
+TEMPLATE size_t BASESTRING::rfind(value_type c, size_t pos) const {
+	if (pos == npos || pos > _size)
+		pos = _size;
+	else
+		++pos;
+
+	while (pos > 0) {
+		--pos;
+		if ((*this)[pos] == c)
+			return pos;
+	}
+
+	return npos;
+}
+
+TEMPLATE size_t BASESTRING::findFirstOf(value_type c, size_t pos) const {
+	const value_type *strP = (pos >= _size) ? nullptr : cMemChr(_str + pos, c, _size - pos);
+	return strP ? strP - _str : npos;
+}
+
+TEMPLATE size_t BASESTRING::findFirstOf(const value_type *chars, size_t pos) const {
+	uint32 charsLen = cStrLen(chars);
+
+	for (uint idx = pos; idx < _size; ++idx) {
+		if (cMemChr(chars, (*this)[idx], charsLen))
+			return idx;
+	}
+
+	return npos;
+}
+
+TEMPLATE size_t BASESTRING::findLastOf(value_type c, size_t pos) const {
+	int start = (pos == npos) ? (int)_size - 1 : MIN((int)_size - 1, (int)pos);
+	for (int idx = start; idx >= 0; --idx) {
+		if ((*this)[idx] == c)
+			return idx;
+	}
+
+	return npos;
+}
+
+TEMPLATE size_t BASESTRING::findLastOf(const value_type *chars, size_t pos) const {
+	uint32 charsLen = cStrLen(chars);
+
+	int start = (pos == npos) ? (int)_size - 1 : MIN((int)_size - 1, (int)pos);
+	for (int idx = start; idx >= 0; --idx) {
+		if (cMemChr(chars, (*this)[idx], charsLen))
+			return idx;
+	}
+
+	return npos;
+}
+
+TEMPLATE size_t BASESTRING::findFirstNotOf(value_type c, size_t pos) const {
+	for (uint idx = pos; idx < _size; ++idx) {
+		if ((*this)[idx] != c)
+			return idx;
+	}
+
+	return npos;
+}
+
+TEMPLATE size_t BASESTRING::findFirstNotOf(const value_type *chars, size_t pos) const {
+	uint32 charsLen = cStrLen(chars);
+
+	for (uint idx = pos; idx < _size; ++idx) {
+		if (!cMemChr(chars, (*this)[idx], charsLen))
+			return idx;
+	}
+
+	return npos;
+}
+
+TEMPLATE size_t BASESTRING::findLastNotOf(value_type c) const {
+	for (int idx = (int)_size - 1; idx >= 0; --idx) {
+		if ((*this)[idx] != c)
+			return idx;
+	}
+
+	return npos;
+}
+
+TEMPLATE size_t BASESTRING::findLastNotOf(const value_type *chars) const {
+	uint32 charsLen = cStrLen(chars);
+
+	for (int idx = (int)_size - 1; idx >= 0; --idx) {
+		if (!cMemChr(chars, (*this)[idx], charsLen))
+			return idx;
+	}
+
+	return npos;
+}
+
 TEMPLATE void BASESTRING::replace(uint32 pos, uint32 count, const BaseString &str) {
 	replace(pos, count, str, 0, str._size);
 }
@@ -666,6 +770,30 @@ TEMPLATE void BASESTRING::replace(uint32 posOri, uint32 countOri, const value_ty
 	memmove(_str + posOri, str + posDest, countDest * sizeof(value_type));
 }
 
+TEMPLATE void BASESTRING::replace(value_type from, value_type to) {
+	// Don't allow removing trailing \x00
+	if (from == '\x00') {
+		return;
+	}
+
+	value_type *next = cMemChr(_str, from, _size);
+	if (!next) {
+		// Nothing to do
+		return;
+	}
+
+	size_t off = next - _str;
+	makeUnique();
+
+	value_type *end = _str + _size;
+	next = _str + off;
+	while(next) {
+		*next = to;
+		next++;
+		next = cMemChr(next + 1, from, end - next);
+	}
+}
+
 TEMPLATE uint64 BASESTRING::asUint64() const {
 	uint64 result = 0;
 	for (uint32 i = 0; i < _size; ++i) {
diff --git a/common/str-base.h b/common/str-base.h
index fc7057b88f1..de58d8c3dc6 100644
--- a/common/str-base.h
+++ b/common/str-base.h
@@ -201,6 +201,51 @@ public:
 	size_t find(const value_type *s, uint32 pos = 0) const;
 	uint32 find(const BaseString &str, uint32 pos = 0) const;
 
+	/** Does a reverse find for the passed string */
+	size_t rfind(const value_type *s) const;
+	size_t rfind(const BaseString &s) const {
+		return rfind(s.c_str());
+	}
+
+	/** Does a reverse find for a passed character */
+	size_t rfind(value_type c, size_t pos = npos) const;
+
+	/** Find first character in the string matching the passed character */
+	size_t findFirstOf(value_type c, size_t pos = 0) const;
+
+	/** Find first character in the string that's any character of the passed string */
+	size_t findFirstOf(const value_type *chars, size_t pos = 0) const;
+	size_t findFirstOf(const BaseString &chars, size_t pos = 0) const {
+		return findFirstOf(chars.c_str(), pos);
+	}
+
+	/** Find the last character in the string that's the specified character */
+	size_t findLastOf(value_type c, size_t pos = npos) const;
+
+	/** Find the last character in the string that's in any of the passed characters */
+	size_t findLastOf(const value_type *chars, size_t pos = npos) const;
+	size_t findLastOf(const BaseString &chars, size_t pos = npos) const {
+		return findLastOf(chars.c_str(), pos);
+	}
+
+	/** Find first character in the string that's not the specified character */
+	size_t findFirstNotOf(value_type c, size_t pos = 0) const;
+
+	/** Find first character in the string that's not any character of the passed string */
+	size_t findFirstNotOf(const value_type *chars, size_t pos = 0) const;
+	size_t findFirstNotOf(const BaseString &chars, size_t pos = 0) const {
+		return findFirstNotOf(chars.c_str(), pos);
+	}
+
+	/** Find the last character in the string that's not the specified character */
+	size_t findLastNotOf(value_type c) const;
+
+	/** Find the last character in the string that's not in any of the passed characters */
+	size_t findLastNotOf(const value_type *chars) const;
+	size_t findLastNotOf(const BaseString &chars) const {
+		return findLastNotOf(chars.c_str());
+	}
+
 	/**@{
 	 * Functions to replace some amount of chars with chars from some other string.
 	 *
@@ -233,6 +278,13 @@ public:
 					uint32 posDest, uint32 countDest);
 	/**@}*/
 
+	/**
+	 * Replace all from characters in object by to character
+	 * @param from the character to look for
+	 * @param to The replacement character
+	 */
+	void replace(value_type from, value_type to);
+
 	/** Appends a string containing the characters between beginP (including) and endP (excluding). */
 	void append(const value_type *begin, const value_type *end);
 
diff --git a/common/str.cpp b/common/str.cpp
index d8a8a7e3591..74e3ca368fa 100644
--- a/common/str.cpp
+++ b/common/str.cpp
@@ -175,30 +175,6 @@ bool String::matchString(const String &pat, bool ignoreCase, const char *wildcar
 
 #endif
 
-void String::replace(char from, char to) {
-	// Don't allow removing trailing \x00
-	if (from == '\x00') {
-		return;
-	}
-
-	char *next = (char *)cMemChr(_str, from, _size);
-	if (!next) {
-		// Nothing to do
-		return;
-	}
-
-	size_t off = next - _str;
-	makeUnique();
-
-	char *end = _str + _size;
-	next = _str + off;
-	while(next) {
-		*next = to;
-		next++;
-		next = (char *)cMemChr(next + 1, from, end - next);
-	}
-}
-
 // static
 String String::format(const char *fmt, ...) {
 	String output;
@@ -263,110 +239,6 @@ String String::vformat(const char *fmt, va_list args) {
 	return output;
 }
 
-size_t String::rfind(const char *s) const {
-	int sLen = cStrLen(s);
-
-	for (int idx = (int)_size - sLen; idx >= 0; --idx) {
-		if (!memcmp(_str + idx, s, sLen * sizeof(value_type)))
-			return idx;
-	}
-
-	return npos;
-}
-
-size_t String::rfind(char c, size_t pos) const {
-	if (pos == npos || pos > _size)
-		pos = _size;
-	else
-		++pos;
-
-	while (pos > 0) {
-		--pos;
-		if ((*this)[pos] == c)
-			return pos;
-	}
-
-	return npos;
-}
-
-size_t String::findFirstOf(char c, size_t pos) const {
-	const char *strP = (pos >= _size) ? nullptr : cMemChr(_str + pos, c, _size - pos);
-	return strP ? strP - _str : npos;
-}
-
-size_t String::findFirstOf(const char *chars, size_t pos) const {
-	uint32 charsLen = cStrLen(chars);
-
-	for (uint idx = pos; idx < _size; ++idx) {
-		if (cMemChr(chars, (*this)[idx], charsLen))
-			return idx;
-	}
-
-	return npos;
-}
-
-size_t String::findLastOf(char c, size_t pos) const {
-	int start = (pos == npos) ? (int)_size - 1 : MIN((int)_size - 1, (int)pos);
-	for (int idx = start; idx >= 0; --idx) {
-		if ((*this)[idx] == c)
-			return idx;
-	}
-
-	return npos;
-}
-
-size_t String::findLastOf(const char *chars, size_t pos) const {
-	uint32 charsLen = cStrLen(chars);
-
-	int start = (pos == npos) ? (int)_size - 1 : MIN((int)_size - 1, (int)pos);
-	for (int idx = start; idx >= 0; --idx) {
-		if (cMemChr(chars, (*this)[idx], charsLen))
-			return idx;
-	}
-
-	return npos;
-}
-
-size_t String::findFirstNotOf(char c, size_t pos) const {
-	for (uint idx = pos; idx < _size; ++idx) {
-		if ((*this)[idx] != c)
-			return idx;
-	}
-
-	return npos;
-}
-
-size_t String::findFirstNotOf(const char *chars, size_t pos) const {
-	uint32 charsLen = cStrLen(chars);
-
-	for (uint idx = pos; idx < _size; ++idx) {
-		if (!cMemChr(chars, (*this)[idx], charsLen))
-			return idx;
-	}
-
-	return npos;
-}
-
-size_t String::findLastNotOf(char c) const {
-	for (int idx = (int)_size - 1; idx >= 0; --idx) {
-		if ((*this)[idx] != c)
-			return idx;
-	}
-
-	return npos;
-}
-
-size_t String::findLastNotOf(const char *chars) const {
-	uint32 charsLen = cStrLen(chars);
-
-	for (int idx = (int)_size - 1; idx >= 0; --idx) {
-		if (!cMemChr(chars, (*this)[idx], charsLen))
-			return idx;
-	}
-
-	return npos;
-}
-
 String String::substr(size_t pos, size_t len) const {
 	if (pos >= _size)
 		return String();
diff --git a/common/str.h b/common/str.h
index 2e5553ff002..ac3a4a11ef6 100644
--- a/common/str.h
+++ b/common/str.h
@@ -147,15 +147,6 @@ public:
 	bool matchString(const char *pat, bool ignoreCase = false, const char *wildcardExclusions = NULL) const;
 	bool matchString(const String &pat, bool ignoreCase = false, const char *wildcardExclusions = NULL) const;
 
-	using BaseString<value_type>::replace;
-
-	/**
-	 * Replace all from characters in object by to character
-	 * @param from the character to look for
-	 * @param to The replacement character
-	 */
-	void replace(char from, char to);
-
 	/**
 	 * Print formatted data into a String object. Similar to sprintf,
 	 * except that it stores the result in (variably sized) String
@@ -170,51 +161,6 @@ public:
 	 */
 	static String vformat(const char *fmt, va_list args);
 
-	/** Does a reverse find for the passed string */
-	size_t rfind(const char *s) const;
-	size_t rfind(const String &s) const {
-		return rfind(s.c_str());
-	}
-
-	/** Does a reverse find for a passed character */
-	size_t rfind(char c, size_t pos = npos) const;
-
-	/** Find first character in the string matching the passed character */
-	size_t findFirstOf(char c, size_t pos = 0) const;
-
-	/** Find first character in the string that's any character of the passed string */
-	size_t findFirstOf(const char *chars, size_t pos = 0) const;
-	size_t findFirstOf(const String &chars, size_t pos = 0) const {
-		return findFirstOf(chars.c_str(), pos);
-	}
-
-	/** Find the last character in the string that's the specified character */
-	size_t findLastOf(char c, size_t pos = npos) const;
-
-	/** Find the last character in the string that's in any of the passed characters */
-	size_t findLastOf(const char *chars, size_t pos = npos) const;
-	size_t findLastOf(const String &chars, size_t pos = npos) const {
-		return findLastOf(chars.c_str(), pos);
-	}
-
-	/** Find first character in the string that's not the specified character */
-	size_t findFirstNotOf(char c, size_t pos = 0) const;
-
-	/** Find first character in the string that's not any character of the passed string */
-	size_t findFirstNotOf(const char *chars, size_t pos = 0) const;
-	size_t findFirstNotOf(const String &chars, size_t pos = 0) const {
-		return findFirstNotOf(chars.c_str(), pos);
-	}
-
-	/** Find the last character in the string that's not the specified character */
-	size_t findLastNotOf(char c) const;
-
-	/** Find the last character in the string that's not in any of the passed characters */
-	size_t findLastNotOf(const char *chars) const;
-	size_t findLastNotOf(const String &chars) const {
-		return findLastNotOf(chars.c_str());
-	}
-
 	/** Return a substring of this string */
 	String substr(size_t pos = 0, size_t len = npos) const;
 




More information about the Scummvm-git-logs mailing list