Index: llvm/include/llvm/ADT/StringExtras.h =================================================================== --- llvm/include/llvm/ADT/StringExtras.h +++ llvm/include/llvm/ADT/StringExtras.h @@ -251,6 +251,11 @@ return Result; } +template +inline std::string join_range(Range &&R, Sep Separator) { + return join(R.begin(), R.end(), Separator); +} + } // End llvm namespace #endif Index: llvm/include/llvm/ADT/StringMap.h =================================================================== --- llvm/include/llvm/ADT/StringMap.h +++ llvm/include/llvm/ADT/StringMap.h @@ -15,13 +15,13 @@ #define LLVM_ADT_STRINGMAP_H #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/PointerLikeTypeTraits.h" #include #include #include #include -#include #include #include #include @@ -32,6 +32,7 @@ class StringMapConstIterator; template class StringMapIterator; + template class StringMapKeyIterator; template class StringMapEntry; @@ -312,6 +313,11 @@ return const_iterator(TheTable+NumBuckets, true); } + llvm::iterator_range> keys() const { + return make_range(StringMapKeyIterator(begin()), + StringMapKeyIterator(end())); + } + iterator find(StringRef Key) { int Bucket = FindKey(Key); if (Bucket == -1) return end(); @@ -444,42 +450,33 @@ } }; -template class StringMapConstIterator { +template +class StringMapIterBase + : public iterator_facade_base { protected: StringMapEntryBase **Ptr = nullptr; public: - typedef StringMapEntry value_type; + StringMapIterBase() = default; - StringMapConstIterator() = default; - - explicit StringMapConstIterator(StringMapEntryBase **Bucket, - bool NoAdvance = false) - : Ptr(Bucket) { + explicit StringMapIterBase(StringMapEntryBase **Bucket, + bool NoAdvance = false) + : Ptr(Bucket) { if (!NoAdvance) AdvancePastEmptyBuckets(); } - const value_type &operator*() const { - return *static_cast*>(*Ptr); - } - const value_type *operator->() const { - return static_cast*>(*Ptr); + DerivedTy &operator=(const DerivedTy &Other) { + Ptr = Other.Ptr; + return static_cast(*this); } - bool operator==(const StringMapConstIterator &RHS) const { - return Ptr == RHS.Ptr; - } - bool operator!=(const StringMapConstIterator &RHS) const { - return Ptr != RHS.Ptr; - } + bool operator==(const DerivedTy &RHS) const { return Ptr == RHS.Ptr; } - inline StringMapConstIterator& operator++() { // Preincrement + DerivedTy &operator++() { // Preincrement ++Ptr; AdvancePastEmptyBuckets(); - return *this; - } - StringMapConstIterator operator++(int) { // Postincrement - StringMapConstIterator tmp = *this; ++*this; return tmp; + return static_cast(*this); } private: @@ -489,24 +486,53 @@ } }; -template -class StringMapIterator : public StringMapConstIterator { +template +class StringMapConstIterator + : public StringMapIterBase, + const StringMapEntry> { public: - StringMapIterator() = default; + StringMapConstIterator() = default; + explicit StringMapConstIterator(StringMapEntryBase **Bucket, + bool NoAdvance = false) + : StringMapIterBase(Bucket, NoAdvance) {} + + const StringMapEntry &operator*() const { + return *static_cast *>(*Ptr); + } +}; +template +class StringMapIterator : public StringMapIterBase, + StringMapEntry> { +public: + StringMapIterator() = default; explicit StringMapIterator(StringMapEntryBase **Bucket, bool NoAdvance = false) - : StringMapConstIterator(Bucket, NoAdvance) { - } + : StringMapIterBase(Bucket, NoAdvance) {} StringMapEntry &operator*() const { - return *static_cast*>(*this->Ptr); + return *static_cast *>(*Ptr); } - StringMapEntry *operator->() const { - return static_cast*>(*this->Ptr); + + operator StringMapConstIterator() const { + return StringMapConstIterator(Ptr, false); } }; +template +class StringMapKeyIterator + : public iterator_adaptor_base, + StringMapConstIterator, + std::forward_iterator_tag, StringRef> { +public: + StringMapKeyIterator() = default; + + explicit StringMapKeyIterator(StringMapConstIterator Iter) + : iterator_adaptor_base(std::move(Iter)) {} + + StringRef operator*() const { return I->getKey(); } +}; + } // end namespace llvm #endif // LLVM_ADT_STRINGMAP_H Index: llvm/unittests/Support/CMakeLists.txt =================================================================== --- llvm/unittests/Support/CMakeLists.txt +++ llvm/unittests/Support/CMakeLists.txt @@ -44,6 +44,7 @@ ScaledNumberTest.cpp SourceMgrTest.cpp SpecialCaseListTest.cpp + StringMap.cpp StringPool.cpp SwapByteOrderTest.cpp TarWriterTest.cpp Index: llvm/unittests/Support/StringMap.cpp =================================================================== --- /dev/null +++ llvm/unittests/Support/StringMap.cpp @@ -0,0 +1,43 @@ +//=== - llvm/unittest/Support/StringMap.cpp - StringMap tests -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" + +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringSet.h" + +using namespace llvm; + +TEST(StringMap, IterMapKeys) { + StringMap 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 Expected = {"A", "B", "C", "D"}; + EXPECT_EQ(Expected, Keys); +} + +TEST(StringMap, 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 Expected = {"A", "B", "C", "D"}; + EXPECT_EQ(Expected, Keys); +}