Gemmi C++ API
Loading...
Searching...
No Matches
iterator.hpp
Go to the documentation of this file.
1// Copyright 2018 Global Phasing Ltd.
2//
3// Bidirectional iterators (over elements of any container) that can filter,
4// uniquify, group, or iterate with a stride.
5
6#ifndef GEMMI_ITERATOR_HPP_
7#define GEMMI_ITERATOR_HPP_
8#include <iterator> // for bidirectional_iterator_tag
9#include <type_traits> // for remove_cv
10#include <vector>
11
12namespace gemmi {
13
14// Disable warning "X<T>::operator X<T>() const will not be called for
15// implicit or explicit conversions", which is triggered when templates
16// StrideIter, IndirectIter and others are expanded with const Value.
17#if defined(__INTEL_COMPILER) || defined(__NVCOMPILER)
18 #pragma diagnostic push
19 #pragma diag_suppress = conversion_function_not_usable
20#elif defined(__NVCC__)
21 #pragma nv_diagnostic push
22 #pragma nv_diag_suppress = conversion_function_not_usable
23#endif
24
25// implements concept BidirectionalIterator
26template <typename Policy>
27struct BidirIterator : Policy {
28 using value_type = typename std::remove_cv<typename Policy::value_type>::type;
29 using difference_type = std::ptrdiff_t;
30 using pointer = typename Policy::value_type*;
31 using reference = typename Policy::reference;
32 using iterator_category = std::bidirectional_iterator_tag;
33
34 BidirIterator() = default;
35 BidirIterator(Policy&& p) : Policy(p) {}
36
37 BidirIterator& operator++() { Policy::increment(); return *this; }
38 BidirIterator operator++(int) { BidirIterator x = *this; ++*this; return x; }
39 BidirIterator& operator--() { Policy::decrement(); return *this; }
40 BidirIterator operator--(int) { BidirIterator x = *this; --*this; return x; }
41 bool operator==(const BidirIterator &o) const { return Policy::equal(o); }
42 bool operator!=(const BidirIterator &o) const { return !Policy::equal(o); }
43 reference operator*() { return Policy::dereference(); }
44 pointer operator->() { return &Policy::dereference(); }
46 operator const_variant() const {
47 return const_variant(static_cast<const Policy&>(*this));
48 }
49};
50
51template<typename Value>
53public:
55 using reference = Value&;
56 StrideIterPolicy() : cur_(nullptr), offset_(0), stride_(0) {}
57 StrideIterPolicy(Value* ptr, std::size_t offset, size_t stride)
58 : cur_(ptr), offset_(offset), stride_((unsigned)stride) {}
59 void increment() { cur_ += stride_; }
60 void decrement() { cur_ -= stride_; }
61 bool equal(const StrideIterPolicy& o) const { return cur_ == o.cur_; }
62 Value& dereference() { return cur_[offset_]; }
64 operator const_policy() const { return const_policy(cur_, offset_, stride_); }
65private:
66 Value* cur_;
67 std::size_t offset_;
68 unsigned stride_;
69};
70template<typename Value>
72
73
74template<typename Redirect, typename Value>
76public:
78 using reference = Value&;
80 IndirectIterPolicy(Redirect* redir, std::vector<int>::const_iterator cur)
81 : redir_(redir), cur_(cur) {}
82 void increment() { ++cur_; }
83 void decrement() { --cur_; }
84 bool equal(const IndirectIterPolicy& o) const { return cur_ == o.cur_; }
85 Value& dereference() { return redir_->value_at(*cur_); }
87 operator const_policy() const { return const_policy(redir_, cur_); }
88 // TODO: what should be done with absent optional tags (*cur_ < 0)?
89private:
90 Redirect* redir_;
91 std::vector<int>::const_iterator cur_; // points into positions
92};
93template<typename Redirect, typename Value>
95
96
97template<typename Vector, typename Value>
99public:
101 using reference = Value&;
102 UniqIterPolicy() : vec_(nullptr), pos_(0) {}
103 UniqIterPolicy(Vector* vec, std::size_t pos) : vec_(vec), pos_(pos) {}
104 void increment() {
105 // move to the first element of the next group
106 const auto& key = (*vec_)[pos_].group_key();
107 ++pos_;
108 while (pos_ != vec_->size() && (*vec_)[pos_].group_key() == key)
109 ++pos_;
110 }
111 void decrement() {
112 --pos_; // now we are at the last element of the previous group
113 const auto& key = (*vec_)[pos_].group_key();
114 while (pos_ != 0 && (*vec_)[pos_-1].group_key() == key)
115 --pos_; // move to the group beginning
116 }
117 bool equal(const UniqIterPolicy& o) const { return pos_ == o.pos_; }
118 Value& dereference() { return (*vec_)[pos_]; }
120 operator const_policy() const { return const_policy(vec_, pos_); }
121private:
122 Vector* vec_;
123 std::size_t pos_;
124};
125template<typename Vector, typename Value>
127
128template<typename Value, typename Vector=std::vector<Value>>
129struct UniqProxy {
132 iterator begin() { return {{&vec, 0}}; }
133 iterator end() { return {{&vec, vec.size()}}; }
134};
135template<typename Value, typename Vector=std::vector<Value>>
137 const Vector& vec;
139 iterator begin() const { return {{&vec, 0}}; }
140 iterator end() const { return {{&vec, vec.size()}}; }
141};
142
143
144template<typename Vector, typename Value>
146public:
148 using reference = Value&;
150 GroupingIterPolicy(const Value& span) : span_(span) {}
151 void increment() {
152 span_.set_begin(span_.end());
153 span_.set_size(0);
154 while (!span_.is_ending() &&
155 span_.begin()->group_key() == span_.end()->group_key())
156 span_.set_size(span_.size() + 1);
157 }
158 void decrement() {
159 span_.set_begin(span_.begin() - 1);
160 span_.set_size(1);
161 while (!span_.is_beginning() &&
162 span_.begin()->group_key() == (span_.begin() - 1)->group_key()) {
163 span_.set_begin(span_.begin() - 1);
164 span_.set_size(span_.size() + 1);
165 }
166 }
167 bool equal(const GroupingIterPolicy& o) const {
168 return span_.begin() == o.span_.begin();
169 }
170 Value& dereference() { return span_; }
172 operator const_policy() const { return const_policy(span_); }
173private:
174 Value span_;
175};
176template<typename Vector, typename Value>
178
179
180template<typename Filter, typename Vector, typename Value>
182public:
184 using reference = Value&;
185 FilterIterPolicy() : vec_(nullptr), pos_(0) {}
186 FilterIterPolicy(const Filter* filter, Vector* vec, std::size_t pos)
187 : filter_(filter), vec_(vec), pos_(pos) {
188 while (pos_ != vec_->size() && !matches(pos_))
189 ++pos_;
190 }
191 bool matches(std::size_t p) const { return filter_->matches((*vec_)[p]); }
192 void increment() { while (++pos_ < vec_->size() && !matches(pos_)) {} }
193 void decrement() { while (pos_ != 0 && !matches(--pos_)) {} }
194 bool equal(const FilterIterPolicy& o) const { return pos_ == o.pos_; }
195 Value& dereference() { return (*vec_)[pos_]; }
197 operator const_policy() const { return const_policy(vec_, pos_); }
198private:
199 const Filter* filter_;
200 Vector* vec_;
201 std::size_t pos_;
202};
203template<typename Filter, typename Vector, typename Value>
205
206template<typename Filter, typename Value>
209 std::vector<Value>& vec;
211 iterator begin() { return {{&filter, &vec, 0}}; }
212 iterator end() { return {{&filter, &vec, vec.size()}}; }
213};
214
215template<typename Filter, typename Value>
218 const std::vector<Value>& vec;
220 iterator begin() const { return {{&filter, &vec, 0}}; }
221 iterator end() const { return {{&filter, &vec, vec.size()}}; }
222};
223
224
225template<typename Item>
226struct ItemGroup {
227 using element_type = Item;
228
229 ItemGroup(Item* start, const Item* end)
230 : size_(int(end - start)), extent_(int(end - start)), start_(start) {
231 for (const Item* i = start + 1; i != end; ++i)
232 if (i->group_key() != start->group_key())
233 --size_;
234 }
235
236 struct iterator {
237 Item* ptr;
238 const Item* end;
239 bool operator==(const iterator& o) const { return ptr == o.ptr; }
240 bool operator!=(const iterator& o) const { return ptr != o.ptr; }
242 const Item* prev = ptr++;
243 while (ptr != end && ptr->group_key() != prev->group_key())
244 ++ptr;
245 return *this;
246 }
247 Item& operator*() { return *ptr; }
248 Item* operator->() { return ptr; }
249 };
250 iterator begin() { return iterator{start_, start_+extent_}; }
251 iterator end() { return iterator{start_+extent_, start_+extent_}; }
252
253 size_t size() const { return (size_t) size_; }
254 int extent() const { return extent_; }
255 bool empty() const { return size_ == 0; }
256 Item& front() { return *start_; }
257 const Item& front() const { return *start_; }
258 Item& back() { return start_[extent_ - 1]; }
259 const Item& back() const { return start_[extent_ - 1]; }
260
261 // constant time unless sparse (extend_ > size_)
262 Item& operator[](std::size_t i) {
263 if (size_ == extent_ || i == 0)
264 return start_[i];
265 for (Item* ptr = start_ + 1; ; ++ptr)
266 if (ptr->group_key() == start_->group_key())
267 if (--i == 0)
268 return *ptr;
269 }
270 const Item& operator[](std::size_t i) const {
271 return const_cast<ItemGroup*>(this)->operator[](i);
272 }
273
274private:
275 int size_ = 0;
276 int extent_ = 0;
277 Item* start_ = nullptr;
278};
279
280#if defined(__INTEL_COMPILER) || defined(__NVCOMPILER)
281 #pragma diagnostic pop
282#elif defined(__NVCC__)
283 #pragma nv_diagnostic pop
284#endif
285
286} // namespace gemmi
287#endif
bool equal(const FilterIterPolicy &o) const
Definition iterator.hpp:194
bool matches(std::size_t p) const
Definition iterator.hpp:191
FilterIterPolicy< Filter, Vector const, Value const > const_policy
Definition iterator.hpp:196
FilterIterPolicy(const Filter *filter, Vector *vec, std::size_t pos)
Definition iterator.hpp:186
GroupingIterPolicy< Vector const, Value const > const_policy
Definition iterator.hpp:171
bool equal(const GroupingIterPolicy &o) const
Definition iterator.hpp:167
GroupingIterPolicy(const Value &span)
Definition iterator.hpp:150
bool equal(const IndirectIterPolicy &o) const
Definition iterator.hpp:84
IndirectIterPolicy< Redirect const, Value const > const_policy
Definition iterator.hpp:86
IndirectIterPolicy(Redirect *redir, std::vector< int >::const_iterator cur)
Definition iterator.hpp:80
StrideIterPolicy< Value const > const_policy
Definition iterator.hpp:63
bool equal(const StrideIterPolicy &o) const
Definition iterator.hpp:61
StrideIterPolicy(Value *ptr, std::size_t offset, size_t stride)
Definition iterator.hpp:57
bool equal(const UniqIterPolicy &o) const
Definition iterator.hpp:117
UniqIterPolicy(Vector *vec, std::size_t pos)
Definition iterator.hpp:103
UniqIterPolicy< Vector const, Value const > const_policy
Definition iterator.hpp:119
bool operator==(const BidirIterator &o) const
Definition iterator.hpp:41
reference operator*()
Definition iterator.hpp:43
BidirIterator< typename Policy::const_policy > const_variant
Definition iterator.hpp:45
typename Policy::value_type * pointer
Definition iterator.hpp:30
typename Policy::reference reference
Definition iterator.hpp:31
std::bidirectional_iterator_tag iterator_category
Definition iterator.hpp:32
BidirIterator operator--(int)
Definition iterator.hpp:40
std::ptrdiff_t difference_type
Definition iterator.hpp:29
bool operator!=(const BidirIterator &o) const
Definition iterator.hpp:42
BidirIterator & operator--()
Definition iterator.hpp:39
BidirIterator operator++(int)
Definition iterator.hpp:38
BidirIterator(Policy &&p)
Definition iterator.hpp:35
BidirIterator & operator++()
Definition iterator.hpp:37
typename std::remove_cv< typename Policy::value_type >::type value_type
Definition iterator.hpp:28
const Filter & filter
Definition iterator.hpp:217
iterator begin() const
Definition iterator.hpp:220
const std::vector< Value > & vec
Definition iterator.hpp:218
iterator end() const
Definition iterator.hpp:221
const Vector & vec
Definition iterator.hpp:137
iterator end() const
Definition iterator.hpp:140
iterator begin() const
Definition iterator.hpp:139
std::vector< Value > & vec
Definition iterator.hpp:209
const Filter & filter
Definition iterator.hpp:208
bool operator!=(const iterator &o) const
Definition iterator.hpp:240
bool operator==(const iterator &o) const
Definition iterator.hpp:239
const Item & operator[](std::size_t i) const
Definition iterator.hpp:270
bool empty() const
Definition iterator.hpp:255
iterator end()
Definition iterator.hpp:251
int extent() const
Definition iterator.hpp:254
const Item & front() const
Definition iterator.hpp:257
iterator begin()
Definition iterator.hpp:250
ItemGroup(Item *start, const Item *end)
Definition iterator.hpp:229
size_t size() const
Definition iterator.hpp:253
Item & operator[](std::size_t i)
Definition iterator.hpp:262
const Item & back() const
Definition iterator.hpp:259
iterator begin()
Definition iterator.hpp:132
iterator end()
Definition iterator.hpp:133