xostream2.h
// xostream2.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2008
#pragma once
#ifndef Ceda_cxUtils_xostream2_H
#define Ceda_cxUtils_xostream2_H
#include "cxUtils.h"
#include "xchar.h"
#include "Archive.h"
#include <iostream>
namespace ceda
{
///////////////////////////////////////////////////////////////////////////////////////////////////
// xostream2
/*
An xostream2 writes text, and text is assumed to consist of characters that are of
type xchar.
*/
class cxUtils_API xostream2
{
cxNotCloneable(xostream2)
public:
xostream2(Archive& ar);
// todo : should use same type as used by the STL
typedef ssize_t streamsize;
void close() { flush(); }
void flush() { m_ar.Flush(); }
void endl();
void ends();
/////////////////////////////////////// unformatted output /////////////////////////////////////
// Write the given string directly to the archive, without accounting for field width
// fill character and jusitifcation (contrast with put(str,numChars) method)
void write(const xchar* str, ssize_t numChars)
{
cxAssert(numChars == 0 || str != nullptr);
m_ar.WriteBuffer(str,numChars * sizeof(xchar));
}
// Write the given bytes to the underlying archive
void writebytes(const octet_t* buffer, ssize_t numBytes)
{
cxAssert(numBytes == 0 || buffer != nullptr);
cxAssert(numBytes % sizeof(xchar) == 0);
m_ar.WriteBuffer(buffer,numBytes);
}
/////////////////////////////////////// formatted output /////////////////////////////////////
/*
The put functions are used for formatted output - meaning that
items are written to the output stream accounting for the current field width, fill character
and justification.
Note: it appears that in STL 'put' is actually used for unformatted output, so some renaming is
in order.
*/
// VS2008
// std::basic_ostream<char> writes an unsigned char as a character not an integer.
// std::basic_ostream<wchar_t> writes an unsigned char as an integer not a character.
// This behaviour seems unnecessarily inconsistent.
void put(bool);
void put(char);
void put(signed char);
void put(unsigned char);
void put(wchar_t);
void put(char16_t);
void put(char32_t);
void put(short);
void put(unsigned short);
void put(int);
void put(unsigned int);
void put(long);
void put(unsigned long);
void put(long long);
void put(unsigned long long);
void put(float);
void put(double);
void put(long double);
void put(const void* f);
void unformatted_put(xchar v)
{
m_ar << v;
}
void put(ConstStringZ str) { put(str, strlen(str)); }
void put(const xchar* str, ssize_t numChars);
void put_internal(const xchar* buffer, ssize_t ln, ssize_t tn);
typedef xostream2& (*Manipulator)(xostream2& os);
xostream2& operator<<(Manipulator f)
{
return f(*this);
}
streamsize precision() const { return m_precision; }
streamsize precision(streamsize p) { streamsize prev = m_precision; m_precision = p; return prev; }
streamsize width() const { return m_width; }
streamsize width(streamsize w) { streamsize prev = m_width; m_width = w; return prev; }
typedef std::ios_base::fmtflags fmtflags;
fmtflags get_flags() const
{
return m_flags;
}
void set_flags(fmtflags f)
{
cxAssert((f & 0xffff) == f);
m_flags = f;
}
void setf(fmtflags f)
{
cxAssert((f & 0xffff) == f);
m_flags |= f;
}
void setf(fmtflags f, fmtflags mask)
{
cxAssert((mask & 0xffff) == mask);
cxAssert((mask & f) == f);
m_flags = (m_flags & ~mask) | f;
}
void unsetf(fmtflags mask)
{
cxAssert((mask & 0xffff) == mask);
m_flags &= ~mask;
}
Archive& m_ar;
streamsize m_width;
streamsize m_precision;
xchar m_fillChar;
fmtflags m_flags;
};
inline xostream2& operator<<(xostream2& os, bool f) { os.put(f); return os; }
inline xostream2& operator<<(xostream2& os, char f) { os.put(f); return os; }
inline xostream2& operator<<(xostream2& os, signed char f) { os.put(f); return os; }
inline xostream2& operator<<(xostream2& os, unsigned char f) { os.put(f); return os; }
inline xostream2& operator<<(xostream2& os, wchar_t f) { os.put(f); return os; }
inline xostream2& operator<<(xostream2& os, char16_t f) { os.put(f); return os; }
inline xostream2& operator<<(xostream2& os, char32_t f) { os.put(f); return os; }
inline xostream2& operator<<(xostream2& os, short f) { os.put(f); return os; }
inline xostream2& operator<<(xostream2& os, unsigned short f) { os.put(f); return os; }
inline xostream2& operator<<(xostream2& os, int f) { os.put(f); return os; }
inline xostream2& operator<<(xostream2& os, unsigned int f) { os.put(f); return os; }
inline xostream2& operator<<(xostream2& os, long f) { os.put(f); return os; }
inline xostream2& operator<<(xostream2& os, unsigned long f) { os.put(f); return os; }
inline xostream2& operator<<(xostream2& os, long long f) { os.put(f); return os; }
inline xostream2& operator<<(xostream2& os, unsigned long long f) { os.put(f); return os; }
inline xostream2& operator<<(xostream2& os, float f) { os.put(f); return os; }
inline xostream2& operator<<(xostream2& os, double f) { os.put(f); return os; }
inline xostream2& operator<<(xostream2& os, long double f) { os.put(f); return os; }
inline xostream2& operator<<(xostream2& os, const void* f) { os.put(f); return os; }
inline xostream2& operator<<(xostream2& os, ConstStringZ f) { os.put(f); return os; }
// store function pointer and argument value
template<typename Arg>
struct SingleArgManip2
{
SingleArgManip2(void (*fn)(xostream2&, Arg), Arg arg)
: m_fn(fn), m_arg(arg)
{
}
void (*m_fn)(xostream2&, Arg); // the function pointer
Arg m_arg; // the argument value
};
// insert by calling function with output stream and argument
template<typename Arg>
inline xostream2& operator<<(xostream2& os, const SingleArgManip2<Arg>& m)
{
(*m.m_fn)(os, m.m_arg);
return os;
}
cxUtils_API SingleArgManip2<ssize_t> setprecision2(ssize_t p);
cxUtils_API SingleArgManip2<ssize_t> setw2(ssize_t w);
cxUtils_API SingleArgManip2<xchar> setfill2(xchar c);
inline xostream2& endl(xostream2& os)
{
os.endl();
return os;
}
inline xostream2& ends(xostream2& os)
{
os.ends();
return os;
}
inline xostream2& flush(xostream2& os)
{
os.flush();
return os;
}
inline xostream2& boolalpha(xostream2& os)
{
os.setf(std::ios::boolalpha);
return os;
}
inline xostream2& noboolalpha(xostream2& os)
{
os.unsetf(std::ios::boolalpha);
return os;
}
inline xostream2& showbase(xostream2& os)
{
os.setf(std::ios::showbase);
return os;
}
inline xostream2& noshowbase(xostream2& os)
{
os.unsetf(std::ios::showbase);
return os;
}
inline xostream2& showpoint(xostream2& os)
{
os.setf(std::ios::showpoint);
return os;
}
inline xostream2& noshowpoint(xostream2& os)
{
os.unsetf(std::ios::showpoint);
return os;
}
inline xostream2& showpos(xostream2& os)
{
os.setf(std::ios::showpos);
return os;
}
inline xostream2& noshowpos(xostream2& os)
{
os.unsetf(std::ios::showpos);
return os;
}
inline xostream2& skipws(xostream2& os)
{
os.setf(std::ios::skipws);
return os;
}
inline xostream2& noskipws(xostream2& os)
{
os.unsetf(std::ios::skipws);
return os;
}
inline xostream2& unitbuf(xostream2& os)
{
os.setf(std::ios::unitbuf);
return os;
}
inline xostream2& nounitbuf(xostream2& os)
{
os.unsetf(std::ios::unitbuf);
return os;
}
inline xostream2& uppercase(xostream2& os)
{
os.setf(std::ios::uppercase);
return os;
}
inline xostream2& nouppercase(xostream2& os)
{
os.unsetf(std::ios::uppercase);
return os;
}
inline xostream2& dec(xostream2& os)
{
os.setf(std::ios::dec, std::ios::basefield);
return os;
}
inline xostream2& oct(xostream2& os)
{
os.setf(std::ios::oct, std::ios::basefield);
return os;
}
inline xostream2& hex(xostream2& os)
{
os.setf(std::ios::hex, std::ios::basefield);
return os;
}
inline xostream2& left(xostream2& os)
{
os.setf(std::ios::left, std::ios::adjustfield);
return os;
}
inline xostream2& internal(xostream2& os)
{
os.setf(std::ios::internal, std::ios::adjustfield);
return os;
}
inline xostream2& right(xostream2& os)
{
os.setf(std::ios::right, std::ios::adjustfield);
return os;
}
inline xostream2& scientific(xostream2& os)
{
os.setf(std::ios::scientific, std::ios::floatfield);
return os;
}
inline xostream2& fixed(xostream2& os)
{
os.setf(std::ios::fixed, std::ios::floatfield);
return os;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
extern cxUtils_API xostream2 xcout2;
} // namespace ceda
#endif // include guard