From bb516602727e99918e6b978680a11cce9868db50 Mon Sep 17 00:00:00 2001 From: ADAM David Alan Martin Date: Tue, 31 Oct 2023 02:17:27 -0400 Subject: [PATCH] Simplify the delimiters --- IOStreams/IStreamable.h | 2 +- IOStreams/OStreamable.h | 2 +- IOStreams/OStreamable.test/0.cc | 12 +-- IOStreams/StreamState.h | 39 ++++++--- IOStreams/delimiters.h | 148 +++++--------------------------- IOStreams/streamable.test/0.cc | 6 +- 6 files changed, 64 insertions(+), 145 deletions(-) diff --git a/IOStreams/IStreamable.h b/IOStreams/IStreamable.h index 8b2c2c4..d9a1c32 100644 --- a/IOStreams/IStreamable.h +++ b/IOStreams/IStreamable.h @@ -34,7 +34,7 @@ namespace Alepha::Hydrogen::IOStreams ::detail:: istreamable_module const auto commentChar= line.find( "#" ); if( commentChar != std::string::npos ) line= line.substr( line.find( "#" ) ); - const auto delim= getFieldDelimiter( is ); + const auto delim= getDelimiter( fieldDelimiter, is ); const auto tokens= split( line, delim ); auto decomposed= Alepha::Reflection::tuplizeAggregate( istreamable ); diff --git a/IOStreams/OStreamable.h b/IOStreams/OStreamable.h index 0e3661f..fb91b26 100644 --- a/IOStreams/OStreamable.h +++ b/IOStreams/OStreamable.h @@ -45,7 +45,7 @@ namespace Alepha::Hydrogen::IOStreams ::detail:: ostreamable_module // aggregates, so we'll go with this simple case for now... tuple_for_each( decomposed ) <=[&]( const auto &element ) { - if( not first ) os << FieldDelimiter; + if( not first ) os << fieldDelimiter; first= false; os << element; }; diff --git a/IOStreams/OStreamable.test/0.cc b/IOStreams/OStreamable.test/0.cc index 103b723..cffc0c7 100644 --- a/IOStreams/OStreamable.test/0.cc +++ b/IOStreams/OStreamable.test/0.cc @@ -31,8 +31,9 @@ namespace stringify_specific( const Agg &agg, const std::string delim ) { std::ostringstream oss; - Alepha::IOStreams::setGlobalFieldDelimiter( "YOU SHOULD NOT SEE THIS" ); - oss << Alepha::IOStreams::setFieldDelimiter( delim ); + using Alepha::IOStreams::fieldDelimiter; + Alepha::IOStreams::setGlobalDelimiter( fieldDelimiter, "YOU SHOULD NOT SEE THIS" ); + oss << Alepha::IOStreams::setDelimiter( fieldDelimiter, delim ); oss << agg; return std::move( oss ).str(); } @@ -41,7 +42,8 @@ namespace stringify_global( const Agg &agg, const std::string delim ) { std::ostringstream oss; - Alepha::IOStreams::setGlobalFieldDelimiter( delim ); + using Alepha::IOStreams::fieldDelimiter; + Alepha::IOStreams::setGlobalDelimiter( fieldDelimiter, delim ); oss << agg; return std::move( oss ).str(); } @@ -81,8 +83,8 @@ static auto init= Alepha::Utility::enroll <=[] []( const Agg agg, const std::string delim ) { using Alepha::IOStreams::String; - using Alepha::IOStreams::setFieldDelimiter; - return String{} << setFieldDelimiter( delim ) << agg << FinishString; + using Alepha::IOStreams::fieldDelimiter; + return String{} << setDelimiter( fieldDelimiter, delim ) << agg << FinishString; } > ::Cases diff --git a/IOStreams/StreamState.h b/IOStreams/StreamState.h index e538f0e..e2d7e77 100644 --- a/IOStreams/StreamState.h +++ b/IOStreams/StreamState.h @@ -11,7 +11,7 @@ namespace Alepha::Hydrogen::IOStreams ::detail:: stream_state { inline namespace exports { - template< typename Tag, typename Type, auto Default= [] { return Type{}; } > + template< typename > class StreamState; } @@ -20,7 +20,14 @@ namespace Alepha::Hydrogen::IOStreams ::detail:: stream_state { private: const int index= std::ios::xalloc(); + std::function< Type () > build; + public: + explicit + StreamState( const std::function< Type () > build ) + : build( build ) {} + + private: static Type *& get_ptr( std::ios_base &ios, const int idx ) { @@ -30,7 +37,7 @@ namespace Alepha::Hydrogen::IOStreams ::detail:: stream_state Type *& get_ptr( std::ios_base &ios ) { - get_ptr( ios, index ); + return get_ptr( ios, index ); } static void @@ -50,7 +57,7 @@ namespace Alepha::Hydrogen::IOStreams ::detail:: stream_state } else if( event == std::ios_base::copyfmt_event ) { - get_ptr( ios, idx )= new Type{ get( ios, idx ) }; + get_ptr( ios, idx )= new Type{ *get_ptr( ios, idx ) }; } } @@ -63,13 +70,13 @@ namespace Alepha::Hydrogen::IOStreams ::detail:: stream_state void init( std::ios_base &ios ) { - if( not ios.iword( idx ) ) + if( not ios.iword( index ) ) { - ios.iword( index() )= 1; - ios.register_callback( callback, idx ); + ios.iword( index )= 1; + ios.register_callback( callback, index ); } - auto *&ptr= get_ptr( ios, idx ); - if( not ptr ) ptr= new Type{ Default() }; + auto *&ptr= get_ptr( ios, index ); + if( not ptr ) ptr= new Type{ build() }; } public: @@ -80,6 +87,12 @@ namespace Alepha::Hydrogen::IOStreams ::detail:: stream_state return *get_ptr( ios ); } + void + setDefault( const Type value ) + { + build= [value] { return value; }; + } + struct Setter { StreamState *state; @@ -88,17 +101,23 @@ namespace Alepha::Hydrogen::IOStreams ::detail:: stream_state friend std::ostream & operator << ( std::ostream &os, const Setter &s ) { - s.get( os )= s.val; + s.state->get( os )= s.val; return os; } friend std::istream & operator >> ( std::istream &is, const Setter &s ) { - s.get( is )= s.val; + s.state->get( is )= s.val; return is; } }; + + auto + makeSetter( const Type val ) + { + return Setter{ this, val }; + } }; } diff --git a/IOStreams/delimiters.h b/IOStreams/delimiters.h index 91c5a08..8cffc76 100644 --- a/IOStreams/delimiters.h +++ b/IOStreams/delimiters.h @@ -24,146 +24,44 @@ namespace Alepha::Hydrogen::IOStreams ::detail:: delimiters_m struct Delimiter : boost::noncopyable { - std::string current; - StreamState state; + StreamState< std::string > state; explicit - Delimiter( const std::string current ) - : current( current ) - { - } + Delimiter( const std::string dflt ) + : state( [dflt] { return dflt; } ) {} }; - template< ConstexprString s > - using CreateDelimiter= void ( const DelimiterParamType< s > & ); - - template< typename T > - constexpr is_delimiter_v= false; - - template< ConstexprString s > - constexpr is_delimiter_v< CreateDelimiter< s > >; - - inline StaticValue< std::map< void (*)( const DelimiterBase & ), StreamState< Delim, std::string, globalDelimiter< - - - template< typename Delimiter > - using DelimiterStateByValue= StreamState< Delim, std::string, globalDelimiter< Delim > >; - - inline namespace exports - { - Delimiter< "\t"_cs > FieldDelimiter; - Delimiter< "\t"_cs > FieldDelimiter2; - - static_assert( FieldDelimiter != FieldDelimiter2 ); - - Delimiter< "\n"_cs > RecordDelimiter; - } - - namespace storage - { - template< auto Delim > - inline StaticValue< std::optional< std::string > > globalDelimiter; - } - - template< auto Delim > - std::string & - globalDelimiter() - { - if( not storage::globalDelimiter< Delim >().has_value() ) - { - - storage::globalDelimiter()= std::string{} + static_cast< char >( Delim ); - } - assert( storage::globalDelimiter< Delim >().has_value() ); - return storage::globalFieldDelimiter().value(); - } - namespace exports { - template< auto Delim > - void - setGlobaDelimiter( const std::string delim ) - { - storage::globalDelimiter< Delim >()= delim; - } - } - - template< auto Delim > - using DelimiterStateByValue= StreamState< Delim, std::string, globalDelimiter< Delim > >; - - - - template< typename DelimType > - using DelimiterState= StreamState< Delim, std::string, globalDelimiter >; - - - struct DelimWrap - { - template< typename Delim > - Delim val; - }; - - std::ostream & - operator << ( std::ostream &os, auto DelimVal ) - { - return os << DelimiterState< decltype( DelimVal ) >::get( os ); - } - - namespace exports - { - auto - setFieldDelimiter( const std::string delim ) - { - return FieldDelimiterState::Setter{ delim }; - } - - const auto & - getFieldDelimiter( std::ios_base &ios ) - { - return FieldDelimiterState::get( ios ); - } - } - - inline const int recordIndex= std::ios::xalloc(); - - inline void - setRecordDelimiterOnIOS( std::ios &ios, const char ch ) - { - ios.iword( recordIndex )= ch; - } - - inline char - getRecordDelimiter( std::ios &ios ) - { - if( ios.iword( recordIndex ) == 0 ) setRecordDelimiterOnIOS( ios, globalRecordDelimiter() ); - - return ios.iword( recordIndex ); + inline Delimiter fieldDelimiter{ "\t" }; + inline Delimiter recordDelimiter{ "\n" }; } inline std::ostream & - operator << ( std::ostream &os, decltype( RecordDelimiter ) ) + operator << ( std::ostream &os, Delimiter &delim ) { - return os << getRecordDelimiter( os ); + const auto &s= delim.state.get( os ); + return os << s; } - struct RecordDelimiterSetter - { - const char ch; - - friend std::ostream & - operator << ( std::ostream &os, const RecordDelimiterSetter &s ) - { - setRecordDelimiterOnIOS( os, s.ch ); - return os; - } - }; - namespace exports { - auto - setRecordDelimiter( const char ch ) + inline std::string + getDelimiter( Delimiter &delim, std::ios_base &ios ) { - return RecordDelimiterSetter{ ch }; + return delim.state.get( ios ); + } + + inline auto + setDelimiter( Delimiter &delim, const std::string s ) + { + return delim.state.makeSetter( s ); + } + + inline void + setGlobalDelimiter( Delimiter &delim, const std::string s ) + { + return delim.state.setDefault( s ); } } } diff --git a/IOStreams/streamable.test/0.cc b/IOStreams/streamable.test/0.cc index c0b2e17..28f3269 100644 --- a/IOStreams/streamable.test/0.cc +++ b/IOStreams/streamable.test/0.cc @@ -31,14 +31,14 @@ namespace std::string roundTripString( const std::string text, const std::string delim ) { - using namespace Alepha::IOStreams::exports::delimiters; + using namespace Alepha::IOStreams::exports::delimiters_m; std::istringstream iss{ text }; Agg agg; - iss >> setFieldDelimiter( delim ) >> agg; + iss >> setDelimiter( fieldDelimiter, delim ) >> agg; std::ostringstream oss; - oss << setFieldDelimiter( delim ) << agg; + oss << setDelimiter( fieldDelimiter, delim ) << agg; return oss.str(); }