Coverage Report

Created: 2025-07-23 07:17

/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