]> git.sesse.net Git - casparcg/blob - common/array.h
dc2cc8bbf9f719922594d651435466ff70fd8b9b
[casparcg] / common / array.h
1 #pragma once\r
2 \r
3 #include "memory.h"\r
4 #include "forward.h"\r
5 \r
6 #include <boost/any.hpp>\r
7 \r
8 #include <cstddef>\r
9 #include <cstdint>\r
10 \r
11 namespace caspar {\r
12         \r
13 template<typename T>\r
14 class array sealed\r
15 {\r
16         array(const array<std::uint8_t>&);\r
17         array& operator=(const array<std::uint8_t>&);\r
18 \r
19         template<typename> friend class array;\r
20 public:\r
21 \r
22         // Static Members\r
23 \r
24         // Constructors\r
25         \r
26         template<typename T>\r
27         explicit array(std::uint8_t* ptr, std::size_t size, bool cacheable, T&& storage)\r
28                 : ptr_(ptr)\r
29                 , size_(size)\r
30                 , cacheable_(cacheable)\r
31                 , storage_(new boost::any(std::forward<T>(storage)))\r
32         {\r
33         }\r
34 \r
35         array(array&& other)\r
36                 : ptr_(other.ptr_)\r
37                 , size_(other.size_)\r
38                 , cacheable_(other.cacheable_)\r
39                 , storage_(std::move(other.storage_))\r
40         {\r
41                 CASPAR_ASSERT(storage_);\r
42         }\r
43 \r
44         // Methods\r
45         \r
46         array& operator=(array&& other)\r
47         {\r
48                 std::swap(ptr_, other.ptr_);\r
49                 std::swap(size_, other.size_);\r
50                 std::swap(storage_,     other.storage_);\r
51                 std::swap(cacheable_, other.cacheable_);\r
52 \r
53                 CASPAR_ASSERT(storage_);\r
54 \r
55                 return *this;\r
56         }\r
57 \r
58         // Properties   \r
59                         \r
60         T* begin() const                        {return ptr_;}          \r
61         T* data() const                         {return ptr_;}\r
62         T* end() const                          {return reinterpret_cast<T*>(reinterpret_cast<char*>(ptr_) + size_);}\r
63         std::size_t size() const        {return size_;}\r
64         bool empty() const                      {return size() == 0;}\r
65         bool cacheable() const          {return cacheable_;}\r
66         \r
67         template<typename T>\r
68         T* storage() const\r
69         {\r
70                 return boost::any_cast<T>(storage_.get());\r
71         }\r
72 private:\r
73         T*                      ptr_;\r
74         std::size_t     size_;\r
75         bool            cacheable_;\r
76         std::unique_ptr<boost::any>     storage_;\r
77 };\r
78 \r
79 template<typename T>\r
80 class array<const T> sealed\r
81 {\r
82 public:\r
83 \r
84         // Static Members\r
85 \r
86         // Constructors\r
87 \r
88         template<typename T>\r
89         explicit array(const std::uint8_t* ptr, std::size_t size, bool cacheable, T&& storage)\r
90                 : ptr_(ptr)\r
91                 , size_(size)\r
92                 , cacheable_(cacheable)\r
93                 , storage_(new boost::any(std::forward<T>(storage)))\r
94         {\r
95         }\r
96         \r
97         array(const array& other)\r
98                 : ptr_(other.ptr_)\r
99                 , size_(other.size_)\r
100                 , cacheable_(other.cacheable_)\r
101                 , storage_(other.storage_)\r
102         {\r
103                 CASPAR_ASSERT(storage_);\r
104         }\r
105 \r
106         array(array<T>&& other)\r
107                 : ptr_(other.ptr_)\r
108                 , size_(other.size_)\r
109                 , cacheable_(other.cacheable_)\r
110                 , storage_(std::move(other.storage_))\r
111         {\r
112                 CASPAR_ASSERT(storage_);\r
113         }\r
114 \r
115         // Methods\r
116 \r
117         array& operator=(array other)\r
118         {\r
119                 other.swap(*this);\r
120                 return *this;\r
121         }\r
122 \r
123         void swap(array& other)\r
124         {\r
125                 std::swap(ptr_, other.ptr_);\r
126                 std::swap(size_, other.size_);\r
127                 std::swap(storage_,     other.storage_);\r
128                 std::swap(cacheable_, other.cacheable_);\r
129         }\r
130 \r
131         // Properties\r
132                         \r
133         const T* begin() const          {return ptr_;}          \r
134         const T* data() const           {return ptr_;}\r
135         const T* end() const            {return reinterpret_cast<const T*>(reinterpret_cast<const char*>(ptr_) + size_);}\r
136         std::size_t size() const        {return size_;}\r
137         bool empty() const                      {return size() == 0;}\r
138         bool cacheable() const          {return cacheable_;}\r
139         \r
140         template<typename T>\r
141         T* storage() const\r
142         {\r
143                 return boost::any_cast<T>(storage_.get());\r
144         }\r
145 \r
146 private:\r
147         const T*        ptr_;\r
148         std::size_t     size_;\r
149         bool            cacheable_;\r
150         std::shared_ptr<boost::any>     storage_;\r
151 };\r
152 \r
153 }\r
154 \r
155 namespace std {\r
156         \r
157 template<typename T>\r
158 void swap(caspar::array<const T>& lhs, caspar::array<const T>& rhs)\r
159 {\r
160         lhs.swap(rhs);\r
161 }\r
162 \r
163 }\r
164 \r