#ifndef _H_DEBUGSUPPORT
#define _H_DEBUGSUPPORT
#if defined(NDEBUG) && !defined(CLEAN_NDEBUG)
# undef NDEBUG
# define NDEBUG_STUBS
#endif
#include <Security/debugging.h>
#include <Security/threading.h>
#include <cstdarg>
#include <set>
namespace Security {
namespace Debug {
#if !defined(NDEBUG)
class Name {
public:
static const int maxLength = 12;
Name(const char *s)
{ strncpy(mName, s, maxLength-1); mName[maxLength-1] = '\0'; }
Name(const char *start, const char *end)
{
int length = end - start; if (length >= maxLength) length = maxLength - 1;
memcpy(mName, start, length); memset(mName + length, 0, maxLength - length);
}
operator const char *() const { return mName; }
bool operator < (const Name &other) const
{ return memcmp(mName, other.mName, maxLength) < 0; }
bool operator == (const Name &other) const
{ return memcmp(mName, other.mName, maxLength) == 0; }
private:
char mName[maxLength]; };
class Target {
public:
Target();
virtual ~Target();
static Target &get();
void setFromEnvironment();
public:
class Sink {
public:
virtual ~Sink();
virtual void put(const char *buffer, unsigned int length) = 0;
virtual void dump(const char *buffer);
virtual void configure(const char *argument);
};
void to(Sink *sink);
void to(const char *filename);
void to(int syslogPriority);
void to(FILE *openFile);
void configure(); void configure(const char *options);
public:
void message(const char *scope, const char *format, va_list args);
bool debugging(const char *scope);
void dump(const char *format, va_list args);
bool dump(const char *scope);
protected:
class Selector {
public:
Selector();
void operator = (const char *config);
bool operator () (const char *name) const;
private:
bool useSet; bool negate; set<Name> enableSet; };
protected:
static const size_t messageConstructionSize = 512;
Selector logSelector; Selector dumpSelector;
bool showScope; bool showThread; bool showPid; size_t dumpLimit;
Sink *sink;
static terminate_handler previousTerminator; static void terminator();
static Target *singleton;
};
class FileSink : public Target::Sink {
public:
FileSink(FILE *f) : file(f), addDate(false), lockIO(true), lock(false) { }
void put(const char *, unsigned int);
void dump(const char *text);
void configure(const char *);
private:
FILE *file;
bool addDate;
bool lockIO;
Mutex lock;
};
class SyslogSink : public Target::Sink {
public:
SyslogSink(int pri) : priority(pri), dumpBase(dumpBuffer), dumpPtr(dumpBuffer) { }
void put(const char *, unsigned int);
void dump(const char *text);
void configure(const char *);
private:
int priority;
static const size_t dumpBufferSize = 1024; char dumpBuffer[dumpBufferSize];
char *dumpBase, *dumpPtr;
};
#else // NDEBUG
#endif // NDEBUG
}
}
#endif //_H_DEBUGSUPPORT