Skip to content

Commit

Permalink
libdeng2: Log entries are now serializable
Browse files Browse the repository at this point in the history
Added ISerializable for LogEntry and LogEntry::Arg.
  • Loading branch information
skyjake committed Jan 27, 2013
1 parent 624a481 commit 8bc4460
Show file tree
Hide file tree
Showing 2 changed files with 163 additions and 55 deletions.
72 changes: 17 additions & 55 deletions doomsday/libdeng2/include/de/core/log.h
Expand Up @@ -24,6 +24,7 @@
#include "../String"
#include "../Lockable"
#include "../Guard"
#include "../ISerializable"

#include <QList>
#include <vector>
Expand Down Expand Up @@ -96,7 +97,7 @@ class LogBuffer;
*
* @ingroup core
*/
class DENG2_PUBLIC LogEntry : public Lockable
class DENG2_PUBLIC LogEntry : public Lockable, public ISerializable
{
public:
/// Level of the log entry.
Expand Down Expand Up @@ -195,7 +196,7 @@ class DENG2_PUBLIC LogEntry : public Lockable
*
* @ingroup core
*/
class DENG2_PUBLIC Arg : public String::IPatternArg
class DENG2_PUBLIC Arg : public String::IPatternArg, public ISerializable
{
public:
/// The wrong type is used in accessing the value. @ingroup errors
Expand Down Expand Up @@ -234,6 +235,7 @@ class DENG2_PUBLIC LogEntry : public Lockable
};

public:
Arg() : _type(INTEGER) { _data.intValue = 0; }
Arg(dint i) : _type(INTEGER) { _data.intValue = i; }
Arg(duint i) : _type(INTEGER) { _data.intValue = i; }
Arg(long int i) : _type(INTEGER) { _data.intValue = i; }
Expand All @@ -248,38 +250,9 @@ class DENG2_PUBLIC LogEntry : public Lockable
Arg(String const &s) : _type(STRING) {
_data.stringValue = new String(s.data(), s.size());
}
Arg(Base const &arg) : _type(arg.logEntryArgType()) {
switch(_type) {
case INTEGER:
_data.intValue = arg.asInt64();
break;
case FLOATING_POINT:
_data.floatValue = arg.asDouble();
break;
case STRING: {
String s = arg.asText();
_data.stringValue = new String(s.data(), s.size());
break; }
}
}
Arg(Arg const &other) : _type(other._type) {
switch(other._type) {
case INTEGER:
_data.intValue = other._data.intValue;
break;
case FLOATING_POINT:
_data.floatValue = other._data.floatValue;
break;
case STRING: {
_data.stringValue = new String(*other._data.stringValue);
break; }
}
}
~Arg() {
if(_type == STRING) {
delete _data.stringValue;
}
}
Arg(Base const &arg);
Arg(Arg const &other);
~Arg();

Type type() const { return _type; }
dint64 intValue() const {
Expand All @@ -296,27 +269,12 @@ class DENG2_PUBLIC LogEntry : public Lockable
}

// Implements String::IPatternArg.
ddouble asNumber() const {
if(_type == INTEGER) {
return ddouble(_data.intValue);
}
else if(_type == FLOATING_POINT) {
return _data.floatValue;
}
throw TypeError("Log::Arg::asNumber", "String argument cannot be used as a number");
}
String asText() const {
if(_type == STRING) {
return *_data.stringValue;
}
else if(_type == INTEGER) {
return String::number(_data.intValue);
}
else if(_type == FLOATING_POINT) {
return String::number(_data.floatValue);
}
throw TypeError("Log::Arg::asText", "Number argument cannot be used a string");
}
ddouble asNumber() const;
String asText() const;

// Implements ISerializable.
void operator >> (Writer &to) const;
void operator << (Reader &from);

private:
Type _type;
Expand Down Expand Up @@ -395,6 +353,10 @@ class DENG2_PUBLIC LogEntry : public Lockable
*/
String asText(Flags const &flags = 0, int shortenSection = 0) const;

// Implements ISerializable.
void operator >> (Writer &to) const;
void operator << (Reader &from);

private:
void advanceFormat(String::const_iterator &i) const;

Expand Down
146 changes: 146 additions & 0 deletions doomsday/libdeng2/src/core/log.cpp
Expand Up @@ -22,6 +22,8 @@
#include "de/Date"
#include "de/LogBuffer"
#include "de/Guard"
#include "de/Reader"
#include "de/Writer"
#include "logtextstyle.h"

#include <QMap>
Expand Down Expand Up @@ -62,6 +64,124 @@ class Logs : public QMap<QThread *, Log *>, public Lockable
/// The logs table contains the log of each thread that uses logging.
static std::auto_ptr<internal::Logs> logsPtr;

LogEntry::Arg::Arg(const LogEntry::Arg::Base &arg) : _type(arg.logEntryArgType())
{
switch(_type)
{
case INTEGER:
_data.intValue = arg.asInt64();
break;

case FLOATING_POINT:
_data.floatValue = arg.asDouble();
break;

case STRING: {
String s = arg.asText();
_data.stringValue = new String(s.data(), s.size());
break; }
}
}

LogEntry::Arg::Arg(Arg const &other) : _type(other._type)
{
switch(other._type)
{
case INTEGER:
_data.intValue = other._data.intValue;
break;

case FLOATING_POINT:
_data.floatValue = other._data.floatValue;
break;

case STRING:
_data.stringValue = new String(*other._data.stringValue);
break;
}
}

LogEntry::Arg::~Arg()
{
if(_type == STRING)
{
delete _data.stringValue;
}
}

ddouble LogEntry::Arg::asNumber() const
{
if(_type == INTEGER)
{
return ddouble(_data.intValue);
}
else if(_type == FLOATING_POINT)
{
return _data.floatValue;
}
throw TypeError("Log::Arg::asNumber", "String argument cannot be used as a number");
}

String LogEntry::Arg::asText() const
{
if(_type == STRING)
{
return *_data.stringValue;
}
else if(_type == INTEGER)
{
return String::number(_data.intValue);
}
else if(_type == FLOATING_POINT)
{
return String::number(_data.floatValue);
}
throw TypeError("Log::Arg::asText", "Number argument cannot be used a string");
}

void LogEntry::Arg::operator >> (Writer &to) const
{
to << dbyte(_type);

switch(_type)
{
case INTEGER:
to << _data.intValue;
break;

case FLOATING_POINT:
to << _data.floatValue;
break;

case STRING:
to << *_data.stringValue;
break;
}
}

void LogEntry::Arg::operator << (Reader &from)
{
if(_type == STRING) delete _data.stringValue;

from.readAs<dbyte>(_type);

switch(_type)
{
case INTEGER:
from >> _data.intValue;
break;

case FLOATING_POINT:
from >> _data.floatValue;
break;

case STRING:
_data.stringValue = new String;
from >> *_data.stringValue;
break;
}
}

LogEntry::LogEntry() : _level(TRACE), _sectionDepth(0), _disabled(true)
{}

Expand Down Expand Up @@ -281,6 +401,32 @@ String LogEntry::asText(Flags const &formattingFlags, int shortenSection) const
return result;
}

void LogEntry::operator >> (Writer &to) const
{
to << _when
<< _section
<< _format
<< dbyte(_level)
<< dbyte(_sectionDepth)
<< duint32(_defaultFlags);

to.writeObjects(_args);
}

void LogEntry::operator << (Reader &from)
{
foreach(Arg *a, _args) delete a;
_args.clear();

from >> _when
>> _section
>> _format;
from.readAs<dbyte>(_level)
.readAs<dbyte>(_sectionDepth)
.readAs<duint32>(_defaultFlags)
.readObjects<Arg>(_args);
}

QTextStream &operator << (QTextStream &stream, LogEntry::Arg const &arg)
{
switch(arg.type())
Expand Down

0 comments on commit 8bc4460

Please sign in to comment.