summaryrefslogtreecommitdiff
path: root/textual.cc
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2005-02-09 05:05:24 +0000
committerJohn Wiegley <johnw@newartisans.com>2008-04-13 02:40:54 -0400
commited000a6967be06bf9e767e7375d2a5ce85c22d94 (patch)
tree69d573b99f2bc1422011cc39abc5342bed2a8b40 /textual.cc
parentd8f35f3152aae177bf0848f6e1e1429600730bb1 (diff)
downloadfork-ledger-ed000a6967be06bf9e767e7375d2a5ce85c22d94.tar.gz
fork-ledger-ed000a6967be06bf9e767e7375d2a5ce85c22d94.tar.bz2
fork-ledger-ed000a6967be06bf9e767e7375d2a5ce85c22d94.zip
Added support for each entry to remember: the file it came from, and
the beginning and ending character positions of that entry within the file. This makes it possible to reproduce the input exactly, with only the changed entries updated.
Diffstat (limited to 'textual.cc')
-rw-r--r--textual.cc105
1 files changed, 103 insertions, 2 deletions
diff --git a/textual.cc b/textual.cc
index c15b7701..339d7a59 100644
--- a/textual.cc
+++ b/textual.cc
@@ -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