|
Boost : |
From: Ivan Dubrov (WFrag_at_[hidden])
Date: 2004-01-08 10:30:33
Here the code of simple logging facility over std::iostream's. I think
it could be useful - no inheritance, just works with every stream!
Usage:
#include "logger.hpp"
int main()
{
using namespace utility;
using namespace std;
const long SOUND = 1;
const long VIDEO = 2;
std::cout << speak_barrier(0);
// Show one VIDEO subsystem messages
std::cout << speak_filter(VIDEO);
// Show only messages with level <= 10
std::cout << speak_barrier(5);
cout << speak_bits(0) << speak_level(5) << "Application started." <<
endl;
cout << speak_bits(0) << speak_level(0) << "Something wrong is
happening..." << endl;
cout << speak_level(-5) << speak_bits(SOUND) << "Critical error in
sound subsystem!" << endl;
cout << speak_level(-5) << speak_bits(VIDEO) "Critical error in video
subsystem!" << endl;
// speak_bits(0) means "no bit filter"
cout << speak_bits(0) << speak_level(5) << "Application finished." <<
endl;
return 0;
}
Code:
#include <ostream>
#include <iterator>
#include <streambuf>
#include <locale>
#include <ios>
#include <algorithm>
#include <cassert>
namespace utility
{
namespace impl
{
enum Constants
{
SPEAK_LEVEL = 0,
SPEAK_BARRIER = 1,
SPEAK_BITS = 2,
SPEAK_FILTER = 3,
PARAMS_COUNT = 4,
OLD_STREAM = 4,
REGISTERED = 5,
PARAMS = 6,
};
struct LogParams
{
LogParams()
: oldStream(0)
{
std::fill(values, values + PARAMS_COUNT, 0);
}
bool checkOutput()
{
return values[SPEAK_LEVEL] <= values[SPEAK_BARRIER] &&
((values[SPEAK_BITS] & values[SPEAK_FILTER]) ||
values[SPEAK_BITS] == 0);
}
long values[PARAMS_COUNT];
void* oldStream;
};
template<int tag>
int allocateIndex()
{
static int index = std::ios_base::xalloc();
return index;
}
template<typename Ch_, typename Tr_>
inline void callback(std::ios_base::event e, std::ios_base& stream,
int arg)
{
void*& ptrRef = stream.pword(allocateIndex<PARAMS>());
LogParams* params = reinterpret_cast<LogParams*>(ptrRef);
ptrRef = 0;
if(params)
{
if(e == std::ios_base::erase_event)
{
delete params;
} else if(e == std::ios_base::copyfmt_event)
{
params = new LogParams(*params);
if(params->oldStream) // other stream was switched off?
{
params->oldStream =
static_cast<std::basic_ios<Ch_, Tr_>& >(stream).rdbuf(0);
}
ptrRef = params;
}
}
}
template<typename Ch_, typename Tr_>
void setParams(std::basic_ostream<Ch_, Tr_>& out, int tag, long value)
{
// register callback if wasn't registered
if(out.iword(allocateIndex<REGISTERED>()) == 0)
{
out.register_callback(&callback<Ch_, Tr_>, 0);
out.iword(allocateIndex<REGISTERED>()) = 1;
}
LogParams* params =
reinterpret_cast<LogParams*>(out.pword(allocateIndex<PARAMS>()));
if(params == 0)
{
params = new LogParams;
out.pword(allocateIndex<PARAMS>()) = params;
}
bool oldSit = params->checkOutput();
params->values[tag] = value;
bool newSit = params->checkOutput();
// if situation changed
if(newSit != oldSit)
{
if(newSit) // restore old stream
{
assert(params->oldStream != 0);
// check if dummy stream wasn't switched to another buffer
// (otherwise leave new buffer)
if(out.rdbuf() == 0)
{
out.rdbuf(reinterpret_cast<std::basic_streambuf<Ch_,
Tr_>*>(params->oldStream));
}
params->oldStream = 0;
}
else // set dummy stream buffer
{
assert(params->oldStream == 0);
params->oldStream = out.rdbuf(0);
}
}
}
/// \brief logger integral parameters
template<int Tag_>
struct stream_param
{
stream_param(long value)
: value_(value) {}
long value_;
};
/// \brief sets one of the logger parameters
template<typename Ch_, typename Tr_, int Tag_> inline
std::basic_ostream<Ch_, Tr_>&
operator <<(std::basic_ostream<Ch_, Tr_>& out,
impl::stream_param<Tag_> param)
{
impl::setParams(out, Tag_, param.value_);
return out;
}
}
/// \brief defines speak level value
typedef impl::stream_param<impl::SPEAK_LEVEL> speak_level;
/// \brief defines speak barrier value
typedef impl::stream_param<impl::SPEAK_BARRIER> speak_barrier;
/// \brief defines speak bits value
typedef impl::stream_param<impl::SPEAK_BITS> speak_bits;
/// \brief defines speak bits filtervalue
typedef impl::stream_param<impl::SPEAK_FILTER> speak_filter;
}
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk