mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-09 21:50:50 +00:00
Resubmit "Improve StringMap iterator support."
The issue was trying to advance past the end of the iterator when computing the end() iterator. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@298461 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
a4a05c5804
commit
d10b8de6de
@ -893,7 +893,8 @@ auto partition(R &&Range, UnaryPredicate P) -> decltype(std::begin(Range)) {
|
|||||||
/// SmallVector with elements of the vector. This is useful, for example,
|
/// SmallVector with elements of the vector. This is useful, for example,
|
||||||
/// when you want to iterate a range and then sort the results.
|
/// when you want to iterate a range and then sort the results.
|
||||||
template <unsigned Size, typename R>
|
template <unsigned Size, typename R>
|
||||||
SmallVector<detail::ValueOfRange<R>, Size> to_vector(R &&Range) {
|
SmallVector<typename std::remove_const<detail::ValueOfRange<R>>::type, Size>
|
||||||
|
to_vector(R &&Range) {
|
||||||
return {std::begin(Range), std::end(Range)};
|
return {std::begin(Range), std::end(Range)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,13 +15,13 @@
|
|||||||
#define LLVM_ADT_STRINGMAP_H
|
#define LLVM_ADT_STRINGMAP_H
|
||||||
|
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
|
#include "llvm/ADT/iterator.h"
|
||||||
#include "llvm/Support/Allocator.h"
|
#include "llvm/Support/Allocator.h"
|
||||||
#include "llvm/Support/PointerLikeTypeTraits.h"
|
#include "llvm/Support/PointerLikeTypeTraits.h"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <utility>
|
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
#include <new>
|
#include <new>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@ -32,6 +32,7 @@ namespace llvm {
|
|||||||
class StringMapConstIterator;
|
class StringMapConstIterator;
|
||||||
template<typename ValueT>
|
template<typename ValueT>
|
||||||
class StringMapIterator;
|
class StringMapIterator;
|
||||||
|
template <typename ValueT> class StringMapKeyIterator;
|
||||||
template<typename ValueTy>
|
template<typename ValueTy>
|
||||||
class StringMapEntry;
|
class StringMapEntry;
|
||||||
|
|
||||||
@ -312,6 +313,11 @@ public:
|
|||||||
return const_iterator(TheTable+NumBuckets, true);
|
return const_iterator(TheTable+NumBuckets, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
llvm::iterator_range<StringMapKeyIterator<ValueTy>> keys() const {
|
||||||
|
return make_range(StringMapKeyIterator<ValueTy>(begin()),
|
||||||
|
StringMapKeyIterator<ValueTy>(end()));
|
||||||
|
}
|
||||||
|
|
||||||
iterator find(StringRef Key) {
|
iterator find(StringRef Key) {
|
||||||
int Bucket = FindKey(Key);
|
int Bucket = FindKey(Key);
|
||||||
if (Bucket == -1) return end();
|
if (Bucket == -1) return end();
|
||||||
@ -444,42 +450,39 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename ValueTy> class StringMapConstIterator {
|
template <typename DerivedTy, typename ValueTy>
|
||||||
|
class StringMapIterBase
|
||||||
|
: public iterator_facade_base<DerivedTy, std::forward_iterator_tag,
|
||||||
|
ValueTy> {
|
||||||
protected:
|
protected:
|
||||||
StringMapEntryBase **Ptr = nullptr;
|
StringMapEntryBase **Ptr = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef StringMapEntry<ValueTy> value_type;
|
StringMapIterBase() = default;
|
||||||
|
|
||||||
StringMapConstIterator() = default;
|
explicit StringMapIterBase(StringMapEntryBase **Bucket,
|
||||||
|
bool NoAdvance = false)
|
||||||
explicit StringMapConstIterator(StringMapEntryBase **Bucket,
|
: Ptr(Bucket) {
|
||||||
bool NoAdvance = false)
|
|
||||||
: Ptr(Bucket) {
|
|
||||||
if (!NoAdvance) AdvancePastEmptyBuckets();
|
if (!NoAdvance) AdvancePastEmptyBuckets();
|
||||||
}
|
}
|
||||||
|
|
||||||
const value_type &operator*() const {
|
DerivedTy &operator=(const DerivedTy &Other) {
|
||||||
return *static_cast<StringMapEntry<ValueTy>*>(*Ptr);
|
Ptr = Other.Ptr;
|
||||||
}
|
return static_cast<DerivedTy &>(*this);
|
||||||
const value_type *operator->() const {
|
|
||||||
return static_cast<StringMapEntry<ValueTy>*>(*Ptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const StringMapConstIterator &RHS) const {
|
bool operator==(const DerivedTy &RHS) const { return Ptr == RHS.Ptr; }
|
||||||
return Ptr == RHS.Ptr;
|
|
||||||
}
|
|
||||||
bool operator!=(const StringMapConstIterator &RHS) const {
|
|
||||||
return Ptr != RHS.Ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline StringMapConstIterator& operator++() { // Preincrement
|
DerivedTy &operator++() { // Preincrement
|
||||||
++Ptr;
|
++Ptr;
|
||||||
AdvancePastEmptyBuckets();
|
AdvancePastEmptyBuckets();
|
||||||
return *this;
|
return static_cast<DerivedTy &>(*this);
|
||||||
}
|
}
|
||||||
StringMapConstIterator operator++(int) { // Postincrement
|
|
||||||
StringMapConstIterator tmp = *this; ++*this; return tmp;
|
DerivedTy operator++(int) { // Post-increment
|
||||||
|
DerivedTy Tmp(Ptr);
|
||||||
|
++*this;
|
||||||
|
return Tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -489,24 +492,69 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ValueTy>
|
template <typename ValueTy>
|
||||||
class StringMapIterator : public StringMapConstIterator<ValueTy> {
|
class StringMapConstIterator
|
||||||
|
: public StringMapIterBase<StringMapConstIterator<ValueTy>,
|
||||||
|
const StringMapEntry<ValueTy>> {
|
||||||
|
using base = StringMapIterBase<StringMapConstIterator<ValueTy>,
|
||||||
|
const StringMapEntry<ValueTy>>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
StringMapConstIterator() = default;
|
||||||
|
explicit StringMapConstIterator(StringMapEntryBase **Bucket,
|
||||||
|
bool NoAdvance = false)
|
||||||
|
: base(Bucket, NoAdvance) {}
|
||||||
|
|
||||||
|
const StringMapEntry<ValueTy> &operator*() const {
|
||||||
|
return *static_cast<const StringMapEntry<ValueTy> *>(*this->Ptr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename ValueTy>
|
||||||
|
class StringMapIterator : public StringMapIterBase<StringMapIterator<ValueTy>,
|
||||||
|
StringMapEntry<ValueTy>> {
|
||||||
|
using base =
|
||||||
|
StringMapIterBase<StringMapIterator<ValueTy>, StringMapEntry<ValueTy>>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
StringMapIterator() = default;
|
StringMapIterator() = default;
|
||||||
|
|
||||||
explicit StringMapIterator(StringMapEntryBase **Bucket,
|
explicit StringMapIterator(StringMapEntryBase **Bucket,
|
||||||
bool NoAdvance = false)
|
bool NoAdvance = false)
|
||||||
: StringMapConstIterator<ValueTy>(Bucket, NoAdvance) {
|
: base(Bucket, NoAdvance) {}
|
||||||
}
|
|
||||||
|
|
||||||
StringMapEntry<ValueTy> &operator*() const {
|
StringMapEntry<ValueTy> &operator*() const {
|
||||||
return *static_cast<StringMapEntry<ValueTy>*>(*this->Ptr);
|
return *static_cast<StringMapEntry<ValueTy> *>(*this->Ptr);
|
||||||
}
|
}
|
||||||
StringMapEntry<ValueTy> *operator->() const {
|
|
||||||
return static_cast<StringMapEntry<ValueTy>*>(*this->Ptr);
|
operator StringMapConstIterator<ValueTy>() const {
|
||||||
|
return StringMapConstIterator<ValueTy>(this->Ptr, true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename ValueTy>
|
||||||
|
class StringMapKeyIterator
|
||||||
|
: public iterator_adaptor_base<StringMapKeyIterator<ValueTy>,
|
||||||
|
StringMapConstIterator<ValueTy>,
|
||||||
|
std::forward_iterator_tag, StringRef> {
|
||||||
|
using base = iterator_adaptor_base<StringMapKeyIterator<ValueTy>,
|
||||||
|
StringMapConstIterator<ValueTy>,
|
||||||
|
std::forward_iterator_tag, StringRef>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
StringMapKeyIterator() = default;
|
||||||
|
|
||||||
|
explicit StringMapKeyIterator(StringMapConstIterator<ValueTy> Iter)
|
||||||
|
: base(std::move(Iter)) {}
|
||||||
|
|
||||||
|
StringRef &operator*() {
|
||||||
|
Key = this->wrapped()->getKey();
|
||||||
|
return Key;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
StringRef Key;
|
||||||
|
};
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
#endif // LLVM_ADT_STRINGMAP_H
|
#endif // LLVM_ADT_STRINGMAP_H
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "llvm/ADT/StringMap.h"
|
#include "llvm/ADT/StringMap.h"
|
||||||
|
#include "llvm/ADT/StringSet.h"
|
||||||
#include "llvm/ADT/Twine.h"
|
#include "llvm/ADT/Twine.h"
|
||||||
#include "llvm/Support/DataTypes.h"
|
#include "llvm/Support/DataTypes.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
@ -269,6 +270,34 @@ TEST_F(StringMapTest, InsertRehashingPairTest) {
|
|||||||
EXPECT_EQ(42u, It->second);
|
EXPECT_EQ(42u, It->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(StringMapTest, IterMapKeys) {
|
||||||
|
StringMap<int> Map;
|
||||||
|
Map["A"] = 1;
|
||||||
|
Map["B"] = 2;
|
||||||
|
Map["C"] = 3;
|
||||||
|
Map["D"] = 3;
|
||||||
|
|
||||||
|
auto Keys = to_vector<4>(Map.keys());
|
||||||
|
std::sort(Keys.begin(), Keys.end());
|
||||||
|
|
||||||
|
SmallVector<StringRef, 4> Expected = {"A", "B", "C", "D"};
|
||||||
|
EXPECT_EQ(Expected, Keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(StringMapTest, IterSetKeys) {
|
||||||
|
StringSet<> Set;
|
||||||
|
Set.insert("A");
|
||||||
|
Set.insert("B");
|
||||||
|
Set.insert("C");
|
||||||
|
Set.insert("D");
|
||||||
|
|
||||||
|
auto Keys = to_vector<4>(Set.keys());
|
||||||
|
std::sort(Keys.begin(), Keys.end());
|
||||||
|
|
||||||
|
SmallVector<StringRef, 4> Expected = {"A", "B", "C", "D"};
|
||||||
|
EXPECT_EQ(Expected, Keys);
|
||||||
|
}
|
||||||
|
|
||||||
// Create a non-default constructable value
|
// Create a non-default constructable value
|
||||||
struct StringMapTestStruct {
|
struct StringMapTestStruct {
|
||||||
StringMapTestStruct(int i) : i(i) {}
|
StringMapTestStruct(int i) : i(i) {}
|
||||||
|
Loading…
Reference in New Issue
Block a user