summaryrefslogtreecommitdiff
path: root/balance.cc
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2003-09-30 07:02:31 +0000
committerJohn Wiegley <johnw@newartisans.com>2003-09-30 07:02:31 +0000
commit5bd2401bc7cde0e01cd5b9d18cf077e255c4bd45 (patch)
treebcc3d57e446c3c7b9c91888bda2fa02d61423e96 /balance.cc
parentff57781f1fc80024ae6387f29b2f06278acadb3b (diff)
downloadfork-ledger-5bd2401bc7cde0e01cd5b9d18cf077e255c4bd45.tar.gz
fork-ledger-5bd2401bc7cde0e01cd5b9d18cf077e255c4bd45.tar.bz2
fork-ledger-5bd2401bc7cde0e01cd5b9d18cf077e255c4bd45.zip
*** empty log message ***
Diffstat (limited to 'balance.cc')
-rw-r--r--balance.cc165
1 files changed, 116 insertions, 49 deletions
diff --git a/balance.cc b/balance.cc
index 8154f466..dedbc4e1 100644
--- a/balance.cc
+++ b/balance.cc
@@ -1,14 +1,11 @@
#include "ledger.h"
+#include <fstream>
+#include <unistd.h>
#include <pcre.h> // Perl regular expression library
namespace ledger {
-//////////////////////////////////////////////////////////////////////
-//
-// Balance report.
-//
-
static bool show_current = false;
static bool show_cleared = false;
static bool show_children = false;
@@ -24,10 +21,14 @@ struct mask
};
static inline bool matches(const std::list<mask>& regexps,
- const std::string& str) {
- // If the first pattern is an exclude, then we assume that all
- // patterns match if they don't match the exclude.
+ const std::string& str)
+{
+ // If the first pattern is an exclude, we assume all patterns match
+ // if they don't match the exclude. If the first pattern is an
+ // include, then only accounts matching the include will match.
+
bool match = (*regexps.begin()).exclude;
+
for (std::list<mask>::const_iterator r = regexps.begin();
r != regexps.end();
r++) {
@@ -36,6 +37,7 @@ static inline bool matches(const std::list<mask>& regexps,
0, 0, ovec, 3) >= 0)
match = ! (*r).exclude;
}
+
return match;
}
@@ -82,48 +84,113 @@ static void display_total(std::ostream& out, totals& total_balance,
}
}
+ // Display balances for all child accounts
+
for (account::const_iterator i = acct->children.begin();
i != acct->children.end();
i++)
display_total(out, total_balance, (*i).second, balances, regexps);
}
+static void record_price(char * setting,
+ std::map<const std::string, amount *>& prices)
+{
+ char * c = setting;
+ char * p = std::strchr(setting, '=');
+ if (! p) {
+ std::cerr << "Warning: Invalid price setting: " << setting << std::endl;
+ } else {
+ *p++ = '\0';
+ amount * price = create_amount(p);
+ prices.insert(std::pair<const std::string, amount *>(c, price));
+ }
+}
+
+static void record_regexp(char * pattern, std::list<mask>& regexps)
+{
+ bool exclude = false;
+
+ char * pat = pattern;
+ if (*pat == '-') {
+ exclude = true;
+ pat++;
+ while (std::isspace(*pat))
+ pat++;
+ }
+ else if (*pat == '+') {
+ pat++;
+ while (std::isspace(*pat))
+ pat++;
+ }
+
+ const char *error;
+ int erroffset;
+ pcre * re = pcre_compile(pat, PCRE_CASELESS, &error, &erroffset, NULL);
+ if (! re)
+ std::cerr << "Warning: Failed to compile regexp: " << pattern
+ << std::endl;
+ else
+ regexps.push_back(mask(exclude, re));
+}
+
+//////////////////////////////////////////////////////////////////////
+//
+// Balance reporting code
+//
+
void report_balances(int argc, char **argv, std::ostream& out)
{
+ std::map<const std::string, amount *> prices;
+ std::list<mask> regexps;
+
int c;
optind = 1;
- while (-1 != (c = getopt(argc, argv, "cCsSn"))) {
+ while (-1 != (c = getopt(argc, argv, "cCsSni:p:"))) {
switch (char(c)) {
case 'c': show_current = true; break;
case 'C': show_cleared = true; break;
case 's': show_children = true; break;
case 'S': show_empty = true; break;
case 'n': no_subtotals = true; break;
+
+ // -i path-to-file-of-regexps
+ case 'i':
+ if (access(optarg, R_OK) != -1) {
+ std::ifstream include(optarg);
+
+ while (! include.eof()) {
+ char buf[80];
+ include.getline(buf, 79);
+ if (*buf && ! std::isspace(*buf))
+ record_regexp(buf, regexps);
+ }
+ }
+ break;
+
+ // -p "COMMODITY=PRICE"
+ // -p path-to-price-database
+ case 'p':
+ if (access(optarg, R_OK) != -1) {
+ std::ifstream pricedb(optarg);
+
+ while (! pricedb.eof()) {
+ char buf[80];
+ pricedb.getline(buf, 79);
+ if (*buf && ! std::isspace(*buf))
+ record_price(buf, prices);
+ }
+ } else {
+ record_price(optarg, prices);
+ }
+ break;
}
}
// Compile the list of specified regular expressions, which can be
- // specified on the command line, or using an include/exclude file.
+ // specified on the command line, or using an include/exclude file
- std::list<mask> regexps;
-
- for (; optind < argc; optind++) {
- bool exclude = false;
- char * pat = argv[optind];
- if (*pat == '-') {
- exclude = true;
- pat++;
- }
-
- const char *error;
- int erroffset;
- pcre * re = pcre_compile(pat, PCRE_CASELESS, &error, &erroffset, NULL);
- if (! re)
- std::cerr << "Warning: Failed to compile regexp: " << argv[optind]
- << std::endl;
- else
- regexps.push_back(mask(exclude, re));
- }
+ for (; optind < argc; optind++)
+ record_regexp(argv[optind], regexps);
// Walk through all of the ledger entries, computing the account
// totals
@@ -165,34 +232,30 @@ void report_balances(int argc, char **argv, std::ostream& out)
do_credit = true;
}
- if (do_credit)
+ if (! do_credit)
+ continue;
+
+ std::map<const std::string, amount *>::iterator pi
+ = prices.find((*x)->cost->comm_symbol());
+
+ if (pi == prices.end()) {
balance->credit((*x)->cost);
+ } else {
+ amount * value = (*x)->cost->value((*pi).second);
+ balance->credit(value);
+ delete value;
+ }
}
}
}
-#if 0
- // Print out the balance report header
-
- std::string which = "Future";
- if (show_current)
- which = "Current";
- else if (show_cleared)
- which = "Cleared";
-
- out.width(20);
- out << std::right << which << std::endl
- << "--------------------" << std::endl;
-#endif
-
- // Walk through all the top-level accounts, given the balance
+ // Walk through all the top-level accounts, giving the balance
// report for each, and then for each of their children.
totals total_balance;
for (accounts_iterator i = accounts.begin(); i != accounts.end(); i++)
- if (! (*i).second->parent)
- display_total(out, total_balance, (*i).second, balances, regexps);
+ display_total(out, total_balance, (*i).second, balances, regexps);
// Print the total of all the balances shown
@@ -204,9 +267,13 @@ void report_balances(int argc, char **argv, std::ostream& out)
for (std::map<account *, totals *>::iterator i = balances.begin();
i != balances.end();
- i++) {
+ i++)
+ delete (*i).second;
+
+ for (std::map<const std::string, amount *>::iterator i = prices.begin();
+ i != prices.end();
+ i++)
delete (*i).second;
- }
}
} // namespace ledger