many more formatting changes
This commit is contained in:
parent
a999372bef
commit
a77c20a772
7 changed files with 430 additions and 432 deletions
|
|
@ -33,8 +33,8 @@ std::string partial_account_name(const account_t * account)
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::auto_ptr<node_t> format_t::value_expr;
|
std::auto_ptr<value_expr_t> format_t::value_expr;
|
||||||
std::auto_ptr<node_t> format_t::total_expr;
|
std::auto_ptr<value_expr_t> format_t::total_expr;
|
||||||
|
|
||||||
element_t * format_t::parse_elements(const std::string& fmt)
|
element_t * format_t::parse_elements(const std::string& fmt)
|
||||||
{
|
{
|
||||||
|
|
@ -99,7 +99,7 @@ element_t * format_t::parse_elements(const std::string& fmt)
|
||||||
throw format_error("Missing ')'");
|
throw format_error("Missing ')'");
|
||||||
|
|
||||||
current->type = element_t::VALUE_EXPR;
|
current->type = element_t::VALUE_EXPR;
|
||||||
current->val_expr = parse_expr(num);
|
current->val_expr = parse_value_expr(num);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '[':
|
case '[':
|
||||||
|
|
|
||||||
29
format.h
29
format.h
|
|
@ -29,13 +29,13 @@ struct element_t
|
||||||
SPACER
|
SPACER
|
||||||
};
|
};
|
||||||
|
|
||||||
bool align_left;
|
bool align_left;
|
||||||
unsigned int min_width;
|
unsigned int min_width;
|
||||||
unsigned int max_width;
|
unsigned int max_width;
|
||||||
|
|
||||||
kind_t type;
|
kind_t type;
|
||||||
std::string chars;
|
std::string chars;
|
||||||
node_t * val_expr;
|
value_expr_t * val_expr;
|
||||||
|
|
||||||
struct element_t * next;
|
struct element_t * next;
|
||||||
|
|
||||||
|
|
@ -52,8 +52,8 @@ struct format_t
|
||||||
{
|
{
|
||||||
element_t * elements;
|
element_t * elements;
|
||||||
|
|
||||||
static std::auto_ptr<node_t> value_expr;
|
static std::auto_ptr<value_expr_t> value_expr;
|
||||||
static std::auto_ptr<node_t> total_expr;
|
static std::auto_ptr<value_expr_t> total_expr;
|
||||||
|
|
||||||
format_t(const std::string& _format) : elements(NULL) {
|
format_t(const std::string& _format) : elements(NULL) {
|
||||||
reset(_format);
|
reset(_format);
|
||||||
|
|
@ -107,17 +107,14 @@ class format_transactions : public item_handler<transaction_t>
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void operator()(transaction_t * xact) {
|
virtual void operator()(transaction_t * xact) {
|
||||||
xact->dflags |= TRANSACTION_DISPLAYED;
|
if (last_entry != xact->entry) {
|
||||||
|
|
||||||
// This makes the assumption that transactions from a single entry
|
|
||||||
// are always grouped together.
|
|
||||||
|
|
||||||
if (last_entry != xact->entry)
|
|
||||||
first_line_format.format_elements(output_stream, details_t(xact));
|
first_line_format.format_elements(output_stream, details_t(xact));
|
||||||
else
|
last_entry = xact->entry;
|
||||||
|
} else {
|
||||||
next_lines_format.format_elements(output_stream, details_t(xact));
|
next_lines_format.format_elements(output_stream, details_t(xact));
|
||||||
|
}
|
||||||
|
|
||||||
last_entry = xact->entry;
|
xact->dflags |= TRANSACTION_DISPLAYED;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
72
main.cc
72
main.cc
|
|
@ -159,7 +159,7 @@ int main(int argc, char * argv[])
|
||||||
|
|
||||||
std::auto_ptr<journal_t> journal(new journal_t);
|
std::auto_ptr<journal_t> journal(new journal_t);
|
||||||
std::list<std::string> files;
|
std::list<std::string> files;
|
||||||
std::auto_ptr<node_t> sort_order;
|
std::auto_ptr<value_expr_t> sort_order;
|
||||||
|
|
||||||
std::string predicate;
|
std::string predicate;
|
||||||
std::string display_predicate;
|
std::string display_predicate;
|
||||||
|
|
@ -538,31 +538,29 @@ int main(int argc, char * argv[])
|
||||||
// Compile the sorting string
|
// Compile the sorting string
|
||||||
|
|
||||||
if (! sort_string.empty())
|
if (! sort_string.empty())
|
||||||
sort_order.reset(parse_expr(sort_string));
|
sort_order.reset(parse_value_expr(sort_string));
|
||||||
|
|
||||||
// Setup the meaning of %t and %T, used in format strings
|
// Setup the meaning of %t and %T, used in format strings
|
||||||
|
|
||||||
format_t::value_expr.reset(parse_expr(value_expr));
|
format_t::value_expr.reset(parse_value_expr(value_expr));
|
||||||
format_t::total_expr.reset(parse_expr(total_expr));
|
format_t::total_expr.reset(parse_value_expr(total_expr));
|
||||||
|
|
||||||
// Now handle the command that was identified above.
|
// Now handle the command that was identified above.
|
||||||
|
|
||||||
unsigned int xact_display_flags = MATCHING_TRANSACTIONS;
|
bool show_all_related = false;
|
||||||
|
|
||||||
if (command == "p" || command == "e") {
|
if (command == "p" || command == "e") {
|
||||||
xact_display_flags |= OTHER_TRANSACTIONS;
|
show_related = show_all_related = true;
|
||||||
show_expanded = true;
|
show_expanded = true;
|
||||||
}
|
}
|
||||||
else if (command == "E") {
|
else if (command == "E") {
|
||||||
show_expanded = true;
|
show_expanded = true;
|
||||||
}
|
}
|
||||||
else if (show_related) {
|
else if (show_related) {
|
||||||
if (command == "r") {
|
if (command == "r")
|
||||||
xact_display_flags = OTHER_TRANSACTIONS;
|
|
||||||
show_inverted = true;
|
show_inverted = true;
|
||||||
} else {
|
else
|
||||||
xact_display_flags |= OTHER_TRANSACTIONS;
|
show_all_related = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * f;
|
const char * f;
|
||||||
|
|
@ -591,9 +589,21 @@ int main(int argc, char * argv[])
|
||||||
format_t nformat(next_lines_format);
|
format_t nformat(next_lines_format);
|
||||||
|
|
||||||
if (command == "b") {
|
if (command == "b") {
|
||||||
format_account formatter(std::cout, format, display_predicate);
|
std::auto_ptr<item_handler<transaction_t> > formatter;
|
||||||
walk_accounts(journal->master, formatter, predicate,
|
|
||||||
xact_display_flags, show_subtotals, sort_order.get());
|
formatter.reset(new add_to_account_value);
|
||||||
|
if (show_related)
|
||||||
|
formatter.reset(new related_transactions(formatter.release(),
|
||||||
|
show_all_related));
|
||||||
|
formatter.reset(new filter_transactions(formatter.release(),
|
||||||
|
predicate));
|
||||||
|
|
||||||
|
walk_entries(journal->entries, *formatter.get());
|
||||||
|
|
||||||
|
format_account acct_formatter(std::cout, format, display_predicate);
|
||||||
|
|
||||||
|
walk_accounts(journal->master, acct_formatter, show_subtotals,
|
||||||
|
sort_order.get());
|
||||||
|
|
||||||
if (format_account::disp_subaccounts_p(journal->master)) {
|
if (format_account::disp_subaccounts_p(journal->master)) {
|
||||||
std::string end_format = "--------------------\n";
|
std::string end_format = "--------------------\n";
|
||||||
|
|
@ -602,17 +612,16 @@ int main(int argc, char * argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (command == "E") {
|
else if (command == "E") {
|
||||||
format_equity formatter(std::cout, format, nformat, display_predicate);
|
add_to_account_value formatter;
|
||||||
walk_accounts(journal->master, formatter, predicate,
|
walk_entries(journal->entries, formatter);
|
||||||
xact_display_flags, true, sort_order.get());
|
|
||||||
|
format_equity acct_formatter(std::cout, format, nformat,
|
||||||
|
display_predicate);
|
||||||
|
walk_accounts(journal->master, acct_formatter, true, sort_order.get());
|
||||||
}
|
}
|
||||||
else if (command == "e") {
|
else if (command == "e") {
|
||||||
format_transactions formatter(std::cout, format, nformat);
|
format_transactions formatter(std::cout, format, nformat);
|
||||||
|
walk_transactions(new_entry->transactions, formatter);
|
||||||
for (transactions_list::iterator i = new_entry->transactions.begin();
|
|
||||||
i != new_entry->transactions.end();
|
|
||||||
i++)
|
|
||||||
handle_transaction(*i, formatter, xact_display_flags);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
std::auto_ptr<item_handler<transaction_t> > formatter;
|
std::auto_ptr<item_handler<transaction_t> > formatter;
|
||||||
|
|
@ -667,10 +676,23 @@ int main(int argc, char * argv[])
|
||||||
formatter.reset(new interval_transactions(formatter.release(), 0,
|
formatter.reset(new interval_transactions(formatter.release(), 0,
|
||||||
interval_t(9676800, 0, 0)));
|
interval_t(9676800, 0, 0)));
|
||||||
|
|
||||||
|
// related_transactions will pass along all transactions related
|
||||||
|
// to the transaction received. If `show_all_related' is true,
|
||||||
|
// then all the entry's transactions are passed; meaning that if
|
||||||
|
// one transaction of an entry is to be printed, all the
|
||||||
|
// transaction for that entry will be printed.
|
||||||
|
if (show_related)
|
||||||
|
formatter.reset(new related_transactions(formatter.release(),
|
||||||
|
show_all_related));
|
||||||
|
|
||||||
|
// This filter_transactions will only pass through transactions
|
||||||
|
// matching the `predicate'.
|
||||||
|
formatter.reset(new filter_transactions(formatter.release(), predicate));
|
||||||
|
|
||||||
// Once the filters are chained, walk `journal's entries and start
|
// Once the filters are chained, walk `journal's entries and start
|
||||||
// feeding each transaction that matches `predicate' to the chain.
|
// feeding each transaction that matches `predicate' to the chain.
|
||||||
walk_entries(journal->entries.begin(), journal->entries.end(),
|
walk_entries(journal->entries.begin(), journal->entries.end(),
|
||||||
*formatter.get(), predicate, xact_display_flags);
|
*formatter.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the cache, if need be
|
// Save the cache, if need be
|
||||||
|
|
@ -679,10 +701,6 @@ int main(int argc, char * argv[])
|
||||||
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"));
|
||||||
#if 0
|
|
||||||
clear_transaction_display_flags(journal->entries.begin(),
|
|
||||||
journal->entries.end());
|
|
||||||
#endif
|
|
||||||
write_binary_journal(outstr, journal.get(), std::getenv("LEDGER"));
|
write_binary_journal(outstr, journal.get(), std::getenv("LEDGER"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
305
valexpr.cc
305
valexpr.cc
|
|
@ -56,45 +56,8 @@ mask_t::~mask_t() {
|
||||||
pcre_free((pcre *)regexp);
|
pcre_free((pcre *)regexp);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
|
||||||
|
|
||||||
bool matches(const masks_list& regexps, const std::string& str,
|
void value_expr_t::compute(balance_t& result, const details_t& details) const
|
||||||
bool * by_exclusion)
|
|
||||||
{
|
|
||||||
if (regexps.empty())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
bool match = false;
|
|
||||||
bool definite = false;
|
|
||||||
|
|
||||||
for (masks_list::const_iterator r = regexps.begin();
|
|
||||||
r != regexps.end();
|
|
||||||
r++) {
|
|
||||||
static int ovec[30];
|
|
||||||
int result = pcre_exec((pcre *)(*r).regexp, NULL,
|
|
||||||
str.c_str(), str.length(), 0, 0, ovec, 30);
|
|
||||||
if (result >= 0) {
|
|
||||||
match = ! (*r).exclude;
|
|
||||||
definite = true;
|
|
||||||
}
|
|
||||||
else if ((*r).exclude) {
|
|
||||||
if (! match)
|
|
||||||
match = ! definite;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
definite = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (by_exclusion)
|
|
||||||
*by_exclusion = match && ! definite && by_exclusion;
|
|
||||||
|
|
||||||
return match;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void node_t::compute(balance_t& result, const details_t& details) const
|
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case CONSTANT_A:
|
case CONSTANT_A:
|
||||||
|
|
@ -351,16 +314,16 @@ inline char peek_next_nonws(std::istream& in)
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
node_t * parse_term(std::istream& in);
|
value_expr_t * parse_value_term(std::istream& in);
|
||||||
|
|
||||||
inline node_t * parse_term(const char * p) {
|
inline value_expr_t * parse_value_term(const char * p) {
|
||||||
std::istringstream stream(p);
|
std::istringstream stream(p);
|
||||||
return parse_term(stream);
|
return parse_value_term(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
node_t * parse_term(std::istream& in)
|
value_expr_t * parse_value_term(std::istream& in)
|
||||||
{
|
{
|
||||||
node_t * node = NULL;
|
value_expr_t * node = NULL;
|
||||||
|
|
||||||
char c = peek_next_nonws(in);
|
char c = peek_next_nonws(in);
|
||||||
if (std::isdigit(c) || c == '.' || c == '{') {
|
if (std::isdigit(c) || c == '.' || c == '{') {
|
||||||
|
|
@ -387,7 +350,7 @@ node_t * parse_term(std::istream& in)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! ident.empty()) {
|
if (! ident.empty()) {
|
||||||
node = new node_t(node_t::CONSTANT_A);
|
node = new value_expr_t(value_expr_t::CONSTANT_A);
|
||||||
node->constant_a.parse(ident);
|
node->constant_a.parse(ident);
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
|
|
@ -396,62 +359,62 @@ node_t * parse_term(std::istream& in)
|
||||||
in.get(c);
|
in.get(c);
|
||||||
switch (c) {
|
switch (c) {
|
||||||
// Basic terms
|
// Basic terms
|
||||||
case 'a': node = new node_t(node_t::AMOUNT); break;
|
case 'a': node = new value_expr_t(value_expr_t::AMOUNT); break;
|
||||||
case 'c': node = new node_t(node_t::COST); break;
|
case 'c': node = new value_expr_t(value_expr_t::COST); break;
|
||||||
case 'd': node = new node_t(node_t::DATE); break;
|
case 'd': node = new value_expr_t(value_expr_t::DATE); break;
|
||||||
case 'X': node = new node_t(node_t::CLEARED); break;
|
case 'X': node = new value_expr_t(value_expr_t::CLEARED); break;
|
||||||
case 'R': node = new node_t(node_t::REAL); break;
|
case 'R': node = new value_expr_t(value_expr_t::REAL); break;
|
||||||
case 'n': node = new node_t(node_t::INDEX); break;
|
case 'n': node = new value_expr_t(value_expr_t::INDEX); break;
|
||||||
case 'B': node = new node_t(node_t::BALANCE); break;
|
case 'B': node = new value_expr_t(value_expr_t::BALANCE); break;
|
||||||
case 'T': node = new node_t(node_t::TOTAL); break;
|
case 'T': node = new value_expr_t(value_expr_t::TOTAL); break;
|
||||||
case 'C': node = new node_t(node_t::COST_TOTAL); break;
|
case 'C': node = new value_expr_t(value_expr_t::COST_TOTAL); break;
|
||||||
|
|
||||||
// Compound terms
|
// Compound terms
|
||||||
case 'v': node = parse_expr("P(a,d)"); break;
|
case 'v': node = parse_value_expr("P(a,d)"); break;
|
||||||
case 'V': node = parse_term("P(T,d)"); break;
|
case 'V': node = parse_value_term("P(T,d)"); break;
|
||||||
case 'g': node = parse_expr("v-c"); break;
|
case 'g': node = parse_value_expr("v-c"); break;
|
||||||
case 'G': node = parse_expr("V-C"); break;
|
case 'G': node = parse_value_expr("V-C"); break;
|
||||||
case 'o': node = parse_expr("d-b"); break;
|
case 'o': node = parse_value_expr("d-b"); break;
|
||||||
case 'w': node = parse_expr("e-d"); break;
|
case 'w': node = parse_value_expr("e-d"); break;
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
case '-':
|
case '-':
|
||||||
node = new node_t(node_t::F_NEG);
|
node = new value_expr_t(value_expr_t::F_NEG);
|
||||||
node->left = parse_term(in);
|
node->left = parse_value_term(in);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'A':
|
case 'A':
|
||||||
node = new node_t(node_t::F_ABS);
|
node = new value_expr_t(value_expr_t::F_ABS);
|
||||||
node->left = parse_term(in);
|
node->left = parse_value_term(in);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'M':
|
case 'M':
|
||||||
node = new node_t(node_t::F_ARITH_MEAN);
|
node = new value_expr_t(value_expr_t::F_ARITH_MEAN);
|
||||||
node->left = parse_term(in);
|
node->left = parse_value_term(in);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'D': {
|
case 'D': {
|
||||||
node = new node_t(node_t::O_SUB);
|
node = new value_expr_t(value_expr_t::O_SUB);
|
||||||
node->left = parse_term("a");
|
node->left = parse_value_term("a");
|
||||||
node->right = parse_term(in);
|
node->right = parse_value_term(in);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'P':
|
case 'P':
|
||||||
node = new node_t(node_t::F_VALUE);
|
node = new value_expr_t(value_expr_t::F_VALUE);
|
||||||
if (peek_next_nonws(in) == '(') {
|
if (peek_next_nonws(in) == '(') {
|
||||||
in.get(c);
|
in.get(c);
|
||||||
node->left = parse_expr(in);
|
node->left = parse_value_expr(in);
|
||||||
if (peek_next_nonws(in) == ',') {
|
if (peek_next_nonws(in) == ',') {
|
||||||
in.get(c);
|
in.get(c);
|
||||||
node->right = parse_expr(in);
|
node->right = parse_value_expr(in);
|
||||||
}
|
}
|
||||||
if (peek_next_nonws(in) == ')')
|
if (peek_next_nonws(in) == ')')
|
||||||
in.get(c);
|
in.get(c);
|
||||||
else
|
else
|
||||||
throw expr_error("Missing ')'");
|
throw expr_error("Missing ')'");
|
||||||
} else {
|
} else {
|
||||||
node->left = parse_term(in);
|
node->left = parse_value_term(in);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -477,8 +440,8 @@ node_t * parse_term(std::istream& in)
|
||||||
|
|
||||||
if (c == '/') {
|
if (c == '/') {
|
||||||
in.get(c);
|
in.get(c);
|
||||||
node = new node_t(payee_mask ?
|
node = new value_expr_t(payee_mask ?
|
||||||
node_t::F_PAYEE_MASK : node_t::F_ACCOUNT_MASK);
|
value_expr_t::F_PAYEE_MASK : value_expr_t::F_ACCOUNT_MASK);
|
||||||
node->mask = new mask_t(ident);
|
node->mask = new mask_t(ident);
|
||||||
} else {
|
} else {
|
||||||
throw expr_error("Missing closing '/'");
|
throw expr_error("Missing closing '/'");
|
||||||
|
|
@ -487,7 +450,7 @@ node_t * parse_term(std::istream& in)
|
||||||
}
|
}
|
||||||
|
|
||||||
case '(':
|
case '(':
|
||||||
node = parse_expr(in);
|
node = parse_value_expr(in);
|
||||||
if (peek_next_nonws(in) == ')')
|
if (peek_next_nonws(in) == ')')
|
||||||
in.get(c);
|
in.get(c);
|
||||||
else
|
else
|
||||||
|
|
@ -505,7 +468,7 @@ node_t * parse_term(std::istream& in)
|
||||||
}
|
}
|
||||||
if (c == ']') {
|
if (c == ']') {
|
||||||
in.get(c);
|
in.get(c);
|
||||||
node = new node_t(node_t::CONSTANT_T);
|
node = new value_expr_t(value_expr_t::CONSTANT_T);
|
||||||
if (! parse_date(ident.c_str(), &node->constant_t))
|
if (! parse_date(ident.c_str(), &node->constant_t))
|
||||||
throw expr_error("Failed to parse date");
|
throw expr_error("Failed to parse date");
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -522,11 +485,11 @@ node_t * parse_term(std::istream& in)
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
node_t * parse_mul_expr(std::istream& in)
|
value_expr_t * parse_mul_expr(std::istream& in)
|
||||||
{
|
{
|
||||||
node_t * node = NULL;
|
value_expr_t * node = NULL;
|
||||||
|
|
||||||
node = parse_term(in);
|
node = parse_value_term(in);
|
||||||
|
|
||||||
if (node && ! in.eof()) {
|
if (node && ! in.eof()) {
|
||||||
char c = peek_next_nonws(in);
|
char c = peek_next_nonws(in);
|
||||||
|
|
@ -534,18 +497,18 @@ node_t * parse_mul_expr(std::istream& in)
|
||||||
in.get(c);
|
in.get(c);
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '*': {
|
case '*': {
|
||||||
node_t * prev = node;
|
value_expr_t * prev = node;
|
||||||
node = new node_t(node_t::O_MUL);
|
node = new value_expr_t(value_expr_t::O_MUL);
|
||||||
node->left = prev;
|
node->left = prev;
|
||||||
node->right = parse_term(in);
|
node->right = parse_value_term(in);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case '/': {
|
case '/': {
|
||||||
node_t * prev = node;
|
value_expr_t * prev = node;
|
||||||
node = new node_t(node_t::O_DIV);
|
node = new value_expr_t(value_expr_t::O_DIV);
|
||||||
node->left = prev;
|
node->left = prev;
|
||||||
node->right = parse_term(in);
|
node->right = parse_value_term(in);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -556,9 +519,9 @@ node_t * parse_mul_expr(std::istream& in)
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
node_t * parse_add_expr(std::istream& in)
|
value_expr_t * parse_add_expr(std::istream& in)
|
||||||
{
|
{
|
||||||
node_t * node = NULL;
|
value_expr_t * node = NULL;
|
||||||
|
|
||||||
node = parse_mul_expr(in);
|
node = parse_mul_expr(in);
|
||||||
|
|
||||||
|
|
@ -568,16 +531,16 @@ node_t * parse_add_expr(std::istream& in)
|
||||||
in.get(c);
|
in.get(c);
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '+': {
|
case '+': {
|
||||||
node_t * prev = node;
|
value_expr_t * prev = node;
|
||||||
node = new node_t(node_t::O_ADD);
|
node = new value_expr_t(value_expr_t::O_ADD);
|
||||||
node->left = prev;
|
node->left = prev;
|
||||||
node->right = parse_mul_expr(in);
|
node->right = parse_mul_expr(in);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case '-': {
|
case '-': {
|
||||||
node_t * prev = node;
|
value_expr_t * prev = node;
|
||||||
node = new node_t(node_t::O_SUB);
|
node = new value_expr_t(value_expr_t::O_SUB);
|
||||||
node->left = prev;
|
node->left = prev;
|
||||||
node->right = parse_mul_expr(in);
|
node->right = parse_mul_expr(in);
|
||||||
break;
|
break;
|
||||||
|
|
@ -590,14 +553,14 @@ node_t * parse_add_expr(std::istream& in)
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
node_t * parse_logic_expr(std::istream& in)
|
value_expr_t * parse_logic_expr(std::istream& in)
|
||||||
{
|
{
|
||||||
node_t * node = NULL;
|
value_expr_t * node = NULL;
|
||||||
|
|
||||||
if (peek_next_nonws(in) == '!') {
|
if (peek_next_nonws(in) == '!') {
|
||||||
char c;
|
char c;
|
||||||
in.get(c);
|
in.get(c);
|
||||||
node = new node_t(node_t::O_NOT);
|
node = new value_expr_t(value_expr_t::O_NOT);
|
||||||
node->left = parse_logic_expr(in);
|
node->left = parse_logic_expr(in);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
@ -610,19 +573,19 @@ node_t * parse_logic_expr(std::istream& in)
|
||||||
in.get(c);
|
in.get(c);
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '=': {
|
case '=': {
|
||||||
node_t * prev = node;
|
value_expr_t * prev = node;
|
||||||
node = new node_t(node_t::O_EQ);
|
node = new value_expr_t(value_expr_t::O_EQ);
|
||||||
node->left = prev;
|
node->left = prev;
|
||||||
node->right = parse_add_expr(in);
|
node->right = parse_add_expr(in);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case '<': {
|
case '<': {
|
||||||
node_t * prev = node;
|
value_expr_t * prev = node;
|
||||||
node = new node_t(node_t::O_LT);
|
node = new value_expr_t(value_expr_t::O_LT);
|
||||||
if (peek_next_nonws(in) == '=') {
|
if (peek_next_nonws(in) == '=') {
|
||||||
in.get(c);
|
in.get(c);
|
||||||
node->type = node_t::O_LTE;
|
node->type = value_expr_t::O_LTE;
|
||||||
}
|
}
|
||||||
node->left = prev;
|
node->left = prev;
|
||||||
node->right = parse_add_expr(in);
|
node->right = parse_add_expr(in);
|
||||||
|
|
@ -630,11 +593,11 @@ node_t * parse_logic_expr(std::istream& in)
|
||||||
}
|
}
|
||||||
|
|
||||||
case '>': {
|
case '>': {
|
||||||
node_t * prev = node;
|
value_expr_t * prev = node;
|
||||||
node = new node_t(node_t::O_GT);
|
node = new value_expr_t(value_expr_t::O_GT);
|
||||||
if (peek_next_nonws(in) == '=') {
|
if (peek_next_nonws(in) == '=') {
|
||||||
in.get(c);
|
in.get(c);
|
||||||
node->type = node_t::O_GTE;
|
node->type = value_expr_t::O_GTE;
|
||||||
}
|
}
|
||||||
node->left = prev;
|
node->left = prev;
|
||||||
node->right = parse_add_expr(in);
|
node->right = parse_add_expr(in);
|
||||||
|
|
@ -654,9 +617,9 @@ node_t * parse_logic_expr(std::istream& in)
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
node_t * parse_expr(std::istream& in)
|
value_expr_t * parse_value_expr(std::istream& in)
|
||||||
{
|
{
|
||||||
node_t * node = NULL;
|
value_expr_t * node = NULL;
|
||||||
|
|
||||||
node = parse_logic_expr(in);
|
node = parse_logic_expr(in);
|
||||||
|
|
||||||
|
|
@ -666,26 +629,26 @@ node_t * parse_expr(std::istream& in)
|
||||||
in.get(c);
|
in.get(c);
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '&': {
|
case '&': {
|
||||||
node_t * prev = node;
|
value_expr_t * prev = node;
|
||||||
node = new node_t(node_t::O_AND);
|
node = new value_expr_t(value_expr_t::O_AND);
|
||||||
node->left = prev;
|
node->left = prev;
|
||||||
node->right = parse_logic_expr(in);
|
node->right = parse_logic_expr(in);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case '|': {
|
case '|': {
|
||||||
node_t * prev = node;
|
value_expr_t * prev = node;
|
||||||
node = new node_t(node_t::O_OR);
|
node = new value_expr_t(value_expr_t::O_OR);
|
||||||
node->left = prev;
|
node->left = prev;
|
||||||
node->right = parse_logic_expr(in);
|
node->right = parse_logic_expr(in);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case '?': {
|
case '?': {
|
||||||
node_t * prev = node;
|
value_expr_t * prev = node;
|
||||||
node = new node_t(node_t::O_QUES);
|
node = new value_expr_t(value_expr_t::O_QUES);
|
||||||
node->left = prev;
|
node->left = prev;
|
||||||
node_t * choices = new node_t(node_t::O_COL);
|
value_expr_t * choices = new value_expr_t(value_expr_t::O_COL);
|
||||||
node->right = choices;
|
node->right = choices;
|
||||||
choices->left = parse_logic_expr(in);
|
choices->left = parse_logic_expr(in);
|
||||||
c = peek_next_nonws(in);
|
c = peek_next_nonws(in);
|
||||||
|
|
@ -756,128 +719,128 @@ std::string regexps_to_predicate(std::list<std::string>::const_iterator begin,
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
|
|
||||||
void dump_tree(std::ostream& out, const node_t * node)
|
void dump_value_expr(std::ostream& out, const value_expr_t * node)
|
||||||
{
|
{
|
||||||
switch (node->type) {
|
switch (node->type) {
|
||||||
case node_t::CONSTANT_A:
|
case value_expr_t::CONSTANT_A:
|
||||||
out << "CONST[" << node->constant_a << "]";
|
out << "CONST[" << node->constant_a << "]";
|
||||||
break;
|
break;
|
||||||
case node_t::CONSTANT_T:
|
case value_expr_t::CONSTANT_T:
|
||||||
out << "DATE/TIME[" << node->constant_t << "]";
|
out << "DATE/TIME[" << node->constant_t << "]";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case node_t::AMOUNT: out << "AMOUNT"; break;
|
case value_expr_t::AMOUNT: out << "AMOUNT"; break;
|
||||||
case node_t::COST: out << "COST"; break;
|
case value_expr_t::COST: out << "COST"; break;
|
||||||
case node_t::DATE: out << "DATE"; break;
|
case value_expr_t::DATE: out << "DATE"; break;
|
||||||
case node_t::CLEARED: out << "CLEARED"; break;
|
case value_expr_t::CLEARED: out << "CLEARED"; break;
|
||||||
case node_t::REAL: out << "REAL"; break;
|
case value_expr_t::REAL: out << "REAL"; break;
|
||||||
case node_t::INDEX: out << "INDEX"; break;
|
case value_expr_t::INDEX: out << "INDEX"; break;
|
||||||
case node_t::BALANCE: out << "BALANCE"; break;
|
case value_expr_t::BALANCE: out << "BALANCE"; break;
|
||||||
case node_t::COST_BALANCE: out << "COST_BALANCE"; break;
|
case value_expr_t::COST_BALANCE: out << "COST_BALANCE"; break;
|
||||||
case node_t::TOTAL: out << "TOTAL"; break;
|
case value_expr_t::TOTAL: out << "TOTAL"; break;
|
||||||
case node_t::COST_TOTAL: out << "COST_TOTAL"; break;
|
case value_expr_t::COST_TOTAL: out << "COST_TOTAL"; break;
|
||||||
|
|
||||||
case node_t::F_ARITH_MEAN:
|
case value_expr_t::F_ARITH_MEAN:
|
||||||
out << "MEAN(";
|
out << "MEAN(";
|
||||||
dump_tree(out, node->left);
|
dump_value_expr(out, node->left);
|
||||||
out << ")";
|
out << ")";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case node_t::F_NEG:
|
case value_expr_t::F_NEG:
|
||||||
out << "ABS(";
|
out << "ABS(";
|
||||||
dump_tree(out, node->left);
|
dump_value_expr(out, node->left);
|
||||||
out << ")";
|
out << ")";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case node_t::F_ABS:
|
case value_expr_t::F_ABS:
|
||||||
out << "ABS(";
|
out << "ABS(";
|
||||||
dump_tree(out, node->left);
|
dump_value_expr(out, node->left);
|
||||||
out << ")";
|
out << ")";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case node_t::F_PAYEE_MASK:
|
case value_expr_t::F_PAYEE_MASK:
|
||||||
assert(node->mask);
|
assert(node->mask);
|
||||||
out << "P_MASK(" << node->mask->pattern << ")";
|
out << "P_MASK(" << node->mask->pattern << ")";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case node_t::F_ACCOUNT_MASK:
|
case value_expr_t::F_ACCOUNT_MASK:
|
||||||
assert(node->mask);
|
assert(node->mask);
|
||||||
out << "A_MASK(" << node->mask->pattern << ")";
|
out << "A_MASK(" << node->mask->pattern << ")";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case node_t::F_VALUE:
|
case value_expr_t::F_VALUE:
|
||||||
out << "VALUE(";
|
out << "VALUE(";
|
||||||
dump_tree(out, node->left);
|
dump_value_expr(out, node->left);
|
||||||
if (node->right) {
|
if (node->right) {
|
||||||
out << ", ";
|
out << ", ";
|
||||||
dump_tree(out, node->right);
|
dump_value_expr(out, node->right);
|
||||||
}
|
}
|
||||||
out << ")";
|
out << ")";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case node_t::O_NOT:
|
case value_expr_t::O_NOT:
|
||||||
out << "!";
|
out << "!";
|
||||||
dump_tree(out, node->left);
|
dump_value_expr(out, node->left);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case node_t::O_QUES:
|
case value_expr_t::O_QUES:
|
||||||
dump_tree(out, node->left);
|
dump_value_expr(out, node->left);
|
||||||
out << "?";
|
out << "?";
|
||||||
dump_tree(out, node->right->left);
|
dump_value_expr(out, node->right->left);
|
||||||
out << ":";
|
out << ":";
|
||||||
dump_tree(out, node->right->right);
|
dump_value_expr(out, node->right->right);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case node_t::O_AND:
|
case value_expr_t::O_AND:
|
||||||
case node_t::O_OR:
|
case value_expr_t::O_OR:
|
||||||
out << "(";
|
out << "(";
|
||||||
dump_tree(out, node->left);
|
dump_value_expr(out, node->left);
|
||||||
switch (node->type) {
|
switch (node->type) {
|
||||||
case node_t::O_AND: out << " & "; break;
|
case value_expr_t::O_AND: out << " & "; break;
|
||||||
case node_t::O_OR: out << " | "; break;
|
case value_expr_t::O_OR: out << " | "; break;
|
||||||
default: assert(0); break;
|
default: assert(0); break;
|
||||||
}
|
}
|
||||||
dump_tree(out, node->right);
|
dump_value_expr(out, node->right);
|
||||||
out << ")";
|
out << ")";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case node_t::O_EQ:
|
case value_expr_t::O_EQ:
|
||||||
case node_t::O_LT:
|
case value_expr_t::O_LT:
|
||||||
case node_t::O_LTE:
|
case value_expr_t::O_LTE:
|
||||||
case node_t::O_GT:
|
case value_expr_t::O_GT:
|
||||||
case node_t::O_GTE:
|
case value_expr_t::O_GTE:
|
||||||
out << "(";
|
out << "(";
|
||||||
dump_tree(out, node->left);
|
dump_value_expr(out, node->left);
|
||||||
switch (node->type) {
|
switch (node->type) {
|
||||||
case node_t::O_EQ: out << "="; break;
|
case value_expr_t::O_EQ: out << "="; break;
|
||||||
case node_t::O_LT: out << "<"; break;
|
case value_expr_t::O_LT: out << "<"; break;
|
||||||
case node_t::O_LTE: out << "<="; break;
|
case value_expr_t::O_LTE: out << "<="; break;
|
||||||
case node_t::O_GT: out << ">"; break;
|
case value_expr_t::O_GT: out << ">"; break;
|
||||||
case node_t::O_GTE: out << ">="; break;
|
case value_expr_t::O_GTE: out << ">="; break;
|
||||||
default: assert(0); break;
|
default: assert(0); break;
|
||||||
}
|
}
|
||||||
dump_tree(out, node->right);
|
dump_value_expr(out, node->right);
|
||||||
out << ")";
|
out << ")";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case node_t::O_ADD:
|
case value_expr_t::O_ADD:
|
||||||
case node_t::O_SUB:
|
case value_expr_t::O_SUB:
|
||||||
case node_t::O_MUL:
|
case value_expr_t::O_MUL:
|
||||||
case node_t::O_DIV:
|
case value_expr_t::O_DIV:
|
||||||
out << "(";
|
out << "(";
|
||||||
dump_tree(out, node->left);
|
dump_value_expr(out, node->left);
|
||||||
switch (node->type) {
|
switch (node->type) {
|
||||||
case node_t::O_ADD: out << "+"; break;
|
case value_expr_t::O_ADD: out << "+"; break;
|
||||||
case node_t::O_SUB: out << "-"; break;
|
case value_expr_t::O_SUB: out << "-"; break;
|
||||||
case node_t::O_MUL: out << "*"; break;
|
case value_expr_t::O_MUL: out << "*"; break;
|
||||||
case node_t::O_DIV: out << "/"; break;
|
case value_expr_t::O_DIV: out << "/"; break;
|
||||||
default: assert(0); break;
|
default: assert(0); break;
|
||||||
}
|
}
|
||||||
dump_tree(out, node->right);
|
dump_value_expr(out, node->right);
|
||||||
out << ")";
|
out << ")";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case node_t::LAST:
|
case value_expr_t::LAST:
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
break;
|
break;
|
||||||
|
|
@ -892,7 +855,7 @@ void dump_tree(std::ostream& out, const node_t * node)
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
ledger::dump_tree(std::cout, ledger::parse_expr(argv[1]));
|
ledger::dump_value_exp(std::cout, ledger::parse_value_expr(argv[1]));
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
51
valexpr.h
51
valexpr.h
|
|
@ -20,13 +20,6 @@ class mask_t
|
||||||
bool match(const std::string& str) const;
|
bool match(const std::string& str) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if 1
|
|
||||||
typedef std::list<mask_t> masks_list;
|
|
||||||
|
|
||||||
bool matches(const masks_list& regexps, const std::string& str,
|
|
||||||
bool * by_exclusion = NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
struct details_t
|
struct details_t
|
||||||
{
|
{
|
||||||
|
|
@ -44,7 +37,7 @@ struct details_t
|
||||||
: entry(NULL), xact(NULL), account(_account) {}
|
: entry(NULL), xact(NULL), account(_account) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct node_t
|
struct value_expr_t
|
||||||
{
|
{
|
||||||
enum kind_t {
|
enum kind_t {
|
||||||
// Constants
|
// Constants
|
||||||
|
|
@ -92,18 +85,18 @@ struct node_t
|
||||||
LAST
|
LAST
|
||||||
};
|
};
|
||||||
|
|
||||||
kind_t type;
|
kind_t type;
|
||||||
node_t * left;
|
value_expr_t * left;
|
||||||
node_t * right;
|
value_expr_t * right;
|
||||||
|
|
||||||
amount_t constant_a;
|
amount_t constant_a;
|
||||||
std::time_t constant_t;
|
std::time_t constant_t;
|
||||||
mask_t * mask;
|
mask_t * mask;
|
||||||
|
|
||||||
node_t(const kind_t _type)
|
value_expr_t(const kind_t _type)
|
||||||
: type(_type), left(NULL), right(NULL), mask(NULL) {}
|
: type(_type), left(NULL), right(NULL), mask(NULL) {}
|
||||||
|
|
||||||
~node_t() {
|
~value_expr_t() {
|
||||||
if (mask) delete mask;
|
if (mask) delete mask;
|
||||||
if (left) delete left;
|
if (left) delete left;
|
||||||
if (right) delete right;
|
if (right) delete right;
|
||||||
|
|
@ -112,52 +105,42 @@ struct node_t
|
||||||
void compute(balance_t& result, const details_t& details) const;
|
void compute(balance_t& result, const details_t& details) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
node_t * parse_expr(std::istream& in);
|
value_expr_t * parse_value_expr(std::istream& in);
|
||||||
|
|
||||||
inline node_t * parse_expr(const char * p) {
|
inline value_expr_t * parse_value_expr(const char * p) {
|
||||||
std::istringstream stream(p);
|
std::istringstream stream(p);
|
||||||
return parse_expr(stream);
|
return parse_value_expr(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline node_t * parse_expr(const std::string& str) {
|
inline value_expr_t * parse_value_expr(const std::string& str) {
|
||||||
return parse_expr(str.c_str());
|
return parse_value_expr(str.c_str());
|
||||||
}
|
|
||||||
|
|
||||||
inline node_t * find_node(node_t * node, node_t::kind_t type) {
|
|
||||||
node_t * result = NULL;
|
|
||||||
if (node->type == type)
|
|
||||||
result = node;
|
|
||||||
if (! result && node->left)
|
|
||||||
result = find_node(node->left, type);
|
|
||||||
if (! result && node->right)
|
|
||||||
result = find_node(node->right, type);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
void dump_tree(std::ostream& out, const node_t * node);
|
void dump_value_expr(std::ostream& out, const value_expr_t * node);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class item_predicate
|
class item_predicate
|
||||||
{
|
{
|
||||||
const node_t * predicate;
|
const value_expr_t * predicate;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
item_predicate(const std::string& _predicate)
|
item_predicate(const std::string& _predicate)
|
||||||
: predicate(_predicate.empty() ? NULL : parse_expr(_predicate)) {
|
: predicate(_predicate.empty() ?
|
||||||
|
NULL : parse_value_expr(_predicate)) {
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
DEBUG_CLASS("valexpr.predicate.parse");
|
DEBUG_CLASS("valexpr.predicate.parse");
|
||||||
|
|
||||||
DEBUG_PRINT_("parsing: '" << _predicate << "'");
|
DEBUG_PRINT_("parsing: '" << _predicate << "'");
|
||||||
if (DEBUG_() && ledger::debug_stream) {
|
if (DEBUG_() && ledger::debug_stream) {
|
||||||
*ledger::debug_stream << "dump: ";
|
*ledger::debug_stream << "dump: ";
|
||||||
dump_tree(*ledger::debug_stream, predicate);
|
dump_value_expr(*ledger::debug_stream, predicate);
|
||||||
*ledger::debug_stream << std::endl;
|
*ledger::debug_stream << std::endl;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
item_predicate(const node_t * _predicate)
|
item_predicate(const value_expr_t * _predicate)
|
||||||
: predicate(_predicate) {}
|
: predicate(_predicate) {}
|
||||||
|
|
||||||
~item_predicate() {
|
~item_predicate() {
|
||||||
|
|
|
||||||
87
walk.cc
87
walk.cc
|
|
@ -30,30 +30,29 @@ void collapse_transactions::report_cumulative_subtotal()
|
||||||
{
|
{
|
||||||
if (count == 1) {
|
if (count == 1) {
|
||||||
(*handler)(last_xact);
|
(*handler)(last_xact);
|
||||||
return;
|
} else {
|
||||||
|
assert(count > 1);
|
||||||
|
|
||||||
|
totals_account->total = subtotal;
|
||||||
|
balance_t result;
|
||||||
|
format_t::compute_total(result, details_t(totals_account));
|
||||||
|
|
||||||
|
for (amounts_map::const_iterator i = result.amounts.begin();
|
||||||
|
i != result.amounts.end();
|
||||||
|
i++) {
|
||||||
|
transaction_t * total_xact = new transaction_t(last_entry,
|
||||||
|
totals_account);
|
||||||
|
xact_temps.push_back(total_xact);
|
||||||
|
|
||||||
|
total_xact->amount = (*i).second;
|
||||||
|
total_xact->cost = (*i).second;
|
||||||
|
|
||||||
|
(*handler)(total_xact);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(count > 1);
|
subtotal = 0;
|
||||||
|
count = 0;
|
||||||
transaction_t * total_xact = new transaction_t(NULL, totals_account);
|
|
||||||
|
|
||||||
balance_t value;
|
|
||||||
total_xact->total = subtotal;
|
|
||||||
format_t::compute_total(value, details_t(total_xact));
|
|
||||||
total_xact->total = 0;
|
|
||||||
|
|
||||||
total_xact->entry = last_entry;
|
|
||||||
|
|
||||||
for (amounts_map::const_iterator i = value.amounts.begin();
|
|
||||||
i != value.amounts.end();
|
|
||||||
i++) {
|
|
||||||
total_xact->amount = (*i).second;
|
|
||||||
total_xact->cost = (*i).second;
|
|
||||||
|
|
||||||
(*handler)(total_xact);
|
|
||||||
}
|
|
||||||
|
|
||||||
xact_temps.push_back(total_xact);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void changed_value_transactions::operator()(transaction_t * xact)
|
void changed_value_transactions::operator()(transaction_t * xact)
|
||||||
|
|
@ -82,13 +81,12 @@ void changed_value_transactions::operator()(transaction_t * xact)
|
||||||
i != diff.amounts.end();
|
i != diff.amounts.end();
|
||||||
i++) {
|
i++) {
|
||||||
transaction_t * temp_xact = new transaction_t(entry, NULL);
|
transaction_t * temp_xact = new transaction_t(entry, NULL);
|
||||||
|
xact_temps.push_back(temp_xact);
|
||||||
|
|
||||||
temp_xact->amount = (*i).second;
|
temp_xact->amount = (*i).second;
|
||||||
temp_xact->total = (*i).second;
|
temp_xact->total = (*i).second;
|
||||||
temp_xact->total.negate();
|
temp_xact->total.negate();
|
||||||
|
|
||||||
xact_temps.push_back(temp_xact);
|
|
||||||
|
|
||||||
(*handler)(temp_xact);
|
(*handler)(temp_xact);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -115,19 +113,21 @@ void subtotal_transactions::flush()
|
||||||
i != balances.end();
|
i != balances.end();
|
||||||
i++) {
|
i++) {
|
||||||
entry->date = finish;
|
entry->date = finish;
|
||||||
transaction_t * xact = new transaction_t(entry, (*i).first);
|
transaction_t temp(entry, (*i).first);
|
||||||
xact->total = (*i).second;
|
temp.total = (*i).second;
|
||||||
balance_t result;
|
balance_t result;
|
||||||
format_t::compute_total(result, details_t(xact));
|
format_t::compute_total(result, details_t(&temp));
|
||||||
xact->total = 0;
|
|
||||||
entry->date = start;
|
entry->date = start;
|
||||||
|
|
||||||
xact_temps.push_back(xact);
|
|
||||||
|
|
||||||
for (amounts_map::const_iterator j = result.amounts.begin();
|
for (amounts_map::const_iterator j = result.amounts.begin();
|
||||||
j != result.amounts.end();
|
j != result.amounts.end();
|
||||||
j++) {
|
j++) {
|
||||||
xact->amount = xact->cost = (*j).second;
|
transaction_t * xact = new transaction_t(entry, (*i).first);
|
||||||
|
xact_temps.push_back(xact);
|
||||||
|
|
||||||
|
xact->amount = (*j).second;
|
||||||
|
xact->cost = (*j).second;
|
||||||
|
|
||||||
(*handler)(xact);
|
(*handler)(xact);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -153,29 +153,4 @@ void subtotal_transactions::operator()(transaction_t * xact)
|
||||||
(*i).second += *xact;
|
(*i).second += *xact;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sum_in_account : public item_handler<transaction_t>
|
|
||||||
{
|
|
||||||
virtual void operator()(transaction_t * xact) {
|
|
||||||
xact->account->value += *xact;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void calc__accounts(account_t * account,
|
|
||||||
const item_predicate<transaction_t>& pred,
|
|
||||||
unsigned int flags)
|
|
||||||
{
|
|
||||||
sum_in_account handler;
|
|
||||||
|
|
||||||
for (transactions_list::iterator i = account->transactions.begin();
|
|
||||||
i != account->transactions.end();
|
|
||||||
i++)
|
|
||||||
if (pred(*i))
|
|
||||||
handle_transaction(*i, handler, flags);
|
|
||||||
|
|
||||||
for (accounts_map::iterator i = account->accounts.begin();
|
|
||||||
i != account->accounts.end();
|
|
||||||
i++)
|
|
||||||
calc__accounts((*i).second, pred, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ledger
|
} // namespace ledger
|
||||||
|
|
|
||||||
312
walk.h
312
walk.h
|
|
@ -20,9 +20,9 @@ struct item_handler {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct compare_items {
|
struct compare_items {
|
||||||
const node_t * sort_order;
|
const value_expr_t * sort_order;
|
||||||
|
|
||||||
compare_items(const node_t * _sort_order)
|
compare_items(const value_expr_t * _sort_order)
|
||||||
: sort_order(_sort_order) {
|
: sort_order(_sort_order) {
|
||||||
assert(sort_order);
|
assert(sort_order);
|
||||||
}
|
}
|
||||||
|
|
@ -40,27 +40,34 @@ struct compare_items {
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Several default handlers
|
// Transaction handlers
|
||||||
//
|
//
|
||||||
|
|
||||||
typedef std::deque<transaction_t *> transactions_deque;
|
typedef std::deque<transaction_t *> transactions_deque;
|
||||||
typedef std::deque<entry_t *> entries_deque;
|
typedef std::deque<entry_t *> entries_deque;
|
||||||
|
|
||||||
struct ignore_transaction : public item_handler<transaction_t>
|
struct ignore_transactions : public item_handler<transaction_t>
|
||||||
{
|
{
|
||||||
virtual void operator()(transaction_t * xact) {}
|
virtual void operator()(transaction_t * xact) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct clear_display_flags : public item_handler<transaction_t>
|
||||||
|
{
|
||||||
|
virtual void operator()(transaction_t * xact) {
|
||||||
|
xact->dflags = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class sort_transactions : public item_handler<transaction_t>
|
class sort_transactions : public item_handler<transaction_t>
|
||||||
{
|
{
|
||||||
transactions_deque transactions;
|
transactions_deque transactions;
|
||||||
const node_t * sort_order;
|
const value_expr_t * sort_order;
|
||||||
|
|
||||||
item_handler<transaction_t> * handler;
|
item_handler<transaction_t> * handler;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
sort_transactions(item_handler<transaction_t> * _handler,
|
sort_transactions(item_handler<transaction_t> * _handler,
|
||||||
const node_t * _sort_order)
|
const value_expr_t * _sort_order)
|
||||||
: sort_order(_sort_order), handler(_handler) {}
|
: sort_order(_sort_order), handler(_handler) {}
|
||||||
|
|
||||||
virtual ~sort_transactions() {
|
virtual ~sort_transactions() {
|
||||||
|
|
@ -173,11 +180,8 @@ class collapse_transactions : public item_handler<transaction_t>
|
||||||
// If we've reached a new entry, report on the subtotal
|
// If we've reached a new entry, report on the subtotal
|
||||||
// accumulated thus far.
|
// accumulated thus far.
|
||||||
|
|
||||||
if (last_entry && last_entry != xact->entry) {
|
if (last_entry && last_entry != xact->entry)
|
||||||
report_cumulative_subtotal();
|
report_cumulative_subtotal();
|
||||||
subtotal = 0;
|
|
||||||
count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
subtotal += *xact;
|
subtotal += *xact;
|
||||||
count++;
|
count++;
|
||||||
|
|
@ -302,90 +306,175 @@ class interval_transactions : public subtotal_transactions
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
class related_transactions : public item_handler<transaction_t>
|
||||||
|
|
||||||
#define MATCHING_TRANSACTIONS 0x01
|
|
||||||
#define OTHER_TRANSACTIONS 0x02
|
|
||||||
|
|
||||||
inline void handle_transaction(transaction_t * xact,
|
|
||||||
item_handler<transaction_t>& handler,
|
|
||||||
unsigned int flags)
|
|
||||||
{
|
{
|
||||||
for (transactions_list::iterator i = xact->entry->transactions.begin();
|
bool also_matching;
|
||||||
i != xact->entry->transactions.end();
|
|
||||||
i++)
|
|
||||||
if ((! (flags & OTHER_TRANSACTIONS) ||
|
|
||||||
! ((*i)->flags & TRANSACTION_AUTO)) &&
|
|
||||||
! ((*i)->dflags & TRANSACTION_HANDLED) &&
|
|
||||||
(*i == xact ?
|
|
||||||
(flags & MATCHING_TRANSACTIONS) : (flags & OTHER_TRANSACTIONS))) {
|
|
||||||
(*i)->dflags |= TRANSACTION_HANDLED;
|
|
||||||
handler(*i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void walk_entries(entries_list::iterator begin,
|
item_handler<transaction_t> * handler;
|
||||||
entries_list::iterator end,
|
|
||||||
item_handler<transaction_t>& handler,
|
|
||||||
const std::string& predicate,
|
|
||||||
unsigned int flags)
|
|
||||||
{
|
|
||||||
item_predicate<transaction_t> pred(predicate);
|
|
||||||
|
|
||||||
for (entries_list::iterator i = begin; i != end; i++)
|
public:
|
||||||
for (transactions_list::iterator j = (*i)->transactions.begin();
|
related_transactions(item_handler<transaction_t> * _handler,
|
||||||
j != (*i)->transactions.end();
|
bool _also_matching = false)
|
||||||
j++)
|
: also_matching(_also_matching), handler(_handler) {}
|
||||||
if (pred(*j))
|
|
||||||
handle_transaction(*j, handler, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void walk_entries(entries_list::iterator begin,
|
virtual ~related_transactions() {
|
||||||
entries_list::iterator end,
|
handler->flush();
|
||||||
item_handler<transaction_t>& handler)
|
delete handler;
|
||||||
{
|
}
|
||||||
for (entries_list::iterator i = begin; i != end; i++)
|
|
||||||
for (transactions_list::iterator j = (*i)->transactions.begin();
|
|
||||||
j != (*i)->transactions.end();
|
|
||||||
j++)
|
|
||||||
handler(*j);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct clear_flags : public item_handler<transaction_t>
|
|
||||||
{
|
|
||||||
virtual void operator()(transaction_t * xact) {
|
virtual void operator()(transaction_t * xact) {
|
||||||
xact->dflags = 0;
|
for (transactions_list::iterator i = xact->entry->transactions.begin();
|
||||||
|
i != xact->entry->transactions.end();
|
||||||
|
i++)
|
||||||
|
if (! ((*i)->dflags & TRANSACTION_HANDLED) &&
|
||||||
|
(*i == xact ? also_matching :
|
||||||
|
! ((*i)->flags & TRANSACTION_AUTO))) {
|
||||||
|
(*i)->dflags |= TRANSACTION_HANDLED;
|
||||||
|
(*handler)(*i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void clear_transaction_display_flags(entries_list::iterator begin,
|
//////////////////////////////////////////////////////////////////////
|
||||||
entries_list::iterator end)
|
|
||||||
{
|
|
||||||
clear_flags handler;
|
|
||||||
walk_entries(begin, end, handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void walk_transactions(transactions_list::iterator begin,
|
inline void walk_transactions(transactions_list::iterator begin,
|
||||||
transactions_list::iterator end,
|
transactions_list::iterator end,
|
||||||
item_handler<transaction_t>& handler)
|
item_handler<transaction_t>& handler) {
|
||||||
{
|
|
||||||
for (transactions_list::iterator i = begin; i != end; i++)
|
for (transactions_list::iterator i = begin; i != end; i++)
|
||||||
handler(*i);
|
handler(*i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void walk_transactions(transactions_list& list,
|
||||||
|
item_handler<transaction_t>& handler) {
|
||||||
|
walk_transactions(list.begin(), list.end(), handler);
|
||||||
|
}
|
||||||
|
|
||||||
inline void walk_transactions(transactions_deque::iterator begin,
|
inline void walk_transactions(transactions_deque::iterator begin,
|
||||||
transactions_deque::iterator end,
|
transactions_deque::iterator end,
|
||||||
item_handler<transaction_t>& handler)
|
item_handler<transaction_t>& handler) {
|
||||||
{
|
|
||||||
for (transactions_deque::iterator i = begin; i != end; i++)
|
for (transactions_deque::iterator i = begin; i != end; i++)
|
||||||
handler(*i);
|
handler(*i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void walk_transactions(transactions_deque& deque,
|
||||||
|
item_handler<transaction_t>& handler) {
|
||||||
|
walk_transactions(deque.begin(), deque.end(), handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void walk_entries(entries_list::iterator begin,
|
||||||
|
entries_list::iterator end,
|
||||||
|
item_handler<transaction_t>& handler) {
|
||||||
|
// jww (2004-08-11): do transaction dflags need to be cleared first?
|
||||||
|
for (entries_list::iterator i = begin; i != end; i++)
|
||||||
|
walk_transactions((*i)->transactions, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void walk_entries(entries_list& list,
|
||||||
|
item_handler<transaction_t>& handler) {
|
||||||
|
walk_entries(list.begin(), list.end(), handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Account handlers
|
||||||
|
//
|
||||||
|
|
||||||
typedef std::deque<account_t *> accounts_deque;
|
typedef std::deque<account_t *> accounts_deque;
|
||||||
|
|
||||||
|
struct add_to_account_value : public item_handler<transaction_t>
|
||||||
|
{
|
||||||
|
virtual void operator()(transaction_t * xact) {
|
||||||
|
xact->account->value += *xact;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
class format_accounts : public item_handler<account_t>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
class filter_accounts : public item_handler<account_t>
|
||||||
|
{
|
||||||
|
item_handler<account_t> * handler;
|
||||||
|
|
||||||
|
public:
|
||||||
|
filter_accounts(item_handler<account_t> * _handler)
|
||||||
|
: handler(_handler) {}
|
||||||
|
|
||||||
|
virtual ~filter_accounts() {
|
||||||
|
handler->flush();
|
||||||
|
delete handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void flush() {}
|
||||||
|
|
||||||
|
virtual void operator()(account_t * account) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class sort_accounts : public item_handler<account_t>
|
||||||
|
{
|
||||||
|
value_expr_t * sort_order;
|
||||||
|
|
||||||
|
item_handler<account_t> * handler;
|
||||||
|
|
||||||
|
public:
|
||||||
|
sort_accounts(item_handler<account_t> * _handler,
|
||||||
|
value_expr_t * _sort_order)
|
||||||
|
: sort_order(_sort_order), handler(_handler) {}
|
||||||
|
|
||||||
|
virtual ~sort_accounts() {
|
||||||
|
handler->flush();
|
||||||
|
delete handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void flush() {}
|
||||||
|
|
||||||
|
virtual void operator()(account_t * account) {
|
||||||
|
accounts_deque accounts;
|
||||||
|
|
||||||
|
for (accounts_map::iterator i = account->accounts.begin();
|
||||||
|
i != account->accounts.end();
|
||||||
|
i++)
|
||||||
|
accounts.push_back((*i).second);
|
||||||
|
|
||||||
|
std::stable_sort(accounts.begin(), accounts.end(),
|
||||||
|
compare_items<account_t>(sort_order));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class balance_accounts : public item_handler<account_t>
|
||||||
|
{
|
||||||
|
item_handler<account_t> * handler;
|
||||||
|
|
||||||
|
public:
|
||||||
|
balance_accounts(item_handler<account_t> * _handler)
|
||||||
|
: handler(_handler) {}
|
||||||
|
|
||||||
|
virtual ~balance_accounts() {
|
||||||
|
handler->flush();
|
||||||
|
delete handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void flush() {
|
||||||
|
if (format_account::disp_subaccounts_p(top)) {
|
||||||
|
std::string end_format = "--------------------\n";
|
||||||
|
format.reset(end_format + f);
|
||||||
|
format.format_elements(std::cout, details_t(top));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void operator()(account_t * account) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
inline void sort_accounts(account_t * account,
|
inline void sort_accounts(account_t * account,
|
||||||
accounts_deque& accounts,
|
accounts_deque& accounts,
|
||||||
const node_t * sort_order)
|
const value_expr_t * sort_order)
|
||||||
{
|
{
|
||||||
for (accounts_map::iterator i = account->accounts.begin();
|
for (accounts_map::iterator i = account->accounts.begin();
|
||||||
i != account->accounts.end();
|
i != account->accounts.end();
|
||||||
|
|
@ -396,6 +485,32 @@ inline void sort_accounts(account_t * account,
|
||||||
compare_items<account_t>(sort_order));
|
compare_items<account_t>(sort_order));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void walk__accounts_sorted(account_t * account,
|
||||||
|
item_handler<account_t>& handler,
|
||||||
|
const value_expr_t * sort_order)
|
||||||
|
{
|
||||||
|
handler(account);
|
||||||
|
|
||||||
|
accounts_deque accounts;
|
||||||
|
sort_accounts(account, accounts, sort_order);
|
||||||
|
|
||||||
|
for (accounts_deque::const_iterator i = accounts.begin();
|
||||||
|
i != accounts.end();
|
||||||
|
i++)
|
||||||
|
walk__accounts_sorted(*i, handler, sort_order);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void sum__accounts(account_t * account)
|
||||||
|
{
|
||||||
|
for (accounts_map::iterator i = account->accounts.begin();
|
||||||
|
i != account->accounts.end();
|
||||||
|
i++) {
|
||||||
|
sum__accounts((*i).second);
|
||||||
|
account->total += (*i).second->total;
|
||||||
|
}
|
||||||
|
account->total += account->value;
|
||||||
|
}
|
||||||
|
|
||||||
inline void walk__accounts(account_t * account,
|
inline void walk__accounts(account_t * account,
|
||||||
item_handler<account_t>& handler)
|
item_handler<account_t>& handler)
|
||||||
{
|
{
|
||||||
|
|
@ -407,64 +522,11 @@ inline void walk__accounts(account_t * account,
|
||||||
walk__accounts((*i).second, handler);
|
walk__accounts((*i).second, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void walk__accounts_sorted(account_t * account,
|
inline void walk_accounts(account_t * account,
|
||||||
item_handler<account_t>& handler,
|
item_handler<account_t>& handler,
|
||||||
const node_t * sort_order)
|
const bool calc_subtotals,
|
||||||
|
const value_expr_t * sort_order = NULL)
|
||||||
{
|
{
|
||||||
handler(account);
|
|
||||||
|
|
||||||
accounts_deque accounts;
|
|
||||||
|
|
||||||
for (accounts_map::const_iterator i = account->accounts.begin();
|
|
||||||
i != account->accounts.end();
|
|
||||||
i++)
|
|
||||||
accounts.push_back((*i).second);
|
|
||||||
|
|
||||||
std::stable_sort(accounts.begin(), accounts.end(),
|
|
||||||
compare_items<account_t>(sort_order));
|
|
||||||
|
|
||||||
for (accounts_deque::const_iterator i = accounts.begin();
|
|
||||||
i != accounts.end();
|
|
||||||
i++)
|
|
||||||
walk__accounts_sorted(*i, handler, sort_order);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void for_each_account(account_t * account,
|
|
||||||
item_handler<account_t>& handler)
|
|
||||||
{
|
|
||||||
handler(account);
|
|
||||||
|
|
||||||
for (accounts_map::iterator i = account->accounts.begin();
|
|
||||||
i != account->accounts.end();
|
|
||||||
i++)
|
|
||||||
walk__accounts((*i).second, handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
void calc__accounts(account_t * account,
|
|
||||||
const item_predicate<transaction_t>& pred,
|
|
||||||
unsigned int flags);
|
|
||||||
|
|
||||||
inline void sum__accounts(account_t * account)
|
|
||||||
{
|
|
||||||
for (accounts_map::iterator i = account->accounts.begin();
|
|
||||||
i != account->accounts.end();
|
|
||||||
i++) {
|
|
||||||
sum__accounts((*i).second);
|
|
||||||
account->total += (*i).second->total;
|
|
||||||
}
|
|
||||||
account->total += account->value;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void walk_accounts(account_t * account,
|
|
||||||
item_handler<account_t>& handler,
|
|
||||||
const std::string& predicate,
|
|
||||||
unsigned int flags,
|
|
||||||
const bool calc_subtotals,
|
|
||||||
const node_t * sort_order = NULL)
|
|
||||||
{
|
|
||||||
item_predicate<transaction_t> pred(predicate);
|
|
||||||
|
|
||||||
calc__accounts(account, pred, flags);
|
|
||||||
if (calc_subtotals)
|
if (calc_subtotals)
|
||||||
sum__accounts(account);
|
sum__accounts(account);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue