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
17#endif
18#ifdef INK_ENABLE_STL
19# include <exception>
20# include <stdexcept>
21# include <optional>
22# include <cctype>
23# include <cstdint>
24# include <cstdio>
25# include <cstdarg>
26#endif
27
28// Platform specific defines //
29
30#ifdef INK_ENABLE_UNREAL
31# define inkZeroMemory(buff, len) FMemory::Memset(buff, 0, len)
32# define inkAssert(condition, text, ...) checkf(condition, TEXT(text), ##__VA_ARGS__)
33# define inkFail(text, ...) checkf(false, TEXT(text), ##__VA_ARGS__)
34# define FORMAT_STRING_STR "%hs"
35#else
36# define inkZeroMemory ink::internal::zero_memory
37# define inkAssert ink::ink_assert
38# define inkFail(...) ink::ink_assert(false, __VA_ARGS__)
39# define FORMAT_STRING_STR "%s"
40#endif
41
42namespace ink
43{
47typedef unsigned int uint32_t;
48
51
54
55#ifdef INK_ENABLE_UNREAL
57inline hash_t hash_string(const char* string)
58{
59 return CityHash32(string, FCStringAnsi::Strlen(string));
60}
61#else
62hash_t hash_string(const char* string);
63#endif
64
66typedef unsigned char byte_t;
67
70
72typedef const unsigned char* ip_t;
73
75typedef unsigned int size_t;
76
79
82
84struct list_flag {
85 int16_t list_id;
86 int16_t flag;
87
88 bool operator==(const list_flag& o) const { return list_id == o.list_id && flag == o.flag; }
89
90 bool operator!=(const list_flag& o) const { return ! (*this == o); }
91};
92
94constexpr list_flag null_flag{-1, -1};
96constexpr list_flag empty_flag{-1, 0};
97
98namespace internal
99{
101 static bool starts_with(const char* string, const char* prefix)
102 {
103 while (*prefix) {
104 if (*string != *prefix) {
105 return false;
106 }
107 string++;
108 prefix++;
109 }
110 return true;
111 }
112
114 static bool is_whitespace(const char* string, bool includeNewline = true)
115 {
116 // Iterate string
117 while (true) {
118 switch (*(string++)) {
119 case 0: return true;
120 case '\n':
121 if (! includeNewline)
122 return false;
123 case '\t': [[fallthrough]];
124 case ' ': continue;
125 default: return false;
126 }
127 }
128 }
129
133 inline bool is_part_of_word(char character) { return isalpha(character) || isdigit(character); }
134
135 inline constexpr bool is_whitespace(char character, bool includeNewline = true)
136 {
137 switch (character) {
138 case '\n':
139 if (! includeNewline)
140 return false;
141 case '\t': [[fallthrough]];
142 case ' ': return true;
143 default: return false;
144 }
145 }
146
147#ifndef INK_ENABLE_UNREAL
149 void zero_memory(void* buffer, size_t length);
150#endif
151} // namespace internal
152
153#ifdef INK_ENABLE_STL
155using ink_exception = std::runtime_error;
156#else
157// Non-STL exception class
158class ink_exception
159{
160public:
161 ink_exception(const char* msg)
162 : _msg(msg)
163 {
164 }
165
166 inline const char* message() const { return _msg; }
167
168private:
169 const char* _msg;
170};
171#endif
172
173// assert
174#ifndef INK_ENABLE_UNREAL
175template<typename... Args>
176void ink_assert(bool condition, const char* msg = nullptr, Args... args)
177{
178 static const char* EMPTY = "";
179 if (msg == nullptr) {
180 msg = EMPTY;
181 }
182 if (! condition) {
183 if constexpr (sizeof...(args) > 0) {
184 size_t size = snprintf(nullptr, 0, msg, args...) + 1;
185 char* message = static_cast<char*>(malloc(size));
186 snprintf(message, size, msg, args...);
187 throw ink_exception(message);
188 } else {
189 throw ink_exception(msg);
190 }
191 }
192}
193
194template<typename... Args>
195[[noreturn]] inline void ink_assert(const char* msg = nullptr, Args... args)
196{
197 ink_assert(false, msg, args...);
198 exit(EXIT_FAILURE);
199}
200#endif
201
202namespace runtime::internal
203{
204 constexpr unsigned abs(int i) { return i < 0 ? -i : i; }
205
206 template<typename T>
207 struct always_false {
208 static constexpr bool value = false;
209 };
210
211 template<bool Con, typename T1, typename T2>
212 struct if_type {
213 using type = T1;
214 };
215
216 template<typename T1, typename T2>
217 struct if_type<false, T1, T2> {
218 using type = T2;
219 };
220
221 template<bool Con, typename T1, typename T2>
222 using if_t = typename if_type<Con, T1, T2>::type;
223
224 template<bool Enable, typename T = void>
225 struct enable_if {
226 };
227
228 template<typename T>
229 struct enable_if<true, T> {
230 using type = T;
231 };
232
233 template<bool Enable, typename T = void>
234 using enable_if_t = typename enable_if<Enable, T>::type;
235} // namespace runtime::internal
236
237
238#ifdef INK_ENABLE_STL
242template<typename T>
243using optional = std::optional<T>;
245constexpr std::nullopt_t nullopt = std::nullopt;
246#else
247struct nullopt_t {
248};
249
250constexpr nullopt_t nullopt;
251
252template<typename T>
253class optional
254{
255public:
256 optional() {}
257
258 optional(nullopt_t) {}
259
260 optional(T&& val)
261 : _has_value{true}
262 , _value{val}
263 {
264 }
265
266 optional(const T& val)
267 : _has_value{true}
268 , _value{val}
269 {
270 }
271
272 const T& operator*() const { return _value; }
273
274 T& operator*() { return _value; }
275
276 const T* operator->() const { return &_value; }
277
278 T* operator->() { return &_value; }
279
280 constexpr bool has_value() const { return _has_value; }
281
282 constexpr T& value()
283 {
284 test_value();
285 return _value;
286 }
287
288 constexpr const T& value() const
289 {
290 test_value();
291 return _value;
292 }
293
294 constexpr operator bool() const { return has_value(); }
295
296 template<typename U>
297 constexpr T value_or(U&& u) const
298 {
299 return _has_value ? _value : static_cast<T>(u);
300 }
301
302 template<typename... Args>
303 T& emplace(Args... args)
304 {
305 _value.~T();
306 return *(new (&_value) T(args...));
307 }
308
309private:
310 void test_value() const
311 {
312 if (! _has_value) {
313 inkFail("Can't access empty optional!");
314 }
315 }
316
317 bool _has_value = false;
318 T _value;
319};
320#endif
321} // 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:94
unsigned int uint32_t
define basic numeric type
Definition system.h:47
std::optional< T > optional
custom optional implementation for usage if STL is disabled
Definition system.h:243
const hash_t InvalidHash
Invalid hash value.
Definition system.h:53
uint32_t container_t
Used as the unique identifier for an ink container.
Definition system.h:78
unsigned char byte_t
Byte type.
Definition system.h:66
unsigned int size_t
Used for the size of arrays.
Definition system.h:75
uint32_t offset_t
Used to identify an offset in a data table (like a string in the string table)
Definition system.h:69
constexpr std::nullopt_t nullopt
an empty optional
Definition system.h:245
std::runtime_error ink_exception
exception type thrown if something goes wrong
Definition system.h:155
uint32_t thread_t
Used to uniquely identify threads.
Definition system.h:81
constexpr list_flag empty_flag
value representing an empty list
Definition system.h:96
hash_t hash_string(const char *string)
Simple hash for serialization of strings.
Definition system.h:57
const unsigned char * ip_t
Instruction pointer used for addressing within the story instructions.
Definition system.h:72
uint32_t hash_t
Name hash (used for temporary variables)
Definition system.h:50