From b564a917be72b0b4b731da70d5639a25fa99b80d Mon Sep 17 00:00:00 2001 From: Hugh Bellamy Date: Sat, 18 Feb 2017 16:15:54 +0700 Subject: [PATCH] Port swiftSyntax to Windows --- include/swift/Basic/OwnedString.h | 48 ++++--- lib/Parse/Lexer.cpp | 13 +- lib/Syntax/LegacyASTTransformer.cpp | 3 +- unittests/Basic/CMakeLists.txt | 1 + unittests/Basic/OwnedStringTest.cpp | 194 ++++++++++++++++++++++++++++ 5 files changed, 233 insertions(+), 26 deletions(-) create mode 100644 unittests/Basic/OwnedStringTest.cpp diff --git a/include/swift/Basic/OwnedString.h b/include/swift/Basic/OwnedString.h index dfc0ccbc94802..4090fd27729dc 100644 --- a/include/swift/Basic/OwnedString.h +++ b/include/swift/Basic/OwnedString.h @@ -44,28 +44,43 @@ class OwnedString { size_t Length; StringOwnership Ownership; + OwnedString(const char* Data, size_t Length, StringOwnership Ownership) + : Length(Length), Ownership(Ownership) { + assert(Length >= 0 && "expected length to be non-negative"); + + if (Ownership == StringOwnership::Copied && Data) { + assert( + Length <= strlen(Data) && + "expected length to be a valid index, within the length of the string"); + + char *substring = static_cast(malloc(Length + 1)); + assert(substring && "expected successful malloc of copy"); + + memcpy(substring, Data, Length); + substring[Length] = '\0'; + + this->Data = substring; + } + else + this->Data = Data; + } + public: - OwnedString() - : Data(nullptr), Length(0), Ownership(StringOwnership::Unowned) {} + OwnedString() : OwnedString(nullptr, 0, StringOwnership::Unowned) {} - OwnedString(const char *Data, size_t Length, StringOwnership Ownership) - : Data(Ownership == StringOwnership::Copied ? strndup(Data, Length) : Data), - Length(Length), Ownership(Ownership) {} + OwnedString(const char *Data, size_t Length) + : OwnedString(Data, Length, StringOwnership::Unowned) {} - OwnedString(StringRef Str, StringOwnership Ownership) - : OwnedString(Ownership == StringOwnership::Copied - ? strndup(Str.data(), Str.size()) - : Str.data(), - Str.size(), Ownership) {} + OwnedString(StringRef Str) : OwnedString(Str.data(), Str.size()) {} - OwnedString(const char *Data) - : OwnedString(StringRef(Data), StringOwnership::Unowned) {} + OwnedString(const char *Data) : OwnedString(StringRef(Data)) {} OwnedString(const OwnedString &Other) - : Data(Other.Ownership == StringOwnership::Copied - ? strndup(Other.Data, Other.Length) - : Other.Data), - Length(Other.Length), Ownership(Other.Ownership) {} + : OwnedString(Other.Data, Other.Length, Other.Ownership) {} + + OwnedString copy() { + return OwnedString(Data, Length, StringOwnership::Copied); + } /// Returns the length of the string in bytes. size_t size() const { @@ -96,4 +111,3 @@ class OwnedString { } // end namespace swift #endif // SWIFT_BASIC_OWNEDSTRING_H - diff --git a/lib/Parse/Lexer.cpp b/lib/Parse/Lexer.cpp index f883e3543268d..8497d3cec257d 100644 --- a/lib/Parse/Lexer.cpp +++ b/lib/Parse/Lexer.cpp @@ -737,8 +737,7 @@ syntax::RC Lexer::fullLex() { TrailingTrivia.push_front(syntax::TriviaPiece::backtick()); } auto Result = syntax::TokenSyntax::make(NextToken.getKind(), - OwnedString(NextToken.getText(), - StringOwnership::Copied), + OwnedString(NextToken.getText()).copy(), syntax::SourcePresence::Present, {LeadingTrivia}, {TrailingTrivia}); LeadingTrivia.clear(); @@ -1951,19 +1950,19 @@ Optional Lexer::lexWhitespace(bool StopAtFirstNewline) { return syntax::TriviaPiece { syntax::TriviaKind::Newline, Length, - OwnedString(Start, Length, StringOwnership::Unowned), + OwnedString(Start, Length), }; case ' ': return syntax::TriviaPiece { syntax::TriviaKind::Space, Length, - OwnedString(Start, Length, StringOwnership::Unowned), + OwnedString(Start, Length), }; case '\t': return syntax::TriviaPiece { syntax::TriviaKind::Tab, Length, - OwnedString(Start, Length, StringOwnership::Unowned), + OwnedString(Start, Length), }; default: return None; @@ -1982,7 +1981,7 @@ Optional Lexer::lexSingleLineComment(syntax::TriviaKind Kin return Optional({ Kind, Length, - OwnedString(Start, Length, StringOwnership::Unowned) + OwnedString(Start, Length) }); } @@ -1997,7 +1996,7 @@ Lexer::lexBlockComment(syntax::TriviaKind Kind) { return Optional({ Kind, Length, - OwnedString(Start, Length, StringOwnership::Unowned) + OwnedString(Start, Length) }); } diff --git a/lib/Syntax/LegacyASTTransformer.cpp b/lib/Syntax/LegacyASTTransformer.cpp index f5efa5c952cec..a6e0286a5bfb4 100644 --- a/lib/Syntax/LegacyASTTransformer.cpp +++ b/lib/Syntax/LegacyASTTransformer.cpp @@ -296,8 +296,7 @@ LegacyASTTransformer::visitStructDecl(StructDecl *D, if (D->getNameLoc().isValid()) { auto Identifier = findTokenSyntax(tok::identifier, - OwnedString(D->getName().str(), - StringOwnership::Unowned), + OwnedString(D->getName().str()), SourceMgr, D->getNameLoc(), BufferID, Tokens); StructBuilder.useIdentifier(Identifier); diff --git a/unittests/Basic/CMakeLists.txt b/unittests/Basic/CMakeLists.txt index e28dbacb9f4c3..d405fdea80584 100644 --- a/unittests/Basic/CMakeLists.txt +++ b/unittests/Basic/CMakeLists.txt @@ -15,6 +15,7 @@ add_swift_unittest(SwiftBasicTests FileSystemTest.cpp ImmutablePointerSetTest.cpp OptionSetTest.cpp + OwnedStringTest.cpp PointerIntEnumTest.cpp PrefixMapTest.cpp RangeTest.cpp diff --git a/unittests/Basic/OwnedStringTest.cpp b/unittests/Basic/OwnedStringTest.cpp new file mode 100644 index 0000000000000..edf26ef5b72fd --- /dev/null +++ b/unittests/Basic/OwnedStringTest.cpp @@ -0,0 +1,194 @@ +//===--- OwnedStringTest.cpp ----------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +#include "swift/Basic/OwnedString.h" +#include "gtest/gtest.h" + +using namespace swift; + +TEST(OwnedStringTest, char_pointer_empty) { + const char *data = ""; + const size_t length = strlen(data); + OwnedString ownedString(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()); +} + +TEST(OwnedStringTest, char_pointer_non_empty) { + const char *data = "string"; + const size_t length = strlen(data); + OwnedString ownedString(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())); +} + +TEST(OwnedStringTest, char_pointer_length_equal) { + const char *data = "string"; + size_t length = strlen(data); + OwnedString ownedString(data, length); + + 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("string", str); + EXPECT_EQ(length, strlen(str.data())); +} + +TEST(OwnedStringTest, char_pointer_length_nonzero) { + const char *data = "string"; + const size_t length = 1; + OwnedString ownedString(data, length); + + 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(1, 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(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(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("atring", 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(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); +}