added back sorting support

This commit is contained in:
John Wiegley 2004-08-05 19:12:23 -04:00
parent 1741c80fe4
commit 7e87a0a0b1
12 changed files with 200 additions and 169 deletions

View file

@ -1,5 +1,4 @@
#include "ledger.h" #include "ledger.h"
#include "textual.h"
#include <vector> #include <vector>
#include <fstream> #include <fstream>
@ -97,7 +96,7 @@ transaction_t * read_binary_transaction(std::istream& in, entry_t * entry)
return xact; return xact;
} }
entry_t * read_binary_entry(std::istream& in, ledger_t * ledger) entry_t * read_binary_entry(std::istream& in, journal_t * journal)
{ {
entry_t * entry = new entry_t; entry_t * entry = new entry_t;
@ -258,7 +257,7 @@ account_t * read_binary_account(std::istream& in, account_t * master = NULL)
// If all of the subaccounts will be added to a different master // If all of the subaccounts will be added to a different master
// account, throw away what we've learned about the recorded // account, throw away what we've learned about the recorded
// ledger's own master account. // journal's own master account.
if (master) { if (master) {
delete acct; delete acct;
@ -282,9 +281,9 @@ account_t * read_binary_account(std::istream& in, account_t * master = NULL)
return acct; return acct;
} }
unsigned int read_binary_ledger(std::istream& in, unsigned int read_binary_journal(std::istream& in,
const std::string& leader, const std::string& leader,
ledger_t * ledger, journal_t * journal,
account_t * master) account_t * master)
{ {
ident = 0; ident = 0;
@ -325,7 +324,7 @@ unsigned int read_binary_ledger(std::istream& in,
in.read(buf, len); in.read(buf, len);
buf[len] = '\0'; buf[len] = '\0';
ledger->sources.push_back(buf); journal->sources.push_back(buf);
std::time_t old_mtime; std::time_t old_mtime;
struct stat info; struct stat info;
@ -335,7 +334,7 @@ unsigned int read_binary_ledger(std::istream& in,
return 0; return 0;
} }
ledger->master = read_binary_account(in, master); journal->master = read_binary_account(in, master);
unsigned long count; unsigned long count;
in.read((char *)&count, sizeof(count)); in.read((char *)&count, sizeof(count));
@ -351,8 +350,8 @@ unsigned int read_binary_ledger(std::istream& in,
in.read((char *)&count, sizeof(count)); in.read((char *)&count, sizeof(count));
for (int i = count; --i >= 0; ) { for (int i = count; --i >= 0; ) {
entry_t * entry = read_binary_entry(in, ledger); entry_t * entry = read_binary_entry(in, journal);
ledger->entries.push_back(entry); journal->entries.push_back(entry);
} }
#ifdef DEBUG #ifdef DEBUG
@ -557,7 +556,7 @@ void write_binary_account(std::ostream& out, account_t * account)
#endif #endif
} }
void write_binary_ledger(std::ostream& out, ledger_t * ledger, void write_binary_journal(std::ostream& out, journal_t * journal,
const std::string& leader) const std::string& leader)
{ {
out.write((char *)&binary_magic_number, sizeof(binary_magic_number)); out.write((char *)&binary_magic_number, sizeof(binary_magic_number));
@ -576,11 +575,11 @@ void write_binary_ledger(std::ostream& out, ledger_t * ledger,
out.write((char *)&len, sizeof(len)); out.write((char *)&len, sizeof(len));
out.write(leader.c_str(), len); out.write(leader.c_str(), len);
len = ledger->sources.size(); len = journal->sources.size();
out.write((char *)&len, sizeof(len)); out.write((char *)&len, sizeof(len));
for (std::list<std::string>::const_iterator i = ledger->sources.begin(); for (std::list<std::string>::const_iterator i = journal->sources.begin();
i != ledger->sources.end(); i != journal->sources.end();
i++) { i++) {
len = (*i).length(); len = (*i).length();
out.write((char *)&len, sizeof(len)); out.write((char *)&len, sizeof(len));
@ -591,7 +590,7 @@ void write_binary_ledger(std::ostream& out, ledger_t * ledger,
out.write((char *)&info.st_mtime, sizeof(info.st_mtime)); out.write((char *)&info.st_mtime, sizeof(info.st_mtime));
} }
write_binary_account(out, ledger->master); write_binary_account(out, journal->master);
unsigned long count = commodity_t::commodities.size(); unsigned long count = commodity_t::commodities.size();
out.write((char *)&count, sizeof(count)); out.write((char *)&count, sizeof(count));
@ -601,11 +600,11 @@ void write_binary_ledger(std::ostream& out, ledger_t * ledger,
i++) i++)
write_binary_commodity(out, (*i).second); write_binary_commodity(out, (*i).second);
count = ledger->entries.size(); count = journal->entries.size();
out.write((char *)&count, sizeof(count)); out.write((char *)&count, sizeof(count));
for (entries_list::const_iterator i = ledger->entries.begin(); for (entries_list::const_iterator i = journal->entries.begin();
i != ledger->entries.end(); i != journal->entries.end();
i++) i++)
write_binary_entry(out, *i); write_binary_entry(out, *i);

View file

@ -1,21 +0,0 @@
#ifndef _BINARY_H
#define _BINARY_H
#include "ledger.h"
namespace ledger {
extern unsigned long binary_magic_number;
extern unsigned int read_binary_ledger(std::istream& in,
const std::string& leader,
ledger_t * journal,
account_t * master = NULL);
extern void write_binary_ledger(std::ostream& out,
ledger_t * ledger,
const std::string& leader);
} // namespace ledger
#endif // _BINARY_H

View file

@ -147,7 +147,7 @@ element_t * format_t::parse_elements(const std::string& fmt)
void format_t::format_elements(std::ostream& out, void format_t::format_elements(std::ostream& out,
const details_t& details) const const details_t& details) const
{ {
for (const element_t * elem = elements.get(); elem; elem = elem->next) { for (const element_t * elem = elements; elem; elem = elem->next) {
if (elem->align_left) if (elem->align_left)
out << std::left; out << std::left;
else else
@ -158,7 +158,7 @@ void format_t::format_elements(std::ostream& out,
switch (elem->type) { switch (elem->type) {
case element_t::STRING: case element_t::STRING:
out << elem->chars;; out << elem->chars;
break; break;
case element_t::VALUE_EXPR: { case element_t::VALUE_EXPR: {

View file

@ -49,13 +49,16 @@ struct element_t
struct format_t struct format_t
{ {
std::auto_ptr<element_t> elements; element_t * elements;
static std::auto_ptr<node_t> value_expr; static std::auto_ptr<node_t> value_expr;
static std::auto_ptr<node_t> total_expr; static std::auto_ptr<node_t> total_expr;
format_t(const std::string& _format) { format_t(const std::string& _format) {
elements.reset(parse_elements(_format)); elements = parse_elements(_format);
}
~format_t() {
if (elements) delete elements;
} }
static element_t * parse_elements(const std::string& fmt); static element_t * parse_elements(const std::string& fmt);

View file

@ -15,7 +15,7 @@ typedef std::pair<const std::string, account_t *> accounts_pair;
typedef std::map<account_t *, commodity_t *> account_comm_map; typedef std::map<account_t *, commodity_t *> account_comm_map;
typedef std::pair<account_t *, commodity_t *> account_comm_pair; typedef std::pair<account_t *, commodity_t *> account_comm_pair;
static ledger_t * curr_ledger; static journal_t * curr_journal;
static account_t * curr_account; static account_t * curr_account;
static commodity_t * curr_account_comm; static commodity_t * curr_account_comm;
static std::string curr_account_id; static std::string curr_account_id;
@ -107,7 +107,7 @@ static void endElement(void *userData, const char *name)
if (std::strcmp(name, "gnc:account") == 0) { if (std::strcmp(name, "gnc:account") == 0) {
assert(curr_account); assert(curr_account);
if (! curr_account->parent) if (! curr_account->parent)
curr_ledger->add_account(curr_account); curr_journal->add_account(curr_account);
accounts_by_id.insert(accounts_pair(curr_account_id, curr_account)); accounts_by_id.insert(accounts_pair(curr_account_id, curr_account));
curr_account = NULL; curr_account = NULL;
} }
@ -118,7 +118,7 @@ static void endElement(void *userData, const char *name)
} }
else if (std::strcmp(name, "gnc:transaction") == 0) { else if (std::strcmp(name, "gnc:transaction") == 0) {
assert(curr_entry); assert(curr_entry);
if (! curr_ledger->add_entry(curr_entry)) if (! curr_journal->add_entry(curr_entry))
assert(0); assert(0);
curr_entry = NULL; curr_entry = NULL;
} }
@ -256,13 +256,13 @@ static void dataHandler(void *userData, const char *s, int len)
} }
} }
int parse_gnucash(std::istream& in, ledger_t * ledger, account_t * master) int parse_gnucash(std::istream& in, journal_t * journal, account_t * master)
{ {
char buf[BUFSIZ]; char buf[BUFSIZ];
count = 0; count = 0;
action = NO_ACTION; action = NO_ACTION;
curr_ledger = ledger; curr_journal = journal;
curr_account = NULL; curr_account = NULL;
curr_entry = NULL; curr_entry = NULL;
curr_comm = NULL; curr_comm = NULL;

View file

@ -1,8 +1,6 @@
#include "ledger.h" #include "ledger.h"
#include "valexpr.h" #include "valexpr.h"
#include "datetime.h" #include "datetime.h"
#include "textual.h"
#include "binary.h"
#include <fstream> #include <fstream>
@ -10,30 +8,7 @@ namespace ledger {
const std::string version = "2.0b"; const std::string version = "2.0b";
#if 0 journal_t::~journal_t()
struct cmp_items {
const node_t * sort_order;
cmp_items(const node_t * _sort_order) : sort_order(_sort_order) {
assert(sort_order);
}
bool operator()(const item_t * left, const item_t * right) const {
assert(left);
assert(right);
return sort_order->compute(left) < sort_order->compute(right);
}
};
void item_t::sort(const node_t * sort_order)
{
std::stable_sort(subitems.begin(), subitems.end(), cmp_items(sort_order));
}
#endif
ledger_t::~ledger_t()
{ {
delete master; delete master;
@ -46,7 +21,7 @@ ledger_t::~ledger_t()
delete *i; delete *i;
} }
bool ledger_t::add_entry(entry_t * entry) bool journal_t::add_entry(entry_t * entry)
{ {
entries.push_back(entry); entries.push_back(entry);
@ -64,7 +39,7 @@ bool ledger_t::add_entry(entry_t * entry)
return true; return true;
} }
bool ledger_t::remove_entry(entry_t * entry) bool journal_t::remove_entry(entry_t * entry)
{ {
entries.remove(entry); entries.remove(entry);
@ -77,7 +52,7 @@ bool ledger_t::remove_entry(entry_t * entry)
return true; return true;
} }
entry_t * ledger_t::derive_entry(int argc, char **argv) const entry_t * journal_t::derive_entry(int argc, char **argv) const
{ {
entry_t * added = new entry_t; entry_t * added = new entry_t;
entry_t * matching = NULL; entry_t * matching = NULL;
@ -204,7 +179,7 @@ entry_t * ledger_t::derive_entry(int argc, char **argv) const
return added; return added;
} }
int parse_ledger_file(char * p, ledger_t * journal) int parse_journal_file(char * p, journal_t * journal)
{ {
char * sep = std::strrchr(p, '='); char * sep = std::strrchr(p, '=');
if (sep) *sep++ = '\0'; if (sep) *sep++ = '\0';
@ -225,9 +200,9 @@ int parse_ledger_file(char * p, ledger_t * journal)
stream.seekg(start); stream.seekg(start);
if (magic == binary_magic_number) if (magic == binary_magic_number)
return read_binary_ledger(stream, "", journal, master); return read_binary_journal(stream, "", journal, master);
else else
return parse_textual_ledger(stream, journal, master); return parse_textual_journal(stream, journal, master);
} }
} // namespace ledger } // namespace ledger

View file

@ -133,14 +133,14 @@ class account_t
return fullname(); return fullname();
} }
// These functions should only be called from ledger_t::add_entry // These functions should only be called from journal_t::add_entry
// and ledger_t::remove_entry; or from the various parsers. // and journal_t::remove_entry; or from the various parsers.
void add_transaction(transaction_t * xact) { void add_transaction(transaction_t * xact) {
transactions.push_back(xact); transactions.push_back(xact);
} }
bool remove_transaction(transaction_t * xact); bool remove_transaction(transaction_t * xact);
friend class ledger_t; friend class journal_t;
}; };
inline std::ostream& operator<<(std::ostream& out, const account_t& acct) { inline std::ostream& operator<<(std::ostream& out, const account_t& acct) {
@ -151,7 +151,7 @@ inline std::ostream& operator<<(std::ostream& out, const account_t& acct) {
typedef std::list<entry_t *> entries_list; typedef std::list<entry_t *> entries_list;
class ledger_t class journal_t
{ {
public: public:
account_t * master; account_t * master;
@ -159,13 +159,13 @@ class ledger_t
mutable accounts_map accounts_cache; mutable accounts_map accounts_cache;
std::list<std::string> sources; std::list<std::string> sources;
ledger_t() { journal_t() {
master = new account_t(NULL, ""); master = new account_t(NULL, "");
master->ident = 0; master->ident = 0;
account_t::next_ident = 1; account_t::next_ident = 1;
} }
~ledger_t(); ~journal_t();
void add_account(account_t * acct) { void add_account(account_t * acct) {
master->add_account(acct); master->add_account(acct);
@ -186,7 +186,7 @@ class ledger_t
account_t * find_account(const std::string& name) const { account_t * find_account(const std::string& name) const {
// With auto_create false, the other `find_account' will not // With auto_create false, the other `find_account' will not
// change the object. // change the object.
return const_cast<ledger_t *>(this)->find_account(name, false); return const_cast<journal_t *>(this)->find_account(name, false);
} }
bool add_entry(entry_t * entry); bool add_entry(entry_t * entry);
@ -195,7 +195,21 @@ class ledger_t
entry_t * derive_entry(int argc, char **argv) const; entry_t * derive_entry(int argc, char **argv) const;
}; };
int parse_ledger_file(char * p, ledger_t * journal); int parse_journal_file(char * p, journal_t * journal);
unsigned int parse_textual_journal(std::istream& in, journal_t * ledger,
account_t * master = NULL);
extern unsigned long binary_magic_number;
unsigned int read_binary_journal(std::istream& in,
const std::string& leader,
journal_t * journal,
account_t * master = NULL);
void write_binary_journal(std::ostream& out,
journal_t * journal,
const std::string& leader);
extern const std::string version; extern const std::string version;

125
main.cc
View file

@ -1,7 +1,5 @@
#include "ledger.h" #include "ledger.h"
#include "error.h" #include "error.h"
#include "textual.h"
#include "binary.h"
#include "valexpr.h" #include "valexpr.h"
#include "format.h" #include "format.h"
#include "walk.h" #include "walk.h"
@ -350,11 +348,13 @@ static void show_help(std::ostream& out)
int main(int argc, char * argv[]) int main(int argc, char * argv[])
{ {
std::auto_ptr<ledger::ledger_t> journal(new ledger::ledger_t); using namespace ledger;
std::list<std::string> files;
std::auto_ptr<ledger::node_t> predicate; std::auto_ptr<journal_t> journal(new journal_t);
std::auto_ptr<ledger::node_t> display_predicate; std::list<std::string> files;
std::auto_ptr<ledger::node_t> sort_order; std::auto_ptr<node_t> predicate;
std::auto_ptr<node_t> display_predicate;
std::auto_ptr<node_t> sort_order;
std::string predicate_string; std::string predicate_string;
std::string display_predicate_string; std::string display_predicate_string;
@ -376,10 +376,10 @@ int main(int argc, char * argv[])
// Initialize some variables based on environment variable settings // Initialize some variables based on environment variable settings
if (char * p = std::getenv("PRICE_HIST")) if (char * p = std::getenv("PRICE_HIST"))
ledger::price_db = p; price_db = p;
if (char * p = std::getenv("PRICE_EXP")) if (char * p = std::getenv("PRICE_EXP"))
ledger::pricing_leeway = std::atol(p) * 60; pricing_leeway = std::atol(p) * 60;
// A ledger data file must be specified // A ledger data file must be specified
@ -392,18 +392,18 @@ int main(int argc, char * argv[])
break; break;
} }
ledger::cache_dirty = true; cache_dirty = true;
if (use_cache) if (use_cache)
if (const char * p = std::getenv("LEDGER_CACHE")) if (const char * p = std::getenv("LEDGER_CACHE"))
if (access(p, R_OK) != -1) { if (access(p, R_OK) != -1) {
std::ifstream instr(p); std::ifstream instr(p);
if (! ledger::read_binary_ledger(instr, std::getenv("LEDGER"), if (! read_binary_journal(instr, std::getenv("LEDGER"),
journal.get())) { journal.get())) {
// Throw away what's been read, and create a new journal // Throw away what's been read, and create a new journal
journal.reset(new ledger::ledger_t); journal.reset(new journal_t);
} else { } else {
ledger::cache_dirty = false; cache_dirty = false;
} }
} }
} }
@ -428,7 +428,7 @@ int main(int argc, char * argv[])
case 'v': case 'v':
std::cout std::cout
<< "Ledger " << ledger::version << "Ledger " << version
<< ", the command-line accounting tool" << std::endl << ", the command-line accounting tool" << std::endl
<< " Copyright (c) 2003-2004, New Artisans LLC. All rights reserved." << " Copyright (c) 2003-2004, New Artisans LLC. All rights reserved."
<< std::endl << std::endl << std::endl << std::endl
@ -445,7 +445,7 @@ int main(int argc, char * argv[])
break; break;
case 'p': case 'p':
ledger::set_price_conversion(optarg); set_price_conversion(optarg);
break; break;
case 'b': case 'b':
@ -536,15 +536,15 @@ int main(int argc, char * argv[])
// Commodity reporting // Commodity reporting
case 'P': case 'P':
ledger::price_db = optarg; price_db = optarg;
break; break;
case 'L': case 'L':
ledger::pricing_leeway = std::atol(optarg) * 60; pricing_leeway = std::atol(optarg) * 60;
break; break;
case 'Q': case 'Q':
ledger::commodity_t::updater = ledger::download_price_quote; commodity_t::updater = download_price_quote;
break; break;
case 't': case 't':
@ -566,15 +566,15 @@ int main(int argc, char * argv[])
break; break;
case 'V': case 'V':
ledger::show_commodities_revalued = true; show_commodities_revalued = true;
value_expr = "v"; value_expr = "v";
total_expr = "V"; total_expr = "V";
break; break;
case 'G': case 'G':
ledger::show_commodities_revalued = show_commodities_revalued =
ledger::show_commodities_revalued_only = true; show_commodities_revalued_only = true;
value_expr = "c"; value_expr = "c";
total_expr = "G"; total_expr = "G";
@ -622,36 +622,36 @@ int main(int argc, char * argv[])
// Read the ledger file, unless we already read it from the cache // Read the ledger file, unless we already read it from the cache
if (! use_cache || ledger::cache_dirty) { if (! use_cache || cache_dirty) {
int entry_count = 0; int entry_count = 0;
try { try {
if (files.empty()) { if (files.empty()) {
if (char * p = std::getenv("LEDGER")) if (char * p = std::getenv("LEDGER"))
for (p = std::strtok(p, ":"); p; p = std::strtok(NULL, ":")) for (p = std::strtok(p, ":"); p; p = std::strtok(NULL, ":"))
entry_count += parse_ledger_file(p, journal.get()); entry_count += parse_journal_file(p, journal.get());
} else { } else {
for (std::list<std::string>::iterator i = files.begin(); for (std::list<std::string>::iterator i = files.begin();
i != files.end(); i++) { i != files.end(); i++) {
char buf[4096]; char buf[4096];
char * p = buf; char * p = buf;
std::strcpy(p, (*i).c_str()); std::strcpy(p, (*i).c_str());
entry_count += parse_ledger_file(p, journal.get()); entry_count += parse_journal_file(p, journal.get());
} }
} }
// Read prices from their own ledger file, after all others have // Read prices from their own ledger file, after all others have
// been read. // been read.
if (! ledger::price_db.empty()) { if (! price_db.empty()) {
const char * path = ledger::price_db.c_str(); const char * path = price_db.c_str();
std::ifstream db(path); std::ifstream db(path);
journal->sources.push_back(path); journal->sources.push_back(path);
entry_count += ledger::parse_textual_ledger(db, journal.get(), entry_count += parse_textual_journal(db, journal.get(),
journal->master); journal->master);
} }
} }
catch (ledger::error& err) { catch (error& err) {
std::cerr << "Fatal: " << err.what() << std::endl; std::cerr << "Fatal: " << err.what() << std::endl;
return 1; return 1;
} }
@ -685,7 +685,7 @@ int main(int argc, char * argv[])
// Process the remaining command-line arguments // Process the remaining command-line arguments
std::auto_ptr<ledger::entry_t> new_entry; std::auto_ptr<entry_t> new_entry;
if (command == "entry") { if (command == "entry") {
new_entry.reset(journal->derive_entry(argc - index, &argv[index])); new_entry.reset(journal->derive_entry(argc - index, &argv[index]));
} else { } else {
@ -770,7 +770,7 @@ int main(int argc, char * argv[])
if (debug) if (debug)
std::cerr << "predicate = " << predicate_string << std::endl; std::cerr << "predicate = " << predicate_string << std::endl;
#endif #endif
predicate.reset(ledger::parse_expr(predicate_string)); predicate.reset(parse_expr(predicate_string));
} }
if (display_predicate_string.empty() && command == "b" && ! show_empty) if (display_predicate_string.empty() && command == "b" && ! show_empty)
@ -782,18 +782,18 @@ int main(int argc, char * argv[])
std::cerr << "display predicate = " << display_predicate_string std::cerr << "display predicate = " << display_predicate_string
<< std::endl; << std::endl;
#endif #endif
display_predicate.reset(ledger::parse_expr(display_predicate_string)); display_predicate.reset(parse_expr(display_predicate_string));
} }
// Compile the sorting string // Compile the sorting string
if (! sort_string.empty()) if (! sort_string.empty())
sort_order.reset(ledger::parse_expr(sort_string)); sort_order.reset(parse_expr(sort_string));
// Setup the meaning of %t and %T encountered in format strings // Setup the meaning of %t and %T encountered in format strings
ledger::format_t::value_expr.reset(ledger::parse_expr(value_expr)); format_t::value_expr.reset(parse_expr(value_expr));
ledger::format_t::total_expr.reset(ledger::parse_expr(total_expr)); format_t::total_expr.reset(parse_expr(total_expr));
// Now handle the command that was identified above. // Now handle the command that was identified above.
@ -812,26 +812,24 @@ int main(int argc, char * argv[])
if (! format_string.empty()) if (! format_string.empty())
f = format_string.c_str(); f = format_string.c_str();
else if (command == "b") else if (command == "b")
f = ledger::bal_fmt.c_str(); f = bal_fmt.c_str();
else if (command == "r") else if (command == "r")
f = ledger::reg_fmt.c_str(); f = reg_fmt.c_str();
else else
f = ledger::print_fmt.c_str(); f = print_fmt.c_str();
if (command == "b") { if (command == "b") {
std::auto_ptr<ledger::format_t> format(new ledger::format_t(f)); format_t format(f);
walk_accounts(journal->master, format_account(std::cout, format),
ledger::walk_accounts(journal->master, predicate.get(), show_related, show_inverted,
ledger::format_account(std::cout, *format.get()), show_subtotals, display_predicate.get());
predicate.get(), show_related, show_inverted,
show_subtotals, display_predicate.get());
if (! display_predicate.get() || if (! display_predicate.get() ||
ledger::item_predicate(display_predicate.get())(journal->master)) { item_predicate(display_predicate.get())(journal->master)) {
std::string end_format = "--------------------\n"; std::string end_format = "--------------------\n";
end_format += f; end_format += f;
format.get()->elements.reset(ledger::format_t::parse_elements(end_format)); format.elements = format_t::parse_elements(end_format);
ledger::format_account(std::cout, *format.get())(journal->master, true); format_account(std::cout, format)(journal->master, true);
} }
} else { } else {
std::string first_line_format; std::string first_line_format;
@ -844,27 +842,34 @@ int main(int argc, char * argv[])
first_line_format = next_lines_format = f; first_line_format = next_lines_format = f;
} }
std::auto_ptr<ledger::format_t> format_t format(first_line_format);
format(new ledger::format_t(first_line_format)); format_t nformat(next_lines_format);
std::auto_ptr<ledger::format_t> format_transaction formatter(std::cout, format, nformat);
nformat(new ledger::format_t(next_lines_format));
ledger::walk_entries(journal->entries.begin(), journal->entries.end(), if (! sort_order.get()) {
ledger::format_transaction(std::cout, walk_entries(journal->entries.begin(), journal->entries.end(),
first_line_format, formatter, predicate.get(), show_related, show_inverted,
next_lines_format), display_predicate.get());
predicate.get(), show_related, show_inverted, } else {
display_predicate.get()); transactions_deque transactions_pool;
walk_entries(journal->entries.begin(), journal->entries.end(),
collect_transactions(transactions_pool), predicate.get(),
show_related, show_inverted, display_predicate.get());
std::stable_sort(transactions_pool.begin(), transactions_pool.end(),
compare_transactions(sort_order.get()));
walk_transactions(transactions_pool.begin(), transactions_pool.end(),
formatter, NULL, show_related, show_inverted,
display_predicate.get());
}
} }
// Save the cache, if need be // Save the cache, if need be
if (use_cache && ledger::cache_dirty) if (use_cache && cache_dirty)
if (const char * p = std::getenv("LEDGER_CACHE")) { if (const char * p = std::getenv("LEDGER_CACHE")) {
std::ofstream outstr(p); std::ofstream outstr(p);
assert(std::getenv("LEDGER")); assert(std::getenv("LEDGER"));
ledger::write_binary_ledger(outstr, journal.get(), write_binary_journal(outstr, journal.get(), std::getenv("LEDGER"));
std::getenv("LEDGER"));
} }
return 0; return 0;

View file

@ -1,4 +1,3 @@
#include "textual.h"
#include "datetime.h" #include "datetime.h"
#include "autoxact.h" #include "autoxact.h"
#include "valexpr.h" #include "valexpr.h"
@ -287,8 +286,8 @@ entry_t * parse_entry(std::istream& in, account_t * master)
return curr; return curr;
} }
unsigned int parse_textual_ledger(std::istream& in, ledger_t * journal, unsigned int parse_textual_journal(std::istream& in, journal_t * journal,
account_t * master) account_t * master)
{ {
static char line[MAX_LINE + 1]; static char line[MAX_LINE + 1];
char c; char c;
@ -518,8 +517,8 @@ unsigned int parse_textual_ledger(std::istream& in, ledger_t * journal,
unsigned int curr_linenum = linenum; unsigned int curr_linenum = linenum;
std::string curr_path = path; std::string curr_path = path;
count += parse_textual_ledger(stream, journal, count += parse_textual_journal(stream, journal,
account_stack.front()); account_stack.front());
linenum = curr_linenum; linenum = curr_linenum;
path = curr_path; path = curr_path;

View file

@ -1,13 +0,0 @@
#ifndef _TEXTUAL_H
#define _TEXTUAL_H
#include "ledger.h"
namespace ledger {
extern unsigned int parse_textual_ledger(std::istream& in, ledger_t * ledger,
account_t * master = NULL);
} // namespace ledger
#endif // _TEXTUAL_H

View file

@ -1,7 +1,6 @@
#include "valexpr.h" #include "valexpr.h"
#include "error.h" #include "error.h"
#include "datetime.h" #include "datetime.h"
#include "textual.h"
#include <pcre.h> #include <pcre.h>

73
walk.h
View file

@ -7,6 +7,7 @@
#include "valexpr.h" #include "valexpr.h"
#include <iostream> #include <iostream>
#include <deque>
namespace ledger { namespace ledger {
@ -84,7 +85,45 @@ class format_transaction
void operator()(transaction_t * xact, void operator()(transaction_t * xact,
balance_pair_t * balance, balance_pair_t * balance,
unsigned int * index, unsigned int * index,
const bool inverted) const; const bool inverted) const;
};
struct compare_transactions {
const node_t * sort_order;
compare_transactions(const node_t * _sort_order)
: sort_order(_sort_order) {
assert(sort_order);
}
bool operator()(const transaction_t * left,
const transaction_t * right) const {
assert(left);
assert(right);
balance_t left_result;
sort_order->compute(left_result, details_t(left));
balance_t right_result;
sort_order->compute(right_result, details_t(right));
return left_result < right_result;
}
};
typedef std::deque<transaction_t *> transactions_deque;
class collect_transactions
{
transactions_deque& transactions;
public:
collect_transactions(transactions_deque& _transactions)
: transactions(_transactions) {}
void operator()(transaction_t * xact,
balance_pair_t * balance,
unsigned int * index,
const bool inverted) {
transactions.push_back(xact);
}
}; };
class ignore_transaction class ignore_transaction
@ -153,6 +192,38 @@ void walk_entries(entries_list::iterator begin,
related, inverted, &balance, &index); related, inverted, &balance, &index);
} }
template <typename Function>
void walk_transactions(transactions_list::iterator begin,
transactions_list::iterator end,
Function functor,
const node_t * predicate,
const bool related,
const bool inverted,
const node_t * display_predicate = NULL)
{
balance_pair_t balance;
unsigned int index;
for (transactions_list::iterator i = begin; i != end; i++)
functor(*i, &balance, &index, inverted);
}
template <typename Function>
void walk_transactions(transactions_deque::iterator begin,
transactions_deque::iterator end,
Function functor,
const node_t * predicate,
const bool related,
const bool inverted,
const node_t * display_predicate = NULL)
{
balance_pair_t balance;
unsigned int index;
for (transactions_deque::iterator i = begin; i != end; i++)
functor(*i, &balance, &index, inverted);
}
class format_account class format_account
{ {
std::ostream& output_stream; std::ostream& output_stream;