chunkedseq
container library for large in-memory data sets
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
chunkedseqextras.hpp
Go to the documentation of this file.
1 
13 #ifndef _PASL_DATA_CHUNKEDSEQEXTRAS_H_
14 #define _PASL_DATA_CHUNKEDSEQEXTRAS_H_
15 
16 namespace pasl {
17 namespace data {
18 namespace chunkedseq {
19 namespace extras {
20 
21 /***********************************************************************/
22 
23 /*---------------------------------------------------------------------*/
24 /* Various special-purpose forms of the split operation */
25 
26 template <class Container, class size_type>
27 void split_by_index(Container& c, size_type i, Container& other) {
28  using measured_type = typename Container::middle_measured_type;
29  using algebra_type = typename Container::middle_algebra_type;
30  using size_access = typename Container::size_access;
32  c.check(); other.check();
33  size_type size_orig = c.size();
34  assert(i >= 0);
35  assert(i <= size_orig);
36  if (size_orig == 0)
37  return;
38  if (i == size_orig)
39  return;
40  if (i == 0) {
41  c.swap(other);
42  return;
43  }
44  predicate_type p(i);
45  measured_type prefix = algebra_type::identity();
46  prefix = c.split_aux(p, prefix, other);
47  c.check(); other.check();
48  size_type size_cur = c.size();
49  size_type size_other = other.size();
50  assert(size_other + size_cur == size_orig);
51  assert(size_cur == i);
52  assert(size_other + i == size_orig);
53  assert(size_access::csize(prefix) == i);
54 }
55 
56 template <class Container, class iterator>
57 void split_by_iterator(Container& c, iterator position, Container& other) {
58  using size_type = typename Container::size_type;
59  if (position == c.end())
60  return;
61  size_type n = position.size() - 1;
62  c.split(n, other);
63 }
64 
65 template <class Container>
66 void split_approximate(Container& c, Container& other) {
67  using size_type = typename Container::size_type;
68  assert(c.size() > 1);
69  size_type mid = c.size() / 2;
70  c.split(mid, other);
71 }
72 
73 /*---------------------------------------------------------------------*/
74 /* Insert and erase */
75 
76 template <class Container, class iterator, class value_type>
77 iterator insert(Container& c, iterator position, const value_type& val) {
78  using self_type = Container;
79  using size_type = typename Container::size_type;
80  c.check();
81  size_type n = position.size() - 1;
82  self_type tmp;
83  c.split(position, tmp);
84  c.push_back(val);
85  c.concat(tmp);
86  c.check();
87  return c.begin() + n;
88 }
89 
90 template <class Container, class iterator>
91 iterator erase(Container& c, iterator first, iterator last) {
92  using self_type = Container;
93  using size_type = typename Container::size_type;
94  if (first == last)
95  return first;
96  size_type sz_orig = c.size();
97  self_type items_to_erase;
98  size_type sz_first = first.size();
99  size_type sz_last = last.size();
100  size_type nb_to_erase = sz_last - sz_first;
101  c.split(first, items_to_erase);
102  self_type tmp;
103  items_to_erase.split(nb_to_erase, tmp);
104  items_to_erase.swap(tmp);
105  c.concat(items_to_erase);
106  assert(c.size() + nb_to_erase == sz_orig);
107  return c.begin() + sz_first;
108 }
109 
110 /*---------------------------------------------------------------------*/
111 /* For each loops */
112 
113 template <class Body, class iterator>
114 void for_each_segment(iterator begin, iterator end, const Body& f) {
115  using segment_type = typename iterator::segment_type;
116  if (begin >= end)
117  return;
118  segment_type seg_end = end.get_segment();
119  for (iterator i = begin; i != end; ) {
120  segment_type seg = i.get_segment();
121  if (seg.begin == seg_end.begin)
122  seg.end = seg_end.middle;
123  f(seg.middle, seg.end);
124  i += seg.end - seg.middle;
125  }
126 }
127 
128 template <class Body, class iterator>
129 void for_each(iterator beg, iterator end, const Body& f) {
130  using value_type = typename iterator::value_type;
131  for_each_segment(beg, end, [&] (value_type* lo, value_type* hi) {
132  for (value_type* p = lo; p < hi; p++)
133  f(*p);
134  });
135 }
136 
137 /*---------------------------------------------------------------------*/
138 /* Streaming operations */
139 
140 template <class Container, class Consumer, class size_type>
141 void stream_backn(const Container& c, const Consumer& cons, size_type nb) {
142  using const_pointer = typename Container::const_pointer;
143  assert(c.size() >= nb);
144  size_type nb_before_target = c.size() - nb;
145  c.for_each_segment(c.begin() + nb_before_target, c.end(), [&] (const_pointer lo, const_pointer hi) {
146  size_type nb_items_to_copy = size_type(hi - lo);
147  cons(lo, nb_items_to_copy);
148  });
149 }
150 
151 template <class Container, class Consumer, class size_type>
152 void stream_frontn(const Container& c, const Consumer& cons, size_type nb) {
153  using const_pointer = typename Container::const_pointer;
154  assert(c.size() >= nb);
155  c.for_each_segment(c.begin(), c.begin() + nb, [&] (const_pointer lo, const_pointer hi) {
156  size_type nb = size_type(hi - lo);
157  cons(lo, nb);
158  });
159 }
160 
161 template <class Container, class value_type, class size_type>
162 void backn(const Container& c, value_type* dst, size_type nb) {
163  using const_pointer = const value_type*;
164  using allocator_type = typename Container::allocator_type;
165  value_type* p = dst;
166  auto cons = [&] (const_pointer lo, size_type nb) {
167  fixedcapacity::base::copy<allocator_type>(p, lo, nb);
168  p += nb;
169  };
170  c.stream_backn(cons, nb);
171 }
172 
173 template <class Container, class value_type, class size_type>
174 void frontn(const Container& c, value_type* dst, size_type nb) {
175  using const_pointer = const value_type*;
176  using allocator_type = typename Container::allocator_type;
177  value_type* p = dst;
178  auto cons = [&] (const_pointer lo, size_type nb) {
179  fixedcapacity::base::copy<allocator_type>(p, lo, nb);
180  p += nb;
181  };
182  c.stream_frontn(cons, nb);
183 }
184 
185 template <class Container, class const_pointer, class size_type>
186 void pushn_back(Container& c, const_pointer src, size_type nb) {
187  auto prod = [src] (size_type i, size_type nb) {
188  const_pointer lo = src + i;
189  const_pointer hi = lo + nb;
190  return std::make_pair(lo, hi);
191  };
192  c.stream_pushn_back(prod, nb);
193 }
194 
195 template <class Container, class const_pointer, class size_type>
196 void pushn_front(Container& c, const_pointer src, size_type nb) {
197  auto prod = [src] (size_type i, size_type nb) {
198  const_pointer lo = src + i;
199  const_pointer hi = lo + nb;
200  return std::make_pair(lo, hi);
201  };
202  c.stream_pushn_front(prod, nb);
203 }
204 
205 template <class Container, class value_type, class size_type>
206 void popn_back(Container& c, value_type* dst, size_type nb) {
207  using const_pointer = const value_type*;
208  using allocator_type = typename Container::allocator_type;
209  value_type* p = dst + nb;
210  auto cons = [&] (const_pointer lo, const_pointer hi) {
211  size_type d = hi - lo;
212  p -= d;
213  fixedcapacity::base::copy<allocator_type>(p, lo, d);
214  };
215  c.template stream_popn_back<typeof(cons), true>(cons, nb);
216 }
217 
218 template <class Container, class value_type, class size_type>
219 void popn_front(Container& c, value_type* dst, size_type nb) {
220  using const_pointer = const value_type*;
221  using allocator_type = typename Container::allocator_type;
222  value_type* p = dst;
223  auto cons = [&] (const_pointer lo, const_pointer hi) {
224  size_type d = hi - lo;
225  fixedcapacity::base::copy<allocator_type>(p, lo, d);
226  p += d;
227  };
228  c.template stream_popn_front<typeof(cons), true>(cons, nb);
229 }
230 
231 /*---------------------------------------------------------------------*/
232 /* Debugging output */
233 
234 template <class Container>
235 std::ostream& generic_print_container(std::ostream& out, const Container& seq) {
236  using value_type = typename Container::value_type;
237  using size_type = typename Container::size_type;
238  size_type sz = seq.size();
239  out << "[";
240  seq.for_each([&] (value_type x) {
241  sz--;
242  if (sz == 0)
243  out << x;
244  else
245  out << x << ", ";
246  });
247  out << "]";
248  return out;
249 }
250 
251 /*---------------------------------------------------------------------*/
252 
253 
254  /* todo:
255  *
256  * - assign
257  * - at
258  * - relational operators http://www.cplusplus.com/reference/vector/vector/operators/
259  *
260  */
261 
262 /***********************************************************************/
263 
264 } // end namespace
265 } // end namespace
266 } // end namespace
267 } // end namespace
268 
269 #endif
std::ostream & generic_print_container(std::ostream &out, const Container &seq)
void popn_back(Container &c, value_type *dst, size_type nb)
iterator insert(Container &c, iterator position, const value_type &val)
void pushn_front(Container &c, const_pointer src, size_type nb)
void for_each_segment(iterator begin, iterator end, const Body &f)
void stream_backn(const Container &c, const Consumer &cons, size_type nb)
void split_by_index(Container &c, size_type i, Container &other)
void backn(const Container &c, value_type *dst, size_type nb)
void popn_front(Container &c, value_type *dst, size_type nb)
Definition: algebra.hpp:18
void stream_frontn(const Container &c, const Consumer &cons, size_type nb)
void split_by_iterator(Container &c, iterator position, Container &other)
void for_each(iterator beg, iterator end, const Body &f)
void split_approximate(Container &c, Container &other)
void pushn_back(Container &c, const_pointer src, size_type nb)
iterator erase(Container &c, iterator first, iterator last)
void frontn(const Container &c, value_type *dst, size_type nb)