Reduced memory consumption of register report.

This commit is contained in:
John Wiegley 2007-04-23 04:42:28 +00:00
parent ece13a8cf1
commit be9f18ccfe
12 changed files with 177 additions and 79 deletions

View file

@ -70,6 +70,7 @@ void debug_assert(const ledger::string& reason,
#include <new> #include <new>
#include <iostream> #include <iostream>
#include <cstdlib> #include <cstdlib>
#include <cassert>
#include <boost/regex.hpp> #include <boost/regex.hpp>
@ -108,6 +109,9 @@ bool _debug_active(const char * const cls);
#define VALIDATE(x) #define VALIDATE(x)
#endif #endif
extern int new_calls;
extern int new_size;
#if 0 #if 0
void * operator new(std::size_t) throw (std::bad_alloc); void * operator new(std::size_t) throw (std::bad_alloc);
void * operator new[](std::size_t) throw (std::bad_alloc); void * operator new[](std::size_t) throw (std::bad_alloc);

View file

@ -3,25 +3,72 @@
namespace ledger { namespace ledger {
static void scan_for_transactions(std::ostream& out, const xml::node_t * node)
{
if (! (node->flags & XML_NODE_IS_PARENT))
return;
const xml::parent_node_t * parent =
static_cast<const xml::parent_node_t *>(node);
for (const xml::node_t * child = parent->children();
child;
child = child->next)
if (child->name_id == xml::document_t::TRANSACTION) {
const xml::transaction_node_t * xact_node =
dynamic_cast<const xml::transaction_node_t *>(child);
assert(xact_node);
const transaction_t * xact = xact_node->transaction;
assert(xact);
std::cout << xact->entry->date() << ' '
<< std::setw(21) << std::left
<< abbreviate(xact->entry->payee, 21) << ' '
<< std::setw(21) << std::left
<< abbreviate(xact->account->fullname(), 21,
ABBREVIATE, true) << ' '
<< std::setw(12) << std::right
<< xact->amount
<< std::endl;
} else {
scan_for_transactions(out, child);
}
}
void register_command::print_document(std::ostream& out, void register_command::print_document(std::ostream& out,
xml::document_t * doc) xml::document_t * doc)
{ {
value_t nodelist = xml::xpath_t::eval("//transaction", doc); #if DEBUG_LEVEL >= BETA
std::size_t old_new_size = new_size;
#endif
value_t::sequence_t * xact_list = nodelist.to_sequence(); #if 1
scan_for_transactions(out, doc->top);
#else
value_t nodelist;
xml::xpath_t::eval(nodelist, "//transaction", doc);
#if DEBUG_LEVEL >= BETA
std::cerr << "Memory requested preparing report: "
<< (new_size - old_new_size) << std::endl;
old_new_size = new_size;
#endif
const value_t::sequence_t * xact_list = nodelist.to_sequence();
assert(xact_list); assert(xact_list);
for (value_t::sequence_t::iterator i = xact_list->begin(); for (value_t::sequence_t::const_iterator i = xact_list->begin();
i != xact_list->end(); i != xact_list->end();
i++) { i++) {
xml::node_t * node = (*i).to_xml_node(); const xml::node_t * node = (*i).to_xml_node();
assert(node); assert(node);
xml::transaction_node_t * xact_node = const xml::transaction_node_t * xact_node =
dynamic_cast<xml::transaction_node_t *>(node); dynamic_cast<const xml::transaction_node_t *>(node);
assert(xact_node); assert(xact_node);
transaction_t * xact = xact_node->transaction; const transaction_t * xact = xact_node->transaction;
assert(xact); assert(xact);
std::cout << xact->entry->date() << ' ' std::cout << xact->entry->date() << ' '
@ -34,6 +81,13 @@ void register_command::print_document(std::ostream& out,
<< xact->amount << xact->amount
<< std::endl; << std::endl;
} }
#if DEBUG_LEVEL >= BETA
std::cerr << "Memory requested generating report: "
<< (new_size - old_new_size) << std::endl;
old_new_size = new_size;
#endif
#endif
} }
} // namespace ledger } // namespace ledger

1
tests/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
*.pyc

1
tests/python/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
*.pyc

1
tests/python/corelib/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
*.pyc

View file

@ -0,0 +1 @@
*.pyc

View file

@ -72,16 +72,16 @@ string resolve_path(const string& path)
} }
string abbreviate(const string& str, unsigned int width, string abbreviate(const string& str, unsigned int width,
elision_style_t elision_style, const bool is_account, elision_style_t elision_style, const bool is_account,
int abbrev_length) int abbrev_length)
{ {
const unsigned int len = str.length(); const unsigned int len = str.length();
if (len <= width) if (len <= width)
return str; return str;
//assert(width < 4095); assert(width < 4095);
char buf[4096]; static char buf[4096];
switch (elision_style) { switch (elision_style) {
case TRUNCATE_LEADING: case TRUNCATE_LEADING:

View file

@ -8,6 +8,8 @@
#include <vector> #include <vector>
#include <exception> #include <exception>
#include <boost/shared_ptr.hpp>
namespace ledger { namespace ledger {
namespace xml { namespace xml {

103
xml.cc
View file

@ -9,10 +9,24 @@
namespace ledger { namespace ledger {
namespace xml { namespace xml {
document_t::document_t(node_t * _top, const char ** _builtins, const std::size_t document_t::ledger_builtins_size = 12;
const int _builtins_size) const char * document_t::ledger_builtins[] = {
: builtins(_builtins), builtins_size(_builtins_size), stub(this), "account",
top(_top ? _top : &stub) { "account-path",
"amount",
"code",
"commodity",
"entries",
"entry",
"journal",
"name",
"note",
"payee",
"transaction"
};
document_t::document_t(node_t * _top)
: stub(this), top(_top ? _top : &stub) {
TRACE_CTOR(xml::document_t, "node_t *, const char **, const int"); TRACE_CTOR(xml::document_t, "node_t *, const char **, const int");
} }
@ -50,24 +64,9 @@ int document_t::register_name(const string& name)
int document_t::lookup_name_id(const string& name) const int document_t::lookup_name_id(const string& name) const
{ {
if (builtins) { int id;
int first = 0; if ((id = lookup_builtin_id(name)) != -1)
int last = builtins_size; return id;
while (first <= last) {
int mid = (first + last) / 2; // compute mid point.
int result;
if ((result = (int)name[0] - (int)builtins[mid][0]) == 0)
result = std::strcmp(name.c_str(), builtins[mid]);
if (result > 0)
first = mid + 1; // repeat search in top half.
else if (result < 0)
last = mid - 1; // repeat search in bottom half.
else
return mid;
}
}
DEBUG_PRINT("xml.lookup", this << " Finding name: " << name); DEBUG_PRINT("xml.lookup", this << " Finding name: " << name);
@ -78,6 +77,29 @@ int document_t::lookup_name_id(const string& name) const
return -1; return -1;
} }
int document_t::lookup_builtin_id(const string& name)
{
int first = 0;
int last = (int)ledger_builtins_size;
while (first <= last) {
int mid = (first + last) / 2; // compute mid point.
int result;
if ((result = (int)name[0] - (int)ledger_builtins[mid][0]) == 0)
result = std::strcmp(name.c_str(), ledger_builtins[mid]);
if (result > 0)
first = mid + 1; // repeat search in top half.
else if (result < 0)
last = mid - 1; // repeat search in bottom half.
else
return mid + 10;
}
return -1;
}
const char * document_t::lookup_name(int id) const const char * document_t::lookup_name(int id) const
{ {
if (id < 1000) { if (id < 1000) {
@ -92,8 +114,7 @@ const char * document_t::lookup_name(int id) const
return "ALL"; return "ALL";
default: default:
assert(id >= 10); assert(id >= 10);
assert(builtins); return ledger_builtins[id - 10];
return builtins[id - 10];
} }
} else { } else {
return names[id - 1000].c_str(); return names[id - 1000].c_str();
@ -343,10 +364,9 @@ bool parser_t::test(std::istream& in) const
return true; return true;
} }
document_t * parser_t::parse(std::istream& in, const char ** builtins, document_t * parser_t::parse(std::istream& in)
const int builtins_size)
{ {
std::auto_ptr<document_t> doc(new document_t(NULL, builtins, builtins_size)); std::auto_ptr<document_t> doc(new document_t);
document = doc.get(); document = doc.get();
@ -410,12 +430,13 @@ node_t * transaction_node_t::children() const
node_t * transaction_node_t::lookup_child(int _name_id) const node_t * transaction_node_t::lookup_child(int _name_id) const
{ {
if (_name_id == entry_node_t::payee_id) { switch (_name_id) {
case document_t::PAYEE:
payee_virtual_node = new terminal_node_t(document); payee_virtual_node = new terminal_node_t(document);
payee_virtual_node->set_text(transaction->entry->payee); payee_virtual_node->set_text(transaction->entry->payee);
return payee_virtual_node; return payee_virtual_node;
}
else if (_name_id == journal_node_t::account_id) { case document_t::ACCOUNT:
return new account_node_t(document, transaction->account, return new account_node_t(document, transaction->account,
const_cast<transaction_node_t *>(this)); const_cast<transaction_node_t *>(this));
} }
@ -427,9 +448,6 @@ value_t transaction_node_t::to_value() const
return transaction->amount; return transaction->amount;
} }
int entry_node_t::code_id = -1;
int entry_node_t::payee_id = -1;
node_t * entry_node_t::children() const node_t * entry_node_t::children() const
{ {
if (! _children) if (! _children)
@ -443,19 +461,20 @@ node_t * entry_node_t::children() const
node_t * entry_node_t::lookup_child(int _name_id) const node_t * entry_node_t::lookup_child(int _name_id) const
{ {
if (_name_id == entry_node_t::code_id) { switch (_name_id) {
case document_t::CODE:
// jww (2007-04-20): I have to save this and then delete it later // jww (2007-04-20): I have to save this and then delete it later
terminal_node_t * code_node = terminal_node_t * code_node =
new terminal_node_t(document, const_cast<entry_node_t *>(this)); new terminal_node_t(document, const_cast<entry_node_t *>(this));
code_node->set_name("code"); code_node->set_name(document_t::CODE);
code_node->set_text(entry->code); code_node->set_text(entry->code);
return code_node; return code_node;
}
else if (_name_id == entry_node_t::payee_id) { case document_t::PAYEE:
// jww (2007-04-20): I have to save this and then delete it later // jww (2007-04-20): I have to save this and then delete it later
terminal_node_t * payee_node = terminal_node_t * payee_node =
new terminal_node_t(document, const_cast<entry_node_t *>(this)); new terminal_node_t(document, const_cast<entry_node_t *>(this));
payee_node->set_name("payee"); payee_node->set_name(document_t::PAYEE);
payee_node->set_text(entry->payee); payee_node->set_text(entry->payee);
return payee_node; return payee_node;
} }
@ -468,14 +487,14 @@ node_t * account_node_t::children() const
if (! account->name.empty()) { if (! account->name.empty()) {
terminal_node_t * name_node = terminal_node_t * name_node =
new terminal_node_t(document, const_cast<account_node_t *>(this)); new terminal_node_t(document, const_cast<account_node_t *>(this));
name_node->set_name("name"); name_node->set_name(document_t::NAME);
name_node->set_text(account->name); name_node->set_text(account->name);
} }
if (! account->note.empty()) { if (! account->note.empty()) {
terminal_node_t * note_node = terminal_node_t * note_node =
new terminal_node_t(document, const_cast<account_node_t *>(this)); new terminal_node_t(document, const_cast<account_node_t *>(this));
note_node->set_name("note"); note_node->set_name(document_t::NOTE);
note_node->set_text(account->note); note_node->set_text(account->note);
} }
@ -487,8 +506,6 @@ node_t * account_node_t::children() const
return parent_node_t::children(); return parent_node_t::children();
} }
int journal_node_t::account_id = -1;
node_t * journal_node_t::children() const node_t * journal_node_t::children() const
{ {
if (! _children) { if (! _children) {
@ -499,7 +516,7 @@ node_t * journal_node_t::children() const
parent_node_t * entries = parent_node_t * entries =
new parent_node_t(document, const_cast<journal_node_t *>(this)); new parent_node_t(document, const_cast<journal_node_t *>(this));
entries->set_name("entries"); entries->set_name(document_t::ENTRIES);
for (entries_list::iterator i = journal->entries.begin(); for (entries_list::iterator i = journal->entries.begin();
i != journal->entries.end(); i != journal->entries.end();

50
xml.h
View file

@ -182,9 +182,26 @@ private:
class document_t class document_t
{ {
const char ** builtins; static const char * ledger_builtins[];
const int builtins_size; static const std::size_t ledger_builtins_size;
public:
enum ledger_builtins_t {
ACCOUNT = 10,
ACCOUNT_PATH,
AMOUNT,
CODE,
COMMODITY,
ENTRIES,
ENTRY,
JOURNAL,
NAME,
NOTE,
PAYEE,
TRANSACTION
};
private:
typedef std::vector<string> names_array; typedef std::vector<string> names_array;
names_array names; names_array names;
@ -205,14 +222,14 @@ class document_t
CURRENT, PARENT, ROOT, ALL CURRENT, PARENT, ROOT, ALL
}; };
document_t(node_t * _top = NULL, const char ** _builtins = NULL, document_t(node_t * _top = NULL);
const int _builtins_size = 0);
~document_t(); ~document_t();
void set_top(node_t * _top); void set_top(node_t * _top);
int register_name(const string& name); int register_name(const string& name);
int lookup_name_id(const string& name) const; int lookup_name_id(const string& name) const;
static int lookup_builtin_id(const string& name);
const char * lookup_name(int id) const; const char * lookup_name(int id) const;
void write(std::ostream& out) const; void write(std::ostream& out) const;
@ -237,9 +254,7 @@ class parser_t
virtual ~parser_t() {} virtual ~parser_t() {}
virtual bool test(std::istream& in) const; virtual bool test(std::istream& in) const;
virtual document_t * parse(std::istream& in, virtual document_t * parse(std::istream& in);
const char ** builtins = NULL,
const int builtins_size = 0);
}; };
class parse_error : public error { class parse_error : public error {
@ -262,7 +277,7 @@ public:
parent_node_t * _parent = NULL) parent_node_t * _parent = NULL)
: parent_node_t(_document, _parent), commodity(_commodity) { : parent_node_t(_document, _parent), commodity(_commodity) {
TRACE_CTOR(commodity_node_t, "document_t *, commodity_t *, parent_node_t *"); TRACE_CTOR(commodity_node_t, "document_t *, commodity_t *, parent_node_t *");
set_name("commodity"); set_name(document_t::COMMODITY);
} }
virtual ~commodity_node_t() { virtual ~commodity_node_t() {
TRACE_DTOR(commodity_node_t); TRACE_DTOR(commodity_node_t);
@ -281,7 +296,7 @@ public:
parent_node_t * _parent = NULL) parent_node_t * _parent = NULL)
: parent_node_t(_document, _parent), amount(_amount) { : parent_node_t(_document, _parent), amount(_amount) {
TRACE_CTOR(amount_node_t, "document_t *, amount_t *, parent_node_t *"); TRACE_CTOR(amount_node_t, "document_t *, amount_t *, parent_node_t *");
set_name("amount"); set_name(document_t::AMOUNT);
} }
virtual ~amount_node_t() { virtual ~amount_node_t() {
TRACE_DTOR(amount_node_t); TRACE_DTOR(amount_node_t);
@ -307,7 +322,7 @@ public:
: parent_node_t(_document, _parent), payee_virtual_node(NULL), : parent_node_t(_document, _parent), payee_virtual_node(NULL),
transaction(_transaction) { transaction(_transaction) {
TRACE_CTOR(transaction_node_t, "document_t *, transaction_t *, parent_node_t *"); TRACE_CTOR(transaction_node_t, "document_t *, transaction_t *, parent_node_t *");
set_name("transaction"); set_name(document_t::TRANSACTION);
} }
virtual ~transaction_node_t() { virtual ~transaction_node_t() {
TRACE_DTOR(transaction_node_t); TRACE_DTOR(transaction_node_t);
@ -322,8 +337,6 @@ public:
class entry_node_t : public parent_node_t class entry_node_t : public parent_node_t
{ {
static int code_id;
static int payee_id;
entry_t * entry; entry_t * entry;
public: public:
@ -331,11 +344,7 @@ public:
parent_node_t * _parent = NULL) parent_node_t * _parent = NULL)
: parent_node_t(_document, _parent), entry(_entry) { : parent_node_t(_document, _parent), entry(_entry) {
TRACE_CTOR(entry_node_t, "document_t *, entry_t *, parent_node_t *"); TRACE_CTOR(entry_node_t, "document_t *, entry_t *, parent_node_t *");
set_name("entry"); set_name(document_t::ENTRY);
if (code_id == -1)
payee_id = document->register_name("code");
if (payee_id == -1)
payee_id = document->register_name("payee");
} }
virtual ~entry_node_t() { virtual ~entry_node_t() {
TRACE_DTOR(entry_node_t); TRACE_DTOR(entry_node_t);
@ -356,7 +365,7 @@ public:
parent_node_t * _parent = NULL) parent_node_t * _parent = NULL)
: parent_node_t(_document, _parent), account(_account) { : parent_node_t(_document, _parent), account(_account) {
TRACE_CTOR(account_node_t, "document_t *, account_t *, parent_node_t *"); TRACE_CTOR(account_node_t, "document_t *, account_t *, parent_node_t *");
set_name("account"); set_name(document_t::ACCOUNT);
} }
virtual ~account_node_t() { virtual ~account_node_t() {
TRACE_DTOR(account_node_t); TRACE_DTOR(account_node_t);
@ -367,7 +376,6 @@ public:
class journal_node_t : public parent_node_t class journal_node_t : public parent_node_t
{ {
static int account_id;
journal_t * journal; journal_t * journal;
public: public:
@ -375,9 +383,7 @@ public:
parent_node_t * _parent = NULL) parent_node_t * _parent = NULL)
: parent_node_t(_document, _parent), journal(_journal) { : parent_node_t(_document, _parent), journal(_journal) {
TRACE_CTOR(journal_node_t, "document_t *, journal_t *, parent_node_t *"); TRACE_CTOR(journal_node_t, "document_t *, journal_t *, parent_node_t *");
set_name("journal"); set_name(document_t::JOURNAL);
if (account_id == -1)
account_id = document->register_name("account");
} }
virtual ~journal_node_t() { virtual ~journal_node_t() {
TRACE_DTOR(journal_node_t); TRACE_DTOR(journal_node_t);

View file

@ -655,10 +655,16 @@ xpath_t::parse_value_term(std::istream& in, unsigned short tflags) const
#endif #endif
string ident = tok.value.to_string(); string ident = tok.value.to_string();
int id = -1;
if (std::isdigit(ident[0])) { if (std::isdigit(ident[0])) {
node.reset(new op_t(op_t::ARG_INDEX)); node.reset(new op_t(op_t::ARG_INDEX));
node->arg_index = std::atol(ident.c_str()); node->arg_index = std::atol(ident.c_str());
} else { }
else if ((id = document_t::lookup_builtin_id(ident)) != -1) {
node.reset(new op_t(op_t::NODE_ID));
node->name_id = id;
}
else {
node.reset(new op_t(op_t::NODE_NAME)); node.reset(new op_t(op_t::NODE_NAME));
node->name = new string(ident); node->name = new string(ident);
} }
@ -1312,7 +1318,7 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
// First, look up the symbol as a node name within the current // First, look up the symbol as a node name within the current
// context. If any exist, then return the set of names. // context. If any exist, then return the set of names.
value_t::sequence_t * nodes = new value_t::sequence_t; std::auto_ptr<value_t::sequence_t> nodes(new value_t::sequence_t);
if (ptr->flags & XML_NODE_IS_PARENT) { if (ptr->flags & XML_NODE_IS_PARENT) {
parent_node_t * parent = static_cast<parent_node_t *>(ptr); parent_node_t * parent = static_cast<parent_node_t *>(ptr);
@ -1325,7 +1331,7 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
nodes->push_back(node); nodes->push_back(node);
} }
} }
return wrap_value(nodes)->acquire(); return wrap_value(nodes.release())->acquire();
} else { } else {
assert(ptr); assert(ptr);
int id = ptr->document->lookup_name_id(*name); int id = ptr->document->lookup_name_id(*name);

View file

@ -734,6 +734,11 @@ public:
return temp; return temp;
} }
static void eval(value_t& result, const string& _expr,
document_t * document, scope_t * scope = NULL) {
xpath_t temp(_expr);
temp.calc(result, document->top, scope);
}
static value_t eval(const string& _expr, document_t * document, static value_t eval(const string& _expr, document_t * document,
scope_t * scope = NULL) { scope_t * scope = NULL) {
xpath_t temp(_expr); xpath_t temp(_expr);