From e2afc783db0dff1927b00dc506390353d9e3bbd2 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Wed, 29 Feb 2012 22:32:23 -0600 Subject: Increased file copyrights to 2012 --- src/annotate.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/annotate.cc') diff --git a/src/annotate.cc b/src/annotate.cc index 8ba46f4f..cd1733ca 100644 --- a/src/annotate.cc +++ b/src/annotate.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * Copyright (c) 2003-2012, John Wiegley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are -- cgit v1.2.3 From e5885cc8a8a1d6cd2a65d04c56ba86d65317f4a1 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Mon, 5 Mar 2012 17:47:12 -0600 Subject: Added annotation_t::operator<() --- src/annotate.cc | 28 ++++++++++++++++++++++++++++ src/annotate.h | 1 + 2 files changed, 29 insertions(+) (limited to 'src/annotate.cc') diff --git a/src/annotate.cc b/src/annotate.cc index cd1733ca..1e243beb 100644 --- a/src/annotate.cc +++ b/src/annotate.cc @@ -38,6 +38,34 @@ namespace ledger { +bool annotation_t::operator<(const annotation_t& rhs) const +{ + if (! price && rhs.price) return true; + if (price && ! rhs.price) return false; + if (! date && rhs.date) return true; + if (date && ! rhs.date) return false; + if (! tag && rhs.tag) return true; + if (tag && ! rhs.tag) return false; + + if (price) { + if (price->commodity().symbol() < rhs.price->commodity().symbol()) + return true; + if (price->commodity().symbol() > rhs.price->commodity().symbol()) + return false; + if (*price < *rhs.price) return true; + if (*price > *rhs.price) return false; + } + if (date) { + if (*date < *rhs.date) return true; + if (*date > *rhs.date) return false; + } + if (tag) { + if (*tag < *rhs.tag) return true; + if (*tag > *rhs.tag) return false; + } + return false; +} + void annotation_t::parse(std::istream& in) { do { diff --git a/src/annotate.h b/src/annotate.h index 3c6db8e8..29294e88 100644 --- a/src/annotate.h +++ b/src/annotate.h @@ -79,6 +79,7 @@ struct annotation_t : public supports_flags<>, return price || date || tag; } + bool operator<(const annotation_t& rhs) const; bool operator==(const annotation_t& rhs) const { return (price == rhs.price && date == rhs.date && -- cgit v1.2.3 From 8ae2fb87211b2c1a0159480ea6908db2afa20189 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Mon, 5 Mar 2012 23:01:41 -0600 Subject: Add support for valuation expressions on commodities --- src/annotate.cc | 62 +++++++++++++++++++++++++++++++++++++++++++---------- src/annotate.h | 46 ++++++++++++++++++++++++++------------- src/expr.h | 3 +++ src/predicate.cc | 40 ---------------------------------- test/unit/t_expr.cc | 2 +- tools/Makefile.am | 41 +++++++++++------------------------ 6 files changed, 98 insertions(+), 96 deletions(-) delete mode 100644 src/predicate.cc (limited to 'src/annotate.cc') diff --git a/src/annotate.cc b/src/annotate.cc index 1e243beb..b1db6bd5 100644 --- a/src/annotate.cc +++ b/src/annotate.cc @@ -33,6 +33,7 @@ #include "amount.h" #include "commodity.h" +#include "expr.h" #include "annotate.h" #include "pool.h" @@ -47,6 +48,9 @@ bool annotation_t::operator<(const annotation_t& rhs) const if (! tag && rhs.tag) return true; if (tag && ! rhs.tag) return false; + if (! value_expr && rhs.value_expr) return true; + if (value_expr && ! rhs.value_expr) return false; + if (price) { if (price->commodity().symbol() < rhs.price->commodity().symbol()) return true; @@ -63,6 +67,10 @@ bool annotation_t::operator<(const annotation_t& rhs) const if (*tag < *rhs.tag) return true; if (*tag > *rhs.tag) return false; } + if (value_expr) { + if (value_expr->text() < rhs.value_expr->text()) return true; + if (value_expr->text() > rhs.value_expr->text()) return false; + } return false; } @@ -112,17 +120,41 @@ void annotation_t::parse(std::istream& in) date = parse_date(buf); } else if (c == '(') { - if (tag) - throw_(amount_error, _("Commodity specifies more than one tag")); - in.get(c); - READ_INTO(in, buf, 255, c, c != ')'); - if (c == ')') - in.get(c); - else - throw_(amount_error, _("Commodity tag lacks closing parenthesis")); + c = static_cast(in.peek()); + if (c == '(') { + if (value_expr) + throw_(amount_error, + _("Commodity specifies more than one valuation expresion")); - tag = buf; + in.get(c); + READ_INTO(in, buf, 255, c, c != ')'); + if (c == ')') { + in.get(c); + c = static_cast(in.peek()); + if (c == ')') + in.get(c); + else + throw_(amount_error, + _("Commodity valuation expression lacks closing parentheses")); + } else { + throw_(amount_error, + _("Commodity valuation expression lacks closing parentheses")); + } + + value_expr = expr_t(buf); + } else { + if (tag) + throw_(amount_error, _("Commodity specifies more than one tag")); + + READ_INTO(in, buf, 255, c, c != ')'); + if (c == ')') + in.get(c); + else + throw_(amount_error, _("Commodity tag lacks closing parenthesis")); + + tag = buf; + } } else { in.clear(); @@ -156,6 +188,10 @@ void annotation_t::print(std::ostream& out, bool keep_base, if (tag && (! no_computed_annotations || ! has_flags(ANNOTATION_TAG_CALCULATED))) out << " (" << *tag << ')'; + + if (value_expr && (! no_computed_annotations || + ! has_flags(ANNOTATION_VALUE_EXPR_CALCULATED))) + out << " ((" << *value_expr << "))"; } bool keep_details_t::keep_all(const commodity_t& comm) const @@ -220,12 +256,14 @@ annotated_commodity_t::strip_annotations(const keep_details_t& what_to_keep) if ((keep_price && details.price) || (keep_date && details.date) || - (keep_tag && details.tag)) + (keep_tag && details.tag) || + details.value_expr) { new_comm = pool().find_or_create (referent(), annotation_t(keep_price ? details.price : none, keep_date ? details.date : none, - keep_tag ? details.tag : none)); + keep_tag ? details.tag : none, + details.value_expr)); // Transfer over any relevant annotation flags, as they still apply. if (new_comm->annotated) { @@ -238,6 +276,8 @@ annotated_commodity_t::strip_annotations(const keep_details_t& what_to_keep) new_details.add_flags(details.flags() & ANNOTATION_DATE_CALCULATED); if (keep_tag) new_details.add_flags(details.flags() & ANNOTATION_TAG_CALCULATED); + if (details.value_expr) + new_details.add_flags(details.flags() & ANNOTATION_VALUE_EXPR_CALCULATED); } return *new_comm; diff --git a/src/annotate.h b/src/annotate.h index 29294e88..eb87a1b2 100644 --- a/src/annotate.h +++ b/src/annotate.h @@ -46,29 +46,38 @@ #ifndef _ANNOTATE_H #define _ANNOTATE_H +#include "expr.h" + namespace ledger { struct annotation_t : public supports_flags<>, public equality_comparable { -#define ANNOTATION_PRICE_CALCULATED 0x01 -#define ANNOTATION_PRICE_FIXATED 0x02 -#define ANNOTATION_DATE_CALCULATED 0x04 -#define ANNOTATION_TAG_CALCULATED 0x08 +#define ANNOTATION_PRICE_CALCULATED 0x01 +#define ANNOTATION_PRICE_FIXATED 0x02 +#define ANNOTATION_DATE_CALCULATED 0x04 +#define ANNOTATION_TAG_CALCULATED 0x08 +#define ANNOTATION_VALUE_EXPR_CALCULATED 0x10 optional price; optional date; optional tag; - - explicit annotation_t(const optional& _price = none, - const optional& _date = none, - const optional& _tag = none) - : supports_flags<>(), price(_price), date(_date), tag(_tag) { - TRACE_CTOR(annotation_t, "const optional& + date_t + string"); + optional value_expr; + + explicit annotation_t(const optional& _price = none, + const optional& _date = none, + const optional& _tag = none, + const optional& _value_expr = none) + : supports_flags<>(), price(_price), date(_date), tag(_tag), + value_expr(_value_expr) { + TRACE_CTOR(annotation_t, + "const optional& + date_t + string + expr_t"); } annotation_t(const annotation_t& other) : supports_flags<>(other.flags()), - price(other.price), date(other.date), tag(other.tag) { + price(other.price), date(other.date), tag(other.tag), + value_expr(other.value_expr) + { TRACE_CTOR(annotation_t, "copy"); } ~annotation_t() { @@ -76,14 +85,15 @@ struct annotation_t : public supports_flags<>, } operator bool() const { - return price || date || tag; + return price || date || tag || value_expr; } bool operator<(const annotation_t& rhs) const; bool operator==(const annotation_t& rhs) const { - return (price == rhs.price && - date == rhs.date && - tag == rhs.tag); + return (price == rhs.price && + date == rhs.date && + tag == rhs.tag && + value_expr == rhs.value_expr); } void parse(std::istream& in); @@ -133,6 +143,12 @@ inline void to_xml(std::ostream& out, const annotation_t& details) push_xml y(out, "tag"); out << y.guard(*details.tag); } + + if (details.value_expr) + { + push_xml y(out, "value-expr"); + out << y.guard(details.value_expr->text()); + } } struct keep_details_t diff --git a/src/expr.h b/src/expr.h index e082efa5..ab3487fe 100644 --- a/src/expr.h +++ b/src/expr.h @@ -58,6 +58,9 @@ public: typedef intrusive_ptr ptr_op_t; typedef intrusive_ptr const_ptr_op_t; + friend void intrusive_ptr_add_ref(const op_t * op); + friend void intrusive_ptr_release(const op_t * op); + enum check_expr_kind_t { EXPR_GENERAL, EXPR_ASSERTION, diff --git a/src/predicate.cc b/src/predicate.cc deleted file mode 100644 index 58d6c752..00000000 --- a/src/predicate.cc +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2003-2012, John Wiegley. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of New Artisans LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include "predicate.h" -#include "query.h" -#include "op.h" - -namespace ledger { - -} // namespace ledger diff --git a/test/unit/t_expr.cc b/test/unit/t_expr.cc index f882f3a1..c10ee029 100644 --- a/test/unit/t_expr.cc +++ b/test/unit/t_expr.cc @@ -1,5 +1,5 @@ #define BOOST_TEST_DYN_LINK -#define BOOST_TEST_MODULE expr +//#define BOOST_TEST_MODULE expr #include #include diff --git a/tools/Makefile.am b/tools/Makefile.am index 671db294..a598966a 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -8,7 +8,6 @@ DISTCLEANFILES = .timestamp lib_LTLIBRARIES = \ libledger_report.la \ libledger_data.la \ - libledger_expr.la \ libledger_math.la \ libledger_util.la @@ -28,6 +27,14 @@ libledger_util_la_CPPFLAGS = $(lib_cppflags) libledger_util_la_LDFLAGS = -release $(LIBVERSION) libledger_math_la_SOURCES = \ + src/format.cc \ + src/query.cc \ + src/scope.cc \ + src/expr.cc \ + src/op.cc \ + src/parser.cc \ + src/token.cc \ + src/value.cc \ src/balance.cc \ src/quotes.cc \ src/history.cc \ @@ -39,22 +46,8 @@ libledger_math_la_SOURCES = \ libledger_math_la_CPPFLAGS = $(lib_cppflags) libledger_math_la_LDFLAGS = -release $(LIBVERSION) -libledger_expr_la_SOURCES = \ - src/option.cc \ - src/format.cc \ - src/query.cc \ - src/predicate.cc \ - src/scope.cc \ - src/expr.cc \ - src/op.cc \ - src/parser.cc \ - src/token.cc \ - src/value.cc - -libledger_expr_la_CPPFLAGS = $(lib_cppflags) -libledger_expr_la_LDFLAGS = -release $(LIBVERSION) - libledger_data_la_SOURCES = \ + src/option.cc \ src/lookup.cc \ src/compare.cc \ src/iterators.cc \ @@ -204,7 +197,6 @@ DISTCLEANFILES += ledger.elc timeclock.elc all_sources = $(libledger_util_la_SOURCES) \ $(libledger_math_la_SOURCES) \ - $(libledger_expr_la_SOURCES) \ $(libledger_data_la_SOURCES) \ $(libledger_report_la_SOURCES) \ $(libledger_python_la_SOURCES) \ @@ -259,8 +251,7 @@ TESTS = RegressTests BaselineTests ManualTests ConfirmTests \ if HAVE_BOOST_TEST TESTS += \ UtilTests \ - MathTests \ - ExprTests + MathTests # DataTests \ # ReportTests endif @@ -285,6 +276,7 @@ UtilTests_CPPFLAGS = -I$(srcdir)/test $(lib_cppflags) UtilTests_LDADD = libledger_util.la $(TESTLIBS) MathTests_SOURCES = \ + test/unit/t_expr.cc \ test/unit/t_commodity.cc \ test/unit/t_amount.cc \ test/unit/t_balance.cc @@ -292,16 +284,10 @@ MathTests_SOURCES = \ MathTests_CPPFLAGS = -I$(srcdir)/test $(lib_cppflags) MathTests_LDADD = libledger_math.la $(UtilTests_LDADD) -ExprTests_SOURCES = \ - test/unit/t_expr.cc - -ExprTests_CPPFLAGS = -I$(srcdir)/test $(lib_cppflags) -ExprTests_LDADD = libledger_expr.la $(MathTests_LDADD) - DataTests_SOURCES = DataTests_CPPFLAGS = -I$(srcdir)/test $(lib_cppflags) -DataTests_LDADD = libledger_data.la $(ExprTests_LDADD) +DataTests_LDADD = libledger_data.la $(MathTests_LDADD) ReportTests_SOURCES = @@ -311,7 +297,6 @@ ReportTests_LDADD = libledger_report.la $(DataTests_LDADD) all_tests_sources = \ $(UtilTests_SOURCES) \ $(MathTests_SOURCES) \ - $(ExprTests_SOURCES) \ $(DataTests_SOURCES) \ $(ReportTests_SOURCES) @@ -421,8 +406,6 @@ unittests: check 2>&1 | grep -v '^GuardMalloc:' @sh $(FULLCHECK) $(top_builddir)/MathTests$(EXEEXT) --verify \ 2>&1 | grep -v '^GuardMalloc:' - @sh $(FULLCHECK) $(top_builddir)/ExprTests$(EXEEXT) --verify \ - 2>&1 | grep -v '^GuardMalloc:' # @sh $(FULLCHECK) $(top_builddir)/DataTests$(EXEEXT) --verify \ # 2>&1 | grep -v '^GuardMalloc:' # @sh $(FULLCHECK) $(top_builddir)/ReportTests$(EXEEXT) --verify \ -- cgit v1.2.3 From eb3591f898e194be0cb6c15107e8e41e9dd67206 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Tue, 6 Mar 2012 02:01:25 -0600 Subject: Implemented annotated_commodity_t::find_price Most specifically, it now respects a valuation expression associated with the commodity. --- src/annotate.cc | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- src/annotate.h | 5 +++++ 2 files changed, 70 insertions(+), 4 deletions(-) (limited to 'src/annotate.cc') diff --git a/src/annotate.cc b/src/annotate.cc index b1db6bd5..83926587 100644 --- a/src/annotate.cc +++ b/src/annotate.cc @@ -34,6 +34,7 @@ #include "amount.h" #include "commodity.h" #include "expr.h" +#include "scope.h" #include "annotate.h" #include "pool.h" @@ -221,6 +222,69 @@ bool annotated_commodity_t::operator==(const commodity_t& comm) const return true; } +optional +annotated_commodity_t::find_price(const optional& commodity, + const optional& moment, + const optional& oldest) const +{ + DEBUG("commodity.price.find", + "annotated_commodity_t::find_price(" << symbol() << ")"); + + datetime_t when; + if (moment) + when = *moment; + else if (epoch) + when = *epoch; + else + when = CURRENT_TIME(); + + DEBUG("commodity.price.find", "reference time: " << when); + + optional target; + if (commodity) + target = commodity; + + if (details.price) { + DEBUG("commodity.price.find", "price annotation: " << *details.price); + + if (details.has_flags(ANNOTATION_PRICE_FIXATED)) { + DEBUG("commodity.price.find", + "amount_t::value: fixated price = " << *details.price); + return price_point_t(when, *details.price); + } + else if (! target) { + DEBUG("commodity.price.find", "setting target commodity from price"); + target = details.price->commodity(); + } + } + +#if defined(DEBUG_ON) + if (target) + DEBUG("commodity.price.find", "target commodity: " << target->symbol()); +#endif + + if (details.value_expr) { +#if defined(DEBUG_ON) + if (SHOW_DEBUG("commodity.price.find")) { + ledger::_log_buffer << "valuation expr: "; + details.value_expr->dump(ledger::_log_buffer); + DEBUG("commodity.price.find", ""); + } +#endif + call_scope_t call_args(*scope_t::default_scope); + + call_args.push_back(string_value(base_symbol())); + call_args.push_back(when); + if (commodity) + call_args.push_back(string_value(commodity->symbol())); + + return price_point_t(when, const_cast(*details.value_expr) + .calc(call_args).to_amount()); + } + + return commodity_t::find_price(commodity, moment, oldest); +} + commodity_t& annotated_commodity_t::strip_annotations(const keep_details_t& what_to_keep) { @@ -262,8 +326,7 @@ annotated_commodity_t::strip_annotations(const keep_details_t& what_to_keep) new_comm = pool().find_or_create (referent(), annotation_t(keep_price ? details.price : none, keep_date ? details.date : none, - keep_tag ? details.tag : none, - details.value_expr)); + keep_tag ? details.tag : none)); // Transfer over any relevant annotation flags, as they still apply. if (new_comm->annotated) { @@ -276,8 +339,6 @@ annotated_commodity_t::strip_annotations(const keep_details_t& what_to_keep) new_details.add_flags(details.flags() & ANNOTATION_DATE_CALCULATED); if (keep_tag) new_details.add_flags(details.flags() & ANNOTATION_TAG_CALCULATED); - if (details.value_expr) - new_details.add_flags(details.flags() & ANNOTATION_VALUE_EXPR_CALCULATED); } return *new_comm; diff --git a/src/annotate.h b/src/annotate.h index eb87a1b2..f9d62c5b 100644 --- a/src/annotate.h +++ b/src/annotate.h @@ -247,6 +247,11 @@ public: return *ptr; } + optional + virtual find_price(const optional& commodity = none, + const optional& moment = none, + const optional& oldest = none) const; + virtual commodity_t& strip_annotations(const keep_details_t& what_to_keep); virtual void write_annotations(std::ostream& out, bool no_computed_annotations = false) const; -- cgit v1.2.3 From 97d68ebc8cf2bf88feffaedd6873934dc785c411 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Tue, 6 Mar 2012 03:18:10 -0600 Subject: Added "value" sub-directive for commodity directive --- src/annotate.cc | 22 +++------------------- src/annotate.h | 6 ++++++ src/commodity.cc | 26 ++++++++++++++++++++++++++ src/commodity.h | 14 ++++++++++++++ src/textual.cc | 8 ++++++++ test/baseline/dir-commodity-value.test | 24 ++++++++++++++++++++++++ 6 files changed, 81 insertions(+), 19 deletions(-) create mode 100644 test/baseline/dir-commodity-value.test (limited to 'src/annotate.cc') diff --git a/src/annotate.cc b/src/annotate.cc index 83926587..d2e4976e 100644 --- a/src/annotate.cc +++ b/src/annotate.cc @@ -34,7 +34,6 @@ #include "amount.h" #include "commodity.h" #include "expr.h" -#include "scope.h" #include "annotate.h" #include "pool.h" @@ -263,24 +262,9 @@ annotated_commodity_t::find_price(const optional& commodity, DEBUG("commodity.price.find", "target commodity: " << target->symbol()); #endif - if (details.value_expr) { -#if defined(DEBUG_ON) - if (SHOW_DEBUG("commodity.price.find")) { - ledger::_log_buffer << "valuation expr: "; - details.value_expr->dump(ledger::_log_buffer); - DEBUG("commodity.price.find", ""); - } -#endif - call_scope_t call_args(*scope_t::default_scope); - - call_args.push_back(string_value(base_symbol())); - call_args.push_back(when); - if (commodity) - call_args.push_back(string_value(commodity->symbol())); - - return price_point_t(when, const_cast(*details.value_expr) - .calc(call_args).to_amount()); - } + if (details.value_expr) + return find_price_from_expr(const_cast(*details.value_expr), + commodity, when); return commodity_t::find_price(commodity, moment, oldest); } diff --git a/src/annotate.h b/src/annotate.h index f9d62c5b..38553752 100644 --- a/src/annotate.h +++ b/src/annotate.h @@ -247,6 +247,12 @@ public: return *ptr; } + virtual optional value_expr() const { + if (details.value_expr) + return details.value_expr; + return commodity_t::value_expr(); + } + optional virtual find_price(const optional& commodity = none, const optional& moment = none, diff --git a/src/commodity.cc b/src/commodity.cc index 565204fd..0543c973 100644 --- a/src/commodity.cc +++ b/src/commodity.cc @@ -35,6 +35,7 @@ #include "commodity.h" #include "annotate.h" #include "pool.h" +#include "scope.h" namespace ledger { @@ -84,6 +85,28 @@ void commodity_t::map_prices(function fn, pool().commodity_price_history.map_prices(fn, *this, when, _oldest); } +optional +commodity_t::find_price_from_expr(expr_t& expr, + const optional& commodity, + const datetime_t& moment) const +{ +#if defined(DEBUG_ON) + if (SHOW_DEBUG("commodity.price.find")) { + ledger::_log_buffer << "valuation expr: "; + expr.dump(ledger::_log_buffer); + DEBUG("commodity.price.find", ""); + } +#endif + call_scope_t call_args(*scope_t::default_scope); + + call_args.push_back(string_value(base_symbol())); + call_args.push_back(moment); + if (commodity) + call_args.push_back(string_value(commodity->symbol())); + + return price_point_t(moment, expr.calc(call_args).to_amount()); +} + optional commodity_t::find_price(const optional& commodity, const optional& moment, @@ -125,6 +148,9 @@ commodity_t::find_price(const optional& commodity, else when = CURRENT_TIME(); + if (base->value_expr) + return find_price_from_expr(*base->value_expr, commodity, when); + optional point = target ? pool().commodity_price_history.find_price(*this, *target, when, oldest) : diff --git a/src/commodity.h b/src/commodity.h index 5cf9c53d..3d36e35e 100644 --- a/src/commodity.h +++ b/src/commodity.h @@ -47,6 +47,8 @@ #ifndef _COMMODITY_H #define _COMMODITY_H +#include "expr.h" + namespace ledger { struct keep_details_t; @@ -113,6 +115,7 @@ protected: optional note; optional smaller; optional larger; + optional value_expr; typedef std::pair, optional > optional_time_pair_t; @@ -259,6 +262,13 @@ public: base->larger = arg; } + virtual optional value_expr() const { + return base->value_expr; + } + void set_value_expr(const optional& expr = none) { + base->value_expr = expr; + } + void add_price(const datetime_t& date, const amount_t& price, const bool reflexive = true); void remove_price(const datetime_t& date, commodity_t& commodity); @@ -267,6 +277,10 @@ public: const optional& moment = none, const optional& _oldest = none); + optional + find_price_from_expr(expr_t& expr, const optional& commodity, + const datetime_t& moment) const; + optional virtual find_price(const optional& commodity = none, const optional& moment = none, diff --git a/src/textual.cc b/src/textual.cc index b1df1fb8..cf15f048 100644 --- a/src/textual.cc +++ b/src/textual.cc @@ -134,6 +134,7 @@ namespace { void commodity_directive(char * line); void commodity_alias_directive(commodity_t& comm, string alias); + void commodity_value_directive(commodity_t& comm, string expr_str); void commodity_format_directive(commodity_t& comm, string format); void commodity_nomarket_directive(commodity_t& comm); void commodity_default_directive(commodity_t& comm); @@ -1018,6 +1019,8 @@ void instance_t::commodity_directive(char * line) string keyword(q); if (keyword == "alias") commodity_alias_directive(*commodity, b); + else if (keyword == "value") + commodity_value_directive(*commodity, b); else if (keyword == "format") commodity_format_directive(*commodity, b); else if (keyword == "nomarket") @@ -1036,6 +1039,11 @@ void instance_t::commodity_alias_directive(commodity_t& comm, string alias) commodity_pool_t::current_pool->alias(alias, comm); } +void instance_t::commodity_value_directive(commodity_t& comm, string expr_str) +{ + comm.set_value_expr(expr_t(expr_str)); +} + void instance_t::commodity_format_directive(commodity_t&, string format) { // jww (2012-02-27): A format specified this way should turn off diff --git a/test/baseline/dir-commodity-value.test b/test/baseline/dir-commodity-value.test new file mode 100644 index 00000000..5e8fe789 --- /dev/null +++ b/test/baseline/dir-commodity-value.test @@ -0,0 +1,24 @@ +commodity $ + value 10 EUR + +commodity USD + alias FOO + value 25 EUR + +2012-03-06 KFC + Expenses:Food $20.00 + Assets:Cash + +2012-03-08 KFC + Expenses:Food USD 750,00 + Assets:Cash + +2012-03-10 KFC + Expenses:Food USD 750,00 + Assets:Cash + +test reg food -X EUR --now=2012-03-15 +12-Mar-06 KFC Expenses:Food 200 EUR 200 EUR +12-Mar-08 KFC Expenses:Food 18750 EUR 18950 EUR +12-Mar-10 KFC Expenses:Food 18750 EUR 37700 EUR +end test -- cgit v1.2.3 From c9f7195936090ecbe2d5b4ec88c196660ae24f81 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Fri, 9 Mar 2012 01:28:20 -0600 Subject: Added the notion of "virtual costs" --- src/annotate.cc | 7 ++++++- src/pool.cc | 1 + src/pool.h | 1 + src/post.h | 3 ++- src/py_commodity.cc | 7 ++++--- src/textual.cc | 11 +++++++++-- src/xact.cc | 2 +- 7 files changed, 24 insertions(+), 8 deletions(-) (limited to 'src/annotate.cc') diff --git a/src/annotate.cc b/src/annotate.cc index d2e4976e..1140bf0a 100644 --- a/src/annotate.cc +++ b/src/annotate.cc @@ -122,7 +122,12 @@ void annotation_t::parse(std::istream& in) else if (c == '(') { in.get(c); c = static_cast(in.peek()); - if (c == '(') { + if (c == '@') { + in.clear(); + in.seekg(pos, std::ios::beg); + break; + } + else if (c == '(') { if (value_expr) throw_(amount_error, _("Commodity specifies more than one valuation expresion")); diff --git a/src/pool.cc b/src/pool.cc index fd661fe1..1dd91e99 100644 --- a/src/pool.cc +++ b/src/pool.cc @@ -246,6 +246,7 @@ cost_breakdown_t commodity_pool_t::exchange(const amount_t& amount, const amount_t& cost, const bool is_per_unit, + const bool add_price, const optional& moment, const optional& tag) { diff --git a/src/pool.h b/src/pool.h index 7203bc20..b7921f59 100644 --- a/src/pool.h +++ b/src/pool.h @@ -119,6 +119,7 @@ public: cost_breakdown_t exchange(const amount_t& amount, const amount_t& cost, const bool is_per_unit = false, + const bool add_price = true, const optional& moment = none, const optional& tag = none); diff --git a/src/post.h b/src/post.h index 217f5509..7d93b1cc 100644 --- a/src/post.h +++ b/src/post.h @@ -58,7 +58,8 @@ public: #define POST_COST_CALCULATED 0x0080 // posting's cost was calculated #define POST_COST_IN_FULL 0x0100 // cost specified using @@ #define POST_COST_FIXATED 0x0200 // cost is fixed using = indicator -#define POST_ANONYMIZED 0x0400 // a temporary, anonymous posting +#define POST_COST_VIRTUAL 0x0400 // cost is virtualized: (@) +#define POST_ANONYMIZED 0x0800 // a temporary, anonymous posting xact_t * xact; // only set for posts of regular xacts account_t * account; diff --git a/src/py_commodity.cc b/src/py_commodity.cc index 25e5b918..c75b5e64 100644 --- a/src/py_commodity.cc +++ b/src/py_commodity.cc @@ -96,14 +96,15 @@ namespace { pool.exchange(commodity, per_unit_cost, moment); } - cost_breakdown_t py_exchange_5(commodity_pool_t& pool, + cost_breakdown_t py_exchange_7(commodity_pool_t& pool, const amount_t& amount, const amount_t& cost, const bool is_per_unit, + const bool add_prices, const boost::optional& moment, const boost::optional& tag) { - return pool.exchange(amount, cost, is_per_unit, moment, tag); + return pool.exchange(amount, cost, is_per_unit, add_prices, moment, tag); } commodity_t * py_pool_getitem(commodity_pool_t& pool, const string& symbol) @@ -280,7 +281,7 @@ void export_commodity() .def("exchange", py_exchange_2, with_custodian_and_ward<1, 2>()) .def("exchange", py_exchange_3, with_custodian_and_ward<1, 2>()) - .def("exchange", py_exchange_5) + .def("exchange", py_exchange_7) .def("parse_price_directive", &commodity_pool_t::parse_price_directive) .def("parse_price_expression", &commodity_pool_t::parse_price_expression, diff --git a/src/textual.cc b/src/textual.cc index 66972fb3..a8cb844b 100644 --- a/src/textual.cc +++ b/src/textual.cc @@ -1447,12 +1447,16 @@ post_t * instance_t::parse_post(char * line, // Parse the optional cost (@ PER-UNIT-COST, @@ TOTAL-COST) - if (*next == '@') { + if (*next == '@' || (*next == '(' && *(next + 1) == '@')) { DEBUG("textual.parse", "line " << context.linenum << ": " << "Found a price indicator"); - bool per_unit = true; + if (*next == '(') { + post->add_flags(POST_COST_VIRTUAL); + ++next; + } + bool per_unit = true; if (*++next == '@') { per_unit = false; post->add_flags(POST_COST_IN_FULL); @@ -1460,6 +1464,9 @@ post_t * instance_t::parse_post(char * line, << "And it's for a total price"); } + if (post->has_flags(POST_COST_VIRTUAL) && *(next + 1) == ')') + ++next; + beg = static_cast(++next - line); p = skip_ws(next); diff --git a/src/xact.cc b/src/xact.cc index 4e43e680..4e8e56fa 100644 --- a/src/xact.cc +++ b/src/xact.cc @@ -269,7 +269,7 @@ bool xact_base_t::finalize() cost_breakdown_t breakdown = commodity_pool_t::current_pool->exchange - (post->amount, *post->cost, false, + (post->amount, *post->cost, false, ! post->has_flags(POST_COST_VIRTUAL), datetime_t(date(), time_duration(0, 0, 0, 0))); if (post->amount.has_annotation() && post->amount.annotation().price) { -- cgit v1.2.3 From 080c1d9a2d0f3013a4d26879a3e98cfa62ef3e48 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sat, 10 Mar 2012 02:27:33 -0600 Subject: Added syntactic sugar for lot pricing: {{$500.00}} --- src/amount.cc | 12 ++++++++---- src/annotate.cc | 20 +++++++++++++++++--- src/annotate.h | 7 ++++--- test/baseline/feat-annotations.test | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 10 deletions(-) create mode 100644 test/baseline/feat-annotations.test (limited to 'src/annotate.cc') diff --git a/src/amount.cc b/src/amount.cc index d1aa1655..46eb5531 100644 --- a/src/amount.cc +++ b/src/amount.cc @@ -1065,10 +1065,6 @@ bool amount_t::parse(std::istream& in, const parse_flags_t& flags) if (! commodity_) commodity_ = commodity_pool_t::current_pool->create(symbol); assert(commodity_); - - if (details) - commodity_ = - commodity_pool_t::current_pool->find_or_create(*commodity_, details); } // Quickly scan through and verify the correctness of the amount's use of @@ -1204,6 +1200,14 @@ bool amount_t::parse(std::istream& in, const parse_flags_t& flags) if (! flags.has_flags(PARSE_NO_REDUCE)) in_place_reduce(); // will not throw an exception + if (commodity_ && details) { + if (details.has_flags(ANNOTATION_PRICE_NOT_PER_UNIT)) { + assert(details.price); + *details.price /= this->abs(); + } + set_commodity(*commodity_pool_t::current_pool->find_or_create(*commodity_, details)); + } + VERIFY(valid()); return true; diff --git a/src/annotate.cc b/src/annotate.cc index 1140bf0a..d2c7f983 100644 --- a/src/annotate.cc +++ b/src/annotate.cc @@ -88,6 +88,12 @@ void annotation_t::parse(std::istream& in) throw_(amount_error, _("Commodity specifies more than one price")); in.get(c); + c = static_cast(in.peek()); + if (c == '{') { + in.get(c); + add_flags(ANNOTATION_PRICE_NOT_PER_UNIT); + } + c = peek_next_nonws(in); if (c == '=') { in.get(c); @@ -95,10 +101,18 @@ void annotation_t::parse(std::istream& in) } READ_INTO(in, buf, 255, c, c != '}'); - if (c == '}') + if (c == '}') { in.get(c); - else - throw_(amount_error, _("Commodity price lacks closing brace")); + if (has_flags(ANNOTATION_PRICE_NOT_PER_UNIT)) { + c = static_cast(in.peek()); + if (c != '}') + throw_(amount_error, _("Commodity lot price lacks double closing brace")); + else + in.get(c); + } + } else { + throw_(amount_error, _("Commodity lot price lacks closing brace")); + } amount_t temp; temp.parse(buf, PARSE_NO_MIGRATE); diff --git a/src/annotate.h b/src/annotate.h index 22c3d8ad..606c6a60 100644 --- a/src/annotate.h +++ b/src/annotate.h @@ -55,9 +55,10 @@ struct annotation_t : public supports_flags<>, { #define ANNOTATION_PRICE_CALCULATED 0x01 #define ANNOTATION_PRICE_FIXATED 0x02 -#define ANNOTATION_DATE_CALCULATED 0x04 -#define ANNOTATION_TAG_CALCULATED 0x08 -#define ANNOTATION_VALUE_EXPR_CALCULATED 0x10 +#define ANNOTATION_PRICE_NOT_PER_UNIT 0x04 +#define ANNOTATION_DATE_CALCULATED 0x08 +#define ANNOTATION_TAG_CALCULATED 0x10 +#define ANNOTATION_VALUE_EXPR_CALCULATED 0x20 optional price; optional date; diff --git a/test/baseline/feat-annotations.test b/test/baseline/feat-annotations.test new file mode 100644 index 00000000..18f5d7d9 --- /dev/null +++ b/test/baseline/feat-annotations.test @@ -0,0 +1,37 @@ +2012-03-09 KFC + Expenses:Food 10 CHIK @ $50 + Assets:Cash + +2012-03-09 KFC + Assets:Cash $75 + Expenses:Food -10 CHIK {{$50}} @ $75 + Equity:Capital Gains $-25 + +2012-03-09 KFC + Expenses:Food 10 CHIK + Assets:Cash $-50 + +2012-03-09 KFC + Assets:Cash $75 + Expenses:Food -10 CHIK {{$50}} + Equity:Capital Gains $-25 + +test print +2012/03/09 KFC + Expenses:Food 10 CHIK @ $50 + Assets:Cash + +2012/03/09 KFC + Assets:Cash $75 + Expenses:Food -10 CHIK {$5} @ $75 + Equity:Capital Gains $-25 + +2012/03/09 KFC + Expenses:Food 10 CHIK + Assets:Cash $-50 + +2012/03/09 KFC + Assets:Cash $75 + Expenses:Food -10 CHIK {$5} + Equity:Capital Gains $-25 +end test -- cgit v1.2.3 From 363670d35bf451ff8ce636c071da73a0d93c514a Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sun, 11 Mar 2012 03:55:25 -0500 Subject: Tighten up argument passing related to fn_market() --- src/amount.cc | 19 +++++------ src/amount.h | 8 +++-- src/annotate.cc | 16 +++++----- src/annotate.h | 6 ++-- src/balance.cc | 4 +-- src/balance.h | 4 +-- src/commodity.cc | 78 ++++++++++++++++++++++------------------------ src/commodity.h | 22 ++++++------- src/history.cc | 55 ++++++++++++++++---------------- src/history.h | 23 +++++++------- src/pool.h | 3 +- src/py_amount.cc | 6 ++-- src/py_balance.cc | 6 ++-- src/py_value.cc | 6 ++-- src/quotes.cc | 2 +- src/quotes.h | 2 +- src/report.cc | 9 +++--- src/value.cc | 16 +++++----- src/value.h | 10 +++--- test/regress/25A099C9.test | 12 +++---- test/unit/t_commodity.cc | 6 ++-- 21 files changed, 153 insertions(+), 160 deletions(-) (limited to 'src/annotate.cc') diff --git a/src/amount.cc b/src/amount.cc index 46eb5531..5fa58528 100644 --- a/src/amount.cc +++ b/src/amount.cc @@ -728,16 +728,16 @@ void amount_t::in_place_unreduce() } optional -amount_t::value(const optional& moment, - const optional& in_terms_of) const +amount_t::value(const datetime_t& moment, + const commodity_t * in_terms_of) const { if (quantity) { #if defined(DEBUG_ON) DEBUG("commodity.price.find", "amount_t::value of " << commodity().symbol()); - if (moment) + if (! moment.is_not_a_date_time()) DEBUG("commodity.price.find", - "amount_t::value: moment = " << *moment); + "amount_t::value: moment = " << moment); if (in_terms_of) DEBUG("commodity.price.find", "amount_t::value: in_terms_of = " << in_terms_of->symbol()); @@ -745,7 +745,7 @@ amount_t::value(const optional& moment, if (has_commodity() && (in_terms_of || ! commodity().has_flags(COMMODITY_PRIMARY))) { optional point; - optional comm(in_terms_of); + const commodity_t * comm(in_terms_of); if (has_annotation() && annotation().price) { if (annotation().has_flags(ANNOTATION_PRICE_FIXATED)) { @@ -755,7 +755,7 @@ amount_t::value(const optional& moment, "amount_t::value: fixated price = " << point->price); } else if (! comm) { - comm = annotation().price->commodity(); + comm = annotation().price->commodity_ptr(); } } @@ -869,15 +869,10 @@ bool amount_t::fits_in_long() const commodity_t * amount_t::commodity_ptr() const { - return (has_commodity() ? + return (commodity_ ? commodity_ : commodity_pool_t::current_pool->null_commodity); } -commodity_t& amount_t::commodity() const -{ - return *commodity_ptr(); -} - bool amount_t::has_commodity() const { return commodity_ && commodity_ != commodity_->pool().null_commodity; diff --git a/src/amount.h b/src/amount.h index 7bf4fe51..903a01cd 100644 --- a/src/amount.h +++ b/src/amount.h @@ -404,8 +404,8 @@ public: $100.00. */ optional - value(const optional& moment = none, - const optional& in_terms_of = none) const; + value(const datetime_t& moment = datetime_t(), + const commodity_t * in_terms_of = NULL) const; optional price() const; @@ -534,7 +534,9 @@ public: useful for accessing just the numeric portion of an amount. */ commodity_t * commodity_ptr() const; - commodity_t& commodity() const; + commodity_t& commodity() const { + return *commodity_ptr(); + } bool has_commodity() const; void set_commodity(commodity_t& comm) { diff --git a/src/annotate.cc b/src/annotate.cc index d2c7f983..2b118e76 100644 --- a/src/annotate.cc +++ b/src/annotate.cc @@ -241,16 +241,16 @@ bool annotated_commodity_t::operator==(const commodity_t& comm) const } optional -annotated_commodity_t::find_price(const optional& commodity, - const optional& moment, - const optional& oldest) const +annotated_commodity_t::find_price(const commodity_t * commodity, + const datetime_t& moment, + const datetime_t& oldest) const { DEBUG("commodity.price.find", "annotated_commodity_t::find_price(" << symbol() << ")"); datetime_t when; - if (moment) - when = *moment; + if (! moment.is_not_a_date_time()) + when = moment; else if (epoch) when = *epoch; else @@ -258,7 +258,7 @@ annotated_commodity_t::find_price(const optional& commodity, DEBUG("commodity.price.find", "reference time: " << when); - optional target; + const commodity_t * target = NULL; if (commodity) target = commodity; @@ -272,7 +272,7 @@ annotated_commodity_t::find_price(const optional& commodity, } else if (! target) { DEBUG("commodity.price.find", "setting target commodity from price"); - target = details.price->commodity(); + target = details.price->commodity_ptr(); } } @@ -285,7 +285,7 @@ annotated_commodity_t::find_price(const optional& commodity, return find_price_from_expr(const_cast(*details.value_expr), commodity, when); - return commodity_t::find_price(commodity, moment, oldest); + return commodity_t::find_price(target, moment, oldest); } commodity_t& diff --git a/src/annotate.h b/src/annotate.h index 606c6a60..044ebc4d 100644 --- a/src/annotate.h +++ b/src/annotate.h @@ -256,9 +256,9 @@ public: } optional - virtual find_price(const optional& commodity = none, - const optional& moment = none, - const optional& oldest = none) const; + virtual find_price(const commodity_t * commodity = NULL, + const datetime_t& moment = datetime_t(), + const datetime_t& oldest = datetime_t()) const; virtual commodity_t& strip_annotations(const keep_details_t& what_to_keep); virtual void write_annotations(std::ostream& out, diff --git a/src/balance.cc b/src/balance.cc index 08368dd8..f87e8bbd 100644 --- a/src/balance.cc +++ b/src/balance.cc @@ -185,8 +185,8 @@ balance_t& balance_t::operator/=(const amount_t& amt) } optional -balance_t::value(const optional& moment, - const optional& in_terms_of) const +balance_t::value(const datetime_t& moment, + const commodity_t * in_terms_of) const { balance_t temp; bool resolved = false; diff --git a/src/balance.h b/src/balance.h index 921f87ef..5f0d52ed 100644 --- a/src/balance.h +++ b/src/balance.h @@ -384,8 +384,8 @@ public: } optional - value(const optional& moment = none, - const optional& in_terms_of = none) const; + value(const datetime_t& moment = datetime_t(), + const commodity_t * in_terms_of = NULL) const; /** * Truth tests. An balance may be truth test in two ways: diff --git a/src/commodity.cc b/src/commodity.cc index 963fb646..8f0dc100 100644 --- a/src/commodity.cc +++ b/src/commodity.cc @@ -71,12 +71,12 @@ void commodity_t::remove_price(const datetime_t& date, commodity_t& commodity) } void commodity_t::map_prices(function fn, - const optional& moment, - const optional& _oldest) + const datetime_t& moment, + const datetime_t& _oldest) { datetime_t when; - if (moment) - when = *moment; + if (! moment.is_not_a_date_time()) + when = moment; else if (epoch) when = *epoch; else @@ -86,8 +86,7 @@ void commodity_t::map_prices(function fn, } optional -commodity_t::find_price_from_expr(expr_t& expr, - const optional& commodity, +commodity_t::find_price_from_expr(expr_t& expr, const commodity_t * commodity, const datetime_t& moment) const { #if defined(DEBUG_ON) @@ -114,31 +113,30 @@ commodity_t::find_price_from_expr(expr_t& expr, } optional -commodity_t::find_price(const optional& commodity, - const optional& moment, - const optional& oldest) const +commodity_t::find_price(const commodity_t * commodity, + const datetime_t& moment, + const datetime_t& oldest) const { DEBUG("commodity.price.find", "commodity_t::find_price(" << symbol() << ")"); - optional target; + const commodity_t * target = NULL; if (commodity) target = commodity; else if (pool().default_commodity) - target = *pool().default_commodity; + target = &*pool().default_commodity; - if (target && *this == *target) + if (target && this == target) return none; - optional - entry(base_t::memoized_price_entry(moment, oldest, - commodity ? &(*commodity) : NULL)); + base_t::memoized_price_entry entry(moment, oldest, + commodity ? commodity : NULL); DEBUG("commodity.price.find", "looking for memoized args: " - << (moment ? format_datetime(*moment) : "NONE") << ", " - << (oldest ? format_datetime(*oldest) : "NONE") << ", " + << (! moment.is_not_a_date_time() ? format_datetime(moment) : "NONE") << ", " + << (! oldest.is_not_a_date_time() ? format_datetime(oldest) : "NONE") << ", " << (commodity ? commodity->symbol() : "NONE")); { - base_t::memoized_price_map::iterator i = base->price_map.find(*entry); + base_t::memoized_price_map::iterator i = base->price_map.find(entry); if (i != base->price_map.end()) { DEBUG("commodity.price.find", "found! returning: " << ((*i).second ? (*i).second->price : amount_t(0L))); @@ -147,8 +145,8 @@ commodity_t::find_price(const optional& commodity, } datetime_t when; - if (moment) - when = *moment; + if (! moment.is_not_a_date_time()) + when = moment; else if (epoch) when = *epoch; else @@ -157,40 +155,40 @@ commodity_t::find_price(const optional& commodity, if (base->value_expr) return find_price_from_expr(*base->value_expr, commodity, when); - optional point = - target ? - pool().commodity_price_history.find_price(*this, *target, when, oldest) : - pool().commodity_price_history.find_price(*this, when, oldest); - - if (entry) { - if (base->price_map.size() > base_t::max_price_map_size) { - DEBUG("history.find", - "price map has grown too large, clearing it by half"); - for (std::size_t i = 0; i < base_t::max_price_map_size >> 1; i++) - base->price_map.erase(base->price_map.begin()); - } + optional + point(target ? + pool().commodity_price_history.find_price(*this, *target, + when, oldest) : + pool().commodity_price_history.find_price(*this, when, oldest)); + // Record this price point in the memoization map + if (base->price_map.size() > base_t::max_price_map_size) { DEBUG("history.find", - "remembered: " << (point ? point->price : amount_t(0L))); - base->price_map.insert(base_t::memoized_price_map::value_type(*entry, point)); + "price map has grown too large, clearing it by half"); + for (std::size_t i = 0; i < base_t::max_price_map_size >> 1; i++) + base->price_map.erase(base->price_map.begin()); } + DEBUG("history.find", + "remembered: " << (point ? point->price : amount_t(0L))); + base->price_map.insert(base_t::memoized_price_map::value_type(entry, point)); + return point; } optional commodity_t::check_for_updated_price(const optional& point, - const optional& moment, - const optional& in_terms_of) + const datetime_t& moment, + const commodity_t* in_terms_of) { if (pool().get_quotes && ! has_flags(COMMODITY_NOMARKET)) { bool exceeds_leeway = true; if (point) { time_duration_t::sec_type seconds_diff; - if (moment) { - seconds_diff = (*moment - point->when).total_seconds(); - DEBUG("commodity.download", "moment = " << *moment); + if (! moment.is_not_a_date_time()) { + seconds_diff = (moment - point->when).total_seconds(); + DEBUG("commodity.download", "moment = " << moment); DEBUG("commodity.download", "slip.moment = " << seconds_diff); } else { seconds_diff = (TRUE_CURRENT_TIME() - point->when).total_seconds(); @@ -209,7 +207,7 @@ commodity_t::check_for_updated_price(const optional& point, pool().get_commodity_quote(*this, in_terms_of)) { if (! in_terms_of || (quote->price.has_commodity() && - quote->price.commodity() == *in_terms_of)) + quote->price.commodity_ptr() == in_terms_of)) return quote; } } diff --git a/src/commodity.h b/src/commodity.h index 1358966e..bd1aedb9 100644 --- a/src/commodity.h +++ b/src/commodity.h @@ -117,12 +117,12 @@ protected: optional larger; optional value_expr; - typedef tuple, - optional, commodity_t *> memoized_price_entry; + typedef tuple memoized_price_entry; typedef std::map > memoized_price_map; - static const std::size_t max_price_map_size = 16; + static const std::size_t max_price_map_size = 8; mutable memoized_price_map price_map; public: @@ -272,22 +272,22 @@ public: void remove_price(const datetime_t& date, commodity_t& commodity); void map_prices(function fn, - const optional& moment = none, - const optional& _oldest = none); + const datetime_t& moment = datetime_t(), + const datetime_t& _oldest = datetime_t()); optional - find_price_from_expr(expr_t& expr, const optional& commodity, + find_price_from_expr(expr_t& expr, const commodity_t * commodity, const datetime_t& moment) const; optional - virtual find_price(const optional& commodity = none, - const optional& moment = none, - const optional& oldest = none) const; + virtual find_price(const commodity_t * commodity = NULL, + const datetime_t& moment = datetime_t(), + const datetime_t& oldest = datetime_t()) const; optional check_for_updated_price(const optional& point, - const optional& moment, - const optional& in_terms_of); + const datetime_t& moment, + const commodity_t * in_terms_of); commodity_t& nail_down(const expr_t& expr); diff --git a/src/history.cc b/src/history.cc index 83326728..22ac4494 100644 --- a/src/history.cc +++ b/src/history.cc @@ -52,15 +52,15 @@ public: PricePointMap price_point; PriceRatioMap ratios; - datetime_t reftime; - optional oldest; + datetime_t reftime; + datetime_t oldest; recent_edge_weight() { } - recent_edge_weight(EdgeWeightMap _weight, - PricePointMap _price_point, - PriceRatioMap _ratios, - datetime_t _reftime, - const optional& _oldest = none) + recent_edge_weight(EdgeWeightMap _weight, + PricePointMap _price_point, + PriceRatioMap _ratios, + const datetime_t& _reftime, + const datetime_t& _oldest = datetime_t()) : weight(_weight), price_point(_price_point), ratios(_ratios), reftime(_reftime), oldest(_oldest) { } @@ -69,8 +69,8 @@ public: { #if defined(DEBUG_ON) DEBUG("history.find", " reftime = " << reftime); - if (oldest) { - DEBUG("history.find", " oldest = " << *oldest); + if (! oldest.is_not_a_date_time()) { + DEBUG("history.find", " oldest = " << oldest); } #endif @@ -88,7 +88,7 @@ public: --low; assert(((*low).first <= reftime)); - if (oldest && (*low).first < *oldest) { + if (! oldest.is_not_a_date_time() && (*low).first < oldest) { DEBUG("history.find", " edge is out of range"); return false; } @@ -170,9 +170,9 @@ void commodity_history_t::remove_price(const commodity_t& source, void commodity_history_t::map_prices(function fn, - const commodity_t& source, - const datetime_t& moment, - const optional& oldest) + const commodity_t& source, + const datetime_t& moment, + const datetime_t& oldest) { vertex_descriptor sv = vertex(*source.graph_index(), price_graph); @@ -193,7 +193,7 @@ void commodity_history_t::map_prices(function= *oldest) && when <= moment) { + if ((oldest.is_not_a_date_time() || when >= oldest) && when <= moment) { if (pair.second.commodity() == source) { amount_t price(pair.second); price.in_place_invert(); @@ -209,9 +209,9 @@ void commodity_history_t::map_prices(function -commodity_history_t::find_price(const commodity_t& source, - const datetime_t& moment, - const optional& oldest) +commodity_history_t::find_price(const commodity_t& source, + const datetime_t& moment, + const datetime_t& oldest) { vertex_descriptor sv = vertex(*source.graph_index(), price_graph); @@ -270,10 +270,10 @@ commodity_history_t::find_price(const commodity_t& source, } optional -commodity_history_t::find_price(const commodity_t& source, - const commodity_t& target, - const datetime_t& moment, - const optional& oldest) +commodity_history_t::find_price(const commodity_t& source, + const commodity_t& target, + const datetime_t& moment, + const datetime_t& oldest) { vertex_descriptor sv = vertex(*source.graph_index(), price_graph); vertex_descriptor tv = vertex(*target.graph_index(), price_graph); @@ -402,17 +402,16 @@ private: Name name; }; -void commodity_history_t::print_map(std::ostream& out, - const optional& moment) +void commodity_history_t::print_map(std::ostream& out, const datetime_t& moment) { - if (moment) { + if (moment.is_not_a_date_time()) { + write_graphviz(out, price_graph, + label_writer(get(vertex_name, price_graph))); + } else { FGraph fg(price_graph, recent_edge_weight - (get(edge_weight, price_graph), pricemap, ratiomap, *moment)); + (get(edge_weight, price_graph), pricemap, ratiomap, moment)); write_graphviz(out, fg, label_writer(get(vertex_name, fg))); - } else { - write_graphviz(out, price_graph, - label_writer(get(vertex_name, price_graph))); } } diff --git a/src/history.h b/src/history.h index 920feec6..71cbad0c 100644 --- a/src/history.h +++ b/src/history.h @@ -111,23 +111,22 @@ public: const datetime_t& date); void map_prices(function fn, - const commodity_t& source, - const datetime_t& moment, - const optional& _oldest = none); + const commodity_t& source, + const datetime_t& moment, + const datetime_t& _oldest = datetime_t()); optional - find_price(const commodity_t& source, - const datetime_t& moment, - const optional& oldest = none); + find_price(const commodity_t& source, + const datetime_t& moment, + const datetime_t& oldest = datetime_t()); optional - find_price(const commodity_t& source, - const commodity_t& target, - const datetime_t& moment, - const optional& oldest = none); + find_price(const commodity_t& source, + const commodity_t& target, + const datetime_t& moment, + const datetime_t& oldest = datetime_t()); - void print_map(std::ostream& out, - const optional& moment = none); + void print_map(std::ostream& out, const datetime_t& moment = datetime_t()); }; } // namespace ledger diff --git a/src/pool.h b/src/pool.h index b7921f59..eb630781 100644 --- a/src/pool.h +++ b/src/pool.h @@ -83,13 +83,12 @@ public: bool get_quotes; // --download function - (commodity_t& commodity, const optional& in_terms_of)> + (commodity_t& commodity, const commodity_t * in_terms_of)> get_commodity_quote; static shared_ptr current_pool; explicit commodity_pool_t(); - virtual ~commodity_pool_t() { TRACE_DTOR(commodity_pool_t); } diff --git a/src/py_amount.cc b/src/py_amount.cc index 25ec8e26..ea69dec5 100644 --- a/src/py_amount.cc +++ b/src/py_amount.cc @@ -48,12 +48,12 @@ namespace { return amount.value(CURRENT_TIME()); } boost::optional py_value_1(const amount_t& amount, - commodity_t& in_terms_of) { + const commodity_t * in_terms_of) { return amount.value(CURRENT_TIME(), in_terms_of); } boost::optional py_value_2(const amount_t& amount, - commodity_t& in_terms_of, - datetime_t& moment) { + const commodity_t * in_terms_of, + const datetime_t& moment) { return amount.value(moment, in_terms_of); } diff --git a/src/py_balance.cc b/src/py_balance.cc index 38941832..2ae546f1 100644 --- a/src/py_balance.cc +++ b/src/py_balance.cc @@ -48,12 +48,12 @@ namespace { return balance.value(CURRENT_TIME()); } boost::optional py_value_1(const balance_t& balance, - commodity_t& in_terms_of) { + const commodity_t * in_terms_of) { return balance.value(CURRENT_TIME(), in_terms_of); } boost::optional py_value_2(const balance_t& balance, - commodity_t& in_terms_of, - datetime_t& moment) { + const commodity_t * in_terms_of, + const datetime_t& moment) { return balance.value(moment, in_terms_of); } diff --git a/src/py_value.cc b/src/py_value.cc index 78301acd..efeb4340 100644 --- a/src/py_value.cc +++ b/src/py_value.cc @@ -51,12 +51,12 @@ namespace { return value.value(CURRENT_TIME()); } boost::optional py_value_1(const value_t& value, - commodity_t& in_terms_of) { + const commodity_t * in_terms_of) { return value.value(CURRENT_TIME(), in_terms_of); } boost::optional py_value_2(const value_t& value, - commodity_t& in_terms_of, - datetime_t& moment) { + const commodity_t * in_terms_of, + const datetime_t& moment) { return value.value(moment, in_terms_of); } diff --git a/src/quotes.cc b/src/quotes.cc index b29eb8bd..c33e0826 100644 --- a/src/quotes.cc +++ b/src/quotes.cc @@ -40,7 +40,7 @@ namespace ledger { optional commodity_quote_from_script(commodity_t& commodity, - const optional& exchange_commodity) + const commodity_t * exchange_commodity) { DEBUG("commodity.download", "downloading quote for symbol " << commodity.symbol()); #if defined(DEBUG_ON) diff --git a/src/quotes.h b/src/quotes.h index 52092fbc..56740e47 100644 --- a/src/quotes.h +++ b/src/quotes.h @@ -46,7 +46,7 @@ namespace ledger { optional commodity_quote_from_script(commodity_t& commodity, - const optional& exchange_commodity); + const commodity_t * exchange_commodity); } // namespace ledger diff --git a/src/report.cc b/src/report.cc index 8205c1dd..a3abcb98 100644 --- a/src/report.cc +++ b/src/report.cc @@ -532,12 +532,13 @@ value_t report_t::fn_should_bold(call_scope_t& scope) value_t report_t::fn_market(call_scope_t& args) { - optional moment = (args.has(1) ? - args.get(1) : - optional()); value_t result; value_t arg0 = args[0]; + datetime_t moment; + if (args.has(1)) + moment = args.get(1); + if (arg0.is_string()) { amount_t tmp(1L); commodity_t * commodity = @@ -962,7 +963,7 @@ value_t report_t::pricemap_command(call_scope_t& args) std::ostream& out(output_stream); commodity_pool_t::current_pool->commodity_price_history.print_map (out, args.has(0) ? - optional(datetime_t(parse_date(args.get(0)))) : none); + datetime_t(parse_date(args.get(0))) : datetime_t()); return true; } diff --git a/src/value.cc b/src/value.cc index c4e7170d..cae2a356 100644 --- a/src/value.cc +++ b/src/value.cc @@ -1399,8 +1399,8 @@ bool value_t::is_zero() const return false; } -value_t value_t::value(const optional& moment, - const optional& in_terms_of) const +value_t value_t::value(const datetime_t& moment, + const commodity_t * in_terms_of) const { switch (type()) { case INTEGER: @@ -1432,9 +1432,9 @@ value_t value_t::value(const optional& moment, return NULL_VALUE; } -value_t value_t::exchange_commodities(const std::string& commodities, - const bool add_prices, - const optional& moment) +value_t value_t::exchange_commodities(const std::string& commodities, + const bool add_prices, + const datetime_t& moment) { if (type() == SEQUENCE) { value_t temp; @@ -1447,7 +1447,7 @@ value_t value_t::exchange_commodities(const std::string& commodities, // expression, skip the expensive logic below. if (commodities.find(',') == string::npos && commodities.find('=') == string::npos) - return value(moment, *commodity_pool_t::current_pool->find_or_create(commodities)); + return value(moment, commodity_pool_t::current_pool->find_or_create(commodities)); std::vector comms; std::vector force; @@ -1479,7 +1479,7 @@ value_t value_t::exchange_commodities(const std::string& commodities, break; DEBUG("commodity.exchange", "Referent doesn't match, pricing..."); - if (optional val = as_amount_lval().value(moment, *comm)) { + if (optional val = as_amount_lval().value(moment, comm)) { DEBUG("commodity.exchange", "Re-priced amount is: " << *val); return *val; } @@ -1502,7 +1502,7 @@ value_t value_t::exchange_commodities(const std::string& commodities, temp += pair.second; } else { DEBUG("commodity.exchange", "Referent doesn't match, pricing..."); - if (optional val = pair.second.value(moment, *comm)) { + if (optional val = pair.second.value(moment, comm)) { DEBUG("commodity.exchange", "Re-priced member amount is: " << *val); temp += *val; repriced = true; diff --git a/src/value.h b/src/value.h index df075843..a95968c2 100644 --- a/src/value.h +++ b/src/value.h @@ -477,12 +477,12 @@ public: void in_place_unreduce(); // exists for efficiency's sake // Return the "market value" of a given value at a specific time. - value_t value(const optional& moment = none, - const optional& in_terms_of = none) const; + value_t value(const datetime_t& moment = datetime_t(), + const commodity_t * in_terms_of = NULL) const; - value_t exchange_commodities(const std::string& commodities, - const bool add_prices = false, - const optional& moment = none); + value_t exchange_commodities(const std::string& commodities, + const bool add_prices = false, + const datetime_t& moment = datetime_t()); /** * Truth tests. diff --git a/test/regress/25A099C9.test b/test/regress/25A099C9.test index c43deb21..418b77c8 100644 --- a/test/regress/25A099C9.test +++ b/test/regress/25A099C9.test @@ -2,16 +2,16 @@ test -f $sourcepath/src/amount.h reg -> 7 __ERROR__ While parsing file "$sourcepath/src/amount.h", line 66: Error: No quantity specified for amount -While parsing file "$sourcepath/src/amount.h", line 732: +While parsing file "$sourcepath/src/amount.h", line 734: Error: Invalid date/time: line amount_t amoun -While parsing file "$sourcepath/src/amount.h", line 738: +While parsing file "$sourcepath/src/amount.h", line 740: Error: Invalid date/time: line string amount_ -While parsing file "$sourcepath/src/amount.h", line 744: +While parsing file "$sourcepath/src/amount.h", line 746: Error: Invalid date/time: line string amount_ -While parsing file "$sourcepath/src/amount.h", line 750: +While parsing file "$sourcepath/src/amount.h", line 752: Error: Invalid date/time: line string amount_ -While parsing file "$sourcepath/src/amount.h", line 756: +While parsing file "$sourcepath/src/amount.h", line 758: Error: Invalid date/time: line std::ostream& -While parsing file "$sourcepath/src/amount.h", line 763: +While parsing file "$sourcepath/src/amount.h", line 765: Error: Invalid date/time: line std::istream& end test diff --git a/test/unit/t_commodity.cc b/test/unit/t_commodity.cc index 6a6f27aa..8caeb694 100644 --- a/test/unit/t_commodity.cc +++ b/test/unit/t_commodity.cc @@ -92,18 +92,18 @@ BOOST_AUTO_TEST_CASE(testPriceHistory) BOOST_CHECK_EQUAL(string("$2124.122"), amt->to_fullstring()); #endif - amt = x1.value(CURRENT_TIME(), euro); + amt = x1.value(CURRENT_TIME(), &euro); BOOST_CHECK(amt); BOOST_CHECK_EQUAL(string("EUR 1787.50"), amt->rounded().to_string()); // Add a newer Euro pricing aapl.add_price(jan17_07, amount_t("EUR 23.00")); - amt = x1.value(CURRENT_TIME(), euro); + amt = x1.value(CURRENT_TIME(), &euro); BOOST_CHECK(amt); BOOST_CHECK_EQUAL(string("EUR 2302.30"), amt->to_string()); - amt = x1.value(CURRENT_TIME(), cad); + amt = x1.value(CURRENT_TIME(), &cad); BOOST_CHECK(amt); BOOST_CHECK_EQUAL(string("CAD 3223.22"), amt->to_string()); #endif // NOT_FOR_PYTHON -- cgit v1.2.3 From 47d7f5a43b286b3c736e21480d84caf75cea885f Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sun, 18 Mar 2012 02:16:41 -0500 Subject: Fix problem with -H and lack of pricing info Fixes #691 --- src/annotate.cc | 6 +++++- src/annotate.h | 9 +++++---- src/pool.cc | 37 +++++++++++++++---------------------- test/regress/96A8E4A1.test | 10 ++++++++++ 4 files changed, 35 insertions(+), 27 deletions(-) create mode 100644 test/regress/96A8E4A1.test (limited to 'src/annotate.cc') diff --git a/src/annotate.cc b/src/annotate.cc index 2b118e76..25f0e582 100644 --- a/src/annotate.cc +++ b/src/annotate.cc @@ -56,6 +56,7 @@ bool annotation_t::operator<(const annotation_t& rhs) const return true; if (price->commodity().symbol() > rhs.price->commodity().symbol()) return false; + if (*price < *rhs.price) return true; if (*price > *rhs.price) return false; } @@ -68,9 +69,12 @@ bool annotation_t::operator<(const annotation_t& rhs) const if (*tag > *rhs.tag) return false; } if (value_expr) { + DEBUG("annotate.less", "Comparing (" << value_expr->text() + << ") < (" << rhs.value_expr->text()); if (value_expr->text() < rhs.value_expr->text()) return true; - if (value_expr->text() > rhs.value_expr->text()) return false; + //if (value_expr->text() > rhs.value_expr->text()) return false; } + return false; } diff --git a/src/annotate.h b/src/annotate.h index 044ebc4d..163ffac5 100644 --- a/src/annotate.h +++ b/src/annotate.h @@ -72,7 +72,7 @@ struct annotation_t : public supports_flags<>, : supports_flags<>(), price(_price), date(_date), tag(_tag), value_expr(_value_expr) { TRACE_CTOR(annotation_t, - "const optional& + date_t + string + expr_t"); + "optional + date_t + string + expr_t"); } annotation_t(const annotation_t& other) : supports_flags<>(other.flags()), @@ -91,9 +91,9 @@ struct annotation_t : public supports_flags<>, bool operator<(const annotation_t& rhs) const; bool operator==(const annotation_t& rhs) const { - return (price == rhs.price && - date == rhs.date && - tag == rhs.tag && + return (price == rhs.price && + date == rhs.date && + tag == rhs.tag && (value_expr && rhs.value_expr ? value_expr->text() == rhs.value_expr->text() : value_expr == rhs.value_expr)); @@ -228,6 +228,7 @@ protected: : commodity_t(_ptr->parent_, _ptr->base), ptr(_ptr), details(_details) { TRACE_CTOR(annotated_commodity_t, "commodity_t *, annotation_t"); annotated = true; + qualified_symbol = _ptr->qualified_symbol; } public: diff --git a/src/pool.cc b/src/pool.cc index 5813c0f6..be26de3b 100644 --- a/src/pool.cc +++ b/src/pool.cc @@ -102,7 +102,7 @@ commodity_t * commodity_pool_t::find_or_create(const string& symbol) commodity_t * commodity_pool_t::alias(const string& name, commodity_t& referent) { - commodities_map::const_iterator i = commodities.find(referent.symbol()); + commodities_map::const_iterator i = commodities.find(referent.base_symbol()); assert(i != commodities.end()); std::pair result @@ -130,20 +130,16 @@ commodity_pool_t::find(const string& symbol, const annotation_t& details) DEBUG("pool.commodities", "commodity_pool_t::find[ann] " << "symbol " << symbol << std::endl << details); - if (details) { - annotated_commodities_map::const_iterator i = - annotated_commodities.find - (annotated_commodities_map::key_type(symbol, details)); - if (i != annotated_commodities.end()) { - DEBUG("pool.commodities", "commodity_pool_t::find[ann] found " - << "symbol " << (*i).second->symbol() << std::endl - << as_annotated_commodity(*(*i).second.get()).details); - return (*i).second.get(); - } else { - return NULL; - } + annotated_commodities_map::const_iterator i = + annotated_commodities.find + (annotated_commodities_map::key_type(symbol, details)); + if (i != annotated_commodities.end()) { + DEBUG("pool.commodities", "commodity_pool_t::find[ann] found " + << "symbol " << (*i).second->base_symbol() << std::endl + << as_annotated_commodity(*(*i).second.get()).details); + return (*i).second.get(); } else { - return find(symbol); + return NULL; } } @@ -170,10 +166,10 @@ commodity_t * commodity_pool_t::find_or_create(commodity_t& comm, const annotation_t& details) { DEBUG("pool.commodities", "commodity_pool_t::find_or_create[ann:comm] " - << "symbol " << comm.symbol() << std::endl << details); + << "symbol " << comm.base_symbol() << std::endl << details); if (details) { - if (commodity_t * ann_comm = find(comm.symbol(), details)) { + if (commodity_t * ann_comm = find(comm.base_symbol(), details)) { assert(ann_comm->annotated && as_annotated_commodity(*ann_comm).details); return ann_comm; } else { @@ -189,7 +185,7 @@ commodity_pool_t::create(commodity_t& comm, const annotation_t& details) { DEBUG("pool.commodities", "commodity_pool_t::create[ann:comm] " - << "symbol " << comm.symbol() << std::endl << details); + << "symbol " << comm.base_symbol() << std::endl << details); assert(comm); assert(! comm.has_annotation()); @@ -206,11 +202,8 @@ commodity_pool_t::create(commodity_t& comm, comm.add_flags(COMMODITY_SAW_ANN_PRICE_FLOAT); } - commodity->qualified_symbol = comm.symbol(); - assert(! commodity->qualified_symbol->empty()); - DEBUG("pool.commodities", "Creating annotated commodity " - << "symbol " << commodity->symbol() + << "symbol " << commodity->base_symbol() << std::endl << details); #if defined(DEBUG_ON) @@ -218,7 +211,7 @@ commodity_pool_t::create(commodity_t& comm, #endif annotated_commodities.insert(annotated_commodities_map::value_type (annotated_commodities_map::key_type - (comm.symbol(), details), commodity)); + (comm.base_symbol(), details), commodity)); #if defined(DEBUG_ON) assert(result.second); #endif diff --git a/test/regress/96A8E4A1.test b/test/regress/96A8E4A1.test new file mode 100644 index 00000000..93fb55d2 --- /dev/null +++ b/test/regress/96A8E4A1.test @@ -0,0 +1,10 @@ +2011-01-31 * Test + Expenses:Travel 1 "Spr MegaBonus" + Assets:Voucher + +test -X EUR -H bal + -1 "Spr MegaBonus" Assets:Voucher + 1 "Spr MegaBonus" Expenses:Travel +-------------------- + 0 +end test -- cgit v1.2.3 From e3248ee5a6b2c29e1c35eb0315fd66370a117784 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Tue, 20 Mar 2012 04:56:03 -0500 Subject: Fix problems with postings --- src/annotate.cc | 3 ++- src/commodity.cc | 2 ++ src/filters.cc | 9 ++++++--- src/temps.cc | 8 ++++++-- src/temps.h | 3 ++- test/regress/A560FDAD.test | 1 - 6 files changed, 18 insertions(+), 8 deletions(-) (limited to 'src/annotate.cc') diff --git a/src/annotate.cc b/src/annotate.cc index 25f0e582..98635ad7 100644 --- a/src/annotate.cc +++ b/src/annotate.cc @@ -328,7 +328,8 @@ annotated_commodity_t::strip_annotations(const keep_details_t& what_to_keep) if ((keep_price && details.price) || (keep_date && details.date) || (keep_tag && details.tag) || - details.value_expr) + (details.value_expr && + ! details.has_flags(ANNOTATION_VALUE_EXPR_CALCULATED))) { new_comm = pool().find_or_create (referent(), annotation_t(keep_price ? details.price : none, diff --git a/src/commodity.cc b/src/commodity.cc index 5335d8a8..51b8f29c 100644 --- a/src/commodity.cc +++ b/src/commodity.cc @@ -221,6 +221,8 @@ commodity_t& commodity_t::nail_down(const expr_t& expr) { annotation_t new_details; new_details.value_expr = expr; + new_details.add_flags(ANNOTATION_VALUE_EXPR_CALCULATED); + commodity_t * new_comm = commodity_pool_t::current_pool->find_or_create(symbol(), new_details); return *new_comm; diff --git a/src/filters.cc b/src/filters.cc index 02dc392b..58e5fcaf 100644 --- a/src/filters.cc +++ b/src/filters.cc @@ -340,9 +340,10 @@ namespace { const bool act_date_p = true, const value_t& total = value_t(), const bool direct_amount = false, - const bool mark_visited = false) + const bool mark_visited = false, + const bool bidir_link = true) { - post_t& post = temps.create_post(*xact, account); + post_t& post = temps.create_post(*xact, account, bidir_link); post.add_flags(ITEM_GENERATED); // If the account for this post is all virtual, then report the post as @@ -566,7 +567,9 @@ bool display_filter_posts::output_rounding(post_t& post) /* date= */ date_t(), /* act_date_p= */ true, /* total= */ precise_display_total, - /* direct_amount= */ true); + /* direct_amount= */ true, + /* mark_visited= */ false, + /* bidir_link= */ false); } } if (show_rounding) diff --git a/src/temps.cc b/src/temps.cc index cb471d41..881077f6 100644 --- a/src/temps.cc +++ b/src/temps.cc @@ -81,7 +81,8 @@ post_t& temporaries_t::copy_post(post_t& origin, xact_t& xact, return temp; } -post_t& temporaries_t::create_post(xact_t& xact, account_t * account) +post_t& temporaries_t::create_post(xact_t& xact, account_t * account, + bool bidir_link) { if (! post_temps) post_temps = std::list(); @@ -93,7 +94,10 @@ post_t& temporaries_t::create_post(xact_t& xact, account_t * account) temp.account = account; temp.account->add_post(&temp); - xact.add_post(&temp); + if (bidir_link) + xact.add_post(&temp); + else + temp.xact = &xact; return temp; } diff --git a/src/temps.h b/src/temps.h index f41c487c..daa1493b 100644 --- a/src/temps.h +++ b/src/temps.h @@ -66,7 +66,8 @@ public: } post_t& copy_post(post_t& origin, xact_t& xact, account_t * account = NULL); - post_t& create_post(xact_t& xact, account_t * account); + post_t& create_post(xact_t& xact, account_t * account, + bool bidir_link = true); post_t& last_post() { return post_temps->back(); } diff --git a/test/regress/A560FDAD.test b/test/regress/A560FDAD.test index b30ea086..ee19e71e 100644 --- a/test/regress/A560FDAD.test +++ b/test/regress/A560FDAD.test @@ -82,5 +82,4 @@ test reg -X EUR -H Expenses:Test 304.82 EUR -2606.99 EUR -0.01 EUR -2607.00 EUR Assets:Current 2612.80 EUR 5.80 EUR - 0.01 EUR 5.82 EUR end test -- cgit v1.2.3 From 3fb7490bc91e65050e090ab7fa2dcae230d1697e Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Tue, 20 Mar 2012 05:03:18 -0500 Subject: Never output calculate commodity valuation expressions --- src/annotate.cc | 8 ++------ src/post.cc | 1 + 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'src/annotate.cc') diff --git a/src/annotate.cc b/src/annotate.cc index 98635ad7..c9fd6d3f 100644 --- a/src/annotate.cc +++ b/src/annotate.cc @@ -212,8 +212,7 @@ void annotation_t::print(std::ostream& out, bool keep_base, (! no_computed_annotations || ! has_flags(ANNOTATION_TAG_CALCULATED))) out << " (" << *tag << ')'; - if (value_expr && (! no_computed_annotations || - ! has_flags(ANNOTATION_VALUE_EXPR_CALCULATED))) + if (value_expr && ! has_flags(ANNOTATION_VALUE_EXPR_CALCULATED)) out << " ((" << *value_expr << "))"; } @@ -327,10 +326,7 @@ annotated_commodity_t::strip_annotations(const keep_details_t& what_to_keep) if ((keep_price && details.price) || (keep_date && details.date) || - (keep_tag && details.tag) || - (details.value_expr && - ! details.has_flags(ANNOTATION_VALUE_EXPR_CALCULATED))) - { + (keep_tag && details.tag)) { new_comm = pool().find_or_create (referent(), annotation_t(keep_price ? details.price : none, keep_date ? details.date : none, diff --git a/src/post.cc b/src/post.cc index d5e0d9bc..2b84fc06 100644 --- a/src/post.cc +++ b/src/post.cc @@ -688,6 +688,7 @@ void extend_post(post_t& post, journal_t& journal) if (! details) { annotation_t new_details; new_details.value_expr = value_expr; + commodity_t * new_comm = commodity_pool_t::current_pool->find_or_create(comm, new_details); post.amount.set_commodity(*new_comm); -- cgit v1.2.3 From 8e8c2904f55eb9a43b3eb8057e9f11767a624dff Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Fri, 30 Mar 2012 00:38:29 -0500 Subject: Never price commodities using annotated commodities --- src/amount.cc | 6 +++--- src/amount.h | 9 +++++++++ src/annotate.cc | 2 +- src/commodity.cc | 17 ++++++++--------- src/commodity.h | 3 +++ test/regress/25A099C9.test | 20 ++++++++++---------- 6 files changed, 34 insertions(+), 23 deletions(-) (limited to 'src/annotate.cc') diff --git a/src/amount.cc b/src/amount.cc index 2f7b434e..50496f2d 100644 --- a/src/amount.cc +++ b/src/amount.cc @@ -757,10 +757,10 @@ amount_t::value(const datetime_t& moment, } } - if (! point) { - if (comm && commodity().referent() == comm->referent()) - return *this; + if (comm && commodity().referent() == comm->referent()) + return with_commodity(comm->referent()); + if (! point) { point = commodity().find_price(comm, moment); // Whether a price was found or not, check whether we should attempt diff --git a/src/amount.h b/src/amount.h index 10e83552..cd77a79a 100644 --- a/src/amount.h +++ b/src/amount.h @@ -544,6 +544,15 @@ public: *this = 0L; commodity_ = &comm; } + amount_t with_commodity(const commodity_t& comm) const { + if (commodity_ == &comm) { + return *this; + } else { + amount_t tmp(*this); + tmp.set_commodity(const_cast(comm)); + return tmp; + } + } void clear_commodity() { commodity_ = NULL; } diff --git a/src/annotate.cc b/src/annotate.cc index c9fd6d3f..41e7a752 100644 --- a/src/annotate.cc +++ b/src/annotate.cc @@ -288,7 +288,7 @@ annotated_commodity_t::find_price(const commodity_t * commodity, return find_price_from_expr(const_cast(*details.value_expr), commodity, when); - return commodity_t::find_price(target, moment, oldest); + return commodity_t::find_price(target, when, oldest); } commodity_t& diff --git a/src/commodity.cc b/src/commodity.cc index bc04c3db..a72d85c8 100644 --- a/src/commodity.cc +++ b/src/commodity.cc @@ -56,14 +56,14 @@ void commodity_t::add_price(const datetime_t& date, const amount_t& price, DEBUG("history.find", "Adding price: " << symbol() << " for " << price << " on " << date); - pool().commodity_price_history.add_price(*this, date, price); + pool().commodity_price_history.add_price(referent(), date, price); base->price_map.clear(); // a price was added, invalid the map } void commodity_t::remove_price(const datetime_t& date, commodity_t& commodity) { - pool().commodity_price_history.remove_price(*this, commodity, date); + pool().commodity_price_history.remove_price(referent(), commodity, date); DEBUG("history.find", "Removing price: " << symbol() << " on " << date); @@ -83,7 +83,7 @@ void commodity_t::map_prices(function fn, else when = CURRENT_TIME(); - pool().commodity_price_history.map_prices(fn, *this, when, _oldest, + pool().commodity_price_history.map_prices(fn, referent(), when, _oldest, bidirectionally); } @@ -159,9 +159,9 @@ commodity_t::find_price(const commodity_t * commodity, optional point(target ? - pool().commodity_price_history.find_price(*this, *target, + pool().commodity_price_history.find_price(referent(), *target, when, oldest) : - pool().commodity_price_history.find_price(*this, when, oldest)); + pool().commodity_price_history.find_price(referent(), when, oldest)); // Record this price point in the memoization map if (base->price_map.size() > base_t::max_price_map_size) { @@ -206,7 +206,7 @@ commodity_t::check_for_updated_price(const optional& point, DEBUG("commodity.download", "attempting to download a more current quote..."); if (optional quote = - pool().get_commodity_quote(*this, in_terms_of)) { + pool().get_commodity_quote(referent(), in_terms_of)) { if (! in_terms_of || (quote->price.has_commodity() && quote->price.commodity_ptr() == in_terms_of)) @@ -220,12 +220,11 @@ commodity_t::check_for_updated_price(const optional& point, commodity_t& commodity_t::nail_down(const expr_t& expr) { annotation_t new_details; + new_details.value_expr = expr; new_details.add_flags(ANNOTATION_VALUE_EXPR_CALCULATED); - commodity_t * new_comm = - commodity_pool_t::current_pool->find_or_create(symbol(), new_details); - return *new_comm; + return *pool().find_or_create(symbol(), new_details); } commodity_t::operator bool() const diff --git a/src/commodity.h b/src/commodity.h index d6885ee9..bfbabe6b 100644 --- a/src/commodity.h +++ b/src/commodity.h @@ -188,6 +188,9 @@ public: return comm == *this; return base.get() == comm.base.get(); } + bool operator==(const string& name) const { + return base_symbol() == name; + } static bool symbol_needs_quotes(const string& symbol); diff --git a/test/regress/25A099C9.test b/test/regress/25A099C9.test index a8a93832..1ef5ebef 100644 --- a/test/regress/25A099C9.test +++ b/test/regress/25A099C9.test @@ -20,24 +20,24 @@ While parsing file "src/amount.h", line 121: Error: Unexpected whitespace at beginning of line While parsing file "src/amount.h", line 132: Error: Unexpected whitespace at beginning of line -While parsing file "src/amount.h", line 693: +While parsing file "src/amount.h", line 702: Error: Unexpected whitespace at beginning of line -While parsing file "src/amount.h", line 723: +While parsing file "src/amount.h", line 732: Error: Unexpected whitespace at beginning of line -While parsing file "src/amount.h", line 731: +While parsing file "src/amount.h", line 740: Error: Unexpected whitespace at beginning of line -While parsing file "src/amount.h", line 734: +While parsing file "src/amount.h", line 743: Error: Invalid date/time: line amount_t amoun -While parsing file "src/amount.h", line 740: +While parsing file "src/amount.h", line 749: Error: Invalid date/time: line string amount_ -While parsing file "src/amount.h", line 746: +While parsing file "src/amount.h", line 755: Error: Invalid date/time: line string amount_ -While parsing file "src/amount.h", line 752: +While parsing file "src/amount.h", line 761: Error: Invalid date/time: line string amount_ -While parsing file "src/amount.h", line 758: +While parsing file "src/amount.h", line 767: Error: Invalid date/time: line std::ostream& -While parsing file "src/amount.h", line 765: +While parsing file "src/amount.h", line 774: Error: Invalid date/time: line std::istream& -While parsing file "src/amount.h", line 771: +While parsing file "src/amount.h", line 780: Error: Unexpected whitespace at beginning of line end test -- cgit v1.2.3