Browse Source

Reusing buffer when casting a String back from ReadableString.

David Piuva 5 years ago
parent
commit
dc7ae4e7e0
2 changed files with 20 additions and 10 deletions
  1. 5 10
      Source/DFPSR/base/text.cpp
  2. 15 0
      Source/test/tests/StringTest.cpp

+ 5 - 10
Source/DFPSR/base/text.cpp

@@ -84,16 +84,11 @@ String::String(const String& source) {
 	this->writeSection = source.writeSection;
 	this->writeSection = source.writeSection;
 }
 }
 String::String(const ReadableString& source) {
 String::String(const ReadableString& source) {
-	const String* sharedSource = dynamic_cast<const String*>(&source);
-	if (sharedSource != nullptr) {
-		// Share immutable buffer when assigning String referred to as ReadableString
-		// + Passing String as a ReadableString reference is okay
-		// - Assigning String to a ReadableString loses access to the buffer
-		//   by having to construct a read-only string pointing to the data
-		this->readSection = sharedSource->readSection;
-		this->length = sharedSource->length;
-		this->buffer = sharedSource->buffer;
-		this->writeSection = sharedSource->writeSection;
+	if (buffer_exists(source.buffer)) {
+		this->readSection = source.readSection;
+		this->length = source.length;
+		this->buffer = source.buffer;
+		this->writeSection = const_cast<char32_t*>(source.readSection); // Still safe because of immutability
 	} else {
 	} else {
 		// No buffer to share, just appending the content
 		// No buffer to share, just appending the content
 		this->append(source);
 		this->append(source);

+ 15 - 0
Source/test/tests/StringTest.cpp

@@ -277,6 +277,21 @@ START_TEST(String)
 		ASSERT_EQUAL(string_getBufferUseCount(source), 1);
 		ASSERT_EQUAL(string_getBufferUseCount(source), 1);
 		ASSERT_EQUAL(string_getBufferUseCount(source2), 4);
 		ASSERT_EQUAL(string_getBufferUseCount(source2), 4);
 	}
 	}
+	{ // Using buffer remembered in ReadableString to reuse memory for splitting
+		String original = U" a . b . c . d ";
+		ReadableString borrowsTheBuffer = string_after(original, 3);
+		ASSERT_MATCH(borrowsTheBuffer, U" b . c . d ");
+		List<String> result = string_split(borrowsTheBuffer, U'.', true);
+		ASSERT_EQUAL(result.length(), 3);
+		ASSERT_MATCH(result[0], U"b");
+		ASSERT_MATCH(result[1], U"c");
+		ASSERT_MATCH(result[2], U"d");
+		ASSERT_EQUAL(string_getBufferUseCount(original), 5);
+		ASSERT_EQUAL(string_getBufferUseCount(borrowsTheBuffer), 5);
+		ASSERT_EQUAL(string_getBufferUseCount(result[0]), 5);
+		ASSERT_EQUAL(string_getBufferUseCount(result[1]), 5);
+		ASSERT_EQUAL(string_getBufferUseCount(result[2]), 5);
+	}
 	{ // Automatically allocating a shared buffer for many elements
 	{ // Automatically allocating a shared buffer for many elements
 		List<String> result = string_split(U" a . b . c . d ", U'.', true);
 		List<String> result = string_split(U" a . b . c . d ", U'.', true);
 		ASSERT_MATCH(result[0], U"a");
 		ASSERT_MATCH(result[0], U"a");