Make 'explicit' constructor

This commit is contained in:
Serge Lamikhov-Center 2021-09-14 18:35:54 +03:00
parent dde66c035e
commit 33089a021a
6 changed files with 121 additions and 78 deletions

22
.vscode/tasks.json vendored
View File

@ -34,6 +34,28 @@
"kind": "build", "kind": "build",
"isDefault": true "isDefault": true
} }
},
{
"type": "shell",
"label": "clang-tidy",
"command": "clang-tidy",
"args": [
"--checks=*,-modernize-use-trailing-return-type,-modernize-avoid-c-arrays,-llvm*,-fuchsia-*",
"-header-filter=./*",
"examples/elfdump/elfdump.cpp",
"--",
"-I.",
],
"options": {
"cwd": "${workspaceRoot}"
},
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
} }
], ],
"version": "2.0.0" "version": "2.0.0"

View File

@ -162,7 +162,7 @@ class elfio
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool save( std::ostream& stream ) bool save( std::ostream& stream )
{ {
if ( !stream || !header ) { if ( !stream || header == nullptr ) {
return false; return false;
} }
@ -171,15 +171,16 @@ class elfio
// The position of the section table is variable and needs to be fixed // The position of the section table is variable and needs to be fixed
// before saving. // before saving.
header->set_segments_num( segments.size() ); header->set_segments_num( segments.size() );
header->set_segments_offset( segments.size() ? header->get_header_size() header->set_segments_offset(
: 0 ); segments.size() > 0 ? header->get_header_size() : 0 );
header->set_sections_num( sections.size() ); header->set_sections_num( sections.size() );
header->set_sections_offset( 0 ); header->set_sections_offset( 0 );
// Layout the first section right after the segment table // Layout the first section right after the segment table
current_file_pos = header->get_header_size() + current_file_pos =
header->get_header_size() +
header->get_segment_entry_size() * header->get_segment_entry_size() *
(Elf_Xword)header->get_segments_num(); static_cast<Elf_Xword>( header->get_segments_num() );
calc_segment_alignment(); calc_segment_alignment();
@ -269,8 +270,8 @@ class elfio
for ( int j = i+1; j < sections.size(); ++j ) { for ( int j = i+1; j < sections.size(); ++j ) {
const section* a = sections[i]; const section* a = sections[i];
const section* b = sections[j]; const section* b = sections[j];
if ( !(a->get_type() & SHT_NOBITS) if ( ((a->get_type() & SHT_NOBITS) == 0)
&& !(b->get_type() & SHT_NOBITS) && ((b->get_type() & SHT_NOBITS) == 0)
&& (a->get_size() > 0) && (a->get_size() > 0)
&& (b->get_size() > 0) && (b->get_size() > 0)
&& (a->get_offset() > 0) && (a->get_offset() > 0)
@ -297,7 +298,7 @@ class elfio
const segment* seg = segments[h]; const segment* seg = segments[h];
if ( seg->get_type() == PT_LOAD && seg->get_file_size() > 0 ) { if ( seg->get_type() == PT_LOAD && seg->get_file_size() > 0 ) {
const section* sec = find_prog_section_for_offset( seg->get_offset() ); const section* sec = find_prog_section_for_offset( seg->get_offset() );
if ( sec ) { if ( sec != nullptr ) {
Elf64_Addr sec_addr = get_virtual_addr( seg->get_offset(), sec ); Elf64_Addr sec_addr = get_virtual_addr( seg->get_offset(), sec );
if ( sec_addr != seg->get_virtual_address() ) { if ( sec_addr != seg->get_virtual_address() ) {
errors += "Virtual address of segment " + std::to_string( h ) + " (" + to_hex_string( seg->get_virtual_address() ) + ")" errors += "Virtual address of segment " + std::to_string( h ) + " (" + to_hex_string( seg->get_virtual_address() ) + ")"
@ -316,14 +317,14 @@ class elfio
private: private:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool is_offset_in_section( Elf64_Off offset, const section* sec ) const static bool is_offset_in_section( Elf64_Off offset, const section* sec )
{ {
return ( offset >= sec->get_offset() ) && return ( offset >= sec->get_offset() ) &&
( offset < ( sec->get_offset() + sec->get_size() ) ); ( offset < ( sec->get_offset() + sec->get_size() ) );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Elf64_Addr get_virtual_addr( Elf64_Off offset, const section* sec ) const static Elf64_Addr get_virtual_addr( Elf64_Off offset, const section* sec )
{ {
return sec->get_address() + offset - sec->get_offset(); return sec->get_address() + offset - sec->get_offset();
} }
@ -331,11 +332,12 @@ class elfio
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
const section* find_prog_section_for_offset( Elf64_Off offset ) const const section* find_prog_section_for_offset( Elf64_Off offset ) const
{ {
for ( auto sec : sections ) { for ( auto* sec : sections ) {
if ( sec->get_type() == SHT_PROGBITS && if ( sec->get_type() == SHT_PROGBITS &&
is_offset_in_section( offset, sec ) ) is_offset_in_section( offset, sec ) ) {
return sec; return sec;
} }
}
return nullptr; return nullptr;
} }
@ -345,12 +347,12 @@ class elfio
delete header; delete header;
header = nullptr; header = nullptr;
for ( auto it : sections_ ) { for ( auto* it : sections_ ) {
delete it; delete it;
} }
sections_.clear(); sections_.clear();
for ( auto it : segments_ ) { for ( auto* it : segments_ ) {
delete it; delete it;
} }
segments_.clear(); segments_.clear();
@ -380,7 +382,7 @@ class elfio
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
section* create_section() section* create_section()
{ {
section* new_section; section* new_section = nullptr;
unsigned char file_class = get_class(); unsigned char file_class = get_class();
if ( file_class == ELFCLASS64 ) { if ( file_class == ELFCLASS64 ) {
@ -393,7 +395,7 @@ class elfio
return nullptr; return nullptr;
} }
new_section->set_index( (Elf_Half)sections_.size() ); new_section->set_index( static_cast<Elf_Half>( sections_.size() ) );
sections_.emplace_back( new_section ); sections_.emplace_back( new_section );
return new_section; return new_section;
@ -402,7 +404,7 @@ class elfio
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
segment* create_segment() segment* create_segment()
{ {
segment* new_segment; segment* new_segment = nullptr;
unsigned char file_class = header->get_class(); unsigned char file_class = header->get_class();
if ( file_class == ELFCLASS64 ) { if ( file_class == ELFCLASS64 ) {
@ -415,7 +417,7 @@ class elfio
return nullptr; return nullptr;
} }
new_segment->set_index( (Elf_Half)segments_.size() ); new_segment->set_index( static_cast<Elf_Half>( segments_.size() ) );
segments_.emplace_back( new_segment ); segments_.emplace_back( new_segment );
return new_segment; return new_segment;
@ -446,8 +448,9 @@ class elfio
for ( Elf_Half i = 0; i < num; ++i ) { for ( Elf_Half i = 0; i < num; ++i ) {
section* sec = create_section(); section* sec = create_section();
sec->load( stream, (std::streamoff)offset + sec->load( stream,
(std::streampos)i * entry_size ); static_cast<std::streamoff>( offset ) +
static_cast<std::streampos>( i ) * entry_size );
sec->set_index( i ); sec->set_index( i );
// To mark that the section is not permitted to reassign address // To mark that the section is not permitted to reassign address
// during layout calculation // during layout calculation
@ -474,7 +477,7 @@ class elfio
//! Checks whether the addresses of the section entirely fall within the given segment. //! Checks whether the addresses of the section entirely fall within the given segment.
//! It doesn't matter if the addresses are memory addresses, or file offsets, //! It doesn't matter if the addresses are memory addresses, or file offsets,
//! they just need to be in the same address space //! they just need to be in the same address space
bool is_sect_in_seg( Elf64_Off sect_begin, static bool is_sect_in_seg( Elf64_Off sect_begin,
Elf_Xword sect_size, Elf_Xword sect_size,
Elf64_Off seg_begin, Elf64_Off seg_begin,
Elf64_Off seg_end ) Elf64_Off seg_end )
@ -495,7 +498,7 @@ class elfio
Elf64_Off offset = header->get_segments_offset(); Elf64_Off offset = header->get_segments_offset();
for ( Elf_Half i = 0; i < num; ++i ) { for ( Elf_Half i = 0; i < num; ++i ) {
segment* seg; segment* seg = nullptr;
unsigned char file_class = header->get_class(); unsigned char file_class = header->get_class();
if ( file_class == ELFCLASS64 ) { if ( file_class == ELFCLASS64 ) {
@ -508,8 +511,9 @@ class elfio
return false; return false;
} }
seg->load( stream, (std::streamoff)offset + seg->load( stream,
(std::streampos)i * entry_size ); static_cast<std::streamoff>( offset ) +
static_cast<std::streampos>( i ) * entry_size );
seg->set_index( i ); seg->set_index( i );
// Add sections to the segments (similar to readelfs algorithm) // Add sections to the segments (similar to readelfs algorithm)
@ -517,10 +521,10 @@ class elfio
Elf64_Off segEndOffset = segBaseOffset + seg->get_file_size(); Elf64_Off segEndOffset = segBaseOffset + seg->get_file_size();
Elf64_Off segVBaseAddr = seg->get_virtual_address(); Elf64_Off segVBaseAddr = seg->get_virtual_address();
Elf64_Off segVEndAddr = segVBaseAddr + seg->get_memory_size(); Elf64_Off segVEndAddr = segVBaseAddr + seg->get_memory_size();
for ( auto psec : sections ) { for ( auto* psec : sections ) {
// SHF_ALLOC sections are matched based on the virtual address // SHF_ALLOC sections are matched based on the virtual address
// otherwise the file offset is matched // otherwise the file offset is matched
if ( ( psec->get_flags() & SHF_ALLOC ) if ( ( ( psec->get_flags() & SHF_ALLOC ) == SHF_ALLOC )
? is_sect_in_seg( psec->get_address(), ? is_sect_in_seg( psec->get_address(),
psec->get_size(), segVBaseAddr, psec->get_size(), segVBaseAddr,
segVEndAddr ) segVEndAddr )
@ -545,10 +549,11 @@ class elfio
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool save_sections( std::ostream& stream ) bool save_sections( std::ostream& stream )
{ {
for ( auto sec : sections_ ) { for ( auto* sec : sections_ ) {
std::streampos headerPosition = std::streampos headerPosition =
(std::streamoff)header->get_sections_offset() + static_cast<std::streamoff>( header->get_sections_offset() ) +
(std::streampos)header->get_section_entry_size() * static_cast<std::streampos>(
header->get_section_entry_size() ) *
sec->get_index(); sec->get_index();
sec->save( stream, headerPosition, sec->get_offset() ); sec->save( stream, headerPosition, sec->get_offset() );
@ -559,10 +564,11 @@ class elfio
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool save_segments( std::ostream& stream ) bool save_segments( std::ostream& stream )
{ {
for ( auto seg : segments_ ) { for ( auto* seg : segments_ ) {
std::streampos headerPosition = std::streampos headerPosition =
header->get_segments_offset() + static_cast<std::streamoff>( header->get_segments_offset() ) +
(std::streampos)header->get_segment_entry_size() * static_cast<std::streampos>(
header->get_segment_entry_size() ) *
seg->get_index(); seg->get_index();
seg->save( stream, headerPosition, seg->get_offset() ); seg->save( stream, headerPosition, seg->get_offset() );
@ -571,7 +577,7 @@ class elfio
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool is_section_without_segment( unsigned int section_index ) bool is_section_without_segment( unsigned int section_index ) const
{ {
bool found = false; bool found = false;
@ -586,7 +592,7 @@ class elfio
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool is_subsequence_of( segment* seg1, segment* seg2 ) static bool is_subsequence_of( segment* seg1, segment* seg2 )
{ {
// Return 'true' if sections of seg1 are a subset of sections in seg2 // Return 'true' if sections of seg1 are a subset of sections in seg2
const std::vector<Elf_Half>& sections1 = seg1->get_sections(); const std::vector<Elf_Half>& sections1 = seg1->get_sections();
@ -635,11 +641,13 @@ class elfio
} }
} }
if ( i < worklist.size() ) if ( i < worklist.size() ) {
worklist.emplace_back( seg ); worklist.emplace_back( seg );
else }
else {
res.emplace_back( seg ); res.emplace_back( seg );
} }
}
return res; return res;
} }
@ -658,8 +666,9 @@ class elfio
section_align - current_file_pos % section_align; section_align - current_file_pos % section_align;
} }
if ( 0 != sec->get_index() ) if ( 0 != sec->get_index() ) {
sec->set_offset( current_file_pos ); sec->set_offset( current_file_pos );
}
if ( SHT_NOBITS != sec->get_type() && if ( SHT_NOBITS != sec->get_type() &&
SHT_NULL != sec->get_type() ) { SHT_NULL != sec->get_type() ) {
@ -674,7 +683,7 @@ class elfio
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void calc_segment_alignment() void calc_segment_alignment()
{ {
for ( auto seg : segments_ ) { for ( auto* seg : segments_ ) {
for ( int i = 0; i < seg->get_sections_num(); ++i ) { for ( int i = 0; i < seg->get_sections_num(); ++i ) {
section* sect = sections_[seg->get_section_index_at( i )]; section* sect = sections_[seg->get_section_index_at( i )];
if ( sect->get_addr_align() > seg->get_align() ) { if ( sect->get_addr_align() > seg->get_align() ) {
@ -694,7 +703,7 @@ class elfio
// sub sequence of other segments are located at the end // sub sequence of other segments are located at the end
worklist = get_ordered_segments(); worklist = get_ordered_segments();
for ( auto seg : worklist ) { for ( auto* seg : worklist ) {
Elf_Xword segment_memory = 0; Elf_Xword segment_memory = 0;
Elf_Xword segment_filesize = 0; Elf_Xword segment_filesize = 0;
Elf_Xword seg_start_pos = current_file_pos; Elf_Xword seg_start_pos = current_file_pos;
@ -704,18 +713,18 @@ class elfio
seg_start_pos = header->get_segments_offset(); seg_start_pos = header->get_segments_offset();
segment_memory = segment_filesize = segment_memory = segment_filesize =
header->get_segment_entry_size() * header->get_segment_entry_size() *
(Elf_Xword)header->get_segments_num(); static_cast<Elf_Xword>( header->get_segments_num() );
} }
// Special case: // Special case:
else if ( seg->is_offset_initialized() && seg->get_offset() == 0 ) { else if ( seg->is_offset_initialized() && seg->get_offset() == 0 ) {
seg_start_pos = 0; seg_start_pos = 0;
if ( seg->get_sections_num() ) { if ( seg->get_sections_num() > 0 ) {
segment_memory = segment_filesize = current_file_pos; segment_memory = segment_filesize = current_file_pos;
} }
} }
// New segments with not generated sections // New segments with not generated sections
// have to be aligned // have to be aligned
else if ( seg->get_sections_num() && else if ( seg->get_sections_num() > 0 &&
!section_generated[seg->get_section_index_at( 0 )] ) { !section_generated[seg->get_section_index_at( 0 )] ) {
Elf_Xword align = seg->get_align() > 0 ? seg->get_align() : 1; Elf_Xword align = seg->get_align() > 0 ? seg->get_align() : 1;
Elf64_Off cur_page_alignment = current_file_pos % align; Elf64_Off cur_page_alignment = current_file_pos % align;
@ -726,7 +735,7 @@ class elfio
current_file_pos += ( seg->get_align() + error ) % align; current_file_pos += ( seg->get_align() + error ) % align;
seg_start_pos = current_file_pos; seg_start_pos = current_file_pos;
} }
else if ( seg->get_sections_num() ) { else if ( seg->get_sections_num() > 0 ) {
seg_start_pos = seg_start_pos =
sections[seg->get_section_index_at( 0 )]->get_offset(); sections[seg->get_section_index_at( 0 )]->get_offset();
} }
@ -780,14 +789,16 @@ class elfio
// Determine the segment file and memory sizes // Determine the segment file and memory sizes
// Special case .tbss section (NOBITS) in non TLS segment // Special case .tbss section (NOBITS) in non TLS segment
if ( ( sec->get_flags() & SHF_ALLOC ) && if ( ( ( sec->get_flags() & SHF_ALLOC ) == SHF_ALLOC ) &&
!( ( sec->get_flags() & SHF_TLS ) && !( ( ( sec->get_flags() & SHF_TLS ) == SHF_TLS ) &&
( seg->get_type() != PT_TLS ) && ( seg->get_type() != PT_TLS ) &&
( SHT_NOBITS == sec->get_type() ) ) ) ( SHT_NOBITS == sec->get_type() ) ) ) {
segment_memory += sec->get_size() + secAlign; segment_memory += sec->get_size() + secAlign;
}
if ( SHT_NOBITS != sec->get_type() ) if ( SHT_NOBITS != sec->get_type() ) {
segment_filesize += sec->get_size() + secAlign; segment_filesize += sec->get_size() + secAlign;
}
// Nothing to be done when generating nested segments // Nothing to be done when generating nested segments
if ( section_generated[index] ) { if ( section_generated[index] ) {
@ -797,15 +808,18 @@ class elfio
current_file_pos += secAlign; current_file_pos += secAlign;
// Set the section addresses when missing // Set the section addresses when missing
if ( !sec->is_address_initialized() ) if ( !sec->is_address_initialized() ) {
sec->set_address( seg->get_virtual_address() + sec->set_address( seg->get_virtual_address() +
current_file_pos - seg_start_pos ); current_file_pos - seg_start_pos );
}
if ( 0 != sec->get_index() ) if ( 0 != sec->get_index() ) {
sec->set_offset( current_file_pos ); sec->set_offset( current_file_pos );
}
if ( SHT_NOBITS != sec->get_type() ) if ( SHT_NOBITS != sec->get_type() ) {
current_file_pos += sec->get_size(); current_file_pos += sec->get_size();
}
section_generated[index] = true; section_generated[index] = true;
} }
@ -843,10 +857,13 @@ class elfio
{ {
public: public:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Sections( elfio* parent ) : parent( parent ) {} explicit Sections( elfio* parent ) : parent( parent ) {}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Elf_Half size() const { return (Elf_Half)parent->sections_.size(); } Elf_Half size() const
{
return static_cast<Elf_Half>( parent->sections_.size() );
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
section* operator[]( unsigned int index ) const section* operator[]( unsigned int index ) const
@ -865,7 +882,7 @@ class elfio
{ {
section* sec = nullptr; section* sec = nullptr;
for ( auto it : parent->sections_ ) { for ( auto* it : parent->sections_ ) {
if ( it->get_name() == name ) { if ( it->get_name() == name ) {
sec = it; sec = it;
break; break;
@ -920,16 +937,18 @@ class elfio
} sections; } sections;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
public:
friend class Segments; friend class Segments;
class Segments class Segments
{ {
public: public:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Segments( elfio* parent ) : parent( parent ) {} explicit Segments( elfio* parent ) : parent( parent ) {}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Elf_Half size() const { return (Elf_Half)parent->segments_.size(); } Elf_Half size() const
{
return static_cast<Elf_Half>( parent->segments_.size() );
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
segment* operator[]( unsigned int index ) const segment* operator[]( unsigned int index ) const

View File

@ -72,7 +72,6 @@ template <class S, typename T> class array_section_accessor_template
private: private:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private:
const elfio& elf_file; const elfio& elf_file;
S* array_section; S* array_section;
}; };

View File

@ -79,8 +79,8 @@ template <class S> class dynamic_section_accessor_template
// If the tag may have a string table reference, prepare the string // If the tag may have a string table reference, prepare the string
if ( tag == DT_NEEDED || tag == DT_SONAME || tag == DT_RPATH || if ( tag == DT_NEEDED || tag == DT_SONAME || tag == DT_RPATH ||
tag == DT_RUNPATH ) { tag == DT_RUNPATH ) {
string_section_accessor strsec = string_section_accessor strsec(
elf_file.sections[get_string_table_index()]; elf_file.sections[get_string_table_index()] );
const char* result = strsec.get_string( value ); const char* result = strsec.get_string( value );
if ( nullptr == result ) { if ( nullptr == result ) {
str.clear(); str.clear();
@ -109,8 +109,8 @@ template <class S> class dynamic_section_accessor_template
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void add_entry( Elf_Xword tag, const std::string& str ) void add_entry( Elf_Xword tag, const std::string& str )
{ {
string_section_accessor strsec = string_section_accessor strsec(
elf_file.sections[get_string_table_index()]; elf_file.sections[get_string_table_index()] );
Elf_Xword value = strsec.add_string( str ); Elf_Xword value = strsec.add_string( str );
add_entry( tag, value ); add_entry( tag, value );
} }

View File

@ -34,7 +34,8 @@ template <class S> class string_section_accessor_template
{ {
public: public:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
string_section_accessor_template( S* section ) : string_section( section ) explicit string_section_accessor_template( S* section )
: string_section( section )
{ {
} }
@ -60,15 +61,16 @@ template <class S> class string_section_accessor_template
if ( string_section ) { if ( string_section ) {
// Strings are addeded to the end of the current section data // Strings are addeded to the end of the current section data
current_position = (Elf_Word)string_section->get_size(); current_position =
static_cast<Elf_Word>( string_section->get_size() );
if ( current_position == 0 ) { if ( current_position == 0 ) {
char empty_string = '\0'; char empty_string = '\0';
string_section->append_data( &empty_string, 1 ); string_section->append_data( &empty_string, 1 );
current_position++; current_position++;
} }
string_section->append_data( str, string_section->append_data(
(Elf_Word)std::strlen( str ) + 1 ); str, static_cast<Elf_Word>( std::strlen( str ) + 1 ) );
} }
return current_position; return current_position;

View File

@ -148,7 +148,7 @@ class endianess_convertor
unsigned char get_host_encoding() const unsigned char get_host_encoding() const
{ {
static const int tmp = 1; static const int tmp = 1;
if ( 1 == *(const char*)&tmp ) { if ( 1 == *reinterpret_cast<const char*>( &tmp ) ) {
return ELFDATA2LSB; return ELFDATA2LSB;
} }
else { else {
@ -157,15 +157,14 @@ class endianess_convertor
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private:
bool need_conversion; bool need_conversion;
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
inline uint32_t elf_hash( const unsigned char* name ) inline uint32_t elf_hash( const unsigned char* name )
{ {
uint32_t h = 0, g; uint32_t h = 0, g = 0;
while ( *name ) { while ( *name != '\0' ) {
h = ( h << 4 ) + *name++; h = ( h << 4 ) + *name++;
g = h & 0xf0000000; g = h & 0xf0000000;
if ( g != 0 ) if ( g != 0 )
@ -191,10 +190,12 @@ inline std::string to_hex_string( uint64_t value )
while ( value ) { while ( value ) {
auto digit = value & 0xF; auto digit = value & 0xF;
if ( digit < 0xA ) if ( digit < 0xA ) {
str = char( '0' + digit ) + str; str = char( '0' + digit ) + str;
else }
else {
str = char( 'A' + digit - 0xA ) + str; str = char( 'A' + digit - 0xA ) + str;
}
value >>= 4; value >>= 4;
} }
@ -204,7 +205,7 @@ inline std::string to_hex_string( uint64_t value )
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
inline void adjust_stream_size( std::ostream& stream, std::streamsize offset ) inline void adjust_stream_size( std::ostream& stream, std::streamsize offset )
{ {
stream.seekp( 0, stream.end ); stream.seekp( 0, std::ios_base::end );
if ( stream.tellp() < offset ) { if ( stream.tellp() < offset ) {
std::streamsize size = offset - stream.tellp(); std::streamsize size = offset - stream.tellp();
stream.write( std::string( size, '\0' ).c_str(), size ); stream.write( std::string( size, '\0' ).c_str(), size );