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; 194 not1_(Pred p) : pred(p) 195 {} 196 template<class T> 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> 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> 211 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 228 linq_driver(Collection c) : c(c) {} 229 230 231 // -------------------- linq core methods -------------------- 232 233 template <class KeyFn> 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> 244 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> > 250 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> 256 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> 262 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> 270 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> 282 T aggregate(T initialValue, Fn fn) const 283 { 284 return std::accumulate(begin(), end(), initialValue, fn); 285 } 286 287 bool any() const { auto cur = c.get_cursor(); return !cur.empty(); } 288 289 template <class Predicate> 290 bool any(Predicate p) const { 291 auto it = std::find_if(begin(), end(), p); 292 return it != end(); 293 } 294 295 template <class Predicate> 296 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> 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 316 bool contains(const typename Collection::cursor::element_type& value) const { 317 return std::find(begin(), end(), value) != end(); 318 } 319 320 typename std::iterator_traits<iterator>::difference_type count() const { 321 return std::distance(begin(), end()); 322 } 323 324 template <class Predicate> 325 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 335 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 345 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 355 bool empty() const { 356 return !this->any(); 357 } 358 359 // TODO: except(second) 360 // TODO: except(second, eq) 361 362 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> 369 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 378 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> 385 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 404 last() const 405 { 406 return linq_last_(c.get_cursor(), typename Collection::cursor::cursor_category()); 407 } 408 409 template <class Predicate> 410 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 416 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> 422 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 428 reference_type max() const 429 { 430 return max(std::less<element_type>()); 431 } 432 433 template <class Compare> 434 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 443 reference_type min() const 444 { 445 return min(std::less<element_type>()); 446 } 447 448 template <class Compare> 449 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 468 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> 475 typename std::enable_if<std::is_default_constructible<ITEM>::value, ITEM>::type sum() const { 476 ITEM seed{}; 477 return sum(seed); 478 } 479 480 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> 485 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> 490 Result sum(Selector sel, Result seed) const { 491 return from(begin(), end()).select(sel).sum(seed); 492 } 493 494 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 511 std::vector<typename Collection::cursor::element_type> to_vector() const 512 { 513 return std::vector<typename Collection::cursor::element_type>(begin(), end()); 514 } 515 516 std::list<typename Collection::cursor::element_type> to_list() const 517 { 518 return std::list<typename Collection::cursor::element_type>(begin(), end()); 519 } 520 521 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 528 iterator begin() const { auto cur = c.get_cursor(); return !cur.empty() ? iterator(cur) : iterator(); } 529 iterator end() const { return iterator(); } 530 linq_driver& operator=(const linq_driver& other) { c = other.c; return *this; } 531 template <class TC2> 532 linq_driver& operator=(const linq_driver<TC2>& other) { c = other.c; return *this; } 533 534 typename std::iterator_traits<iterator>::reference 535 operator[](std::size_t ix) const { 536 return *(begin()+=ix); 537 } 538 539 // -------------------- collection methods (leaky abstraction) -------------------- 540 541 typedef typename Collection::cursor cursor; 542 cursor get_cursor() { return c.get_cursor(); } 543 544 linq_driver< dynamic_collection<typename Collection::cursor::reference_type> > 545 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> 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> 562 const linq_driver<T>& from(const linq_driver<T>& c) 563 { 564 return c; 565 } 566 template <class Iter> 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> 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