aboutsummaryrefslogtreecommitdiff
path: root/include/llvm/ADT
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/ADT')
-rw-r--r--include/llvm/ADT/BitVector.h18
-rw-r--r--include/llvm/ADT/SmallBitVector.h373
-rw-r--r--include/llvm/ADT/StringExtras.h84
-rw-r--r--include/llvm/ADT/StringRef.h28
-rw-r--r--include/llvm/ADT/Twine.h34
5 files changed, 448 insertions, 89 deletions
diff --git a/include/llvm/ADT/BitVector.h b/include/llvm/ADT/BitVector.h
index 9c046efaaddd..45108c8cc519 100644
--- a/include/llvm/ADT/BitVector.h
+++ b/include/llvm/ADT/BitVector.h
@@ -95,6 +95,9 @@ public:
delete[] Bits;
}
+ /// empty - Tests whether there are no bits in this bitvector.
+ bool empty() const { return Size == 0; }
+
/// size - Returns the number of bits in this bitvector.
unsigned size() const { return Size; }
@@ -341,6 +344,12 @@ public:
return *this;
}
+ void swap(BitVector &RHS) {
+ std::swap(Bits, RHS.Bits);
+ std::swap(Size, RHS.Size);
+ std::swap(Capacity, RHS.Capacity);
+ }
+
private:
unsigned NumBitWords(unsigned S) const {
return (S + BITWORD_SIZE-1) / BITWORD_SIZE;
@@ -406,4 +415,13 @@ inline BitVector operator^(const BitVector &LHS, const BitVector &RHS) {
}
} // End llvm namespace
+
+namespace std {
+ /// Implement std::swap in terms of BitVector swap.
+ inline void
+ swap(llvm::BitVector &LHS, llvm::BitVector &RHS) {
+ LHS.swap(RHS);
+ }
+}
+
#endif
diff --git a/include/llvm/ADT/SmallBitVector.h b/include/llvm/ADT/SmallBitVector.h
new file mode 100644
index 000000000000..346fb1ca43dc
--- /dev/null
+++ b/include/llvm/ADT/SmallBitVector.h
@@ -0,0 +1,373 @@
+//===- llvm/ADT/SmallBitVector.h - 'Normally small' bit vectors -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the SmallBitVector class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_SMALLBITVECTOR_H
+#define LLVM_ADT_SMALLBITVECTOR_H
+
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/Support/MathExtras.h"
+#include <cassert>
+
+namespace llvm {
+
+/// SmallBitVector - This is a 'bitvector' (really, a variable-sized bit array),
+/// optimized for the case when the array is small. It contains one
+/// pointer-sized field, which is directly used as a plain collection of bits
+/// when possible, or as a pointer to a larger heap-allocated array when
+/// necessary. This allows normal "small" cases to be fast without losing
+/// generality for large inputs.
+///
+class SmallBitVector {
+ // TODO: In "large" mode, a pointer to a BitVector is used, leading to an
+ // unnecessary level of indirection. It would be more efficient to use a
+ // pointer to memory containing size, allocation size, and the array of bits.
+ PointerIntPair<BitVector *, 1, uintptr_t> X;
+
+ // The number of bits in this class.
+ static const size_t NumBaseBits = sizeof(uintptr_t) * CHAR_BIT;
+
+ // One bit is used to discriminate between small and large mode. The
+ // remaining bits are used for the small-mode representation.
+ static const size_t SmallNumRawBits = NumBaseBits - 1;
+
+ // A few more bits are used to store the size of the bit set in small mode.
+ // Theoretically this is a ceil-log2. These bits are encoded in the most
+ // significant bits of the raw bits.
+ static const size_t SmallNumSizeBits = (NumBaseBits == 32 ? 5 :
+ NumBaseBits == 64 ? 6 :
+ SmallNumRawBits);
+
+ // The remaining bits are used to store the actual set in small mode.
+ static const size_t SmallNumDataBits = SmallNumRawBits - SmallNumSizeBits;
+
+ bool isSmall() const {
+ return X.getInt();
+ }
+
+ void switchToSmall(uintptr_t NewSmallBits, size_t NewSize) {
+ X.setInt(true);
+ setSmallSize(NewSize);
+ setSmallBits(NewSmallBits);
+ }
+
+ void switchToLarge(BitVector *BV) {
+ X.setInt(false);
+ X.setPointer(BV);
+ }
+
+ // Return all the bits used for the "small" representation; this includes
+ // bits for the size as well as the element bits.
+ uintptr_t getSmallRawBits() const {
+ return reinterpret_cast<uintptr_t>(X.getPointer()) >> 1;
+ }
+
+ void setSmallRawBits(uintptr_t NewRawBits) {
+ return X.setPointer(reinterpret_cast<BitVector *>(NewRawBits << 1));
+ }
+
+ // Return the size.
+ size_t getSmallSize() const {
+ return getSmallRawBits() >> SmallNumDataBits;
+ }
+
+ void setSmallSize(size_t Size) {
+ setSmallRawBits(getSmallBits() | (Size << SmallNumDataBits));
+ }
+
+ // Return the element bits.
+ uintptr_t getSmallBits() const {
+ return getSmallRawBits() & ~(~uintptr_t(0) << SmallNumDataBits);
+ }
+
+ void setSmallBits(uintptr_t NewBits) {
+ setSmallRawBits((getSmallRawBits() & (~uintptr_t(0) << SmallNumDataBits)) |
+ (NewBits & ~(~uintptr_t(0) << getSmallSize())));
+ }
+
+public:
+ /// SmallBitVector default ctor - Creates an empty bitvector.
+ SmallBitVector() : X(0, 1) {}
+
+ /// SmallBitVector ctor - Creates a bitvector of specified number of bits. All
+ /// bits are initialized to the specified value.
+ explicit SmallBitVector(unsigned s, bool t = false) : X(0, 1) {
+ if (s <= SmallNumRawBits)
+ switchToSmall(t ? ~uintptr_t(0) : 0, s);
+ else
+ switchToLarge(new BitVector(s, t));
+ }
+
+ /// SmallBitVector copy ctor.
+ SmallBitVector(const SmallBitVector &RHS) {
+ if (RHS.isSmall())
+ X = RHS.X;
+ else
+ switchToLarge(new BitVector(*RHS.X.getPointer()));
+ }
+
+ ~SmallBitVector() {
+ if (!isSmall())
+ delete X.getPointer();
+ }
+
+ /// empty - Tests whether there are no bits in this bitvector.
+ bool empty() const {
+ return isSmall() ? getSmallSize() == 0 : X.getPointer()->empty();
+ }
+
+ /// size - Returns the number of bits in this bitvector.
+ size_t size() const {
+ return isSmall() ? getSmallSize() : X.getPointer()->size();
+ }
+
+ /// count - Returns the number of bits which are set.
+ unsigned count() const {
+ if (isSmall()) {
+ uintptr_t Bits = getSmallBits();
+ if (sizeof(uintptr_t) * CHAR_BIT == 32)
+ return CountPopulation_32(Bits);
+ if (sizeof(uintptr_t) * CHAR_BIT == 64)
+ return CountPopulation_64(Bits);
+ assert(0 && "Unsupported!");
+ }
+ return X.getPointer()->count();
+ }
+
+ /// any - Returns true if any bit is set.
+ bool any() const {
+ if (isSmall())
+ return getSmallBits() != 0;
+ return X.getPointer()->any();
+ }
+
+ /// none - Returns true if none of the bits are set.
+ bool none() const {
+ if (isSmall())
+ return getSmallBits() == 0;
+ return X.getPointer()->none();
+ }
+
+ /// find_first - Returns the index of the first set bit, -1 if none
+ /// of the bits are set.
+ int find_first() const {
+ if (isSmall()) {
+ uintptr_t Bits = getSmallBits();
+ if (sizeof(uintptr_t) * CHAR_BIT == 32)
+ return CountTrailingZeros_32(Bits);
+ if (sizeof(uintptr_t) * CHAR_BIT == 64)
+ return CountTrailingZeros_64(Bits);
+ assert(0 && "Unsupported!");
+ }
+ return X.getPointer()->find_first();
+ }
+
+ /// find_next - Returns the index of the next set bit following the
+ /// "Prev" bit. Returns -1 if the next set bit is not found.
+ int find_next(unsigned Prev) const {
+ if (isSmall()) {
+ uintptr_t Bits = getSmallBits();
+ // Mask off previous bits.
+ Bits &= ~uintptr_t(0) << Prev;
+ if (sizeof(uintptr_t) * CHAR_BIT == 32)
+ return CountTrailingZeros_32(Bits);
+ if (sizeof(uintptr_t) * CHAR_BIT == 64)
+ return CountTrailingZeros_64(Bits);
+ assert(0 && "Unsupported!");
+ }
+ return X.getPointer()->find_next(Prev);
+ }
+
+ /// clear - Clear all bits.
+ void clear() {
+ if (!isSmall())
+ delete X.getPointer();
+ switchToSmall(0, 0);
+ }
+
+ /// resize - Grow or shrink the bitvector.
+ void resize(unsigned N, bool t = false) {
+ if (!isSmall()) {
+ X.getPointer()->resize(N, t);
+ } else if (getSmallSize() >= N) {
+ setSmallSize(N);
+ setSmallBits(getSmallBits());
+ } else {
+ BitVector *BV = new BitVector(N, t);
+ uintptr_t OldBits = getSmallBits();
+ for (size_t i = 0, e = getSmallSize(); i != e; ++i)
+ (*BV)[i] = (OldBits >> i) & 1;
+ switchToLarge(BV);
+ }
+ }
+
+ void reserve(unsigned N) {
+ if (isSmall()) {
+ if (N > SmallNumDataBits) {
+ uintptr_t OldBits = getSmallRawBits();
+ size_t SmallSize = getSmallSize();
+ BitVector *BV = new BitVector(SmallSize);
+ for (size_t i = 0; i < SmallSize; ++i)
+ if ((OldBits >> i) & 1)
+ BV->set(i);
+ BV->reserve(N);
+ switchToLarge(BV);
+ }
+ } else {
+ X.getPointer()->reserve(N);
+ }
+ }
+
+ // Set, reset, flip
+ SmallBitVector &set() {
+ if (isSmall())
+ setSmallBits(~uintptr_t(0));
+ else
+ X.getPointer()->set();
+ return *this;
+ }
+
+ SmallBitVector &set(unsigned Idx) {
+ if (isSmall())
+ setSmallBits(getSmallBits() | (uintptr_t(1) << Idx));
+ else
+ X.getPointer()->set(Idx);
+ return *this;
+ }
+
+ SmallBitVector &reset() {
+ if (isSmall())
+ setSmallBits(0);
+ else
+ X.getPointer()->reset();
+ return *this;
+ }
+
+ SmallBitVector &reset(unsigned Idx) {
+ if (isSmall())
+ setSmallBits(getSmallBits() & ~(uintptr_t(1) << Idx));
+ else
+ X.getPointer()->reset(Idx);
+ return *this;
+ }
+
+ SmallBitVector &flip() {
+ if (isSmall())
+ setSmallBits(~getSmallBits());
+ else
+ X.getPointer()->flip();
+ return *this;
+ }
+
+ SmallBitVector &flip(unsigned Idx) {
+ if (isSmall())
+ setSmallBits(getSmallBits() ^ (uintptr_t(1) << Idx));
+ else
+ X.getPointer()->flip(Idx);
+ return *this;
+ }
+
+ // No argument flip.
+ SmallBitVector operator~() const {
+ return SmallBitVector(*this).flip();
+ }
+
+ // Indexing.
+ // TODO: Add an index operator which returns a "reference" (proxy class).
+ bool operator[](unsigned Idx) const {
+ assert(Idx < size() && "Out-of-bounds Bit access.");
+ if (isSmall())
+ return ((getSmallBits() >> Idx) & 1) != 0;
+ return X.getPointer()->operator[](Idx);
+ }
+
+ bool test(unsigned Idx) const {
+ return (*this)[Idx];
+ }
+
+ // Comparison operators.
+ bool operator==(const SmallBitVector &RHS) const {
+ if (size() != RHS.size())
+ return false;
+ if (isSmall())
+ return getSmallBits() == RHS.getSmallBits();
+ else
+ return *X.getPointer() == *RHS.X.getPointer();
+ }
+
+ bool operator!=(const SmallBitVector &RHS) const {
+ return !(*this == RHS);
+ }
+
+ // Intersection, union, disjoint union.
+ BitVector &operator&=(const SmallBitVector &RHS); // TODO: implement
+
+ BitVector &operator|=(const SmallBitVector &RHS); // TODO: implement
+
+ BitVector &operator^=(const SmallBitVector &RHS); // TODO: implement
+
+ // Assignment operator.
+ const SmallBitVector &operator=(const SmallBitVector &RHS) {
+ if (isSmall()) {
+ if (RHS.isSmall())
+ X = RHS.X;
+ else
+ switchToLarge(new BitVector(*RHS.X.getPointer()));
+ } else {
+ if (!RHS.isSmall())
+ *X.getPointer() = *RHS.X.getPointer();
+ else {
+ delete X.getPointer();
+ X = RHS.X;
+ }
+ }
+ return *this;
+ }
+
+ void swap(SmallBitVector &RHS) {
+ std::swap(X, RHS.X);
+ }
+};
+
+inline SmallBitVector
+operator&(const SmallBitVector &LHS, const SmallBitVector &RHS) {
+ SmallBitVector Result(LHS);
+ Result &= RHS;
+ return Result;
+}
+
+inline SmallBitVector
+operator|(const SmallBitVector &LHS, const SmallBitVector &RHS) {
+ SmallBitVector Result(LHS);
+ Result |= RHS;
+ return Result;
+}
+
+inline SmallBitVector
+operator^(const SmallBitVector &LHS, const SmallBitVector &RHS) {
+ SmallBitVector Result(LHS);
+ Result ^= RHS;
+ return Result;
+}
+
+} // End llvm namespace
+
+namespace std {
+ /// Implement std::swap in terms of BitVector swap.
+ inline void
+ swap(llvm::SmallBitVector &LHS, llvm::SmallBitVector &RHS) {
+ LHS.swap(RHS);
+ }
+}
+
+#endif
diff --git a/include/llvm/ADT/StringExtras.h b/include/llvm/ADT/StringExtras.h
index 85936c019d3b..1ea546f46f29 100644
--- a/include/llvm/ADT/StringExtras.h
+++ b/include/llvm/ADT/StringExtras.h
@@ -23,6 +23,7 @@
#include <vector>
namespace llvm {
+template<typename T> class SmallVectorImpl;
/// hexdigit - Return the (uppercase) hexadecimal character for the
/// given number \arg X (which should be less than 16).
@@ -136,86 +137,25 @@ static inline std::string UppercaseString(const std::string &S) {
return result;
}
-/// StringsEqualNoCase - Return true if the two strings are equal, ignoring
-/// case.
-static inline bool StringsEqualNoCase(const std::string &LHS,
- const std::string &RHS) {
- if (LHS.size() != RHS.size()) return false;
- for (unsigned i = 0, e = static_cast<unsigned>(LHS.size()); i != e; ++i)
- if (tolower(LHS[i]) != tolower(RHS[i])) return false;
- return true;
-}
-
-/// StringsEqualNoCase - Return true if the two strings are equal, ignoring
-/// case.
-static inline bool StringsEqualNoCase(const std::string &LHS,
- const char *RHS) {
- for (unsigned i = 0, e = static_cast<unsigned>(LHS.size()); i != e; ++i) {
- if (RHS[i] == 0) return false; // RHS too short.
- if (tolower(LHS[i]) != tolower(RHS[i])) return false;
- }
- return RHS[LHS.size()] == 0; // Not too long?
-}
-
-/// StringsEqualNoCase - Return true if the two null-terminated C strings are
-/// equal, ignoring
-
-static inline bool StringsEqualNoCase(const char *LHS, const char *RHS,
- unsigned len) {
-
- for (unsigned i = 0; i < len; ++i) {
- if (tolower(LHS[i]) != tolower(RHS[i]))
- return false;
-
- // If RHS[i] == 0 then LHS[i] == 0 or otherwise we would have returned
- // at the previous branch as tolower('\0') == '\0'.
- if (RHS[i] == 0)
- return true;
- }
-
- return true;
-}
-
-/// CStrInCStrNoCase - Portable version of strcasestr. Locates the first
-/// occurance of c-string 's2' in string 's1', ignoring case. Returns
-/// NULL if 's2' cannot be found.
-static inline const char* CStrInCStrNoCase(const char *s1, const char *s2) {
-
- // Are either strings NULL or empty?
- if (!s1 || !s2 || s1[0] == '\0' || s2[0] == '\0')
- return 0;
-
- if (s1 == s2)
- return s1;
-
- const char *I1=s1, *I2=s2;
-
- while (*I1 != '\0' && *I2 != '\0' )
- if (tolower(*I1) != tolower(*I2)) { // No match. Start over.
- ++s1; I1 = s1; I2 = s2;
- }
- else { // Character match. Advance to the next character.
- ++I1; ++I2;
- }
-
- // If we exhausted all of the characters in 's2', then 's2' appears in 's1'.
- return *I2 == '\0' ? s1 : 0;
-}
+/// StrInStrNoCase - Portable version of strcasestr. Locates the first
+/// occurrence of string 's1' in string 's2', ignoring case. Returns
+/// the offset of s2 in s1 or npos if s2 cannot be found.
+StringRef::size_type StrInStrNoCase(StringRef s1, StringRef s2);
/// getToken - This function extracts one token from source, ignoring any
/// leading characters that appear in the Delimiters string, and ending the
/// token at any of the characters that appear in the Delimiters string. If
/// there are no tokens in the source string, an empty string is returned.
-/// The Source source string is updated in place to remove the returned string
-/// and any delimiter prefix from it.
-std::string getToken(std::string &Source,
- const char *Delimiters = " \t\n\v\f\r");
+/// The function returns a pair containing the extracted token and the
+/// remaining tail string.
+std::pair<StringRef, StringRef> getToken(StringRef Source,
+ StringRef Delimiters = " \t\n\v\f\r");
/// SplitString - Split up the specified string according to the specified
/// delimiters, appending the result fragments to the output list.
-void SplitString(const std::string &Source,
- std::vector<std::string> &OutFragments,
- const char *Delimiters = " \t\n\v\f\r");
+void SplitString(StringRef Source,
+ SmallVectorImpl<StringRef> &OutFragments,
+ StringRef Delimiters = " \t\n\v\f\r");
/// HashString - Hash funtion for strings.
///
diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h
index 1c738369d75e..3064af3abbca 100644
--- a/include/llvm/ADT/StringRef.h
+++ b/include/llvm/ADT/StringRef.h
@@ -29,6 +29,7 @@ namespace llvm {
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;
@@ -42,15 +43,8 @@ namespace llvm {
// Workaround PR5482: nearly all gcc 4.x miscompile StringRef and std::min()
// Changing the arg of min to be an integer, instead of a reference to an
// integer works around this bug.
- size_t min(size_t a, size_t b) const
- {
- return a < b ? a : b;
- }
-
- size_t max(size_t a, size_t b) const
- {
- return a > b ? a : b;
- }
+ size_t min(size_t a, size_t b) const { return a < b ? a : b; }
+ size_t max(size_t a, size_t b) const { return a > b ? a : b; }
public:
/// @name Constructors
@@ -191,7 +185,7 @@ namespace llvm {
/// find - Search for the first character \arg C in the string.
///
- /// \return - The index of the first occurence of \arg C, or npos if not
+ /// \return - The index of the first occurrence of \arg C, or npos if not
/// found.
size_t find(char C, size_t From = 0) const {
for (size_t i = min(From, Length), e = Length; i != e; ++i)
@@ -202,13 +196,13 @@ namespace llvm {
/// find - Search for the first string \arg Str in the string.
///
- /// \return - The index of the first occurence of \arg Str, or npos if not
+ /// \return - The index of the first occurrence of \arg Str, or npos if not
/// found.
size_t find(StringRef Str, size_t From = 0) const;
/// rfind - Search for the last character \arg C in the string.
///
- /// \return - The index of the last occurence of \arg C, or npos if not
+ /// \return - The index of the last occurrence of \arg C, or npos if not
/// found.
size_t rfind(char C, size_t From = npos) const {
From = min(From, Length);
@@ -223,7 +217,7 @@ namespace llvm {
/// rfind - Search for the last string \arg Str in the string.
///
- /// \return - The index of the last occurence of \arg Str, or npos if not
+ /// \return - The index of the last occurrence of \arg Str, or npos if not
/// found.
size_t rfind(StringRef Str) const;
@@ -313,7 +307,7 @@ namespace llvm {
return StringRef(Data + Start, End - Start);
}
- /// split - Split into two substrings around the first occurence of a
+ /// split - Split into two substrings around the first occurrence of a
/// separator character.
///
/// If \arg Separator is in the string, then the result is a pair (LHS, RHS)
@@ -330,7 +324,7 @@ namespace llvm {
return std::make_pair(slice(0, Idx), slice(Idx+1, npos));
}
- /// split - Split into two substrings around the first occurence of a
+ /// split - Split into two substrings around the first occurrence of a
/// separator string.
///
/// If \arg Separator is in the string, then the result is a pair (LHS, RHS)
@@ -347,7 +341,7 @@ namespace llvm {
return std::make_pair(slice(0, Idx), slice(Idx + Separator.size(), npos));
}
- /// split - Split into substrings around the occurences of a separator
+ /// split - Split into substrings around the occurrences of a separator
/// string.
///
/// Each substring is stored in \arg A. If \arg MaxSplit is >= 0, at most
@@ -366,7 +360,7 @@ namespace llvm {
StringRef Separator, int MaxSplit = -1,
bool KeepEmpty = true) const;
- /// rsplit - Split into two substrings around the last occurence of a
+ /// rsplit - Split into two substrings around the last occurrence of a
/// separator character.
///
/// If \arg Separator is in the string, then the result is a pair (LHS, RHS)
diff --git a/include/llvm/ADT/Twine.h b/include/llvm/ADT/Twine.h
index ca0be53d481d..97e9df445817 100644
--- a/include/llvm/ADT/Twine.h
+++ b/include/llvm/ADT/Twine.h
@@ -329,6 +329,22 @@ namespace llvm {
bool isTriviallyEmpty() const {
return isNullary();
}
+
+ /// isSingleStringRef - Return true if this twine can be dynamically
+ /// accessed as a single StringRef value with getSingleStringRef().
+ bool isSingleStringRef() const {
+ if (getRHSKind() != EmptyKind) return false;
+
+ switch (getLHSKind()) {
+ case EmptyKind:
+ case CStringKind:
+ case StdStringKind:
+ case StringRefKind:
+ return true;
+ default:
+ return false;
+ }
+ }
/// @}
/// @name String Operations
@@ -347,6 +363,24 @@ namespace llvm {
/// SmallVector.
void toVector(SmallVectorImpl<char> &Out) const;
+ /// getSingleStringRef - This returns the twine as a single StringRef. This
+ /// method is only valid if isSingleStringRef() is true.
+ StringRef getSingleStringRef() const {
+ assert(isSingleStringRef() &&"This cannot be had as a single stringref!");
+ switch (getLHSKind()) {
+ default: assert(0 && "Out of sync with isSingleStringRef");
+ case EmptyKind: return StringRef();
+ case CStringKind: return StringRef((const char*)LHS);
+ case StdStringKind: return StringRef(*(const std::string*)LHS);
+ case StringRefKind: return *(const StringRef*)LHS;
+ }
+ }
+
+ /// toStringRef - This returns the twine as a single StringRef if it can be
+ /// represented as such. Otherwise the twine is written into the given
+ /// SmallVector and a StringRef to the SmallVector's data is returned.
+ StringRef toStringRef(SmallVectorImpl<char> &Out) const;
+
/// print - Write the concatenated string represented by this twine to the
/// stream \arg OS.
void print(raw_ostream &OS) const;