mirror of
https://github.com/vtil-project/VTIL-Core
synced 2026-08-17 08:23:03 -04:00
Fix alignment.
This commit is contained in:
parent
b0e5a252f0
commit
d5fd957f87
1 changed files with 112 additions and 112 deletions
|
|
@ -39,52 +39,52 @@
|
|||
namespace vtil::format
|
||||
{
|
||||
// Table renderer configuration.
|
||||
//
|
||||
struct table_rendering_configuration
|
||||
{
|
||||
char vertical_delimiter = '|';
|
||||
char horizontal_delimiter = '-';
|
||||
size_t left_pad = 0;
|
||||
size_t right_pad = 0;
|
||||
//
|
||||
struct table_rendering_configuration
|
||||
{
|
||||
char vertical_delimiter = '|';
|
||||
char horizontal_delimiter = '-';
|
||||
size_t left_pad = 0;
|
||||
size_t right_pad = 0;
|
||||
size_t max_entries = std::numeric_limits<size_t>::max();
|
||||
size_t field_max_length = std::numeric_limits<size_t>::max();
|
||||
};
|
||||
};
|
||||
|
||||
// Declare table structure, data source container must hold a tuple with
|
||||
// every element being string convertible by ::as_string.
|
||||
//
|
||||
template<Iterable C> requires( Tuple<iterator_value_type_t<C>> &&
|
||||
StringConvertible<C> )
|
||||
struct table_view
|
||||
{
|
||||
// Required typedefs.
|
||||
//
|
||||
using entry_type_t = iterator_value_type_t<C>;
|
||||
|
||||
// Declare field count.
|
||||
//
|
||||
static constexpr size_t field_count = std::tuple_size_v<iterator_value_type_t<C>>;
|
||||
|
||||
// Takes a data source, a list of labels, and optionally rendering configuration.
|
||||
//
|
||||
C&& data_source;
|
||||
// Declare table structure, data source container must hold a tuple with
|
||||
// every element being string convertible by ::as_string.
|
||||
//
|
||||
template<Iterable C> requires( Tuple<iterator_value_type_t<C>> &&
|
||||
StringConvertible<C> )
|
||||
struct table_view
|
||||
{
|
||||
// Required typedefs.
|
||||
//
|
||||
using entry_type_t = iterator_value_type_t<C>;
|
||||
|
||||
// Declare field count.
|
||||
//
|
||||
static constexpr size_t field_count = std::tuple_size_v<iterator_value_type_t<C>>;
|
||||
|
||||
// Takes a data source, a list of labels, and optionally rendering configuration.
|
||||
//
|
||||
C&& data_source;
|
||||
table_rendering_configuration config;
|
||||
std::array<std::string_view, field_count> labels;
|
||||
|
||||
constexpr table_view( C&& data_source, std::array<std::string_view, field_count> labels, table_rendering_configuration config = {} )
|
||||
: data_source( std::forward<C>( data_source ) ), labels( std::move( labels ) ), config( std::move( config ) ) {}
|
||||
: data_source( std::forward<C>( data_source ) ), labels( std::move( labels ) ), config( std::move( config ) ) {}
|
||||
|
||||
// Declare string conversion.
|
||||
//
|
||||
std::string to_string() const
|
||||
{
|
||||
// Determine entry count.
|
||||
//
|
||||
const size_t entry_count = std::size( data_source );
|
||||
// Declare string conversion.
|
||||
//
|
||||
std::string to_string() const
|
||||
{
|
||||
// Determine entry count.
|
||||
//
|
||||
const size_t entry_count = std::size( data_source );
|
||||
|
||||
// Convert fields in each entry into string and resize if over limit.
|
||||
//
|
||||
std::vector<std::array<std::string, field_count>> string_entries;
|
||||
// Convert fields in each entry into string and resize if over limit.
|
||||
//
|
||||
std::vector<std::array<std::string, field_count>> string_entries;
|
||||
string_entries.reserve( entry_count );
|
||||
|
||||
for ( auto eit = std::begin( data_source ); eit != std::end( data_source ); ++eit )
|
||||
|
|
@ -110,73 +110,73 @@ namespace vtil::format
|
|||
break;
|
||||
}
|
||||
|
||||
// Determine field lengths.
|
||||
//
|
||||
std::array<size_t, field_count> field_lengths;
|
||||
for ( auto [len, label] : zip( field_lengths, labels ) )
|
||||
len = label.length();
|
||||
for ( auto& fields : string_entries )
|
||||
{
|
||||
for ( auto [len, label] : zip( field_lengths, fields ) )
|
||||
len = std::max( len, label.length() );
|
||||
}
|
||||
// Determine field lengths.
|
||||
//
|
||||
std::array<size_t, field_count> field_lengths;
|
||||
for ( auto [len, label] : zip( field_lengths, labels ) )
|
||||
len = label.length();
|
||||
for ( auto& fields : string_entries )
|
||||
{
|
||||
for ( auto [len, label] : zip( field_lengths, fields ) )
|
||||
len = std::max( len, label.length() );
|
||||
}
|
||||
|
||||
// Allocate a buffer for the output.
|
||||
//
|
||||
// Allocate a buffer for the output.
|
||||
//
|
||||
const bool table_overflow = string_entries.size() != entry_count;
|
||||
const size_t line_length =
|
||||
/* field data */ std::accumulate( field_lengths.begin(), field_lengths.end(), 0ull ) +
|
||||
/* delimiters */ 2 + field_count * 3 - 1 +
|
||||
/* new line */ 1;
|
||||
const size_t line_count =
|
||||
const size_t line_length =
|
||||
/* field data */ std::accumulate( field_lengths.begin(), field_lengths.end(), 0ull ) +
|
||||
/* delimiters */ 2 + field_count * 3 - 1 +
|
||||
/* new line */ 1;
|
||||
const size_t line_count =
|
||||
/* active entries */ string_entries.size() +
|
||||
/* labels */ 1 +
|
||||
/* delimiters */ 3 + table_overflow;
|
||||
|
||||
std::string result( line_count * ( line_length + config.left_pad + config.right_pad ), '\0' );
|
||||
|
||||
// Declare the iterator and data primitives.
|
||||
//
|
||||
auto iterator = result.begin();
|
||||
auto write = [ & ] ( auto... cs ) { ( ( *iterator++ = cs ), ... ); };
|
||||
auto write_n = [ & ] ( const std::string_view& v ) { iterator = std::copy( v.begin(), v.end(), iterator ); };
|
||||
auto fill = [ & ] ( char c, size_t n ) { iterator = std::fill_n( iterator, n, c ); };
|
||||
auto begl = [ & ] () { fill( ' ', config.left_pad ); };
|
||||
auto rendl = [ & ] () { fill( ' ', config.right_pad ); *( iterator - 1 ) = '\n'; };
|
||||
|
||||
std::string result( line_count * ( line_length + config.left_pad + config.right_pad ), '\0' );
|
||||
|
||||
// Declare the iterator and data primitives.
|
||||
//
|
||||
auto iterator = result.begin();
|
||||
auto write = [ & ] ( auto... cs ) { ( ( *iterator++ = cs ), ... ); };
|
||||
auto write_n = [ & ] ( const std::string_view& v ) { iterator = std::copy( v.begin(), v.end(), iterator ); };
|
||||
auto fill = [ & ] ( char c, size_t n ) { iterator = std::fill_n( iterator, n, c ); };
|
||||
auto begl = [ & ] () { fill( ' ', config.left_pad ); };
|
||||
auto rendl = [ & ] () { fill( ' ', config.right_pad ); *( iterator - 1 ) = '\n'; };
|
||||
|
||||
// Declare helpers for writing lines.
|
||||
//
|
||||
auto write_table_limit = [ & ] ()
|
||||
{
|
||||
begl();
|
||||
fill( config.horizontal_delimiter, line_length );
|
||||
rendl();
|
||||
};
|
||||
auto write_fields = [ & ] ( const auto& fields )
|
||||
{
|
||||
begl();
|
||||
write( config.vertical_delimiter, ' ' );
|
||||
for ( auto [field, len] : zip( fields, field_lengths ) )
|
||||
{
|
||||
auto end_real = iterator + len;
|
||||
write_n( field );
|
||||
if ( end_real > iterator )
|
||||
fill( ' ', end_real - iterator );
|
||||
write( ' ', config.vertical_delimiter, ' ' );
|
||||
}
|
||||
rendl();
|
||||
};
|
||||
auto write_label_delim = [ & ] ()
|
||||
{
|
||||
begl();
|
||||
write( config.vertical_delimiter, config.horizontal_delimiter );
|
||||
for ( size_t field_len : field_lengths )
|
||||
{
|
||||
fill( config.horizontal_delimiter, field_len );
|
||||
write( config.horizontal_delimiter, config.vertical_delimiter, config.horizontal_delimiter );
|
||||
}
|
||||
rendl();
|
||||
};
|
||||
// Declare helpers for writing lines.
|
||||
//
|
||||
auto write_table_limit = [ & ] ()
|
||||
{
|
||||
begl();
|
||||
fill( config.horizontal_delimiter, line_length );
|
||||
rendl();
|
||||
};
|
||||
auto write_fields = [ & ] ( const auto& fields )
|
||||
{
|
||||
begl();
|
||||
write( config.vertical_delimiter, ' ' );
|
||||
for ( auto [field, len] : zip( fields, field_lengths ) )
|
||||
{
|
||||
auto end_real = iterator + len;
|
||||
write_n( field );
|
||||
if ( end_real > iterator )
|
||||
fill( ' ', end_real - iterator );
|
||||
write( ' ', config.vertical_delimiter, ' ' );
|
||||
}
|
||||
rendl();
|
||||
};
|
||||
auto write_label_delim = [ & ] ()
|
||||
{
|
||||
begl();
|
||||
write( config.vertical_delimiter, config.horizontal_delimiter );
|
||||
for ( size_t field_len : field_lengths )
|
||||
{
|
||||
fill( config.horizontal_delimiter, field_len );
|
||||
write( config.horizontal_delimiter, config.vertical_delimiter, config.horizontal_delimiter );
|
||||
}
|
||||
rendl();
|
||||
};
|
||||
auto write_overflow_delim = [ & ] ()
|
||||
{
|
||||
if ( table_overflow )
|
||||
|
|
@ -189,21 +189,21 @@ namespace vtil::format
|
|||
}
|
||||
};
|
||||
|
||||
// Format the whole table and return the result.
|
||||
//
|
||||
write_table_limit();
|
||||
write_fields( labels );
|
||||
write_label_delim();
|
||||
for( auto& fields : string_entries )
|
||||
write_fields( fields );
|
||||
// Format the whole table and return the result.
|
||||
//
|
||||
write_table_limit();
|
||||
write_fields( labels );
|
||||
write_label_delim();
|
||||
for( auto& fields : string_entries )
|
||||
write_fields( fields );
|
||||
write_overflow_delim();
|
||||
write_table_limit();
|
||||
return result;
|
||||
}
|
||||
};
|
||||
write_table_limit();
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
// Declare deduction guide.
|
||||
//
|
||||
template<typename C> table_view( C&&, std::initializer_list<std::string_view> )->table_view<C>;
|
||||
// Declare deduction guide.
|
||||
//
|
||||
template<typename C> table_view( C&&, std::initializer_list<std::string_view> )->table_view<C>;
|
||||
template<typename C> table_view( C&&, std::initializer_list<std::string_view>, table_rendering_configuration )->table_view<C>;
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue