• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_TAKE_HPP)
4 #define CPPLINQ_LINQ_TAKE_HPP
5 #pragma once
6 
7 #include <cstddef>
8 
9 namespace cpplinq
10 {
11     template <class InnerCursor>
12     struct linq_take_cursor
13     {
14         typedef typename InnerCursor::element_type element_type;
15         typedef typename InnerCursor::reference_type reference_type;
16         typedef typename InnerCursor::cursor_category cursor_category;
17 
linq_take_cursorcpplinq::linq_take_cursor18         linq_take_cursor(const InnerCursor& cur, std::size_t rem) : cur(cur), rem(rem) {}
19 
forgetcpplinq::linq_take_cursor20         void forget() { cur.forget(); }
emptycpplinq::linq_take_cursor21         bool empty() const { return cur.empty() || rem == 0; }
inccpplinq::linq_take_cursor22         void inc() { cur.inc(); --rem; }
getcpplinq::linq_take_cursor23         reference_type get() const { return cur.get(); }
24 
atbegincpplinq::linq_take_cursor25         bool atbegin() const { return cur.atbegin(); }
deccpplinq::linq_take_cursor26         void dec() { cur.dec(); --rem; }
27 
skipcpplinq::linq_take_cursor28         void skip(std::size_t n) { cur.skip(n); rem -= n; }
positioncpplinq::linq_take_cursor29         std::size_t position() const { return cur.position(); }
sizecpplinq::linq_take_cursor30         std::size_t size() const { return cur.size(); }
31 
32     private:
33         InnerCursor cur;
34         std::size_t rem;
35     };
36 
37     namespace detail {
38         template <class Collection>
39         linq_take_cursor<typename Collection::cursor>
take_get_cursor_(const Collection & c,std::size_t n,onepass_cursor_tag)40             take_get_cursor_(
41                 const Collection& c,
42                 std::size_t n,
43                 onepass_cursor_tag
44                 )
45         {
46             return linq_take_cursor<typename Collection::cursor>(c.get_cursor(), n);
47         }
48 
49         template <class Collection>
50         typename Collection::cursor
take_get_cursor_(const Collection & c,std::size_t n,random_access_cursor_tag)51             take_get_cursor_(
52                 const Collection& c,
53                 std::size_t n,
54                 random_access_cursor_tag
55                 )
56         {
57             auto cur = c.get_cursor();
58             if (cur.size() > n) {
59                 cur.truncate(n);
60             }
61             return cur;
62         }
63     }
64 
65     template <class Collection>
66     struct linq_take
67     {
68         typedef typename std::conditional<
69                 util::less_or_equal_cursor_category<
70                     random_access_cursor_tag,
71                     typename Collection::cursor::cursor_category>::value,
72                 typename Collection::cursor,
73                 linq_take_cursor<typename Collection::cursor>>::type
74             cursor;
75 
linq_takecpplinq::linq_take76         linq_take(const Collection& c, std::size_t n) : c(c), n(n) {}
77 
get_cursorcpplinq::linq_take78         cursor get_cursor() const {
79             return detail::take_get_cursor_(c, n, typename Collection::cursor::cursor_category());
80         }
81 
82         Collection  c;
83         std::size_t n;
84     };
85 
86     template <class Collection>
get_cursor(const linq_take<Collection> & take)87     auto get_cursor(
88             const linq_take<Collection>& take
89             )
90     -> decltype(get_cursor_(take, typename Collection::cursor::cursor_category()))
91     {
92         return get_cursor_(take, typename Collection::cursor::cursor_category());
93     }
94 
95 
96 }
97 #endif // !defined(CPPLINQ_LINQ_TAKE_HPP)
98 
99