mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
125 lines
4.7 KiB
C++
125 lines
4.7 KiB
C++
//===--- 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"
|
|
#include "llvm/Support/TrailingObjects.h"
|
|
|
|
using llvm::StringRef;
|
|
|
|
namespace swift {
|
|
|
|
/// Holds a string - either statically allocated or dynamically allocated
|
|
/// and owned by this type.
|
|
class OwnedString {
|
|
/// An owner that keeps the buffer of a ref counted \c OwnedString alive.
|
|
class TextOwner final : public llvm::ThreadSafeRefCountedBase<TextOwner>,
|
|
public llvm::TrailingObjects<TextOwner, char> {
|
|
TextOwner(StringRef Text) {
|
|
std::uninitialized_copy(Text.begin(), Text.end(),
|
|
getTrailingObjects<char>());
|
|
}
|
|
|
|
public:
|
|
static TextOwner *make(StringRef Text) {
|
|
auto size = totalSizeToAlloc<char>(Text.size());
|
|
void *data = ::operator new(size);
|
|
return new (data) TextOwner(Text);
|
|
}
|
|
|
|
/// Disable sized deallocation for TextOwner, because it has tail-allocated
|
|
/// data.
|
|
void operator delete(void *p) { ::operator delete(p); }
|
|
|
|
const char *getText() const { return getTrailingObjects<char>(); }
|
|
};
|
|
|
|
/// The text this owned string represents
|
|
StringRef Text;
|
|
|
|
/// In case of a ref counted string an owner that keeps the buffer \c Text
|
|
/// references alive.
|
|
llvm::IntrusiveRefCntPtr<TextOwner> OwnedPtr;
|
|
|
|
OwnedString(StringRef Text, llvm::IntrusiveRefCntPtr<TextOwner> OwnedPtr)
|
|
: Text(Text), OwnedPtr(OwnedPtr) {}
|
|
|
|
public:
|
|
OwnedString() : OwnedString(/*Text=*/StringRef(), /*OwnedPtr=*/nullptr) {}
|
|
|
|
/// Create a ref counted \c OwnedString that is initialized with the text of
|
|
/// the given \c StringRef.
|
|
OwnedString(StringRef Str) : OwnedString(makeRefCounted(Str)) {}
|
|
|
|
/// Create a ref counted \c OwnedString that is initialized with the text of
|
|
/// the given buffer.
|
|
OwnedString(const char *Str) : OwnedString(StringRef(Str)) {}
|
|
|
|
/// Create an \c OwnedString that references the given string. The
|
|
/// \c OwnedString will not take ownership of that buffer and will assume that
|
|
/// the buffer outlives its lifetime.
|
|
static OwnedString makeUnowned(StringRef Str) {
|
|
return OwnedString(Str, /*OwnedPtr=*/nullptr);
|
|
}
|
|
|
|
/// Create an \c OwnedString that keeps its contents in a reference counted
|
|
/// buffer. The contents of \p Str will be copied initially and are allowed to
|
|
/// be disposed after the \c OwnedString has been created.
|
|
static OwnedString makeRefCounted(StringRef Str) {
|
|
if (Str.empty()) {
|
|
// Copying an empty string doesn't make sense. Just create an unowned
|
|
// string that points to the empty string.
|
|
return makeUnowned(Str);
|
|
} else {
|
|
llvm::IntrusiveRefCntPtr<TextOwner> OwnedPtr(TextOwner::make(Str));
|
|
// Allocate the StringRef on the stack first. This is to ensure that the
|
|
// order of evaluation of the arguments is specified. The specification
|
|
// does not specify the order of evaluation for the arguments. Itanium
|
|
// chose to evaluate left to right, while Windows evaluates right to left.
|
|
// As such, it is possible that the OwnedPtr has already been `std::move`d
|
|
// by the time that the StringRef is attempted to be created. In such a
|
|
// case, the offset of the field (+4) is used instead of the pointer to
|
|
// the text, resulting in invalid memory references.
|
|
StringRef S(OwnedPtr->getText(), Str.size());
|
|
return OwnedString(S, std::move(OwnedPtr));
|
|
}
|
|
}
|
|
|
|
/// Returns the length of the string in bytes.
|
|
size_t size() const { return Text.size(); }
|
|
|
|
/// Returns true if the length is 0.
|
|
bool empty() const { return size() == 0; }
|
|
|
|
/// Returns a StringRef to the underlying data. No copy is made and no
|
|
/// ownership changes take place.
|
|
StringRef str() const { return Text; }
|
|
|
|
bool operator==(const OwnedString &Right) const {
|
|
return str() == Right.str();
|
|
}
|
|
};
|
|
|
|
} // end namespace swift
|
|
|
|
#endif // SWIFT_BASIC_OWNEDSTRING_H
|