Forráskód Böngészése

Sharing new buffer with all elements when splitting a string literal.

David Piuva 5 éve
szülő
commit
44c6498c68
2 módosított fájl, 34 hozzáadás és 22 törlés
  1. 12 18
      Source/DFPSR/base/text.cpp
  2. 22 4
      Source/test/tests/StringTest.cpp

+ 12 - 18
Source/DFPSR/base/text.cpp

@@ -964,26 +964,20 @@ static void string_split_callback_shared(std::function<void(String)> action, con
 
 List<String> dsr::string_split(const ReadableString& source, DsrChar separator, bool removeWhiteSpace) {
 	List<String> result;
+	String commonBuffer;
 	const String* sharedSource = dynamic_cast<const String*>(&source);
-	if (sharedSource != nullptr) {
-		// Source is allocated as String
-		string_split_callback_shared([&result, removeWhiteSpace](String element) {
-			if (removeWhiteSpace) {
-				result.push(string_removeOuterWhiteSpace_shared(element));
-			} else {
-				result.push(element);
-			}
-		}, source, separator, removeWhiteSpace);
-	} else {
-		// Source is allocated as ReadableString
-		string_split_callback([&result, removeWhiteSpace](ReadableString element) {
-			if (removeWhiteSpace) {
-				result.push(string_removeOuterWhiteSpace(element));
-			} else {
-				result.push(element);
-			}
-		}, source, separator, removeWhiteSpace);
+	if (sharedSource == nullptr) {
+		// Clone the whole input into one allocation to avoid fragmenting the heap with many small allocations
+		commonBuffer = source;
 	}
+	// Source is allocated as String
+	string_split_callback_shared([&result, removeWhiteSpace](String element) {
+		if (removeWhiteSpace) {
+			result.push(string_removeOuterWhiteSpace_shared(element));
+		} else {
+			result.push(element);
+		}
+	}, source, separator, removeWhiteSpace);
 	return result;
 }
 

+ 22 - 4
Source/test/tests/StringTest.cpp

@@ -256,17 +256,17 @@ START_TEST(String)
 		ASSERT_EQUAL(string_getBufferUseCount(c), 3);
 	}
 	{ // String splitting by shared reference counted buffer
-		String source = U"a . b . c . d";
-		String source2 = U"a . b .\tc";
+		String source = U" a . b . c . d ";
+		String source2 = U" a . b .\tc ";
 		ASSERT_EQUAL(string_getBufferUseCount(source), 1);
 		ASSERT_EQUAL(string_getBufferUseCount(source2), 1);
 		List<String> result;
 		result = string_split(source, U'.', false);
 		ASSERT_EQUAL(result.length(), 4);
-		ASSERT_MATCH(result[0], U"a ");
+		ASSERT_MATCH(result[0], U" a ");
 		ASSERT_MATCH(result[1], U" b ");
 		ASSERT_MATCH(result[2], U" c ");
-		ASSERT_MATCH(result[3], U" d");
+		ASSERT_MATCH(result[3], U" d ");
 		ASSERT_EQUAL(string_getBufferUseCount(source), 5);
 		ASSERT_EQUAL(string_getBufferUseCount(source2), 1);
 		result = string_split(source2, U'.', true);
@@ -277,6 +277,24 @@ START_TEST(String)
 		ASSERT_EQUAL(string_getBufferUseCount(source), 1);
 		ASSERT_EQUAL(string_getBufferUseCount(source2), 4);
 	}
+	{ // Automatically allocating a shared buffer for many elements
+		List<String> result = string_split(U" a . b . c . d ", U'.', true);
+		ASSERT_MATCH(result[0], U"a");
+		ASSERT_MATCH(result[1], U"b");
+		ASSERT_MATCH(result[2], U"c");
+		ASSERT_MATCH(result[3], U"d");
+		ASSERT_EQUAL(string_getBufferUseCount(result[0]), 4);
+		ASSERT_EQUAL(string_getBufferUseCount(result[1]), 4);
+		ASSERT_EQUAL(string_getBufferUseCount(result[2]), 4);
+		ASSERT_EQUAL(string_getBufferUseCount(result[3]), 4);
+		result = string_split(U" a . b . c ", U'.', false);
+		ASSERT_MATCH(result[0], U" a ");
+		ASSERT_MATCH(result[1], U" b ");
+		ASSERT_MATCH(result[2], U" c ");
+		ASSERT_EQUAL(string_getBufferUseCount(result[0]), 3);
+		ASSERT_EQUAL(string_getBufferUseCount(result[1]), 3);
+		ASSERT_EQUAL(string_getBufferUseCount(result[2]), 3);
+	}
 	{ // Callback splitting
 		String numbers = U"1, 3, 5, 7, 9";
 		List<int> result;