v4k-git-backup/engine/split/v4k_obj.h

132 lines
5.2 KiB
C

// -----------------------------------------------------------------------------
// C object framework (constructors/destructors, methods, rtti, refcounting)
// - rlyeh, public domain.
//
// ## object api (low level)
//
// - [ ] make object from reflected type (factory)
// - [x] make object (if debug, include callstack as well)
// - [x] ctor method (optional, ref to constructor)
// - [x] dtor method (optional, ref to deleter)
// - [x] zero mem object
// - [x] object logger
// - [ ] iterate members in a struct
//
// - [x] clone/copy/mutate classes
// - [x] load/save objects from/to memory/disk
// - [ ] diff/patch objects
// - [ ] experimental: support for AoSoA layout (using objcnt, 3bits)
//
// ## object decomposition
//
// <---------|--------->
// OBJ-SHADOW (64-bits) | OBJ CONTENT (N bytes)
// +-----+-----+-------------+-----------+-----+-----+-----+-----+--
// |TYPE |REFS.| OBJ NAME | obj cnt | ... | ... | ... | ... | .
// +-----+-----+-------------+-----------+-----+-----+-----+-----+--
// \-16-bits--/\---45-bits--/\--3-bits--/\-------N-bytes-----------
//
// OBJ TYPE+NAME format:
// - [type] custom tags at 0x0
// - [1..N] name
// - [\n] blank separator
// - [comments, logger, infos, etc] << obj_printf();
//
// ## object limitations
// - 256 classes max
// - 256 references max
// - 8-byte overhead per object
// - 2 total allocs per object (could be flattened into 1 with some more work)
//
// @todo: obj_extend( "class_src", "class_dst" ); call[super(obj)]()
// @todo: preferred load/save format: [ver:1,user:2,type:1] ([eof|size:7/15/23/31][blob:N])+ [crc:1/2/3/4]
// @todo: more serious loading/saving spec
// object api (heap+rtti)
API void* obj_malloc( int sz, ... );
API void* obj_calloc( int sz, ... );
API void obj_free( void *obj );
API bool obj_typeeq( const void *obj1, const void *obj2 );
API const char* obj_typeof( const void *obj );
API unsigned obj_typeid( const void *obj );
API unsigned obj_typeid_from_name( const char *name );
// object api (ctor/dtor, refcounting, oop)
API void obj_new( const char *type, ... );
API void obj_del( void *obj );
API void* obj_ref( void *obj );
API void* obj_unref( void *obj );
API void obj_extend( const char *dstclass, const char *srcclass );
API void obj_override( const char *objclass, void (**vtable)(), void(*fn)() );
// object: serialize
API unsigned obj_load(void *obj, const array(char) buffer);
API unsigned obj_load_file(void *obj, FILE *fp);
API unsigned obj_load_inplace(void *obj, const void *src, unsigned srclen);
API array(char) obj_save(const void *obj); // empty if error. must array_free() after use
API unsigned obj_save_file(FILE *fp, const void *obj);
API unsigned obj_save_inplace(void *dst, unsigned cap, const void *obj);
// object: utils
API unsigned obj_instances( const void *obj );
API void obj_zero( void *obj );
API unsigned obj_sizeof( const void *obj );
API void obj_hexdump( const void *obj );
API void obj_hexdumpf( FILE *out, const void *obj );
API void obj_printf( void *obj, const char *text );
API const char* obj_output( const void *obj );
API void * obj_clone(const void *obj);
API void * obj_copy(void **dst, const void *src);
API void * obj_mutate(void **dst, const void *src);
// object: method dispatch tables
#define ctor(obj) obj_method0(obj, ctor) // ctor[obj_typeid(obj)](obj)
#define dtor(obj) obj_method0(obj, dtor) // dtor[obj_typeid(obj)](obj)
API extern void (*ctor[256])(); ///-
API extern void (*dtor[256])(); ///-
// object: syntax sugars
#define obj_malloc(sz, ...) obj_initialize((void**)MALLOC( sizeof(void*)+sz), stringf("\1untyped\n%s\n", "" #__VA_ARGS__))
#define obj_calloc(sz, ...) obj_initialize((void**)CALLOC(1,sizeof(void*)+sz), stringf("\1untyped\n%s\n", "" #__VA_ARGS__))
#define obj_new0(type) obj_new(type, 0)
#define obj_new(type, ...) ( \
obj_tmpalloc = obj_initialize((void**)CALLOC(1, sizeof(void*)+sizeof(type)), stringf("%c" #type "\n", (char)obj_typeid_from_name(#type))), \
(*(type*)obj_tmpalloc = (type){ __VA_ARGS__ }), \
ctor(obj_tmpalloc), \
(type*)obj_tmpalloc )
#define obj_override(class, method) obj_override(#class, (void(**)())method, (void(*)())class##_##method)
#define obj_method0(obj, method) method[obj_typeid(obj)]((obj))
#define obj_method(obj, method, ...) method[obj_typeid(obj)]((obj), __VA_ARGS__)
#define obj_printf(obj, ...) obj_printf(obj, va(__VA_ARGS__))
#define obj_extend(dstclass, srcclass) obj_extend(#dstclass, #srcclass)
// object: implementation details
// https://stackoverflow.com/questions/16198700/using-the-extra-16-bits-in-64-bit-pointers (note: using 19-bits here)
#define OBJBOX(ptr, payload16) (void*)(((long long unsigned)(payload16) << 48) | (long long unsigned)(ptr))
#define OBJUNBOX(ptr) (void*)((long long unsigned)(ptr) & 0x0000FFFFFFFFFFFFull)
#define OBJPAYLOAD16(ptr) (((long long unsigned)(ptr)) >> 48)
#define OBJPAYLOAD3(ptr) (((long long unsigned)(ptr)) & 7)
API void* obj_initialize( void **ptr, char *type_and_info );
static __thread void *obj_tmpalloc;