static void dl_internal_store_array( dl_ctx_t dl_ctx, dl_type_t storage_type, const dl_type_desc* sub_type, uint8_t* instance, uint32_t count, uintptr_t size, CDLBinStoreContext* store_ctx ) { switch( storage_type ) { case DL_TYPE_STORAGE_STRUCT: { uintptr_t size_ = sub_type->size[DL_PTR_SIZE_HOST]; if( sub_type->flags & DL_TYPE_FLAG_HAS_SUBDATA ) { for (uint32_t elem = 0; elem < count; ++elem) dl_internal_instance_store(dl_ctx, sub_type, instance + (elem * size_), store_ctx); } else dl_binary_writer_write( &store_ctx->writer, instance, count * size_ ); } break; case DL_TYPE_STORAGE_STR: for( uint32_t elem = 0; elem < count; ++elem ) dl_internal_store_string( instance + (elem * sizeof(char*)), store_ctx ); break; default: // default is a standard pod-type dl_binary_writer_write( &store_ctx->writer, instance, count * size ); break; } }
dl_error_t dl_instance_store( dl_ctx_t dl_ctx, dl_typeid_t type_id, void* instance, unsigned char* out_buffer, size_t out_buffer_size, size_t* produced_bytes ) { if( out_buffer_size > 0 && out_buffer_size <= sizeof(SDLDataHeader) ) return DL_ERROR_BUFFER_TO_SMALL; const SDLType* type = dl_internal_find_type( dl_ctx, type_id ); if( type == 0x0 ) return DL_ERROR_TYPE_NOT_FOUND; // write header SDLDataHeader header; header.id = DL_INSTANCE_ID; header.version = DL_INSTANCE_VERSION; header.root_instance_type = type_id; header.instance_size = 0; header.is_64_bit_ptr = sizeof(void*) == 8 ? 1 : 0; header.pad[0] = header.pad[1] = header.pad[2] = 0; unsigned char* store_ctx_buffer = 0x0; size_t store_ctx_buffer_size = 0; bool store_ctx_is_dummy = out_buffer_size == 0; if( out_buffer_size > 0 ) { memcpy(out_buffer, &header, sizeof(SDLDataHeader)); store_ctx_buffer = out_buffer + sizeof(SDLDataHeader); store_ctx_buffer_size = out_buffer_size - sizeof(SDLDataHeader); } CDLBinStoreContext store_context( store_ctx_buffer, store_ctx_buffer_size, store_ctx_is_dummy ); dl_binary_writer_reserve( &store_context.writer, type->size[DL_PTR_SIZE_HOST] ); store_context.AddWrittenPtr(instance, 0); // if pointer refere to root-node, it can be found at offset 0 dl_error_t err = dl_internal_instance_store( dl_ctx, type, (uint8*)instance, &store_context ); // write instance size! SDLDataHeader* out_header = (SDLDataHeader*)out_buffer; dl_binary_writer_seek_end( &store_context.writer ); if( out_buffer ) out_header->instance_size = (uint32)dl_binary_writer_tell( &store_context.writer ); if( produced_bytes ) *produced_bytes = (uint32)dl_binary_writer_tell( &store_context.writer ) + sizeof(SDLDataHeader); if( out_buffer_size > 0 && out_header->instance_size > out_buffer_size ) return DL_ERROR_BUFFER_TO_SMALL; return err; }
static dl_error_t dl_internal_store_member( dl_ctx_t dl_ctx, const SDLMember* member, uint8* instance, CDLBinStoreContext* store_ctx ) { dl_type_t atom_type = dl_type_t(member->type & DL_TYPE_ATOM_MASK); dl_type_t storage_type = dl_type_t(member->type & DL_TYPE_STORAGE_MASK); switch ( atom_type ) { case DL_TYPE_ATOM_POD: { switch( storage_type ) { case DL_TYPE_STORAGE_STRUCT: { const SDLType* sub_type = dl_internal_find_type( dl_ctx, member->type_id ); if( sub_type == 0x0 ) { dl_log_error( dl_ctx, "Could not find subtype for member %s", member->name ); return DL_ERROR_TYPE_NOT_FOUND; } dl_internal_instance_store( dl_ctx, sub_type, instance, store_ctx ); } break; case DL_TYPE_STORAGE_STR: dl_internal_store_string( instance, store_ctx ); break; case DL_TYPE_STORAGE_PTR: { uint8* data = *(uint8**)instance; pint offset = store_ctx->FindWrittenPtr( data ); if( data == 0x0 ) // Null-pointer, store pint(-1) to signal to patching! { DL_ASSERT(offset == pint(-1) && "This pointer should not have been found among the written ptrs!"); // keep the -1 in Offset and store it to ptr. } else if( offset == pint(-1) ) // has not been written yet! { pint pos = dl_binary_writer_tell( &store_ctx->writer ); dl_binary_writer_seek_end( &store_ctx->writer ); const SDLType* sub_type = dl_internal_find_type( dl_ctx, member->type_id ); pint size = dl_internal_align_up( sub_type->size[DL_PTR_SIZE_HOST], sub_type->alignment[DL_PTR_SIZE_HOST] ); dl_binary_writer_align( &store_ctx->writer, sub_type->alignment[DL_PTR_SIZE_HOST] ); offset = dl_binary_writer_tell( &store_ctx->writer ); // write data! dl_binary_writer_reserve( &store_ctx->writer, size ); // reserve space for ptr so subdata is placed correctly store_ctx->AddWrittenPtr(data, offset); dl_internal_instance_store(dl_ctx, sub_type, data, store_ctx); dl_binary_writer_seek_set( &store_ctx->writer, pos ); } dl_binary_writer_write( &store_ctx->writer, &offset, sizeof(pint) ); } break; default: // default is a standard pod-type DL_ASSERT( member->IsSimplePod() || storage_type == DL_TYPE_STORAGE_ENUM ); dl_binary_writer_write( &store_ctx->writer, instance, member->size[DL_PTR_SIZE_HOST] ); break; } } return DL_ERROR_OK; case DL_TYPE_ATOM_INLINE_ARRAY: { switch( storage_type ) { case DL_TYPE_STORAGE_STRUCT: dl_binary_writer_write( &store_ctx->writer, instance, member->size[DL_PTR_SIZE_HOST] ); // TODO: I Guess that this is a bug! Will it fix ptrs well? break; case DL_TYPE_STORAGE_STR: { uint32 count = member->size[DL_PTR_SIZE_HOST] / sizeof(char*); for( uint32 elem = 0; elem < count; ++elem ) dl_internal_store_string( instance + (elem * sizeof(char*)), store_ctx ); } break; default: // default is a standard pod-type DL_ASSERT( member->IsSimplePod() || storage_type == DL_TYPE_STORAGE_ENUM ); dl_binary_writer_write( &store_ctx->writer, instance, member->size[DL_PTR_SIZE_HOST] ); break; } } return DL_ERROR_OK; case DL_TYPE_ATOM_ARRAY: { pint size = 0; const SDLType* sub_type = 0x0; uint8* data_ptr = instance; uint32 count = *(uint32*)( data_ptr + sizeof(void*) ); pint offset = 0; if( count == 0 ) offset = DL_NULL_PTR_OFFSET[ DL_PTR_SIZE_HOST ]; else { pint pos = dl_binary_writer_tell( &store_ctx->writer ); dl_binary_writer_seek_end( &store_ctx->writer ); switch(storage_type) { case DL_TYPE_STORAGE_STRUCT: sub_type = dl_internal_find_type( dl_ctx, member->type_id ); size = dl_internal_align_up( sub_type->size[DL_PTR_SIZE_HOST], sub_type->alignment[DL_PTR_SIZE_HOST] ); dl_binary_writer_align( &store_ctx->writer, sub_type->alignment[DL_PTR_SIZE_HOST] ); break; case DL_TYPE_STORAGE_STR: size = sizeof(void*); dl_binary_writer_align( &store_ctx->writer, size ); break; default: size = DLPodSize( member->type ); dl_binary_writer_align( &store_ctx->writer, size ); } offset = dl_binary_writer_tell( &store_ctx->writer ); // write data! dl_binary_writer_reserve( &store_ctx->writer, count * size ); // reserve space for array so subdata is placed correctly uint8* data = *(uint8**)data_ptr; switch(storage_type) { case DL_TYPE_STORAGE_STRUCT: for ( unsigned int elem = 0; elem < count; ++elem ) dl_internal_instance_store( dl_ctx, sub_type, data + (elem * size), store_ctx ); break; case DL_TYPE_STORAGE_STR: for ( unsigned int elem = 0; elem < count; ++elem ) dl_internal_store_string( data + (elem * size), store_ctx ); break; default: for ( unsigned int elem = 0; elem < count; ++elem ) dl_binary_writer_write( &store_ctx->writer, data + (elem * size), size ); break; } dl_binary_writer_seek_set( &store_ctx->writer, pos ); } // make room for ptr dl_binary_writer_write( &store_ctx->writer, &offset, sizeof(pint) ); // write count dl_binary_writer_write( &store_ctx->writer, &count, sizeof(uint32) ); } return DL_ERROR_OK; case DL_TYPE_ATOM_BITFIELD: dl_binary_writer_write( &store_ctx->writer, instance, member->size[DL_PTR_SIZE_HOST] ); break; default: DL_ASSERT(false && "Invalid ATOM-type!"); break; } return DL_ERROR_OK; }
static dl_error_t dl_internal_store_member( dl_ctx_t dl_ctx, const dl_member_desc* member, uint8_t* instance, CDLBinStoreContext* store_ctx ) { dl_type_t atom_type = dl_type_t(member->type & DL_TYPE_ATOM_MASK); dl_type_t storage_type = dl_type_t(member->type & DL_TYPE_STORAGE_MASK); switch ( atom_type ) { case DL_TYPE_ATOM_POD: { switch( storage_type ) { case DL_TYPE_STORAGE_STRUCT: { const dl_type_desc* sub_type = dl_internal_find_type( dl_ctx, member->type_id ); if( sub_type == 0x0 ) { dl_log_error( dl_ctx, "Could not find subtype for member %s", dl_internal_member_name( dl_ctx, member ) ); return DL_ERROR_TYPE_NOT_FOUND; } dl_internal_instance_store( dl_ctx, sub_type, instance, store_ctx ); } break; case DL_TYPE_STORAGE_STR: dl_internal_store_string( instance, store_ctx ); break; case DL_TYPE_STORAGE_PTR: { uint8_t* data = *(uint8_t**)instance; uintptr_t offset = store_ctx->FindWrittenPtr( data ); if( data == 0x0 ) // Null-pointer, store pint(-1) to signal to patching! { DL_ASSERT(offset == (uintptr_t)-1 && "This pointer should not have been found among the written ptrs!"); // keep the -1 in Offset and store it to ptr. } else if( offset == (uintptr_t)-1 ) // has not been written yet! { uintptr_t pos = dl_binary_writer_tell( &store_ctx->writer ); dl_binary_writer_seek_end( &store_ctx->writer ); const dl_type_desc* sub_type = dl_internal_find_type( dl_ctx, member->type_id ); uintptr_t size = dl_internal_align_up( sub_type->size[DL_PTR_SIZE_HOST], sub_type->alignment[DL_PTR_SIZE_HOST] ); dl_binary_writer_align( &store_ctx->writer, sub_type->alignment[DL_PTR_SIZE_HOST] ); offset = dl_binary_writer_tell( &store_ctx->writer ); // write data! dl_binary_writer_reserve( &store_ctx->writer, size ); // reserve space for ptr so subdata is placed correctly store_ctx->AddWrittenPtr(data, offset); dl_internal_instance_store(dl_ctx, sub_type, data, store_ctx); dl_binary_writer_seek_set( &store_ctx->writer, pos ); } dl_binary_writer_write( &store_ctx->writer, &offset, sizeof(uintptr_t) ); } break; default: // default is a standard pod-type DL_ASSERT( member->IsSimplePod() || storage_type == DL_TYPE_STORAGE_ENUM ); dl_binary_writer_write( &store_ctx->writer, instance, member->size[DL_PTR_SIZE_HOST] ); break; } } return DL_ERROR_OK; case DL_TYPE_ATOM_INLINE_ARRAY: { const dl_type_desc* sub_type = 0x0; uint32_t count = member->inline_array_cnt(); if( storage_type == DL_TYPE_STORAGE_STRUCT ) { sub_type = dl_internal_find_type(dl_ctx, member->type_id); if (sub_type == 0x0) { dl_log_error(dl_ctx, "Could not find subtype for member %s", dl_internal_member_name(dl_ctx, member)); return DL_ERROR_TYPE_NOT_FOUND; } } else if( storage_type != DL_TYPE_STORAGE_STR ) count = member->size[DL_PTR_SIZE_HOST]; dl_internal_store_array( dl_ctx, storage_type, sub_type, instance, count, 1, store_ctx ); } return DL_ERROR_OK; case DL_TYPE_ATOM_ARRAY: { uintptr_t size = 0; const dl_type_desc* sub_type = 0x0; uint8_t* data_ptr = instance; uint32_t count = *(uint32_t*)( data_ptr + sizeof(void*) ); uintptr_t offset = 0; if( count == 0 ) offset = DL_NULL_PTR_OFFSET[ DL_PTR_SIZE_HOST ]; else { uintptr_t pos = dl_binary_writer_tell( &store_ctx->writer ); dl_binary_writer_seek_end( &store_ctx->writer ); switch(storage_type) { case DL_TYPE_STORAGE_STRUCT: sub_type = dl_internal_find_type( dl_ctx, member->type_id ); size = dl_internal_align_up( sub_type->size[DL_PTR_SIZE_HOST], sub_type->alignment[DL_PTR_SIZE_HOST] ); dl_binary_writer_align( &store_ctx->writer, sub_type->alignment[DL_PTR_SIZE_HOST] ); break; case DL_TYPE_STORAGE_STR: size = sizeof(void*); dl_binary_writer_align( &store_ctx->writer, size ); break; default: size = dl_pod_size( member->type ); dl_binary_writer_align( &store_ctx->writer, size ); } offset = dl_binary_writer_tell( &store_ctx->writer ); // write data! dl_binary_writer_reserve( &store_ctx->writer, count * size ); // reserve space for array so subdata is placed correctly uint8_t* data = *(uint8_t**)data_ptr; dl_internal_store_array( dl_ctx, storage_type, sub_type, data, count, size, store_ctx ); dl_binary_writer_seek_set( &store_ctx->writer, pos ); } // make room for ptr dl_binary_writer_write( &store_ctx->writer, &offset, sizeof(uintptr_t) ); // write count dl_binary_writer_write( &store_ctx->writer, &count, sizeof(uint32_t) ); } return DL_ERROR_OK; case DL_TYPE_ATOM_BITFIELD: dl_binary_writer_write( &store_ctx->writer, instance, member->size[DL_PTR_SIZE_HOST] ); break; default: DL_ASSERT(false && "Invalid ATOM-type!"); break; } return DL_ERROR_OK; }