RxCpp
The Reactive Extensions for Native (RxCpp) is a library for composing asynchronous and event-based programs using observable sequences and LINQ-style query operators in both C and C++.
linq_cursor.hpp
Go to the documentation of this file.
1 // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
2 
3 #if !defined(CPPLINQ_LINQ_CURSOR_HPP)
4 #define CPPLINQ_LINQ_CURSOR_HPP
5 #pragma once
6 
7 #include <cstddef>
8 
55 
56 
57 
58 namespace cpplinq {
59 
60  // used to identify cursor-based collections
61  struct collection_tag {};
62 
63  struct onepass_cursor_tag {};
67 
68  struct noread_cursor_tag {}; // TODO: remove if not used
71 
72 
73 
74  // standard cursor adaptors
75 
76  namespace util
77  {
78  namespace detail
79  {
80  template <std::size_t n> struct type_to_size { char value[n]; };
81 
82  type_to_size<1> get_category_from_iterator(std::input_iterator_tag);
83  type_to_size<2> get_category_from_iterator(std::forward_iterator_tag);
84  type_to_size<3> get_category_from_iterator(std::bidirectional_iterator_tag);
85  type_to_size<4> get_category_from_iterator(std::random_access_iterator_tag);
86  }
87 
88  template <std::size_t>
90 
91  template <class Iter>
93  {
94  static const std::size_t catIx = sizeof(detail::get_category_from_iterator(typename std::iterator_traits<Iter>::iterator_category()) /*.value*/ );
96  };
97 
98  template <> struct iter_to_cursor_category_<1> { typedef onepass_cursor_tag type; };
99  template <> struct iter_to_cursor_category_<2> { typedef forward_cursor_tag type; };
100  template <> struct iter_to_cursor_category_<3> { typedef bidirectional_cursor_tag type; };
101  template <> struct iter_to_cursor_category_<4> { typedef random_access_cursor_tag type; };
102 
103 
104  // Note: returns false if no partial order exists between two
105  // particular iterator categories, such as with some of the boost categories
106  template <class Cat1, class Cat2>
108  {
109  private:
110  typedef char yes;
111  typedef struct { char c1,c2; } no;
112  static yes invoke(Cat1);
113  static no invoke(...);
114  public:
115  enum { value = (sizeof(invoke(Cat2())) == sizeof(yes)) };
116  };
117 
118  // Return the weaker of the two iterator categories. Make sure
119  // a non-standard category is in the second argument position, as
120  // this metafunction will default to the first value if the order is undefined
121  template <class Cat1, class Cat2, class Cat3 = void>
122  struct min_cursor_category : min_cursor_category<typename min_cursor_category<Cat1, Cat2>::type, Cat3>
123  {
124  };
125 
126  template <class Cat1, class Cat2>
127  struct min_cursor_category<Cat1, Cat2>
128  : std::conditional<
129  less_or_equal_cursor_category<Cat2, Cat1>::value,
130  Cat2,
131  Cat1>
132  {
133  };
134 
135  template <class Collection>
136  struct cursor_type {
137  typedef decltype(cursor(*static_cast<Collection*>(0))) type;
138  };
139  }
140 
141  // simultaniously models a cursor and a cursor-collection
142  template <class Iterator>
144  public:
145 
147 
148  typedef typename std::remove_reference<typename std::iterator_traits<Iterator>::value_type>::type
150  typedef typename std::iterator_traits<Iterator>::reference
154 
155  void forget() { start = current; }
156  bool empty() const { return current == fin; }
157  void inc() {
158  if (current == fin)
159  throw std::logic_error("inc past end");
160  ++current;
161  }
162  typename std::iterator_traits<Iterator>::reference get() const { return *current; }
163 
164  bool atbegin() const { return current == start; }
165  void dec() {
166  if (current == start)
167  throw std::logic_error("dec past begin");
168  --current;
169  }
170 
171  void skip(std::ptrdiff_t n) { current += n; }
172  std::size_t size() { return fin-start; }
173  void position() { return current-start; }
174  void truncate(std::size_t n) {
175  if (n > fin-current) {
176  fin = current + n;
177  }
178  }
179 
180 
181  iter_cursor(Iterator start, Iterator fin)
182  : current(start)
183  , start(start)
184  , fin(std::move(fin))
185  {
186  }
187 
188  iter_cursor(Iterator start, Iterator fin, Iterator current)
189  : current(std::move(current))
190  , start(std::move(start))
191  , fin(std::move(fin))
192  {
193  }
194 
195  iter_cursor get_cursor() const { return *this; }
196 
197  private:
198  Iterator current;
199  Iterator start, fin;
200  };
201 
202 
203  template <class T>
205  {
206  virtual bool empty() const = 0;
207  virtual void inc() = 0;
208  virtual cursor_interface* copy() const = 0;
209 
210  virtual T get() const = 0;
211 
212  virtual ~cursor_interface() {}
213  };
214 
215  template <class T>
217  {
218  template <class Cur>
219  struct instance : cursor_interface<T>
220  {
221  Cur innerCursor;
222 
223  instance(Cur cursor) : innerCursor(std::move(cursor))
224  {
225  }
226  virtual bool empty() const
227  {
228  return innerCursor.empty();
229  }
230  virtual void inc()
231  {
232  innerCursor.inc();
233  }
234  virtual T get() const
235  {
236  return innerCursor.get();
237  }
238  virtual cursor_interface<T>* copy() const
239  {
240  return new instance(*this);
241  }
242  };
243 
244  std::unique_ptr<cursor_interface<T>> myCur;
245 
246  public:
247  typedef forward_cursor_tag cursor_category; // TODO: not strictly true!
248  typedef typename std::remove_reference<T>::type element_type;
249  typedef T reference_type;
250 
252 
254  : myCur(other.myCur ? other.myCur->copy() : nullptr)
255  {
256  }
257 
259  : myCur(other.myCur.release())
260  {
261  }
262 
263  template <class Cursor>
264  dynamic_cursor(Cursor cursor)
265  : myCur(new instance<Cursor>(std::move(cursor)))
266  {
267  }
268 
269  template <class Iterator>
270  dynamic_cursor(Iterator start, Iterator end)
271  {
272  *this = iter_cursor<Iterator>(start, end);
273  }
274 
275  bool empty() const { return !myCur || myCur->empty(); }
276  void inc() { myCur->inc(); }
277  T get() const { return myCur->get(); }
278 
280  {
281  std::swap(myCur, other.myCur);
282  return *this;
283  }
284  };
285 
286  template <class T>
288  {
289  virtual dynamic_cursor<T> get_cursor() const = 0;
290  };
291 
292  template <class T>
294  {
295  std::shared_ptr< container_interface<T> > container;
296 
297  template <class Container>
298  struct instance : container_interface<T>
299  {
300  Container c;
301 
302  instance(Container c) : c(c)
303  {
304  }
305 
307  {
308  return c.get_cursor();
309  }
310  };
311 
312  public:
314 
316 
318  : container(other.container)
319  {
320  }
321 
322  // container or query
323  template <class Container>
324  dynamic_collection(Container c)
325  : container(new instance<Container>(c))
326  {
327  }
328 
329  // container or query
330  template <class Iterator>
331  dynamic_collection(Iterator begin, Iterator end)
332  : container(new instance< iter_cursor<Iterator> >(iter_cursor<Iterator>(begin, end)))
333  {
334  }
335 
337  return container ? container->get_cursor() : dynamic_cursor<T>();
338  }
339  };
340 }
341 
342 #endif // !defined(CPPLINQ_LINQ_CURSOR_HPP
dynamic_collection(Iterator begin, Iterator end)
Definition: linq_cursor.hpp:331
onepass_cursor_tag type
Definition: linq_cursor.hpp:98
void forget()
Definition: linq_cursor.hpp:155
dynamic_cursor(Cursor cursor)
Definition: linq_cursor.hpp:264
bidirectional_cursor_tag type
Definition: linq_cursor.hpp:100
bool empty() const
Definition: linq_cursor.hpp:156
Definition: linq_cursor.hpp:122
forward_cursor_tag type
Definition: linq_cursor.hpp:99
iter_to_cursor_category_< catIx >::type type
Definition: linq_cursor.hpp:95
void inc()
Definition: linq_cursor.hpp:276
dynamic_cursor(dynamic_cursor &&other)
Definition: linq_cursor.hpp:258
auto empty() -> decltype(from< T >())
Returns an observable that sends no items to observer and immediately completes, on the specified sch...
Definition: rx-empty.hpp:37
Definition: linq_cursor.hpp:68
Definition: linq_cursor.hpp:63
random_access_cursor_tag type
Definition: linq_cursor.hpp:101
Definition: linq_cursor.hpp:143
iter_cursor(Iterator start, Iterator fin, Iterator current)
Definition: linq_cursor.hpp:188
dynamic_cursor & operator=(dynamic_cursor other)
Definition: linq_cursor.hpp:279
Definition: linq_cursor.hpp:66
iter_cursor cursor
Definition: linq_cursor.hpp:146
void inc()
Definition: linq_cursor.hpp:157
std::iterator_traits< Iterator >::reference reference_type
Definition: linq_cursor.hpp:151
dynamic_cursor< T > cursor
Definition: linq_cursor.hpp:313
Definition: linq.hpp:186
Definition: linq_cursor.hpp:64
iter_cursor get_cursor() const
Definition: linq_cursor.hpp:195
dynamic_cursor()
Definition: linq_cursor.hpp:251
std::remove_reference< T >::type element_type
Definition: linq_cursor.hpp:248
void position()
Definition: linq_cursor.hpp:173
Definition: linq_cursor.hpp:204
virtual ~cursor_interface()
Definition: linq_cursor.hpp:212
Definition: linq_cursor.hpp:287
Definition: linq_cursor.hpp:92
Definition: linq_cursor.hpp:293
dynamic_collection(const dynamic_collection &other)
Definition: linq_cursor.hpp:317
Definition: linq_cursor.hpp:61
Definition: linq_cursor.hpp:216
dynamic_collection()
Definition: linq_cursor.hpp:315
bool empty() const
Definition: linq_cursor.hpp:275
T reference_type
Definition: linq_cursor.hpp:249
Definition: linq_cursor.hpp:136
Definition: linq_cursor.hpp:65
Definition: linq_cursor.hpp:107
std::remove_reference< typename std::iterator_traits< Iterator >::value_type >::type element_type
Definition: linq_cursor.hpp:149
void skip(std::ptrdiff_t n)
Definition: linq_cursor.hpp:171
dynamic_cursor(const dynamic_cursor &other)
Definition: linq_cursor.hpp:253
bool atbegin() const
Definition: linq_cursor.hpp:164
auto get_cursor(const linq_take< Collection > &take) -> decltype(get_cursor_(take, typename Collection::cursor::cursor_category()))
Definition: linq_take.hpp:87
util::iter_to_cursor_category< Iterator >::type cursor_category
Definition: linq_cursor.hpp:153
void truncate(std::size_t n)
Definition: linq_cursor.hpp:174
std::size_t size()
Definition: linq_cursor.hpp:172
dynamic_cursor< T > get_cursor() const
Definition: linq_cursor.hpp:336
Definition: linq_cursor.hpp:69
Definition: linq_cursor.hpp:89
forward_cursor_tag cursor_category
Definition: linq_cursor.hpp:247
iter_cursor(Iterator start, Iterator fin)
Definition: linq_cursor.hpp:181
dynamic_collection(Container c)
Definition: linq_cursor.hpp:324
Definition: linq_cursor.hpp:70
dynamic_cursor(Iterator start, Iterator end)
Definition: linq_cursor.hpp:270
void dec()
Definition: linq_cursor.hpp:165