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
56
57#ifdef INK_ENABLE_UNREAL
58# define inkAssert(condition, text, ...) checkf(condition, TEXT(text), ##__VA_ARGS__)
59# define inkFail(text, ...) checkf(false, TEXT(text), ##__VA_ARGS__)
60#else
61# define inkAssert(...) ink::ink_assert(__VA_ARGS__)
62# define inkFail(...) ink::ink_assert(false, __VA_ARGS__)
63#endif
64
65
66namespace ink
67{
71typedef unsigned int uint32_t;
72
73#ifndef INK_ENABLE_STL
74
76typedef int int32_t;
77typedef short int16_t;
78
80typedef unsigned long long uint64_t;
81typedef unsigned short uint16_t;
82#endif // ndef INK_ENABLE_STL
83
86
89
90
92typedef unsigned char byte_t;
93
95typedef decltype(static_cast<int*>(nullptr) - static_cast<int*>(nullptr)) ptrdiff_t;
96
98static_assert(sizeof(byte_t) == 1);
99static_assert(sizeof(uint16_t) == 2);
100static_assert(sizeof(int16_t) == 2);
101static_assert(sizeof(uint32_t) == 4);
102static_assert(sizeof(int32_t) == 4);
103static_assert(sizeof(uint64_t) == 8);
104static_assert(sizeof(ptrdiff_t) == sizeof(void*));
105
108
110typedef const unsigned char* ip_t;
111
113typedef unsigned int size_t;
114
117
120
122struct list_flag {
123 int16_t list_id;
124 int16_t flag;
125
126 bool operator==(const list_flag& o) const { return list_id == o.list_id && flag == o.flag; }
127
128 bool operator!=(const list_flag& o) const { return ! (*this == o); }
129};
130
132constexpr list_flag null_flag{-1, -1};
134constexpr list_flag empty_flag{-1, 0};
135
136#ifdef INK_ENABLE_UNREAL
138inline hash_t hash_string(const char* string)
139{
140 return CityHash32(string, FCStringAnsi::Strlen(string));
141}
142
144inline hash_t hash_data(const unsigned char* data, size_t len)
145{
146 return CityHash32(reinterpret_cast<const char*>(data), len);
147}
148#else
149hash_t hash_string(const char* string);
150hash_t hash_data(const unsigned char* data, size_t len);
151#endif
152
153namespace internal
154{
155#ifdef __GNUC__
156#else
157# pragma warning(push)
158// functions are defined in header file, they do not need to be used.
159# pragma warning(disable : 4514)
160#endif
162 static inline constexpr bool starts_with(const char* string, const char* prefix)
163 {
164 while (*prefix) {
165 if (*string != *prefix) {
166 return false;
167 }
168 string++;
169 prefix++;
170 }
171 return true;
172 }
173
175 static inline constexpr bool is_whitespace(const char* string, bool includeNewline = true)
176 {
177 // Iterate string
178 while (true) {
179 switch (*(string++)) {
180 case 0: return true;
181 case '\f': [[fallthrough]];
182 case '\r': [[fallthrough]];
183 case '\n':
184 if (! includeNewline)
185 return false;
186 [[fallthrough]];
187 case '\t': [[fallthrough]];
188 case '\v': [[fallthrough]];
189 case ' ': continue;
190 default: return false;
191 }
192 }
193 }
194
195 inline bool is_part_of_word(char character) { return isalpha(character) || isdigit(character); }
196
197 static inline constexpr bool is_whitespace(char character, bool includeNewline = true)
198 {
199 switch (character) {
200 case '\n':
201 if (! includeNewline)
202 return false;
203 case '\t': [[fallthrough]];
204 case ' ': return true;
205 default: return false;
206 }
207 }
208
209#ifndef INK_ENABLE_UNREAL
211 void zero_memory(void* buffer, size_t length);
212#endif
213#ifdef __GNUC__
214#else
215# pragma warning(pop)
216#endif
217} // namespace internal
218
219#ifdef INK_ENABLE_STL
221using ink_exception = std::runtime_error;
222#else
223// Non-STL exception class
224class ink_exception
225{
226public:
227 ink_exception(const char* msg)
228 : _msg(msg)
229 {
230 }
231
232 inline const char* message() const { return _msg; }
233
234private:
235 const char* _msg;
236};
237#endif
238
239#ifdef __GNUC__
240# pragma GCC diagnostic push
241# pragma GCC diagnostic ignored "-Wunused-parameter"
242#else
243# pragma warning(push)
244// dependend on rtti, exception and stl support not all arguments are needed
245# pragma warning(disable : 4100)
246#endif
249template<typename... Args>
250void ink_assert(bool condition, const char* msg = nullptr, Args... args)
251{
252 static const char* EMPTY = "";
253 if (msg == nullptr) {
254 msg = EMPTY;
255 }
256 if (! condition) {
257#if defined(INK_ENABLE_STL) || defined(INK_ENABLE_CSTD)
258 if constexpr (sizeof...(args) > 0) {
259 size_t size = snprintf(nullptr, 0, msg, args...) + 1;
260 char* message = static_cast<char*>(malloc(size));
261 snprintf(message, size, msg, args...);
262 msg = message;
263 }
264#endif
265#ifdef INK_ENABLE_EXCEPTIONS
266 throw ink_exception(msg);
267#elif defined(INK_ENABLE_CSTD)
268 fprintf(stderr, "Ink Assert: %s\n", msg);
269 abort();
270#elif defined(INK_ENABLE_UNREAL)
271 // TODO: implement UE exception handling
272#else
273# warning no assertion handling this could lead to invalid code paths
274#endif
275 }
276}
277#ifdef __GNUC__
278# pragma GCC diagnostic pop
279#else
280# pragma warning(pop)
281#endif
282
285template<typename... Args>
286[[noreturn]] inline void ink_assert(const char* msg = nullptr, Args... args)
287{
288 ink_assert(false, msg, args...);
289#ifdef INK_ENABLE_CSTD
290 exit(EXIT_FAILURE);
291#endif
292}
293
294namespace runtime::internal
295{
296 constexpr unsigned abs(int i) { return static_cast<unsigned>(i < 0 ? -i : i); }
297
298 template<typename T>
299 struct always_false {
300 static constexpr bool value = false;
301 };
302
303 template<bool Con, typename T1, typename T2>
304 struct if_type {
305 using type = T1;
306 };
307
308 template<typename T1, typename T2>
309 struct if_type<false, T1, T2> {
310 using type = T2;
311 };
312
313 template<bool Con, typename T1, typename T2>
314 using if_t = typename if_type<Con, T1, T2>::type;
315
316 template<bool Enable, typename T = void>
317 struct enable_if {
318 };
319
320 template<typename T>
321 struct enable_if<true, T> {
322 using type = T;
323 };
324
325 template<bool Enable, typename T = void>
326 using enable_if_t = typename enable_if<Enable, T>::type;
327} // namespace runtime::internal
328
329
330#ifdef INK_ENABLE_STL
334template<typename T>
335using optional = std::optional<T>;
337constexpr std::nullopt_t nullopt = std::nullopt;
338#else
339struct nullopt_t {
340};
341
342constexpr nullopt_t nullopt;
343
344template<typename T>
345class optional
346{
347public:
348 optional() {}
349
350 optional(nullopt_t) {}
351
352 optional(T&& val)
353 : _has_value{true}
354 , _value{val}
355 {
356 }
357
358 optional(const T& val)
359 : _has_value{true}
360 , _value{val}
361 {
362 }
363
364 const T& operator*() const { return value(); }
365
366 T& operator*() { return value(); }
367
368 const T* operator->() const { return &value(); }
369
370 T* operator->() { return &value(); }
371
372 constexpr bool has_value() const { return _has_value; }
373
374 constexpr T& value()
375 {
376 test_value();
377 return _value;
378 }
379
380 constexpr const T& value() const
381 {
382 test_value();
383 return _value;
384 }
385
386 constexpr operator bool() const { return has_value(); }
387
388 template<typename U>
389 constexpr T value_or(U&& u) const
390 {
391 return _has_value ? _value : static_cast<T>(u);
392 }
393
394 template<typename... Args>
395 T& emplace(Args... args)
396 {
397 if (_has_value)
398 _value.~T();
399
400 new (&_value) T(args...);
401 _has_value = true;
402 return _value;
403 }
404
405private:
406 void test_value() const
407 {
408 if (! _has_value) {
409 inkFail("Can't access empty optional!");
410 }
411 }
412
413 bool _has_value = false;
414 T _value;
415};
416#endif
417} // namespace ink
#define inkFail(text,...)
Compile argument agnostic assert macro (always asserts).
Definition system.h:59
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:132
unsigned int uint32_t
define basic numeric type
Definition system.h:71
std::optional< T > optional
custom optional implementation for usage if STL is disabled
Definition system.h:335
const hash_t InvalidHash
Invalid hash value.
Definition system.h:88
uint32_t container_t
Used as the unique identifier for an ink container.
Definition system.h:116
void ink_assert(bool condition, const char *msg=nullptr, Args... args)
Assert helper, not to be used directly, please use inkAssert and inkFail to be enviroment agnostic.
Definition system.h:250
unsigned char byte_t
Byte type.
Definition system.h:92
unsigned int size_t
Used for the size of arrays.
Definition system.h:113
uint32_t offset_t
Verify sizes.
Definition system.h:107
hash_t hash_data(const unsigned char *data, size_t len)
Simple hash for detcting changes in binary data.
Definition system.h:144
constexpr std::nullopt_t nullopt
an empty optional
Definition system.h:337
std::runtime_error ink_exception
exception type thrown if something goes wrong
Definition system.h:221
uint32_t thread_t
Used to uniquely identify threads.
Definition system.h:119
decltype(static_cast< int * >(nullptr) - static_cast< int * >(nullptr)) ptrdiff_t
Ptr difference type.
Definition system.h:95
constexpr list_flag empty_flag
value representing an empty list
Definition system.h:134
hash_t hash_string(const char *string)
Simple hash for serialization of strings.
Definition system.h:138
const unsigned char * ip_t
Instruction pointer used for addressing within the story instructions.
Definition system.h:110
uint32_t hash_t
Name hash (used for temporary variables).
Definition system.h:85