ListToOStream.h
// ListToOStream.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2008
#pragma once
#ifndef Ceda_cxUtils_ListToOStream_H
#define Ceda_cxUtils_ListToOStream_H
#include "xostream.h"
#include "Detect.h"
#include <utility>
#include <vector>
#include <deque>
#include <forward_list>
#include <list>
#include <set>
#include <map>
#include <array>
namespace ceda
{
///////////////////////////////////////////////////////////////////////////////////////////////////
// Decorator to display in brackets
template <xchar leftBracket, xchar rightBracket, class Base>
class BracketedMixin : public Base {};
template <xchar leftBracket, xchar rightBracket, class Base>
xostream& operator<<(xostream& os, const BracketedMixin<leftBracket,rightBracket,Base>& v)
{
os << leftBracket << (const Base&) v << rightBracket;
return os;
}
template <xchar leftBracket, xchar rightBracket, class Base>
const BracketedMixin<leftBracket,rightBracket,Base>& AsBracketed(const Base& b)
{
return (const BracketedMixin<leftBracket,rightBracket,Base>&) b;
}
template <typename Base>
const BracketedMixin<'[',']',Base>& AsSquareBracketed(const Base& b)
{
return (const BracketedMixin<'[',']',Base>&) b;
}
template <typename Base>
const BracketedMixin<'(',')',Base>& AsRoundBracketed(const Base& b)
{
return (const BracketedMixin<'(',')',Base>&) b;
}
template <typename Base>
const BracketedMixin<'{','}',Base>& AsCurlyBracketed(const Base& b)
{
return (const BracketedMixin<'{','}',Base>&) b;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Decorator to apply an indent
template <ssize_t indent,class Base>
class IndentMixin : public Base {};
template <ssize_t indent, class Base>
xostream& operator<<(xostream& os, const IndentMixin<indent,Base>& v)
{
Indenter indenter(os,indent);
os << (const Base&) v;
return os;
}
template <ssize_t indent, class Base>
const IndentMixin<indent,Base>& AsIndented(const Base& b)
{
return (const IndentMixin<indent,Base>&) b;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
enum EDelimiterPlacement
{
DELIMIT_NEVER,
DELIMIT_BEFORE,
DELIMIT_AFTER,
DELIMIT_BETWEEN,
DELIMIT_AROUND,
};
template <xchar delimiter, EDelimiterPlacement placement, class It>
void WriteList(xostream& os, It p1, It p2)
{
for (It p = p1 ; p != p2 ; ++p)
{
if (placement == DELIMIT_BEFORE ||
placement == DELIMIT_AROUND ||
(placement == DELIMIT_BETWEEN && p != p1))
{
os << delimiter;
}
os << *p;
if (placement == DELIMIT_AFTER)
os << delimiter;
}
if (placement == DELIMIT_AROUND)
os << delimiter;
}
template <xchar delimiter, EDelimiterPlacement placement,class Base>
struct ListMixin : public Base
{
};
template <xchar delimiter, EDelimiterPlacement placement,class Base>
xostream& operator<<(xostream& os, const ListMixin<delimiter,placement,Base>& v)
{
WriteList<delimiter,placement>(os, v.begin(), v.end());
return os;
}
template <xchar delimiter, EDelimiterPlacement placement,class Base>
const ListMixin<delimiter,placement,Base>& AsList(const Base& b)
{
return (const ListMixin<delimiter,placement,Base>&) b;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
template <typename It> void WriteLineFeedSeparatedList(xostream& os, It p1, It p2)
{
for (It p = p1 ; p != p2 ; ++p)
{
os << *p << '\n';
}
}
template <typename It> void WriteLineFeedSeparatedPtrList(xostream& os, It p1, It p2)
{
for (It p = p1 ; p != p2 ; ++p)
{
os << **p << '\n';
}
}
template <typename It> void WriteCommaSeparatedListToStream(xostream& os, It p1, It p2)
{
for (It p = p1 ; p != p2 ; ++p)
{
if (p != p1) os << ',';
os << *p;
}
}
template <typename It> void WriteCommaSeparatedPtrListToStream(xostream& os, It p1, It p2)
{
for (It p = p1 ; p != p2 ; ++p)
{
if (p != p1) os << ',';
os << **p;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
template <typename Base>
struct CommaSeparatedListMixin : public Base {};
template <typename Base>
xostream& operator<<(xostream& os, const CommaSeparatedListMixin<Base>& v)
{
WriteCommaSeparatedListToStream(os, v.begin(), v.end());
return os;
}
template <typename Base>
const CommaSeparatedListMixin<Base>& AsCommaSeparatedList(const Base& b)
{
return (const CommaSeparatedListMixin<Base>&) b;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
template <typename T, size_t N, std::enable_if_t<has_xostream_insertion<T>::value, int> = 0>
xostream& operator<<(xostream& os, const std::array<T,N>& v)
{
os << AsSquareBracketed(AsCommaSeparatedList(v));
return os;
}
template <typename T, typename A, std::enable_if_t<has_xostream_insertion<T>::value, int> = 0>
xostream& operator<<(xostream& os, const std::vector<T,A>& v)
{
os << AsSquareBracketed(AsCommaSeparatedList(v));
return os;
}
template <typename T,typename A, std::enable_if_t<has_xostream_insertion<T>::value, int> = 0>
xostream& operator<<(xostream& os, const std::deque<T,A>& v)
{
os << AsSquareBracketed(AsCommaSeparatedList(v));
return os;
}
template <typename T,typename A, std::enable_if_t<has_xostream_insertion<T>::value, int> = 0>
xostream& operator<<(xostream& os, const std::forward_list<T,A>& v)
{
os << AsSquareBracketed(AsCommaSeparatedList(v));
return os;
}
template <typename T,typename A, std::enable_if_t<has_xostream_insertion<T>::value, int> = 0>
xostream& operator<<(xostream& os, const std::list<T,A>& v)
{
os << AsSquareBracketed(AsCommaSeparatedList(v));
return os;
}
template <typename U, typename V, std::enable_if_t<has_xostream_insertion<U>::value && has_xostream_insertion<V>::value, int> = 0>
xostream& operator<<(xostream& os, const std::pair<U,V>& p)
{
os << '(' << p.first << ',' << p.second << ')';
return os;
}
template <typename K,typename P,typename A, std::enable_if_t<has_xostream_insertion<K>::value, int> = 0>
xostream& operator<<(xostream& os, const std::set<K,P,A>& v)
{
os << AsCurlyBracketed(AsCommaSeparatedList(v));
return os;
}
template <typename K,typename P,typename A, std::enable_if_t<has_xostream_insertion<K>::value, int> = 0>
xostream& operator<<(xostream& os, const std::multiset<K,P,A>& v)
{
os << AsCurlyBracketed(AsCommaSeparatedList(v));
return os;
}
template <typename K,typename T,typename P,typename A, std::enable_if_t<has_xostream_insertion<K>::value && has_xostream_insertion<T>::value, int> = 0>
xostream& operator<<(xostream& os, const std::map<K,T,P,A>& v)
{
os << AsCurlyBracketed(AsCommaSeparatedList(v));
return os;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
template <typename Base>
struct SquareBracketedListWithLineFeeds : public Base {};
template <typename Base>
xostream& operator<<(xostream& os, const SquareBracketedListWithLineFeeds<Base>& v)
{
os << '[' << '\n';
{
Indenter indent(os);
WriteLineFeedSeparatedList(os, v.begin(), v.end());
}
os << ']';
return os;
}
template <typename Base>
const SquareBracketedListWithLineFeeds<Base>& AsSquareBracketedListWithLineFeeds(const Base& b)
{
return (const SquareBracketedListWithLineFeeds<Base>&) b;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
template <typename Base>
struct SquareBracketedPtrListWithLineFeeds : public Base {};
template <typename Base>
xostream& operator<<(xostream& os, const SquareBracketedPtrListWithLineFeeds<Base>& v)
{
os << '[' << '\n';
{
Indenter indent(os);
WriteLineFeedSeparatedPtrList(os, v.begin(), v.end());
}
os << ']';
return os;
}
template <typename Base>
const SquareBracketedPtrListWithLineFeeds<Base>& AsSquareBracketedPtrListWithLineFeeds(const Base& b)
{
return (const SquareBracketedPtrListWithLineFeeds<Base>&) b;
}
} // namespace ceda
#endif // include guard