From 4a74921cb8b058ff703bc37db7397e580fa76082 Mon Sep 17 00:00:00 2001 From: ADAM David Alan Martin Date: Tue, 31 Oct 2023 01:44:34 -0400 Subject: [PATCH] I started a weird rewrite, but I'll likely abandon it. But I'll keep this commit in my history, in case I want to try again. --- IOStreams/StreamState.h | 46 +++++++++--------- IOStreams/delimiters.h | 102 +++++++++++++++++++++++++++++----------- 2 files changed, 97 insertions(+), 51 deletions(-) diff --git a/IOStreams/StreamState.h b/IOStreams/StreamState.h index 5366819..e538f0e 100644 --- a/IOStreams/StreamState.h +++ b/IOStreams/StreamState.h @@ -15,43 +15,42 @@ namespace Alepha::Hydrogen::IOStreams ::detail:: stream_state class StreamState; } - template< typename Tag, typename Type, auto Default > - class exports::StreamState + template< typename Type > + class exports::StreamState : boost::noncopyable { private: - static auto - index() - { - static const auto rv= std::ios::xalloc(); - return rv; - } + const int index= std::ios::xalloc(); static Type *& + get_ptr( std::ios_base &ios, const int idx ) + { + return reinterpret_cast< Type *& >( ios.pword( idx ) ); + } + + Type *& get_ptr( std::ios_base &ios ) { - return reinterpret_cast< Type *& >( ios.pword( index() ) ); + get_ptr( ios, index ); } static void - destroy( std::ios_base &ios ) + destroy( std::ios_base &ios, const int idx ) { - delete get_ptr( ios ); - get_ptr( ios )= nullptr; + delete get_ptr( ios, idx ); + get_ptr( ios, idx )= nullptr; } static void callback_impl( const std::ios_base::event event, std::ios_base &ios, const int idx ) { - if( idx != index() ) throw std::logic_error( "Wrong index." ); - - if( event == std::ios_base::erase_event ) destroy( ios ); + if( event == std::ios_base::erase_event ) destroy( ios, idx ); else if( event == std::ios_base::imbue_event ) { // Nothing to do... until I develop locale support. } else if( event == std::ios_base::copyfmt_event ) { - get_ptr( ios )= new Type{ get( ios ) }; + get_ptr( ios, idx )= new Type{ get( ios, idx ) }; } } @@ -61,20 +60,20 @@ namespace Alepha::Hydrogen::IOStreams ::detail:: stream_state return callback_impl( event, ios, idx ); } - static void + void init( std::ios_base &ios ) { - if( not ios.iword( index() ) ) + if( not ios.iword( idx ) ) { ios.iword( index() )= 1; - ios.register_callback( callback, index() ); + ios.register_callback( callback, idx ); } - auto *&ptr= get_ptr( ios ); + auto *&ptr= get_ptr( ios, idx ); if( not ptr ) ptr= new Type{ Default() }; } public: - static Type & + Type & get( std::ios_base &ios ) { init( ios ); @@ -83,19 +82,20 @@ namespace Alepha::Hydrogen::IOStreams ::detail:: stream_state struct Setter { + StreamState *state; const Type val; friend std::ostream & operator << ( std::ostream &os, const Setter &s ) { - StreamState::get( os )= s.val; + s.get( os )= s.val; return os; } friend std::istream & operator >> ( std::istream &is, const Setter &s ) { - StreamState::get( is )= s.val; + s.get( is )= s.val; return is; } }; diff --git a/IOStreams/delimiters.h b/IOStreams/delimiters.h index becbd99..91c5a08 100644 --- a/IOStreams/delimiters.h +++ b/IOStreams/delimiters.h @@ -12,55 +12,101 @@ static_assert( __cplusplus > 2020'00 ); #include -namespace Alepha::Hydrogen::IOStreams ::detail:: delimiters +namespace Alepha::Hydrogen::IOStreams ::detail:: delimiters_m { + inline namespace exports {} + + // Syntax I want to work: + // + // std::cout << someDelimiter; + // auto value= getDelimiter( someDelimiter, std::cin ); + // std::cout << setDelimiter( someDelimiter, value ); + + struct Delimiter : boost::noncopyable + { + std::string current; + StreamState state; + + explicit + Delimiter( const std::string current ) + : current( current ) + { + } + }; + + 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 { - enum { FieldDelimiter }; - enum { RecordDelimiter }; - } + Delimiter< "\t"_cs > FieldDelimiter; + Delimiter< "\t"_cs > FieldDelimiter2; - namespace C - { - const std::string defaultFieldDelimiter= "\t"; - const char defaultRecordDelimiter= '\n'; + static_assert( FieldDelimiter != FieldDelimiter2 ); + + Delimiter< "\n"_cs > RecordDelimiter; } namespace storage { - inline StaticValue< std::optional< std::string > > globalFieldDelimiter; - inline StaticValue< std::optional< char > > globalRecordDelimiter; + template< auto Delim > + inline StaticValue< std::optional< std::string > > globalDelimiter; } - inline std::string - globalFieldDelimiter() + template< auto Delim > + std::string & + globalDelimiter() { - if( not storage::globalFieldDelimiter().has_value() ) storage::globalFieldDelimiter()= C::defaultFieldDelimiter; + 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 { - inline void - setGlobalFieldDelimiter( const std::string delim ) + template< auto Delim > + void + setGlobaDelimiter( const std::string delim ) { - storage::globalFieldDelimiter()= delim; + storage::globalDelimiter< Delim >()= delim; } } - inline char - globalRecordDelimiter() - { - if( not storage::globalRecordDelimiter().has_value() ) storage::globalRecordDelimiter()= C::defaultRecordDelimiter; - return storage::globalRecordDelimiter().value(); - } + template< auto Delim > + using DelimiterStateByValue= StreamState< Delim, std::string, globalDelimiter< Delim > >; - using FieldDelimiterState= StreamState< decltype( FieldDelimiter ), std::string, globalFieldDelimiter >; + - inline std::ostream & - operator << ( std::ostream &os, decltype( FieldDelimiter ) ) + 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 << FieldDelimiterState::get( os ); + return os << DelimiterState< decltype( DelimVal ) >::get( os ); } namespace exports @@ -122,7 +168,7 @@ namespace Alepha::Hydrogen::IOStreams ::detail:: delimiters } } -namespace Alepha::Hydrogen::IOStreams::inline exports::inline delimiters +namespace Alepha::Hydrogen::IOStreams::inline exports::inline delimiters_m { - using namespace detail::delimiters::exports; + using namespace detail::delimiters_m::exports; }