kerep-headers
This commit is contained in:
17
kerep-headers/base/base.h
Normal file
17
kerep-headers/base/base.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "std.h"
|
||||
#include "errors.h"
|
||||
#include "cptr.h"
|
||||
#include "optime.h"
|
||||
#include "type_system/type_system.h"
|
||||
#include "../kprint/kprintf.h"
|
||||
#include "endian.h"
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
94
kerep-headers/base/cptr.h
Normal file
94
kerep-headers/base/cptr.h
Normal file
@@ -0,0 +1,94 @@
|
||||
#pragma once
|
||||
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "std.h"
|
||||
|
||||
// returns length of char buffer (without \0)
|
||||
u32 cptr_length(const char* str);
|
||||
|
||||
// allocates new char[] and copies src there
|
||||
char* cptr_copy(const char* src);
|
||||
|
||||
bool cptr_equals(const char* key0, const char* key1);
|
||||
|
||||
bool cptr_startsWith(const char* src, const char* fragment);
|
||||
|
||||
bool cptr_endsWith(const char* src, const char* fragment);
|
||||
|
||||
// multiplies char n times
|
||||
char* char_multiply(char c, u32 n);
|
||||
|
||||
/// @param startIndex 0 ... src length
|
||||
/// @param seekLength 0 ... -1
|
||||
/// @return pos of first <fragment> inclusion in <src> or -1 if not found
|
||||
i32 cptr_seek(const char* src, const char* fragment, u32 startIndex, u32 seekLength);
|
||||
|
||||
/// @param startIndex -1 ... src length
|
||||
/// @param seekLength 0 ... -1
|
||||
/// @return pos of first <fragment> inclusion in <src> or -1 if not found
|
||||
i32 cptr_seekReverse(const char* src, const char* fragment, u32 startIndex, u32 seekLength);
|
||||
|
||||
/// @param startIndex 0 ... src length
|
||||
/// @param seekLength 0 ... -1
|
||||
/// @return pos of first <fragment> inclusion in <src> or -1 if not found
|
||||
i32 cptr_seekChar(const char* src, char fragment, u32 startIndex, u32 seekLength);
|
||||
|
||||
/// @param startIndex -1 ... src length
|
||||
/// @param seekLength 0 ... -1
|
||||
/// @return pos of first <fragment> inclusion in <src> or -1 if not found
|
||||
i32 cptr_seekCharReverse(const char* src, char fragment, u32 startIndex, u32 seekLength);
|
||||
|
||||
/// @brief search for <fragment> in <ptr>
|
||||
/// @return index of first <fragment> inclusion or -1 if not found
|
||||
static inline i32 cptr_indexOf(const char* src, const char* fragment)
|
||||
{ return cptr_seek(src, fragment, 0, -1); }
|
||||
|
||||
/// @brief search for <fragment> in <ptr>
|
||||
/// @return index of first <fragment> inclusion or -1 if not found
|
||||
static inline i32 cptr_indexOfChar(const char* src, char fragment)
|
||||
{ return cptr_seekChar(src, fragment, 0, -1); }
|
||||
|
||||
/// @brief search for <fragment> in <ptr>
|
||||
/// @return index of last <fragment> inclusion or -1 if not found
|
||||
static inline i32 cptr_lastIndexOf(const char* src, const char* fragment)
|
||||
{ return cptr_seekReverse(src, fragment, -1, -1); }
|
||||
|
||||
/// @brief search for <fragment> in <ptr>
|
||||
/// @return index of last <fragment> inclusion or -1 if not found
|
||||
static inline i32 cptr_lastIndexOfChar(const char* src, char fragment)
|
||||
{ return cptr_seekCharReverse(src, fragment, -1, -1); }
|
||||
|
||||
|
||||
static inline bool cptr_contains(const char* src, const char* fragment){
|
||||
return cptr_seek(src, fragment, 0, -1) +1;
|
||||
}
|
||||
|
||||
void memcopy(void* from, void* to, u32 size);
|
||||
|
||||
char* __cptr_concat(u32 n, ...);
|
||||
#define cptr_concat(STR...) __cptr_concat(count_args(STR), STR)
|
||||
|
||||
char* cptr_toLower(const char* src);
|
||||
char* cptr_toUpper(const char* src);
|
||||
|
||||
/// @param startIndex 0 ... src length
|
||||
/// @param seekLength 0 ... -1
|
||||
/// @return <src> with <str_old> replaced by <str_new> or empty cstring if <str_old> not found
|
||||
char* cptr_replaceIn(const char* src, const char* str_old, const char* str_new, u32 startIndex, u32 seekLength);
|
||||
/// @param startIndex 0 ... src length
|
||||
/// @param seekLength 0 ... -1
|
||||
/// @return <src> with <c_old> replaced by <c_new> or empty cstring if <str_old> not found
|
||||
char* cptr_replaceCharIn(const char* src, char c_old, char c_new, u32 startIndex, u32 seekLength);
|
||||
|
||||
static inline char* cptr_replace(const char* src, const char* str_old, const char* str_new)
|
||||
{ return cptr_replaceIn(src, str_old, str_new, 0, -1); }
|
||||
|
||||
static inline char* cptr_replaceChar(const char* src, char c_old, char c_new)
|
||||
{ return cptr_replaceCharIn(src, c_old, c_new, 0, -1); }
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
20
kerep-headers/base/endian.h
Normal file
20
kerep-headers/base/endian.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "std.h"
|
||||
#include "type_system/typedef_macros.h"
|
||||
|
||||
PACKED_ENUM(Endian,
|
||||
UnknownEndian=0,
|
||||
LittleEndian=1,
|
||||
BigEndian=2
|
||||
)
|
||||
|
||||
Endian getEndian();
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
90
kerep-headers/base/errors.h
Normal file
90
kerep-headers/base/errors.h
Normal file
@@ -0,0 +1,90 @@
|
||||
#pragma once
|
||||
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "std.h"
|
||||
#include "type_system/type_system.h"
|
||||
|
||||
PACKED_ENUM(ErrorId,
|
||||
SUCCESS, // not an error
|
||||
ERR_MAXLENGTH, ERR_WRONGTYPE, ERR_WRONGINDEX,
|
||||
ERR_NOTIMPLEMENTED, ERR_NULLPTR, ERR_ENDOFSTR,
|
||||
ERR_KEYNOTFOUND, ERR_FORMAT, ERR_UNEXPECTEDVAL,
|
||||
ERR_IO, ERR_IO_EOF
|
||||
)
|
||||
|
||||
char* errname(ErrorId err);
|
||||
|
||||
char* __genErrMsg(const char* errmsg, const char* srcfile, i32 line, const char* funcname);
|
||||
char* __extendErrMsg(const char* errmsg, const char* srcfile, i32 line, const char* funcname);
|
||||
|
||||
STRUCT(Maybe,
|
||||
Unitype value;
|
||||
char* errmsg;
|
||||
)
|
||||
|
||||
// return it if func doesn't return anything
|
||||
// .value .errmsg
|
||||
#define MaybeNull (Maybe){UniNull, NULL}
|
||||
|
||||
void Maybe_free(Maybe e);
|
||||
void printMaybe(Maybe e);
|
||||
|
||||
|
||||
#define SUCCESS(REZLT) (Maybe){.errmsg=NULL, .value=REZLT}
|
||||
|
||||
#define __RETURN_EXCEPTION(ERRMSG) return (Maybe){.value=UniNull, .errmsg=ERRMSG}
|
||||
|
||||
#define __EXIT(ERRMSG) ({ kprintf("\e[91m%s\e[0m \n", ERRMSG); free(ERRMSG); exit(128); })
|
||||
|
||||
char* __doNothing(char* a);
|
||||
char* __unknownErr( );
|
||||
|
||||
#define __stringify_err(E) _Generic( \
|
||||
(E), \
|
||||
char*: __doNothing, \
|
||||
int: errname, \
|
||||
default: __unknownErr \
|
||||
)(E)
|
||||
|
||||
#if __cplusplus
|
||||
#define throw_id(E) __EXIT(((char*)__genErrMsg(errname(E), __FILE__,__LINE__,__func__)))
|
||||
#define throw_msg(E) __EXIT(((char*)__genErrMsg(E, __FILE__,__LINE__,__func__)))
|
||||
|
||||
#define safethrow_id(E, FREEMEM) { FREEMEM; \
|
||||
__RETURN_EXCEPTION(((char*)__genErrMsg(errname(E), __FILE__,__LINE__,__func__))); \
|
||||
}
|
||||
#define safethrow_msg(E, FREEMEM) { FREEMEM; \
|
||||
__RETURN_EXCEPTION(((char*)__genErrMsg(E, __FILE__,__LINE__,__func__))); \
|
||||
}
|
||||
|
||||
#define try_cpp(_funcCall, _rezult, freeMem) Maybe _rezult=_funcCall; if(_rezult.errmsg){ \
|
||||
freeMem; \
|
||||
_rezult.errmsg=__extendErrMsg(_rezult.errmsg, __FILE__,__LINE__,__func__); \
|
||||
return _rezult; \
|
||||
}
|
||||
|
||||
#else
|
||||
#define throw(E) __EXIT(((char*)__genErrMsg((__stringify_err(E)), __FILE__,__LINE__,__func__)))
|
||||
|
||||
#define safethrow(E, FREEMEM) { FREEMEM; \
|
||||
__RETURN_EXCEPTION(((char*)__genErrMsg((__stringify_err(E)), __FILE__,__LINE__,__func__))); \
|
||||
}
|
||||
|
||||
#define try(_funcCall, _rezult, freeMem) Maybe _rezult=_funcCall; if(_rezult.errmsg){ \
|
||||
freeMem; \
|
||||
_rezult.errmsg=__extendErrMsg(_rezult.errmsg, __FILE__,__LINE__,__func__); \
|
||||
return _rezult; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define tryLast(_funcCall, _rezult, ON_EXIT) Maybe _rezult=_funcCall; if(_rezult.errmsg){ \
|
||||
_rezult.errmsg=__extendErrMsg(_rezult.errmsg, __FILE__,__LINE__,__func__); \
|
||||
__EXIT(_rezult.errmsg); \
|
||||
}
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
41
kerep-headers/base/optime.h
Normal file
41
kerep-headers/base/optime.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include "std.h"
|
||||
|
||||
#define __optime_print(opname, t) \
|
||||
char tnames[3][3]={"s\0","ms","us"}; \
|
||||
i32 tni=0; \
|
||||
if(t>1000000){ \
|
||||
t/=1000000; \
|
||||
tni=0; \
|
||||
} else if(t>1000){ \
|
||||
t/=1000; \
|
||||
tni=1; \
|
||||
} else tni=2; \
|
||||
kprintf("\e[93moperation \e[94m%s\e[93m lasted \e[94m%f \e[93m%s\n", \
|
||||
opname, t, tnames[tni]);
|
||||
|
||||
#ifdef CLOCK_REALTIME
|
||||
/// executes codeblock and prints execution time
|
||||
/// u64 op_i is counter of the internal loop
|
||||
/// uses non-standard high-precision clock
|
||||
#define optime(opname, repeats, codeblock...) { \
|
||||
struct timespec start, stop; \
|
||||
clock_gettime(CLOCK_REALTIME, &start); \
|
||||
for(u64 op_i=0;op_i<(u64)repeats;op_i++) \
|
||||
{ codeblock; } \
|
||||
clock_gettime(CLOCK_REALTIME, &stop); \
|
||||
f64 t=(f64)(stop.tv_sec-start.tv_sec)*1000000+(f64)(stop.tv_nsec-start.tv_nsec)/1000; \
|
||||
__optime_print(opname,t); \
|
||||
}
|
||||
#else
|
||||
/// uses standard low precision clock
|
||||
#define optime(opname, repeats, codeblock...) { \
|
||||
clock_t start=clock(); \
|
||||
for(u64 op_i=0;op_i<(u64)repeats;op_i++) \
|
||||
{ codeblock; } \
|
||||
clock_t stop=clock(); \
|
||||
f64 t=(f64)(stop-start)/CLOCKS_PER_SEC*1000000; \
|
||||
__optime_print(opname,t); \
|
||||
}
|
||||
#endif
|
||||
135
kerep-headers/base/std.h
Normal file
135
kerep-headers/base/std.h
Normal file
@@ -0,0 +1,135 @@
|
||||
#pragma once
|
||||
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <locale.h>
|
||||
#include <time.h>
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include <math.h>
|
||||
|
||||
typedef int8_t i8;
|
||||
typedef uint8_t u8;
|
||||
typedef int16_t i16;
|
||||
typedef uint16_t u16;
|
||||
typedef int32_t i32;
|
||||
typedef uint32_t u32;
|
||||
typedef int64_t i64;
|
||||
typedef uint64_t u64;
|
||||
typedef float f32;
|
||||
typedef double f64;
|
||||
/// anonymous pointer without specified freeMembers() func
|
||||
typedef void* Pointer;
|
||||
|
||||
// Usually bool from stdbool.h is defined as macro,
|
||||
// so in other macros like ktid_##TYPE it will be replaced by _Bool.
|
||||
// ktid__Bool will be created instead of ktid_bool
|
||||
// In C++ bool is a keyword, so there is no need to redefine it.
|
||||
#if !__cplusplus
|
||||
typedef u8 bool;
|
||||
#define true 1
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
#define dbg(N) kprintf("\e[95m%d\n",N)
|
||||
|
||||
#define nameof(V) #V
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "mincore_downlevel.lib") // Support OS older than SDK
|
||||
#define _CRT_SECURE_NO_WARNINGS 1
|
||||
#define EXPORT __declspec(dllexport)
|
||||
#define CALL __cdecl
|
||||
#elif defined(__GNUC__)
|
||||
#define EXPORT __attribute__((visibility("default")))
|
||||
#if __SIZEOF_POINTER__ == 4
|
||||
#define CALL __attribute__((__cdecl__))
|
||||
#else
|
||||
#define CALL
|
||||
#endif
|
||||
#ifndef typeof
|
||||
#define typeof(X) __typeof__(X)
|
||||
#endif
|
||||
#else
|
||||
#pragma GCC error "unknown compiler"
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define IFWIN(YES, NO) YES
|
||||
#define IFMSC(YES, NO) YES
|
||||
#elif defined(_WIN64) || defined(_WIN32)
|
||||
#define IFWIN(YES, NO) YES
|
||||
#define IFMSC(YES, NO) NO
|
||||
#elif defined(__GNUC__)
|
||||
#define IFWIN(YES, NO) NO
|
||||
#define IFMSC(YES, NO) NO
|
||||
#else
|
||||
#pragma GCC error "unknown compiler"
|
||||
#endif
|
||||
|
||||
#ifndef sprintf_s
|
||||
#define sprintf_s(BUF, BUFSIZE, FORMAT, ...) sprintf(BUF, FORMAT, ## __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
|
||||
#define __count_args( \
|
||||
a0, a1, a2, a3, a4, a5, a6, a7 , \
|
||||
a8, a9, a10,a11,a12,a13,a14,a15, \
|
||||
a16,a17,a18,a19,a20,a21,a22,a23, \
|
||||
a24,a25,a26,a27,a28,a29,a30,a31, \
|
||||
a32,a33,a34,a35,a36,a37,a38,a39, \
|
||||
a40,a41,a42,a43,a44,a45,a46,a47, \
|
||||
a48,a49,a50,a51,a52,a53,a54,a55, \
|
||||
a56,a57,a58,a59,a60,a61,a62,a63, \
|
||||
a64,...) a64
|
||||
// Macro for counting variadic arguments (max 64)
|
||||
// (see usage in kprint.h)
|
||||
#define count_args(ARGS...) __count_args( \
|
||||
ARGS, \
|
||||
64,63,62,61,60,59,58,57, \
|
||||
56,55,54,53,52,51,50,49, \
|
||||
48,47,46,45,44,43,42,41, \
|
||||
40,39,38,37,36,35,34,33, \
|
||||
32,31,30,29,28,27,26,25, \
|
||||
24,23,22,21,20,19,18,17, \
|
||||
16,15,14,13,12,11,10,9, \
|
||||
8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
|
||||
/*
|
||||
Cross-platform warning supression.
|
||||
WARNING_DISABLE( W_EXAMPLE,
|
||||
some code producing W_EXAMPLE;
|
||||
);
|
||||
You can even embed it into macro in header (see kprint.h)
|
||||
*/
|
||||
#ifdef _MSC_VER
|
||||
#define PRAGMA_WARNING_PUSH __pragma(warning( push ))
|
||||
#define DISABLE_WARNING(wNumber) __pragma(warning( disable : wNumber ))
|
||||
#define PRAGMA_WARNING_POP __pragma(warning( pop ))
|
||||
#else
|
||||
#define _PRAGMA(P) _Pragma(#P)
|
||||
#define PRAGMA_WARNING_PUSH _PRAGMA(GCC diagnostic push)
|
||||
#define PRAGMA_WARNING_DISABLE(wName) _PRAGMA(GCC diagnostic ignored wName)
|
||||
#define PRAGMA_WARNING_POP _PRAGMA(GCC diagnostic pop)
|
||||
#define W_INT_CONVERSION "-Wint-conversion"
|
||||
#define W_IMPLICIT_FALLTHROUGH "-Wimplicit-fallthrough"
|
||||
#endif
|
||||
#define WARNING_DISABLE(WARNING, CODE...) \
|
||||
PRAGMA_WARNING_PUSH \
|
||||
PRAGMA_WARNING_DISABLE(WARNING) \
|
||||
CODE; \
|
||||
PRAGMA_WARNING_POP
|
||||
|
||||
/// gcc throws warning on unused function return value
|
||||
#define WARN_UNUSED_REZULT __attribute__((warn_unused_result))
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
34
kerep-headers/base/type_system/README.md
Normal file
34
kerep-headers/base/type_system/README.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# kerep type system
|
||||
|
||||
For using some kerep capabilities, such as generic structs, unitype, and kprint, types should be *registered*.
|
||||
|
||||
## type id
|
||||
|
||||
Every registered type has its own `ktDescriptor` and `ktid` is an index of the descriptor in descriptors array.
|
||||
Descriptor should be declared in header file.
|
||||
Following macro declares `typedef struct` and `ktDescriptor`
|
||||
```c
|
||||
//someStruct.h
|
||||
STRUCT(someStruct,
|
||||
i32 i; i32 j; i32 k;
|
||||
);
|
||||
```
|
||||
then you need to define descriptor in a source file
|
||||
```c
|
||||
//someStruct.c
|
||||
kt_define(someStruct);
|
||||
```
|
||||
and register it.
|
||||
|
||||
## type descriptors
|
||||
|
||||
Every registered type should have it's own descriptor (`ktDescriptor`). It's a struct, which contains some information about type and pointers to some specific functions for this type (`toString`, `freeMembers`).
|
||||
|
||||
## type registration
|
||||
|
||||
To finally register a type, you should call macro `kt_register()` between `kt_beginInit()` and `kt_endInit()`. Better do it at the start of your program. To register all types from kerep, call `kt_initKerepTypes()`.
|
||||
|
||||
You can free internal ktDescriptors storage by calling `kt_free()` at exit, if your debugger (valgrind in my case) sees a memory leak.
|
||||
Examples:
|
||||
+ [kerep types registration](src/base/type_system/init.c)
|
||||
+ [kt_initKerepTypes()](tests/main.cpp)
|
||||
47
kerep-headers/base/type_system/base_toString.h
Normal file
47
kerep-headers/base/type_system/base_toString.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "../errors.h"
|
||||
|
||||
// accepts char* (ptr to char) and char* (ptr to string)
|
||||
// uses format kp_s and kp_c to determine what type is <c> argument
|
||||
char* __toString_char(void* c, u32 fmt);
|
||||
|
||||
// bool
|
||||
char* __toString_bool(void* c, u32 fmt);
|
||||
|
||||
// signed int
|
||||
char* toString_i64(i64 n);
|
||||
char* __toString_i8(void* n, u32 fmt);
|
||||
char* __toString_i16(void* n, u32 fmt);
|
||||
char* __toString_i32(void* n, u32 fmt);
|
||||
char* __toString_i64(void* n, u32 fmt);
|
||||
|
||||
// unsigned int
|
||||
char* toString_u64(u64 n, bool withPostfix, bool uppercase);
|
||||
char* __toString_u8(void* n, u32 fmt);
|
||||
char* __toString_u16(void* n, u32 fmt);
|
||||
char* __toString_u32(void* n, u32 fmt);
|
||||
char* __toString_u64(void* n, u32 fmt);
|
||||
|
||||
// float
|
||||
#define toString_f32_max_precision 6
|
||||
#define toString_f64_max_precision 15
|
||||
#define toString_float_default_precision 6
|
||||
char* toString_f32(f32 n, u8 precision, bool withPostfix, bool uppercase); // uses sprintf
|
||||
char* toString_f64(f64 n, u8 precision, bool withPostfix, bool uppercase); // uses sprintf
|
||||
char* __toString_f32(void* n, u32 fmt);
|
||||
char* __toString_f64(void* n, u32 fmt);
|
||||
|
||||
|
||||
///@param inverse set to true for little endian numbers (their bytes are in reverse order)
|
||||
char* toString_bin(void* bytes, u32 size, bool inverse, bool withPrefix);
|
||||
///@param inverse set to true for little endian numbers (their bytes are in reverse order)
|
||||
char* toString_hex(void* bytes, u32 size, bool inverse, bool withPrefix, bool uppercase);
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
12
kerep-headers/base/type_system/init.h
Normal file
12
kerep-headers/base/type_system/init.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// call this between kt_beginInit() and kt_endInit()
|
||||
void kt_initKerepTypes();
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
51
kerep-headers/base/type_system/ktDescriptor.h
Normal file
51
kerep-headers/base/type_system/ktDescriptor.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "../std.h"
|
||||
#include "ktid.h"
|
||||
#include "typedef_macros.h"
|
||||
|
||||
#define kt_declare(TYPE)\
|
||||
ktid_declare(TYPE);\
|
||||
extern ktDescriptor ktDescriptor_##TYPE; \
|
||||
extern ktDescriptor ktDescriptor_##TYPE##_Ptr;
|
||||
|
||||
#define kt_define(TYPE, FREE_MEMBERS_F, TOSTRING_F)\
|
||||
ktid_define(TYPE); \
|
||||
ktDescriptor ktDescriptor_##TYPE={ \
|
||||
.name=#TYPE, \
|
||||
.id=ktid_undefined, \
|
||||
.size=sizeof(TYPE), \
|
||||
.freeMembers=FREE_MEMBERS_F, \
|
||||
.toString=TOSTRING_F \
|
||||
}; \
|
||||
ktDescriptor ktDescriptor_##TYPE##_Ptr={\
|
||||
.name=#TYPE "_Ptr", \
|
||||
.id=ktid_undefined, \
|
||||
.size=sizeof(TYPE), \
|
||||
.freeMembers=FREE_MEMBERS_F, \
|
||||
.toString=TOSTRING_F \
|
||||
};
|
||||
|
||||
typedef void (*freeMembers_t)(void*);
|
||||
typedef char* (*toString_t)(void* obj, u32 fmt);
|
||||
|
||||
STRUCT(ktDescriptor,
|
||||
char* name;
|
||||
ktid id;
|
||||
u16 size;
|
||||
freeMembers_t freeMembers; // NULL or function which frees all struct members
|
||||
toString_t toString; // NULL or function which generates string representaion of object
|
||||
)
|
||||
|
||||
/// gets descriptor for TYPE
|
||||
#define ktDescriptor_name(TYPE) ktDescriptor_##TYPE
|
||||
/// gets descriptor for pointer to TYPE
|
||||
#define ktDescriptor_namePtr(TYPE) ktDescriptor_##TYPE##_Ptr
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
49
kerep-headers/base/type_system/kt_functions.h
Normal file
49
kerep-headers/base/type_system/kt_functions.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "../std.h"
|
||||
#include "ktid.h"
|
||||
#include "ktDescriptor.h"
|
||||
|
||||
extern ktid ktid_last;
|
||||
void __kt_register(ktDescriptor* descriptor);
|
||||
|
||||
#define kt_register(TYPE) \
|
||||
__kt_register(&ktDescriptor_##TYPE); \
|
||||
ktid_##TYPE=ktid_last; \
|
||||
__kt_register(&ktDescriptor_##TYPE##_Ptr); \
|
||||
ktid_##TYPE##_Ptr=ktid_last;
|
||||
|
||||
void kt_beginInit();
|
||||
void kt_endInit();
|
||||
|
||||
/// @param id id of registered type
|
||||
ktDescriptor* ktDescriptor_get(ktid id);
|
||||
|
||||
char* ktDescriptor_toString(ktDescriptor* d);
|
||||
|
||||
// call it to free heap-allocated ktDescriptors array
|
||||
void kt_free();
|
||||
|
||||
kt_declare(Pointer);
|
||||
kt_declare(char);
|
||||
kt_declare(bool);
|
||||
kt_declare(f32);
|
||||
kt_declare(f64);
|
||||
kt_declare(i8);
|
||||
kt_declare(u8);
|
||||
kt_declare(i16);
|
||||
kt_declare(u16);
|
||||
kt_declare(i32);
|
||||
kt_declare(u32);
|
||||
kt_declare(i64);
|
||||
kt_declare(u64);
|
||||
|
||||
kt_declare(ktDescriptor);
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
28
kerep-headers/base/type_system/ktid.h
Normal file
28
kerep-headers/base/type_system/ktid.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "../std.h"
|
||||
#include "typedef_macros.h"
|
||||
|
||||
typedef u16 ktid;
|
||||
static const ktid ktid_undefined=-1;
|
||||
|
||||
/// gets descriptor id for TYPE
|
||||
#define ktid_name(TYPE) ktid_##TYPE
|
||||
/// gets descriptor id for pointer to TYPE
|
||||
#define ktid_ptrName(TYPE) ktid_##TYPE##_Ptr
|
||||
|
||||
#define ktid_declare(TYPE) \
|
||||
extern ktid ktid_##TYPE; \
|
||||
extern ktid ktid_##TYPE##_Ptr;
|
||||
|
||||
#define ktid_define(TYPE) \
|
||||
ktid ktid_##TYPE=-1; \
|
||||
ktid ktid_##TYPE##_Ptr=-1;
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
8
kerep-headers/base/type_system/type_system.h
Normal file
8
kerep-headers/base/type_system/type_system.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "init.h"
|
||||
#include "ktid.h"
|
||||
#include "ktDescriptor.h"
|
||||
#include "kt_functions.h"
|
||||
#include "unitype.h"
|
||||
#include "typedef_macros.h"
|
||||
15
kerep-headers/base/type_system/typedef_macros.h
Normal file
15
kerep-headers/base/type_system/typedef_macros.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#define ENUM(ENUM_NAME, ENUM_MEMBERS...) typedef enum ENUM_NAME { \
|
||||
ENUM_MEMBERS \
|
||||
} ENUM_NAME;
|
||||
|
||||
#define PACKED_ENUM(ENUM_NAME, ENUM_MEMBERS...) typedef enum ENUM_NAME { \
|
||||
ENUM_MEMBERS \
|
||||
} __attribute__((__packed__)) ENUM_NAME;
|
||||
|
||||
#define STRUCT(STRUCT_NAME, STRUCT_MEMBERS...) typedef struct STRUCT_NAME STRUCT_NAME; \
|
||||
typedef struct STRUCT_NAME { \
|
||||
STRUCT_MEMBERS \
|
||||
} STRUCT_NAME; \
|
||||
kt_declare(STRUCT_NAME);
|
||||
55
kerep-headers/base/type_system/unitype.h
Normal file
55
kerep-headers/base/type_system/unitype.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ktid.h"
|
||||
#include "typedef_macros.h"
|
||||
|
||||
STRUCT(Unitype,
|
||||
union {
|
||||
i64 Int64;
|
||||
u64 UInt64;
|
||||
f64 Float64;
|
||||
bool Bool;
|
||||
void* VoidPtr;
|
||||
char Bytes[8];
|
||||
};
|
||||
ktid typeId;
|
||||
bool allocatedInHeap; // should Unitype_free call free() to VoidPtr*
|
||||
)
|
||||
|
||||
|
||||
#define __UniDef(FIELD, TYPE, VAL) ((Unitype){ \
|
||||
.FIELD=VAL, .typeId=ktid_name(TYPE), .allocatedInHeap=false})
|
||||
|
||||
#define UniInt64(VAL) __UniDef(Int64, i64, VAL)
|
||||
#define UniUInt64(VAL) __UniDef(UInt64, u64, VAL)
|
||||
#define UniFloat64(VAL) __UniDef(Float64, f64, VAL)
|
||||
#define UniBool(VAL) __UniDef(Bool, bool, VAL)
|
||||
|
||||
#define UniPtr(TYPE_ID, VAL, ALLOCATED_ON_HEAP)((Unitype){ \
|
||||
.VoidPtr=VAL, .typeId=TYPE_ID, .allocatedInHeap=ALLOCATED_ON_HEAP })
|
||||
#define UniStackPtr(TYPE, VAL) UniPtr(ktid_ptrName(TYPE), VAL, false)
|
||||
#define UniHeapPtr(TYPE, VAL) UniPtr(ktid_ptrName(TYPE), VAL, true)
|
||||
// 0==ktid_Pointer
|
||||
#define UniNull ((Unitype){.Int64=0, .typeId=0, .allocatedInHeap=false})
|
||||
#define UniTrue UniBool(true)
|
||||
#define UniFalse UniBool(false)
|
||||
|
||||
#define Unitype_isUniNull(UNI) (UNI.typeId==0 && UNI.Int64==0)
|
||||
|
||||
#define UniCheckTypeId(UNI, TYPE_ID) (UNI.typeId==TYPE_ID)
|
||||
#define UniCheckType(UNI, TYPE) UniCheckTypeId(UNI, ktid_name(TYPE))
|
||||
#define UniCheckTypePtr(UNI, TYPE) UniCheckTypeId(UNI, ktid_ptrName(TYPE))
|
||||
|
||||
// frees VoidPtr value or does nothing if type isn't pointer
|
||||
void Unitype_free(Unitype u);
|
||||
void __UnitypePtr_free(void* u);
|
||||
char* Unitype_toString(Unitype v, u32 fmt);
|
||||
void printuni(Unitype v);
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user