Added use of boost::optional<> to amount.h

This commit is contained in:
John Wiegley 2007-04-30 12:20:58 +00:00
parent 21af83013f
commit 18aaf588ab
17 changed files with 251 additions and 126 deletions

View file

@ -27,7 +27,8 @@ AM_LFLAGS = -o $(LEX_OUTPUT_ROOT).c
#WARNFLAGS += -Wconversion -Wshorten-64-to-32 -Wsign-compare
#WARNFLAGS += -Wmissing-field-initializers -pedantic-errors
libledger_la_CPPFLAGS = -I$(top_builddir)/gdtoa -I$(srcdir) -I$(srcdir)/src
libledger_la_CPPFLAGS = -I$(top_builddir)/gdtoa -I$(srcdir)/gdtoa \
-I$(srcdir)/src
libledger_la_LDFLAGS = -release 3.0
libledger_la_SOURCES = \

View file

@ -355,7 +355,7 @@ AM_LFLAGS = -o $(LEX_OUTPUT_ROOT).c
#WARNFLAGS += -Wcast-qual -Wcast-align -Wwrite-strings -Wconversion
#WARNFLAGS += -Wconversion -Wshorten-64-to-32 -Wsign-compare
#WARNFLAGS += -Wmissing-field-initializers -pedantic-errors
libledger_la_CPPFLAGS = -I$(top_builddir)/gdtoa -I$(srcdir) \
libledger_la_CPPFLAGS = -I$(top_builddir)/gdtoa -I$(srcdir)/gdtoa \
-I$(srcdir)/src $(am__append_2) $(am__append_4) \
$(am__append_6) $(am__append_8) $(am__append_9)
libledger_la_LDFLAGS = -release 3.0

View file

@ -1,5 +1,6 @@
lib_LTLIBRARIES = libgdtoa.la
libgdtoa_la_LDFLAGS = -release 1.0
libgdtoa_la_CPPFLAGS = -I$(top_builddir)
libgdtoa_la_SOURCES = \
dmisc.c dtoa.c g_Qfmt.c g__fmt.c g_ddfmt.c g_dfmt.c g_ffmt.c \
@ -11,7 +12,8 @@ libgdtoa_la_SOURCES = \
EXTRA_libgdtoa_la_SOURCES = arithchk.c qnan.c
$(libgdtoa_la_SOURCES): arith.h gd_qnan.h
BUILT_SOURCES = arith.h gd_qnan.h
CLEANFILES = arith.h gd_qnan.h arithchk qnan
arith.h: arithchk.c
$(CC) $(CFLAGS) -o $(top_builddir)/arithchk $< || \
@ -24,9 +26,4 @@ gd_qnan.h: qnan.c arith.h
$(top_builddir)/qnan > $(top_builddir)/$@
rm -f $(top_builddir)/qnan
libgdtoa_la_LDFLAGS = -release 1.0
pkginclude_HEADERS = gdtoa.h gdtoaimp.h
CLEANFILES = arithchk qnan
DISTCLEANFILES = arithchk arith.h qnan gd_qnan.h
pkginclude_HEADERS = gdtoa.h gdtoaimp.h arith.h gd_qnan.h

View file

@ -219,6 +219,7 @@ target_alias = @target_alias@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
lib_LTLIBRARIES = libgdtoa.la
libgdtoa_la_LDFLAGS = -release 1.0
libgdtoa_la_CPPFLAGS = -I$(top_builddir)
libgdtoa_la_SOURCES = \
dmisc.c dtoa.c g_Qfmt.c g__fmt.c g_ddfmt.c g_dfmt.c g_ffmt.c \
@ -229,11 +230,10 @@ libgdtoa_la_SOURCES = \
strtord.c strtordd.c strtorf.c strtorx.c strtorxL.c sum.c ulp.c
EXTRA_libgdtoa_la_SOURCES = arithchk.c qnan.c
libgdtoa_la_LDFLAGS = -release 1.0
pkginclude_HEADERS = gdtoa.h gdtoaimp.h
CLEANFILES = arithchk qnan
DISTCLEANFILES = arithchk arith.h qnan gd_qnan.h
all: acconf.h
BUILT_SOURCES = arith.h gd_qnan.h
CLEANFILES = arith.h gd_qnan.h arithchk qnan
pkginclude_HEADERS = gdtoa.h gdtoaimp.h arith.h gd_qnan.h
all: $(BUILT_SOURCES) acconf.h
$(MAKE) $(AM_MAKEFLAGS) all-am
.SUFFIXES:
@ -890,13 +890,15 @@ distcleancheck: distclean
$(distcleancheck_listfiles) ; \
exit 1; } >&2
check-am: all-am
check: check-am
check: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) check-am
all-am: Makefile $(LTLIBRARIES) $(HEADERS) acconf.h
installdirs:
for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgincludedir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
install: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
@ -917,11 +919,11 @@ clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
clean: clean-am
clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
@ -1004,8 +1006,6 @@ uninstall-am: uninstall-libLTLIBRARIES uninstall-pkgincludeHEADERS
uninstall-libLTLIBRARIES uninstall-pkgincludeHEADERS
$(libgdtoa_la_SOURCES): arith.h gd_qnan.h
arith.h: arithchk.c
$(CC) $(CFLAGS) -o $(top_builddir)/arithchk $< || \
$(CC) -DNO_LONG_LONG $(CFLAGS) -o $(top_builddir)/arithchk $<

