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# include <cstdio>
26# include <cstdarg>
27#endif
28#ifdef INK_ENABLE_CSTD
29# include <ctype.h>
30#endif
31
32// Platform specific defines //
33
34#ifdef INK_ENABLE_UNREAL
35# define inkZeroMemory(buff, len) FMemory::Memset(buff, 0, len)
36# define FORMAT_STRING_STR "%hs"
37#else
38# define inkZeroMemory ink::internal::zero_memory
39# define FORMAT_STRING_STR "%s"
40#endif
41
42#ifdef INK_ENABLE_UNREAL
43# define inkAssert(condition, text, ...) checkf(condition, TEXT(text), ##__VA_ARGS__)
44# define inkFail(text, ...) checkf(false, TEXT(text), ##__VA_ARGS__)
45#else
46# define inkAssert ink::ink_assert
47# define inkFail(...) ink::ink_assert(false, __VA_ARGS__)
48#endif
49
50namespace ink
51{
55typedef unsigned int uint32_t;
56
57#ifndef INK_ENABLE_STL
58
60typedef int int32_t;
61typedef short int16_t;
62
64typedef unsigned long long uint64_t;
65typedef unsigned short uint16_t;
66#endif // ndef INK_ENABLE_STL
67
70
73
74#ifdef INK_ENABLE_UNREAL
76inline hash_t hash_string(const char* string)
77{
78 return CityHash32(string, FCStringAnsi::Strlen(string));
79}
80#else
81hash_t hash_string(const char* string);
82#endif
83
85typedef unsigned char byte_t;
86
88typedef decltype(static_cast<int*>(nullptr) - static_cast<int*>(nullptr)) ptrdiff_t;
89
91static_assert(sizeof(byte_t) == 1);
92static_assert(sizeof(uint16_t) == 2);
93static_assert(sizeof(int16_t) == 2);
94static_assert(sizeof(uint32_t) == 4);
95static_assert(sizeof(int32_t) == 4);
96static_assert(sizeof(uint64_t) == 8);
97static_assert(sizeof(ptrdiff_t) == sizeof(void*));
98
101
103typedef const unsigned char* ip_t;
104
106typedef unsigned int size_t;
107
110
113
115struct list_flag {
116 int16_t list_id;
117 int16_t flag;
118
119 bool operator==(const list_flag& o) const { return list_id == o.list_id && flag == o.flag; }
120
121 bool operator!=(const list_flag& o) const { return ! (*this == o); }
122};
123
125constexpr list_flag null_flag{-1, -1};
127constexpr list_flag empty_flag{-1, 0};
128
129namespace internal
130{
131#ifdef __GNUC__
132#else
133# pragma warning(push)
134# pragma warning( \
135 disable : 4514, \
136 justification : "functions are defined in header file, they do not need to be used." \
137 )
138#endif
140 static inline constexpr bool starts_with(const char* string, const char* prefix)
141 {
142 while (*prefix) {
143 if (*string != *prefix) {
144 return false;
145 }
146 string++;
147 prefix++;
148 }
149 return true;
150 }
151
153 static inline constexpr bool is_whitespace(const char* string, bool includeNewline = true)
154 {
155 // Iterate string
156 while (true) {
157 switch (*(string++)) {
158 case 0: return true;
159 case '\n':
160 if (! includeNewline)
161 return false;
162 [[fallthrough]];
163 case '\t': [[fallthrough]];
164 case ' ': continue;
165 default: return false;
166 }
167 }
168 }
169
173 static inline bool is_part_of_word(char character)
174 {
175 return isalpha(character) || isdigit(character);
176 }
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_EXCEPTIONS
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// assert
221#ifndef INK_ENABLE_UNREAL
222template<typename... Args>
223void ink_assert(bool condition, const char* msg = nullptr, Args... args)
224{
225 static const char* EMPTY = "";
226 if (msg == nullptr) {
227 msg = EMPTY;
228 }
229 if (! condition) {
230 if constexpr (sizeof...(args) > 0) {
231 size_t size = snprintf(nullptr, 0, msg, args...) + 1;
232 char* message = static_cast<char*>(malloc(size));
233 snprintf(message, size, msg, args...);
234 msg = message;
235 }
236
237# ifdef INK_ENABLE_EXCEPTIONS
238 throw ink_exception(msg);
239# elif defined(INK_ENABLE_CSTD)
240 fprintf(stderr, "Ink Assert: %s\n", msg);
241 abort();
242# else
243# error "This path needs a way to warn and then terminate, otherwise it'll silently fail"
244# endif
245 }
246}
247
248template<typename... Args>
249[[noreturn]] inline void ink_assert(const char* msg = nullptr, Args... args)
250{
251 ink_assert(false, msg, args...);
252 exit(EXIT_FAILURE);
253}
254#endif
255
256namespace runtime::internal
257{
258 constexpr unsigned abs(int i) { return static_cast<unsigned>(i < 0 ? -i : i); }
259
260 template<typename T>
261 struct always_false {
262 static constexpr bool value = false;
263 };
264
265 template<bool Con, typename T1, typename T2>
266 struct if_type {
267 using type = T1;
268 };
269
270 template<typename T1, typename T2>
271 struct if_type<false, T1, T2> {
272 using type = T2;
273 };
274
275 template<bool Con, typename T1, typename T2>
276 using if_t = typename if_type<Con, T1, T2>::type;
277
278 template<bool Enable, typename T = void>
279 struct enable_if {
280 };
281
282 template<typename T>
283 struct enable_if<true, T> {
284 using type = T;
285 };
286
287 template<bool Enable, typename T = void>
288 using enable_if_t = typename enable_if<Enable, T>::type;
289} // namespace runtime::internal
290
291
292#ifdef INK_ENABLE_STL
296template<typename T>
297using optional = std::optional<T>;
299constexpr std::nullopt_t nullopt = std::nullopt;
300#else
301struct nullopt_t {
302};
303
304constexpr nullopt_t nullopt;
305
306template<typename T>
307class optional
308{
309public:
310 optional() {}
311
312 optional(nullopt_t) {}
313
314 optional(T&& val)
315 : _has_value{true}
316 , _value{val}
317 {
318 }
319
320 optional(const T& val)
321 : _has_value{true}
322 , _value{val}
323 {
324 }
325
326 const T& operator*() const { return value(); }
327
328 T& operator*() { return value(); }
329
330 const T* operator->() const { return &value(); }
331
332 T* operator->() { return &value(); }
333
334 constexpr bool has_value() const { return _has_value; }
335
336 constexpr T& value()
337 {
338 test_value();
339 return _value;
340 }
341
342 constexpr const T& value() const
343 {
344 test_value();
345 return _value;
346 }
347
348 constexpr operator bool() const { return has_value(); }
349
350 template<typename U>
351 constexpr T value_or(U&& u) const
352 {
353 return _has_value ? _value : static_cast<T>(u);
354 }
355
356 template<typename... Args>
357 T& emplace(Args... args)
358 {
359 if (_has_value)
360 _value.~T();
361
362 new (&_value) T(args...);
363 _has_value = true;
364 return _value;
365 }
366
367private:
368 void test_value() const
369 {
370 if (! _has_value) {
371 inkFail("Can't access empty optional!");
372 }
373 }
374
375 bool _has_value = false;
376 T _value;
377};
378#endif
379} // 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:125
unsigned int uint32_t
define basic numeric type
Definition system.h:55
std::optional< T > optional
custom optional implementation for usage if STL is disabled
Definition system.h:297
const hash_t InvalidHash
Invalid hash value.
Definition system.h:72
uint32_t container_t
Used as the unique identifier for an ink container.
Definition system.h:109
unsigned char byte_t
Byte type.
Definition system.h:85
unsigned int size_t
Used for the size of arrays.
Definition system.h:106
uint32_t offset_t
Verify sizes.
Definition system.h:100
constexpr std::nullopt_t nullopt
an empty optional
Definition system.h:299
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:112
decltype(static_cast< int * >(nullptr) - static_cast< int * >(nullptr)) ptrdiff_t
Ptr difference type.
Definition system.h:88
constexpr list_flag empty_flag
value representing an empty list
Definition system.h:127
hash_t hash_string(const char *string)
Simple hash for serialization of strings.
Definition system.h:76
const unsigned char * ip_t
Instruction pointer used for addressing within the story instructions.
Definition system.h:103
uint32_t hash_t
Name hash (used for temporary variables)
Definition system.h:69