diff options
-rw-r--r-- | journal.cc | 13 | ||||
-rw-r--r-- | journal.h | 29 | ||||
-rw-r--r-- | textual.cc | 105 |
3 files changed, 135 insertions, 12 deletions
@@ -165,7 +165,7 @@ void entry_t::add_transaction(transaction_t * xact) bool entry_t::valid() const { - if (! date) + if (! date || ! journal) return false; if (state != UNCLEARED && state != CLEARED && state != PENDING) @@ -276,6 +276,7 @@ account_t * account_t::find_account(const std::string& name, return NULL; account = new account_t(this, first); + account->journal = journal; std::pair<accounts_map::iterator, bool> result = accounts.insert(accounts_pair(first, account)); @@ -338,7 +339,7 @@ std::ostream& operator<<(std::ostream& out, const account_t& account) bool account_t::valid() const { - if (depth > 256) + if (depth > 256 || ! journal) return false; for (accounts_map::const_iterator i = accounts.begin(); @@ -398,6 +399,7 @@ bool journal_t::add_entry(entry_t * entry) return false; entries.push_back(entry); + entry->journal = this; for (transactions_list::const_iterator i = entry->transactions.begin(); i != entry->transactions.end(); @@ -422,6 +424,7 @@ bool journal_t::remove_entry(entry_t * entry) return false; entries.erase(i); + entry->journal = NULL; return true; } @@ -686,6 +689,7 @@ void export_journal() .def(self == self) .def(self != self) + .def_readonly("journal", &account_t::journal) .add_property("parent", make_getter(&account_t::parent, return_internal_reference<1>())) @@ -739,6 +743,11 @@ void export_journal() .def("__getitem__", transactions_getitem, return_internal_reference<1>()) + .def_readonly("journal", &entry_base_t::journal) + .def_readonly("src_idx", &entry_base_t::src_idx) + .def_readonly("beg_pos", &entry_base_t::beg_pos) + .def_readonly("end_pos", &entry_base_t::end_pos) + .def("add_transaction", py_add_transaction) .def("remove_transaction", &entry_base_t::remove_transaction) @@ -74,12 +74,18 @@ class transaction_t bool valid() const; }; +class journal_t; + typedef std::list<transaction_t *> transactions_list; class entry_base_t { public: - transactions_list transactions; + journal_t * journal; + unsigned long src_idx; + std::istream::pos_type beg_pos; + std::istream::pos_type end_pos; + transactions_list transactions; entry_base_t() { DEBUG_PRINT("ledger.memory.ctors", "ctor entry_base_t"); @@ -216,14 +222,15 @@ class account_t public: typedef unsigned long ident_t; - account_t * parent; - std::string name; - std::string note; - unsigned short depth; - accounts_map accounts; + journal_t * journal; + account_t * parent; + std::string name; + std::string note; + unsigned short depth; + accounts_map accounts; - mutable void * data; - mutable ident_t ident; + mutable void * data; + mutable ident_t ident; mutable std::string _fullname; account_t(account_t * _parent = NULL, @@ -247,9 +254,11 @@ class account_t void add_account(account_t * acct) { accounts.insert(accounts_pair(acct->name, acct)); + acct->journal = journal; } bool remove_account(account_t * acct) { accounts_map::size_type n = accounts.erase(acct->name); + acct->journal = NULL; return n > 0; } @@ -325,6 +334,7 @@ class journal_t journal_t() { DEBUG_PRINT("ledger.memory.ctors", "ctor journal_t"); master = new account_t(NULL, ""); + master->journal = this; item_pool = item_pool_end = NULL; } ~journal_t(); @@ -338,9 +348,11 @@ class journal_t void add_account(account_t * acct) { master->add_account(acct); + acct->journal = this; } bool remove_account(account_t * acct) { return master->remove_account(acct); + acct->journal = NULL; } account_t * find_account(const std::string& name, bool auto_create = true) { @@ -350,6 +362,7 @@ class journal_t account_t * account = master->find_account(name, auto_create); accounts_cache.insert(accounts_pair(name, account)); + account->journal = this; return account; } account_t * find_account_re(const std::string& regexp); @@ -7,6 +7,7 @@ #include "config.h" #include "timing.h" #include "util.h" +#include "acconf.h" #ifdef USE_BOOST_PYTHON #include "py_eval.h" #endif @@ -308,6 +309,8 @@ unsigned int textual_parser_t::parse(std::istream& in, while (in.good() && ! in.eof()) { try { + std::istream::pos_type beg_pos = in.tellg(); + in.getline(line, MAX_LINE); if (in.eof()) break; @@ -477,11 +480,15 @@ unsigned int textual_parser_t::parse(std::istream& in, auto_entry_t * ae = new auto_entry_t(skip_ws(line + 1)); if (parse_transactions(in, account_stack.front(), *ae, "automated")) { - if (ae->finalize()) + if (ae->finalize()) { journal->auto_entries.push_back(ae); - else + ae->src_idx = journal->sources.size() - 1; + ae->beg_pos = beg_pos; + ae->end_pos = in.tellg(); + } else { throw parse_error(path, linenum, "Automated entry failed to balance"); + } } break; } @@ -496,6 +503,9 @@ unsigned int textual_parser_t::parse(std::istream& in, if (pe->finalize()) { extend_entry_base(journal, *pe); journal->period_entries.push_back(pe); + pe->src_idx = journal->sources.size() - 1; + pe->beg_pos = beg_pos; + pe->end_pos = in.tellg(); } else { throw parse_error(path, linenum, "Period entry failed to balance"); } @@ -543,9 +553,13 @@ unsigned int textual_parser_t::parse(std::istream& in, default: { unsigned int first_line = linenum; + if (entry_t * entry = parse_entry(in, line, account_stack.front(), *this)) { if (journal->add_entry(entry)) { + entry->src_idx = journal->sources.size() - 1; + entry->beg_pos = beg_pos; + entry->end_pos = in.tellg(); count++; } else { delete entry; @@ -584,6 +598,93 @@ unsigned int textual_parser_t::parse(std::istream& in, return count; } +void write_textual_journal(journal_t& journal, std::string path, + item_handler<transaction_t>& formatter, + std::ostream& out) +{ + unsigned long index = 0; + std::string found; + char buf1[PATH_MAX]; + char buf2[PATH_MAX]; + +#ifdef HAVE_REALPATH + realpath(path.c_str(), buf1); + for (strings_list::iterator i = journal.sources.begin(); + i != journal.sources.end(); + i++) { + realpath((*i).c_str(), buf2); + if (std::strcmp(buf1, buf2) == 0) { + found = *i; + break; + } + index++; + } +#else + for (strings_list::iterator i = journal.sources.begin(); + i != journal.sources.end(); + i++) { + if (path == *i) { + found = *i; + break; + } + index++; + } +#endif + + if (found.empty()) + throw error(std::string("Journal does not refer to file '") + + found + "'"); + + entries_list::iterator el = journal.entries.begin(); + auto_entries_list::iterator al = journal.auto_entries.begin(); + period_entries_list::iterator pl = journal.period_entries.begin(); + + std::istream::pos_type pos = 0; + std::istream::pos_type jump_to; + + format_t hdr_fmt(config.write_hdr_format); + + std::ifstream in(found.c_str()); + while (! in.eof()) { + entry_base_t * base = NULL; + if (el != journal.entries.end() && + pos == (*el)->beg_pos) { + hdr_fmt.format(out, details_t(**el)); + base = *el++; + } + else if (al != journal.auto_entries.end() && + pos == (*al)->beg_pos) { + out << "= " << (*al)->predicate_string << '\n'; + base = *al++; + } + else if (pl != journal.period_entries.end() && + pos == (*pl)->beg_pos) { + out << "~ " << (*pl)->period_string << '\n'; + base = *pl++; + } + + char c; + if (base) { + for (transactions_list::iterator x = base->transactions.begin(); + x != base->transactions.end(); + x++) + transaction_xdata(**x).dflags |= TRANSACTION_TO_DISPLAY; + + walk_transactions(base->transactions, formatter); + formatter.flush(); + + while (pos < base->end_pos) { + in.get(c); + pos = in.tellg(); // pos++; + } + } else { + in.get(c); + pos = in.tellg(); // pos++; + out.put(c); + } + } +} + } // namespace ledger #ifdef USE_BOOST_PYTHON |