Cuberite
A lightweight, fast and extensible game server for Minecraft
Globals.h
Go to the documentation of this file.
1 
2 // Globals.h
3 
4 // This file gets included from every module in the project, so that global symbols may be introduced easily
5 // Also used for precompiled header generation in MSVC environments
6 
7 
8 
9 
10 
11 #pragma once
12 
13 
14 
15 
16 
17 // Compiler-dependent stuff:
18 #if defined(_MSC_VER)
19  // Use non-standard defines in <cmath>
20  #define _USE_MATH_DEFINES
21 
22  #ifndef NDEBUG
23  // Override the "new" operator to include file and line specification for debugging memory leaks
24  // Ref.: https://social.msdn.microsoft.com/Forums/en-US/ebc7dd7a-f3c6-49f1-8a60-e381052f21b6/debugging-memory-leaks?forum=vcgeneral#53f0cc89-62fe-45e8-bbf0-56b89f2a1901
25  // This causes MSVC Debug runs to produce a report upon program exit, that contains memory-leaks
26  // together with the file:line information about where the memory was allocated.
27  // Note that this doesn't work with placement-new, which needs to temporarily #undef the macro
28  // (See AllocationPool.h for an example).
29  #define _CRTDBG_MAP_ALLOC
30  #include <stdlib.h>
31  #include <crtdbg.h>
32  #define DEBUG_CLIENTBLOCK new(_CLIENT_BLOCK, __FILE__, __LINE__)
33  #define new DEBUG_CLIENTBLOCK
34  // For some reason this works magically - each "new X" gets replaced as "new(_CLIENT_BLOCK, "file", line) X"
35  // The CRT has a definition for this operator new that stores the debugging info for leak-finding later.
36  #endif
37 
38  #define UNREACHABLE_INTRINSIC __assume(false)
39 
40 #elif defined(__GNUC__)
41 
42  // TODO: Can GCC explicitly mark classes as abstract (no instances can be created)?
43  #define abstract
44 
45  #define UNREACHABLE_INTRINSIC __builtin_unreachable()
46 
47 #else
48 
49  #error "You are using an unsupported compiler, you might need to #define some stuff here for your compiler"
50 
51 #endif
52 
53 
54 
55 
56 
57 // A macro to disallow the copy constructor and operator = functions
58 // This should be used in the declarations for any class that shouldn't allow copying itself
59 #define DISALLOW_COPY_AND_ASSIGN(TypeName) \
60  TypeName(const TypeName &) = delete; \
61  TypeName & operator =(const TypeName &) = delete
62 
63 // A macro that is used to mark unused local variables, to avoid pedantic warnings in gcc / clang / MSVC
64 // Note that in MSVC it requires the full type of X to be known
65 #define UNUSED_VAR(X) (void)(X)
66 
67 // A macro that is used to mark unused function parameters, to avoid pedantic warnings in gcc
68 // Written so that the full type of param needn't be known
69 #ifdef _MSC_VER
70  #define UNUSED(X)
71 #else
72  #define UNUSED UNUSED_VAR
73 #endif
74 
75 
76 
77 
78 
79 // OS-dependent stuff:
80 #ifdef _WIN32
81  #define NOMINMAX // Windows SDK defines min and max macros, messing up with our std::min and std::max usage.
82  #define WIN32_LEAN_AND_MEAN
83  #define _WIN32_WINNT 0x0501 // We want to target Windows XP with Service Pack 2 & Windows Server 2003 with Service Pack 1 and higher.
84 
85  // Use CryptoAPI primitives when targeting a version that supports encrypting with AES-CFB8 smaller than a full block at a time.
86  #define PLATFORM_CRYPTOGRAPHY (_WIN32_WINNT >= 0x0602)
87 
88  #include <Windows.h>
89  #include <winsock2.h>
90  #include <Ws2tcpip.h> // IPv6 stuff
91 
92  // Windows SDK defines GetFreeSpace as a constant, probably a Win16 API remnant:
93  #ifdef GetFreeSpace
94  #undef GetFreeSpace
95  #endif // GetFreeSpace
96 #else
97  #define PLATFORM_CRYPTOGRAPHY 0
98 
99  #include <arpa/inet.h>
100  #include <netinet/in.h>
101  #include <netinet/tcp.h>
102  #include <sys/socket.h>
103  #include <unistd.h>
104 #endif
105 
106 
107 
108 
109 
110 // CRT stuff:
111 #include <cassert>
112 #include <cstdio>
113 #include <cmath>
114 #include <cstdarg>
115 #include <cstddef>
116 
117 
118 
119 
120 
121 // STL stuff:
122 #include <algorithm>
123 #include <array>
124 #include <atomic>
125 #include <chrono>
126 #include <condition_variable>
127 #include <deque>
128 #include <fstream>
129 #include <limits>
130 #include <list>
131 #include <map>
132 #include <memory>
133 #include <mutex>
134 #include <queue>
135 #include <random>
136 #include <set>
137 #include <string>
138 #include <thread>
139 #include <type_traits>
140 #include <unordered_map>
141 #include <unordered_set>
142 #include <utility>
143 #include <vector>
144 #include <variant>
145 
146 
147 
148 
149 
150 // Integral types with predefined sizes:
151 typedef signed long long Int64;
152 typedef signed int Int32;
153 typedef signed short Int16;
154 typedef signed char Int8;
155 
156 typedef unsigned long long UInt64;
157 typedef unsigned int UInt32;
158 typedef unsigned short UInt16;
159 typedef unsigned char UInt8;
160 
161 typedef unsigned char Byte;
162 typedef Byte ColourID;
163 
164 
165 template <typename T, size_t Size>
167 {
168  static_assert(sizeof(T) == Size, "Check the size of integral types");
169 };
170 
171 template class SizeChecker<Int64, 8>;
172 template class SizeChecker<Int32, 4>;
173 template class SizeChecker<Int16, 2>;
174 template class SizeChecker<Int8, 1>;
175 
176 template class SizeChecker<UInt64, 8>;
177 template class SizeChecker<UInt32, 4>;
178 template class SizeChecker<UInt16, 2>;
179 template class SizeChecker<UInt8, 1>;
180 
181 // Common headers (part 1, without macros):
182 #include "fmt.h"
183 #include "StringUtils.h"
184 #include "LoggerSimple.h"
186 #include "OSSupport/Event.h"
187 #include "OSSupport/File.h"
188 #include "OSSupport/StackTrace.h"
189 
190 #ifdef TEST_GLOBALS
191 
192  // Basic logging function implementations
193  namespace Logger
194  {
195 
196  inline void LogFormat(
197  std::string_view a_Format, eLogLevel, fmt::format_args a_ArgList
198  )
199  {
200  fmt::vprint(a_Format, a_ArgList);
201  putchar('\n');
202  fflush(stdout);
203  }
204 
205  inline void LogPrintf(
206  std::string_view a_Format, eLogLevel, fmt::printf_args a_ArgList
207  )
208  {
209  fmt::vprintf(a_Format, a_ArgList);
210  putchar('\n');
211  fflush(stdout);
212  }
213 
214  inline void LogSimple(std::string_view a_Message, eLogLevel)
215  {
216  fmt::print("{}\n", a_Message);
217  fflush(stdout);
218  }
219 
220  } // namespace Logger
221 
222 #endif
223 
224 
225 
226 
227 
228 // Common definitions:
229 
231 #define ARRAYCOUNT(X) (sizeof(X) / sizeof(*(X)))
232 
234 #define KiB * 1024
235 #define MiB * 1024 * 1024
236 
238 #define FAST_FLOOR_DIV(x, div) (((x) - (((x) < 0) ? ((div) - 1) : 0)) / (div))
239 
240 // Own version of ASSERT() that plays nicely with the testing framework
241 #ifdef TEST_GLOBALS
242 
243  class cAssertFailure
244  {
245  AString mExpression;
246  AString mFileName;
247  int mLineNumber;
248 
249  public:
250  cAssertFailure(const AString & aExpression, const AString & aFileName, int aLineNumber):
251  mExpression(aExpression),
252  mFileName(aFileName),
253  mLineNumber(aLineNumber)
254  {
255  }
256 
257  const AString & expression() const { return mExpression; }
258  const AString & fileName() const { return mFileName; }
259  int lineNumber() const { return mLineNumber; }
260  };
261 
262  #ifdef NDEBUG
263  #define ASSERT(x)
264  #else
265  #define ASSERT(x) do { if (!(x)) { throw cAssertFailure(#x, __FILE__, __LINE__);} } while (0)
266  #endif
267 
268  // Pretty much the same as ASSERT() but stays in Release builds
269  #define VERIFY(x) (!!(x) || ( LOGERROR("Verification failed: %s, file %s, line %i", #x, __FILE__, __LINE__), std::abort(), 0))
270 
271 #else // TEST_GLOBALS
272 
273  #ifdef NDEBUG
274  #define ASSERT(x)
275  #else
276  #define ASSERT(x) ( !!(x) || ( LOGERROR("Assertion failed: %s, file %s, line %i", #x, __FILE__, __LINE__), std::abort(), 0))
277  #endif
278 
279  // Pretty much the same as ASSERT() but stays in Release builds
280  #define VERIFY(x) (!!(x) || ( LOGERROR("Verification failed: %s, file %s, line %i", #x, __FILE__, __LINE__), std::abort(), 0))
281 
282 #endif // else TEST_GLOBALS
283 
284 // Use to mark code that should be impossible to reach.
285 #ifdef NDEBUG
286  #define UNREACHABLE(x) UNREACHABLE_INTRINSIC
287 #else
288  #define UNREACHABLE(x) ( FLOGERROR("Hit unreachable code: {0}, file {1}, line {2}", #x, __FILE__, __LINE__), std::abort(), 0)
289 #endif
290 
291 
292 
293 
294 
295 namespace cpp20
296 {
297  template <class T>
298  std::enable_if_t<std::is_array_v<T> && (std::extent_v<T> == 0), std::unique_ptr<T>> make_unique_for_overwrite(std::size_t a_Size)
299  {
300  return std::unique_ptr<T>(new std::remove_extent_t<T>[a_Size]);
301  }
302 
303  template <class T>
304  std::enable_if_t<!std::is_array_v<T>, std::unique_ptr<T>> make_unique_for_overwrite()
305  {
306  return std::unique_ptr<T>(new T);
307  }
308 }
309 
310 
311 
312 
313 
327 template<class... Ts> struct OverloadedVariantAccess : Ts... { using Ts::operator()...; };
328 template<class... Ts> OverloadedVariantAccess(Ts...)->OverloadedVariantAccess<Ts...>;
329 
330 
331 
332 
333 
335 template <typename T>
336 T Clamp(T a_Value, T a_Min, T a_Max)
337 {
338  return (a_Value < a_Min) ? a_Min : ((a_Value > a_Max) ? a_Max : a_Value);
339 }
340 
341 
342 
343 
344 
346 template <typename C = int, typename T>
347 typename std::enable_if<std::is_arithmetic<T>::value, C>::type FloorC(T a_Value)
348 {
349  return static_cast<C>(std::floor(a_Value));
350 }
351 
353 template <typename C = int, typename T>
354 typename std::enable_if<std::is_arithmetic<T>::value, C>::type CeilC(T a_Value)
355 {
356  return static_cast<C>(std::ceil(a_Value));
357 }
358 
359 
360 
361 
362 
363 // A time duration representing a Minecraft tick (50 ms), capable of storing at least 32'767 ticks.
364 using cTickTime = std::chrono::duration<signed int, std::ratio_multiply<std::chrono::milliseconds::period, std::ratio<50>>>;
365 
366 // A time duration representing a Minecraft tick (50 ms), capable of storing at least a 64 bit signed duration.
367 using cTickTimeLong = std::chrono::duration<signed long long int, cTickTime::period>;
368 
370 constexpr cTickTimeLong operator ""_tick(const unsigned long long a_Ticks)
371 {
372  return cTickTimeLong(a_Ticks);
373 }
374 
375 using ContiguousByteBuffer = std::basic_string<std::byte>;
376 using ContiguousByteBufferView = std::basic_string_view<std::byte>;
377 
378 #ifndef TOLUA_TEMPLATE_BIND
379  #define TOLUA_TEMPLATE_BIND(x)
380 #endif
381 
382 #ifdef TOLUA_EXPOSITION
383  #error TOLUA_EXPOSITION should never actually be defined
384 #endif
385 
386 template <typename T>
387 auto ToUnsigned(T a_Val)
388 {
389  ASSERT(a_Val >= 0);
390  return static_cast<std::make_unsigned_t<T>>(a_Val);
391 }
392 
393 // https://stackoverflow.com/questions/1666802/is-there-a-class-macro-in-c
394 constexpr std::string_view methodName(std::string_view a_PrettyFunction)
395 {
396  size_t Bracket = a_PrettyFunction.rfind("(");
397  size_t Space = a_PrettyFunction.rfind(" ", Bracket) + 1;
398 
399  return a_PrettyFunction.substr(Space, Bracket - Space);
400 }
401 
402 // https://stackoverflow.com/questions/48857887/pretty-function-in-visual-c
403 #if !defined(__PRETTY_FUNCTION__) && !defined(__GNUC__)
404 #define __PRETTY_FUNCTION__ __FUNCSIG__
405 #endif
406 
407 #define __METHOD_NAME__ methodName(__PRETTY_FUNCTION__)
408 
409 // Common headers (part 2, with macros):
410 #include "Vector3.h"
OverloadedVariantAccess(Ts...) -> OverloadedVariantAccess< Ts... >
constexpr std::string_view methodName(std::string_view a_PrettyFunction)
Definition: Globals.h:394
std::chrono::duration< signed long long int, cTickTime::period > cTickTimeLong
Definition: Globals.h:367
Byte ColourID
Definition: Globals.h:162
auto ToUnsigned(T a_Val)
Definition: Globals.h:387
unsigned int UInt32
Definition: Globals.h:157
signed long long Int64
Definition: Globals.h:151
signed short Int16
Definition: Globals.h:153
std::basic_string_view< std::byte > ContiguousByteBufferView
Definition: Globals.h:376
signed char Int8
Definition: Globals.h:154
signed int Int32
Definition: Globals.h:152
T Clamp(T a_Value, T a_Min, T a_Max)
Clamp X to the specified range.
Definition: Globals.h:336
unsigned char UInt8
Definition: Globals.h:159
std::chrono::duration< signed int, std::ratio_multiply< std::chrono::milliseconds::period, std::ratio< 50 > >> cTickTime
Definition: Globals.h:364
unsigned long long UInt64
Definition: Globals.h:156
std::enable_if< std::is_arithmetic< T >::value, C >::type CeilC(T a_Value)
Ceils a value, then casts it to C (an int by default).
Definition: Globals.h:354
#define ASSERT(x)
Definition: Globals.h:276
unsigned short UInt16
Definition: Globals.h:158
std::basic_string< std::byte > ContiguousByteBuffer
Definition: Globals.h:375
std::enable_if< std::is_arithmetic< T >::value, C >::type FloorC(T a_Value)
Floors a value, then casts it to C (an int by default).
Definition: Globals.h:347
unsigned char Byte
Definition: Globals.h:161
eLogLevel
Definition: LoggerSimple.h:6
std::string AString
Definition: StringUtils.h:11
Definition: Globals.h:296
std::enable_if_t<!std::is_array_v< T >, std::unique_ptr< T > > make_unique_for_overwrite()
Definition: Globals.h:304
void LogSimple(std::string_view a_Message, eLogLevel a_LogLevel)
Definition: Logger.cpp:169
void LogFormat(std::string_view a_Format, eLogLevel a_LogLevel, fmt::format_args a_ArgList)
Definition: Logger.cpp:151
void LogPrintf(std::string_view a_Format, eLogLevel a_LogLevel, fmt::printf_args a_ArgList)
Definition: Logger.cpp:160
You can use this struct to use in std::visit example: std::visit( OverloadedVariantAccess { [&] (cFir...
Definition: Globals.h:327