/src/rocksdb/util/vector_iterator.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. |
2 | | #pragma once |
3 | | |
4 | | #include <algorithm> |
5 | | #include <string> |
6 | | #include <vector> |
7 | | |
8 | | #include "db/dbformat.h" |
9 | | #include "rocksdb/comparator.h" |
10 | | #include "rocksdb/iterator.h" |
11 | | #include "rocksdb/slice.h" |
12 | | #include "table/internal_iterator.h" |
13 | | |
14 | | namespace ROCKSDB_NAMESPACE { |
15 | | |
16 | | // Iterator over a vector of keys/values |
17 | | class VectorIterator : public InternalIterator { |
18 | | public: |
19 | | VectorIterator(std::vector<std::string> keys, std::vector<std::string> values, |
20 | | const CompareInterface* icmp = nullptr) |
21 | 0 | : keys_(std::move(keys)), |
22 | 0 | values_(std::move(values)), |
23 | 0 | current_(keys_.size()), |
24 | 0 | indexed_cmp_(icmp, &keys_) { |
25 | 0 | assert(keys_.size() == values_.size()); |
26 | |
|
27 | 0 | indices_.reserve(keys_.size()); |
28 | 0 | for (size_t i = 0; i < keys_.size(); i++) { |
29 | 0 | indices_.push_back(i); |
30 | 0 | } |
31 | 0 | if (icmp != nullptr) { |
32 | 0 | std::sort(indices_.begin(), indices_.end(), indexed_cmp_); |
33 | 0 | } |
34 | 0 | } |
35 | | |
36 | 0 | bool Valid() const override { |
37 | 0 | return !indices_.empty() && current_ < indices_.size(); |
38 | 0 | } |
39 | | |
40 | 0 | void SeekToFirst() override { current_ = 0; } |
41 | 0 | void SeekToLast() override { current_ = indices_.size() - 1; } |
42 | | |
43 | 0 | void Seek(const Slice& target) override { |
44 | 0 | if (indexed_cmp_.cmp != nullptr) { |
45 | 0 | current_ = std::lower_bound(indices_.begin(), indices_.end(), target, |
46 | 0 | indexed_cmp_) - |
47 | 0 | indices_.begin(); |
48 | 0 | } else { |
49 | 0 | current_ = |
50 | 0 | std::lower_bound(keys_.begin(), keys_.end(), target.ToString()) - |
51 | 0 | keys_.begin(); |
52 | 0 | } |
53 | 0 | } |
54 | | |
55 | 0 | void SeekForPrev(const Slice& target) override { |
56 | 0 | if (indexed_cmp_.cmp != nullptr) { |
57 | 0 | current_ = std::upper_bound(indices_.begin(), indices_.end(), target, |
58 | 0 | indexed_cmp_) - |
59 | 0 | indices_.begin(); |
60 | 0 | } else { |
61 | 0 | current_ = |
62 | 0 | std::upper_bound(keys_.begin(), keys_.end(), target.ToString()) - |
63 | 0 | keys_.begin(); |
64 | 0 | } |
65 | 0 | if (!Valid()) { |
66 | 0 | SeekToLast(); |
67 | 0 | } else { |
68 | 0 | Prev(); |
69 | 0 | } |
70 | 0 | } |
71 | | |
72 | 0 | void Next() override { current_++; } |
73 | 0 | void Prev() override { current_--; } |
74 | | |
75 | 0 | Slice key() const override { return Slice(keys_[indices_[current_]]); } |
76 | 0 | Slice value() const override { return Slice(values_[indices_[current_]]); } |
77 | | |
78 | 0 | Status status() const override { return Status::OK(); } |
79 | | |
80 | 0 | bool IsKeyPinned() const override { return true; } |
81 | 0 | bool IsValuePinned() const override { return true; } |
82 | | |
83 | | protected: |
84 | | std::vector<std::string> keys_; |
85 | | std::vector<std::string> values_; |
86 | | size_t current_; |
87 | | |
88 | | private: |
89 | | struct IndexedKeyComparator { |
90 | | IndexedKeyComparator(const CompareInterface* c, |
91 | | const std::vector<std::string>* ks) |
92 | 0 | : cmp(c), keys(ks) {} |
93 | | |
94 | 0 | bool operator()(size_t a, size_t b) const { |
95 | 0 | return cmp->Compare((*keys)[a], (*keys)[b]) < 0; |
96 | 0 | } |
97 | | |
98 | 0 | bool operator()(size_t a, const Slice& b) const { |
99 | 0 | return cmp->Compare((*keys)[a], b) < 0; |
100 | 0 | } |
101 | | |
102 | 0 | bool operator()(const Slice& a, size_t b) const { |
103 | 0 | return cmp->Compare(a, (*keys)[b]) < 0; |
104 | 0 | } |
105 | | |
106 | | const CompareInterface* cmp; |
107 | | const std::vector<std::string>* keys; |
108 | | }; |
109 | | |
110 | | IndexedKeyComparator indexed_cmp_; |
111 | | std::vector<size_t> indices_; |
112 | | }; |
113 | | |
114 | | } // namespace ROCKSDB_NAMESPACE |