12 template< 
class Type, 
typename Enabled >
 
   15     Type 
Read( 
const char * source, 
Context const * context )
 const 
   17         std::stringstream in( source );
 
   26         if( in.fail() || !in.eof() )
 
   28             std::string rest(std::istreambuf_iterator<char>(in), {});
 
   29             context->
log( 
SRC_INFO, 
iv::Defs::Log::Warning, 
"String '", source, 
"' can not be read as type ", 
typeid( Type ).name(), 
" using stream operator >>. Rest: '", rest, 
"'." );
 
   36     std::string 
Write( Type 
const & value, 
Context const * context )
 const 
   48     bool Read( 
const char * source, 
Context const * context )
 const 
   50         std::string val( source );
 
   51         return val == 
"true" || val == 
"1";
 
   54     std::string 
Write( 
bool const & value, 
Context const * context )
 const 
   56         return value ? 
"true" : 
"false";
 
   64     std::string 
Read( 
const char * source, 
Context const * context )
 const 
   69     std::string 
Write( std::string 
const & value, 
Context const * context )
 const 
   79     std::string 
Write( 
const char * 
const & value, 
Context const * context )
 const 
   89     T * 
Read( 
const char * source, 
Context const * context )
 const 
   94     std::string 
Write( T * 
const & value, 
Context const * context )
 const 
  104     std::nullptr_t 
Read( 
const char * source, 
Context const * context )
 const 
  109     std::string 
Write( std::nullptr_t 
const &, 
Context const * context )
 const 
  119     static constexpr 
const char * NIL = 
"nil";
 
  121     std::optional< T > 
Read( 
const char * name, 
Context const * context )
 
  123         if( strcmp( name, NIL ) == 0 )
 
  124             return std::optional< T >( {} );
 
  129     std::string 
Write( std::optional< T > 
const & value, 
Context const * context )
 const 
  131         if( value.has_value() )
 
  134             return std::string( NIL );
 
  139 template< 
class T, 
class U >
 
  142     std::pair< T, U > 
Read( 
const char * name, 
Context const * context )
 
  148         size_t len = strlen( name );
 
  149         while( i < len && name[ i ] != 
'(' )
 
  153         while( i < len && i != 
',' )
 
  154             first += name[ i++ ];
 
  157         while( i < len && i != 
')' )
 
  158             second += name[ i++ ];
 
  160         T t = StringIO_Read< T >( first.c_str(), context );
 
  161         U u = StringIO_Read< U >( second.c_str(), context );
 
  162         return std::pair( t, u );
 
  165     std::string 
Write( std::pair< T, U > 
const & value, 
Context const * context )
 const 
  167         std::stringstream ss;
 
  168         ss << 
"( " << StringIO_Write< T >( value.first, context ) << 
", " << StringIO_Write< U >( value.second, context ) << 
" )";
 
  176 template< 
class Float >
 
  177 struct StringIO< Float, std::enable_if_t< std::is_floating_point< Float >::value > >
 
  182         if( strcmp( source, 
"inf" ) == 0 )
 
  183             return std::numeric_limits< Float >::infinity();
 
  184         else if( strcmp( source, 
"+inf" ) == 0 )
 
  185             return std::numeric_limits< Float >::infinity();
 
  186         else if( strcmp( source, 
"-inf" ) == 0 )
 
  187             return - std::numeric_limits< Float >::infinity();
 
  188         else if( strcmp( source, 
"nan" ) == 0 )
 
  189             return - std::numeric_limits< Float >::quiet_NaN();
 
  190         else if( strcmp( source, 
"NaN" ) == 0 )
 
  191             return - std::numeric_limits< Float >::quiet_NaN();
 
  194         std::stringstream in( source );
 
  203         if( in.fail() || !in.eof() )
 
  205             std::string rest(std::istreambuf_iterator<char>(in), {});
 
  206             context->
warning( 
SRC_INFO, 
"String '", source, 
"' can not be read as float using stream operator >>. Rest: '", rest, 
"'." );
 
  213     std::string 
Write( Float 
const & value, 
Context const * context )
 const 
  215         return std::to_string( value );
 
  221 template< 
class TypedRuntimeId >
 
  222 struct StringIO< TypedRuntimeId, std::enable_if_t< std::is_base_of< RuntimeId< TypedRuntimeId >, TypedRuntimeId >::value > >
 
  224     TypedRuntimeId 
Read( 
const char * source, 
Context const * context )
 const 
  226         auto result = TypedRuntimeId( source );
 
  227         if( !result.valid() )
 
  228             context->
warning( 
SRC_INFO, 
"Can not read string '", source, 
"' as RuntimeId ", 
typeid( TypedRuntimeId ).name(), 
"." );
 
  233     std::string 
Write( TypedRuntimeId 
const & value, 
Context const * context )
 const 
  235         return value.persistent_value();