@ -1276,6 +1276,10 @@ template <typename T> const T& unwrap(const std::reference_wrapper<T>& v) {
}
}
class dynamic_arg_list {
class dynamic_arg_list {
public :
static constexpr std : : size_t max_pool_string_size = 140 ;
private :
// Workaround for clang's -Wweak-vtables. Unlike for regular classes, for
// Workaround for clang's -Wweak-vtables. Unlike for regular classes, for
// templates it doesn't complain about inability to deduce single translation
// templates it doesn't complain about inability to deduce single translation
// unit for placing vtable. So storage_node_base is made a fake template.
// unit for placing vtable. So storage_node_base is made a fake template.
@ -1284,6 +1288,10 @@ class dynamic_arg_list {
std : : unique_ptr < node < > > next ;
std : : unique_ptr < node < > > next ;
} ;
} ;
// Pool storage allocation functions.
static void * allocate_from_pool ( std : : size_t sz ) ;
static void free_from_pool ( void * ptr ) ;
template < typename T > struct typed_node : node < > {
template < typename T > struct typed_node : node < > {
T value ;
T value ;
@ -1295,9 +1303,35 @@ class dynamic_arg_list {
: value ( arg . data ( ) , arg . size ( ) ) { }
: value ( arg . data ( ) , arg . size ( ) ) { }
} ;
} ;
struct pooled_node : node < > {
std : : array < char , max_pool_string_size > value ;
static void * operator new ( std : : size_t sz ) {
return allocate_from_pool ( sz ) ;
}
static void operator delete ( void * ptr ) {
free_from_pool ( ptr ) ;
}
pooled_node ( const char * str , std : : size_t sz ) {
FMT_ASSERT ( sz < value . size ( ) , " String is too big " ) ;
std : : copy ( str , str + sz , value . begin ( ) ) ;
}
} ;
std : : unique_ptr < node < > > head_ ;
std : : unique_ptr < node < > > head_ ;
public :
public :
static constexpr std : : size_t max_pool_node_size = sizeof ( pooled_node ) ;
const char * push_small_string ( const char * str , std : : size_t sz ) {
auto new_node = std : : unique_ptr < pooled_node > ( new pooled_node ( str , sz ) ) ;
auto & value = new_node - > value ;
new_node - > next = std : : move ( head_ ) ;
head_ = std : : move ( new_node ) ;
return value . data ( ) ;
}
template < typename T , typename Arg > const T & push ( const Arg & arg ) {
template < typename T , typename Arg > const T & push ( const Arg & arg ) {
auto new_node = std : : unique_ptr < typed_node < T > > ( new typed_node < T > ( arg ) ) ;
auto new_node = std : : unique_ptr < typed_node < T > > ( new typed_node < T > ( arg ) ) ;
auto & value = new_node - > value ;
auto & value = new_node - > value ;
@ -1541,12 +1575,25 @@ class dynamic_format_arg_store
std : : string result = fmt : : vformat ( " {} and {} and {} " , store ) ;
std : : string result = fmt : : vformat ( " {} and {} and {} " , store ) ;
\ endrst
\ endrst
*/
*/
template < typename T > void push_back ( const T & arg ) {
template < typename T ,
if ( detail : : const_check ( need_copy < T > : : value ) )
typename std : : enable_if < detail : : is_string < typename std : : decay < T > : : type > : : value , int > : : type = 0 >
void push_back ( const T & arg ) {
fmt : : string_view view ( arg ) ;
if ( view . size ( ) + 1 < dynamic_args_ . max_pool_string_size ) {
emplace_arg ( dynamic_args_ . push_small_string ( view . data ( ) , view . size ( ) + 1 ) ) ;
} else {
emplace_arg ( dynamic_args_ . push < stored_type < T > > ( arg ) ) ;
emplace_arg ( dynamic_args_ . push < stored_type < T > > ( arg ) ) ;
else
}
}
template < typename T ,
typename std : : enable_if < ! detail : : is_string < typename std : : decay < T > : : type > : : value , int > : : type = 0 >
void push_back ( const T & arg ) {
if ( detail : : const_check ( need_copy < T > : : value ) ) {
emplace_arg ( dynamic_args_ . push < stored_type < T > > ( arg ) ) ;
} else {
emplace_arg ( detail : : unwrap ( arg ) ) ;
emplace_arg ( detail : : unwrap ( arg ) ) ;
}
}
}
/**
/**
\ rst
\ rst