llvm.org GIT mirror llvm / d10b8de
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 Zachary Turner 2 years ago
3 changed file(s) with 117 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 using base = StringMapIterBase,
499 const StringMapEntry>;
500
501 public:
502 StringMapConstIterator() = default;
503 explicit StringMapConstIterator(StringMapEntryBase **Bucket,
504 bool NoAdvance = false)
505 : base(Bucket, NoAdvance) {}
506
507 const StringMapEntry &operator*() const {
508 return *static_cast *>(*this->Ptr);
509 }
510 };
511
512 template
513 class StringMapIterator : public StringMapIterBase,
514 StringMapEntry> {
515 using base =
516 StringMapIterBase, StringMapEntry>;
517
493518 public:
494519 StringMapIterator() = default;
495
496520 explicit StringMapIterator(StringMapEntryBase **Bucket,
497521 bool NoAdvance = false)
498 : StringMapConstIterator(Bucket, NoAdvance) {
499 }
522 : base(Bucket, NoAdvance) {}
500523
501524 StringMapEntry &operator*() const {
502 return *static_cast*>(*this->Ptr);
503 }
504 StringMapEntry *operator->() const {
505 return static_cast*>(*this->Ptr);
506 }
525 return *static_cast *>(*this->Ptr);
526 }
527
528 operator StringMapConstIterator() const {
529 return StringMapConstIterator(this->Ptr, true);
530 }
531 };
532
533 template
534 class StringMapKeyIterator
535 : public iterator_adaptor_base,
536 StringMapConstIterator,
537 std::forward_iterator_tag, StringRef> {
538 using base = iterator_adaptor_base,
539 StringMapConstIterator,
540 std::forward_iterator_tag, StringRef>;
541
542 public:
543 StringMapKeyIterator() = default;
544
545 explicit StringMapKeyIterator(StringMapConstIterator Iter)
546 : base(std::move(Iter)) {}
547
548 StringRef &operator*() {
549 Key = this->wrapped()->getKey();
550 return Key;
551 }
552
553 private:
554 StringRef Key;
507555 };
508556
509557 } // 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