From 8d6bf11334562d7781b339cf822a93ff42fee2b5 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Mon, 5 Mar 2012 01:48:21 -0600 Subject: All tests are working again but one --- test/unit/t_commodity.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test/unit') diff --git a/test/unit/t_commodity.cc b/test/unit/t_commodity.cc index dc64dcfb..6a6f27aa 100644 --- a/test/unit/t_commodity.cc +++ b/test/unit/t_commodity.cc @@ -94,7 +94,7 @@ BOOST_AUTO_TEST_CASE(testPriceHistory) amt = x1.value(CURRENT_TIME(), euro); BOOST_CHECK(amt); - BOOST_CHECK_EQUAL(string("EUR 1366.87"), amt->rounded().to_string()); + 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")); -- 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 'test/unit') 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 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 'test/unit') 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