View file

@ -59,11 +59,13 @@ bool amount_t::full_strings = false;
class amount_t::bigint_t
{
public:
mpz_t val;
unsigned char prec;
unsigned char flags;
unsigned int ref;
unsigned int index;
typedef uint8_t precision_t;
mpz_t val;
precision_t prec;
uint8_t flags;
uint_least16_t ref;
uint_fast32_t index;
bigint_t() : prec(0), flags(0), ref(1), index(0) {
TRACE_CTOR(bigint_t, "");
@ -245,7 +247,7 @@ amount_t::amount_t(const unsigned long val)
}
namespace {
unsigned char convert_double(mpz_t dest, double val)
amount_t::bigint_t::precision_t convert_double(mpz_t dest, double val)
{
#ifndef HAVE_GDTOA
// This code is far too imprecise to be worthwhile.
@ -285,7 +287,7 @@ namespace {
mpz_set_str(dest, buf, 10);
free(buf);
return (unsigned char)exp;
return amount_t::bigint_t::precision_t(exp);
#else
int decpt, sign;
char * buf = dtoa(val, 0, 0, &decpt, &sign, NULL);
@ -830,7 +832,7 @@ void amount_t::print_quantity(std::ostream& out) const
// outputting it. NOTE: `rquotient' is used here as a temp variable!
commodity_t& comm(commodity());
unsigned char precision;
bigint_t::precision_t precision;
if (! comm || quantity->flags & BIGINT_KEEP_PREC) {
mpz_ui_pow_ui(divisor, 10, quantity->prec);
@ -932,7 +934,7 @@ void amount_t::print(std::ostream& _out, bool omit_commodity,
// outputting it. NOTE: `rquotient' is used here as a temp variable!
commodity_t& comm(base.commodity());
unsigned char precision = 0;
bigint_t::precision_t precision = 0;
if (quantity) {
if (! comm || full_precision || base.quantity->flags & BIGINT_KEEP_PREC) {
@ -1213,7 +1215,7 @@ bool parse_annotations(std::istream& in, amount_t& price,
return has_date;
}
void amount_t::parse(std::istream& in, unsigned char flags)
void amount_t::parse(std::istream& in, uint8_t flags)
{
// The possible syntax for an amount is:
//
@ -1425,10 +1427,10 @@ void amount_t::write(std::ostream& out) const
#ifndef THREADSAFE
static char * bigints;
static char * bigints_next;
static unsigned int bigints_index;
static unsigned int bigints_count;
static char * bigints;
static char * bigints_next;
static uint_fast32_t bigints_index;
static uint_fast32_t bigints_count;
#endif
void amount_t::read_quantity(char *& data)
@ -1452,14 +1454,14 @@ void amount_t::read_quantity(char *& data)
if (negative)
mpz_neg(MPZ(quantity), MPZ(quantity));
quantity->prec = *((unsigned char *) data);
data += sizeof(unsigned char);
quantity->flags = *((unsigned char *) data);
data += sizeof(unsigned char);
quantity->prec = *((bigint_t::precision_t *) data);
data += sizeof(bigint_t::precision_t);
quantity->flags = *((uint8_t *) data);
data += sizeof(uint8_t);
quantity->flags |= BIGINT_BULK_ALLOC;
} else {
unsigned int index = *((unsigned int *) data);
data += sizeof(unsigned int);
uint_fast32_t index = *((uint_fast32_t *) data);
data += sizeof(uint_fast32_t);
quantity = (bigint_t *) (bigints + (index - 1) * sizeof(bigint_t));
DEBUG("amounts.refs",
@ -1533,7 +1535,7 @@ void amount_t::write_quantity(std::ostream& out) const
out.write(&byte, sizeof(byte));
out.write((char *)&quantity->prec, sizeof(quantity->prec));
unsigned char flags = quantity->flags & ~BIGINT_BULK_ALLOC;
uint8_t flags = quantity->flags & ~BIGINT_BULK_ALLOC;
assert(sizeof(flags) == sizeof(quantity->flags));
out.write((char *)&flags, sizeof(flags));
} else {
@ -1634,7 +1636,7 @@ amount_t amount_t::strip_annotations(const bool _keep_price,
return t;
}
amount_t amount_t::price() const
optional<amount_t> amount_t::price() const
{
if (commodity_ && commodity_->annotated) {
amount_t t(((annotated_commodity_t *)commodity_)->price);
@ -1643,10 +1645,10 @@ amount_t amount_t::price() const
"Returning price of " << *this << " = " << t);
return t;
}
return *this;
return optional<amount_t>();
}
moment_t amount_t::date() const
optional<moment_t> amount_t::date() const
{
if (commodity_ && commodity_->annotated) {
DEBUG("amounts.commodities",
@ -1654,7 +1656,18 @@ moment_t amount_t::date() const
<< ((annotated_commodity_t *)commodity_)->date);
return ((annotated_commodity_t *)commodity_)->date;
}
return moment_t();
return optional<moment_t>();
}
optional<string> amount_t::tag() const
{
if (commodity_ && commodity_->annotated) {
DEBUG("amounts.commodities",
"Returning tag of " << *this << " = "
<< ((annotated_commodity_t *)commodity_)->tag);
return ((annotated_commodity_t *)commodity_)->tag;
}
return optional<string>();
}

View file

@ -48,7 +48,6 @@
#define _AMOUNT_H
#include "utils.h"
#include "times.h"
namespace ledger {
@ -126,27 +125,34 @@ class amount_t
}
amount_t number() const {
if (! has_commodity())
return *this;
amount_t temp(*this);
temp.clear_commodity();
return temp;
}
bool has_commodity() const;
commodity_t& commodity() const;
void set_commodity(commodity_t& comm) {
commodity_ = &comm;
}
void annotate_commodity(const amount_t& price,
const moment_t& date = moment_t(),
const string& tag = "");
amount_t strip_annotations(const bool _keep_price = keep_price,
const bool _keep_date = keep_date,
const bool _keep_tag = keep_tag) const;
void clear_commodity() {
commodity_ = NULL;
}
amount_t price() const;
moment_t date() const;
commodity_t& commodity() const;
void annotate_commodity(const amount_t& price,
const moment_t& date = moment_t(),
const string& tag = "");
amount_t strip_annotations(const bool _keep_price = keep_price,
const bool _keep_date = keep_date,
const bool _keep_tag = keep_tag) const;
optional<amount_t> price() const;
optional<moment_t> date() const;
optional<string> tag() const;
bool null() const {
return ! quantity && ! has_commodity();
@ -247,7 +253,7 @@ class amount_t
}
// test for zero and non-zero
int sign() const;
int sign() const;
bool zero() const;
bool realzero() const {
return sign() == 0;
@ -688,9 +694,9 @@ class annotated_commodity_t : public commodity_t
public:
const commodity_t * ptr;
amount_t price;
moment_t date;
string tag;
amount_t price;
moment_t date;
string tag;
explicit annotated_commodity_t() {
TRACE_CTOR(annotated_commodity_t, "");
@ -732,6 +738,8 @@ inline std::ostream& operator<<(std::ostream& out, const commodity_t& comm) {
}
inline amount_t amount_t::round() const {
if (! has_commodity())
return *this;
return round(commodity().precision());
}
@ -740,10 +748,7 @@ inline bool amount_t::has_commodity() const {
}
inline commodity_t& amount_t::commodity() const {
if (! commodity_)
return *commodity_t::null_commodity;
else
return *commodity_;
return has_commodity() ? *commodity_ : *commodity_t::null_commodity;
}
void parse_conversion(const string& larger_str,

View file

@ -39,30 +39,51 @@ balance_t balance_t::value(const moment_t& moment) const
return temp;
}
balance_t balance_t::price() const
optional<balance_t> balance_t::price() const
{
balance_t temp;
for (amounts_map::const_iterator i = amounts.begin();
i != amounts.end();
i++)
temp += (*i).second.price();
return temp;
}
moment_t balance_t::date() const
{
moment_t temp;
optional<balance_t> temp;
for (amounts_map::const_iterator i = amounts.begin();
i != amounts.end();
i++) {
moment_t tdate = (*i).second.date();
if (! is_valid_moment(temp) && is_valid_moment(tdate))
temp = tdate;
else if (temp != tdate)
return moment_t();
optional<amount_t> i_price = (*i).second.price();
if (i_price) {
if (! temp)
temp = balance_t();
*temp += *i_price;
}
}
return temp;
}
optional<moment_t> balance_t::date() const
{
optional<moment_t> temp;
for (amounts_map::const_iterator i = amounts.begin();
i != amounts.end();
i++) {
optional<moment_t> tdate = (*i).second.date();
if (! temp && tdate)
temp = *tdate;
else if (temp && tdate && temp != tdate)
return optional<moment_t>();
}
return temp;
}
optional<string> balance_t::tag() const
{
optional<string> temp;
for (amounts_map::const_iterator i = amounts.begin();
i != amounts.end();
i++) {
optional<string> ttag = (*i).second.tag();
if (! temp && ttag)
temp = *ttag;
else if (temp && ttag && temp != ttag)
return optional<string>();
}
return temp;
}

View file

@ -435,8 +435,10 @@ class balance_t
amount_t amount(const commodity_t& commodity =
*commodity_t::null_commodity) const;
balance_t value(const moment_t& moment = now) const;
balance_t price() const;
moment_t date() const;
optional<balance_t> price() const;
optional<moment_t> date() const;
optional<string> tag() const;
balance_t
strip_annotations(const bool keep_price = amount_t::keep_price,
@ -896,12 +898,16 @@ class balance_pair_t
balance_t value(const moment_t& moment = now) const {
return quantity.value(moment);
}
balance_t price() const {
optional<balance_t> price() const {
return quantity.price();
}
moment_t date() const {
optional<moment_t> date() const {
return quantity.date();
}
optional<string> tag() const {
return quantity.tag();
}
balance_t
strip_annotations(const bool keep_price = amount_t::keep_price,

View file

@ -23,9 +23,6 @@
#include <parser.h>
#include <textual.h>
#include <binary.h>
#include <gnucash.h>
#include <qif.h>
#include <ofx.h>
#include <report.h>
#include <transform.h>

View file

@ -3,9 +3,12 @@
#else
#include <ledger.h>
#endif
#include <option.h>
#include "acconf.h"
#include "option.h"
#include "gnucash.h"
#include "qif.h"
#include "ofx.h"
#ifdef HAVE_UNIX_PIPES
#include <sys/types.h>

View file

@ -82,7 +82,7 @@ namespace std {
#define HAVE_GDTOA 1
#ifdef HAVE_GDTOA
#include <gdtoa/gdtoa.h>
#include "gdtoa.h"
#endif
extern "C" {

View file

@ -1,4 +1,4 @@
#include "times.h"
#include "utils.h"
namespace ledger {

View file

@ -1,8 +1,6 @@
#ifndef _TIMES_H
#define _TIMES_H
#include "utils.h"
namespace ledger {
#define SUPPORT_DATE_AND_TIME 1

View file

@ -1,5 +1,4 @@
#include "utils.h"
#include "times.h"
/**********************************************************************
*

View file

@ -3,6 +3,26 @@
#include <system.hh>
/**********************************************************************
*
* Default values
*/
#if defined(FULL_DEBUG)
#define VERIFY_ON 1
#define TRACING_ON 1
#define DEBUG_ON 1
#define TIMERS_ON 1
#define FREE_MEMORY 1
#elif defined(NO_DEBUG)
#define NO_ASSERTS 1
#define NO_LOGGING 1
#else
#define VERIFY_ON 1 // compiled in, use --verify to enable
#define TRACING_ON 1 // use --trace X to enable
#define TIMERS_ON 1
#endif
/**********************************************************************
*
* Forward declarations
@ -29,26 +49,6 @@ namespace ledger {
typedef boost::filesystem::filesystem_error filesystem_error;
}
/**********************************************************************
*
* Default values
*/
#if defined(FULL_DEBUG)
#define VERIFY_ON 1
#define TRACING_ON 1
#define DEBUG_ON 1
#define TIMERS_ON 1
#define FREE_MEMORY 1
#elif defined(NO_DEBUG)
#define NO_ASSERTS 1
#define NO_LOGGING 1
#else
#define VERIFY_ON 1 // compiled in, use --verify to enable
#define TRACING_ON 1 // use --trace X to enable
#define TIMERS_ON 1 // jww (2007-04-25): is this correct?
#endif
/**********************************************************************
*
* Assertions
@ -72,6 +72,10 @@ namespace ledger {
((x) ? ((void)0) : debug_assert(#x, BOOST_CURRENT_FUNCTION, \
__FILE__, __LINE__))
#else // ! ASSERTS_ON
#define assert(x)
#endif // ASSERTS_ON
/**********************************************************************
@ -429,6 +433,13 @@ inline void throw_unexpected_error(char c, char wanted) {
} // namespace ledger
/**********************************************************************
*
* Date/time support classes
*/
#include "times.h"
/**********************************************************************
*
* General utility functions

View file

@ -1981,12 +1981,24 @@ value_t value_t::price() const
case DATETIME:
throw_(value_error, "Cannot find the price of a date/time");
case AMOUNT:
return ((amount_t *) data)->price();
case BALANCE:
return ((balance_t *) data)->price();
case BALANCE_PAIR:
return ((balance_pair_t *) data)->quantity.price();
case AMOUNT: {
optional<amount_t> temp = ((amount_t *) data)->price();
if (! temp)
return false;
return *temp;
}
case BALANCE: {
optional<balance_t> temp = ((balance_t *) data)->price();
if (! temp)
return false;
return *temp;
}
case BALANCE_PAIR: {
optional<balance_t> temp = ((balance_pair_t *) data)->price();
if (! temp)
return false;
return *temp;
}
case STRING:
throw_(value_error, "Cannot find the price of a string");
@ -2018,12 +2030,73 @@ value_t value_t::date() const
case DATETIME:
return *this;
case AMOUNT:
return ((amount_t *) data)->date();
case BALANCE:
return ((balance_t *) data)->date();
case BALANCE_PAIR:
return ((balance_pair_t *) data)->quantity.date();
case AMOUNT: {
optional<moment_t> temp = ((amount_t *) data)->date();
if (! temp)
return false;
return *temp;
}
case BALANCE: {
optional<moment_t> temp = ((balance_t *) data)->date();
if (! temp)
return false;
return *temp;
}
case BALANCE_PAIR: {
optional<moment_t> temp = ((balance_pair_t *) data)->date();
if (! temp)
return false;
return *temp;
}
case STRING:
throw_(value_error, "Cannot find the date of a string");
case XML_NODE:
return (*(xml::node_t **) data)->to_value().date();
case POINTER:
throw_(value_error, "Cannot find the date of a pointer");
case SEQUENCE:
throw_(value_error, "Cannot find the date of a sequence");
default:
assert(0);
break;
}
assert(0);
return value_t();
}
value_t value_t::tag() const
{
switch (type) {
case BOOLEAN:
throw_(value_error, "Cannot find the date of a boolean");
case INTEGER:
throw_(value_error, "Cannot find the date of an integer");
case DATETIME:
return *this;
case AMOUNT: {
optional<string> temp = ((amount_t *) data)->tag();
if (! temp)
return false;
return *temp;
}
case BALANCE: {
optional<string> temp = ((balance_t *) data)->tag();
if (! temp)
return false;
return *temp;
}
case BALANCE_PAIR: {
optional<string> temp = ((balance_pair_t *) data)->tag();
if (! temp)
return false;
return *temp;
}
case STRING:
throw_(value_error, "Cannot find the date of a string");

View file

@ -441,6 +441,7 @@ class value_t
value_t cost() const;
value_t price() const;
value_t date() const;
value_t tag() const;
value_t cast(type_t cast_type) const {
value_t temp(*this);