*** empty log message ***
This commit is contained in:
parent
32bdfe20d9
commit
c8ebf53ed8
6 changed files with 154 additions and 104 deletions
73
amount.cc
73
amount.cc
|
|
@ -496,39 +496,50 @@ int amount_t::sign() const
|
|||
return quantity ? mpz_sgn(MPZ(quantity)) : 0;
|
||||
}
|
||||
|
||||
// comparisons between amounts
|
||||
#define AMOUNT_CMP_AMOUNT(OP) \
|
||||
bool amount_t::operator OP(const amount_t& amt) const \
|
||||
{ \
|
||||
if (! quantity) \
|
||||
return amt OP 0; \
|
||||
if (! amt.quantity) \
|
||||
return *this OP 0; \
|
||||
\
|
||||
if (commodity() && amt.commodity() && \
|
||||
commodity() != amt.commodity()) \
|
||||
return false; \
|
||||
\
|
||||
if (quantity->prec == amt.quantity->prec) { \
|
||||
return mpz_cmp(MPZ(quantity), MPZ(amt.quantity)) OP 0; \
|
||||
} \
|
||||
else if (quantity->prec < amt.quantity->prec) { \
|
||||
amount_t temp = *this; \
|
||||
temp._resize(amt.quantity->prec); \
|
||||
return mpz_cmp(MPZ(temp.quantity), MPZ(amt.quantity)) OP 0; \
|
||||
} \
|
||||
else { \
|
||||
amount_t temp = amt; \
|
||||
temp._resize(quantity->prec); \
|
||||
return mpz_cmp(MPZ(quantity), MPZ(temp.quantity)) OP 0; \
|
||||
} \
|
||||
int amount_t::compare(const amount_t& amt) const
|
||||
{
|
||||
if (! quantity) {
|
||||
if (! amt.quantity)
|
||||
return 0;
|
||||
return - amt.sign();
|
||||
}
|
||||
if (! amt.quantity)
|
||||
return sign();
|
||||
|
||||
if (commodity() && amt.commodity() &&
|
||||
commodity() != amt.commodity())
|
||||
throw new amount_error
|
||||
(std::string("Cannot compare amounts with different commodities: ") +
|
||||
commodity().symbol() + " and " + amt.commodity().symbol());
|
||||
|
||||
if (quantity->prec == amt.quantity->prec) {
|
||||
return mpz_cmp(MPZ(quantity), MPZ(amt.quantity));
|
||||
}
|
||||
else if (quantity->prec < amt.quantity->prec) {
|
||||
amount_t temp = *this;
|
||||
temp._resize(amt.quantity->prec);
|
||||
return mpz_cmp(MPZ(temp.quantity), MPZ(amt.quantity));
|
||||
}
|
||||
else {
|
||||
amount_t temp = amt;
|
||||
temp._resize(quantity->prec);
|
||||
return mpz_cmp(MPZ(quantity), MPZ(temp.quantity));
|
||||
}
|
||||
}
|
||||
|
||||
AMOUNT_CMP_AMOUNT(<)
|
||||
AMOUNT_CMP_AMOUNT(<=)
|
||||
AMOUNT_CMP_AMOUNT(>)
|
||||
AMOUNT_CMP_AMOUNT(>=)
|
||||
AMOUNT_CMP_AMOUNT(==)
|
||||
bool amount_t::operator==(const amount_t& amt) const
|
||||
{
|
||||
if (commodity() != amt.commodity())
|
||||
return false;
|
||||
return compare(amt) == 0;
|
||||
}
|
||||
|
||||
bool amount_t::operator!=(const amount_t& amt) const
|
||||
{
|
||||
if (commodity() != amt.commodity())
|
||||
return true;
|
||||
return compare(amt) != 0;
|
||||
}
|
||||
|
||||
amount_t::operator bool() const
|
||||
{
|
||||
|
|
|
|||
24
amount.h
24
amount.h
|
|
@ -202,16 +202,22 @@ class amount_t
|
|||
bool realzero() const;
|
||||
|
||||
// comparisons between amounts
|
||||
bool operator<(const amount_t& amt) const;
|
||||
bool operator<=(const amount_t& amt) const;
|
||||
bool operator>(const amount_t& amt) const;
|
||||
bool operator>=(const amount_t& amt) const;
|
||||
bool operator==(const amount_t& amt) const;
|
||||
bool operator!=(const amount_t& amt) const {
|
||||
if (commodity_ != amt.commodity_)
|
||||
return true;
|
||||
return ! (*this == amt);
|
||||
int compare(const amount_t& amt) const;
|
||||
|
||||
bool operator<(const amount_t& amt) const {
|
||||
return compare(amt) < 0;
|
||||
}
|
||||
bool operator<=(const amount_t& amt) const {
|
||||
return compare(amt) <= 0;
|
||||
}
|
||||
bool operator>(const amount_t& amt) const {
|
||||
return compare(amt) > 0;
|
||||
}
|
||||
bool operator>=(const amount_t& amt) const {
|
||||
return compare(amt) >= 0;
|
||||
}
|
||||
bool operator==(const amount_t& amt) const;
|
||||
bool operator!=(const amount_t& amt) const;
|
||||
|
||||
template <typename T>
|
||||
void parse_num(T num) {
|
||||
|
|
|
|||
96
config.cc
96
config.cc
|
|
@ -163,6 +163,8 @@ void config_t::reset()
|
|||
keep_price = false;
|
||||
keep_date = false;
|
||||
keep_tag = false;
|
||||
entry_sort = false;
|
||||
sort_all = false;
|
||||
|
||||
use_cache = false;
|
||||
cache_dirty = false;
|
||||
|
|
@ -381,6 +383,9 @@ void config_t::process_options(const std::string& command,
|
|||
amount_t::keep_price = keep_price;
|
||||
amount_t::keep_date = keep_date;
|
||||
amount_t::keep_tag = keep_tag;
|
||||
|
||||
if (! report_period.empty() && ! sort_all)
|
||||
entry_sort = true;
|
||||
}
|
||||
|
||||
item_handler<transaction_t> *
|
||||
|
|
@ -451,7 +456,7 @@ config_t::chain_xact_handlers(const std::string& command,
|
|||
parse_date(reconcile_date.c_str(), &cutoff);
|
||||
ptrs.push_back(formatter =
|
||||
new reconcile_transactions
|
||||
(formatter, value_t(reconcile_balance), cutoff));
|
||||
(formatter, value_t(reconcile_balance), cutoff));
|
||||
}
|
||||
|
||||
// filter_transactions will only pass through transactions
|
||||
|
|
@ -463,9 +468,14 @@ config_t::chain_xact_handlers(const std::string& command,
|
|||
|
||||
// sort_transactions will sort all the transactions it sees, based
|
||||
// on the `sort_order' value expression.
|
||||
if (! sort_string.empty())
|
||||
ptrs.push_back(formatter =
|
||||
new sort_transactions(formatter, sort_string));
|
||||
if (! sort_string.empty()) {
|
||||
if (entry_sort)
|
||||
ptrs.push_back(formatter =
|
||||
new sort_entries(formatter, sort_string));
|
||||
else
|
||||
ptrs.push_back(formatter =
|
||||
new sort_transactions(formatter, sort_string));
|
||||
}
|
||||
|
||||
// changed_value_transactions adds virtual transactions to the
|
||||
// list to account for changes in market value of commodities,
|
||||
|
|
@ -480,37 +490,37 @@ config_t::chain_xact_handlers(const std::string& command,
|
|||
// commodity used.
|
||||
if (show_collapsed)
|
||||
ptrs.push_back(formatter = new collapse_transactions(formatter));
|
||||
}
|
||||
|
||||
// subtotal_transactions combines all the transactions it receives
|
||||
// into one subtotal entry, which has one transaction for each
|
||||
// commodity in each account.
|
||||
//
|
||||
// period_transactions is like subtotal_transactions, but it
|
||||
// subtotals according to time periods rather than totalling
|
||||
// everything.
|
||||
//
|
||||
// dow_transactions is like period_transactions, except that it
|
||||
// reports all the transactions that fall on each subsequent day
|
||||
// of the week.
|
||||
if (show_subtotal && ! (command == "b" || command == "E"))
|
||||
ptrs.push_back(formatter =
|
||||
new subtotal_transactions(formatter, remember_components));
|
||||
// subtotal_transactions combines all the transactions it receives
|
||||
// into one subtotal entry, which has one transaction for each
|
||||
// commodity in each account.
|
||||
//
|
||||
// period_transactions is like subtotal_transactions, but it
|
||||
// subtotals according to time periods rather than totalling
|
||||
// everything.
|
||||
//
|
||||
// dow_transactions is like period_transactions, except that it
|
||||
// reports all the transactions that fall on each subsequent day
|
||||
// of the week.
|
||||
if (show_subtotal)
|
||||
ptrs.push_back(formatter =
|
||||
new subtotal_transactions(formatter, remember_components));
|
||||
|
||||
if (days_of_the_week)
|
||||
ptrs.push_back(formatter =
|
||||
new dow_transactions(formatter, remember_components));
|
||||
else if (by_payee)
|
||||
ptrs.push_back(formatter =
|
||||
new by_payee_transactions(formatter, remember_components));
|
||||
if (days_of_the_week)
|
||||
ptrs.push_back(formatter =
|
||||
new dow_transactions(formatter, remember_components));
|
||||
else if (by_payee)
|
||||
ptrs.push_back(formatter =
|
||||
new by_payee_transactions(formatter, remember_components));
|
||||
|
||||
if (! report_period.empty()) {
|
||||
ptrs.push_back(formatter =
|
||||
new interval_transactions(formatter,
|
||||
report_period,
|
||||
report_period_sort,
|
||||
remember_components));
|
||||
ptrs.push_back(formatter = new sort_transactions(formatter, "d"));
|
||||
// interval_transactions groups transactions together based on a
|
||||
// time period, such as weekly or monthly.
|
||||
if (! report_period.empty()) {
|
||||
ptrs.push_back(formatter =
|
||||
new interval_transactions(formatter, report_period,
|
||||
remember_components));
|
||||
ptrs.push_back(formatter = new sort_transactions(formatter, "d"));
|
||||
}
|
||||
}
|
||||
|
||||
// invert_transactions inverts the value of the transactions it
|
||||
|
|
@ -1037,6 +1047,22 @@ OPT_BEGIN(sort, "S:") {
|
|||
config->sort_string = optarg;
|
||||
} OPT_END(sort);
|
||||
|
||||
OPT_BEGIN(sort_entries, "") {
|
||||
config->sort_string = optarg;
|
||||
config->entry_sort = true;
|
||||
} OPT_END(sort_entries);
|
||||
|
||||
OPT_BEGIN(sort_all, "") {
|
||||
config->sort_string = optarg;
|
||||
config->entry_sort = false;
|
||||
config->sort_all = true;
|
||||
} OPT_END(sort_all);
|
||||
|
||||
OPT_BEGIN(period_sort, ":") {
|
||||
config->sort_string = optarg;
|
||||
config->entry_sort = true;
|
||||
} OPT_END(period_sort);
|
||||
|
||||
OPT_BEGIN(related, "r") {
|
||||
config->show_related = true;
|
||||
} OPT_END(related);
|
||||
|
|
@ -1096,10 +1122,6 @@ OPT_BEGIN(period, "p:") {
|
|||
}
|
||||
} OPT_END(period);
|
||||
|
||||
OPT_BEGIN(period_sort, ":") {
|
||||
config->report_period_sort = optarg;
|
||||
} OPT_END(period_sort);
|
||||
|
||||
OPT_BEGIN(daily, "") {
|
||||
if (config->report_period.empty())
|
||||
config->report_period = "daily";
|
||||
|
|
@ -1392,6 +1414,8 @@ option_t config_options[CONFIG_OPTIONS_SIZE] = {
|
|||
{ "related", 'r', false, opt_related, false },
|
||||
{ "set-price", '\0', true, opt_set_price, false },
|
||||
{ "sort", 'S', true, opt_sort, false },
|
||||
{ "sort-all", '\0', true, opt_sort_all, false },
|
||||
{ "sort-entries", '\0', true, opt_sort_entries, false },
|
||||
{ "subtotal", 's', false, opt_subtotal, false },
|
||||
{ "tail", '\0', true, opt_tail, false },
|
||||
{ "total", 'T', true, opt_total, false },
|
||||
|
|
|
|||
4
config.h
4
config.h
|
|
@ -74,6 +74,8 @@ class config_t
|
|||
bool keep_price;
|
||||
bool keep_date;
|
||||
bool keep_tag;
|
||||
bool entry_sort;
|
||||
bool sort_all;
|
||||
|
||||
config_t() {
|
||||
reset();
|
||||
|
|
@ -107,7 +109,7 @@ class config_t
|
|||
std::list<item_handler<transaction_t> *>& ptrs);
|
||||
};
|
||||
|
||||
#define CONFIG_OPTIONS_SIZE 91
|
||||
#define CONFIG_OPTIONS_SIZE 93
|
||||
extern option_t config_options[CONFIG_OPTIONS_SIZE];
|
||||
|
||||
void option_help(std::ostream& out);
|
||||
|
|
|
|||
3
walk.cc
3
walk.cc
|
|
@ -439,9 +439,6 @@ void interval_transactions::report_subtotal(const std::time_t moment)
|
|||
|
||||
subtotal_transactions::report_subtotal();
|
||||
|
||||
if (sorter)
|
||||
sorter->post_accumulated_xacts();
|
||||
|
||||
last_xact = NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
58
walk.h
58
walk.h
|
|
@ -252,7 +252,7 @@ class sort_transactions : public item_handler<transaction_t>
|
|||
sort_transactions(item_handler<transaction_t> * handler,
|
||||
const value_expr_t * _sort_order)
|
||||
: item_handler<transaction_t>(handler),
|
||||
sort_order(_sort_order) {}
|
||||
sort_order(_sort_order->acquire()) {}
|
||||
|
||||
sort_transactions(item_handler<transaction_t> * handler,
|
||||
const std::string& _sort_order)
|
||||
|
|
@ -278,6 +278,35 @@ class sort_transactions : public item_handler<transaction_t>
|
|||
}
|
||||
};
|
||||
|
||||
class sort_entries : public item_handler<transaction_t>
|
||||
{
|
||||
sort_transactions sorter;
|
||||
entry_t * last_entry;
|
||||
|
||||
public:
|
||||
sort_entries(item_handler<transaction_t> * handler,
|
||||
const value_expr_t * _sort_order)
|
||||
: sorter(handler, _sort_order) {}
|
||||
|
||||
sort_entries(item_handler<transaction_t> * handler,
|
||||
const std::string& _sort_order)
|
||||
: sorter(handler, _sort_order) {}
|
||||
|
||||
virtual void flush() {
|
||||
sorter.flush();
|
||||
item_handler<transaction_t>::flush();
|
||||
}
|
||||
|
||||
virtual void operator()(transaction_t& xact) {
|
||||
if (last_entry && xact.entry != last_entry)
|
||||
sorter.post_accumulated_xacts();
|
||||
|
||||
sorter(xact);
|
||||
|
||||
last_entry = xact.entry;
|
||||
}
|
||||
};
|
||||
|
||||
class filter_transactions : public item_handler<transaction_t>
|
||||
{
|
||||
item_predicate<transaction_t> pred;
|
||||
|
|
@ -492,37 +521,18 @@ class interval_transactions : public subtotal_transactions
|
|||
transaction_t * last_xact;
|
||||
bool started;
|
||||
|
||||
sort_transactions * sorter;
|
||||
|
||||
public:
|
||||
interval_transactions(item_handler<transaction_t> * _handler,
|
||||
const interval_t& _interval,
|
||||
const value_expr_t * sort_order = NULL,
|
||||
const interval_t& _interval,
|
||||
bool remember_components = false)
|
||||
: subtotal_transactions(_handler, remember_components),
|
||||
interval(_interval), last_xact(NULL), started(false),
|
||||
sorter(NULL) {
|
||||
if (sort_order) {
|
||||
sorter = new sort_transactions(handler, sort_order);
|
||||
handler = sorter;
|
||||
}
|
||||
}
|
||||
interval(_interval), last_xact(NULL), started(false) {}
|
||||
|
||||
interval_transactions(item_handler<transaction_t> * _handler,
|
||||
const std::string& _interval,
|
||||
const std::string& sort_order = "",
|
||||
bool remember_components = false)
|
||||
: subtotal_transactions(_handler, remember_components),
|
||||
interval(_interval), last_xact(NULL), started(false),
|
||||
sorter(NULL) {
|
||||
if (! sort_order.empty()) {
|
||||
sorter = new sort_transactions(handler, sort_order);
|
||||
handler = sorter;
|
||||
}
|
||||
}
|
||||
virtual ~interval_transactions() {
|
||||
if (sorter)
|
||||
delete sorter;
|
||||
}
|
||||
interval(_interval), last_xact(NULL), started(false) {}
|
||||
|
||||
void report_subtotal(const std::time_t moment = 0);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue