1
0
forked from Alepha/Alepha

Delimiters helpers which work with ostream helpers.

This commit is contained in:
2023-10-23 03:31:23 -04:00
parent 3a92d2b788
commit e1d3374e09
5 changed files with 195 additions and 2 deletions

View File

@ -1 +1,2 @@
add_subdirectory( IStreamable.test )
add_subdirectory( OStreamable.test )

View File

@ -13,6 +13,8 @@ static_assert( __cplusplus > 2020'00 );
#include <Alepha/Reflection/tuplizeAggregate.h>
#include <Alepha/IOStreams/delimiters.h>
namespace Alepha::Hydrogen::IOStreams ::detail:: ostreamable_module
{
inline namespace exports
@ -43,11 +45,10 @@ 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 << '\t';
if( not first ) os << FieldDelimiter;
first= false;
os << element;
};
os << '\n';
return os;
}

View File

@ -0,0 +1,50 @@
static_assert( __cplusplus > 2020'00 );
#include "../OStreamable.h"
#include <Alepha/Testing/TableTest.h>
#include <Alepha/Testing/test.h>
#include <sstream>
#include <Alepha/auto_comparable.h>
#include <Alepha/IOStreams/delimiters.h>
namespace
{
template< typename= Alepha::Capabilities< Alepha::auto_comparable, Alepha::IOStreams::OStreamable > >
struct Agg_core
{
int x;
int y;
int z;
};
using Agg= Agg_core<>;
static_assert( Alepha::Aggregate< Agg > );
static_assert( Alepha::Capability< Agg, Alepha::IOStreams::OStreamable > );
auto
stringify( const Agg &agg, const char delim )
{
std::ostringstream oss;
oss << Alepha::IOStreams::setFieldDelimiter( delim );
oss << agg;
return std::move( oss ).str();
}
}
static auto init= Alepha::Utility::enroll <=[]
{
using namespace Alepha::Testing::exports;
using namespace Alepha::Testing::literals::test_literals;
"Simple OStream"_test <=TableTest< stringify >
::Cases
{
{ "smoke test", { { 1, 2, 3 }, '\t' }, { "1\t2\t3" } },
{ "smoke test", { { 1, 2, 3 }, ',' }, { "1,2,3" } },
};
};

View File

@ -0,0 +1,3 @@
link_libraries( unit-test )
unit_test( 0 )

138
IOStreams/delimiters.h Normal file
View File

@ -0,0 +1,138 @@
static_assert( __cplusplus > 2020'00 );
#pragma once
#include <Alepha/Alepha.h>
#include <ios>
#include <ostream>
#include <optional>
#include <Alepha/StaticValue.h>
namespace Alepha::Hydrogen::IOStreams ::detail:: delimiters
{
inline namespace exports
{
enum { FieldDelimiter };
enum { RecordDelimiter };
}
namespace C
{
const char defaultFieldDelimiter= '\t';
const char defaultRecordDelimiter= '\n';
}
namespace storage
{
inline StaticValue< std::optional< char > > globalFieldDelimiter;
inline StaticValue< std::optional< char > > globalRecordDelimiter;
}
inline char
globalFieldDelimiter()
{
if( not storage::globalFieldDelimiter().has_value() ) storage::globalFieldDelimiter()= C::defaultFieldDelimiter;
return storage::globalFieldDelimiter().value();
}
inline char
globalRecordDelimiter()
{
if( not storage::globalRecordDelimiter().has_value() ) storage::globalRecordDelimiter()= C::defaultRecordDelimiter;
return storage::globalRecordDelimiter().value();
}
inline const int fieldIndex= std::ios::xalloc();
inline void
setFieldDelimiterOnIOS( std::ios &ios, const char ch )
{
ios.iword( fieldIndex )= ch;
}
inline char
getFieldDelimiter( std::ios &ios )
{
if( ios.iword( fieldIndex ) == 0 ) setFieldDelimiterOnIOS( ios, globalFieldDelimiter() );
return ios.iword( fieldIndex );
}
inline std::ostream &
operator << ( std::ostream &os, decltype( FieldDelimiter ) )
{
return os << getFieldDelimiter( os );
}
struct FieldDelimiterSetter
{
const char ch;
friend std::ostream &
operator << ( std::ostream &os, const FieldDelimiterSetter &s )
{
setFieldDelimiterOnIOS( os, s.ch );
return os;
}
};
namespace exports
{
auto
setFieldDelimiter( const char ch )
{
return FieldDelimiterSetter{ ch };
}
}
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 std::ostream &
operator << ( std::ostream &os, decltype( RecordDelimiter ) )
{
return os << getRecordDelimiter( os );
}
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 )
{
return RecordDelimiterSetter{ ch };
}
}
}
namespace Alepha::Hydrogen::IOStreams::inline exports::inline delimiters
{
using namespace detail::delimiters::exports;
}