forked from Alepha/Alepha
Delimiters helpers which work with ostream helpers.
This commit is contained in:
@ -1 +1,2 @@
|
|||||||
add_subdirectory( IStreamable.test )
|
add_subdirectory( IStreamable.test )
|
||||||
|
add_subdirectory( OStreamable.test )
|
||||||
|
|||||||
@ -13,6 +13,8 @@ static_assert( __cplusplus > 2020'00 );
|
|||||||
|
|
||||||
#include <Alepha/Reflection/tuplizeAggregate.h>
|
#include <Alepha/Reflection/tuplizeAggregate.h>
|
||||||
|
|
||||||
|
#include <Alepha/IOStreams/delimiters.h>
|
||||||
|
|
||||||
namespace Alepha::Hydrogen::IOStreams ::detail:: ostreamable_module
|
namespace Alepha::Hydrogen::IOStreams ::detail:: ostreamable_module
|
||||||
{
|
{
|
||||||
inline namespace exports
|
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...
|
// aggregates, so we'll go with this simple case for now...
|
||||||
tuple_for_each( decomposed ) <=[&]( const auto &element )
|
tuple_for_each( decomposed ) <=[&]( const auto &element )
|
||||||
{
|
{
|
||||||
if( not first ) os << '\t';
|
if( not first ) os << FieldDelimiter;
|
||||||
first= false;
|
first= false;
|
||||||
os << element;
|
os << element;
|
||||||
};
|
};
|
||||||
os << '\n';
|
|
||||||
|
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|||||||
50
IOStreams/OStreamable.test/0.cc
Normal file
50
IOStreams/OStreamable.test/0.cc
Normal 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" } },
|
||||||
|
};
|
||||||
|
};
|
||||||
3
IOStreams/OStreamable.test/CMakeLists.txt
Normal file
3
IOStreams/OStreamable.test/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
link_libraries( unit-test )
|
||||||
|
|
||||||
|
unit_test( 0 )
|
||||||
138
IOStreams/delimiters.h
Normal file
138
IOStreams/delimiters.h
Normal 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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user