summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2007-04-23 04:42:28 +0000
committerJohn Wiegley <johnw@newartisans.com>2008-04-13 03:38:30 -0400
commitbe9f18ccfe81acdd2f34b27352f2843235fab69b (patch)
tree89bb8aea8ac4d367b1c054eeea5d3fd9f7bb197c
parentece13a8cf10e9afb576139411f450d8b37ec8e65 (diff)
downloadfork-ledger-be9f18ccfe81acdd2f34b27352f2843235fab69b.tar.gz
fork-ledger-be9f18ccfe81acdd2f34b27352f2843235fab69b.tar.bz2
fork-ledger-be9f18ccfe81acdd2f34b27352f2843235fab69b.zip
Reduced memory consumption of register report.
-rw-r--r--debug.h4
-rw-r--r--register.cc68
-rw-r--r--tests/.gitignore1
-rw-r--r--tests/python/.gitignore1
-rw-r--r--tests/python/corelib/.gitignore1
-rw-r--r--tests/python/corelib/numerics/.gitignore1
-rw-r--r--util.cc8
-rw-r--r--value.h2
-rw-r--r--xml.cc103
-rw-r--r--xml.h50
-rw-r--r--xpath.cc12
-rw-r--r--xpath.h5
12 files changed, 177 insertions, 79 deletions
diff --git a/debug.h b/debug.h
index 0de0a7ea..e0c2dc6e 100644
--- a/debug.h
+++ b/debug.h
@@ -70,6 +70,7 @@ void debug_assert(const ledger::string& reason,
#include <new>
#include <iostream>
#include <cstdlib>
+#include <cassert>
#include <boost/regex.hpp>
@@ -108,6 +109,9 @@ bool _debug_active(const char * const cls);
#define VALIDATE(x)
#endif
+extern int new_calls;
+extern int new_size;
+
#if 0
void * operator new(std::size_t) throw (std::bad_alloc);
void * operator new[](std::size_t) throw (std::bad_alloc);
diff --git a/register.cc b/register.cc
index 3e75eb13..311bfda1 100644
--- a/register.cc
+++ b/register.cc
@@ -3,25 +3,72 @@
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,
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
+
+#if 1
+ scan_for_transactions(out, doc->top);
+#else
+ value_t nodelist;
+ xml::xpath_t::eval(nodelist, "//transaction", doc);
- value_t::sequence_t * xact_list = nodelist.to_sequence();
+#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);
- 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++) {
- xml::node_t * node = (*i).to_xml_node();
+ const xml::node_t * node = (*i).to_xml_node();
assert(node);
- xml::transaction_node_t * xact_node =
- dynamic_cast<xml::transaction_node_t *>(node);
+ const xml::transaction_node_t * xact_node =
+ dynamic_cast<const xml::transaction_node_t *>(node);
assert(xact_node);
- transaction_t * xact = xact_node->transaction;
+ const transaction_t * xact = xact_node->transaction;
assert(xact);
std::cout << xact->entry->date() << ' '
@@ -34,6 +81,13 @@ void register_command::print_document(std::ostream& out,
<< xact->amount
<< 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
diff --git a/tests/.gitignore b/tests/.gitignore
new file mode 100644
index 00000000..0d20b648
--- /dev/null
+++ b/tests/.gitignore
@@ -0,0 +1 @@
+*.pyc
diff --git a/tests/python/.gitignore b/tests/python/.gitignore
new file mode 100644
index 00000000..0d20b648
--- /dev/null
+++ b/tests/python/.gitignore
@@ -0,0 +1 @@
+*.pyc
diff --git a/tests/python/corelib/.gitignore b/tests/python/corelib/.gitignore
new file mode 100644
index 00000000..0d20b648
--- /dev/null
+++ b/tests/python/corelib/.gitignore
@@ -0,0 +1 @@
+*.pyc
diff --git a/tests/python/corelib/numerics/.gitignore b/tests/python/corelib/numerics/.gitignore
new file mode 100644
index 00000000..0d20b648
--- /dev/null
+++ b/tests/python/corelib/numerics/.gitignore
@@ -0,0 +1 @@
+*.pyc
diff --git a/util.cc b/util.cc
index bda2eba4..cdd1219b 100644
--- a/util.cc
+++ b/util.cc
@@ -72,16 +72,16 @@ string resolve_path(const string& path)
}
string abbreviate(const string& str, unsigned int width,
- elision_style_t elision_style, const bool is_account,
- int abbrev_length)
+ elision_style_t elision_style, const bool is_account,
+ int abbrev_length)
{
const unsigned int len = str.length();
if (len <= width)
return str;
- //assert(width < 4095);
+ assert(width < 4095);
- char buf[4096];
+ static char buf[4096];
switch (elision_style) {
case TRUNCATE_LEADING:
diff --git a/value.h b/value.h
index f7a13f05..dc67e66a 100644
--- a/value.h
+++ b/value.h
@@ -8,6 +8,8 @@
#include <vector>
#include <exception>
+#include <boost/shared_ptr.hpp>
+
namespace ledger {
namespace xml {
diff --git a/xml.cc b/xml.cc
index f35a9134..f5b8c177 100644
--- a/xml.cc
+++ b/xml.cc
@@ -9,10 +9,24 @@
namespace ledger {
namespace xml {
-document_t::document_t(node_t * _top, const char ** _builtins,
- const int _builtins_size)
- : builtins(_builtins), builtins_size(_builtins_size), stub(this),
- top(_top ? _top : &stub) {
+const std::size_t document_t::ledger_builtins_size = 12;
+const char * document_t::ledger_builtins[] = {
+ "account",
+ "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");
}
@@ -50,24 +64,9 @@ int document_t::register_name(const string& name)
int document_t::lookup_name_id(const string& name) const
{
- if (builtins) {
- int first = 0;
- int last = builtins_size;
- 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;
- }
- }
+ int id;
+ if ((id = lookup_builtin_id(name)) != -1)
+ return id;
DEBUG_PRINT("xml.lookup", this << " Finding name: " << name);
@@ -78,6 +77,29 @@ int document_t::lookup_name_id(const string& name) const
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
{
if (id < 1000) {
@@ -92,8 +114,7 @@ const char * document_t::lookup_name(int id) const
return "ALL";
default:
assert(id >= 10);
- assert(builtins);
- return builtins[id - 10];
+ return ledger_builtins[id - 10];
}
} else {
return names[id - 1000].c_str();
@@ -343,10 +364,9 @@ bool parser_t::test(std::istream& in) const
return true;
}
-document_t * parser_t::parse(std::istream& in, const char ** builtins,
- const int builtins_size)
+document_t * parser_t::parse(std::istream& in)
{
- 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();
@@ -410,12 +430,13 @@ node_t * transaction_node_t::children() 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->set_text(transaction->entry->payee);
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,
const_cast<transaction_node_t *>(this));
}
@@ -427,9 +448,6 @@ value_t transaction_node_t::to_value() const
return transaction->amount;
}
-int entry_node_t::code_id = -1;
-int entry_node_t::payee_id = -1;
-
node_t * entry_node_t::children() const
{
if (! _children)
@@ -443,19 +461,20 @@ node_t * entry_node_t::children() 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
terminal_node_t * code_node =
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);
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
terminal_node_t * payee_node =
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);
return payee_node;
}
@@ -468,14 +487,14 @@ node_t * account_node_t::children() const
if (! account->name.empty()) {
terminal_node_t * name_node =
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);
}
if (! account->note.empty()) {
terminal_node_t * note_node =
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);
}
@@ -487,8 +506,6 @@ node_t * account_node_t::children() const
return parent_node_t::children();
}
-int journal_node_t::account_id = -1;
-
node_t * journal_node_t::children() const
{
if (! _children) {
@@ -499,7 +516,7 @@ node_t * journal_node_t::children() const
parent_node_t * entries =
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();
i != journal->entries.end();
diff --git a/xml.h b/xml.h
index b9daa912..e95cf578 100644
--- a/xml.h
+++ b/xml.h
@@ -182,9 +182,26 @@ private:
class document_t
{
- const char ** builtins;
- const int builtins_size;
+ static const char * ledger_builtins[];
+ 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;
names_array names;
@@ -205,14 +222,14 @@ class document_t
CURRENT, PARENT, ROOT, ALL
};
- document_t(node_t * _top = NULL, const char ** _builtins = NULL,
- const int _builtins_size = 0);
+ document_t(node_t * _top = NULL);
~document_t();
void set_top(node_t * _top);
int register_name(const string& name);
int lookup_name_id(const string& name) const;
+ static int lookup_builtin_id(const string& name);
const char * lookup_name(int id) const;
void write(std::ostream& out) const;
@@ -237,9 +254,7 @@ class parser_t
virtual ~parser_t() {}
virtual bool test(std::istream& in) const;
- virtual document_t * parse(std::istream& in,
- const char ** builtins = NULL,
- const int builtins_size = 0);
+ virtual document_t * parse(std::istream& in);
};
class parse_error : public error {
@@ -262,7 +277,7 @@ public:
parent_node_t * _parent = NULL)
: parent_node_t(_document, _parent), commodity(_commodity) {
TRACE_CTOR(commodity_node_t, "document_t *, commodity_t *, parent_node_t *");
- set_name("commodity");
+ set_name(document_t::COMMODITY);
}
virtual ~commodity_node_t() {
TRACE_DTOR(commodity_node_t);
@@ -281,7 +296,7 @@ public:
parent_node_t * _parent = NULL)
: parent_node_t(_document, _parent), amount(_amount) {
TRACE_CTOR(amount_node_t, "document_t *, amount_t *, parent_node_t *");
- set_name("amount");
+ set_name(document_t::AMOUNT);
}
virtual ~amount_node_t() {
TRACE_DTOR(amount_node_t);
@@ -307,7 +322,7 @@ public:
: parent_node_t(_document, _parent), payee_virtual_node(NULL),
transaction(_transaction) {
TRACE_CTOR(transaction_node_t, "document_t *, transaction_t *, parent_node_t *");
- set_name("transaction");
+ set_name(document_t::TRANSACTION);
}
virtual ~transaction_node_t() {
TRACE_DTOR(transaction_node_t);
@@ -322,8 +337,6 @@ public:
class entry_node_t : public parent_node_t
{
- static int code_id;
- static int payee_id;
entry_t * entry;
public:
@@ -331,11 +344,7 @@ public:
parent_node_t * _parent = NULL)
: parent_node_t(_document, _parent), entry(_entry) {
TRACE_CTOR(entry_node_t, "document_t *, entry_t *, parent_node_t *");
- set_name("entry");
- if (code_id == -1)
- payee_id = document->register_name("code");
- if (payee_id == -1)
- payee_id = document->register_name("payee");
+ set_name(document_t::ENTRY);
}
virtual ~entry_node_t() {
TRACE_DTOR(entry_node_t);
@@ -356,7 +365,7 @@ public:
parent_node_t * _parent = NULL)
: parent_node_t(_document, _parent), account(_account) {
TRACE_CTOR(account_node_t, "document_t *, account_t *, parent_node_t *");
- set_name("account");
+ set_name(document_t::ACCOUNT);
}
virtual ~account_node_t() {
TRACE_DTOR(account_node_t);
@@ -367,7 +376,6 @@ public:
class journal_node_t : public parent_node_t
{
- static int account_id;
journal_t * journal;
public:
@@ -375,9 +383,7 @@ public:
parent_node_t * _parent = NULL)
: parent_node_t(_document, _parent), journal(_journal) {
TRACE_CTOR(journal_node_t, "document_t *, journal_t *, parent_node_t *");
- set_name("journal");
- if (account_id == -1)
- account_id = document->register_name("account");
+ set_name(document_t::JOURNAL);
}
virtual ~journal_node_t() {
TRACE_DTOR(journal_node_t);
diff --git a/xpath.cc b/xpath.cc
index aa62edd9..e77f7bc7 100644
--- a/xpath.cc
+++ b/xpath.cc
@@ -655,10 +655,16 @@ xpath_t::parse_value_term(std::istream& in, unsigned short tflags) const
#endif
string ident = tok.value.to_string();
+ int id = -1;
if (std::isdigit(ident[0])) {
node.reset(new op_t(op_t::ARG_INDEX));
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->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
// 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) {
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);
}
}
- return wrap_value(nodes)->acquire();
+ return wrap_value(nodes.release())->acquire();
} else {
assert(ptr);
int id = ptr->document->lookup_name_id(*name);
diff --git a/xpath.h b/xpath.h
index c0cf81d0..e8390f2c 100644
--- a/xpath.h
+++ b/xpath.h
@@ -734,6 +734,11 @@ public:
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,
scope_t * scope = NULL) {
xpath_t temp(_expr);