chunkedseq
container library for large in-memory data sets
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
iterator.hpp
Go to the documentation of this file.
1 
13 #include <assert.h>
14 #include <iterator>
15 
16 #include "itemsearch.hpp"
17 
18 #ifndef _PASL_DATA_ITERATOR_H_
19 #define _PASL_DATA_ITERATOR_H_
20 
21 namespace pasl {
22 namespace data {
23 namespace chunkedseq {
24 namespace iterator {
25 
26 /***********************************************************************/
27 
28 using position_type = enum { begin, end };
29 
30 /*---------------------------------------------------------------------*/
32 
41 template <class Configuration>
43 private:
44 
45  using config_type = Configuration;
46  using chunk_pointer = const typename config_type::chunk_type*;
47  using segment_type = typename config_type::segment_type;
48 
49 public:
50 
51  using iterator_category = std::bidirectional_iterator_tag;
53  using difference_type = typename config_type::difference_type;
54  using pointer = value_type*;
57 
58 private:
59 
60  chunk_pointer cur;
61  segment_type seg;
62 
63  self_type& increment() {
64  assert(false); // todo
65  return *this;
66  }
67 
68  self_type& decrement() {
69  assert(false); // todo
70  return *this;
71  }
72 
73 public:
74 
75  bidirectional(chunk_pointer p)
76  : cur(p) {
77  assert(false); // todo
78  }
79 
81  assert(false); // todo
82  }
83 
84  /*---------------------------------------------------------------------*/
87 
89  bool operator==(const self_type& other) const {
90  return seg.middle == other.seg.middle
91  && seg.end == other.seg.end;
92  }
93 
94  bool operator!=(const self_type& other) const {
95  return ! (*this == other);
96  }
97 
98  reference operator*() const {
99  return *seg.middle;
100  }
101 
103  return increment();
104  }
105 
107  return increment();
108 
109  }
110 
112  return decrement();
113  }
114 
116  return decrement();
117  }
118 
120 
121  segment_type get_segment() const {
122  return seg;
123  }
124 
125 };
126 
127 /*---------------------------------------------------------------------*/
129 
138 template <class Chunkedseq, class Configuration>
140 private:
141 
142  using chunkedseq_type = Chunkedseq;
143  using config_type = Configuration;
144  using const_chunkedseq_pointer = const chunkedseq_type*;
145  using const_chunk_pointer = const typename config_type::chunk_type*;
146 
147 public:
148 
149  /*---------------------------------------------------------------------*/
152  using iterator_category = std::random_access_iterator_tag;
154  using size_type = typename config_type::size_type;
155  using difference_type = typename config_type::difference_type;
157 
158  /*---------------------------------------------------------------------*/
164  using pointer = value_type*;
165  using const_pointer = const value_type*;
167  using const_reference = const value_type&;
168  using segment_type = typename config_type::segment_type;
170 
171  /*---------------------------------------------------------------------*/
174  using cache_type = typename config_type::middle_cache_type;
176  using measured_type = typename cache_type::measured_type;
177  using algebra_type = typename cache_type::algebra_type;
178  using measure_type = typename cache_type::measure_type;
180 
181  /*---------------------------------------------------------------------*/
182 
183 private:
184 
185  using chunk_search_type = typename config_type::chunk_search_type;
186 
187  using size_access = typename config_type::size_access;
188 
189  const_chunkedseq_pointer seq;
190  const_chunk_pointer cur;
191  segment_type seg;
192 
193  measure_type meas_fct;
194 
195  /*---------------------------------------------------------------------*/
196 
197  void check() {
198 #ifndef NDEBUG
199  size_type sz = size();
200  size_type ssz = seq->size();
201  if (sz > ssz + 1)
202  std::cout << "error" << std::endl;
203  sz = size();
204  assert(sz <= ssz + 1);
205  assert(sz >= 0);
206 #endif
207  }
208 
209  template <class Pred>
210  measured_type chunk_search_by(const Pred& p, measured_type prefix) {
211  chunk_search_type chunk_search;
212  assert(size_access::csize(prefix) != seq->size());
213  cur->annotation.prefix.set_cached(prefix);
214  auto res = chunk_search(*cur, meas_fct, prefix, p);
215  size_type pos = res.position;
216  prefix = res.prefix;
217  seg = cur->segment_by_index(pos - 1);
218  if (seg.middle - seg.begin > cur->size())
219  cur->segment_by_index(pos - 1);
220  assert(seg.middle - seg.begin <= cur->size());
221  return prefix;
222  }
223 
224  // Updates position of the iterator to the position of the target
225  // updates cur and seg fields
226  template <class Pred>
227  measured_type chunkedseq_search_by(const Pred& p, measured_type prefix) {
228  bool found;
229  if (seq->is_buffer(cur))
230  cur = nullptr;
231  prefix = seq->search_for_chunk(p, prefix, found, cur);
232  if (found) {
233  prefix = chunk_search_by(p, prefix);
234  } else {
235  // make the iterator logically point one past the end of the sequence
236  assert(size_access::csize(prefix) == seq->size());
237  cur = seq->get_chunk_containing_last_item();
238  size_type sz_cur = cur->size();
239  measured_type m = prefix;
240  size_access::size(m) = seq->size() - sz_cur;
241  cur->annotation.prefix.set_cached(m);
242  if (sz_cur == 0)
243  seg.begin = seg.end = nullptr;
244  else
245  seg = cur->segment_by_index(sz_cur - 1);
246  seg.middle = seg.end;
247  }
248  check();
249  return prefix;
250  }
251 
252  template <class Pred>
253  measured_type chunkedseq_search_by(const Pred& p) {
254  return chunkedseq_search_by(p, algebra_type::identity());
255  }
256 
257  self_type new_iterator_at(size_type sz) const {
258  self_type it(*this);
259  it.search_by_one_based_index(sz);
260  return it;
261  }
262 
263  self_type& increment_by(size_type n) {
264  check();
265  size_type orig_sz = size();
266  pointer m = seg.middle + n;
267  if (m >= seg.end)
268  search_by_one_based_index(orig_sz + n);
269  else
270  seg.middle = m;
271  assert(size() == orig_sz + n);
272  check();
273  return *this;
274  }
275 
276  self_type& decrement_by(size_type n) {
277  check();
278  size_type orig_sz = size();
279  pointer m = seg.middle - n;
280  if (m < seg.begin)
281  search_by_one_based_index(orig_sz - n);
282  else
283  seg.middle = m;
284  assert(size() == orig_sz - n);
285  check();
286  return *this;
287  }
288 
289  static size_type nb_before_middle(const_chunk_pointer c, segment_type seg) {
290  if (seg.middle == seg.end) {
291  if (seg.middle == seg.begin)
292  return 0;
293  return c->index_of_pointer(seg.middle - 1) + 1;
294  } else {
295  return c->index_of_pointer(seg.middle);
296  }
297  }
298 
299  size_type size_of_prefix() const {
300  measured_type prefix_of_chunk = cur->annotation.prefix.template get_cached<measured_type>();
301  size_type nb_items_before_chunk = size_access::csize(prefix_of_chunk);
302  size_type nb_items_before_seg_middle = nb_before_middle(cur, seg);
303  return nb_items_before_chunk + nb_items_before_seg_middle;
304  }
305 
306  void search_by_one_based_index(size_type i) {
307  using predicate_type = itemsearch::less_than_by_position<measured_type, size_type, size_access>;
308  predicate_type p(i - 1);
309  chunkedseq_search_by(p);
310  size_type sz = size();
311  size_type ssz = seq->size();
312  assert(sz <= ssz + 1);
313  assert(sz == i);
314  }
315 
316  void search_by_zero_based_index(size_type i) {
317  search_by_one_based_index(i + 1);
318  }
319 
320  /*---------------------------------------------------------------------*/
321 
322 public:
323 
324  random_access(const_chunkedseq_pointer seq, const measure_type& meas, position_type pos)
325  : seq(seq), cur(nullptr), meas_fct(meas) {
326  search_by_one_based_index(1);
327  switch (pos) {
328  case begin: {
329  search_by_one_based_index(1);
330  break;
331  }
332  case end: {
333  search_by_one_based_index(seq->size() + 1);
334  break;
335  }
336  }
337 
338  }
339 
340  random_access() : seq(nullptr), cur(nullptr) { }
341 
342  /*---------------------------------------------------------------------*/
345 
347  bool operator==(const self_type& other) const {
348  assert(seq == other.seq);
349  bool eq = seg.middle == other.seg.middle
350  && seg.end == other.seg.end;
351 #ifndef NDEBUG
352  size_type sz = size();
353  size_type sz_other = other.size();
354  assert(eq ? sz == sz_other : sz != sz_other);
355 #endif
356  return eq;
357  }
358 
359  bool operator!=(const self_type& other) const {
360  return ! (*this == other);
361  }
362 
364  return *seg.middle;
365  }
366 
367  // prefix ++
369  return increment_by(1);
370  }
371 
372  // postfix ++
374  self_type result(*this);
375  ++(*this);
376  return result;
377  }
378 
379  // prefix --
381  return decrement_by(1);
382  }
383 
384  // postfix --
386  self_type result(*this);
387  --(*this);
388  return result;
389  }
390 
392 
393  /*---------------------------------------------------------------------*/
396 
399  return increment_by(n);
400  }
401 
402  self_type operator+(const self_type& other) const {
403  return new_iterator_at(size() + other.size());
404  }
405 
406  self_type operator+(const size_type n) const {
407  return new_iterator_at(size() + n);
408  }
409 
411  return decrement_by(n);
412  }
413 
414  difference_type operator-(const self_type& other) const {
415  return size() - other.size();
416  }
417 
418  self_type operator-(const size_type n) const {
419  size_type sz = size();
420  assert(sz > n);
421  return new_iterator_at(sz - n);
422  }
423 
424  reference operator[](const size_type n) const {
425  return *(*this + n);
426  }
427 
428  bool operator<(const self_type& other) const {
429  return size() < other.size();
430  }
431 
432  bool operator>(const self_type& other) const {
433  return size() > other.size();
434  }
435 
436  bool operator<=(const self_type& other) const {
437  return size() <= other.size();
438  }
439 
440  bool operator>=(const self_type& other) const {
441  return size() >= other.size();
442  }
443 
445 
446  /*---------------------------------------------------------------------*/
449 
459  size_type size() const {
460  return size_of_prefix() + 1;
461  }
462 
463  template <class Pred>
464  void search_by(const Pred& p) {
465  auto q = [&] (measured_type m) {
466  return p(size_access::cclient(m));
467  };
468  chunkedseq_search_by(q, algebra_type::identity());
469  }
470 
472  return seg;
473  }
474 
476 
477 };
478 
479 /***********************************************************************/
480 
481 } // end namespace
482 } // end namespace
483 } // end namespace
484 } // end namespace
485 
486 #endif
typename config_type::difference_type difference_type
Definition: iterator.hpp:53
bool operator>=(const self_type &other) const
Definition: iterator.hpp:440
typename cache_type::measured_type measured_type
Definition: iterator.hpp:176
typename config_type::value_type value_type
Definition: iterator.hpp:163
typename config_type::value_type value_type
Definition: iterator.hpp:52
typename cache_type::algebra_type algebra_type
Definition: iterator.hpp:177
bool operator==(const self_type &other) const
Definition: iterator.hpp:89
self_type & operator-=(const size_type n)
Definition: iterator.hpp:410
self_type operator+(const self_type &other) const
Definition: iterator.hpp:402
bool operator==(const self_type &other) const
Definition: iterator.hpp:347
bidirectional< config_type > self_type
Definition: iterator.hpp:56
bool operator<=(const self_type &other) const
Definition: iterator.hpp:436
self_type operator+(const size_type n) const
Definition: iterator.hpp:406
typename config_type::segment_type segment_type
Definition: iterator.hpp:168
difference_type operator-(const self_type &other) const
Definition: iterator.hpp:414
std::random_access_iterator_tag iterator_category
Definition: iterator.hpp:153
random_access< chunkedseq_type, config_type > self_type
Definition: iterator.hpp:162
bool operator>(const self_type &other) const
Definition: iterator.hpp:432
Definition: algebra.hpp:18
Routines for finding an item in a container via binary search.
result_t res
Definition: bench.cpp:51
bool operator<(const self_type &other) const
Definition: iterator.hpp:428
typename cache_type::measure_type measure_type
Definition: iterator.hpp:178
bool operator!=(const self_type &other) const
Definition: iterator.hpp:359
typename config_type::size_type size_type
Definition: iterator.hpp:154
reference operator[](const size_type n) const
Definition: iterator.hpp:424
self_type & operator+=(const size_type n)
Definition: iterator.hpp:398
bool operator!=(const self_type &other) const
Definition: iterator.hpp:94
typename config_type::difference_type difference_type
Definition: iterator.hpp:155
size_type size() const
Returns the number of items preceding and including the item pointed to by the iterator.
Definition: iterator.hpp:459
typename config_type::middle_cache_type cache_type
Definition: iterator.hpp:175
enum{begin, end} position_type
Definition: iterator.hpp:28
random_access(const_chunkedseq_pointer seq, const measure_type &meas, position_type pos)
Definition: iterator.hpp:324
std::bidirectional_iterator_tag iterator_category
Definition: iterator.hpp:51
self_type operator-(const size_type n) const
Definition: iterator.hpp:418