#include <stdio.h>
#include <unistd.h>
#include "Errstream.h"
Errstream errout;
static void
_StdDisplayImpl_(const char *msg)
{
cerr << msg << endl;
}
void
(*Errstream::_displayImpl)(const char *)
= _StdDisplayImpl_;
Errstream::Errstream()
: _line(0),
_collectLine(0),
_diffLevel(0),
_collectDiffLevel(0),
_numMultiples(0),
_collect(true),
_logOnly(false),
_logOpen(false)
{
clear();
pid_t pid = getpid();
sprintf(_logFile, "%s.%d",
DEFAULT_ERROR_FILE, (int)pid);
}
Errstream::Errstream(const char *name)
: _line(0),
_collectLine(0),
_diffLevel(0),
_collectDiffLevel(0),
_numMultiples(0),
_collect(true),
_logOnly(false),
_logOpen(false)
{
clear();
strcpy(_logFile, name);
}
Errstream::~Errstream()
{
if(_collect && _numMultiples)
_writeMultiples();
ofstream::close();
}
void Errstream::open(const char *name)
{
ofstream::close();
ofstream::open(name);
}
void Errstream::collect(bool set)
{
if(_numMultiples && !set)
_writeMultiples();
_collect = set;
}
Errstream &
Errstream::displayError(Errstream &stream)
{
if(!stream.logOnly())
(*_displayImpl)(stream.errString());
if(stream._collectMultipleMsgs())
return stream;
stream._writeMultiples();
stream._writeDebugInfo();
return stream;
}
Errstream &
Errstream::operator<<(const char *str)
{
_concatenate(str);
if(_okayToWriteToLog())
(ofstream&)*this << str;
return *this;
}
Errstream &Errstream::operator<<(int d)
{
char buf[64];
sprintf(buf, "%d", d);
_concatenate(buf);
if(_okayToWriteToLog())
(ofstream&)*this << d;
return *this;
}
Errstream &Errstream::operator<<(double f)
{
char buf[64];
sprintf(buf, "%lf", f);
_concatenate(buf);
if(_okayToWriteToLog())
(ofstream&)*this << f;
return *this;
}
void Errstream::_openLogFile()
{
ofstream::open(_logFile);
if(good())
_logOpen = true;
else
cerr << "Unable to open log file "
<< _logFile << endl;
}
bool Errstream::_collectMultipleMsgs()
{
if(!_collect ||
(_diffLevel != _collectDiffLevel) ||
(_line != _collectLine) ||
(_file != _collectFile))
return false;
clear();
_logOnly = false;
_diffLevel = 0;
_numMultiples++;
return true;
}
void Errstream::_writeMultiples()
{
if(_numMultiples)
{
(ofstream&)*this
<< "\n\t*** MESSAGE REPEATS "
<< _numMultiples
<< " TIMES ***\n"
<< endl;
(ofstream&)*this << _str;
_numMultiples = 0;
}
}
void Errstream::_writeDebugInfo()
{
if(_collect)
{
_collectLine = _line;
_collectFile = _file;
_collectDiffLevel = _diffLevel;
}
clear();
_logOnly = false;
_diffLevel = 0;
(ofstream&)*this << "\n\tFile: "
<< _file
<< "\n\tLine: "
<< _line
<< '\n'
<< endl;
}
void
Errstream::_concatenate
(const char *buf, int len)
{
int catSize =
MAX_STR_SIZE - strlen(_str);
if(catSize > len) catSize = len;
strncat(_str, buf, catSize);
}
bool Errstream::_okayToWriteToLog()
{
if(_collect && _numMultiples)
return false;
if(!_logOpen)
_openLogFile();
return true;
}
Errstream &
set_diffLevel(Errstream &stream, int d)
{
stream.diffLevel(d);
return stream;
}
Errstream &
set_debug_line(Errstream &stream, int l)
{
stream.line(l);
return stream;
}
Errstream &
set_debug_file(Errstream &stream,
const std::string &f)
{
stream.file(f);
return stream;
}
Errstream &logOnly(Errstream &stream)
{
stream.logOnly(true);
return stream;
}
Errstream &endl(Errstream &stream)
{
(ofstream&)stream << endl;
return stream;
}
EMANIP_int differentiate(int d)
{
return EMANIP_int(set_diffLevel, d);
}
EMANIP_int setDebugLine(int l)
{
return EMANIP_int(set_debug_line, l);
}
EMANIP_string
setDebugFile(const std::string &f)
{
return EMANIP_string(set_debug_file,
f);
}