Publishing R3
[platform/upstream/dldt.git] / inference-engine / thirdparty / ade / common / include / util / memory_range.hpp
1 // Copyright (C) 2018 Intel Corporation
2 //
3 // SPDX-License-Identifier: Apache-2.0
4 //
5
6 #ifndef UTIL_MEMORYRANGE_HPP
7 #define UTIL_MEMORYRANGE_HPP
8
9 #include <type_traits>
10 #include <cstring> //size_t
11 #include <algorithm>
12 #include <array>
13
14 #include "util/type_traits.hpp"
15 #include "util/assert.hpp"
16
17 namespace util
18 {
19
20 /// Non owning view over the data in another container
21 /// T can be cv-qualified object or cv-qualified void
22 template<typename T>
23 struct MemoryRange
24 {
25    static_assert(std::is_object<T>::value || std::is_void<T>::value, "Invalid type");
26    using value_type = T;
27    T*     data = nullptr;
28    size_t size = 0;
29
30    MemoryRange()                              = default;
31    MemoryRange(const MemoryRange&)            = default;
32    MemoryRange& operator=(const MemoryRange&) = default;
33
34    MemoryRange(T* data_, size_t size_):
35       data(data_), size(size_)
36    {
37       ASSERT((nullptr != data) || (0 == size)); //size must be 0 for null data
38    }
39
40    /// Slice view
41    /// if T is void start and newSize addressable in bytes
42    /// otherwise in elements
43    MemoryRange<T> Slice(size_t start, size_t newSize) const
44    {
45       ASSERT(nullptr != data);
46       ASSERT((start + newSize) <= size);
47       using temp_t = typename std::conditional<std::is_void<T>::value, char, T>::type;
48       return MemoryRange<T>(static_cast<temp_t*>(data) + start, newSize);
49    }
50
51    template<typename Dummy = void>
52    typename std::enable_if<!std::is_void<T>::value, typename std::conditional<true, T*, Dummy>::type >::type
53    begin()
54    {
55       return data;
56    }
57
58    template<typename Dummy = void>
59    typename std::enable_if<!std::is_void<T>::value, typename std::conditional<true, T*, Dummy>::type >::type
60    end()
61    {
62       return data + size;
63    }
64
65    template<typename Dummy = void>
66    typename std::enable_if<!std::is_void<T>::value, typename std::conditional<true, const T*, Dummy>::type >::type
67    begin() const
68    {
69       return data;
70    }
71
72    template<typename Dummy = void>
73    typename std::enable_if<!std::is_void<T>::value, typename std::conditional<true, const T*, Dummy>::type >::type
74    end() const
75    {
76       return data + size;
77    }
78
79    template<typename Dummy = T> // hack for sfinae
80    typename std::enable_if<(sizeof(Dummy) > 0), Dummy& >::type
81    operator[](size_t index)
82    {
83       ASSERT(index < size);
84       return data[index];
85    }
86
87    template<typename Dummy = T> // hack for sfinae
88    typename std::enable_if<(sizeof(Dummy) > 0), const Dummy& >::type
89    operator[](size_t index) const
90    {
91       ASSERT(index < size);
92       return data[index];
93    }
94
95    template<typename NewT>
96    MemoryRange<NewT> reinterpret() const
97    {
98       const size_t elem_size     = sizeof(util::conditional_t< std::is_void<T>::value, char, T >);
99       const size_t elem_size_new = sizeof(util::conditional_t< std::is_void<NewT>::value, char, NewT >);
100       const size_t newSize = (size * elem_size) / elem_size_new;
101       return MemoryRange<NewT>(static_cast<NewT*>(data), newSize);
102    }
103
104    template<typename Dummy = T> // hack for sfinae
105    typename std::enable_if<(sizeof(Dummy) > 0), Dummy& >::type
106    front()
107    {
108       ASSERT(size > 0);
109       return data[0];
110    }
111
112    template<typename Dummy = T> // hack for sfinae
113    typename std::enable_if<(sizeof(Dummy) > 0), const Dummy& >::type
114    front() const
115    {
116       ASSERT(size > 0);
117       return data[0];
118    }
119
120    template<typename Dummy = T> // hack for sfinae
121    typename std::enable_if<(sizeof(Dummy) > 0), Dummy& >::type
122    back()
123    {
124       ASSERT(size > 0);
125       return data[size - 1];
126    }
127
128    template<typename Dummy = T> // hack for sfinae
129    typename std::enable_if<(sizeof(Dummy) > 0), const Dummy& >::type
130    back() const
131    {
132       ASSERT(size > 0);
133       return data[size - 1];
134    }
135
136    bool empty() const
137    {
138        return 0 == size;
139    }
140
141    void popFront()
142    {
143        ASSERT(!empty());
144        *this = Slice(1, size - 1);
145    }
146 };
147
148 template<typename T>
149 inline MemoryRange<T> memory_range(T* ptr, const std::size_t size)
150 {
151     return {ptr, size};
152 }
153
154 template<typename T, std::size_t size_>
155 inline MemoryRange<T> memory_range(T (&range)[size_])
156 {
157     return memory_range(&range[0], size_);
158 }
159
160 template<typename T, std::size_t size_>
161 inline MemoryRange<T> memory_range(std::array<T, size_>& arr)
162 {
163     return memory_range(arr.data(), size_);
164 }
165
166 template<typename T>
167 inline T* data(const MemoryRange<T>& range)
168 {
169     return range.data;
170 }
171
172 template<typename T, std::size_t size>
173 inline T* data(T (&range)[size])
174 {
175     return &(range[0]);
176 }
177
178 template<typename T>
179 inline std::size_t size(const MemoryRange<T>& range)
180 {
181     return range.size;
182 }
183
184 template<typename T, std::size_t size_>
185 inline std::size_t size(T (&)[size_])
186 {
187     return size_;
188 }
189
190 template<typename T>
191 inline bool operator==(const MemoryRange<T>& range, std::nullptr_t)
192 {
193     return range.data == nullptr;
194 }
195
196 template<typename T>
197 inline bool operator==(std::nullptr_t, const MemoryRange<T>& range)
198 {
199     return range.data == nullptr;
200 }
201
202 template<typename T>
203 inline bool operator!=(const MemoryRange<T>& range, std::nullptr_t)
204 {
205     return range.data != nullptr;
206 }
207
208 template<typename T>
209 inline bool operator!=(std::nullptr_t, const MemoryRange<T>& range)
210 {
211     return range.data != nullptr;
212 }
213
214 template<typename T>
215 inline MemoryRange<T> slice(const MemoryRange<T>& range, const std::size_t start, const std::size_t newSize)
216 {
217     return range.Slice(start, newSize);
218 }
219
220 template<typename T, std::size_t size>
221 inline MemoryRange<T> slice(T (&range)[size], const std::size_t start, const std::size_t newSize)
222 {
223     return memory_range(&range[0], size).Slice(start, newSize);
224 }
225
226 template<typename SrcRange, typename DstRange>
227 inline auto raw_copy(const SrcRange& src, DstRange&& dst)
228 -> decltype(slice(dst, size(src), size(dst) - size(src)))
229 {
230     static_assert(std::is_same< util::decay_t<decltype(*data(src))>,
231                                 util::decay_t<decltype(*data(dst))> >::value, "Types must be same");
232     static_assert(std::is_pod< util::decay_t<decltype(*data(src))> >::value, "Types must be pod");
233     static_assert(sizeof(src[std::size_t{}]) == sizeof(dst[std::size_t{}]), "Size mismatch");
234     const auto src_size = size(src);
235     const auto dst_size = size(dst);
236     ASSERT(nullptr != src);
237     ASSERT(nullptr != dst);
238     ASSERT(dst_size >= src_size);
239     auto src_data = data(src);
240     auto dst_data = data(dst);
241     // Check overlap
242     ASSERT(((src_data < dst_data) || (src_data >= (dst_data + dst_size))) &&
243            ((dst_data < src_data) || (dst_data >= (src_data + src_size))));
244     std::copy_n(src_data, src_size, dst_data);
245
246     return slice(dst, size(src), size(dst) - size(src));
247 }
248
249 inline MemoryRange<void> raw_copy(const MemoryRange<void>& src, MemoryRange<void> dst)
250 {
251     return raw_copy(src.reinterpret<const char>(), dst.reinterpret<char>()).reinterpret<void>();
252 }
253
254 inline MemoryRange<void> raw_copy(const MemoryRange<const void>& src, MemoryRange<void> dst)
255 {
256     return raw_copy(src.reinterpret<const char>(), dst.reinterpret<char>()).reinterpret<void>();
257 }
258
259 } // util
260
261 #endif // UTIL_MEMORYRANGE_HPP