llvm.org GIT mirror llvm / 26bdd1d
Improve StringMap iterator support. StringMap's iterators did not support LLVM's iterator_facade_base, which made it unusable in various STL algorithms or with some of our range adapters. This patch makes both StringMapConstIterator as well as StringMapIterator support iterator_facade_base. With this in place, it is easy to make an iterator adapter that iterates over only keys, and whose value_type is StringRef. So I add StringMapKeyIterator as well, and provide the method StringMap::keys() that returns a range that can be iterated. Differential Revision: https://reviews.llvm.org/D31171 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@298436 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 3 years ago
3 changed file(s) with 107 addition(s) and 39 deletion(s). Raw diff Collapse all Expand all
892892 /// SmallVector with elements of the vector. This is useful, for example,
893893 /// when you want to iterate a range and then sort the results.
894894 template
895 SmallVector<detail::ValueOfRange, Size> to_vector(R &&Range) {
895 SmallVector<typename std::remove_const>::type, Size>
896 to_vector(R &&Range) {
896897 return {std::begin(Range), std::end(Range)};
897898 }
898899
1414 #define LLVM_ADT_STRINGMAP_H
1515
1616 #include "llvm/ADT/StringRef.h"
17 #include "llvm/ADT/iterator.h"
1718 #include "llvm/Support/Allocator.h"
1819 #include "llvm/Support/PointerLikeTypeTraits.h"
1920 #include
2021 #include
2122 #include
2223 #include
23 #include
2424 #include
2525 #include
2626 #include
3131 class StringMapConstIterator;
3232 template
3333 class StringMapIterator;
34 template class StringMapKeyIterator;
3435 template
3536 class StringMapEntry;
3637
311312 return const_iterator(TheTable+NumBuckets, true);
312313 }
313314
315 llvm::iterator_range> keys() const {
316 return make_range(StringMapKeyIterator(begin()),
317 StringMapKeyIterator(end()));
318 }
319
314320 iterator find(StringRef Key) {
315321 int Bucket = FindKey(Key);
316322 if (Bucket == -1) return end();
443449 }
444450 };
445451
446 template ValueTy> class StringMapConstIterator {
452 template DerivedTy, typename ValueTy>
453 class StringMapIterBase
454 : public iterator_facade_base
455 ValueTy> {
447456 protected:
448457 StringMapEntryBase **Ptr = nullptr;
449458
450459 public:
451 typedef StringMapEntry value_type;
452
453 StringMapConstIterator() = default;
454
455 explicit StringMapConstIterator(StringMapEntryBase **Bucket,
456 bool NoAdvance = false)
457 : Ptr(Bucket) {
460 StringMapIterBase() = default;
461
462 explicit StringMapIterBase(StringMapEntryBase **Bucket,
463 bool NoAdvance = false)
464 : Ptr(Bucket) {
458465 if (!NoAdvance) AdvancePastEmptyBuckets();
459466 }
460467
461 const value_type &operator*() const {
462 return *static_cast*>(*Ptr);
463 }
464 const value_type *operator->() const {
465 return static_cast*>(*Ptr);
466 }
467
468 bool operator==(const StringMapConstIterator &RHS) const {
469 return Ptr == RHS.Ptr;
470 }
471 bool operator!=(const StringMapConstIterator &RHS) const {
472 return Ptr != RHS.Ptr;
473 }
474
475 inline StringMapConstIterator& operator++() { // Preincrement
468 DerivedTy &operator=(const DerivedTy &Other) {
469 Ptr = Other.Ptr;
470 return static_cast(*this);
471 }
472
473 bool operator==(const DerivedTy &RHS) const { return Ptr == RHS.Ptr; }
474
475 DerivedTy &operator++() { // Preincrement
476476 ++Ptr;
477477 AdvancePastEmptyBuckets();
478 return *this;
479 }
480 StringMapConstIterator operator++(int) { // Postincrement
481 StringMapConstIterator tmp = *this; ++*this; return tmp;
478 return static_cast(*this);
479 }
480
481 DerivedTy operator++(int) { // Post-increment
482 DerivedTy Tmp(Ptr);
483 ++*this;
484 return Tmp;
482485 }
483486
484487 private:
488491 }
489492 };
490493
491 template
492 class StringMapIterator : public StringMapConstIterator {
494 template
495 class StringMapConstIterator
496 : public StringMapIterBase,
497 const StringMapEntry> {
498 public:
499 StringMapConstIterator() = default;
500 explicit StringMapConstIterator(StringMapEntryBase **Bucket,
501 bool NoAdvance = false)
502 : StringMapIterBase(Bucket, NoAdvance) {}
503
504 const StringMapEntry &operator*() const {
505 return *static_cast *>(*Ptr);
506 }
507 };
508
509 template
510 class StringMapIterator : public StringMapIterBase,
511 StringMapEntry> {
493512 public:
494513 StringMapIterator() = default;
495
496514 explicit StringMapIterator(StringMapEntryBase **Bucket,
497515 bool NoAdvance = false)
498 : StringMapConstIterator(Bucket, NoAdvance) {
499 }
516 : StringMapIterBase(Bucket, NoAdvance) {}
500517
501518 StringMapEntry &operator*() const {
502 return *static_cast*>(*this->Ptr);
503 }
504 StringMapEntry *operator->() const {
505 return static_cast*>(*this->Ptr);
506 }
519 return *static_cast *>(*Ptr);
520 }
521
522 operator StringMapConstIterator() const {
523 return StringMapConstIterator(Ptr, false);
524 }
525 };
526
527 template
528 class StringMapKeyIterator
529 : public iterator_adaptor_base,
530 StringMapConstIterator,
531 std::forward_iterator_tag, StringRef> {
532 public:
533 StringMapKeyIterator() = default;
534
535 explicit StringMapKeyIterator(StringMapConstIterator Iter)
536 : iterator_adaptor_base(std::move(Iter)) {}
537
538 StringRef &operator*() {
539 Key = wrapped()->getKey();
540 return Key;
541 }
542
543 private:
544 StringRef Key;
507545 };
508546
509547 } // end namespace llvm
77 //===----------------------------------------------------------------------===//
88
99 #include "llvm/ADT/StringMap.h"
10 #include "llvm/ADT/StringSet.h"
1011 #include "llvm/ADT/Twine.h"
1112 #include "llvm/Support/DataTypes.h"
1213 #include "gtest/gtest.h"
266267 EXPECT_EQ(16u, t.getNumBuckets());
267268 EXPECT_EQ("abcdef", It->first());
268269 EXPECT_EQ(42u, It->second);
270 }
271
272 TEST_F(StringMapTest, IterMapKeys) {
273 StringMap Map;
274 Map["A"] = 1;
275 Map["B"] = 2;
276 Map["C"] = 3;
277 Map["D"] = 3;
278
279 auto Keys = to_vector<4>(Map.keys());
280 std::sort(Keys.begin(), Keys.end());
281
282 SmallVector Expected = {"A", "B", "C", "D"};
283 EXPECT_EQ(Expected, Keys);
284 }
285
286 TEST_F(StringMapTest, IterSetKeys) {
287 StringSet<> Set;
288 Set.insert("A");
289 Set.insert("B");
290 Set.insert("C");
291 Set.insert("D");
292
293 auto Keys = to_vector<4>(Set.keys());
294 std::sort(Keys.begin(), Keys.end());
295
296 SmallVector Expected = {"A", "B", "C", "D"};
297 EXPECT_EQ(Expected, Keys);
269298 }
270299
271300 // Create a non-default constructable value