1 // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
2
3 ///
4 /// namespace cpplinq
5 /// -----------------
6 ///
7 /// Defines a number of range-based composable operators for enumerating and modifying collections
8 ///
9 /// The general design philosophy is to
10 /// (1) emulate the composable query patterns introduced in C# Linq
11 /// (2) preserve iterator category and writability where possible
12 /// For instance, like C# Linq we have a select operator to project one sequence into a new one.
13 /// Unlike Linq, invoking Select on a random access sequence will yield you a _random_ access sequence.
14 ///
15 /// The general workflow begins with 'from()' which normally only takes a reference
16 /// the the collection in question. However, from that point on, all operators function
17 /// by value, so that the range can store any necessary state, rather than duplicating it
18 /// onto iterator pairs.
19 ///
20 /// In subsequent documentation, "powers" lists which powers that the operator attempts to preserve if
21 /// available on on the input sequence. Some iterator powers may be skipped - in such a case, round down
22 /// to the next supported power (e.g. if 'fwd' and 'rnd', an input of 'bidi' will round down to a 'fwd' result).
23 ///
24 ///
25 ///
26 /// class linq_query
27 /// ----------------
28 ///
29 /// from(container&)
30 /// ================
31 /// - Result: Query
32 ///
33 /// Construct a new query, from an lvalue reference to a collection. Does not copy the collection
34 ///
35 ///
36 ///
37 /// from(iter, iter)
38 /// ================
39 /// - Result: Query
40 ///
41 /// Construct a new query, from an iterator pair.
42 ///
43 ///
44 ///
45 /// query.select(map)
46 /// ==========================
47 /// - Result: Query
48 /// - Powers: input, forward, bidirectional, random access
49 ///
50 /// For each element `x` in the input sequences, computes `map(x)` for the result sequence.
51 ///
52 ///
53 ///
54 /// query.where(pred) -> query
55 /// ==========================
56 /// - Result: Query
57 /// - Powers: input, forward, bidirectional
58 ///
59 /// Each element `x` in the input appears in the output if `pred(x)` is true.
60 ///
61 /// The expression `pred(x)` is evaluated only when moving iterators (op++, op--).
62 /// Dereferencing (op*) does not invoke the predicate.
63 ///
64 ///
65 ///
66 /// query.groupby(keymap [, keyequal])
67 /// ====================================
68 /// Result: Query of groups. Each group has a 'key' field, and is a query of elements from the input.
69 /// Powers: forward
70 ///
71 ///
72 ///
73 /// query.any([pred])
74 /// =================
75 /// - Result: bool
76 ///
77 /// (No argument) Returns true if sequence is non-empty. Equivalent to `query.begin()!=query.end()`
78 ///
79 /// (One argument) Returns true if the sequence contains any elements for which `pred(element)` is true.
80 /// Equivalent to `query.where(pred).any()`.
81 ///
82 ///
83 ///
84 /// query.all(pred)
85 /// ===============
86 /// - Result: bool
87 ///
88 /// Returns true if `pred` holds for all elements in the sequence. Equivalent to `!query.any(std::not1(pred))`
89 ///
90 ///
91 ///
92 /// query.take(n)
93 /// =============
94 /// - Result: query
95 /// - Powers: input, forward, random access (not bidirectional)
96 ///
97 /// Returns a sequence that contains up to `n` items from the original sequence.
98 ///
99 ///
100 ///
101 /// query.skip(n)
102 /// =============
103 /// - Result: query
104 /// - Powers: input, forward, random access (not bidirectional)
105 ///
106 /// Returns a sequence that skips the first `n` items from the original sequence, or an empty sequence if
107 /// fewer than `n` were available on input.
108 ///
109 /// Note: begin() takes O(n) time when input iteration power is weaker than random access.
110 ///
111 ///
112 ///
113 /// query.count([pred])
114 /// ===================
115 /// - Result: std::size_t
116 ///
117 /// _TODO: should use inner container's iterator distance type instead._
118 ///
119 /// (Zero-argument) Returns the number of elements in the range.
120 /// Equivalent to `std::distance(query.begin(), query.end())`
121 ///
122 /// (One-argument) Returns the number of elements for whicht `pred(element)` is true.
123 /// Equivalent to `query.where(pred).count()`
124 ///
125
126
127
128 #if !defined(CPPLINQ_LINQ_HPP)
129 #define CPPLINQ_LINQ_HPP
130 #pragma once
131
132 #pragma push_macro("min")
133 #pragma push_macro("max")
134 #undef min
135 #undef max
136
137 #include <functional>
138 #include <iterator>
139 #include <algorithm>
140 #include <numeric>
141 #include <list>
142 #include <map>
143 #include <set>
144 #include <memory>
145 #include <utility>
146 #include <type_traits>
147 #include <vector>
148 #include <cstddef>
149
150
151
152 // some configuration macros
153 #if _MSC_VER > 1600 || __cplusplus > 199711L
154 #define LINQ_USE_RVALUEREF 1
155 #endif
156
157 #if (defined(_MSC_VER) && _CPPRTTI) || !defined(_MSC_VER)
158 #define LINQ_USE_RTTI 1
159 #endif
160
161 #if defined(__clang__)
162 #if __has_feature(cxx_rvalue_references)
163 #define LINQ_USE_RVALUEREF 1
164 #endif
165 #if __has_feature(cxx_rtti)
166 #define LINQ_USE_RTTI 1
167 #endif
168 #endif
169
170
171 // individual features
172 #include "util.hpp"
173 #include "linq_cursor.hpp"
174 #include "linq_iterators.hpp"
175 #include "linq_select.hpp"
176 #include "linq_take.hpp"
177 #include "linq_skip.hpp"
178 #include "linq_groupby.hpp"
179 #include "linq_where.hpp"
180 #include "linq_last.hpp"
181 #include "linq_selectmany.hpp"
182
183
184
185
186 namespace cpplinq
187 {
188
189 namespace detail
190 {
191 template<class Pred>
192 struct not1_{
193 Pred pred;
not1_cpplinq::detail::not1_194 not1_(Pred p) : pred(p)
195 {}
196 template<class T>
operator ()cpplinq::detail::not1_197 bool operator()(const T& value)
198 {
199 return !pred(value);
200 }
201 };
202 // note: VC2010's std::not1 doesn't support lambda expressions. provide our own.
203 template<class Pred>
not1(Pred p)204 not1_<Pred> not1(Pred p) { return not1_<Pred>(p); }
205 }
206
207 namespace detail {
208 template <class U>
209 struct cast_to {
210 template <class T>
operator ()cpplinq::detail::cast_to211 U operator()(const T& value) const {
212 return static_cast<U>(value);
213 }
214 };
215 }
216
217 template <class Collection>
218 class linq_driver
219 {
220 typedef typename Collection::cursor::element_type
221 element_type;
222 typedef typename Collection::cursor::reference_type
223 reference_type;
224 public:
225 typedef cursor_iterator<typename Collection::cursor>
226 iterator;
227
linq_driver(Collection c)228 linq_driver(Collection c) : c(c) {}
229
230
231 // -------------------- linq core methods --------------------
232
233 template <class KeyFn>
groupby(KeyFn fn)234 linq_driver< linq_groupby<Collection, KeyFn> > groupby(KeyFn fn)
235 {
236 return linq_groupby<Collection, KeyFn>(c, std::move(fn) );
237 }
238
239 // TODO: groupby(keyfn, eq)
240
241 // TODO: join...
242
243 template <class Selector>
select(Selector sel) const244 linq_driver< linq_select<Collection, Selector> > select(Selector sel) const {
245 return linq_select<Collection, Selector>(c, std::move(sel) );
246 }
247
248 template <class Fn>
249 linq_driver< linq_select_many<Collection, Fn, detail::default_select_many_selector> >
select_many(Fn fn) const250 select_many(Fn fn) const
251 {
252 return linq_select_many<Collection, Fn, detail::default_select_many_selector>(c, fn, detail::default_select_many_selector());
253 }
254
255 template <class Fn, class Fn2>
select_many(Fn fn,Fn2 fn2) const256 linq_driver< linq_select_many<Collection, Fn, Fn2> > select_many(Fn fn, Fn2 fn2) const
257 {
258 return linq_select_many<Collection, Fn, Fn2>(c, fn, fn2);
259 }
260
261 template <class Predicate>
where(Predicate p) const262 linq_driver< linq_where<Collection, Predicate> > where(Predicate p) const {
263 return linq_where<Collection, Predicate>(c, std::move(p) );
264 }
265
266
267 // -------------------- linq peripheral methods --------------------
268
269 template <class Fn>
aggregate(Fn fn) const270 element_type aggregate(Fn fn) const
271 {
272 auto it = begin();
273 if (it == end()) {
274 return element_type();
275 }
276
277 reference_type first = *it;
278 return std::accumulate(++it, end(), first, fn);
279 }
280
281 template <class T, class Fn>
aggregate(T initialValue,Fn fn) const282 T aggregate(T initialValue, Fn fn) const
283 {
284 return std::accumulate(begin(), end(), initialValue, fn);
285 }
286
any() const287 bool any() const { auto cur = c.get_cursor(); return !cur.empty(); }
288
289 template <class Predicate>
any(Predicate p) const290 bool any(Predicate p) const {
291 auto it = std::find_if(begin(), end(), p);
292 return it != end();
293 }
294
295 template <class Predicate>
all(Predicate p) const296 bool all(Predicate p) const {
297 auto it = std::find_if(begin(), end(), detail::not1(p));
298 return it == end();
299 }
300
301 // TODO: average
302
303 #if !defined(__clang__)
304 // Clang complains that linq_driver is not complete until the closing brace
305 // so (linq_driver*)->select() cannot be resolved.
306 template <class U>
cast()307 auto cast()
308 -> decltype(static_cast<linq_driver*>(0)->select(detail::cast_to<U>()))
309 {
310 return this->select(detail::cast_to<U>());
311 }
312 #endif
313
314 // TODO: concat
315
contains(const typename Collection::cursor::element_type & value) const316 bool contains(const typename Collection::cursor::element_type& value) const {
317 return std::find(begin(), end(), value) != end();
318 }
319
count() const320 typename std::iterator_traits<iterator>::difference_type count() const {
321 return std::distance(begin(), end());
322 }
323
324 template <class Predicate>
count(Predicate p) const325 typename std::iterator_traits<iterator>::difference_type count(Predicate p) const {
326 auto filtered = this->where(p);
327 return std::distance(begin(filtered), end(filtered));
328 }
329
330 // TODO: default_if_empty
331
332 // TODO: distinct()
333 // TODO: distinct(cmp)
334
element_at(std::size_t ix) const335 reference_type element_at(std::size_t ix) const {
336 auto cur = c.get_cursor();
337 while(ix && !cur.empty()) {
338 cur.inc();
339 --ix;
340 }
341 if (cur.empty()) { throw std::logic_error("index out of bounds"); }
342 else { return cur.get(); }
343 }
344
element_at_or_default(std::size_t ix) const345 element_type element_at_or_default(std::size_t ix) const {
346 auto cur = c.get_cursor();
347 while(ix && !cur.empty()) {
348 cur.inc();
349 -- ix;
350 }
351 if (cur.empty()) { return element_type(); }
352 else { return cur.get(); }
353 }
354
empty() const355 bool empty() const {
356 return !this->any();
357 }
358
359 // TODO: except(second)
360 // TODO: except(second, eq)
361
first() const362 reference_type first() const {
363 auto cur = c.get_cursor();
364 if (cur.empty()) { throw std::logic_error("index out of bounds"); }
365 else { return cur.get(); }
366 }
367
368 template <class Predicate>
first(Predicate pred) const369 reference_type first(Predicate pred) const {
370 auto cur = c.get_cursor();
371 while (!cur.empty() && !pred(cur.get())) {
372 cur.inc();
373 }
374 if (cur.empty()) { throw std::logic_error("index out of bounds"); }
375 else { return cur.get(); }
376 }
377
first_or_default() const378 element_type first_or_default() const {
379 auto cur = c.get_cursor();
380 if (cur.empty()) { return element_type(); }
381 else { return cur.get(); }
382 }
383
384 template <class Predicate>
first_or_default(Predicate pred) const385 element_type first_or_default(Predicate pred) const {
386 auto cur = c.get_cursor();
387 while (!cur.empty() && !pred(cur.get())) {
388 cur.inc();
389 }
390 if (cur.empty()) { return element_type(); }
391 else { return cur.get(); }
392 }
393
394 // TODO: intersect(second)
395 // TODO: intersect(second, eq)
396
397 // note: forward cursors and beyond can provide a clone, so we can refer to the element directly
398 typename std::conditional<
399 std::is_convertible<
400 typename Collection::cursor::cursor_category,
401 forward_cursor_tag>::value,
402 reference_type,
403 element_type>::type
last() const404 last() const
405 {
406 return linq_last_(c.get_cursor(), typename Collection::cursor::cursor_category());
407 }
408
409 template <class Predicate>
last(Predicate pred) const410 reference_type last(Predicate pred) const
411 {
412 auto cur = c.where(pred).get_cursor();
413 return linq_last_(cur, typename decltype(cur)::cursor_category());
414 }
415
last_or_default() const416 element_type last_or_default() const
417 {
418 return linq_last_or_default_(c.get_cursor(), typename Collection::cursor::cursor_category());
419 }
420
421 template <class Predicate>
last_or_default(Predicate pred) const422 element_type last_or_default(Predicate pred) const
423 {
424 auto cur = c.where(pred).get_cursor();
425 return linq_last_or_default_(cur, typename decltype(cur)::cursor_category());
426 }
427
max() const428 reference_type max() const
429 {
430 return max(std::less<element_type>());
431 }
432
433 template <class Compare>
max(Compare less) const434 reference_type max(Compare less) const
435 {
436 auto it = std::max_element(begin(), end(), less);
437 if (it == end())
438 throw std::logic_error("max performed on empty range");
439
440 return *it;
441 }
442
min() const443 reference_type min() const
444 {
445 return min(std::less<element_type>());
446 }
447
448 template <class Compare>
min(Compare less) const449 reference_type min(Compare less) const
450 {
451 auto it = std::min_element(begin(), end(), less);
452 if (it == end())
453 throw std::logic_error("max performed on empty range");
454
455 return *it;
456 }
457
458 // TODO: order_by(sel)
459 // TODO: order_by(sel, less)
460 // TODO: order_by_descending(sel)
461 // TODO: order_by_descending(sel, less)
462
463 // TODO: sequence_equal(second)
464 // TODO: sequence_equal(second, eq)
465
466 // TODO: single / single_or_default
467
skip(std::size_t n) const468 linq_driver<linq_skip<Collection>> skip(std::size_t n) const {
469 return linq_skip<Collection>(c, n);
470 }
471
472 // TODO: skip_while(pred)
473
474 template<typename ITEM = element_type>
sum() const475 typename std::enable_if<std::is_default_constructible<ITEM>::value, ITEM>::type sum() const {
476 ITEM seed{};
477 return sum(seed);
478 }
479
sum(element_type seed) const480 element_type sum(element_type seed) const {
481 return std::accumulate(begin(), end(), seed);
482 }
483
484 template <typename Selector, typename Result = typename std::result_of<Selector(element_type)>::type>
sum(Selector sel) const485 typename std::enable_if<std::is_default_constructible<Result>::value, Result>::type sum(Selector sel) const {
486 return from(begin(), end()).select(sel).sum();
487 }
488
489 template <typename Selector, typename Result = typename std::result_of<Selector(element_type)>::type>
sum(Selector sel,Result seed) const490 Result sum(Selector sel, Result seed) const {
491 return from(begin(), end()).select(sel).sum(seed);
492 }
493
take(std::size_t n) const494 linq_driver<linq_take<Collection>> take(std::size_t n) const {
495 return linq_take<Collection>(c, n);
496 }
497
498 // TODO: take_while
499
500 // TODO: then_by / then_by_descending ?
501
502 // TODO: to_...
503
504 // TODO: union(second)
505 // TODO: union(eq)
506
507 // TODO: zip
508
509 // -------------------- conversion methods --------------------
510
to_vector() const511 std::vector<typename Collection::cursor::element_type> to_vector() const
512 {
513 return std::vector<typename Collection::cursor::element_type>(begin(), end());
514 }
515
to_list() const516 std::list<typename Collection::cursor::element_type> to_list() const
517 {
518 return std::list<typename Collection::cursor::element_type>(begin(), end());
519 }
520
to_set() const521 std::set<typename Collection::cursor::element_type> to_set() const
522 {
523 return std::set<typename Collection::cursor::element_type>(begin(), end());
524 }
525
526 // -------------------- container/range methods --------------------
527
begin() const528 iterator begin() const { auto cur = c.get_cursor(); return !cur.empty() ? iterator(cur) : iterator(); }
end() const529 iterator end() const { return iterator(); }
operator =(const linq_driver & other)530 linq_driver& operator=(const linq_driver& other) { c = other.c; return *this; }
531 template <class TC2>
operator =(const linq_driver<TC2> & other)532 linq_driver& operator=(const linq_driver<TC2>& other) { c = other.c; return *this; }
533
534 typename std::iterator_traits<iterator>::reference
operator [](std::size_t ix) const535 operator[](std::size_t ix) const {
536 return *(begin()+=ix);
537 }
538
539 // -------------------- collection methods (leaky abstraction) --------------------
540
541 typedef typename Collection::cursor cursor;
get_cursor()542 cursor get_cursor() { return c.get_cursor(); }
543
544 linq_driver< dynamic_collection<typename Collection::cursor::reference_type> >
late_bind() const545 late_bind() const
546 {
547 return dynamic_collection<typename Collection::cursor::reference_type>(c);
548 }
549
550 private:
551 Collection c;
552 };
553
554 // TODO: should probably use reference-wrapper instead?
555 template <class TContainer>
from(TContainer & c)556 linq_driver<iter_cursor<typename util::container_traits<TContainer>::iterator>> from(TContainer& c)
557 {
558 auto cur = iter_cursor<typename util::container_traits<TContainer>::iterator>(std::begin(c), std::end(c));
559 return cur;
560 }
561 template <class T>
from(const linq_driver<T> & c)562 const linq_driver<T>& from(const linq_driver<T>& c)
563 {
564 return c;
565 }
566 template <class Iter>
from(Iter start,Iter finish)567 linq_driver<iter_cursor<Iter>> from(Iter start, Iter finish)
568 {
569 return iter_cursor<Iter>(start, finish);
570 }
571
572 template <class TContainer>
from_value(const TContainer & c)573 linq_driver<TContainer> from_value(const TContainer& c)
574 {
575 return linq_driver<TContainer>(c);
576 }
577
578 }
579
580 #pragma pop_macro("min")
581 #pragma pop_macro("max")
582
583 #endif // defined(CPPLINQ_LINQ_HPP)
584
585