Skip to content

Instantly share code, notes, and snippets.

@wc-duck
Last active December 11, 2018 20:58
Show Gist options
  • Save wc-duck/ae50cdebf1fa0a7c20abbc8c2cd1233a to your computer and use it in GitHub Desktop.
Save wc-duck/ae50cdebf1fa0a7c20abbc8c2cd1233a to your computer and use it in GitHub Desktop.
wc_engine dl utils.
#include <wcdl/wcdl.h>
#include <dbgtools/assert.h>
#include <debug/log.h>
#include <memory/memory_file.h>
#include <dl/dl_txt.h>
#include <dl/dl_reflect.h>
#include <stdlib.h>
static log_domain DL_LOG_DOMAIN( "dl" );
static void wcdl_log_error( const char* msg, void* userdata )
{
LOG_DOMAIN_ERROR( &DL_LOG_DOMAIN, "%s", msg );
}
static void* wcdl_alloc ( size_t size, void* alloc_ctx ) { return memory_alloc ( (memory_allocator_t)alloc_ctx, size ); }
static void* wcdl_realloc( void* ptr, size_t size, size_t /*old_size*/, void* alloc_ctx ) { return memory_realloc( (memory_allocator_t)alloc_ctx, ptr, size ); }
static void wcdl_free ( void* ptr, void* alloc_ctx ) { return memory_free ( (memory_allocator_t)alloc_ctx, ptr ); }
static const char* wcdl_get_type_name( dl_ctx_t ctx, dl_typeid_t type )
{
dl_type_info_t info;
dl_error_t err = dl_reflect_get_type_info( ctx, type, &info );
if(err == DL_ERROR_OK)
return info.name;
return "<unknown_type>";
}
dl_ctx_t wcdl_create_ctx( memory_allocator_t alloc )
{
dl_create_params_t create_params;
DL_CREATE_PARAMS_SET_DEFAULT( create_params );
if( alloc != nullptr )
{
create_params.alloc_func = wcdl_alloc;
create_params.realloc_func = wcdl_realloc;
create_params.free_func = wcdl_free;
create_params.alloc_ctx = alloc;
}
create_params.error_msg_func = wcdl_log_error;
dl_ctx_t ctx = 0x0;
dl_error_t err = dl_context_create( &ctx, &create_params );
ASSERT( err == DL_ERROR_OK );
return ctx;
}
dl_ctx_t wcdl_create_ctx( memory_allocator_t alloc, const wcdl_tld* libs, size_t libcnt )
{
dl_ctx_t ctx = wcdl_create_ctx( alloc );
if( ctx == 0x0 )
return 0x0;
for( size_t i = 0; i < libcnt; ++i )
{
dl_error_t err = dl_context_load_type_library( ctx, libs[i].lib, libs[i].size );
ASSERT( err == DL_ERROR_OK, "%s", dl_error_to_string( err ) );
}
return ctx;
}
dl_ctx_t wcdl_create_ctx( memory_allocator_t alloc, const uint8_t* typelib, size_t typelibsize )
{
wcdl_tld t = { typelib, typelibsize };
return wcdl_create_ctx( alloc, &t, 1 );
}
static void* wcdl_alloc( memory_allocator_t alloc, size_t bytes )
{
if( alloc )
return memory_alloc( alloc, bytes );
return malloc( bytes );
}
static void wcdl_free( memory_allocator_t alloc, void* ptr )
{
if( alloc )
memory_free( alloc, ptr );
else
free( ptr );
}
void* wcdl_load_from_buffer( dl_ctx_t dl_ctx, dl_typeid_t tid, memory_allocator_t alloc, const uint8_t* data, size_t data_size )
{
dl_error_t dlerr;
dl_instance_info_t info;
dlerr = dl_instance_get_info( data, data_size, &info );
if( dlerr != DL_ERROR_OK )
{
LOG_ERROR( "Failed to fetch instance info with error %s", dl_error_to_string( dlerr ) );
return nullptr;
}
void* loaded = wcdl_alloc( alloc, info.load_size );
dlerr = dl_instance_load( dl_ctx, tid, loaded, info.load_size, data, data_size, nullptr );
if( dlerr != DL_ERROR_OK )
{
LOG_ERROR( "Failed to load instance with error %s", dl_error_to_string( dlerr ) );
wcdl_free( alloc, loaded );
return nullptr;
}
return loaded;
}
void* wcdl_load_from_buffer_inplace( dl_ctx_t dl_ctx, dl_typeid_t tid, uint8_t* data, size_t data_size )
{
void* loaded;
dl_error_t dlerr = dl_instance_load_inplace( dl_ctx, tid, data, data_size, (void**)&loaded, 0x0 );
if( dlerr != DL_ERROR_OK )
{
LOG_ERROR( "Failed to load instance inplace with error %s", dl_error_to_string( dlerr ) );
return nullptr;
}
return loaded;
}
uint8_t* wcdl_pack_to_buffer( dl_ctx_t dl_ctx, dl_typeid_t tid, memory_allocator_t alloc, const void* instance, size_t* pack_size )
{
dl_error_t dlerr;
dlerr = dl_instance_store( dl_ctx, tid, instance, 0x0, 0, pack_size );
if( dlerr != DL_ERROR_OK )
{
LOG_ERROR( "Failed to calculate instance size with error %s", dl_error_to_string( dlerr ) );
return 0x0;
}
uint8_t* res = (uint8_t*)wcdl_alloc( alloc, *pack_size );
dlerr = dl_instance_store( dl_ctx, tid, instance, res, *pack_size, 0x0 );
if( dlerr != DL_ERROR_OK )
{
wcdl_free( alloc, res );
LOG_ERROR( "Failed to calculate instance size with error %s", dl_error_to_string( dlerr ) );
return 0x0;
}
return res;
}
void* wcdl_load_from_txt( dl_ctx_t ctx, memory_allocator_t alloc, const char* txt, dl_typeid_t type )
{
dl_error_t error;
size_t packsize;
error = dl_txt_pack( ctx, txt, 0x0, 0, &packsize );
if( error != DL_ERROR_OK )
{
LOG_DOMAIN_ERROR( &DL_LOG_DOMAIN, "failed to load %s-instance from txt, error: %s", wcdl_get_type_name(ctx, type), dl_error_to_string( error ) );
return nullptr;
}
unsigned char* packbuffer = (unsigned char*)wcdl_alloc( alloc, packsize );
error = dl_txt_pack( ctx, txt, packbuffer, packsize, 0x0 );
if( error != DL_ERROR_OK )
{
wcdl_free( alloc, packbuffer );
LOG_DOMAIN_ERROR( &DL_LOG_DOMAIN, "failed to load %s-instance from txt, error: %s", wcdl_get_type_name(ctx, type), dl_error_to_string( error ) );
return nullptr;
}
dl_instance_info_t out_info;
error = dl_instance_get_info( packbuffer, packsize, &out_info );
if( error != DL_ERROR_OK )
{
wcdl_free( alloc, packbuffer );
LOG_DOMAIN_ERROR( &DL_LOG_DOMAIN, "failed to load %s-instance from txt, error: %s", wcdl_get_type_name(ctx, type), dl_error_to_string( error ) );
return nullptr;
}
void* instance = wcdl_alloc( alloc, out_info.load_size );
error = dl_instance_load( ctx, type, instance, out_info.load_size, packbuffer, packsize, 0x0 );
wcdl_free( alloc, packbuffer );
if( error != DL_ERROR_OK )
{
wcdl_free( alloc, instance );
LOG_DOMAIN_ERROR( &DL_LOG_DOMAIN, "failed to load %s-instance from txt, error: %s", wcdl_get_type_name(ctx, type), dl_error_to_string( error ) );
return nullptr;
}
return instance;
}
void* wcdl_load_txt_from_file( dl_ctx_t dlctx, memory_allocator_t inst_alloc, memory_allocator_t tmp_alloc, const char* path, dl_typeid_t type )
{
const uint8_t* filedata = nullptr;
if(tmp_alloc)
filedata = memory_fileslurp( tmp_alloc, path, nullptr );
else
filedata = fileslurp(path, nullptr);
if(filedata == nullptr)
{
LOG_DOMAIN_ERROR( &DL_LOG_DOMAIN, "failed to open file %s", path );
return nullptr;
}
void* instance = wcdl_load_from_txt( dlctx, inst_alloc, (const char*)filedata, type );
if(instance == nullptr)
LOG_DOMAIN_ERROR( &DL_LOG_DOMAIN, "failed to open file %s", path );
wcdl_free(tmp_alloc, (void*)filedata);
return instance;
}
char* wcdl_pack_to_txt( dl_ctx_t ctx, dl_typeid_t tid, memory_allocator_t alloc, memory_allocator_t temp_alloc, const void* instance )
{
size_t packed_size;
uint8_t* packed = wcdl_pack_to_buffer( ctx, tid, temp_alloc, instance, &packed_size );
if( packed == nullptr )
return nullptr;
size_t out_txt_size = 0;
dl_error_t error;
error = dl_txt_unpack( ctx, tid, packed, packed_size, nullptr, 0, &out_txt_size );
if( error != DL_ERROR_OK )
{
memory_free( temp_alloc, (void*)packed );
LOG_DOMAIN_ERROR( &DL_LOG_DOMAIN, "failed to unpack %s-instance to txt, error: %s", wcdl_get_type_name(ctx, tid), dl_error_to_string( error ) );
return nullptr;
}
char* packed_txt = (char*)memory_alloc( alloc, out_txt_size );
error = dl_txt_unpack( ctx, tid, packed, packed_size, packed_txt, out_txt_size, nullptr );
if( error != DL_ERROR_OK )
{
memory_free( temp_alloc, (void*)packed );
LOG_DOMAIN_ERROR( &DL_LOG_DOMAIN, "failed to unpack %s-instance to txt, error: %s", wcdl_get_type_name(ctx, tid), dl_error_to_string( error ) );
return nullptr;
}
memory_free( temp_alloc, (void*)packed );
packed = (uint8_t*)packed_txt;
return packed_txt;
}
#ifndef WCDL_WCDL_H_INCLUDED
#define WCDL_WCDL_H_INCLUDED
#include <dl/dl.h>
#include <platform/fileutil.h>
#include <memory/memory.h>
#include <stdlib.h>
/**
*
*/
struct wcdl_tld
{
const uint8_t* lib;
size_t size;
};
/**
* Create a dl_ctx_t and hook up wc-engine specific functionality.
*
* @param alloc allocator to use in created ctx.
*/
dl_ctx_t wcdl_create_ctx( memory_allocator_t alloc );
/**
* Create a dl_ctx_t and hook up wc-engine specific functionality and load a typelibrary into ctx.
*
* @param alloc allocator to use in created ctx.
* @param typelib libdata to load.
* @param typelibsize number of bytes pointed to by typelib.
*/
dl_ctx_t wcdl_create_ctx( memory_allocator_t alloc, const wcdl_tld* libs, size_t libcnt );
/**
* Create a dl_ctx_t and hook up wc-engine specific functionality and load a typelibrary into ctx.
*
* @param alloc allocator to use in created ctx.
* @param typelib libdata to load.
* @param typelibsize number of bytes pointed to by typelib.
*/
dl_ctx_t wcdl_create_ctx( memory_allocator_t alloc, const uint8_t* typelib, size_t typelibsize );
/**
*
*/
void* wcdl_load_from_buffer( dl_ctx_t dl_ctx, dl_typeid_t tid, memory_allocator_t alloc, const uint8_t* data, size_t data_size );
template <typename T>
T* wcdl_load_from_buffer( dl_ctx_t dl_ctx, memory_allocator_t alloc, const uint8_t* data, size_t data_size )
{
return (T*)wcdl_load_from_buffer( dl_ctx, T::TYPE_ID, alloc, data, data_size );
}
/**
*
*/
void* wcdl_load_from_buffer_inplace( dl_ctx_t dl_ctx, dl_typeid_t tid, uint8_t* data, size_t data_size );
template <typename T>
T* wcdl_load_from_buffer_inplace( dl_ctx_t dl_ctx, uint8_t* data, size_t data_size )
{
return (T*)wcdl_load_from_buffer_inplace( dl_ctx, T::TYPE_ID, data, data_size );
}
/**
* Store dl instance to binary buffer.
*
* @param dl_ctx dl-context to use when packing.
* @param tid type id of instance.
* @param alloc allocator to use when allocating result.
* @param instance to store
* @param pack_size [out] number of bytes in returned buffer.
*
* @return buffer containing the packed dl-instance
*/
uint8_t* wcdl_pack_to_buffer( dl_ctx_t dl_ctx, dl_typeid_t tid, memory_allocator_t alloc, const void* instance, size_t* pack_size );
/**
*
*/
template <typename T>
uint8_t* wcdl_pack_to_buffer( dl_ctx_t dl_ctx, memory_allocator_t alloc, const T* instance, size_t* pack_size )
{
return wcdl_pack_to_buffer( dl_ctx, T::TYPE_ID, alloc, instance, pack_size );
}
/**
*
*/
template <typename T>
bool wcdl_pack_to_file( dl_ctx_t dl_ctx, const char* path, memory_allocator_t temp_alloc, const T* instance )
{
size_t pack_size;
uint8_t* packed = wcdl_pack_to_buffer( dl_ctx, T::TYPE_ID, temp_alloc, instance, &pack_size );
if( !packed )
return false;
bool res = filedump( path, packed, pack_size );
if( temp_alloc )
memory_free( temp_alloc, packed );
else
free( packed );
return res;
}
/**
*
*/
template <typename T>
bool wcdl_pack_to_file( dl_ctx_t dl_ctx, const char* path, const T* instance )
{
return wcdl_pack_to_file<T>(dl_ctx, path, nullptr, instance);
}
/**
* Load instance from text data into instance where all memory is allocated by specified allocator.
*/
void* wcdl_load_from_txt( dl_ctx_t ctx, memory_allocator_t alloc, const char* txt, dl_typeid_t type );
/**
* Load instance from file into instance where all memory is allocated by specified allocator.
* @param dlcxt ctx with loaded typelib for type
* @param inst_alloc allocator to allocate the returned type with.
* @param tmp_alloc allocator to use for temporary allocations, if null malloc/free will be used.
* @param path to file to load.
* @param type typeid of type expected to be loaded from txt.
*
* @return loaded type or nullptr on failure.
*/
void* wcdl_load_txt_from_file( dl_ctx_t dlctx,
memory_allocator_t inst_alloc,
memory_allocator_t tmp_alloc,
const char* path,
dl_typeid_t type );
template <typename T>
T* wcdl_load_from_txt( dl_ctx_t ctx, memory_allocator_t alloc, const char* txt )
{
return (T*)wcdl_load_from_txt( ctx, alloc, txt, T::TYPE_ID );
}
/**
* Helper-function for compilers only to load dl-instance from file.
*/
template <typename T>
T* wcdl_load_txt_from_file( dl_ctx_t dlctx, memory_allocator_t inst_alloc, memory_allocator_t tmp_alloc, const char* path )
{
return (T*)wcdl_load_txt_from_file( dlctx, inst_alloc, tmp_alloc, path, T::TYPE_ID );
}
template <typename T>
T* wcdl_load_txt_from_file( dl_ctx_t dlctx, memory_allocator_t alloc, const char* path )
{
return wcdl_load_txt_from_file<T>(dlctx, alloc, alloc, path);
}
/**
* Helper-function for compilers only to load dl-instance from file.
*/
template <typename T>
T* wcdl_load_txt_from_file( dl_ctx_t dlctx, const char* path )
{
return wcdl_load_txt_from_file<T>( dlctx, nullptr, nullptr, path );
}
/**
*
*/
char* wcdl_pack_to_txt( dl_ctx_t dl_ctx, dl_typeid_t tid, memory_allocator_t alloc, memory_allocator_t temp_alloc, const void* instance );
/**
*
*/
template <typename T>
char* wcdl_pack_to_txt( dl_ctx_t dl_ctx, memory_allocator_t alloc, memory_allocator_t temp_alloc, const T* instance )
{
return wcdl_pack_to_txt( dl_ctx, T::TYPE_ID, alloc, temp_alloc, instance );
}
#endif // WCDL_WCDL_H_INCLUDED
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment