static void dl_load_txt_build_default_data( dl_ctx_t ctx, dl_txt_read_ctx* read_state, unsigned int member_index ) { if( ctx->member_descs[member_index].default_value_offset == 0xFFFFFFFF ) return; // TODO: check that this is not outside the buffers dl_type_desc* def_type = dl_alloc_type( ctx, dl_internal_hash_string( "a_type_here" ) ); dl_member_desc* def_member = dl_alloc_member( ctx ); dl_member_desc* member = &ctx->member_descs[member_index]; uint32_t def_start = member->default_value_offset; uint32_t def_len = member->default_value_size; char def_buffer[2048]; // TODO: no hardcode =/ // TODO: check that typename do not exist in the ctx! size_t name_start = ctx->typedata_strings_size; dl_txt_read_substr temp = { "a_type_here", 11 }; def_type->name = dl_alloc_string( ctx, &temp ); def_type->size[DL_PTR_SIZE_HOST] = member->size[DL_PTR_SIZE_HOST]; def_type->alignment[DL_PTR_SIZE_HOST] = member->alignment[DL_PTR_SIZE_HOST]; def_type->member_count = 1; memcpy( def_member, member, sizeof( dl_member_desc ) ); def_member->offset[0] = 0; def_member->offset[1] = 0; dl_internal_str_format( def_buffer, sizeof(def_buffer), "{\"a_type_here\":{\"%s\":%.*s}}", dl_internal_member_name( ctx, member ), (int)def_len, read_state->start + def_start ); size_t prod_bytes; dl_error_t err; err = dl_txt_pack( ctx, def_buffer, 0x0, 0, &prod_bytes ); if( err != DL_ERROR_OK ) dl_txt_read_failed( ctx, read_state, DL_ERROR_INVALID_DEFAULT_VALUE, "failed to pack default-value for member \"%s\" with error \"%s\"", dl_internal_member_name( ctx, member ), dl_error_to_string( err ) ); uint8_t* pack_buffer = (uint8_t*)dl_alloc( &ctx->alloc, prod_bytes ); dl_txt_pack( ctx, def_buffer, pack_buffer, prod_bytes, 0x0 ); // TODO: convert packed instance to typelib endian/ptrsize here! size_t inst_size = prod_bytes - sizeof( dl_data_header ); ctx->default_data = (uint8_t*)dl_realloc( &ctx->alloc, ctx->default_data, ctx->default_data_size + inst_size, ctx->default_data_size ); memcpy( ctx->default_data + ctx->default_data_size, pack_buffer + sizeof( dl_data_header ), inst_size ); dl_free( &ctx->alloc, pack_buffer ); member->default_value_offset = (uint32_t)ctx->default_data_size; member->default_value_size = (uint32_t)inst_size; ctx->default_data_size += inst_size; --ctx->type_count; --ctx->member_count; ctx->typedata_strings_size = name_start; }
static void dl_load_txt_calc_type_size_and_align( dl_ctx_t ctx, dl_txt_read_ctx* read_state, dl_type_desc* type ) { // ... is the type already processed ... if( type->size[0] > 0 ) return; dl_load_txt_fixup_bitfield_members( ctx, type ); uint32_t size[2] = { 0, 0 }; uint32_t align[2] = { type->alignment[DL_PTR_SIZE_32BIT], type->alignment[DL_PTR_SIZE_64BIT] }; unsigned int mem_start = type->member_start; unsigned int mem_end = type->member_start + type->member_count; dl_member_desc* bitfield_group_start = 0x0; for( unsigned int member_index = mem_start; member_index < mem_end; ++member_index ) { dl_member_desc* member = ctx->member_descs + member_index; // If a member is marked as a struct it could also have been an enum that we didn't know about parse-time, patch it in that case. if( member->StorageType() == DL_TYPE_STORAGE_STRUCT ) { if( const dl_enum_desc* edesc = dl_internal_find_enum( ctx, member->type_id ) ) member->set_storage( edesc->storage ); } dl_type_atom_t atom = member->AtomType(); dl_type_storage_t storage = member->StorageType(); switch( atom ) { case DL_TYPE_ATOM_POD: case DL_TYPE_ATOM_INLINE_ARRAY: { if( atom == DL_TYPE_ATOM_INLINE_ARRAY ) { if( member->inline_array_cnt() == 0 ) { const char* enum_value_name = 0x0; uint32_t enum_value_name_len = 0; if( sizeof(void*) == 8 ) { enum_value_name = (const char*)( ( (uint64_t)member->size[0] ) | (uint64_t)member->size[1] << 32 ); enum_value_name_len = member->alignment[0]; } else { enum_value_name = (const char*)(uint64_t)member->size[0]; enum_value_name_len = member->alignment[0]; } uint64_t val; if( !dl_internal_find_enum_value_from_name( ctx, enum_value_name, (size_t)enum_value_name_len, &val ) ) dl_txt_read_failed( ctx, read_state, DL_ERROR_TXT_INVALID_ENUM_VALUE, "%s.%s is an inline array with size %.*s, but that enum value does not exist.", dl_internal_type_name( ctx, type ), dl_internal_member_name( ctx, member ), (int)enum_value_name_len, enum_value_name ); member->set_inline_array_cnt( (uint32_t)val ); } } if( storage == DL_TYPE_STORAGE_STRUCT ) { const dl_type_desc* sub_type = dl_internal_find_type( ctx, member->type_id ); if( sub_type == 0x0 ) continue; dl_load_txt_calc_type_size_and_align( ctx, read_state, (dl_type_desc*)sub_type ); member->copy_size( sub_type->size ); member->copy_align( sub_type->alignment ); } else dl_set_member_size_and_align_from_builtin( storage, member ); if( atom == DL_TYPE_ATOM_INLINE_ARRAY ) { member->size[DL_PTR_SIZE_32BIT] *= member->inline_array_cnt(); member->size[DL_PTR_SIZE_64BIT] *= member->inline_array_cnt(); } bitfield_group_start = 0x0; } break; case DL_TYPE_ATOM_ARRAY: { member->set_size( 8, 16 ); member->set_align( 4, 8 ); } break; case DL_TYPE_ATOM_BITFIELD: { if( bitfield_group_start ) { member->offset[DL_PTR_SIZE_32BIT] = bitfield_group_start->offset[DL_PTR_SIZE_32BIT]; member->offset[DL_PTR_SIZE_64BIT] = bitfield_group_start->offset[DL_PTR_SIZE_64BIT]; continue; } bitfield_group_start = member; } break; default: bitfield_group_start = 0x0; } if( type->flags & DL_TYPE_FLAG_IS_UNION ) { member->set_offset( 0, 0 ); size[DL_PTR_SIZE_32BIT] = member->size[DL_PTR_SIZE_32BIT] > size[DL_PTR_SIZE_32BIT] ? member->size[DL_PTR_SIZE_32BIT] : size[DL_PTR_SIZE_32BIT]; size[DL_PTR_SIZE_64BIT] = member->size[DL_PTR_SIZE_64BIT] > size[DL_PTR_SIZE_64BIT] ? member->size[DL_PTR_SIZE_64BIT] : size[DL_PTR_SIZE_64BIT]; } else { member->offset[DL_PTR_SIZE_32BIT] = dl_internal_align_up( size[DL_PTR_SIZE_32BIT], member->alignment[DL_PTR_SIZE_32BIT] ); member->offset[DL_PTR_SIZE_64BIT] = dl_internal_align_up( size[DL_PTR_SIZE_64BIT], member->alignment[DL_PTR_SIZE_64BIT] ); size[DL_PTR_SIZE_32BIT] = member->offset[DL_PTR_SIZE_32BIT] + member->size[DL_PTR_SIZE_32BIT]; size[DL_PTR_SIZE_64BIT] = member->offset[DL_PTR_SIZE_64BIT] + member->size[DL_PTR_SIZE_64BIT]; } align[DL_PTR_SIZE_32BIT] = member->alignment[DL_PTR_SIZE_32BIT] > align[DL_PTR_SIZE_32BIT] ? member->alignment[DL_PTR_SIZE_32BIT] : align[DL_PTR_SIZE_32BIT]; align[DL_PTR_SIZE_64BIT] = member->alignment[DL_PTR_SIZE_64BIT] > align[DL_PTR_SIZE_64BIT] ? member->alignment[DL_PTR_SIZE_64BIT] : align[DL_PTR_SIZE_64BIT]; } if( type->flags & DL_TYPE_FLAG_IS_UNION ) { // ... add size for the union type flag ... size[DL_PTR_SIZE_32BIT] = dl_internal_align_up( size[DL_PTR_SIZE_32BIT], align[DL_PTR_SIZE_32BIT] ) + (uint32_t)sizeof(uint32_t); size[DL_PTR_SIZE_64BIT] = dl_internal_align_up( size[DL_PTR_SIZE_64BIT], align[DL_PTR_SIZE_64BIT] ) + (uint32_t)sizeof(uint32_t); } type->size[DL_PTR_SIZE_32BIT] = dl_internal_align_up( size[DL_PTR_SIZE_32BIT], align[DL_PTR_SIZE_32BIT] ); type->size[DL_PTR_SIZE_64BIT] = dl_internal_align_up( size[DL_PTR_SIZE_64BIT], align[DL_PTR_SIZE_64BIT] ); type->alignment[DL_PTR_SIZE_32BIT] = align[DL_PTR_SIZE_32BIT]; type->alignment[DL_PTR_SIZE_64BIT] = align[DL_PTR_SIZE_64BIT]; }
static void dl_txt_unpack_member( dl_ctx_t dl_ctx, dl_txt_unpack_ctx* unpack_ctx, dl_binary_writer* writer, const dl_member_desc* member, const uint8_t* member_data ) { dl_txt_unpack_write_indent( writer, unpack_ctx ); dl_txt_unpack_write_string( writer, dl_internal_member_name( dl_ctx, member ) ); dl_binary_writer_write( writer, " : ", 3 ); switch( member->AtomType() ) { case DL_TYPE_ATOM_POD: { switch( member->StorageType() ) { case DL_TYPE_STORAGE_INT8: dl_txt_unpack_int8 ( writer, *(int8_t* )member_data ); break; case DL_TYPE_STORAGE_INT16: dl_txt_unpack_int16 ( writer, *(int16_t*)member_data ); break; case DL_TYPE_STORAGE_INT32: dl_txt_unpack_int32 ( writer, *(int32_t*)member_data ); break; case DL_TYPE_STORAGE_INT64: dl_txt_unpack_int64 ( writer, *(int64_t*)member_data ); break; case DL_TYPE_STORAGE_UINT8: dl_txt_unpack_uint8 ( writer, *(uint8_t* )member_data ); break; case DL_TYPE_STORAGE_UINT16: dl_txt_unpack_uint16( writer, *(uint16_t*)member_data ); break; case DL_TYPE_STORAGE_UINT32: dl_txt_unpack_uint32( writer, *(uint32_t*)member_data ); break; case DL_TYPE_STORAGE_UINT64: dl_txt_unpack_uint64( writer, *(uint64_t*)member_data ); break; case DL_TYPE_STORAGE_FP32: dl_txt_unpack_fp32 ( writer, *(float*)member_data ); break; case DL_TYPE_STORAGE_FP64: dl_txt_unpack_fp64 ( writer, *(double*)member_data ); break; case DL_TYPE_STORAGE_ENUM_INT8: dl_txt_unpack_enum ( dl_ctx, writer, dl_internal_find_enum( dl_ctx, member->type_id ), (uint64_t)*( int8_t*) member_data ); break; case DL_TYPE_STORAGE_ENUM_UINT8: dl_txt_unpack_enum ( dl_ctx, writer, dl_internal_find_enum( dl_ctx, member->type_id ), (uint64_t)*(uint8_t*) member_data ); break; case DL_TYPE_STORAGE_ENUM_INT16: dl_txt_unpack_enum ( dl_ctx, writer, dl_internal_find_enum( dl_ctx, member->type_id ), (uint64_t)*( int16_t*) member_data ); break; case DL_TYPE_STORAGE_ENUM_UINT16: dl_txt_unpack_enum ( dl_ctx, writer, dl_internal_find_enum( dl_ctx, member->type_id ), (uint64_t)*(uint16_t*) member_data ); break; case DL_TYPE_STORAGE_ENUM_INT32: dl_txt_unpack_enum ( dl_ctx, writer, dl_internal_find_enum( dl_ctx, member->type_id ), (uint64_t)*( int32_t*) member_data ); break; case DL_TYPE_STORAGE_ENUM_UINT32: dl_txt_unpack_enum ( dl_ctx, writer, dl_internal_find_enum( dl_ctx, member->type_id ), (uint64_t)*(uint32_t*) member_data ); break; case DL_TYPE_STORAGE_ENUM_INT64: dl_txt_unpack_enum ( dl_ctx, writer, dl_internal_find_enum( dl_ctx, member->type_id ), (uint64_t)*( int64_t*) member_data ); break; case DL_TYPE_STORAGE_ENUM_UINT64: dl_txt_unpack_enum ( dl_ctx, writer, dl_internal_find_enum( dl_ctx, member->type_id ), (uint64_t)*(uint64_t*) member_data ); break; case DL_TYPE_STORAGE_STR: dl_txt_unpack_write_string_or_null( writer, unpack_ctx, *(uintptr_t*)member_data ); break; case DL_TYPE_STORAGE_PTR: { dl_txt_unpack_ptr( writer, *(uintptr_t*)member_data ); unpack_ctx->has_ptrs = true; } break; case DL_TYPE_STORAGE_STRUCT: dl_txt_unpack_struct( dl_ctx, unpack_ctx, writer, dl_internal_find_type( dl_ctx, member->type_id ), member_data ); break; default: DL_ASSERT(false); } } break; case DL_TYPE_ATOM_ARRAY: { uintptr_t offset = *(uintptr_t*)member_data; uint32_t count = *(uint32_t*)(member_data + sizeof(uintptr_t)); if( offset == (uintptr_t)-1 ) dl_binary_writer_write( writer, "[]", 2 ); else dl_txt_unpack_array( dl_ctx, unpack_ctx, writer, member->StorageType(), &unpack_ctx->packed_instance[offset], count, member->type_id ); } break; case DL_TYPE_ATOM_INLINE_ARRAY: dl_txt_unpack_array( dl_ctx, unpack_ctx, writer, member->StorageType(), member_data, member->inline_array_cnt(), member->type_id ); break; case DL_TYPE_ATOM_BITFIELD: { uint64_t write_me = 0; uint32_t bf_bits = member->bitfield_bits(); uint32_t bf_offset = dl_bf_offset( DL_ENDIAN_HOST, member->size[DL_PTR_SIZE_HOST], member->bitfield_offset(), bf_bits ); switch( member->size[DL_PTR_SIZE_HOST] ) { case 1: write_me = DL_EXTRACT_BITS( uint64_t( *(uint8_t*)member_data), uint64_t(bf_offset), uint64_t(bf_bits) ); break; case 2: write_me = DL_EXTRACT_BITS( uint64_t(*(uint16_t*)member_data), uint64_t(bf_offset), uint64_t(bf_bits) ); break; case 4: write_me = DL_EXTRACT_BITS( uint64_t(*(uint32_t*)member_data), uint64_t(bf_offset), uint64_t(bf_bits) ); break; case 8: write_me = DL_EXTRACT_BITS( uint64_t(*(uint64_t*)member_data), uint64_t(bf_offset), uint64_t(bf_bits) ); break; default: DL_ASSERT(false && "This should not happen!"); break; } dl_txt_unpack_uint64( writer, write_me ); } break; default: DL_ASSERT( false ); } }
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; }