45 lines
1.5 KiB
C
45 lines
1.5 KiB
C
|
// ---
|
||
|
|
||
|
void *obj_copy(void **dst, const void *src) {
|
||
|
if(!*dst) return *dst = obj_clone(src);
|
||
|
|
||
|
if( obj_typeeq(*dst, src) ) {
|
||
|
return memcpy(*dst, src, obj_sizeof(src));
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
void *obj_mutate(void **dst_, const void *src) {
|
||
|
// mutate a class. ie, convert a given object class into a different one,
|
||
|
// while preserving the original metas and references as much as possible.
|
||
|
//
|
||
|
// @fixme: systems might be tracking objects in the future. the fact that we
|
||
|
// can reallocate a pointer (and hence, change its address) seems way too dangerous,
|
||
|
// as the tracking systems could crash when referencing a mutated object.
|
||
|
// solutions: do not reallocate if sizeof(new_class) > sizeof(old_class) maybe? good enough?
|
||
|
// also, optimization hint: no need to reallocate if both sizes matches, just copy contents.
|
||
|
|
||
|
if(!*dst_) return *dst_ = obj_clone(src);
|
||
|
|
||
|
void *dst = *dst_;
|
||
|
dtor(dst);
|
||
|
|
||
|
unsigned src_sz = obj_sizeof(src);
|
||
|
unsigned src_id = obj_typeid(src);
|
||
|
|
||
|
void *dst_ptr = *((void**)dst - 1);
|
||
|
unsigned payload = (OBJPAYLOAD16(dst_ptr) & 255) | src_id << 8;
|
||
|
FREE( OBJUNBOX(dst_ptr) );
|
||
|
*((void**)dst - 1) = OBJBOX( STRDUP( OBJUNBOX(*((void**)src - 1)) ), payload);
|
||
|
|
||
|
void *base = (void*)((void**)dst - 1);
|
||
|
base = REALLOC(base, src_sz + sizeof(void*));
|
||
|
*dst_ = (char*)base + sizeof(void*);
|
||
|
dst = (char*)base + sizeof(void*);
|
||
|
memcpy(dst, src, src_sz);
|
||
|
|
||
|
ctor(dst);
|
||
|
return dst;
|
||
|
}
|