More work done toward rearranging the utility code.

This commit is contained in:
John Wiegley 2007-04-27 10:08:05 +00:00
parent 9039e728b2
commit 4716975cb1
10 changed files with 552 additions and 569 deletions

View file

@ -31,8 +31,9 @@ libledger_la_CPPFLAGS = -I$(top_builddir)/gdtoa
libledger_la_LDFLAGS = -release 3.0
libledger_la_SOURCES = \
amount.cc \
utils.cc \
times.cc \
amount.cc \
quotes.cc \
balance.cc \
value.cc \
@ -40,8 +41,6 @@ libledger_la_SOURCES = \
xpath.cc \
mask.cc \
format.cc \
util.cc \
trace.cc \
\
session.cc \
journal.cc \
@ -55,7 +54,6 @@ libledger_la_SOURCES = \
transform.cc \
\
register.cc \
\
csv.cc \
derive.cc \
emacs.cc \
@ -74,8 +72,7 @@ libledger_la_CPPFLAGS += -DHAVE_LIBOFX=1
libledger_la_SOURCES += ofx.cc
endif
if DEBUG
libledger_la_CPPFLAGS += -DDEBUG_LEVEL=4
libledger_la_SOURCES += debug.cc
libledger_la_CPPFLAGS += -DFULL_DEBUG
endif
if HAVE_BOOST_PYTHON
libledger_la_CPPFLAGS += -DUSE_BOOST_PYTHON=1
@ -107,8 +104,8 @@ pkginclude_HEADERS = \
times.h \
balance.h \
binary.h \
context.h \
csv.h \
debug.h \
derive.h \
emacs.h \
error.h \
@ -131,10 +128,8 @@ pkginclude_HEADERS = \
session.h \
system.hh \
textual.h \
timing.h \
trace.h \
transform.h \
util.h \
utils.h \
value.h \
xml.h \
xmlparse.h \

28
context.h Normal file
View file

@ -0,0 +1,28 @@
#ifndef _CONTEXT_H
#define _CONTEXT_H
namespace ledger {
class context
{
public:
string context; // ex: 'While parsing file "%R" at line %L'
string resource; // ex: ledger.dat
long linenum_beg; // ex: 1010
long linenum_end; // ex: 1010
long colnum_beg; // ex: 8
long colnum_end; // ex: 8
long position_beg;
long position_end;
string text; // ex: (The multi-line text of an entry)
long linenum_beg_off; // ex: 2 / -1 means start at beginning
long linenum_end_off; // ex: 2 / -1 means start at beginning
long colnum_beg_off; // ex: 8 / -1 means start
long colnum_end_off; // ex: 8 / -1 means start
};
} // namespace ledger
#endif // _CONTEXT_H

View file

@ -1,95 +0,0 @@
#include "utils.h"
#include <boost/regex.hpp>
#ifdef DEBUG_ENABLED
int new_calls = 0;
unsigned long new_size = 0;
void * operator new(std::size_t size) throw (std::bad_alloc) {
void * ptr = std::malloc(size);
new_calls++;
new_size += size;
return ptr;
}
void * operator new[](std::size_t size) throw (std::bad_alloc) {
void * ptr = std::malloc(size);
new_calls++;
new_size += size;
return ptr;
}
void * operator new(std::size_t size, const std::nothrow_t&) throw() {
void * ptr = std::malloc(size);
new_calls++;
new_size += size;
return ptr;
}
void * operator new[](std::size_t size, const std::nothrow_t&) throw() {
void * ptr = std::malloc(size);
new_calls++;
new_size += size;
return ptr;
}
void operator delete(void * ptr) throw() {
std::free(ptr);
}
void operator delete[](void * ptr) throw() {
std::free(ptr);
}
void operator delete(void * ptr, const std::nothrow_t&) throw() {
std::free(ptr);
}
void operator delete[](void * ptr, const std::nothrow_t&) throw() {
std::free(ptr);
}
std::ostream * _debug_stream = &std::cerr;
bool _free_debug_stream = false;
boost::regex _debug_regex;
bool _set_debug_regex = false;
bool _debug_regex_on = false;
bool _debug_active(const char * const cls) {
if (! _set_debug_regex) {
const char * user_class = std::getenv("DEBUG_CLASS");
if (user_class) {
_debug_regex = user_class;
_debug_regex_on = true;
}
_set_debug_regex = true;
}
if (_debug_regex_on)
return boost::regex_match(cls, _debug_regex);
return false;
}
static struct init_streams {
init_streams() {
// If debugging is enabled and DEBUG_FILE is set, all debugging
// output goes to that file.
if (const char * p = std::getenv("DEBUG_FILE")) {
_debug_stream = new std::ofstream(p);
_free_debug_stream = true;
}
}
~init_streams() {
if (_free_debug_stream && _debug_stream) {
delete _debug_stream;
_debug_stream = NULL;
}
}
} _debug_init;
#endif // DEBUG_ENABLED
#if DEBUG_LEVEL >= BETA
void debug_assert(const ledger::string& reason,
const ledger::string& file,
unsigned long line)
{
throw new ledger::fatal_assert(reason, new ledger::file_context(file, line));
}
#endif

