//===--- OwnedString.h - String storage -------------------------*- C++ -*-===// // // 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 // //===----------------------------------------------------------------------===// // // This file defines the 'OwnedString' storage wrapper, which can hold its own // unique copy of a string, or merely hold a reference to some point in a // source buffer, which is assumed to live at least as long as a value of this // type. // //===----------------------------------------------------------------------===// #ifndef SWIFT_BASIC_OWNEDSTRING_H #define SWIFT_BASIC_OWNEDSTRING_H #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringRef.h" using llvm::StringRef; namespace swift { enum class StringOwnership { /// An OwnedString holds a weak reference to the underlying string storage /// and will never attempt to free it. Unowned, /// An OwnedString has its own copy of the underlying string storage and /// will free the storage upon its destruction. Copied, }; /// Holds a string - either statically allocated or dynamically allocated /// and owned by this type. class OwnedString { const char *Data; size_t Length; StringOwnership Ownership = StringOwnership::Unowned; void release() { if (Ownership == StringOwnership::Copied) free(const_cast(Data)); } void initialize(const char* Data, size_t Length, StringOwnership Ownership) { this->Length = Length; this->Ownership = Ownership; if (Ownership == StringOwnership::Copied && Data) { 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; } OwnedString(const char* Data, size_t Length, StringOwnership Ownership) { initialize(Data, Length, Ownership); } public: OwnedString(): OwnedString(nullptr, 0, StringOwnership::Unowned) {} OwnedString(const char *Data, size_t Length): OwnedString(Data, Length, StringOwnership::Unowned) {} OwnedString(StringRef Str) : OwnedString(Str.data(), Str.size()) {} OwnedString(const char *Data) : OwnedString(StringRef(Data)) {} OwnedString(const OwnedString &Other): OwnedString(Other.Data, Other.Length, Other.Ownership) {} OwnedString(OwnedString &&Other): Data(Other.Data), Length(Other.Length), Ownership(Other.Ownership) { Other.Data = nullptr; Other.Ownership = StringOwnership::Unowned; } OwnedString& operator=(const OwnedString &Other) { if (&Other != this) { release(); initialize(Other.Data, Other.Length, Other.Ownership); } return *this; } OwnedString& operator=(OwnedString &&Other) { if (&Other != this) { release(); this->Data = Other.Data; this->Length = Other.Length; this->Ownership = Other.Ownership; Other.Ownership = StringOwnership::Unowned; Other.Data = nullptr; } return *this; } OwnedString copy() { return OwnedString(Data, Length, StringOwnership::Copied); } /// Returns the length of the string in bytes. size_t size() const { return Length; } /// Returns true if the length is 0. bool empty() const { return Length == 0; } /// Returns a StringRef to the underlying data. No copy is made and no /// ownership changes take place. StringRef str() const { return StringRef { Data, Length }; } bool operator==(const OwnedString &Right) const { return str() == Right.str(); } ~OwnedString() { release(); } }; } // end namespace swift #endif // SWIFT_BASIC_OWNEDSTRING_H