1 // Copyright (C) 2018 Intel Corporation
3 // SPDX-License-Identifier: Apache-2.0
6 #ifndef UTIL_MEMORYRANGE_HPP
7 #define UTIL_MEMORYRANGE_HPP
10 #include <cstring> //size_t
14 #include "util/type_traits.hpp"
15 #include "util/assert.hpp"
20 /// Non owning view over the data in another container
21 /// T can be cv-qualified object or cv-qualified void
25 static_assert(std::is_object<T>::value || std::is_void<T>::value, "Invalid type");
30 MemoryRange() = default;
31 MemoryRange(const MemoryRange&) = default;
32 MemoryRange& operator=(const MemoryRange&) = default;
34 MemoryRange(T* data_, size_t size_):
35 data(data_), size(size_)
37 ASSERT((nullptr != data) || (0 == size)); //size must be 0 for null data
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
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);
51 template<typename Dummy = void>
52 typename std::enable_if<!std::is_void<T>::value, typename std::conditional<true, T*, Dummy>::type >::type
58 template<typename Dummy = void>
59 typename std::enable_if<!std::is_void<T>::value, typename std::conditional<true, T*, Dummy>::type >::type
65 template<typename Dummy = void>
66 typename std::enable_if<!std::is_void<T>::value, typename std::conditional<true, const T*, Dummy>::type >::type
72 template<typename Dummy = void>
73 typename std::enable_if<!std::is_void<T>::value, typename std::conditional<true, const T*, Dummy>::type >::type
79 template<typename Dummy = T> // hack for sfinae
80 typename std::enable_if<(sizeof(Dummy) > 0), Dummy& >::type
81 operator[](size_t index)
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
95 template<typename NewT>
96 MemoryRange<NewT> reinterpret() const
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);
104 template<typename Dummy = T> // hack for sfinae
105 typename std::enable_if<(sizeof(Dummy) > 0), Dummy& >::type
112 template<typename Dummy = T> // hack for sfinae
113 typename std::enable_if<(sizeof(Dummy) > 0), const Dummy& >::type
120 template<typename Dummy = T> // hack for sfinae
121 typename std::enable_if<(sizeof(Dummy) > 0), Dummy& >::type
125 return data[size - 1];
128 template<typename Dummy = T> // hack for sfinae
129 typename std::enable_if<(sizeof(Dummy) > 0), const Dummy& >::type
133 return data[size - 1];
144 *this = Slice(1, size - 1);
149 inline MemoryRange<T> memory_range(T* ptr, const std::size_t size)
154 template<typename T, std::size_t size_>
155 inline MemoryRange<T> memory_range(T (&range)[size_])
157 return memory_range(&range[0], size_);
160 template<typename T, std::size_t size_>
161 inline MemoryRange<T> memory_range(std::array<T, size_>& arr)
163 return memory_range(arr.data(), size_);
167 inline T* data(const MemoryRange<T>& range)
172 template<typename T, std::size_t size>
173 inline T* data(T (&range)[size])
179 inline std::size_t size(const MemoryRange<T>& range)
184 template<typename T, std::size_t size_>
185 inline std::size_t size(T (&)[size_])
191 inline bool operator==(const MemoryRange<T>& range, std::nullptr_t)
193 return range.data == nullptr;
197 inline bool operator==(std::nullptr_t, const MemoryRange<T>& range)
199 return range.data == nullptr;
203 inline bool operator!=(const MemoryRange<T>& range, std::nullptr_t)
205 return range.data != nullptr;
209 inline bool operator!=(std::nullptr_t, const MemoryRange<T>& range)
211 return range.data != nullptr;
215 inline MemoryRange<T> slice(const MemoryRange<T>& range, const std::size_t start, const std::size_t newSize)
217 return range.Slice(start, newSize);
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)
223 return memory_range(&range[0], size).Slice(start, newSize);
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)))
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);
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);
246 return slice(dst, size(src), size(dst) - size(src));
249 inline MemoryRange<void> raw_copy(const MemoryRange<void>& src, MemoryRange<void> dst)
251 return raw_copy(src.reinterpret<const char>(), dst.reinterpret<char>()).reinterpret<void>();
254 inline MemoryRange<void> raw_copy(const MemoryRange<const void>& src, MemoryRange<void> dst)
256 return raw_copy(src.reinterpret<const char>(), dst.reinterpret<char>()).reinterpret<void>();
261 #endif // UTIL_MEMORYRANGE_HPP