1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#pragma once
4
5#ifdef __BORLANDC__
6 #define __STD_ALGORITHM
7#endif
8
9#include <cassert>
10#include <cstdio>
11#include <cstdlib>
12#include <ctime>
13#include <cstring>
14#include <cstdarg>
15#include <cmath>
16
17#include <memory>
18
19// STL containers
20#include <vector>
21#include <stack>
22#include <map>
23#include <string>
24#include <set>
25#include <list>
26#include <forward_list>
27#include <deque>
28#include <queue>
29#include <bitset>
30#include <array>
31
32#include <unordered_map>
33#include <unordered_set>
34
35// STL algorithms & functions
36#include <algorithm>
37#include <functional>
38#include <limits>
39#include <iterator>
40
41// C++ Stream stuff
42#include <fstream>
43#include <iostream>
44#include <iomanip>
45#include <sstream>
46
47extern "C" {
48
49# include <sys/types.h>
50# include <sys/stat.h>
51
52}
53
54#if BS_PLATFORM == BS_PLATFORM_WIN32
55# undef min
56# undef max
57# if !defined(NOMINMAX) && defined(_MSC_VER)
58# define NOMINMAX // required to stop windows.h messing up std::min
59# endif
60# if defined( __MINGW32__ )
61# include <unistd.h>
62# endif
63#endif
64
65#if BS_PLATFORM == BS_PLATFORM_LINUX
66extern "C" {
67
68# include <unistd.h>
69# include <dlfcn.h>
70
71}
72#endif
73
74#if BS_PLATFORM == BS_PLATFORM_OSX
75extern "C" {
76
77# include <unistd.h>
78# include <sys/param.h>
79# include <CoreFoundation/CoreFoundation.h>
80
81}
82#endif
83
84namespace bs
85{
86 /**
87 * Hash for enum types, to be used instead of std::hash<T> when T is an enum.
88 *
89 * Until C++14, std::hash<T> is not defined if T is a enum (see
90 * http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2148). But
91 * even with C++14, as of october 2016, std::hash for enums is not widely
92 * implemented by compilers, so here when T is a enum, we use EnumClassHash
93 * instead of std::hash. (For instance, in bs::hash_combine(), or
94 * bs::UnorderedMap.)
95 */
96 struct EnumClassHash
97 {
98 template <typename T>
99 constexpr std::size_t operator()(T t) const
100 {
101 return static_cast<std::size_t>(t);
102 }
103 };
104
105 /** @addtogroup Containers
106 * @{
107 */
108
109 /** Hasher that handles custom enums automatically. */
110 template <typename Key>
111 using HashType = typename std::conditional<std::is_enum<Key>::value, EnumClassHash, std::hash<Key>>::type;
112
113 /** Double ended queue. Allows for fast insertion and removal at both its beggining and end. */
114 template <typename T, typename A = StdAlloc<T>>
115 using Deque = std::deque<T, A>;
116
117 /** Dynamically sized array that stores element contigously. */
118 template <typename T, typename A = StdAlloc<T>>
119 using Vector = std::vector<T, A>;
120
121 /**
122 * Container that supports constant time insertion and removal for elements with known locations, but without fast
123 * random access to elements. Internally implemented as a doubly linked list. Use ForwardList if you do not need
124 * reverse iteration.
125 */
126 template <typename T, typename A = StdAlloc<T>>
127 using List = std::list<T, A>;
128
129 /**
130 * Container that supports constant time insertion and removal for elements with known locations, but without fast
131 * random access to elements. Internally implemented as a singly linked list that doesn't support reverse iteration.
132 */
133 template <typename T, typename A = StdAlloc<T>>
134 using ForwardList = std::forward_list<T, A>;
135
136 /** First-in, last-out data structure. */
137 template <typename T, typename A = StdAlloc<T>>
138 using Stack = std::stack<T, std::deque<T, A>>;
139
140 /** First-in, first-out data structure. */
141 template <typename T, typename A = StdAlloc<T>>
142 using Queue = std::queue<T, std::deque<T, A>>;
143
144 /** An associative container containing an ordered set of elements. */
145 template <typename T, typename P = std::less<T>, typename A = StdAlloc<T>>
146 using Set = std::set<T, P, A>;
147
148 /** An associative container containing an ordered set of key-value pairs. */
149 template <typename K, typename V, typename P = std::less<K>, typename A = StdAlloc<std::pair<const K, V>>>
150 using Map = std::map<K, V, P, A>;
151
152 /** An associative container containing an ordered set of elements where multiple elements can have the same key. */
153 template <typename T, typename P = std::less<T>, typename A = StdAlloc<T>>
154 using MultiSet = std::multiset<T, P, A>;
155
156 /** An associative container containing an ordered set of key-value pairs where multiple elements can have the same key. */
157 template <typename K, typename V, typename P = std::less<K>, typename A = StdAlloc<std::pair<const K, V>>>
158 using MultiMap = std::multimap<K, V, P, A>;
159
160 /** An associative container containing an unordered set of elements. Usually faster than Set for larger data sets. */
161 template <typename T, typename H = HashType<T>, typename C = std::equal_to<T>, typename A = StdAlloc<T>>
162 using UnorderedSet = std::unordered_set<T, H, C, A>;
163
164 /** An associative container containing an ordered set of key-value pairs. Usually faster than Map for larger data sets. */
165 template <typename K, typename V, typename H = HashType<K>, typename C = std::equal_to<K>, typename A = StdAlloc<std::pair<const K, V>>>
166 using UnorderedMap = std::unordered_map<K, V, H, C, A>;
167
168 /**
169 * An associative container containing an ordered set of key-value pairs where multiple elements can have the same key.
170 * Usually faster than MultiMap for larger data sets.
171 */
172 template <typename K, typename V, typename H = HashType<K>, typename C = std::equal_to<K>, typename A = StdAlloc<std::pair<const K, V>>>
173 using UnorderedMultimap = std::unordered_multimap<K, V, H, C, A>;
174
175 /** @} */
176
177 /** @addtogroup Memory
178 * @{
179 */
180
181 /**
182 * Smart pointer that retains shared ownership of an project through a pointer. The object is destroyed automatically
183 * when the last shared pointer to the object is destroyed.
184 */
185 template <typename T>
186 using SPtr = std::shared_ptr<T>;
187
188 /** Holds a reference to an object whose lifetime is managed by a SPtr, but doesn't increment the reference count. */
189 template <typename T>
190 using WeakSPtr = std::weak_ptr<T>;
191
192 /**
193 * Smart pointer that retains shared ownership of an project through a pointer. Reference to the object must be unique.
194 * The object is destroyed automatically when the pointer to the object is destroyed.
195 */
196 template <typename T, typename Alloc = GenAlloc, typename Delete = Deleter<T, Alloc>>
197 using UPtr = std::unique_ptr<T, Delete>;
198
199 /** Create a new shared pointer using a custom allocator category. */
200 template<typename Type, typename AllocCategory = GenAlloc, typename... Args>
201 SPtr<Type> bs_shared_ptr_new(Args &&... args)
202 {
203 return std::allocate_shared<Type>(StdAlloc<Type, AllocCategory>(), std::forward<Args>(args)...);
204 }
205
206 /**
207 * Create a new shared pointer from a previously constructed object.
208 * Pointer specific data will be allocated using the provided allocator category.
209 */
210 template<typename Type, typename MainAlloc = GenAlloc, typename PtrDataAlloc = GenAlloc, typename Delete = Deleter<Type, MainAlloc>>
211 SPtr<Type> bs_shared_ptr(Type* data, Delete del = Delete())
212 {
213 return SPtr<Type>(data, std::move(del), StdAlloc<Type, PtrDataAlloc>());
214 }
215
216 /**
217 * Create a new unique pointer from a previously constructed object.
218 * Pointer specific data will be allocated using the provided allocator category.
219 */
220 template<typename Type, typename Alloc = GenAlloc, typename Delete = Deleter<Type, Alloc>>
221 UPtr<Type, Alloc, Delete> bs_unique_ptr(Type* data, Delete del = Delete())
222 {
223 return std::unique_ptr<Type, Delete>(data, std::move(del));
224 }
225
226 /** Create a new unique pointer using a custom allocator category. */
227 template<typename Type, typename Alloc = GenAlloc, typename Delete = Deleter<Type, Alloc>, typename... Args>
228 UPtr<Type, Alloc, Delete> bs_unique_ptr_new(Args &&... args)
229 {
230 Type* rawPtr = bs_new<Type, Alloc>(std::forward<Args>(args)...);
231
232 return bs_unique_ptr<Type, Alloc, Delete>(rawPtr);
233 }
234
235 /**
236 * "Smart" pointer that is not smart. Does nothing but hold a pointer value. No memory management is performed at all.
237 * This class exists to make storing pointers in containers easier to manage, such as with non-member comparison
238 * operators.
239 */
240 template<typename T>
241 struct NativePtr
242 {
243 constexpr NativePtr(T* p) : mPtr(p) {}
244 constexpr T& operator*() const { return *mPtr; }
245 constexpr T* operator->() const { return mPtr; }
246 constexpr T* get() const { return mPtr; }
247
248 private:
249 T* mPtr = nullptr;
250 };
251
252 template<typename T>
253 using NPtr = NativePtr<T>;
254
255 template<typename L_T, typename R_T>
256 constexpr bool operator< (const NPtr<L_T>& lhs, const NPtr<R_T>& rhs)
257 {
258 return lhs.get() < rhs.get();
259 }
260
261 template<typename L_T, typename R_T>
262 constexpr bool operator> (const NPtr<L_T>& lhs, const NPtr<R_T>& rhs)
263 {
264 return lhs.get() > rhs.get();
265 }
266
267 template<typename L_T, typename R_T>
268 constexpr bool operator<= (const NPtr<L_T>& lhs, const NPtr<R_T>& rhs)
269 {
270 return lhs.get() <= rhs.get();
271 }
272
273 template<typename L_T, typename R_T>
274 constexpr bool operator>= (const NPtr<L_T>& lhs, const NPtr<R_T>& rhs)
275 {
276 return lhs.get() >= rhs.get();
277 }
278
279 template<typename L_T, typename R_T>
280 constexpr bool operator== (const NPtr<L_T>& lhs, const NPtr<R_T>& rhs)
281 {
282 return lhs.get() == rhs.get();
283 }
284
285 template<typename L_T, typename R_T>
286 constexpr bool operator!= (const NPtr<L_T>& lhs, const NPtr<R_T>& rhs)
287 {
288 return lhs.get() != rhs.get();
289 }
290
291 /** @} */
292}
293