mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[libSyntax] Add a reference counted version of OwnedString
We cannot use unowned strings for token texts of incrementally parsed syntax trees since the source buffer to which reused nodes refer will have been freed for reused nodes. Always copying the token text whenever OwnedString is passed is too expensive. A reference counted copy of the string allows us to keep the token's string alive across incremental parses while eliminating unnecessary copies.
This commit is contained in:
@@ -18,177 +18,43 @@ using namespace swift;
|
||||
TEST(OwnedStringTest, char_pointer_empty) {
|
||||
const char *data = "";
|
||||
const size_t length = strlen(data);
|
||||
OwnedString ownedString(data);
|
||||
OwnedString ownedString = OwnedString::makeUnowned(data);
|
||||
|
||||
EXPECT_EQ(length, ownedString.size());
|
||||
EXPECT_TRUE(ownedString.empty());
|
||||
|
||||
OwnedString copy = ownedString.copy();
|
||||
EXPECT_EQ(length, copy.size());
|
||||
EXPECT_TRUE(copy.empty());
|
||||
|
||||
StringRef str = copy.str();
|
||||
EXPECT_EQ("", str);
|
||||
EXPECT_EQ(length, str.size());
|
||||
EXPECT_EQ(data, ownedString.str().data());
|
||||
}
|
||||
|
||||
TEST(OwnedStringTest, char_pointer_non_empty) {
|
||||
const char *data = "string";
|
||||
const size_t length = strlen(data);
|
||||
OwnedString ownedString(data);
|
||||
OwnedString ownedString = OwnedString::makeUnowned(data);
|
||||
|
||||
EXPECT_EQ(length, ownedString.size());
|
||||
EXPECT_FALSE(ownedString.empty());
|
||||
|
||||
OwnedString copy = ownedString.copy();
|
||||
EXPECT_EQ(length, copy.size());
|
||||
EXPECT_FALSE(copy.empty());
|
||||
|
||||
StringRef str = copy.str();
|
||||
EXPECT_EQ("string", str);
|
||||
EXPECT_EQ(length, strlen(str.data()));
|
||||
EXPECT_EQ(data, ownedString.str().data());
|
||||
}
|
||||
|
||||
TEST(OwnedStringTest, char_pointer_length_equal) {
|
||||
const char *data = "string";
|
||||
TEST(OwnedStringTest, ref_counted_copies_buffer) {
|
||||
char *data = static_cast<char *>(malloc(6));
|
||||
memcpy(data, "hello", 6);
|
||||
size_t length = strlen(data);
|
||||
OwnedString ownedString(data, length);
|
||||
|
||||
EXPECT_EQ(length, ownedString.size());
|
||||
EXPECT_FALSE(ownedString.empty());
|
||||
OwnedString ownedString =
|
||||
OwnedString::makeRefCounted(StringRef(data, length));
|
||||
|
||||
OwnedString copy = ownedString.copy();
|
||||
EXPECT_EQ(length, copy.size());
|
||||
EXPECT_FALSE(copy.empty());
|
||||
EXPECT_EQ(ownedString.str(), "hello");
|
||||
EXPECT_NE(ownedString.str().data(), data);
|
||||
|
||||
// Make sure we correctly copied the data and that it is null
|
||||
// terminated.
|
||||
StringRef str = copy.str();
|
||||
EXPECT_EQ("string", str);
|
||||
EXPECT_EQ(length, strlen(str.data()));
|
||||
memcpy(data, "world", 6);
|
||||
|
||||
// Even if the original buffer changes, the string should stay the same
|
||||
EXPECT_EQ(ownedString.str(), "hello");
|
||||
}
|
||||
|
||||
TEST(OwnedStringTest, char_pointer_length_nonzero) {
|
||||
const char *data = "string";
|
||||
const size_t length = 1;
|
||||
OwnedString ownedString(data, length);
|
||||
TEST(OwnedStringTest, ref_counted_assignment) {
|
||||
OwnedString str = OwnedString::makeRefCounted("hello");
|
||||
OwnedString copy = str;
|
||||
|
||||
EXPECT_EQ(length, ownedString.size());
|
||||
EXPECT_FALSE(ownedString.empty());
|
||||
|
||||
OwnedString copy = ownedString.copy();
|
||||
EXPECT_EQ(length, copy.size());
|
||||
EXPECT_FALSE(copy.empty());
|
||||
|
||||
// Make sure we correctly copied the data and that it is null
|
||||
// terminated.
|
||||
StringRef str = copy.str();
|
||||
EXPECT_EQ("s", str);
|
||||
EXPECT_EQ(1UL, strlen(str.data()));
|
||||
}
|
||||
|
||||
TEST(OwnedStringTest, char_pointer_length_zero) {
|
||||
const char *data = "string";
|
||||
const size_t length = 0;
|
||||
OwnedString ownedString(data, length);
|
||||
|
||||
EXPECT_EQ(length, ownedString.size());
|
||||
EXPECT_TRUE(ownedString.empty());
|
||||
|
||||
OwnedString copy = ownedString.copy();
|
||||
EXPECT_EQ(length, copy.size());
|
||||
EXPECT_TRUE(copy.empty());
|
||||
}
|
||||
|
||||
TEST(OwnedStringTest, copy_original_new_different) {
|
||||
// Initialize a mutable string.
|
||||
const char *original = "string";
|
||||
const size_t length = strlen(original);
|
||||
char *data = static_cast<char *>(malloc(length + 1));
|
||||
memcpy(data, original, length);
|
||||
data[length] = '\0';
|
||||
|
||||
// Create an OwnedString.
|
||||
OwnedString ownedString(data, length);
|
||||
|
||||
EXPECT_EQ(length, ownedString.size());
|
||||
EXPECT_FALSE(ownedString.empty());
|
||||
|
||||
// Copy the string
|
||||
OwnedString copy = ownedString.copy();
|
||||
EXPECT_EQ(length, copy.size());
|
||||
EXPECT_FALSE(copy.empty());
|
||||
|
||||
// Make sure we correctly copied the data and that it is null
|
||||
// terminated.
|
||||
StringRef str = copy.str();
|
||||
EXPECT_EQ("string", str);
|
||||
EXPECT_EQ(length, strlen(str.data()));
|
||||
|
||||
// Make sure updating the original pointer doesn't affect the copy.
|
||||
data[0] = 'a';
|
||||
|
||||
EXPECT_EQ("string", str);
|
||||
}
|
||||
|
||||
TEST(OwnedStringTest, copy_constructor_original_not_copy) {
|
||||
// Initialize a mutable string.
|
||||
const char *original = "string";
|
||||
const size_t length = strlen(original);
|
||||
char *data = static_cast<char *>(malloc(length + 1));
|
||||
memcpy(data, original, length);
|
||||
data[length] = '\0';
|
||||
|
||||
// Create an OwnedString.
|
||||
OwnedString ownedString(data, length);
|
||||
|
||||
EXPECT_EQ(length, ownedString.size());
|
||||
EXPECT_FALSE(ownedString.empty());
|
||||
|
||||
// Copy the string
|
||||
OwnedString copy = OwnedString(ownedString);
|
||||
EXPECT_EQ(length, copy.size());
|
||||
EXPECT_FALSE(copy.empty());
|
||||
|
||||
// Make sure we correctly copied the data and that it is null
|
||||
// terminated.
|
||||
StringRef str = copy.str();
|
||||
EXPECT_EQ("string", str);
|
||||
EXPECT_EQ(length, strlen(str.data()));
|
||||
|
||||
// Make sure updating the original pointer doesn't affect the copy.
|
||||
data[0] = 'a';
|
||||
|
||||
EXPECT_EQ("string", str);
|
||||
}
|
||||
|
||||
TEST(OwnedStringTest, copy_constructor_original_copy) {
|
||||
// Initialize a mutable string.
|
||||
const char *original = "string";
|
||||
const size_t length = strlen(original);
|
||||
char *data = static_cast<char *>(malloc(length + 1));
|
||||
memcpy(data, original, length);
|
||||
data[length] = '\0';
|
||||
|
||||
// Create an OwnedString.
|
||||
OwnedString ownedString(data, length);
|
||||
|
||||
EXPECT_EQ(length, ownedString.size());
|
||||
EXPECT_FALSE(ownedString.empty());
|
||||
|
||||
// Copy the string
|
||||
OwnedString copy = OwnedString(ownedString.copy());
|
||||
EXPECT_EQ(length, copy.size());
|
||||
EXPECT_FALSE(copy.empty());
|
||||
|
||||
// Make sure we correctly copied the data and that it is null
|
||||
// terminated.
|
||||
StringRef str = copy.str();
|
||||
EXPECT_EQ("string", str);
|
||||
EXPECT_EQ(length, strlen(str.data()));
|
||||
|
||||
// Make sure updating the original pointer doesn't affect the copy.
|
||||
data[0] = 'a';
|
||||
|
||||
EXPECT_EQ("string", str);
|
||||
EXPECT_EQ(str.str().data(), copy.str().data());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user