inkcpp
Loading...
Searching...
No Matches
system.h
1/* Copyright (c) 2024 Julian Benda
2 *
3 * This file is part of inkCPP which is released under MIT license.
4 * See file LICENSE.txt or go to
5 * https://github.com/JBenda/inkcpp for full license details.
6 */
7#pragma once
8
9#include "config.h"
10
11#ifdef INK_ENABLE_UNREAL
12# include "Misc/AssertionMacros.h"
13# include "Misc/CString.h"
14# include "HAL/UnrealMemory.h"
15# include "Hash/CityHash.h"
16#endif
17#ifdef INK_ENABLE_STL
18# ifdef INK_ENABLE_EXCEPTIONS
19# include <exception>
20# endif
21# include <stdexcept>
22# include <optional>
23# include <cctype>
24# include <cstdint>
25#endif
26#ifdef INK_ENABLE_CSTD
27# include <cstdio>
28# include <cstdlib>
29# include <ctype.h>
30# include <cassert>
31#endif
32
33// Platform specific defines //
34
35#ifdef INK_ENABLE_UNREAL
36# define inkZeroMemory(buff, len) FMemory::Memset(buff, 0, len)
37# define FORMAT_STRING_STR "%hs"
38#else
39# define inkZeroMemory ink::internal::zero_memory
40# define FORMAT_STRING_STR "%s"
41#endif
42
43#ifdef INK_ENABLE_UNREAL
44# define inkAssert(condition, text, ...) checkf(condition, TEXT(text), ##__VA_ARGS__)
45# define inkFail(text, ...) checkf(false, TEXT(text), ##__VA_ARGS__)
46#else
47# define inkAssert ink::ink_assert
48# define inkFail(...) ink::ink_assert(false, __VA_ARGS__)
49
50#endif
51
52
53namespace ink
54{
58typedef unsigned int uint32_t;
59
60#ifndef INK_ENABLE_STL
61
63typedef int int32_t;
64typedef short int16_t;
65
67typedef unsigned long long uint64_t;
68typedef unsigned short uint16_t;
69#endif // ndef INK_ENABLE_STL
70
73
76
77#ifdef INK_ENABLE_UNREAL
79inline hash_t hash_string(const char* string)
80{
81 return CityHash32(string, FCStringAnsi::Strlen(string));
82}
83#else
84hash_t hash_string(const char* string);
85#endif
86
88typedef unsigned char byte_t;
89
91typedef decltype(static_cast<int*>(nullptr) - static_cast<int*>(nullptr)) ptrdiff_t;
92
94static_assert(sizeof(byte_t) == 1);
95static_assert(sizeof(uint16_t) == 2);
96static_assert(sizeof(int16_t) == 2);
97static_assert(sizeof(uint32_t) == 4);
98static_assert(sizeof(int32_t) == 4);
99static_assert(sizeof(uint64_t) == 8);
100static_assert(sizeof(ptrdiff_t) == sizeof(void*));
101
104
106typedef const unsigned char* ip_t;
107
109typedef unsigned int size_t;
110
113
116
118struct list_flag {
119 int16_t list_id;
120 int16_t flag;
121
122 bool operator==(const list_flag& o) const { return list_id == o.list_id && flag == o.flag; }
123
124 bool operator!=(const list_flag& o) const { return ! (*this == o); }
125};
126
128constexpr list_flag null_flag{-1, -1};
130constexpr list_flag empty_flag{-1, 0};
131
132namespace internal
133{
134#ifdef __GNUC__
135#else
136# pragma warning(push)
137# pragma warning( \
138 disable : 4514, \
139 justification : "functions are defined in header file, they do not need to be used." \
140 )
141#endif
143 static inline constexpr bool starts_with(const char* string, const char* prefix)
144 {
145 while (*prefix) {
146 if (*string != *prefix) {
147 return false;
148 }
149 string++;
150 prefix++;
151 }
152 return true;
153 }
154
156 static inline constexpr bool is_whitespace(const char* string, bool includeNewline = true)
157 {
158 // Iterate string
159 while (true) {
160 switch (*(string++)) {
161 case 0: return true;
162 case '\f': [[fallthrough]];
163 case '\r': [[fallthrough]];
164 case '\n':
165 if (! includeNewline)
166 return false;
167 [[fallthrough]];
168 case '\t': [[fallthrough]];
169 case '\v': [[fallthrough]];
170 case ' ': continue;
171 default: return false;
172 }
173 }
174 }
175
176 inline bool is_part_of_word(char character) { return isalpha(character) || isdigit(character); }
177
178 static inline constexpr bool is_whitespace(char character, bool includeNewline = true)
179 {
180 switch (character) {
181 case '\n':
182 if (! includeNewline)
183 return false;
184 case '\t': [[fallthrough]];
185 case ' ': return true;
186 default: return false;
187 }
188 }
189
190#ifndef INK_ENABLE_UNREAL
192 void zero_memory(void* buffer, size_t length);
193#endif
194#ifdef __GNUC__
195#else
196# pragma warning(pop)
197#endif
198} // namespace internal
199
200#ifdef INK_ENABLE_STL
202using ink_exception = std::runtime_error;
203#else
204// Non-STL exception class
205class ink_exception
206{
207public:
208 ink_exception(const char* msg)
209 : _msg(msg)
210 {
211 }
212
213 inline const char* message() const { return _msg; }
214
215private:
216 const char* _msg;
217};
218#endif
219
220#ifdef __GNUC__
221# pragma GCC diagnostic push
222# pragma GCC diagnostic ignored "-Wunused-parameter"
223#else
224# pragma warning(push)
225# pragma warning( \
226 disable : 4100, \
227 justification : "dependend on rtti, exception and stl support not all arguments are needed" \
228 )
229#endif
230// assert
231template<typename... Args>
232void ink_assert(bool condition, const char* msg = nullptr, Args... args)
233{
234 static const char* EMPTY = "";
235 if (msg == nullptr) {
236 msg = EMPTY;
237 }
238 if (! condition) {
239#if defined(INKCPP_ENABLE_STL) || defined(INKCPP_ENABLE_CSTD)
240 if constexpr (sizeof...(args) > 0) {
241 size_t size = snprintf(nullptr, 0, msg, args...) + 1;
242 char* message = static_cast<char*>(malloc(size));
243 snprintf(message, size, msg, args...);
244 msg = message;
245 } else
246#endif
247 {
248#ifdef INK_ENABLE_EXCEPTIONS
249 throw ink_exception(msg);
250#elif defined(INK_ENABLE_CSTD)
251 fprintf(stderr, "Ink Assert: %s\n", msg);
252 abort();
253#else
254# warning no assertion handling this could lead to invalid code paths
255#endif
256 }
257 }
258}
259#ifdef __GNUC__
260# pragma GCC diagnostic pop
261#else
262# pragma warning(pop)
263#endif
264
265template<typename... Args>
266[[noreturn]] inline void ink_assert(const char* msg = nullptr, Args... args)
267{
268 ink_assert(false, msg, args...);
269#ifdef INK_ENABLE_CSTD
270 exit(EXIT_FAILURE);
271#endif
272}
273
274namespace runtime::internal
275{
276 constexpr unsigned abs(int i) { return static_cast<unsigned>(i < 0 ? -i : i); }
277
278 template<typename T>
279 struct always_false {
280 static constexpr bool value = false;
281 };
282
283 template<bool Con, typename T1, typename T2>
284 struct if_type {
285 using type = T1;
286 };
287
288 template<typename T1, typename T2>
289 struct if_type<false, T1, T2> {
290 using type = T2;
291 };
292
293 template<bool Con, typename T1, typename T2>
294 using if_t = typename if_type<Con, T1, T2>::type;
295
296 template<bool Enable, typename T = void>
297 struct enable_if {
298 };
299
300 template<typename T>
301 struct enable_if<true, T> {
302 using type = T;
303 };
304
305 template<bool Enable, typename T = void>
306 using enable_if_t = typename enable_if<Enable, T>::type;
307} // namespace runtime::internal
308
309
310#ifdef INK_ENABLE_STL
314template<typename T>
315using optional = std::optional<T>;
317constexpr std::nullopt_t nullopt = std::nullopt;
318#else
319struct nullopt_t {
320};
321
322constexpr nullopt_t nullopt;
323
324template<typename T>
325class optional
326{
327public:
328 optional() {}
329
330 optional(nullopt_t) {}
331
332 optional(T&& val)
333 : _has_value{true}
334 , _value{val}
335 {
336 }
337
338 optional(const T& val)
339 : _has_value{true}
340 , _value{val}
341 {
342 }
343
344 const T& operator*() const { return value(); }
345
346 T& operator*() { return value(); }
347
348 const T* operator->() const { return &value(); }
349
350 T* operator->() { return &value(); }
351
352 constexpr bool has_value() const { return _has_value; }
353
354 constexpr T& value()
355 {
356 test_value();
357 return _value;
358 }
359
360 constexpr const T& value() const
361 {
362 test_value();
363 return _value;
364 }
365
366 constexpr operator bool() const { return has_value(); }
367
368 template<typename U>
369 constexpr T value_or(U&& u) const
370 {
371 return _has_value ? _value : static_cast<T>(u);
372 }
373
374 template<typename... Args>
375 T& emplace(Args... args)
376 {
377 if (_has_value)
378 _value.~T();
379
380 new (&_value) T(args...);
381 _has_value = true;
382 return _value;
383 }
384
385private:
386 void test_value() const
387 {
388 if (! _has_value) {
389 inkFail("Can't access empty optional!");
390 }
391 }
392
393 bool _has_value = false;
394 T _value;
395};
396#endif
397} // namespace ink
Namespace contaning all modules and classes from InkCPP.
Definition choice.h:11
constexpr list_flag null_flag
value of an unset list_flag
Definition system.h:128
unsigned int uint32_t
define basic numeric type
Definition system.h:58
std::optional< T > optional
custom optional implementation for usage if STL is disabled
Definition system.h:315
const hash_t InvalidHash
Invalid hash value.
Definition system.h:75
uint32_t container_t
Used as the unique identifier for an ink container.
Definition system.h:112
unsigned char byte_t
Byte type.
Definition system.h:88
unsigned int size_t
Used for the size of arrays.
Definition system.h:109
uint32_t offset_t
Verify sizes.
Definition system.h:103
constexpr std::nullopt_t nullopt
an empty optional
Definition system.h:317
std::runtime_error ink_exception
exception type thrown if something goes wrong
Definition system.h:202
uint32_t thread_t
Used to uniquely identify threads.
Definition system.h:115
decltype(static_cast< int * >(nullptr) - static_cast< int * >(nullptr)) ptrdiff_t
Ptr difference type.
Definition system.h:91
constexpr list_flag empty_flag
value representing an empty list
Definition system.h:130
hash_t hash_string(const char *string)
Simple hash for serialization of strings.
Definition system.h:79
const unsigned char * ip_t
Instruction pointer used for addressing within the story instructions.
Definition system.h:106
uint32_t hash_t
Name hash (used for temporary variables)
Definition system.h:72