blob: 483fd67ba4500a5baab2a5c98f70e0887ce1da50 [file] [log] [blame]
//===--- 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<char *>(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<char *>(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