Proton  1.1.1
Make porting easy from Python to C++11
deque.hpp
Go to the documentation of this file.
1 #ifndef PROTON_DEQUE_HEADER
2 #define PROTON_DEQUE_HEADER
3 
4 
5 /** @file deque.hpp
6  * @brief deque support.
7  * Please include this header instead of <deque>.
8  */
9 
10 #include <deque>
11 #include <algorithm>
12 #include <iostream>
13 #include <initializer_list>
14 #include <algorithm>
15 #include <stdexcept>
16 
17 #include <proton/base.hpp>
18 #include <proton/pool.hpp>
19 #include <proton/ref.hpp>
20 
21 namespace proton{
22 
23 /** @addtogroup deque_
24  * @{
25  */
26 
27 /** add an item in streaming style.
28  * @param x the deque to be added
29  * @param val the new item
30  * @return the new x
31  */
32 template <typename T, typename A, typename V>
33 std::deque<T,A>& operator<<(std::deque<T,A>& x, V&& val)
34 {
35  x.push_back(val);
36  return x;
37 }
38 
39 /** pop an item in streaming style.
40  * @param x the deque to be popped from
41  * @param val the popped item
42  * @return the new x
43  */
44 template <typename T, typename A, typename V>
45 std::deque<T,A>& operator>>(std::deque<T,A>& x, V& val)
46 {
47  PROTON_THROW_IF(x.empty(), "want to pop an empty deque.");
48  val=x.back();
49  x.pop_back();
50  return x;
51 }
52 
53 /** general output for deque.
54  * @param s the output stream
55  * @param x the deque to be outputed
56  * @return s
57  */
58 template <typename T, typename A>
59 std::ostream& operator<<(std::ostream& s, const std::deque<T,A>& x)
60 {
61  s << "[";
62  bool first=true;
63  for(auto& t: x){
64  if(first)
65  first=false;
66  else
67  s <<", ";
68  s << t;
69  }
70  s << "]";
71  return s;
72 }
73 
74 template <typename T, typename A>
75 std::wostream& operator<<(std::wostream& s, const std::deque<T,A>& x)
76 {
77  s << L"[";
78  bool first=true;
79  for(auto& t: x){
80  if(first)
81  first=false;
82  else
83  s <<L", ";
84  s << t;
85  }
86  s << L"]";
87  return s;
88 }
89 
90 /* sort a deque
91  * @param x the deque to be sorted
92  */
93 template <typename T, typename A>
94 void sort(std::deque<T,A>& x)
95 {
96  std::sort(x.begin(), x.end());
97 }
98 
99 /* get an item like python.
100  * @param x the sequence
101  * @param i the index
102  * @return x[i]
103  */
104 template <typename T, typename A>
105 T& get(std::deque<T,A>& x, long i)
106 {
107  unsigned long s=x.size();
108  if(i<0)
109  i=s+i;
110  if(i<0 || (unsigned long)i >= s )
111  PROTON_ERR("out of range: look up "<<i<<" in deque whose size is " << s);
112  return x[i];
113 }
114 
115 /* get a const item like python.
116  * @param x the sequence
117  * @param i the index
118  * @return x[i]
119  */
120 template <typename T, typename A>
121 const T& get(const std::deque<T,A>& x, long i)
122 {
123  unsigned long s=x.size();
124  if(i<0)
125  i=s+i;
126  if(i<0 || (unsigned long)i >= s )
127  PROTON_ERR("out of range: look up "<<i<<" in deque whose size is " << s);
128  return x[i];
129 }
130 
131 /* get a slice like python.
132  * @param x the sequence
133  * @param first the start
134  * @return x[first:]
135  */
136 template <typename T, typename A>
137 std::deque<T,A> sub(const std::deque<T,A>& x, long first)
138 {
139  std::deque<T,A> r;
140  unsigned long s=x.size();
141  if(first<0)
142  first=first+s;
143  if(first<0)
144  first=0;
145  if((unsigned long)first >= s )
146  return r;
147 
148  auto start=x.begin();
149  std::copy(start+first, x.end(), std::back_inserter(r));
150  return r;
151 }
152 
153 /* get a slice like python.
154  * @param x the sequence
155  * @param first the start
156  * @param last the end
157  * @return x[first:last]
158  */
159 template <typename T, typename A>
160 std::deque<T,A> sub(const std::deque<T,A>& x, long first, long last)
161 {
162  std::deque<T,A> r;
163  unsigned long s=x.size();
164  if(first<0)
165  first=first+s;
166  if(first<0)
167  first=0;
168  if((unsigned long)first >= s )
169  return r;
170 
171  if(last<0)
172  last=last+s;
173  if(last<=0)
174  return r;
175 
176  if((unsigned long)last>s)
177  last=s;
178  auto start=x.begin();
179  std::copy(start+first, start+last, std::back_inserter(r));
180  return r;
181 }
182 
183 /** a deque extension implementing python's list-like interfaces.
184  */
185 template <typename T, typename A=smart_allocator<T> >
186 class deque_ : public std::deque<T,A>{
187  public:
188  typedef std::deque<T,A> baseT;
189  typedef typename baseT::difference_type offset_t;
190 
191 protected:
192  offset_t __offset(offset_t i)const
193  {
194  if(i<0)
195  i+=this->size();
196  return i;
197  }
198 
199  offset_t offset(offset_t i)const
200  {
201  i=__offset(i);
202  PROTON_THROW_IF(i<0 || (size_t)i>=this->size(), "out of range, offset is " << i
203  << " while size is " << this->size() );
204  return i;
205  }
206 
207  int fix_offset(offset_t begin)const
208  {
209  offset_t size=(offset_t)this->size();
210  begin=__offset(begin);
211  if(begin>=size){
212  return size;
213  }
214  if(begin<0)
215  return 0;
216  return begin;
217  }
218 
219  void fix_range(offset_t& begin, offset_t& end)const
220  {
221  offset_t size=(offset_t)this->size();
222  begin=__offset(begin);
223  end=__offset(end);
224  if(begin>=size || end<=0 || end<=begin){
225  begin=0;
226  end=0;
227  return;
228  }
229  if(begin<0)
230  begin=0;
231  if(end>=size)
232  end=size;
233  }
234 
235 public:
236  /** forwarding ctor.
237  */
238  template<typename ...argT> deque_(argT&& ...a):baseT(a...)
239  {}
240 
241  /** initializer_list forwarding ctor.
242  */
243  deque_(std::initializer_list<T> a):baseT(a)
244  {}
245 
246  /** copy ctor.
247  */
248  deque_(const deque_& x):baseT(x)
249  {}
250 
251  /** move ctor.
252  */
253  deque_(deque_&& x)noexcept:baseT(x)
254  {}
255 
256  explicit deque_(const baseT& x):baseT(x)
257  {}
258 
259  deque_(baseT&& x)noexcept:baseT(x)
260  {}
261 
262  /** assign.
263  */
265  {
266  baseT::operator=(x);
267  return *this;
268  }
269 
270  deque_& operator=(deque_&& x)noexcept
271  {
272  baseT::operator=(x);
273  return *this;
274  }
275 
276  deque_& operator=(const baseT& x)
277  {
278  baseT::operator=(x);
279  return *this;
280  }
281 
282  deque_& operator=(baseT&& x)noexcept
283  {
284  baseT::operator=(x);
285  return *this;
286  }
287 
288  template<typename argT> deque_& operator=(argT&& a)
289  {
290  baseT::operator=(a);
291  return *this;
292  }
293 
294  deque_& operator=(std::initializer_list<T> a)
295  {
296  baseT::operator=(a);
297  return *this;
298  }
299 
300  /** cast to std::deque<>&.
301  */
302  operator baseT&()
303  {
304  return reinterpret_cast<baseT&>(*this);
305  }
306 
307  /** [i] in python
308  */
309  T& operator[](offset_t i)
310  {
311  return *(this->begin()+offset(i));
312  }
313 
314  /** [i] in python
315  */
316  const T& operator[](offset_t i)const
317  {
318  return *(this->begin()+offset(i));
319  }
320 
321  /** slice of [i:]
322  */
323  deque_ operator()(offset_t i)const
324  {
325  auto begin=this->begin();
326  return deque_(begin+offset(i),this->end());
327  }
328 
329  /** slice of [i:j]
330  */
331  deque_ operator()(offset_t i, offset_t j)const
332  {
333  auto begin=this->begin();
334  fix_range(i,j);
335  return deque_(begin+i,begin+j);
336  }
337 
338  /** slice of [i:j:k]
339  */
340  deque_ operator()(offset_t i, offset_t j, size_t k)const
341  {
342  fix_range(i,j);
343  deque_ r;
344  auto it=this->begin()+i;
345  for(offset_t n=i; n<j; n+=k,it+=k)
346  r.push_back(*it);
347  return r;
348  }
349 
350  /** append an item at the end.
351  */
352  void append(const T& x)
353  {
354  this->push_back(x);
355  }
356 
357  void append(T&& x)
358  {
359  this->push_back(x);
360  }
361 
362  /** total number of occurences of x.
363  */
364  size_t count(const T& x)const
365  {
366  return std::count(this->begin(), this->end(), x);
367  }
368 
369  /** delete the i-th item
370  */
371  void del(offset_t i)
372  {
373  this->erase(this->begin()+offset(i));
374  }
375 
376  /** delete from i-th to the j-th items
377  */
378  void del(offset_t i, offset_t j)
379  {
380  fix_range(i,j);
381  auto begin=this->begin();
382  this->erase(begin+i, begin+j);
383  }
384 
385  /** delete from i-th item to the end
386  */
387  void del_to_end(offset_t i)
388  {
389  this->erase(this->begin()+offset(i), this->end());
390  }
391 
392  /** append items from a sequence.
393  */
394  template<typename seqT>void extend(const seqT& x)
395  {
396  for(auto& i:x){
397  this->push_back(i);
398  }
399  }
400 
401  template<typename seqT>void extend(seqT&& x)
402  {
403  for(auto&& i:x){
404  this->push_back(i);
405  }
406  }
407 
408  /** index of the first occurence of a value.
409  * @param val the value.
410  * @throw std::invalid_argument if there is no such a value.
411  */
412  offset_t index(const T& val)const
413  {
414  auto begin=this->begin(), end=this->end();
415  auto it=std::find(begin, end, val);
416  if(it==end)
417  throw std::invalid_argument("The given value doesn't exist in this sequence.");
418  return it-begin;
419  }
420 
421  /** insert value at offset i.
422  * @param i the offset, like python, -1 means the last position.
423  * @param val the value.
424  * @throw proton::err if i is bad.
425  */
426  void insert(offset_t i, const T& val)
427  {
428  auto it=this->begin()+ offset(i);
429  baseT::insert(it, val);
430  }
431 
432  void insert(offset_t i, T&& val)
433  {
434  auto it=this->begin()+offset(i);
435  baseT::insert(it, val);
436  }
437 
438  /** pop an item from the sequence.
439  * @param i the index of the itme, default is -1, the last item.
440  * @return the value at offset i.
441  * @throw proton::err if i is bad.
442  */
443  T pop(offset_t i=-1)
444  {
445  auto it=this->begin()+offset(i);
446  T r=*it;
447  this->erase(it);
448  return r;
449  }
450 
451  /** remove the first occurence of a value.
452  * @param val the value.
453  * @throw std::invalid_argument if there is no such a value.
454  */
455  void remove(const T& val)
456  {
457  auto begin=this->begin(), end=this->end();
458  auto it=std::find(begin, end, val);
459  if(it==end)
460  throw std::invalid_argument("The given value doesn't exist in this sequence.");
461  this->erase(it);
462  }
463 
464  /** reverses the items in place.
465  */
466  void reverse()
467  {
468  std::reverse(this->begin(), this->end());
469  }
470 
471  /** sort the items in place.
472  */
473  void sort()
474  {
475  std::sort(this->begin(), this->end());
476  }
477 
478  /** sort the items in place using a customized cmp.
479  */
480  template<class cmpT>void sort(cmpT cmp)
481  {
482  std::sort(this->begin(), this->end(),cmp);
483  }
484 
485 };
486 
487 /**
488  * @example deque.cpp
489  */
490 
491 /** deque + deque
492  */
493 template<typename T, typename A, typename X>
494 deque_<T,A> operator+(const std::deque<T,A>& s, X&& t)
495 {
496  deque_<T,A> r(s);
497  r.extend(std::forward<X>(t));
498  return r;
499 }
500 
501 template<typename T, typename A, typename X>
502 deque_<T,A> operator+(std::deque<T,A>&& s, X&& t)
503 {
504  deque_<T,A> r(s);
505  r.extend(std::forward<X>(t));
506  return r;
507 }
508 
509 /** deque_ * n
510  */
511 template<typename T, typename A>
512 deque_<T,A> operator*(const std::deque<T,A>& s, size_t n)
513 {
514  deque_<T,A> r;
515  for(size_t i=0; i<n; i++)
516  r.extend(s);
517  return r;
518 }
519 
520 /** n * deque_
521  */
522 template<typename T, typename A>
523 deque_<T,A> operator*(size_t n, const std::deque<T,A>& s)
524 {
525  return s*n;
526 }
527 
528 /** cast to proton::deque_<>& from std::deque<>&.
529  */
530 template<typename T, typename A>
531 deque_<T,A>& cast_(std::deque<T,A>& x)
532 {
533  return reinterpret_cast<deque_<T,A>&>(x);
534 }
535 
536 template<typename T, typename A>
537 const deque_<T,A>& cast_(const std::deque<T,A>& x)
538 {
539  return reinterpret_cast<const deque_<T,A>&>(x);
540 }
541 
542 template<typename T, typename A>
543 deque_<T,A>&& cast_(std::deque<T,A>&& x)
544 {
545  return reinterpret_cast<deque_<T,A>&&>(x);
546 }
547 
548 template<typename T, typename A>
549 const deque_<T,A>&& cast_(const std::deque<T,A>&& x)
550 {
551  return reinterpret_cast<const deque_<T,A>&&>(x);
552 }
553 
554 /**
555  * @}
556  */
557 }
558 
559 #endif // PROTON_DEQUE_HEADER