166
debug.h
View file

@ -1,166 +0,0 @@
#ifndef _DEBUG_H
#define _DEBUG_H
#define DEVELOPER 4
#define ALPHA 3
#define BETA 2
#define RELEASE 1
#define NO_SEATBELT 0
#ifndef DEBUG_LEVEL
#define DEBUG_LEVEL NO_SEATBELT
#endif
#if DEBUG_LEVEL >= RELEASE
#ifdef assert
#undef assert
#endif
#if DEBUG_LEVEL >= BETA
void debug_assert(const ledger::string& reason,
const ledger::string& file,
unsigned long line);
#define assert(x) \
if (! (x)) \
debug_assert(#x, __FILE__, __LINE__)
#else
#define assert(x) \
if (! (x)) \
throw new fatal_assert(#x, new file_context(__FILE__, __LINE__))
#endif
#else
#ifdef assert
#undef assert
#endif
#define assert(x)
#endif
//////////////////////////////////////////////////////////////////////
//
// General debugging facilities
//
// - In developer level, all checking and debugging facilities are
// active.
//
// - Alpha level does not include performance degrading
// VALIDATE calls.
//
// - Beta level is like Alpha, but does not include debugging
// facilities.
//
// - Release level does not include CONFIRM checks, but does include
// assert calls.
//
// - Running with no seatbelt disables all checking except for normal
// syntax and semantic error checking.
#if DEBUG_LEVEL >= ALPHA
#define DEBUG_ENABLED
extern std::ostream * _debug_stream;
extern bool _free_debug_stream;
bool _debug_active(const char * const cls);
#define DEBUG_CLASS(cls) static const char * const _debug_cls = (cls)
#define DEBUG(cls) (_debug_active(cls))
#define DEBUG_() DEBUG(_debug_cls)
#define DEBUG_IF(cls) if (_debug_active(cls))
#define DEBUG_IF_() if (_debug_active(_debug_cls))
#define DEBUG_PRINT(cls, x) \
if (_debug_stream && _debug_active(cls)) { \
*_debug_stream << x << std::endl; \
}
#define DEBUG_PRINT_(x) DEBUG_PRINT(_debug_cls, x)
#define DEBUG_PRINT_TIME(cls, x) { \
DEBUG_PRINT(cls, #x << " is " << x); \
}
#define DEBUG_PRINT_TIME_(x) DEBUG_PRINT_TIME(_debug_cls, x)
#define CONFIRM(x) assert(x)
#if DEBUG_LEVEL == DEVELOPER
#define VALIDATE(x) assert(x)
#else
#define VALIDATE(x)
#endif
extern int new_calls;
extern unsigned long new_size;
#if 0
void * operator new(std::size_t) throw (std::bad_alloc);
void * operator new[](std::size_t) throw (std::bad_alloc);
void operator delete(void*) throw();
void operator delete[](void*) throw();
void * operator new(std::size_t, const std::nothrow_t&) throw();
void * operator new[](std::size_t, const std::nothrow_t&) throw();
void operator delete(void*, const std::nothrow_t&) throw();
void operator delete[](void*, const std::nothrow_t&) throw();
#endif
#else // DEBUG_LEVEL
#define DEBUG_CLASS(cls)
#define DEBUG(cls) 0
#define DEBUG_() 0
#define DEBUG_IF(cls)
#define DEBUG_IF_()
#define DEBUG_PRINT(cls, x)
#define DEBUG_PRINT_(x)
#define DEBUG_PRINT_TIME(cls, x)
#define DEBUG_PRINT_TIME_(x)
#define VALIDATE(x)
#if DEBUG_LEVEL == NO_SEATBELT
#ifdef assert
#undef assert
#endif
#define assert(x)
#define CONFIRM(x)
#ifndef TRACE_CTOR
#define TRACE_CTOR(cls, args)
#define TRACE_DTOR(cls)
#define TRACE(cat, msg)
#define TRACE_PUSH(cat, msg)
#define TRACE_POP(cat, msg)
#endif
#elif DEBUG_LEVEL == RELEASE
#define CONFIRM(x)
#ifndef TRACE_CTOR
#define TRACE_CTOR(cls, args)
#define TRACE_DTOR(cls)
#define TRACE(cat, msg)
#define TRACE_PUSH(cat, msg)
#define TRACE_POP(cat, msg)
#endif
#elif DEBUG_LEVEL >= BETA
#define CONFIRM(x) assert(x)
#endif
#endif // DEBUG_LEVEL
#endif // _DEBUG_H

77
error.h
View file

@ -1,8 +1,43 @@
#ifndef _ERROR_H
#define _ERROR_H
#import "context.h"
namespace ledger {
class exception : public std::exception
{
protected:
string reason;
public:
std::list<context> context_stack;
exception(const string& _reason,
const context& immediate_ctxt) throw()
: reason(_reason) {
push(immediate_ctxt);
}
void push(const context& intermediate_ctxt) throw() {
context_stack.push_front(intermediate_ctxt);
}
void write(std::ostream& out) const throw() {
for (std::list<context>::const_iterator
i = context.begin();
i != context.end();
i++)
(*i).write(out);
}
const char * what() const throw() {
return reason.c_str();
}
};
#if 0
class error_context
{
public:
@ -57,46 +92,6 @@ class line_context : public error_context {
}
};
//////////////////////////////////////////////////////////////////////
class str_exception : public std::exception {
protected:
string reason;
public:
std::list<error_context *> context;
str_exception(const string& _reason,
error_context * ctxt = NULL) throw()
: reason(_reason) {
if (ctxt)
context.push_back(ctxt);
}
virtual ~str_exception() throw() {
for (std::list<error_context *>::iterator i = context.begin();
i != context.end();
i++)
delete *i;
}
virtual void reveal_context(std::ostream& out,
const string& kind) const throw() {
for (std::list<error_context *>::const_reverse_iterator i =
context.rbegin();
i != context.rend();
i++) {
std::list<error_context *>::const_reverse_iterator x = i;
if (++x == context.rend())
out << kind << ": ";
(*i)->describe(out);
}
}
virtual const char* what() const throw() {
return reason.c_str();
}
};
class error : public str_exception {
public:
error(const string& _reason, error_context * _ctxt = NULL) throw()
@ -118,6 +113,8 @@ class fatal_assert : public fatal {
virtual ~fatal_assert() throw() {}
};
#endif // 0
inline void unexpected(char c, char wanted)
{
if ((unsigned char) c == 0xff) {

View file

@ -1,61 +0,0 @@
#ifndef _TIMING_H
#define _TIMING_H
namespace ledger {
class timing_t
{
public:
std::clock_t begin;
std::clock_t cumulative;
string file;
unsigned long line;
string symbol;
string category;
timing_t(const string& _symbol, const string& _category)
: begin(0), cumulative(0), symbol(_symbol), category(_category) {}
timing_t(const string& _symbol)
: begin(0), cumulative(0), symbol(_symbol) {}
~timing_t() {
string cls = "timing.results.";
cls += symbol;
#if 0
// jww (2007-04-19): This crashes things nowadays
DEBUG_PRINT(cls.c_str(), file << ":" << line << ": "
<< category << " = "
<< (double(cumulative) / double(CLOCKS_PER_SEC)) << "s");
#endif
}
void start(const string& _file, unsigned long _line) {
file = _file;
line = _line;
begin = std::clock();
}
void start() {
begin = std::clock();
}
void stop() {
cumulative += std::clock() - begin;
}
};
#if 0 && DEBUG_LEVEL >= 4
#define TIMER_DEF(sym, cat) static timing_t sym(#sym, cat);
#define TIMER_DEF_(sym) static timing_t sym(#sym, #sym);
#define TIMER_START(sym) sym.start(__FILE__, __LINE__);
#define TIMER_STOP(sym) sym.stop();
#else
#define TIMER_DEF(sym, cat)
#define TIMER_DEF_(sym)
#define TIMER_START(sym)
#define TIMER_STOP(sym)
#endif
} // namespace ledger
#endif // _TIMING_H

130
trace.h
View file

@ -1,130 +0,0 @@
#ifndef _TRACE_H
#define _TRACE_H
namespace ledger {
class timing_t;
extern bool trace_alloc_mode;
extern bool trace_class_mode;
#if 0 && DEBUG_LEVEL >= 4 && ! defined(USE_BOOST_PYTHON)
class string;
#else
typedef std::string string;
#endif
void trace(const string& cat, const string& str);
void trace_push(const string& cat, const string& str, timing_t& timer);
void trace_pop(const string& cat, const string& str, timing_t& timer);
#ifndef TRACE
#define TRACE(cat, msg) if (trace_class_mode) trace(#cat, msg)
#define TRACE_(cat, msg) if (trace_class_mode) trace(#cat, msg)
#define TRACE_PUSH(cat, msg) \
timing_t timer_ ## cat(#cat); \
if (trace_class_mode) trace_push(#cat, msg, timer_ ## cat)
#define TRACE_POP(cat, msg) \
if (trace_class_mode) trace_pop(#cat, msg, timer_ ## cat)
#endif
typedef std::multimap<void *, std::string> live_objects_map;
typedef std::pair<void *, std::string> live_objects_pair;
typedef std::pair<unsigned int, std::size_t> count_size_pair;
typedef std::map<std::string, count_size_pair> object_count_map;
typedef std::pair<std::string, count_size_pair> object_count_pair;
extern live_objects_map live_objects;
extern object_count_map live_count;
extern object_count_map ctor_count;
extern object_count_map object_count;
extern bool tracing_active;
bool trace_ctor(void * ptr, const char * cls_name, const char * args,
std::size_t cls_size);
bool trace_dtor(void * ptr, const char * cls_name, std::size_t cls_size);
void report_memory(std::ostream& out);
#if 1
#ifndef TRACE_CTOR
#define TRACE_CTOR(cls, args) \
CONFIRM(ledger::trace_ctor(this, #cls, args, sizeof(cls)))
#define TRACE_DTOR(cls) \
CONFIRM(ledger::trace_dtor(this, #cls, sizeof(cls)))
#endif
#else
#define TRACE_CTOR(cls, args)
#define TRACE_DTOR(cls)
#endif
#if 0 && DEBUG_LEVEL >= 4 && ! defined(USE_BOOST_PYTHON)
class string : public std::string
{
public:
string();
string(const string& str);
string(const std::string& str);
string(const int len, char x);
string(const char * str);
string(const char * str, const char * end);
string(const string& str, int x);
string(const string& str, int x, int y);
string(const char * str, int x);
string(const char * str, int x, int y);
~string();
};
inline string operator+(const string& __lhs, const string& __rhs)
{
string __str(__lhs);
__str.append(__rhs);
return __str;
}
string operator+(const char* __lhs, const string& __rhs);
string operator+(char __lhs, const string& __rhs);
inline string operator+(const string& __lhs, const char* __rhs)
{
string __str(__lhs);
__str.append(__rhs);
return __str;
}
inline string operator+(const string& __lhs, char __rhs)
{
typedef string __string_type;
typedef string::size_type __size_type;
__string_type __str(__lhs);
__str.append(__size_type(1), __rhs);
return __str;
}
inline bool operator==(const string& __lhs, const string& __rhs)
{ return __lhs.compare(__rhs) == 0; }
inline bool operator==(const char* __lhs, const string& __rhs)
{ return __rhs.compare(__lhs) == 0; }
inline bool operator==(const string& __lhs, const char* __rhs)
{ return __lhs.compare(__rhs) == 0; }
inline bool operator!=(const string& __lhs, const string& __rhs)
{ return __rhs.compare(__lhs) != 0; }
inline bool operator!=(const char* __lhs, const string& __rhs)
{ return __rhs.compare(__lhs) != 0; }
inline bool operator!=(const string& __lhs, const char* __rhs)
{ return __lhs.compare(__rhs) != 0; }
#endif
} // namespace ledger
#endif // _TRACE_H

23
util.h
View file

@ -1,29 +1,6 @@
#ifndef _UTIL_H
#define _UTIL_H
#if defined __FreeBSD__ && __FreeBSD__ <=4
// FreeBSD has a broken isspace macro, so dont use it
#undef isspace(c)
#endif
#if defined(__GNUG__) && __GNUG__ < 3
namespace std {
inline ostream & right (ostream & i) {
i.setf(i.right, i.adjustfield);
return i;
}
inline ostream & left (ostream & i) {
i.setf(i.left, i.adjustfield);
return i;
}
}
typedef unsigned long istream_pos_type;
typedef unsigned long ostream_pos_type;
#else
typedef std::istream::pos_type istream_pos_type;
typedef std::ostream::pos_type ostream_pos_type;
#endif
namespace ledger {
inline char * skip_ws(char * ptr) {

View file

@ -1,31 +1,60 @@
#include "utils.h"
#include "times.h"
namespace ledger {
namespace ledger
bool trace_alloc_mode;
bool trace_class_mode;
#if defined(ASSERTS_ON)
void trace(const string& cat, const string& str)
void debug_assert(const ledger::string& reason,
const ledger::string& func,
const ledger::string& file,
unsigned long line)
{
std::cerr << boost::posix_time::to_simple_string(now) << " "
<< cat << ": " << str << std::endl;
throw fatal(reason, context());
}
void trace_push(const string& cat, const string& str,
timing_t& timer)
{
timer.start();
trace(cat, str);
}
#endif
void trace_pop(const string& cat, const string& str,
timing_t& timer)
{
timer.stop();
std::ostringstream out;
out << str << ": " << (double(timer.cumulative) / double(CLOCKS_PER_SEC)) << "s";
trace(cat, out.str());
#if defined(VERIFY_ON)
int new_calls = 0;
unsigned long new_size = 0;
void * operator new(std::size_t size) throw (std::bad_alloc) {
void * ptr = std::malloc(size);
new_calls++;
new_size += size;
return ptr;
}
void * operator new[](std::size_t size) throw (std::bad_alloc) {
void * ptr = std::malloc(size);
new_calls++;
new_size += size;
return ptr;
}
void * operator new(std::size_t size, const std::nothrow_t&) throw() {
void * ptr = std::malloc(size);
new_calls++;
new_size += size;
return ptr;
}
void * operator new[](std::size_t size, const std::nothrow_t&) throw() {
void * ptr = std::malloc(size);
new_calls++;
new_size += size;
return ptr;
}
void operator delete(void * ptr) throw() {
std::free(ptr);
}
void operator delete[](void * ptr) throw() {
std::free(ptr);
}
void operator delete(void * ptr, const std::nothrow_t&) throw() {
std::free(ptr);
}
void operator delete[](void * ptr, const std::nothrow_t&) throw() {
std::free(ptr);
}
live_objects_map live_objects;
@ -33,8 +62,6 @@ object_count_map ctor_count;
object_count_map object_count;
object_count_map live_count;
bool tracing_active = false;
inline void add_to_count_map(object_count_map& the_map,
const char * name, std::size_t size)
{
@ -63,9 +90,6 @@ inline void report_count_map(std::ostream& out, object_count_map& the_map)
bool trace_ctor(void * ptr, const char * cls_name, const char * args,
std::size_t cls_size)
{
if (! tracing_active)
return true;
if (trace_class_mode && cls_name[0] == '_')
return true;
if (trace_alloc_mode && cls_name[0] != '_')
@ -92,9 +116,6 @@ bool trace_ctor(void * ptr, const char * cls_name, const char * args,
bool trace_dtor(void * ptr, const char * cls_name, std::size_t cls_size)
{
if (! tracing_active)
return true;
if (trace_class_mode && cls_name[0] == '_')
return true;
if (trace_alloc_mode && cls_name[0] != '_')
@ -162,42 +183,106 @@ void report_memory(std::ostream& out)
}
}
#if 0 && DEBUG_LEVEL >= 4 && ! defined(USE_BOOST_PYTHON)
#if ! defined(USE_BOOST_PYTHON)
string::string() : std::string() {
TRACE_CTOR(string, "");
trace_ctor(string, "");
}
string::string(const string& str) : std::string(str) {
TRACE_CTOR(string, "const string&");
trace_ctor(string, "const string&");
}
string::string(const std::string& str) : std::string(str) {
TRACE_CTOR(string, "const std::string&");
trace_ctor(string, "const std::string&");
}
string::string(const int len, char x) : std::string(len, x) {
TRACE_CTOR(string, "const int, char");
trace_ctor(string, "const int, char");
}
string::string(const char * str) : std::string(str) {
TRACE_CTOR(string, "const char *");
trace_ctor(string, "const char *");
}
string::string(const char * str, const char * end) : std::string(str, end) {
TRACE_CTOR(string, "const char *, const char *");
trace_ctor(string, "const char *, const char *");
}
string::string(const string& str, int x) : std::string(str, x) {
TRACE_CTOR(string, "const string&, int");
trace_ctor(string, "const string&, int");
}
string::string(const string& str, int x, int y) : std::string(str, x, y) {
TRACE_CTOR(string, "const string&, int, int");
trace_ctor(string, "const string&, int, int");
}
string::string(const char * str, int x) : std::string(str, x) {
TRACE_CTOR(string, "const char *, int");
trace_ctor(string, "const char *, int");
}
string::string(const char * str, int x, int y) : std::string(str, x, y) {
TRACE_CTOR(string, "const char *, int, int");
trace_ctor(string, "const char *, int, int");
}
string::~string() {
TRACE_DTOR(string);
trace_dtor(string);
}
#endif
#endif // VERIFY_ON
#if defined(TIMERS_ON)
void start_timer(const char * name)
{
begin = std::clock();
}
void stop_timer(const char * name)
{
cumulative += std::clock() - begin;
}
void finish_timer(const char * name)
{
DEBUG_PRINT(cls.c_str(), file << ":" << line << ": "
<< category << " = "
<< (double(cumulative) / double(CLOCKS_PER_SEC)) << "s");
}
#endif // TIMERS_ON
#if defined(LOGGING_ON) && defined(DEBUG_ON)
std::ostream * _debug_stream = &std::cerr;
bool _free_debug_stream = false;
boost::regex _debug_regex;
bool _set_debug_regex = false;
bool _debug_regex_on = false;
bool _debug_active(const char * const cls) {
if (! _set_debug_regex) {
const char * user_class = std::getenv("DEBUG_CLASS");
if (user_class) {
_debug_regex = user_class;
_debug_regex_on = true;
}
_set_debug_regex = true;
}
if (_debug_regex_on)
return boost::regex_match(cls, _debug_regex);
return false;
}
static struct init_streams {
init_streams() {
// If debugging is enabled and DEBUG_FILE is set, all debugging
// output goes to that file.
if (const char * p = std::getenv("DEBUG_FILE")) {
_debug_stream = new std::ofstream(p);
_free_debug_stream = true;
}
}
~init_streams() {
if (_free_debug_stream && _debug_stream) {
delete _debug_stream;
_debug_stream = NULL;
}
}
} _debug_init;
#endif // LOGGING_ON && DEBUG_ON
} // namespace ledger

363
utils.h
View file

@ -3,6 +3,26 @@
#include <system.hh>
#if defined __FreeBSD__ && __FreeBSD__ <=4
// FreeBSD has a broken isspace macro, so don't use it
#undef isspace(c)
#endif
#if defined(__GNUG__) && __GNUG__ < 3
namespace std {
inline ostream & right (ostream & i) {
i.setf(i.right, i.adjustfield);
return i;
}
inline ostream & left (ostream & i) {
i.setf(i.left, i.adjustfield);
return i;
}
}
#endif
namespace ledger {
// jww (2007-04-23): Need to clean up the following include files. I
// want to following services:
//
@ -15,10 +35,343 @@
// verification (optionally on, like debugging but silent)
// memory tracing and debugging (and watching for threshholds)
#include "trace.h"
#include "debug.h"
#include "timing.h"
#include "error.h"
#include "util.h"
#import "error.h"
/**********************************************************************
*
* Default values
*/
#if defined(FULL_DEBUG)
#define VERIFY_ON 1
#define TRACING_ON 1
#define DEBUG_ON 1
#define TIMERS_ON 1
#elif defined(NO_DEBUG)
#define NO_ASSERTS 1
#define NO_LOGGING 1
#else
#define TIMERS_ON 1
#endif
/**********************************************************************
*
* Assertions
*/
#ifdef assert
#undef assert
#endif
#if ! defined(NO_ASSERTS)
#define ASSERTS_ON 1
#endif
#if defined(ASSERTS_ON)
#include <boost/current_function.hpp>
void debug_assert(const ledger::string& reason,
const ledger::string& func,
const ledger::string& file,
unsigned long line);
#define assert(x) \
((x) ? ((void)0) : debug_assert(#x, BOOST_CURRENT_FUNCTION, \
__FILE__, __LINE__)
#endif // ASSERTS_ON
/**********************************************************************
*
* Verification (basically, very slow asserts)
*/
#if defined(VERIFY_ON)
extern bool verify_enabled;
#define verify(x) (verify_enabled ? assert(x) : ((void)0))
extern int new_calls;
extern unsigned long new_size;
void * operator new(std::size_t) throw(std::bad_alloc);
void * operator new[](std::size_t) throw(std::bad_alloc);
void operator delete(void*) throw();
void operator delete[](void*) throw();
void * operator new(std::size_t, const std::nothrow_t&) throw();
void * operator new[](std::size_t, const std::nothrow_t&) throw();
void operator delete(void*, const std::nothrow_t&) throw();
void operator delete[](void*, const std::nothrow_t&) throw();
typedef std::multimap<void *, std::string> live_objects_map;
typedef std::pair<void *, std::string> live_objects_pair;
typedef std::pair<unsigned int, std::size_t> count_size_pair;
typedef std::map<std::string, count_size_pair> object_count_map;
typedef std::pair<std::string, count_size_pair> object_count_pair;
extern live_objects_map live_objects;
extern object_count_map live_count;
extern object_count_map ctor_count;
extern object_count_map object_count;
bool trace_ctor(void * ptr, const char * cls_name, const char * args,
std::size_t cls_size);
bool trace_dtor(void * ptr, const char * cls_name, std::size_t cls_size);
#define trace_ctor(cls, args) \
verify(trace_ctor(this, #cls, args, sizeof(cls)))
#define trace_dtor(cls) \
verify(trace_dtor(this, #cls, sizeof(cls)))
void report_memory(std::ostream& out);
#if ! defined(USE_BOOST_PYTHON)
class string : public std::string
{
public:
string();
string(const string& str);
string(const std::string& str);
string(const int len, char x);
string(const char * str);
string(const char * str, const char * end);
string(const string& str, int x);
string(const string& str, int x, int y);
string(const char * str, int x);
string(const char * str, int x, int y);
~string();
};
inline string operator+(const string& __lhs, const string& __rhs)
{
string __str(__lhs);
__str.append(__rhs);
return __str;
}
string operator+(const char* __lhs, const string& __rhs);
string operator+(char __lhs, const string& __rhs);
inline string operator+(const string& __lhs, const char* __rhs)
{
string __str(__lhs);
__str.append(__rhs);
return __str;
}
inline string operator+(const string& __lhs, char __rhs)
{
typedef string __string_type;
typedef string::size_type __size_type;
__string_type __str(__lhs);
__str.append(__size_type(1), __rhs);
return __str;
}
inline bool operator==(const string& __lhs, const string& __rhs)
{ return __lhs.compare(__rhs) == 0; }
inline bool operator==(const char* __lhs, const string& __rhs)
{ return __rhs.compare(__lhs) == 0; }
inline bool operator==(const string& __lhs, const char* __rhs)
{ return __lhs.compare(__rhs) == 0; }
inline bool operator!=(const string& __lhs, const string& __rhs)
{ return __rhs.compare(__lhs) != 0; }
inline bool operator!=(const char* __lhs, const string& __rhs)
{ return __rhs.compare(__lhs) != 0; }
inline bool operator!=(const string& __lhs, const char* __rhs)
{ return __lhs.compare(__rhs) != 0; }
#endif
#else // ! VERIFY_ON
#define verify(x)
#define trace_ctor(cls, args)
#define trace_dtor(cls)
#endif // VERIFY_ON
/**********************************************************************
*
* Logging
*/
#if ! defined(NO_LOGGING)
#define LOGGING_ON 1
#endif
#if defined(LOGGING_ON)
// Logging
enum log_level_t {
LOG_OFF = 0,
LOG_CRIT,
LOG_FATAL,
LOG_ASSERT,
LOG_ERROR,
LOG_VERIFY,
LOG_WARN,
LOG_INFO,
LOG_EXCEPT,
LOG_DEBUG,
LOG_TRACE,
LOG_ALL
};
extern log_level_t _log_level;
extern unsigned int _trace_level;
extern std::string _log_category;
extern std::ostream * _log_stream;
extern std::ostringstream _log_buffer;
#define category(cat) \
static const char * const _this_category = (cat)
bool logger(log_level_t level);
#if defined(TRACING_ON)
#define trace(lvl, msg) \
(_log_level >= LOG_TRACE && lvl >= _trace_level ? \
((_log_buffer << msg), logger(LOG_TRACE)) : false)
#else
#define trace(lvl, msg)
#endif
#if defined(DEBUG_ON)
#define debug_(cat, msg) \
(_log_level >= LOG_DEBUG && \
(_log_category == cat || \
_log_category.find(cat ".") == 0) ? \
((_log_buffer << msg), logger(LOG_DEBUG)) : false)
#define debug(msg) debug_(_this_category, msg)
#else
#define debug_(cat, msg)
#define debug(msg)
#endif
#define info_(cat, msg) \
(_log_level >= LOG_INFO && \
(_log_category == cat || \
_log_category.find(cat ".") == 0) ? \
((_log_buffer << msg), logger(LOG_INFO)) : false)
#define info(msg) info_(_this_category, msg)
#define log_macro(level, msg) \
(_log_level >= level ? \
((_log_buffer << msg), logger(level)) : false)
#define warn(msg) log_macro(LOG_WARN, msg)
#define error(msg) log_macro(LOG_ERROR, msg)
#define fatal(msg) log_macro(LOG_FATAL, msg)
#define critical(msg) log_macro(LOG_CRIT, msg)
#else // ! LOGGING_ON
#define category(cat)
#define trace(lvl, msg)
#define debug(msg)
#define debug_(cat, msg)
#define info(msg)
#define info_(cat, msg)
#define warn(msg)
#define error(msg)
#define fatal(msg)
#define critical(msg)
/**********************************************************************
*
* Timers (allows log entries to specify cumulative time spent)
*/
#if defined(LOGGING_ON) && defined(TIMERS_ON)
struct timer_t {
std::clock_t count;
std::string message;
};
typedef std::map<std::string, timer_t> timing_map;
typedef timing_map::value_type timing_pair;
void start_timer(const char * name);
void stop_timer(const char * name);
void finish_timer(const char * name);
#if defined(TRACING_ON)
#define trace_start(name, lvl, msg) \
(trace(lvl, msg) && start_timer(name))
#define trace_stop(name) stop_timer(name)
#define trace_finish(name) finish_timer(name)
#else
#define trace_start(name, lvl, msg)
#define trace_stop(name)
#define trace_finish(name)
#endif
#if defined(DEBUG_ON)
#define debug_start(name, msg) \
(debug(msg) && start_timer(name))
#define debug_start_(name, cat, msg) \
(debug_(cat, msg) && start_timer(name))
#define debug_stop(name) stop_timer(name)
#define debug_finish(name) finish_timer(name)
#else
#define debug_start(name, msg)
#define debug_start_(name, cat, msg)
#define debug_stop(name)
#define debug_finish(name)
#endif
#define info_start(name, msg) \
(info(msg) && start_timer(name))
#define info_start_(name, cat, msg)
#define info_stop(name) stop_timer(name)
#define info_finish(name) finish_timer(name)
#else // ! (LOGGING_ON && TIMERS_ON)
#define trace_start(lvl, msg, name)
#define trace_stop(name)
#define trace_finish(name)
#define debug_start(name, msg)
#define debug_start_(name, cat, msg)
#define debug_stop(name)
#define debug_finish(name)
#define info_start(name, msg)
#define info_start_(name, cat, msg)
#define info_stop(name)
#define info_finish(name)
#endif // TIMERS_ON
/**********************************************************************
*
* Debug macros
*/
#if defined(DEBUG_ON)
#define if_debug_(cat) \
if (_log_level >= LOG_DEBUG && \
(_log_category == cat || \
_log_category.find(cat ".") == 0))
#define if_debug() if_debug_(_this_category)
#else // ! DEBUG_ON
#define if_debug(cat) if (false)
#endif // DEBUG_ON
// } namespace ledger
#endif // _UTILS_H