Update LLVM to latest upstream. (#1080)

Also change header guards to WPI header guards.
Remove StringRef::c_str() customization, replacing the handful of uses with Twine or SmallString.
TCPStream: Include errno.h and make Windows includes lowercase for consistency.

Upstream LLVM version: eb4186cca7924fb1706357545311a2fa3de40c59
This commit is contained in:
Peter Johnson
2018-05-22 23:31:08 -07:00
committed by GitHub
parent 680aabbe7c
commit a2ecb1027a
62 changed files with 5956 additions and 2522 deletions

View File

@@ -1,4 +1,4 @@
//===--- StringRef.h - Constant String Reference Wrapper --------*- C++ -*-===//
//===- StringRef.h - Constant String Reference Wrapper ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,23 +7,26 @@
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ADT_STRINGREF_H
#define LLVM_ADT_STRINGREF_H
#ifndef WPIUTIL_WPI_STRINGREF_H
#define WPIUTIL_WPI_STRINGREF_H
#include "wpi/STLExtras.h"
#include "wpi/iterator_range.h"
#include "wpi/Compiler.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstring>
#include <iosfwd>
#include <limits>
#include <ostream>
#include <string>
#include <type_traits>
#include <utility>
namespace wpi {
template <typename T>
class SmallVectorImpl;
class hash_code;
template <typename T> class SmallVectorImpl;
class StringRef;
/// Helper functions for StringRef::getAsInteger.
@@ -32,6 +35,10 @@ namespace wpi {
bool getAsSignedInteger(StringRef Str, unsigned Radix, long long &Result) noexcept;
bool consumeUnsignedInteger(StringRef &Str, unsigned Radix,
unsigned long long &Result) noexcept;
bool consumeSignedInteger(StringRef &Str, unsigned Radix, long long &Result) noexcept;
/// StringRef - Represent a constant reference to a string, i.e. a character
/// array and a length, which need not be null terminated.
///
@@ -41,76 +48,56 @@ namespace wpi {
/// general safe to store a StringRef.
class StringRef {
public:
typedef const char *iterator;
typedef const char *const_iterator;
static const size_t npos = ~size_t(0);
typedef size_t size_type;
using iterator = const char *;
using const_iterator = const char *;
using size_type = size_t;
private:
/// The start of the string, in an external buffer.
const char *Data;
const char *Data = nullptr;
/// The length of the string.
/// MSB of length indicates if we are null terminated or not
/// Flag set is null terminated, flag not set is not
size_t Length;
size_t Length = 0;
// Workaround memcmp issue with null pointers (undefined behavior)
// by providing a specialized version
LLVM_ATTRIBUTE_ALWAYS_INLINE
static int compareMemory(const char *Lhs, const char *Rhs, size_t Length) noexcept {
if (Length == 0) { return 0; }
return ::memcmp(Lhs,Rhs,Length);
}
/// Set the flag to say we are null terminated
void set_null_terminated(bool set) noexcept {
if (set)
Length |= ((size_t)1 << (sizeof(size_t) * 8 - 1));
else {
Length &= ~((size_t)1 << (sizeof(size_t) * 8 - 1));
}
}
public:
/// @name Constructors
/// @{
/// Construct an empty string ref.
/*implicit*/ StringRef() noexcept : Data(""), Length(0) {
set_null_terminated(true);
}
/*implicit*/ StringRef() = default;
/// Disable conversion from nullptr. This prevents things like
/// if (S == nullptr)
StringRef(std::nullptr_t) = delete;
/// Construct a string ref from a cstring.
/*implicit*/ StringRef(const char *Str) noexcept
: Data(Str) {
assert(Str && "StringRef cannot be built from a NULL argument");
Length = ::strlen(Str); // invoking strlen(NULL) is undefined behavior
// Require length to not use MSB of size
assert(Length < ~((size_t)1 << (sizeof(size_t) * 8 - 1)));
// If from a const char*, we are null terminated
set_null_terminated(true);
}
LLVM_ATTRIBUTE_ALWAYS_INLINE
/*implicit*/ StringRef(const char *Str)
: Data(Str), Length(Str ? ::strlen(Str) : 0) {}
/// Construct a string ref from a pointer and length.
/*implicit*/ StringRef(const char *data, size_t length, bool isNullTerminated = false) noexcept
: Data(data), Length(length) {
assert((data || length == 0) &&
"StringRef cannot be built from a NULL argument with non-null length");
// Require length to not use MSB of size
assert(Length < ~((size_t)1 << (sizeof(size_t) * 8 - 1)));
// If passed an explicit length, use the parameter
// Default to false (not null) to match previous behavior.
set_null_terminated(isNullTerminated);
}
LLVM_ATTRIBUTE_ALWAYS_INLINE
/*implicit*/ constexpr StringRef(const char *data, size_t length)
: Data(data), Length(length) {}
/// Construct a string ref from an std::string.
LLVM_ATTRIBUTE_ALWAYS_INLINE
/*implicit*/ StringRef(const std::string &Str)
: Data(Str.data()), Length(Str.length()) {
// Require length to not use MSB of size
assert(Length < ~((size_t)1 << (sizeof(size_t) * 8 - 1)));
// If from a std::string, we are null terminated
set_null_terminated(true);
}
: Data(Str.data()), Length(Str.length()) {}
static StringRef withNullAsEmpty(const char *data) {
return StringRef(data ? data : "");
}
/// @}
/// @name Iterators
@@ -118,7 +105,7 @@ namespace wpi {
iterator begin() const noexcept { return Data; }
iterator end() const noexcept { return Data + size(); }
iterator end() const noexcept { return Data + Length; }
const unsigned char *bytes_begin() const noexcept {
return reinterpret_cast<const unsigned char *>(begin());
@@ -136,95 +123,110 @@ namespace wpi {
/// data - Get a pointer to the start of the string (which may not be null
/// terminated).
LLVM_NODISCARD
LLVM_ATTRIBUTE_ALWAYS_INLINE
const char *data() const noexcept { return Data; }
/// c_str - Get a null terminated pointer to the start of the string
/// If string is not null terminated, use buffer to store new string
const char *c_str(wpi::SmallVectorImpl<char>& buf) const;
/// empty - Check if the string is empty.
LLVM_NODISCARD
LLVM_ATTRIBUTE_ALWAYS_INLINE
bool empty() const noexcept { return size() == 0; }
/// size - Get the string size.
size_t size() const noexcept {
return Length & ~((size_t)1 << (sizeof(size_t) * 8 - 1));
}
/// is_null_terminated - Get if the string is guaranteed null terminated
bool is_null_terminated() const noexcept {
return (Length & ((size_t)1 << (sizeof(size_t) * 8 - 1))) ==
((size_t)1 << (sizeof(size_t) * 8 - 1));
}
LLVM_NODISCARD
LLVM_ATTRIBUTE_ALWAYS_INLINE
size_t size() const noexcept { return Length; }
/// front - Get the first character in the string.
LLVM_NODISCARD
char front() const noexcept {
assert(!empty());
return Data[0];
}
/// back - Get the last character in the string.
LLVM_NODISCARD
char back() const noexcept {
assert(!empty());
return Data[size()-1];
return Data[Length-1];
}
// copy - Allocate copy in Allocator and return StringRef to it.
template <typename Allocator> StringRef copy(Allocator &A) const {
template <typename Allocator>
LLVM_NODISCARD StringRef copy(Allocator &A) const {
// Don't request a length 0 copy from the allocator.
if (empty())
return StringRef();
char *S = A.template Allocate<char>(size());
char *S = A.template Allocate<char>(Length);
std::copy(begin(), end(), S);
return StringRef(S, size());
return StringRef(S, Length);
}
/// equals - Check for string equality, this is more efficient than
/// compare() when the relative ordering of inequal strings isn't needed.
LLVM_NODISCARD
LLVM_ATTRIBUTE_ALWAYS_INLINE
bool equals(StringRef RHS) const noexcept {
return (size() == RHS.size() &&
compareMemory(Data, RHS.Data, RHS.size()) == 0);
return (Length == RHS.Length &&
compareMemory(Data, RHS.Data, RHS.Length) == 0);
}
/// equals_lower - Check for string equality, ignoring case.
LLVM_NODISCARD
bool equals_lower(StringRef RHS) const noexcept {
return size() == RHS.size() && compare_lower(RHS) == 0;
return Length == RHS.Length && compare_lower(RHS) == 0;
}
/// compare - Compare two strings; the result is -1, 0, or 1 if this string
/// is lexicographically less than, equal to, or greater than the \p RHS.
LLVM_NODISCARD
LLVM_ATTRIBUTE_ALWAYS_INLINE
int compare(StringRef RHS) const noexcept {
// Check the prefix for a mismatch.
if (int Res = compareMemory(Data, RHS.Data, std::min(size(), RHS.size())))
if (int Res = compareMemory(Data, RHS.Data, std::min(Length, RHS.Length)))
return Res < 0 ? -1 : 1;
// Otherwise the prefixes match, so we only need to check the lengths.
if (size() == RHS.size())
if (Length == RHS.Length)
return 0;
return size() < RHS.size() ? -1 : 1;
return Length < RHS.Length ? -1 : 1;
}
/// compare_lower - Compare two strings, ignoring case.
LLVM_NODISCARD
int compare_lower(StringRef RHS) const noexcept;
/// compare_numeric - Compare two strings, treating sequences of digits as
/// numbers.
LLVM_NODISCARD
int compare_numeric(StringRef RHS) const noexcept;
/// str - Get the contents as an std::string.
LLVM_NODISCARD
std::string str() const {
if (!Data) return std::string();
return std::string(Data, size());
return std::string(Data, Length);
}
/// @}
/// @name Operator Overloads
/// @{
LLVM_NODISCARD
char operator[](size_t Index) const noexcept {
assert(Index < size() && "Invalid index!");
assert(Index < Length && "Invalid index!");
return Data[Index];
}
/// Disallow accidental assignment from a temporary std::string.
///
/// The declaration here is extra complicated so that `stringRef = {}`
/// and `stringRef = "abc"` continue to select the move assignment operator.
template <typename T>
typename std::enable_if<std::is_same<T, std::string>::value,
StringRef>::type &
operator=(T &&Str) = delete;
/// @}
/// @name Type Conversions
/// @{
@@ -238,21 +240,27 @@ namespace wpi {
/// @{
/// Check if this string starts with the given \p Prefix.
LLVM_NODISCARD
LLVM_ATTRIBUTE_ALWAYS_INLINE
bool startswith(StringRef Prefix) const noexcept {
return size() >= Prefix.size() &&
compareMemory(Data, Prefix.Data, Prefix.size()) == 0;
return Length >= Prefix.Length &&
compareMemory(Data, Prefix.Data, Prefix.Length) == 0;
}
/// Check if this string starts with the given \p Prefix, ignoring case.
LLVM_NODISCARD
bool startswith_lower(StringRef Prefix) const noexcept;
/// Check if this string ends with the given \p Suffix.
LLVM_NODISCARD
LLVM_ATTRIBUTE_ALWAYS_INLINE
bool endswith(StringRef Suffix) const noexcept {
return size() >= Suffix.size() &&
compareMemory(end() - Suffix.size(), Suffix.Data, Suffix.size()) == 0;
return Length >= Suffix.Length &&
compareMemory(end() - Suffix.Length, Suffix.Data, Suffix.Length) == 0;
}
/// Check if this string ends with the given \p Suffix, ignoring case.
LLVM_NODISCARD
bool endswith_lower(StringRef Suffix) const noexcept;
/// @}
@@ -263,28 +271,72 @@ namespace wpi {
///
/// \returns The index of the first occurrence of \p C, or npos if not
/// found.
LLVM_NODISCARD
LLVM_ATTRIBUTE_ALWAYS_INLINE
size_t find(char C, size_t From = 0) const noexcept {
size_t FindBegin = std::min(From, size());
if (FindBegin < size()) { // Avoid calling memchr with nullptr.
size_t FindBegin = std::min(From, Length);
if (FindBegin < Length) { // Avoid calling memchr with nullptr.
// Just forward to memchr, which is faster than a hand-rolled loop.
if (const void *P = ::memchr(Data + FindBegin, C, size() - FindBegin))
if (const void *P = ::memchr(Data + FindBegin, C, Length - FindBegin))
return static_cast<const char *>(P) - Data;
}
return npos;
}
/// Search for the first character \p C in the string, ignoring case.
///
/// \returns The index of the first occurrence of \p C, or npos if not
/// found.
LLVM_NODISCARD
size_t find_lower(char C, size_t From = 0) const noexcept;
/// Search for the first character satisfying the predicate \p F
///
/// \returns The index of the first character satisfying \p F starting from
/// \p From, or npos if not found.
LLVM_NODISCARD
LLVM_ATTRIBUTE_ALWAYS_INLINE
size_t find_if(function_ref<bool(char)> F, size_t From = 0) const noexcept {
StringRef S = drop_front(From);
while (!S.empty()) {
if (F(S.front()))
return size() - S.size();
S = S.drop_front();
}
return npos;
}
/// Search for the first character not satisfying the predicate \p F
///
/// \returns The index of the first character not satisfying \p F starting
/// from \p From, or npos if not found.
LLVM_NODISCARD
LLVM_ATTRIBUTE_ALWAYS_INLINE
size_t find_if_not(function_ref<bool(char)> F, size_t From = 0) const noexcept {
return find_if([F](char c) { return !F(c); }, From);
}
/// Search for the first string \p Str in the string.
///
/// \returns The index of the first occurrence of \p Str, or npos if not
/// found.
LLVM_NODISCARD
size_t find(StringRef Str, size_t From = 0) const noexcept;
/// Search for the first string \p Str in the string, ignoring case.
///
/// \returns The index of the first occurrence of \p Str, or npos if not
/// found.
LLVM_NODISCARD
size_t find_lower(StringRef Str, size_t From = 0) const noexcept;
/// Search for the last character \p C in the string.
///
/// \returns The index of the last occurrence of \p C, or npos if not
/// found.
LLVM_NODISCARD
size_t rfind(char C, size_t From = npos) const noexcept {
From = std::min(From, size());
From = std::min(From, Length);
size_t i = From;
while (i != 0) {
--i;
@@ -294,14 +346,30 @@ namespace wpi {
return npos;
}
/// Search for the last character \p C in the string, ignoring case.
///
/// \returns The index of the last occurrence of \p C, or npos if not
/// found.
LLVM_NODISCARD
size_t rfind_lower(char C, size_t From = npos) const noexcept;
/// Search for the last string \p Str in the string.
///
/// \returns The index of the last occurrence of \p Str, or npos if not
/// found.
LLVM_NODISCARD
size_t rfind(StringRef Str) const noexcept;
/// Search for the last string \p Str in the string, ignoring case.
///
/// \returns The index of the last occurrence of \p Str, or npos if not
/// found.
LLVM_NODISCARD
size_t rfind_lower(StringRef Str) const noexcept;
/// Find the first character in the string that is \p C, or npos if not
/// found. Same as find.
LLVM_NODISCARD
size_t find_first_of(char C, size_t From = 0) const noexcept {
return find(C, From);
}
@@ -310,20 +378,24 @@ namespace wpi {
/// not found.
///
/// Complexity: O(size() + Chars.size())
LLVM_NODISCARD
size_t find_first_of(StringRef Chars, size_t From = 0) const noexcept;
/// Find the first character in the string that is not \p C or npos if not
/// found.
LLVM_NODISCARD
size_t find_first_not_of(char C, size_t From = 0) const noexcept;
/// Find the first character in the string that is not in the string
/// \p Chars, or npos if not found.
///
/// Complexity: O(size() + Chars.size())
LLVM_NODISCARD
size_t find_first_not_of(StringRef Chars, size_t From = 0) const noexcept;
/// Find the last character in the string that is \p C, or npos if not
/// found.
LLVM_NODISCARD
size_t find_last_of(char C, size_t From = npos) const noexcept {
return rfind(C, From);
}
@@ -332,26 +404,56 @@ namespace wpi {
/// found.
///
/// Complexity: O(size() + Chars.size())
LLVM_NODISCARD
size_t find_last_of(StringRef Chars, size_t From = npos) const noexcept;
/// Find the last character in the string that is not \p C, or npos if not
/// found.
LLVM_NODISCARD
size_t find_last_not_of(char C, size_t From = npos) const noexcept;
/// Find the last character in the string that is not in \p Chars, or
/// npos if not found.
///
/// Complexity: O(size() + Chars.size())
LLVM_NODISCARD
size_t find_last_not_of(StringRef Chars, size_t From = npos) const noexcept;
/// Return true if the given string is a substring of *this, and false
/// otherwise.
LLVM_NODISCARD
LLVM_ATTRIBUTE_ALWAYS_INLINE
bool contains(StringRef Other) const noexcept { return find(Other) != npos; }
/// Return true if the given character is contained in *this, and false
/// otherwise.
LLVM_NODISCARD
LLVM_ATTRIBUTE_ALWAYS_INLINE
bool contains(char C) const noexcept { return find_first_of(C) != npos; }
/// Return true if the given string is a substring of *this, and false
/// otherwise.
LLVM_NODISCARD
LLVM_ATTRIBUTE_ALWAYS_INLINE
bool contains_lower(StringRef Other) const noexcept {
return find_lower(Other) != npos;
}
/// Return true if the given character is contained in *this, and false
/// otherwise.
LLVM_NODISCARD
LLVM_ATTRIBUTE_ALWAYS_INLINE
bool contains_lower(char C) const noexcept { return find_lower(C) != npos; }
/// @}
/// @name Helpful Algorithms
/// @{
/// Return the number of occurrences of \p C in the string.
LLVM_NODISCARD
size_t count(char C) const noexcept {
size_t Count = 0;
for (size_t i = 0, e = size(); i != e; ++i)
for (size_t i = 0, e = Length; i != e; ++i)
if (Data[i] == C)
++Count;
return Count;
@@ -393,14 +495,47 @@ namespace wpi {
return false;
}
/// Parse the current string as an integer of the specified radix. If
/// \p Radix is specified as zero, this does radix autosensing using
/// extended C rules: 0 is octal, 0x is hex, 0b is binary.
///
/// If the string does not begin with a number of the specified radix,
/// this returns true to signify the error. The string is considered
/// erroneous if empty or if it overflows T.
/// The portion of the string representing the discovered numeric value
/// is removed from the beginning of the string.
template <typename T>
typename std::enable_if<std::numeric_limits<T>::is_signed, bool>::type
consumeInteger(unsigned Radix, T &Result) noexcept {
long long LLVal;
if (consumeSignedInteger(*this, Radix, LLVal) ||
static_cast<long long>(static_cast<T>(LLVal)) != LLVal)
return true;
Result = LLVal;
return false;
}
template <typename T>
typename std::enable_if<!std::numeric_limits<T>::is_signed, bool>::type
consumeInteger(unsigned Radix, T &Result) noexcept {
unsigned long long ULLVal;
if (consumeUnsignedInteger(*this, Radix, ULLVal) ||
static_cast<unsigned long long>(static_cast<T>(ULLVal)) != ULLVal)
return true;
Result = ULLVal;
return false;
}
/// @}
/// @name String Operations
/// @{
// Convert the given ASCII string to lowercase.
LLVM_NODISCARD
std::string lower() const;
/// Convert the given ASCII string to uppercase.
LLVM_NODISCARD
std::string upper() const;
/// @}
@@ -416,13 +551,55 @@ namespace wpi {
/// \param N The number of characters to included in the substring. If N
/// exceeds the number of characters remaining in the string, the string
/// suffix (starting with \p Start) will be returned.
LLVM_NODISCARD
LLVM_ATTRIBUTE_ALWAYS_INLINE
StringRef substr(size_t Start, size_t N = npos) const noexcept {
Start = std::min(Start, size());
return StringRef(Data + Start, std::min(N, size() - Start));
Start = std::min(Start, Length);
return StringRef(Data + Start, std::min(N, Length - Start));
}
/// Return a StringRef equal to 'this' but with only the first \p N
/// elements remaining. If \p N is greater than the length of the
/// string, the entire string is returned.
LLVM_NODISCARD
LLVM_ATTRIBUTE_ALWAYS_INLINE
StringRef take_front(size_t N = 1) const noexcept {
if (N >= size())
return *this;
return drop_back(size() - N);
}
/// Return a StringRef equal to 'this' but with only the last \p N
/// elements remaining. If \p N is greater than the length of the
/// string, the entire string is returned.
LLVM_NODISCARD
LLVM_ATTRIBUTE_ALWAYS_INLINE
StringRef take_back(size_t N = 1) const noexcept {
if (N >= size())
return *this;
return drop_front(size() - N);
}
/// Return the longest prefix of 'this' such that every character
/// in the prefix satisfies the given predicate.
LLVM_NODISCARD
LLVM_ATTRIBUTE_ALWAYS_INLINE
StringRef take_while(function_ref<bool(char)> F) const noexcept {
return substr(0, find_if_not(F));
}
/// Return the longest prefix of 'this' such that no character in
/// the prefix satisfies the given predicate.
LLVM_NODISCARD
LLVM_ATTRIBUTE_ALWAYS_INLINE
StringRef take_until(function_ref<bool(char)> F) const noexcept {
return substr(0, find_if(F));
}
/// Return a StringRef equal to 'this' but with the first \p N elements
/// dropped.
LLVM_NODISCARD
LLVM_ATTRIBUTE_ALWAYS_INLINE
StringRef drop_front(size_t N = 1) const noexcept {
assert(size() >= N && "Dropping more elements than exist");
return substr(N);
@@ -430,11 +607,51 @@ namespace wpi {
/// Return a StringRef equal to 'this' but with the last \p N elements
/// dropped.
LLVM_NODISCARD
LLVM_ATTRIBUTE_ALWAYS_INLINE
StringRef drop_back(size_t N = 1) const noexcept {
assert(size() >= N && "Dropping more elements than exist");
return substr(0, size()-N);
}
/// Return a StringRef equal to 'this', but with all characters satisfying
/// the given predicate dropped from the beginning of the string.
LLVM_NODISCARD
LLVM_ATTRIBUTE_ALWAYS_INLINE
StringRef drop_while(function_ref<bool(char)> F) const noexcept {
return substr(find_if_not(F));
}
/// Return a StringRef equal to 'this', but with all characters not
/// satisfying the given predicate dropped from the beginning of the string.
LLVM_NODISCARD
LLVM_ATTRIBUTE_ALWAYS_INLINE
StringRef drop_until(function_ref<bool(char)> F) const noexcept {
return substr(find_if(F));
}
/// Returns true if this StringRef has the given prefix and removes that
/// prefix.
LLVM_ATTRIBUTE_ALWAYS_INLINE
bool consume_front(StringRef Prefix) noexcept {
if (!startswith(Prefix))
return false;
*this = drop_front(Prefix.size());
return true;
}
/// Returns true if this StringRef has the given suffix and removes that
/// suffix.
LLVM_ATTRIBUTE_ALWAYS_INLINE
bool consume_back(StringRef Suffix) noexcept {
if (!endswith(Suffix))
return false;
*this = drop_back(Suffix.size());
return true;
}
/// Return a reference to the substring from [Start, End).
///
/// \param Start The index of the starting character in the substring; if
@@ -446,9 +663,11 @@ namespace wpi {
/// remaining in the string, the string suffix (starting with \p Start)
/// will be returned. If this is less than \p Start, an empty string will
/// be returned.
LLVM_NODISCARD
LLVM_ATTRIBUTE_ALWAYS_INLINE
StringRef slice(size_t Start, size_t End) const noexcept {
Start = std::min(Start, size());
End = std::min(std::max(Start, End), size());
Start = std::min(Start, Length);
End = std::min(std::max(Start, End), Length);
return StringRef(Data + Start, End - Start);
}
@@ -462,6 +681,7 @@ namespace wpi {
///
/// \param Separator The character to split on.
/// \returns The split substrings.
LLVM_NODISCARD
std::pair<StringRef, StringRef> split(char Separator) const {
size_t Idx = find(Separator);
if (Idx == npos)
@@ -479,6 +699,7 @@ namespace wpi {
///
/// \param Separator - The string to split on.
/// \return - The split substrings.
LLVM_NODISCARD
std::pair<StringRef, StringRef> split(StringRef Separator) const {
size_t Idx = find(Separator);
if (Idx == npos)
@@ -531,6 +752,7 @@ namespace wpi {
///
/// \param Separator - The character to split on.
/// \return - The split substrings.
LLVM_NODISCARD
std::pair<StringRef, StringRef> rsplit(char Separator) const {
size_t Idx = rfind(Separator);
if (Idx == npos)
@@ -540,36 +762,42 @@ namespace wpi {
/// Return string with consecutive \p Char characters starting from the
/// the left removed.
LLVM_NODISCARD
StringRef ltrim(char Char) const noexcept {
return drop_front(std::min(size(), find_first_not_of(Char)));
return drop_front(std::min(Length, find_first_not_of(Char)));
}
/// Return string with consecutive characters in \p Chars starting from
/// the left removed.
LLVM_NODISCARD
StringRef ltrim(StringRef Chars = " \t\n\v\f\r") const noexcept {
return drop_front(std::min(size(), find_first_not_of(Chars)));
return drop_front(std::min(Length, find_first_not_of(Chars)));
}
/// Return string with consecutive \p Char characters starting from the
/// right removed.
LLVM_NODISCARD
StringRef rtrim(char Char) const noexcept {
return drop_back(size() - std::min(size(), find_last_not_of(Char) + 1));
return drop_back(size() - std::min(Length, find_last_not_of(Char) + 1));
}
/// Return string with consecutive characters in \p Chars starting from
/// the right removed.
LLVM_NODISCARD
StringRef rtrim(StringRef Chars = " \t\n\v\f\r") const noexcept {
return drop_back(size() - std::min(size(), find_last_not_of(Chars) + 1));
return drop_back(size() - std::min(Length, find_last_not_of(Chars) + 1));
}
/// Return string with consecutive \p Char characters starting from the
/// left and right removed.
LLVM_NODISCARD
StringRef trim(char Char) const noexcept {
return ltrim(Char).rtrim(Char);
}
/// Return string with consecutive characters in \p Chars starting from
/// the left and right removed.
LLVM_NODISCARD
StringRef trim(StringRef Chars = " \t\n\v\f\r") const noexcept {
return ltrim(Chars).rtrim(Chars);
}
@@ -577,14 +805,48 @@ namespace wpi {
/// @}
};
/// A wrapper around a string literal that serves as a proxy for constructing
/// global tables of StringRefs with the length computed at compile time.
/// In order to avoid the invocation of a global constructor, StringLiteral
/// should *only* be used in a constexpr context, as such:
///
/// constexpr StringLiteral S("test");
///
class StringLiteral : public StringRef {
private:
constexpr StringLiteral(const char *Str, size_t N) : StringRef(Str, N) {
}
public:
template <size_t N>
constexpr StringLiteral(const char (&Str)[N])
#if defined(__clang__) && __has_attribute(enable_if)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgcc-compat"
__attribute((enable_if(__builtin_strlen(Str) == N - 1,
"invalid string literal")))
#pragma clang diagnostic pop
#endif
: StringRef(Str, N - 1) {
}
// Explicit construction for strings like "foo\0bar".
template <size_t N>
static constexpr StringLiteral withInnerNUL(const char (&Str)[N]) {
return StringLiteral(Str, N - 1);
}
};
/// @name StringRef Comparison Operators
/// @{
inline bool operator==(StringRef LHS, StringRef RHS) noexcept {
LLVM_ATTRIBUTE_ALWAYS_INLINE
bool operator==(StringRef LHS, StringRef RHS) noexcept {
return LHS.equals(RHS);
}
inline bool operator!=(StringRef LHS, StringRef RHS) noexcept {
LLVM_ATTRIBUTE_ALWAYS_INLINE
bool operator!=(StringRef LHS, StringRef RHS) noexcept {
return !(LHS == RHS);
}
@@ -656,19 +918,18 @@ namespace wpi {
return buffer.append(string.data(), string.size());
}
inline std::ostream &operator<<(std::ostream &os, StringRef string) {
os.write(string.data(), string.size());
return os;
}
std::ostream &operator<<(std::ostream &os, StringRef string);
/// @}
/// \brief Compute a hash_code for a StringRef.
/// Compute a hash_code for a StringRef.
LLVM_NODISCARD
hash_code hash_value(StringRef S);
// StringRefs can be treated like a POD type.
template <typename T> struct isPodLike;
template <> struct isPodLike<StringRef> { static const bool value = true; };
} // namespace wpi
#endif
} // end namespace wpi
#endif // LLVM_ADT_STRINGREF_H