Publishing R3
[platform/upstream/dldt.git] / inference-engine / thirdparty / ade / common / include / util / range.hpp
1 // Copyright (C) 2018 Intel Corporation
2 //
3 // SPDX-License-Identifier: Apache-2.0
4 //
5
6 #ifndef UTIL_RANGE_HPP
7 #define UTIL_RANGE_HPP
8
9 #include <iterator>
10 #include <utility>
11
12 #include "util/assert.hpp"
13 #include "util/type_traits.hpp"
14
15 namespace util
16 {
17
18 namespace details
19 {
20 struct RangeIncrementer
21 {
22     template<typename Rng>
23     void operator()(Rng& range) const
24     {
25         range.popFront();
26     }
27 };
28 struct RangeChecker
29 {
30     bool empty = false;
31
32     template<typename Rng>
33     void operator()(Rng& range)
34     {
35         empty = empty || range.empty();
36     }
37 };
38 struct RangeCleaner
39 {
40     template<typename Rng>
41     void operator()(Rng& range) const
42     {
43         range.clear();
44     }
45 };
46
47 //SFINAE and decltype doesn't work wery well together
48 // so this additional wrapper is needed
49 template<typename T>
50 struct range_size_wrapper_helper
51 {
52     using type = decltype(size(std::declval<T>()));
53 };
54
55 template<typename T>
56 inline auto range_size_wrapper(const T& r)
57 ->typename range_size_wrapper_helper<T>::type
58 {
59     return size(r);
60 }
61
62 template<typename T>
63 class has_size_fun
64 {
65     using y = char;
66     using n = long;
67
68     template<typename C>
69     static y test(decltype(size(std::declval<C>()))*);
70     template<typename C>
71     static n test(...);
72 public:
73     static const constexpr bool value = (sizeof(test<T>(0)) == sizeof(y));
74 };
75
76 }
77 inline namespace Range
78 {
79 template<typename BeginT, typename EndT = BeginT>
80 struct IterRange
81 {
82     BeginT beginIter;
83     EndT   endIter;
84
85     BeginT begin() const
86     {
87         return beginIter;
88     }
89
90     EndT end() const
91     {
92         return endIter;
93     }
94
95     bool empty() const
96     {
97         return beginIter == endIter;
98     }
99
100     void popFront()
101     {
102         ASSERT(!empty());
103         ++beginIter;
104     }
105
106     auto front() -> decltype(*beginIter)
107     {
108         ASSERT(!empty());
109         return *beginIter;
110     }
111
112     auto front() const -> decltype(*beginIter)
113     {
114         ASSERT(!empty());
115         return *beginIter;
116     }
117
118     bool operator==(const IterRange<BeginT, EndT>& rhs) const
119     {
120         return beginIter == rhs.beginIter && endIter == rhs.endIter;
121     }
122
123     bool operator!=(const IterRange<BeginT, EndT>& rhs) const
124     {
125         return !(*this == rhs);
126     }
127
128     template<typename I1 = BeginT, typename I2 = EndT,
129              util::enable_b_t<(sizeof(std::declval<I2>() - std::declval<I1>()) > 0)> = true> //SFINAE
130     auto size() const
131     ->decltype(std::declval<I2>() - std::declval<I1>())
132     {
133         return endIter - beginIter;
134     }
135
136     // TODO: bidirectional and random access ranges
137 };
138
139 template<typename BeginT, typename EndT>
140 inline auto size(const IterRange<BeginT, EndT>& range)
141 ->decltype(range.size())
142 {
143     return range.size();
144 }
145
146 template<typename T>
147 inline auto toRange(T&& val) -> IterRange<decltype(std::begin(val)), decltype(std::end(val))>
148 {
149     return {std::begin(val), std::end(val)};
150 }
151
152 template<typename T>
153 inline auto toRangeReverse(T&& val) -> IterRange<decltype(val.rbegin()), decltype(val.rbegin())>
154 {
155     // TODO: use c++14 std::rbegin, std::rend
156     return {val.rbegin(), val.rend()};
157 }
158
159 template<typename Iter>
160 inline auto toRange(const std::pair<Iter,Iter>& val) -> IterRange<decltype(val.first), decltype(val.second)>
161 {
162     return {val.first, val.second};
163 }
164
165 template<typename Iter>
166 inline auto toRange(Iter&& val, std::size_t count) -> IterRange<remove_reference_t<Iter>, remove_reference_t<Iter>>
167 {
168     return {std::forward<Iter>(val), std::next(val, count)};
169 }
170
171 template<typename T>
172 inline auto index(T&& val)->decltype(std::get<0>(std::forward<T>(val)))
173 {
174     return std::get<0>(std::forward<T>(val));
175 }
176
177 template<int I = 0, typename T>
178 inline auto value(T&& val)->decltype(std::get<I + 1>(std::forward<T>(val)))
179 {
180     static_assert(I >= 0,"Invalid I");
181     return std::get<I + 1>(std::forward<T>(val));
182 }
183
184 template<typename Range>
185 inline void advance_range(Range&& range)
186 {
187     range.popFront();
188 }
189
190 }
191 }
192
193 #endif // UTIL_RANGE_HPP