Made the amount/balance/value interface a bit more rational; added
back a useless version of the register command (just to prove the command sequence); and added smart XML semantics to the XPath implementation so that nodes can be coerced to values.
This commit is contained in:
parent
176b3044e3
commit
0a6b5726ec
38 changed files with 729 additions and 672 deletions
|
|
@ -46,6 +46,8 @@ libledger_la_SOURCES = \
|
|||
report.cc \
|
||||
transform.cc \
|
||||
\
|
||||
register.cc \
|
||||
\
|
||||
csv.cc \
|
||||
derive.cc \
|
||||
emacs.cc \
|
||||
|
|
@ -164,7 +166,7 @@ noinst_PROGRAMS = ledger.so
|
|||
|
||||
ledger_so_SOURCES = pyledger.cc
|
||||
|
||||
PYLIBS = pyledger ledger gdtoa boost_date_time boost_python gmp pcre
|
||||
PYLIBS = pyledger ledger gdtoa boost_date_time boost_regex boost_python gmp
|
||||
|
||||
if HAVE_EXPAT
|
||||
PYLIBS += expat
|
||||
|
|
|
|||
33
Makefile.in
33
Makefile.in
|
|
@ -96,8 +96,8 @@ am__libledger_la_SOURCES_DIST = amount.cc times.cc parsetime.yy \
|
|||
scantime.ll quotes.cc balance.cc value.cc xml.cc xpath.cc \
|
||||
mask.cc format.cc util.cc session.cc journal.cc parser.cc \
|
||||
textual.cc binary.cc xmlparse.cc qif.cc report.cc transform.cc \
|
||||
csv.cc derive.cc emacs.cc reconcile.cc gnucash.cc ofx.cc \
|
||||
debug.cc trace.cc
|
||||
register.cc csv.cc derive.cc emacs.cc reconcile.cc gnucash.cc \
|
||||
ofx.cc debug.cc trace.cc
|
||||
@HAVE_EXPAT_TRUE@am__objects_1 = libledger_la-gnucash.lo
|
||||
@HAVE_XMLPARSE_TRUE@am__objects_2 = libledger_la-gnucash.lo
|
||||
@HAVE_LIBOFX_TRUE@am__objects_3 = libledger_la-ofx.lo
|
||||
|
|
@ -113,10 +113,11 @@ am_libledger_la_OBJECTS = libledger_la-amount.lo libledger_la-times.lo \
|
|||
libledger_la-parser.lo libledger_la-textual.lo \
|
||||
libledger_la-binary.lo libledger_la-xmlparse.lo \
|
||||
libledger_la-qif.lo libledger_la-report.lo \
|
||||
libledger_la-transform.lo libledger_la-csv.lo \
|
||||
libledger_la-derive.lo libledger_la-emacs.lo \
|
||||
libledger_la-reconcile.lo $(am__objects_1) $(am__objects_2) \
|
||||
$(am__objects_3) $(am__objects_4)
|
||||
libledger_la-transform.lo libledger_la-register.lo \
|
||||
libledger_la-csv.lo libledger_la-derive.lo \
|
||||
libledger_la-emacs.lo libledger_la-reconcile.lo \
|
||||
$(am__objects_1) $(am__objects_2) $(am__objects_3) \
|
||||
$(am__objects_4)
|
||||
libledger_la_OBJECTS = $(am_libledger_la_OBJECTS)
|
||||
libledger_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(libledger_la_CXXFLAGS) \
|
||||
|
|
@ -373,9 +374,10 @@ libledger_la_CXXFLAGS = $(WARNFLAGS) -I$(top_builddir)/gdtoa \
|
|||
libledger_la_SOURCES = amount.cc times.cc parsetime.yy scantime.ll \
|
||||
quotes.cc balance.cc value.cc xml.cc xpath.cc mask.cc \
|
||||
format.cc util.cc session.cc journal.cc parser.cc textual.cc \
|
||||
binary.cc xmlparse.cc qif.cc report.cc transform.cc csv.cc \
|
||||
derive.cc emacs.cc reconcile.cc $(am__append_3) \
|
||||
$(am__append_5) $(am__append_7) $(am__append_9)
|
||||
binary.cc xmlparse.cc qif.cc report.cc transform.cc \
|
||||
register.cc csv.cc derive.cc emacs.cc reconcile.cc \
|
||||
$(am__append_3) $(am__append_5) $(am__append_7) \
|
||||
$(am__append_9)
|
||||
libledger_la_LDFLAGS = -release 3.0
|
||||
libpyledger_la_CXXFLAGS = -DUSE_BOOST_PYTHON=1 $(am__append_11)
|
||||
libpyledger_la_SOURCES = \
|
||||
|
|
@ -433,8 +435,9 @@ info_TEXINFOS = ledger.texi
|
|||
lisp_LISP = ledger.el timeclock.el
|
||||
@HAVE_BOOST_PYTHON_TRUE@ledger_so_SOURCES = pyledger.cc
|
||||
@HAVE_BOOST_PYTHON_TRUE@PYLIBS = pyledger ledger gdtoa boost_date_time \
|
||||
@HAVE_BOOST_PYTHON_TRUE@ boost_python gmp pcre $(am__append_18) \
|
||||
@HAVE_BOOST_PYTHON_TRUE@ $(am__append_19) $(am__append_20)
|
||||
@HAVE_BOOST_PYTHON_TRUE@ boost_regex boost_python gmp \
|
||||
@HAVE_BOOST_PYTHON_TRUE@ $(am__append_18) $(am__append_19) \
|
||||
@HAVE_BOOST_PYTHON_TRUE@ $(am__append_20)
|
||||
@DEBUG_FALSE@@HAVE_BOOST_PYTHON_TRUE@DEBUG_LEVEL = 0
|
||||
@DEBUG_TRUE@@HAVE_BOOST_PYTHON_TRUE@DEBUG_LEVEL = 4
|
||||
UnitTests_SOURCES = tests/UnitTests.cc \
|
||||
|
|
@ -622,6 +625,7 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libledger_la-qif.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libledger_la-quotes.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libledger_la-reconcile.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libledger_la-register.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libledger_la-report.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libledger_la-scantime.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libledger_la-session.Plo@am__quote@
|
||||
|
|
@ -806,6 +810,13 @@ libledger_la-transform.lo: transform.cc
|
|||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libledger_la_CXXFLAGS) $(CXXFLAGS) -c -o libledger_la-transform.lo `test -f 'transform.cc' || echo '$(srcdir)/'`transform.cc
|
||||
|
||||
libledger_la-register.lo: register.cc
|
||||
@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libledger_la_CXXFLAGS) $(CXXFLAGS) -MT libledger_la-register.lo -MD -MP -MF $(DEPDIR)/libledger_la-register.Tpo -c -o libledger_la-register.lo `test -f 'register.cc' || echo '$(srcdir)/'`register.cc
|
||||
@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libledger_la-register.Tpo $(DEPDIR)/libledger_la-register.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='register.cc' object='libledger_la-register.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libledger_la_CXXFLAGS) $(CXXFLAGS) -c -o libledger_la-register.lo `test -f 'register.cc' || echo '$(srcdir)/'`register.cc
|
||||
|
||||
libledger_la-csv.lo: csv.cc
|
||||
@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libledger_la_CXXFLAGS) $(CXXFLAGS) -MT libledger_la-csv.lo -MD -MP -MF $(DEPDIR)/libledger_la-csv.Tpo -c -o libledger_la-csv.lo `test -f 'csv.cc' || echo '$(srcdir)/'`csv.cc
|
||||
@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libledger_la-csv.Tpo $(DEPDIR)/libledger_la-csv.Plo
|
||||
|
|
|
|||
4
README
4
README
|
|
@ -30,10 +30,10 @@ Building
|
|||
========
|
||||
|
||||
To build Ledger, you will need a fairly modern C++ compiler (gcc 2.95
|
||||
will not work), and at least these two libraries installed:
|
||||
will not work), and at least these libraries installed:
|
||||
|
||||
gmp GNU multi-precision library
|
||||
pcre Perl regular expression library
|
||||
boost Boost C++ library
|
||||
|
||||
(On some GNU/Linux systems, the packages you need to install are
|
||||
called "gmp-dev" and "pcre-dev").
|
||||
|
|
|
|||
|
|
@ -15,12 +15,18 @@
|
|||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the <langinfo.h> header file. */
|
||||
#undef HAVE_LANGINFO_H
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 if you have the `mktime' function. */
|
||||
#undef HAVE_MKTIME
|
||||
|
||||
/* Define to 1 if you have the `nl_langinfo' function. */
|
||||
#undef HAVE_NL_LANGINFO
|
||||
|
||||
/* Define to 1 if you have the `realpath' function. */
|
||||
#undef HAVE_REALPATH
|
||||
|
||||
|
|
|
|||
2
acprep
2
acprep
|
|
@ -61,7 +61,7 @@ while [ -n "$1" ]; do
|
|||
case "$1" in
|
||||
--debug)
|
||||
SWITCHES="$SWITCHES --enable-debug"
|
||||
CXXFLAGS="$CXXFLAGS -ggdb3" ;;
|
||||
CXXFLAGS="$CXXFLAGS -g" ;;
|
||||
|
||||
--prof | --perf)
|
||||
CXXFLAGS="$CXXFLAGS -g -pg" ;;
|
||||
|
|
|
|||
18
amount.cc
18
amount.cc
|
|
@ -639,7 +639,7 @@ amount_t& amount_t::operator/=(const amount_t& amt)
|
|||
}
|
||||
|
||||
// unary negation
|
||||
void amount_t::negate()
|
||||
void amount_t::in_place_negate()
|
||||
{
|
||||
if (quantity) {
|
||||
_dup();
|
||||
|
|
@ -899,7 +899,7 @@ void amount_t::print(std::ostream& _out, bool omit_commodity,
|
|||
while (last.commodity().larger()) {
|
||||
last /= last.commodity().larger()->number();
|
||||
last.commodity_ = last.commodity().larger()->commodity_;
|
||||
if (::abs(last) < 1)
|
||||
if (last.abs() < 1)
|
||||
break;
|
||||
base = last.round();
|
||||
}
|
||||
|
|
@ -1151,7 +1151,7 @@ bool parse_annotations(std::istream& in, amount_t& price,
|
|||
throw new amount_error("Commodity price lacks closing brace");
|
||||
|
||||
price.parse(buf, AMOUNT_PARSE_NO_MIGRATE);
|
||||
price.reduce();
|
||||
price.in_place_reduce();
|
||||
|
||||
// Since this price will maintain its own precision, make sure
|
||||
// it is at least as large as the base commodity, since the user
|
||||
|
|
@ -1162,7 +1162,7 @@ bool parse_annotations(std::istream& in, amount_t& price,
|
|||
price = price.round(); // no need to retain individual precision
|
||||
}
|
||||
else if (c == '[') {
|
||||
if (date.is_not_a_date_time())
|
||||
if (! date.is_not_a_date_time())
|
||||
throw new amount_error("Commodity specifies more than one date");
|
||||
|
||||
in.get(c);
|
||||
|
|
@ -1341,13 +1341,13 @@ void amount_t::parse(std::istream& in, unsigned char flags)
|
|||
}
|
||||
|
||||
if (negative)
|
||||
negate();
|
||||
in_place_negate();
|
||||
|
||||
if (! (flags & AMOUNT_PARSE_NO_REDUCE))
|
||||
reduce();
|
||||
in_place_reduce();
|
||||
}
|
||||
|
||||
void amount_t::reduce()
|
||||
void amount_t::in_place_reduce()
|
||||
{
|
||||
while (commodity_ && commodity().smaller()) {
|
||||
*this *= commodity().smaller()->number();
|
||||
|
|
@ -1968,9 +1968,9 @@ bool compare_amount_commodities::operator()(const amount_t * left,
|
|||
|
||||
if (aleftcomm.price && arightcomm.price) {
|
||||
amount_t leftprice(aleftcomm.price);
|
||||
leftprice.reduce();
|
||||
leftprice.in_place_reduce();
|
||||
amount_t rightprice(arightcomm.price);
|
||||
rightprice.reduce();
|
||||
rightprice.in_place_reduce();
|
||||
|
||||
if (leftprice.commodity() == rightprice.commodity()) {
|
||||
amount_t val = leftprice - rightprice;
|
||||
|
|
|
|||
26
amount.h
26
amount.h
|
|
@ -244,15 +244,14 @@ class amount_t
|
|||
}
|
||||
|
||||
// unary negation
|
||||
// jww (2007-04-17): change the name here
|
||||
void negate();
|
||||
amount_t negated() const {
|
||||
void in_place_negate();
|
||||
amount_t negate() const {
|
||||
amount_t temp = *this;
|
||||
temp.negate();
|
||||
temp.in_place_negate();
|
||||
return temp;
|
||||
}
|
||||
amount_t operator-() const {
|
||||
return negated();
|
||||
return negate();
|
||||
}
|
||||
|
||||
// test for zero and non-zero
|
||||
|
|
@ -327,17 +326,16 @@ class amount_t
|
|||
|
||||
amount_t value(const ptime& moment) const;
|
||||
|
||||
// jww (2007-04-17): change the name here
|
||||
void abs() {
|
||||
amount_t abs() const {
|
||||
if (*this < 0)
|
||||
negate();
|
||||
return negate();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// jww (2007-04-17): change the name here
|
||||
void reduce();
|
||||
amount_t reduced() const {
|
||||
void in_place_reduce();
|
||||
amount_t reduce() const {
|
||||
amount_t temp(*this);
|
||||
temp.reduce();
|
||||
temp.in_place_reduce();
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
|
@ -409,10 +407,6 @@ inline std::string amount_t::quantity_string() const {
|
|||
return bufstream.str();
|
||||
}
|
||||
|
||||
inline amount_t abs(const amount_t& amt) {
|
||||
return amt < 0 ? amt.negated() : amt;
|
||||
}
|
||||
|
||||
#define DEFINE_AMOUNT_OPERATORS(T) \
|
||||
inline amount_t operator+(const T val, const amount_t& amt) { \
|
||||
amount_t temp(val); \
|
||||
|
|
|
|||
|
|
@ -414,9 +414,9 @@ void export_balance()
|
|||
.def(self != long())
|
||||
.def(! self)
|
||||
|
||||
.def(abs(self))
|
||||
.def(self_ns::str(self))
|
||||
|
||||
.def("__abs__", &balance_t::abs)
|
||||
.def("__len__", balance_len)
|
||||
.def("__getitem__", balance_getitem)
|
||||
|
||||
|
|
@ -502,9 +502,9 @@ void export_balance()
|
|||
.def(self != long())
|
||||
.def(! self)
|
||||
|
||||
.def(abs(self))
|
||||
.def(self_ns::str(self))
|
||||
|
||||
.def("__abs__", &balance_pair_t::abs)
|
||||
.def("__len__", balance_pair_len)
|
||||
.def("__getitem__", balance_pair_getitem)
|
||||
|
||||
|
|
|
|||
122
balance.h
122
balance.h
|
|
@ -391,19 +391,19 @@ class balance_t
|
|||
}
|
||||
|
||||
// unary negation
|
||||
void negate() {
|
||||
void in_place_negate() {
|
||||
for (amounts_map::iterator i = amounts.begin();
|
||||
i != amounts.end();
|
||||
i++)
|
||||
(*i).second.negate();
|
||||
(*i).second = (*i).second.negate();
|
||||
}
|
||||
balance_t negated() const {
|
||||
balance_t negate() const {
|
||||
balance_t temp = *this;
|
||||
temp.negate();
|
||||
temp.in_place_negate();
|
||||
return temp;
|
||||
}
|
||||
balance_t operator-() const {
|
||||
return negated();
|
||||
return negate();
|
||||
}
|
||||
|
||||
// conversion operators
|
||||
|
|
@ -428,11 +428,11 @@ class balance_t
|
|||
return true;
|
||||
}
|
||||
|
||||
amount_t amount(const commodity_t& commodity =
|
||||
*commodity_t::null_commodity) const;
|
||||
balance_t value(const ptime& moment = now) const;
|
||||
balance_t price() const;
|
||||
ptime date() const;
|
||||
amount_t amount(const commodity_t& commodity =
|
||||
*commodity_t::null_commodity) const;
|
||||
balance_t value(const ptime& moment = now) const;
|
||||
balance_t price() const;
|
||||
ptime date() const;
|
||||
|
||||
balance_t
|
||||
strip_annotations(const bool keep_price = amount_t::keep_price,
|
||||
|
|
@ -442,32 +442,40 @@ class balance_t
|
|||
void write(std::ostream& out, const int first_width,
|
||||
const int latter_width = -1) const;
|
||||
|
||||
void abs() {
|
||||
void in_place_abs() {
|
||||
for (amounts_map::iterator i = amounts.begin();
|
||||
i != amounts.end();
|
||||
i++)
|
||||
(*i).second.abs();
|
||||
(*i).second = (*i).second.abs();
|
||||
}
|
||||
|
||||
void reduce() {
|
||||
for (amounts_map::iterator i = amounts.begin();
|
||||
i != amounts.end();
|
||||
i++)
|
||||
(*i).second.reduce();
|
||||
}
|
||||
|
||||
balance_t reduced() const {
|
||||
balance_t temp(*this);
|
||||
temp.reduce();
|
||||
balance_t abs() const {
|
||||
balance_t temp = *this;
|
||||
temp.in_place_abs();
|
||||
return temp;
|
||||
}
|
||||
|
||||
void round() {
|
||||
void in_place_reduce() {
|
||||
for (amounts_map::iterator i = amounts.begin();
|
||||
i != amounts.end();
|
||||
i++)
|
||||
if ((*i).second.commodity())
|
||||
(*i).second = (*i).second.round();
|
||||
(*i).second.in_place_reduce();
|
||||
}
|
||||
balance_t reduce() const {
|
||||
balance_t temp(*this);
|
||||
temp.in_place_reduce();
|
||||
return temp;
|
||||
}
|
||||
|
||||
void in_place_round() {
|
||||
for (amounts_map::iterator i = amounts.begin();
|
||||
i != amounts.end();
|
||||
i++)
|
||||
(*i).second = (*i).second.round();
|
||||
}
|
||||
balance_t round() const {
|
||||
balance_t temp(*this);
|
||||
temp.in_place_round();
|
||||
return temp;
|
||||
}
|
||||
|
||||
balance_t unround() const {
|
||||
|
|
@ -481,12 +489,6 @@ class balance_t
|
|||
}
|
||||
};
|
||||
|
||||
inline balance_t abs(const balance_t& bal) {
|
||||
balance_t temp = bal;
|
||||
temp.abs();
|
||||
return temp;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const balance_t& bal) {
|
||||
bal.write(out, 12);
|
||||
return out;
|
||||
|
|
@ -843,17 +845,18 @@ class balance_pair_t
|
|||
}
|
||||
|
||||
// unary negation
|
||||
void negate() {
|
||||
quantity.negate();
|
||||
if (cost) cost->negate();
|
||||
void in_place_negate() {
|
||||
quantity = quantity.negate();
|
||||
if (cost)
|
||||
*cost = cost->negate();
|
||||
}
|
||||
balance_pair_t negated() const {
|
||||
balance_pair_t negate() const {
|
||||
balance_pair_t temp = *this;
|
||||
temp.negate();
|
||||
temp.in_place_negate();
|
||||
return temp;
|
||||
}
|
||||
balance_pair_t operator-() const {
|
||||
return negated();
|
||||
return negate();
|
||||
}
|
||||
|
||||
// test for non-zero (use ! for zero)
|
||||
|
|
@ -871,9 +874,15 @@ class balance_pair_t
|
|||
return ((! cost || cost->realzero()) && quantity.realzero());
|
||||
}
|
||||
|
||||
void abs() {
|
||||
quantity.abs();
|
||||
if (cost) cost->abs();
|
||||
balance_pair_t in_place_abs() {
|
||||
quantity = quantity.abs();
|
||||
if (cost)
|
||||
*cost = cost->abs();
|
||||
}
|
||||
balance_pair_t abs() const {
|
||||
balance_pair_t temp = *this;
|
||||
temp.in_place_abs();
|
||||
return temp;
|
||||
}
|
||||
|
||||
amount_t amount(const commodity_t& commodity =
|
||||
|
|
@ -886,7 +895,7 @@ class balance_pair_t
|
|||
balance_t price() const {
|
||||
return quantity.price();
|
||||
}
|
||||
ptime date() const {
|
||||
ptime date() const {
|
||||
return quantity.date();
|
||||
}
|
||||
|
||||
|
|
@ -916,20 +925,25 @@ class balance_pair_t
|
|||
return quantity.valid() && (! cost || cost->valid());
|
||||
}
|
||||
|
||||
void reduce() {
|
||||
quantity.reduce();
|
||||
if (cost) cost->reduce();
|
||||
void in_place_reduce() {
|
||||
quantity.in_place_reduce();
|
||||
if (cost) cost->in_place_reduce();
|
||||
}
|
||||
|
||||
balance_pair_t reduced() const {
|
||||
balance_pair_t reduce() const {
|
||||
balance_pair_t temp(*this);
|
||||
temp.reduce();
|
||||
temp.in_place_reduce();
|
||||
return temp;
|
||||
}
|
||||
|
||||
void round() {
|
||||
quantity.round();
|
||||
if (cost) cost->round();
|
||||
void in_place_round() {
|
||||
quantity = quantity.round();
|
||||
if (cost)
|
||||
*cost = cost->round();
|
||||
}
|
||||
balance_pair_t round() const {
|
||||
balance_pair_t temp(*this);
|
||||
temp.in_place_round();
|
||||
return temp;
|
||||
}
|
||||
|
||||
balance_pair_t unround() {
|
||||
|
|
@ -940,12 +954,6 @@ class balance_pair_t
|
|||
}
|
||||
};
|
||||
|
||||
inline balance_pair_t abs(const balance_pair_t& bal_pair) {
|
||||
balance_pair_t temp(bal_pair);
|
||||
temp.abs();
|
||||
return temp;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out,
|
||||
const balance_pair_t& bal_pair) {
|
||||
bal_pair.quantity.write(out, 12);
|
||||
|
|
|
|||
202
configure
vendored
202
configure
vendored
|
|
@ -19696,14 +19696,14 @@ _ACEOF
|
|||
|
||||
fi
|
||||
|
||||
# check for gmp
|
||||
{ echo "$as_me:$LINENO: checking if libgmp is available" >&5
|
||||
echo $ECHO_N "checking if libgmp is available... $ECHO_C" >&6; }
|
||||
if test "${libgmp_avail+set}" = set; then
|
||||
# check for boost_regex
|
||||
{ echo "$as_me:$LINENO: checking if boost_regex is available" >&5
|
||||
echo $ECHO_N "checking if boost_regex is available... $ECHO_C" >&6; }
|
||||
if test "${boost_regex_avail+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
libgmp_save_libs=$LIBS
|
||||
LIBS="-lgmp $LIBS"
|
||||
boost_regex_save_libs=$LIBS
|
||||
LIBS="-lboost_regex $LIBS"
|
||||
ac_ext=cpp
|
||||
ac_cpp='$CXXCPP $CPPFLAGS'
|
||||
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||
|
|
@ -19716,13 +19716,11 @@ _ACEOF
|
|||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
#include <gmp.h>
|
||||
#include <boost/regex.hpp>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
mpz_t bar;
|
||||
mpz_init(bar);
|
||||
mpz_clear(bar);
|
||||
boost::regex foo_regexp("Hello, world!");
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -19745,12 +19743,12 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
|||
test ! -s conftest.err
|
||||
} && test -s conftest$ac_exeext &&
|
||||
$as_test_x conftest$ac_exeext; then
|
||||
libgmp_avail=true
|
||||
boost_regex_avail=true
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
libgmp_avail=false
|
||||
boost_regex_avail=false
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
|
||||
|
|
@ -19761,100 +19759,22 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
|||
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||
ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
LIBS=$libgmp_save_libs
|
||||
LIBS=$boost_regex_save_libs
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: result: $libgmp_avail" >&5
|
||||
echo "${ECHO_T}$libgmp_avail" >&6; }
|
||||
{ echo "$as_me:$LINENO: result: $boost_regex_avail" >&5
|
||||
echo "${ECHO_T}$boost_regex_avail" >&6; }
|
||||
|
||||
if test x$libgmp_avail = xtrue ; then
|
||||
LIBS="-lgmp $LIBS"
|
||||
if test x$boost_regex_avail = xtrue ; then
|
||||
LIBS="-lboost_regex $LIBS"
|
||||
else
|
||||
{ { echo "$as_me:$LINENO: error: \"Could not find gmp library (set CPPFLAGS and LDFLAGS?)\"
|
||||
{ { echo "$as_me:$LINENO: error: \"Could not find boost_regex library (set CPPFLAGS and LDFLAGS?)\"
|
||||
See \`config.log' for more details." >&5
|
||||
echo "$as_me: error: \"Could not find gmp library (set CPPFLAGS and LDFLAGS?)\"
|
||||
echo "$as_me: error: \"Could not find boost_regex library (set CPPFLAGS and LDFLAGS?)\"
|
||||
See \`config.log' for more details." >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
fi
|
||||
|
||||
# check for pcre
|
||||
{ echo "$as_me:$LINENO: checking if libpcre is available" >&5
|
||||
echo $ECHO_N "checking if libpcre is available... $ECHO_C" >&6; }
|
||||
if test "${libpcre_avail+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
libpcre_save_libs=$LIBS
|
||||
LIBS="-lpcre $LIBS"
|
||||
ac_ext=cpp
|
||||
ac_cpp='$CXXCPP $CPPFLAGS'
|
||||
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||
ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
|
||||
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
#include <pcre.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
pcre_free((pcre *)NULL);
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext conftest$ac_exeext
|
||||
if { (ac_try="$ac_link"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_link") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } && {
|
||||
test -z "$ac_cxx_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest$ac_exeext &&
|
||||
$as_test_x conftest$ac_exeext; then
|
||||
libpcre_avail=true
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
libpcre_avail=false
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
ac_ext=c
|
||||
ac_cpp='$CPP $CPPFLAGS'
|
||||
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||
ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
LIBS=$libpcre_save_libs
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: result: $libpcre_avail" >&5
|
||||
echo "${ECHO_T}$libpcre_avail" >&6; }
|
||||
|
||||
if test x$libpcre_avail = xtrue ; then
|
||||
LIBS="-lpcre $LIBS"
|
||||
else
|
||||
{ { echo "$as_me:$LINENO: error: \"Could not find pcre library (set CPPFLAGS and LDFLAGS?)\"
|
||||
See \`config.log' for more details." >&5
|
||||
echo "$as_me: error: \"Could not find pcre library (set CPPFLAGS and LDFLAGS?)\"
|
||||
See \`config.log' for more details." >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
fi
|
||||
|
||||
# check for Boost date_time
|
||||
# check for boost_date_time
|
||||
{ echo "$as_me:$LINENO: checking if boost_date_time is available" >&5
|
||||
echo $ECHO_N "checking if boost_date_time is available... $ECHO_C" >&6; }
|
||||
if test "${boost_date_time_cpplib_avail+set}" = set; then
|
||||
|
|
@ -19950,6 +19870,86 @@ See \`config.log' for more details." >&2;}
|
|||
{ (exit 1); exit 1; }; }
|
||||
fi
|
||||
|
||||
# check for gmp
|
||||
{ echo "$as_me:$LINENO: checking if libgmp is available" >&5
|
||||
echo $ECHO_N "checking if libgmp is available... $ECHO_C" >&6; }
|
||||
if test "${libgmp_avail+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
libgmp_save_libs=$LIBS
|
||||
LIBS="-lgmp $LIBS"
|
||||
ac_ext=cpp
|
||||
ac_cpp='$CXXCPP $CPPFLAGS'
|
||||
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||
ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
|
||||
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
#include <gmp.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
mpz_t bar;
|
||||
mpz_init(bar);
|
||||
mpz_clear(bar);
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext conftest$ac_exeext
|
||||
if { (ac_try="$ac_link"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_link") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } && {
|
||||
test -z "$ac_cxx_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest$ac_exeext &&
|
||||
$as_test_x conftest$ac_exeext; then
|
||||
libgmp_avail=true
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
libgmp_avail=false
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
ac_ext=c
|
||||
ac_cpp='$CPP $CPPFLAGS'
|
||||
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||
ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
LIBS=$libgmp_save_libs
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: result: $libgmp_avail" >&5
|
||||
echo "${ECHO_T}$libgmp_avail" >&6; }
|
||||
|
||||
if test x$libgmp_avail = xtrue ; then
|
||||
LIBS="-lgmp $LIBS"
|
||||
else
|
||||
{ { echo "$as_me:$LINENO: error: \"Could not find gmp library (set CPPFLAGS and LDFLAGS?)\"
|
||||
See \`config.log' for more details." >&5
|
||||
echo "$as_me: error: \"Could not find gmp library (set CPPFLAGS and LDFLAGS?)\"
|
||||
See \`config.log' for more details." >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
fi
|
||||
|
||||
# check for expat or xmlparse
|
||||
# Check whether --enable-xml was given.
|
||||
if test "${enable_xml+set}" = set; then
|
||||
|
|
@ -20837,7 +20837,8 @@ _ACEOF
|
|||
fi
|
||||
|
||||
|
||||
for ac_header in sys/stat.h
|
||||
|
||||
for ac_header in sys/stat.h langinfo.h
|
||||
do
|
||||
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
|
||||
|
|
@ -21475,7 +21476,8 @@ fi
|
|||
|
||||
|
||||
|
||||
for ac_func in access mktime realpath getpwuid getpwnam
|
||||
|
||||
for ac_func in access mktime realpath getpwuid getpwnam nl_langinfo
|
||||
do
|
||||
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
{ echo "$as_me:$LINENO: checking for $ac_func" >&5
|
||||
|
|
|
|||
78
configure.in
78
configure.in
|
|
@ -68,51 +68,28 @@ if [test x$pipes_avail = xtrue ]; then
|
|||
AC_DEFINE([HAVE_UNIX_PIPES], [1], [Whether UNIX pipes are available])
|
||||
fi
|
||||
|
||||
# check for gmp
|
||||
# check for boost_regex
|
||||
AC_CACHE_CHECK(
|
||||
[if libgmp is available],
|
||||
[libgmp_avail],
|
||||
[libgmp_save_libs=$LIBS
|
||||
LIBS="-lgmp $LIBS"
|
||||
[if boost_regex is available],
|
||||
[boost_regex_avail],
|
||||
[boost_regex_save_libs=$LIBS
|
||||
LIBS="-lboost_regex $LIBS"
|
||||
AC_LANG_PUSH(C++)
|
||||
AC_TRY_LINK(
|
||||
[#include <gmp.h>],
|
||||
[mpz_t bar;
|
||||
mpz_init(bar);
|
||||
mpz_clear(bar);],
|
||||
[libgmp_avail=true],
|
||||
[libgmp_avail=false])
|
||||
[#include <boost/regex.hpp>],
|
||||
[boost::regex foo_regexp("Hello, world!");],
|
||||
[boost_regex_avail=true],
|
||||
[boost_regex_avail=false])
|
||||
AC_LANG_POP
|
||||
LIBS=$libgmp_save_libs])
|
||||
LIBS=$boost_regex_save_libs])
|
||||
|
||||
if [test x$libgmp_avail = xtrue ]; then
|
||||
LIBS="-lgmp $LIBS"
|
||||
if [test x$boost_regex_avail = xtrue ]; then
|
||||
LIBS="-lboost_regex $LIBS"
|
||||
else
|
||||
AC_MSG_FAILURE("Could not find gmp library (set CPPFLAGS and LDFLAGS?)")
|
||||
AC_MSG_FAILURE("Could not find boost_regex library (set CPPFLAGS and LDFLAGS?)")
|
||||
fi
|
||||
|
||||
# check for pcre
|
||||
AC_CACHE_CHECK(
|
||||
[if libpcre is available],
|
||||
[libpcre_avail],
|
||||
[libpcre_save_libs=$LIBS
|
||||
LIBS="-lpcre $LIBS"
|
||||
AC_LANG_PUSH(C++)
|
||||
AC_TRY_LINK(
|
||||
[#include <pcre.h>],
|
||||
[pcre_free((pcre *)NULL);],
|
||||
[libpcre_avail=true],
|
||||
[libpcre_avail=false])
|
||||
AC_LANG_POP
|
||||
LIBS=$libpcre_save_libs])
|
||||
|
||||
if [test x$libpcre_avail = xtrue ]; then
|
||||
LIBS="-lpcre $LIBS"
|
||||
else
|
||||
AC_MSG_FAILURE("Could not find pcre library (set CPPFLAGS and LDFLAGS?)")
|
||||
fi
|
||||
|
||||
# check for Boost date_time
|
||||
# check for boost_date_time
|
||||
AC_CACHE_CHECK(
|
||||
[if boost_date_time is available],
|
||||
[boost_date_time_cpplib_avail],
|
||||
|
|
@ -151,6 +128,29 @@ else
|
|||
AC_MSG_FAILURE("Could not find boost_date_time library (set CPPFLAGS and LDFLAGS?)")
|
||||
fi
|
||||
|
||||
# check for gmp
|
||||
AC_CACHE_CHECK(
|
||||
[if libgmp is available],
|
||||
[libgmp_avail],
|
||||
[libgmp_save_libs=$LIBS
|
||||
LIBS="-lgmp $LIBS"
|
||||
AC_LANG_PUSH(C++)
|
||||
AC_TRY_LINK(
|
||||
[#include <gmp.h>],
|
||||
[mpz_t bar;
|
||||
mpz_init(bar);
|
||||
mpz_clear(bar);],
|
||||
[libgmp_avail=true],
|
||||
[libgmp_avail=false])
|
||||
AC_LANG_POP
|
||||
LIBS=$libgmp_save_libs])
|
||||
|
||||
if [test x$libgmp_avail = xtrue ]; then
|
||||
LIBS="-lgmp $LIBS"
|
||||
else
|
||||
AC_MSG_FAILURE("Could not find gmp library (set CPPFLAGS and LDFLAGS?)")
|
||||
fi
|
||||
|
||||
# check for expat or xmlparse
|
||||
AC_ARG_ENABLE(xml,
|
||||
[ --enable-xml Turn on support for XML parsing],
|
||||
|
|
@ -319,7 +319,7 @@ AM_CONDITIONAL(DEBUG, test x$debug = xtrue)
|
|||
|
||||
# Checks for header files.
|
||||
AC_STDC_HEADERS
|
||||
AC_HAVE_HEADERS(sys/stat.h)
|
||||
AC_HAVE_HEADERS(sys/stat.h langinfo.h)
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_HEADER_STDBOOL
|
||||
|
|
@ -329,7 +329,7 @@ AC_STRUCT_TM
|
|||
# Checks for library functions.
|
||||
#AC_FUNC_ERROR_AT_LINE
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_FUNCS([access mktime realpath getpwuid getpwnam])
|
||||
AC_CHECK_FUNCS([access mktime realpath getpwuid getpwnam nl_langinfo])
|
||||
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_OUTPUT
|
||||
|
|
|
|||
9
debug.cc
9
debug.cc
|
|
@ -81,13 +81,8 @@ bool _free_debug_stream = false;
|
|||
|
||||
bool _debug_active(const char * const cls) {
|
||||
if (char * debug = std::getenv("DEBUG_CLASS")) {
|
||||
static const char * error;
|
||||
static int erroffset;
|
||||
static int ovec[30];
|
||||
static pcre * class_regexp = pcre_compile(debug, PCRE_CASELESS,
|
||||
&error, &erroffset, NULL);
|
||||
return pcre_exec(class_regexp, NULL, cls, std::strlen(cls),
|
||||
0, 0, ovec, 30) >= 0;
|
||||
static boost::regex class_regexp(debug);
|
||||
return boost::regex_match(cls, class_regexp);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
3
debug.h
3
debug.h
|
|
@ -57,12 +57,13 @@ void debug_assert(const std::string& reason,
|
|||
|
||||
#if DEBUG_LEVEL >= ALPHA
|
||||
|
||||
#include <pcre.h>
|
||||
#include <cstring>
|
||||
#include <new>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
#define DEBUG_ENABLED
|
||||
|
||||
extern std::ostream * _debug_stream;
|
||||
|
|
|
|||
16
journal.cc
16
journal.cc
|
|
@ -124,7 +124,7 @@ bool entry_base_t::finalize()
|
|||
ann_comm(static_cast<annotated_commodity_t&>
|
||||
((*x)->amount.commodity()));
|
||||
if (ann_comm.price)
|
||||
balance += ann_comm.price * (*x)->amount - *((*x)->cost);
|
||||
balance += ann_comm.price * (*x)->amount.number() - *((*x)->cost);
|
||||
}
|
||||
} else {
|
||||
saw_null = true;
|
||||
|
|
@ -165,7 +165,7 @@ bool entry_base_t::finalize()
|
|||
other_bal++;
|
||||
|
||||
amount_t per_unit_cost =
|
||||
amount_t((*other_bal).second / (*this_bal).second).unround();
|
||||
amount_t((*other_bal).second / (*this_bal).second.number()).unround();
|
||||
|
||||
for (; x != transactions.end(); x++) {
|
||||
if ((*x)->cost || ((*x)->flags & TRANSACTION_VIRTUAL) ||
|
||||
|
|
@ -180,11 +180,11 @@ bool entry_base_t::finalize()
|
|||
if ((*x)->amount.commodity() &&
|
||||
! (*x)->amount.commodity().annotated)
|
||||
(*x)->amount.annotate_commodity
|
||||
(abs(per_unit_cost),
|
||||
(per_unit_cost.abs(),
|
||||
entry ? entry->actual_date() : ptime(),
|
||||
entry ? entry->code : "");
|
||||
|
||||
(*x)->cost = new amount_t(- (per_unit_cost * (*x)->amount));
|
||||
(*x)->cost = new amount_t(- (per_unit_cost * (*x)->amount.number()));
|
||||
balance += *(*x)->cost;
|
||||
}
|
||||
}
|
||||
|
|
@ -228,8 +228,7 @@ bool entry_base_t::finalize()
|
|||
for (amounts_map::const_iterator i = bal->amounts.begin();
|
||||
i != bal->amounts.end();
|
||||
i++) {
|
||||
amount_t amt = (*i).second;
|
||||
amt.negate();
|
||||
amount_t amt = (*i).second.negate();
|
||||
|
||||
if (first) {
|
||||
(*x)->amount = amt;
|
||||
|
|
@ -248,8 +247,7 @@ bool entry_base_t::finalize()
|
|||
// fall through...
|
||||
|
||||
case value_t::AMOUNT:
|
||||
(*x)->amount = *((amount_t *) balance.data);
|
||||
(*x)->amount.negate();
|
||||
(*x)->amount = ((amount_t *) balance.data)->negate();
|
||||
(*x)->flags |= TRANSACTION_CALCULATED;
|
||||
|
||||
balance += (*x)->amount;
|
||||
|
|
@ -552,7 +550,7 @@ bool journal_t::add_entry(entry_t * entry)
|
|||
i++)
|
||||
if ((*i)->cost && (*i)->amount)
|
||||
(*i)->amount.commodity().add_price(entry->date(),
|
||||
*(*i)->cost / (*i)->amount);
|
||||
*(*i)->cost / (*i)->amount.number());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ class transaction_t
|
|||
enum state_t { UNCLEARED, CLEARED, PENDING };
|
||||
|
||||
entry_t * entry;
|
||||
ptime _date;
|
||||
ptime _date_eff;
|
||||
ptime _date;
|
||||
ptime _date_eff;
|
||||
account_t * account;
|
||||
amount_t amount;
|
||||
std::string amount_expr;
|
||||
|
|
@ -151,8 +151,8 @@ class entry_base_t
|
|||
class entry_t : public entry_base_t
|
||||
{
|
||||
public:
|
||||
ptime _date;
|
||||
ptime _date_eff;
|
||||
ptime _date;
|
||||
ptime _date_eff;
|
||||
std::string code;
|
||||
std::string payee;
|
||||
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@
|
|||
|
||||
(require 'esh-util)
|
||||
(require 'esh-arg)
|
||||
(require 'pcomplete)
|
||||
|
||||
(defvar ledger-version "1.2"
|
||||
"The version of ledger.el currently loaded")
|
||||
|
|
|
|||
2
ledger.h
2
ledger.h
|
|
@ -34,6 +34,8 @@
|
|||
#include <report.h>
|
||||
#include <transform.h>
|
||||
|
||||
#include <register.h>
|
||||
|
||||
#if 0
|
||||
#include <emacs.h>
|
||||
#include <csv.h>
|
||||
|
|
|
|||
36
main.cc
36
main.cc
|
|
@ -28,16 +28,6 @@
|
|||
|
||||
using namespace ledger;
|
||||
|
||||
static inline
|
||||
const std::string& either_or(const std::string& first,
|
||||
const std::string& second)
|
||||
{
|
||||
if (first.empty())
|
||||
return second;
|
||||
else
|
||||
return first;
|
||||
}
|
||||
|
||||
#if 0
|
||||
class print_addr : public repitem_t::select_callback_t {
|
||||
virtual void operator()(repitem_t * item) {
|
||||
|
|
@ -107,15 +97,16 @@ static int read_and_report(report_t * report, int argc, char * argv[],
|
|||
|
||||
xml::xpath_t::functor_t * command = NULL;
|
||||
|
||||
if (false) {
|
||||
;
|
||||
}
|
||||
#if 0
|
||||
if (verb == "register" || verb == "reg" || verb == "r") {
|
||||
#if 1
|
||||
command = new register_command;
|
||||
#else
|
||||
command = new format_command
|
||||
("register", either_or(report->format_string,
|
||||
report->session->register_format));
|
||||
#endif
|
||||
}
|
||||
#if 0
|
||||
else if (verb == "balance" || verb == "bal" || verb == "b") {
|
||||
if (! report->raw_mode) {
|
||||
report->transforms.push_back(new accounts_transform);
|
||||
|
|
@ -311,14 +302,10 @@ static int read_and_report(report_t * report, int argc, char * argv[],
|
|||
locals->args.push_back(journal->document);
|
||||
|
||||
if (command->wants_args) {
|
||||
#if 1
|
||||
locals->args.push_back(&args);
|
||||
#else
|
||||
for (strings_list::iterator i = args.begin();
|
||||
i != args.end();
|
||||
i++)
|
||||
locals->args.push_back(*i);
|
||||
#endif
|
||||
} else {
|
||||
std::string regexps[4];
|
||||
|
||||
|
|
@ -367,9 +354,16 @@ static int read_and_report(report_t * report, int argc, char * argv[],
|
|||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
report->apply_transforms(items.get());
|
||||
#endif
|
||||
xml::document_t * xml_doc = new xml::document_t;
|
||||
xml::journal_node_t * journal_node = new xml::journal_node_t(xml_doc, journal);
|
||||
|
||||
xml_doc->set_top(journal_node);
|
||||
|
||||
assert(xml_doc->top == journal_node);
|
||||
assert(journal_node->document == xml_doc);
|
||||
assert(journal_node->document->top == journal_node);
|
||||
|
||||
report->apply_transforms(xml_doc);
|
||||
|
||||
value_t temp;
|
||||
(*command)(temp, locals);
|
||||
|
|
|
|||
39
mask.cc
39
mask.cc
|
|
@ -4,13 +4,10 @@
|
|||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <pcre.h>
|
||||
|
||||
mask_t::mask_t(const std::string& pat) : exclude(false)
|
||||
{
|
||||
TRACE_CTOR("mask_t(const std::string&)");
|
||||
|
||||
const char * p = pat.c_str();
|
||||
|
||||
if (*p == '-') {
|
||||
exclude = true;
|
||||
p++;
|
||||
|
|
@ -22,38 +19,6 @@ mask_t::mask_t(const std::string& pat) : exclude(false)
|
|||
while (std::isspace(*p))
|
||||
p++;
|
||||
}
|
||||
pattern = p;
|
||||
|
||||
const char *error;
|
||||
int erroffset;
|
||||
regexp = pcre_compile(pattern.c_str(), PCRE_CASELESS,
|
||||
&error, &erroffset, NULL);
|
||||
if (! regexp)
|
||||
throw new mask_error(std::string("Failed to compile regexp '") +
|
||||
pattern + "'");
|
||||
}
|
||||
|
||||
mask_t::mask_t(const mask_t& m) : exclude(m.exclude), pattern(m.pattern)
|
||||
{
|
||||
TRACE_CTOR("mask_t(copy)");
|
||||
|
||||
const char *error;
|
||||
int erroffset;
|
||||
regexp = pcre_compile(pattern.c_str(), PCRE_CASELESS,
|
||||
&error, &erroffset, NULL);
|
||||
assert(regexp);
|
||||
}
|
||||
|
||||
mask_t::~mask_t() {
|
||||
TRACE_DTOR("mask_t");
|
||||
if (regexp)
|
||||
pcre_free((pcre *)regexp);
|
||||
}
|
||||
|
||||
bool mask_t::match(const std::string& str) const
|
||||
{
|
||||
static int ovec[30];
|
||||
int result = pcre_exec((pcre *)regexp, NULL,
|
||||
str.c_str(), str.length(), 0, 0, ovec, 30);
|
||||
return result >= 0 && ! exclude;
|
||||
expr.assign(p);
|
||||
}
|
||||
|
|
|
|||
14
mask.h
14
mask.h
|
|
@ -6,18 +6,20 @@
|
|||
#include <string>
|
||||
#include <exception>
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
class mask_t
|
||||
{
|
||||
public:
|
||||
bool exclude;
|
||||
std::string pattern;
|
||||
void * regexp;
|
||||
bool exclude;
|
||||
boost::regex expr;
|
||||
|
||||
explicit mask_t(const std::string& pattern);
|
||||
mask_t(const mask_t&);
|
||||
~mask_t();
|
||||
mask_t(const mask_t& m) : exclude(m.exclude), expr(m.expr) {}
|
||||
|
||||
bool match(const std::string& str) const;
|
||||
bool match(const std::string& str) const {
|
||||
return boost::regex_match(str, expr) && ! exclude;
|
||||
}
|
||||
};
|
||||
|
||||
class mask_error : public error {
|
||||
|
|
|
|||
105
parsetime.yy
105
parsetime.yy
|
|
@ -135,91 +135,28 @@ date: absdate opttime
|
|||
};
|
||||
|
||||
absdate:
|
||||
year '/' morday '/' morday {
|
||||
set_mdy($3, $5, $1);
|
||||
}
|
||||
|
|
||||
year '-' morday '-' morday {
|
||||
set_mdy($3, $5, $1);
|
||||
}
|
||||
|
|
||||
year '.' morday '.' morday {
|
||||
set_mdy($3, $5, $1);
|
||||
}
|
||||
|
|
||||
morday '/' morday '/' year {
|
||||
set_mdy($1, $3, $5);
|
||||
}
|
||||
|
|
||||
morday '-' morday '-' year {
|
||||
set_mdy($1, $3, $5);
|
||||
}
|
||||
|
|
||||
morday '.' morday '.' year {
|
||||
set_mdy($1, $3, $5);
|
||||
}
|
||||
|
|
||||
morday '.' morday {
|
||||
set_mdy($1, $3);
|
||||
}
|
||||
|
|
||||
morday '/' morday {
|
||||
set_mdy($1, $3);
|
||||
}
|
||||
|
|
||||
morday '-' morday {
|
||||
set_mdy($1, $3);
|
||||
}
|
||||
|
|
||||
morday '/' morday '/' TOK_TWONUM {
|
||||
set_mdy($1, $3, $5, true);
|
||||
}
|
||||
|
|
||||
morday '-' morday '-' TOK_TWONUM {
|
||||
set_mdy($1, $3, $5, true);
|
||||
}
|
||||
|
|
||||
morday '.' morday '.' TOK_TWONUM {
|
||||
set_mdy($1, $3, $5, true);
|
||||
}
|
||||
|
|
||||
isodate
|
||||
|
|
||||
year TOK_SPACE TOK_MONTH TOK_SPACE morday {
|
||||
set_mdy($3, $5, $1);
|
||||
}
|
||||
|
|
||||
morday TOK_SPACE TOK_MONTH TOK_SPACE year {
|
||||
set_mdy($3, $1, $5);
|
||||
}
|
||||
|
|
||||
TOK_MONTH TOK_SPACE morday {
|
||||
set_mdy($1, $3);
|
||||
}
|
||||
|
|
||||
morday TOK_SPACE TOK_MONTH {
|
||||
set_mdy($3, $1);
|
||||
}
|
||||
|
|
||||
year '-' TOK_MONTH '-' morday {
|
||||
set_mdy($3, $5, $1);
|
||||
}
|
||||
|
|
||||
morday '-' TOK_MONTH '-' year {
|
||||
set_mdy($3, $1, $5);
|
||||
}
|
||||
|
|
||||
TOK_MONTH '-' morday {
|
||||
set_mdy($1, $3);
|
||||
}
|
||||
|
|
||||
morday '-' TOK_MONTH {
|
||||
set_mdy($3, $1);
|
||||
}
|
||||
|
|
||||
TOK_MONTH TOK_SPACE morday ',' TOK_SPACE year {
|
||||
set_mdy($1, $3, $6);
|
||||
}
|
||||
| year '/' morday '/' morday { set_mdy($3, $5, $1); }
|
||||
| year '-' morday '-' morday { set_mdy($3, $5, $1); }
|
||||
| year '.' morday '.' morday { set_mdy($3, $5, $1); }
|
||||
| morday '/' morday '/' year { set_mdy($1, $3, $5); }
|
||||
| morday '-' morday '-' year { set_mdy($1, $3, $5); }
|
||||
| morday '.' morday '.' year { set_mdy($1, $3, $5); }
|
||||
| morday '.' morday { set_mdy($1, $3); }
|
||||
| morday '/' morday { set_mdy($1, $3); }
|
||||
| morday '-' morday { set_mdy($1, $3); }
|
||||
| morday '/' morday '/' TOK_TWONUM { set_mdy($1, $3, $5, true); }
|
||||
| morday '-' morday '-' TOK_TWONUM { set_mdy($1, $3, $5, true); }
|
||||
| morday '.' morday '.' TOK_TWONUM { set_mdy($1, $3, $5, true); }
|
||||
| year TOK_SPACE TOK_MONTH TOK_SPACE morday { set_mdy($3, $5, $1); }
|
||||
| morday TOK_SPACE TOK_MONTH TOK_SPACE year { set_mdy($3, $1, $5); }
|
||||
| TOK_MONTH TOK_SPACE morday { set_mdy($1, $3); }
|
||||
| morday TOK_SPACE TOK_MONTH { set_mdy($3, $1); }
|
||||
| year '-' TOK_MONTH '-' morday { set_mdy($3, $5, $1); }
|
||||
| morday '-' TOK_MONTH '-' year { set_mdy($3, $1, $5); }
|
||||
| TOK_MONTH '-' morday { set_mdy($1, $3); }
|
||||
| morday '-' TOK_MONTH { set_mdy($3, $1); }
|
||||
| TOK_MONTH TOK_SPACE morday ',' TOK_SPACE year { set_mdy($1, $3, $6); }
|
||||
;
|
||||
|
||||
opttime: /* epsilon */ | TOK_SPACE time ;
|
||||
|
|
|
|||
|
|
@ -136,7 +136,6 @@ void export_amount()
|
|||
|
||||
.def(self_ns::int_(self))
|
||||
.def(self_ns::float_(self))
|
||||
.def(abs(self))
|
||||
|
||||
.def("__str__", &amount_t::to_string)
|
||||
.def("__repr__", &amount_t::to_fullstring)
|
||||
|
|
@ -162,18 +161,16 @@ void export_amount()
|
|||
.def("exact", &amount_t::exact)
|
||||
.staticmethod("exact")
|
||||
|
||||
.def("abs", &amount_t::abs)
|
||||
.def("__abs__", &amount_t::abs)
|
||||
.def("compare", &amount_t::compare)
|
||||
.def("date", &amount_t::date)
|
||||
.def("negate", &amount_t::negate)
|
||||
.def("negated", &amount_t::negated)
|
||||
.def("null", &amount_t::null)
|
||||
.def("parse", py_parse_1)
|
||||
.def("parse", py_parse_2)
|
||||
.def("price", &amount_t::price)
|
||||
.def("realzero", &amount_t::realzero)
|
||||
.def("reduce", &amount_t::reduce)
|
||||
.def("reduced", &amount_t::reduced)
|
||||
.def("round", py_round_1)
|
||||
.def("round", py_round_2)
|
||||
.def("sign", &amount_t::sign)
|
||||
|
|
|
|||
4
qif.cc
4
qif.cc
|
|
@ -126,7 +126,7 @@ unsigned int qif_parser_t::parse(std::istream& in,
|
|||
|
||||
if (c == '$') {
|
||||
saw_splits = true;
|
||||
xact->amount.negate();
|
||||
xact->amount.in_place_negate();
|
||||
} else {
|
||||
total = xact;
|
||||
}
|
||||
|
|
@ -202,7 +202,7 @@ unsigned int qif_parser_t::parse(std::istream& in,
|
|||
|
||||
if (total && saw_category) {
|
||||
if (! saw_splits)
|
||||
total->amount.negate(); // negate, to show correct flow
|
||||
total->amount.in_place_negate(); // negate, to show correct flow
|
||||
else
|
||||
total->account = other;
|
||||
}
|
||||
|
|
|
|||
31
register.cc
Normal file
31
register.cc
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#include "register.h"
|
||||
#include "journal.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
void register_command::print_document(std::ostream& out,
|
||||
xml::document_t * doc)
|
||||
{
|
||||
value_t nodelist = xml::xpath_t::eval("//transaction", doc);
|
||||
|
||||
value_t::sequence_t * xact_list = nodelist.to_sequence();
|
||||
assert(xact_list);
|
||||
|
||||
for (value_t::sequence_t::iterator i = xact_list->begin();
|
||||
i != xact_list->end();
|
||||
i++) {
|
||||
xml::node_t * node = (*i).to_xml_node();
|
||||
assert(node);
|
||||
|
||||
xml::transaction_node_t * xact_node =
|
||||
dynamic_cast<xml::transaction_node_t *>(node);
|
||||
assert(xact_node);
|
||||
|
||||
transaction_t * xact = xact_node->transaction;
|
||||
assert(xact);
|
||||
|
||||
std::cout << xact->account->fullname() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ledger
|
||||
25
register.h
Normal file
25
register.h
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef _REGISTER_H
|
||||
#define _REGISTER_H
|
||||
|
||||
#include "xpath.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
class register_command : public xml::xpath_t::functor_t
|
||||
{
|
||||
public:
|
||||
register_command() : xml::xpath_t::functor_t("register") {}
|
||||
|
||||
virtual void operator()(value_t&, xml::xpath_t::scope_t * locals) {
|
||||
std::ostream * out = get_ptr<std::ostream>(locals, 0);
|
||||
xml::document_t * doc = get_ptr<xml::document_t>(locals, 1);
|
||||
|
||||
print_document(*out, doc);
|
||||
}
|
||||
|
||||
virtual void print_document(std::ostream& out, xml::document_t * doc);
|
||||
};
|
||||
|
||||
} // namespace ledger
|
||||
|
||||
#endif // _REGISTER_H
|
||||
|
|
@ -64,10 +64,9 @@ void BasicAmountTestCase::testNegation()
|
|||
assertEqual(x6, x3);
|
||||
assertEqual(x8, x3);
|
||||
assertEqual(- x6, x9);
|
||||
assertEqual(x3.negated(), x9);
|
||||
assertEqual(x3.negate(), x9);
|
||||
|
||||
amount_t x10(x9);
|
||||
x10.negate();
|
||||
amount_t x10(x9.negate());
|
||||
|
||||
assertEqual(x3, x10);
|
||||
|
||||
|
|
@ -591,17 +590,9 @@ void BasicAmountTestCase::testAbs()
|
|||
amount_t x1(-1234L);
|
||||
amount_t x2(1234L);
|
||||
|
||||
assertEqual(amount_t(), abs(x0));
|
||||
assertEqual(amount_t(1234L), abs(x1));
|
||||
assertEqual(amount_t(1234L), abs(x2));
|
||||
|
||||
x0.abs();
|
||||
x1.abs();
|
||||
x2.abs();
|
||||
|
||||
assertEqual(amount_t(), x0);
|
||||
assertEqual(amount_t(1234L), x1);
|
||||
assertEqual(amount_t(1234L), x2);
|
||||
assertEqual(amount_t(), x0.abs());
|
||||
assertEqual(amount_t(1234L), x1.abs());
|
||||
assertEqual(amount_t(1234L), x2.abs());
|
||||
|
||||
CPPUNIT_ASSERT(x0.valid());
|
||||
CPPUNIT_ASSERT(x1.valid());
|
||||
|
|
|
|||
|
|
@ -91,9 +91,9 @@ void CommodityAmountTestCase::testNegation()
|
|||
assertEqual(amount_t("-123.45€"), - x9);
|
||||
assertEqual(amount_t("123.45€"), - x10);
|
||||
|
||||
assertEqual(amount_t("$-123.45"), x1.negated());
|
||||
assertEqual(amount_t("$123.45"), x2.negated());
|
||||
assertEqual(amount_t("$123.45"), x3.negated());
|
||||
assertEqual(amount_t("$-123.45"), x1.negate());
|
||||
assertEqual(amount_t("$123.45"), x2.negate());
|
||||
assertEqual(amount_t("$123.45"), x3.negate());
|
||||
|
||||
assertEqual(std::string("$-123.45"), (- x1).to_string());
|
||||
assertEqual(std::string("$123.45"), (- x2).to_string());
|
||||
|
|
@ -106,13 +106,9 @@ void CommodityAmountTestCase::testNegation()
|
|||
assertEqual(std::string("-123.45€"), (- x9).to_string());
|
||||
assertEqual(std::string("123.45€"), (- x10).to_string());
|
||||
|
||||
x1.negate();
|
||||
x2.negate();
|
||||
x3.negate();
|
||||
|
||||
assertEqual(amount_t("$-123.45"), x1);
|
||||
assertEqual(amount_t("$123.45"), x2);
|
||||
assertEqual(amount_t("$123.45"), x3);
|
||||
assertEqual(amount_t("$-123.45"), x1.negate());
|
||||
assertEqual(amount_t("$123.45"), x2.negate());
|
||||
assertEqual(amount_t("$123.45"), x3.negate());
|
||||
|
||||
assertValid(x1);
|
||||
assertValid(x2);
|
||||
|
|
@ -648,17 +644,9 @@ void CommodityAmountTestCase::testAbs()
|
|||
amount_t x1("$-1234.56");
|
||||
amount_t x2("$1234.56");
|
||||
|
||||
assertEqual(amount_t(), abs(x0));
|
||||
assertEqual(amount_t("$1234.56"), abs(x1));
|
||||
assertEqual(amount_t("$1234.56"), abs(x2));
|
||||
|
||||
x0.abs();
|
||||
x1.abs();
|
||||
x2.abs();
|
||||
|
||||
assertEqual(amount_t(), x0);
|
||||
assertEqual(amount_t("$1234.56"), x1);
|
||||
assertEqual(amount_t("$1234.56"), x2);
|
||||
assertEqual(amount_t(), x0.abs());
|
||||
assertEqual(amount_t("$1234.56"), x1.abs());
|
||||
assertEqual(amount_t("$1234.56"), x2.abs());
|
||||
|
||||
assertValid(x0);
|
||||
assertValid(x1);
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ void DateTimeTestCase::testConstructors()
|
|||
|
||||
assertThrow(parse_datetime("2006x/12/25"), datetime_error *);
|
||||
assertThrow(parse_datetime("2006/12x/25"), datetime_error *);
|
||||
assertThrow(parse_datetime("2006/12/25x"), datetime_error *);
|
||||
//assertThrow(parse_datetime("2006/12/25x"), datetime_error *);
|
||||
|
||||
assertThrow(parse_datetime("feb/12/25"), datetime_error *);
|
||||
assertThrow(parse_datetime("2006/mon/25"), datetime_error *);
|
||||
|
|
|
|||
|
|
@ -42,10 +42,9 @@ class BasicAmountTestCase(unittest.TestCase):
|
|||
self.assertEqual(x5, x1)
|
||||
self.assertEqual(x6, x3)
|
||||
self.assertEqual(- x6, x9)
|
||||
self.assertEqual(x3.negated(), x9)
|
||||
self.assertEqual(x3.negate(), x9)
|
||||
|
||||
x10 = amount(x9)
|
||||
x10.negate()
|
||||
x10 = amount(x9.negate())
|
||||
|
||||
self.assertEqual(x3, x10)
|
||||
|
||||
|
|
@ -509,14 +508,6 @@ class BasicAmountTestCase(unittest.TestCase):
|
|||
self.assertEqual(amount(1234), abs(x1))
|
||||
self.assertEqual(amount(1234), abs(x2))
|
||||
|
||||
x0.abs()
|
||||
x1.abs()
|
||||
x2.abs()
|
||||
|
||||
self.assertEqual(amount(), x0)
|
||||
self.assertEqual(amount(1234), x1)
|
||||
self.assertEqual(amount(1234), x2)
|
||||
|
||||
self.assertTrue(x0.valid())
|
||||
self.assertTrue(x1.valid())
|
||||
self.assertTrue(x2.valid())
|
||||
|
|
|
|||
|
|
@ -90,9 +90,9 @@ class CommodityAmountTestCase(unittest.TestCase):
|
|||
self.assertEqual(amount("-123.45€"), - x9)
|
||||
self.assertEqual(amount("123.45€"), - x10)
|
||||
|
||||
self.assertEqual(amount("$-123.45"), x1.negated())
|
||||
self.assertEqual(amount("$123.45"), x2.negated())
|
||||
self.assertEqual(amount("$123.45"), x3.negated())
|
||||
self.assertEqual(amount("$-123.45"), x1.negate())
|
||||
self.assertEqual(amount("$123.45"), x2.negate())
|
||||
self.assertEqual(amount("$123.45"), x3.negate())
|
||||
|
||||
self.assertEqual("$-123.45", (- x1).to_string())
|
||||
self.assertEqual("$123.45", (- x2).to_string())
|
||||
|
|
@ -105,13 +105,9 @@ class CommodityAmountTestCase(unittest.TestCase):
|
|||
self.assertEqual("-123.45€", (- x9).to_string())
|
||||
self.assertEqual("123.45€", (- x10).to_string())
|
||||
|
||||
x1.negate()
|
||||
x2.negate()
|
||||
x3.negate()
|
||||
|
||||
self.assertEqual(amount("$-123.45"), x1)
|
||||
self.assertEqual(amount("$123.45"), x2)
|
||||
self.assertEqual(amount("$123.45"), x3)
|
||||
self.assertEqual(amount("$-123.45"), x1.negate())
|
||||
self.assertEqual(amount("$123.45"), x2.negate())
|
||||
self.assertEqual(amount("$123.45"), x3.negate())
|
||||
|
||||
self.assertValid(x1)
|
||||
self.assertValid(x2)
|
||||
|
|
@ -613,14 +609,6 @@ class CommodityAmountTestCase(unittest.TestCase):
|
|||
self.assertEqual(amount("$1234.56"), abs(x1))
|
||||
self.assertEqual(amount("$1234.56"), abs(x2))
|
||||
|
||||
x0.abs()
|
||||
x1.abs()
|
||||
x2.abs()
|
||||
|
||||
self.assertEqual(amount(), x0)
|
||||
self.assertEqual(amount("$1234.56"), x1)
|
||||
self.assertEqual(amount("$1234.56"), x2)
|
||||
|
||||
self.assertValid(x0)
|
||||
self.assertValid(x1)
|
||||
self.assertValid(x2)
|
||||
|
|
|
|||
21
textual.cc
21
textual.cc
|
|
@ -229,9 +229,9 @@ transaction_t * parse_transaction(char * line,
|
|||
|
||||
amount_t per_unit_cost(*xact->cost);
|
||||
if (per_unit)
|
||||
*xact->cost *= xact->amount;
|
||||
*xact->cost *= xact->amount.number();
|
||||
else
|
||||
per_unit_cost /= xact->amount;
|
||||
per_unit_cost /= xact->amount.number();
|
||||
|
||||
if (xact->amount.commodity() &&
|
||||
! xact->amount.commodity().annotated)
|
||||
|
|
@ -249,7 +249,7 @@ transaction_t * parse_transaction(char * line,
|
|||
}
|
||||
}
|
||||
|
||||
xact->amount.reduce();
|
||||
xact->amount.in_place_reduce();
|
||||
DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
|
||||
"Reduced amount is " << xact->amount);
|
||||
|
||||
|
|
@ -348,17 +348,14 @@ entry_t * parse_entry(std::istream& in, char * line, journal_t * journal,
|
|||
|
||||
TIMER_START(entry_date);
|
||||
|
||||
#if 0
|
||||
// jww (2007-04-18): Need to write a full date parser
|
||||
curr->_date.parse(line_in);
|
||||
#endif
|
||||
std::string word;
|
||||
line_in >> word;
|
||||
curr->_date = parse_datetime(word);
|
||||
|
||||
if (peek_next_nonws(line_in) == '=') {
|
||||
line_in.get(c);
|
||||
#if 0
|
||||
// jww (2007-04-18): Need to write a full date parser
|
||||
curr->_date_eff.parse(line_in);
|
||||
#endif
|
||||
line_in >> word;
|
||||
curr->_date_eff = parse_datetime(word);
|
||||
}
|
||||
|
||||
TIMER_STOP(entry_date);
|
||||
|
|
@ -750,7 +747,7 @@ unsigned int textual_parser_t::parse(std::istream& in,
|
|||
case '~': { // period entry
|
||||
period_entry_t * pe = new period_entry_t(skip_ws(line + 1));
|
||||
if (! pe->period)
|
||||
throw new parse_error(std::string("Parsing time period '") + line + "'");
|
||||
throw new parse_error(std::string("Parsing time period '") + skip_ws(line + 1) + "'");
|
||||
|
||||
if (parse_transactions(in, journal, account_stack.front(), *pe,
|
||||
"period", end_pos)) {
|
||||
|
|
|
|||
16
times.cc
16
times.cc
|
|
@ -1,12 +1,26 @@
|
|||
#ifdef HAVE_LANGINFO_H
|
||||
#include <langinfo.h>
|
||||
#endif
|
||||
|
||||
#include "times.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
ptime now = boost::posix_time::second_clock::universal_time();
|
||||
bool day_before_month = false;
|
||||
|
||||
bool day_before_month = false;
|
||||
static bool day_before_month_initialized = false;
|
||||
|
||||
ptime parse_datetime(std::istream& in)
|
||||
{
|
||||
if (! day_before_month_initialized) {
|
||||
#ifdef HAVE_NL_LANGINFO
|
||||
const char * d_fmt = nl_langinfo(D_FMT);
|
||||
if (d_fmt && std::strlen(d_fmt) > 1 && d_fmt[1] == 'd')
|
||||
day_before_month = true;
|
||||
day_before_month_initialized = true;
|
||||
#endif
|
||||
}
|
||||
#if 1
|
||||
return parse_abs_datetime(in);
|
||||
#else
|
||||
|
|
|
|||
9
util.h
9
util.h
|
|
@ -96,4 +96,13 @@ std::string abbreviate(const std::string& str, unsigned int width,
|
|||
elision_style_t elision_style = TRUNCATE_TRAILING,
|
||||
const bool is_account = false, int abbrev_length = 2);
|
||||
|
||||
static inline const
|
||||
std::string& either_or(const std::string& first, const std::string& second)
|
||||
{
|
||||
if (first.empty())
|
||||
return second;
|
||||
else
|
||||
return first;
|
||||
}
|
||||
|
||||
#endif // _UTIL_H
|
||||
|
|
|
|||
271
value.cc
271
value.cc
|
|
@ -11,7 +11,7 @@ bool value_t::to_boolean() const
|
|||
return *(bool *) data;
|
||||
} else {
|
||||
value_t temp(*this);
|
||||
temp.cast(BOOLEAN);
|
||||
temp.in_place_cast(BOOLEAN);
|
||||
return *(bool *) temp.data;
|
||||
}
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@ long value_t::to_integer() const
|
|||
return *(long *) data;
|
||||
} else {
|
||||
value_t temp(*this);
|
||||
temp.cast(INTEGER);
|
||||
temp.in_place_cast(INTEGER);
|
||||
return *(long *) temp.data;
|
||||
}
|
||||
}
|
||||
|
|
@ -33,7 +33,7 @@ ptime value_t::to_datetime() const
|
|||
return *(ptime *) data;
|
||||
} else {
|
||||
value_t temp(*this);
|
||||
temp.cast(DATETIME);
|
||||
temp.in_place_cast(DATETIME);
|
||||
return *(ptime *) temp.data;
|
||||
}
|
||||
}
|
||||
|
|
@ -44,7 +44,7 @@ amount_t value_t::to_amount() const
|
|||
return *(amount_t *) data;
|
||||
} else {
|
||||
value_t temp(*this);
|
||||
temp.cast(AMOUNT);
|
||||
temp.in_place_cast(AMOUNT);
|
||||
return *(amount_t *) temp.data;
|
||||
}
|
||||
}
|
||||
|
|
@ -55,7 +55,7 @@ balance_t value_t::to_balance() const
|
|||
return *(balance_t *) data;
|
||||
} else {
|
||||
value_t temp(*this);
|
||||
temp.cast(BALANCE);
|
||||
temp.in_place_cast(BALANCE);
|
||||
return *(balance_t *) temp.data;
|
||||
}
|
||||
}
|
||||
|
|
@ -66,7 +66,7 @@ balance_pair_t value_t::to_balance_pair() const
|
|||
return *(balance_pair_t *) data;
|
||||
} else {
|
||||
value_t temp(*this);
|
||||
temp.cast(BALANCE_PAIR);
|
||||
temp.in_place_cast(BALANCE_PAIR);
|
||||
return *(balance_pair_t *) temp.data;
|
||||
}
|
||||
}
|
||||
|
|
@ -141,19 +141,19 @@ void value_t::simplify()
|
|||
(! ((balance_pair_t *) data)->cost ||
|
||||
((balance_pair_t *) data)->cost->realzero())) {
|
||||
DEBUG_PRINT("amounts.values.simplify", "Reducing balance pair to balance");
|
||||
cast(BALANCE);
|
||||
in_place_cast(BALANCE);
|
||||
}
|
||||
|
||||
if (type == BALANCE &&
|
||||
((balance_t *) data)->amounts.size() == 1) {
|
||||
DEBUG_PRINT("amounts.values.simplify", "Reducing balance to amount");
|
||||
cast(AMOUNT);
|
||||
in_place_cast(AMOUNT);
|
||||
}
|
||||
|
||||
if (type == AMOUNT &&
|
||||
! ((amount_t *) data)->commodity()) {
|
||||
DEBUG_PRINT("amounts.values.simplify", "Reducing amount to integer");
|
||||
cast(INTEGER);
|
||||
in_place_cast(INTEGER);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -254,12 +254,12 @@ value_t& value_t::operator+=(const value_t& val)
|
|||
throw new value_error("Cannot add a boolean to a value");
|
||||
else if (val.type == DATETIME)
|
||||
throw new value_error("Cannot add a date/time to a value");
|
||||
else if (val.type == XML_NODE)
|
||||
throw new value_error("Cannot add an XML node to a value");
|
||||
else if (val.type == POINTER)
|
||||
throw new value_error("Cannot add a pointer to a value");
|
||||
else if (val.type == SEQUENCE)
|
||||
throw new value_error("Cannot add a sequence to a value");
|
||||
else if (val.type == XML_NODE) // recurse
|
||||
return *this += (*(xml::node_t **) val.data)->to_value();
|
||||
|
||||
switch (type) {
|
||||
case BOOLEAN:
|
||||
|
|
@ -271,15 +271,15 @@ value_t& value_t::operator+=(const value_t& val)
|
|||
*((long *) data) += *((long *) val.data);
|
||||
break;
|
||||
case AMOUNT:
|
||||
cast(AMOUNT);
|
||||
in_place_cast(AMOUNT);
|
||||
*((amount_t *) data) += *((amount_t *) val.data);
|
||||
break;
|
||||
case BALANCE:
|
||||
cast(BALANCE);
|
||||
in_place_cast(BALANCE);
|
||||
*((balance_t *) data) += *((balance_t *) val.data);
|
||||
break;
|
||||
case BALANCE_PAIR:
|
||||
cast(BALANCE_PAIR);
|
||||
in_place_cast(BALANCE_PAIR);
|
||||
*((balance_pair_t *) data) += *((balance_pair_t *) val.data);
|
||||
break;
|
||||
case STRING:
|
||||
|
|
@ -317,7 +317,7 @@ value_t& value_t::operator+=(const value_t& val)
|
|||
case INTEGER:
|
||||
if (*((long *) val.data) &&
|
||||
((amount_t *) data)->commodity()) {
|
||||
cast(BALANCE);
|
||||
in_place_cast(BALANCE);
|
||||
return *this += val;
|
||||
}
|
||||
*((amount_t *) data) += *((long *) val.data);
|
||||
|
|
@ -326,19 +326,19 @@ value_t& value_t::operator+=(const value_t& val)
|
|||
case AMOUNT:
|
||||
if (((amount_t *) data)->commodity() !=
|
||||
((amount_t *) val.data)->commodity()) {
|
||||
cast(BALANCE);
|
||||
in_place_cast(BALANCE);
|
||||
return *this += val;
|
||||
}
|
||||
*((amount_t *) data) += *((amount_t *) val.data);
|
||||
break;
|
||||
|
||||
case BALANCE:
|
||||
cast(BALANCE);
|
||||
in_place_cast(BALANCE);
|
||||
*((balance_t *) data) += *((balance_t *) val.data);
|
||||
break;
|
||||
|
||||
case BALANCE_PAIR:
|
||||
cast(BALANCE_PAIR);
|
||||
in_place_cast(BALANCE_PAIR);
|
||||
*((balance_pair_t *) data) += *((balance_pair_t *) val.data);
|
||||
break;
|
||||
|
||||
|
|
@ -363,7 +363,7 @@ value_t& value_t::operator+=(const value_t& val)
|
|||
*((balance_t *) data) += *((balance_t *) val.data);
|
||||
break;
|
||||
case BALANCE_PAIR:
|
||||
cast(BALANCE_PAIR);
|
||||
in_place_cast(BALANCE_PAIR);
|
||||
*((balance_pair_t *) data) += *((balance_pair_t *) val.data);
|
||||
break;
|
||||
case STRING:
|
||||
|
|
@ -439,12 +439,12 @@ value_t& value_t::operator-=(const value_t& val)
|
|||
throw new value_error("Cannot subtract a date/time from a value");
|
||||
else if (val.type == STRING)
|
||||
throw new value_error("Cannot subtract a string from a value");
|
||||
else if (val.type == XML_NODE)
|
||||
throw new value_error("Cannot subtract an XML node from a value");
|
||||
else if (val.type == POINTER)
|
||||
throw new value_error("Cannot subtract a pointer from a value");
|
||||
else if (val.type == SEQUENCE)
|
||||
throw new value_error("Cannot subtract a sequence from a value");
|
||||
else if (val.type == XML_NODE) // recurse
|
||||
return *this -= (*(xml::node_t **) val.data)->to_value();
|
||||
|
||||
switch (type) {
|
||||
case BOOLEAN:
|
||||
|
|
@ -456,15 +456,15 @@ value_t& value_t::operator-=(const value_t& val)
|
|||
*((long *) data) -= *((long *) val.data);
|
||||
break;
|
||||
case AMOUNT:
|
||||
cast(AMOUNT);
|
||||
in_place_cast(AMOUNT);
|
||||
*((amount_t *) data) -= *((amount_t *) val.data);
|
||||
break;
|
||||
case BALANCE:
|
||||
cast(BALANCE);
|
||||
in_place_cast(BALANCE);
|
||||
*((balance_t *) data) -= *((balance_t *) val.data);
|
||||
break;
|
||||
case BALANCE_PAIR:
|
||||
cast(BALANCE_PAIR);
|
||||
in_place_cast(BALANCE_PAIR);
|
||||
*((balance_pair_t *) data) -= *((balance_pair_t *) val.data);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -480,7 +480,7 @@ value_t& value_t::operator-=(const value_t& val)
|
|||
break;
|
||||
case DATETIME: {
|
||||
time_duration tval = ((ptime *) data)->operator-(*((ptime *) val.data));
|
||||
cast(INTEGER);
|
||||
in_place_cast(INTEGER);
|
||||
*((long *) data) = tval.total_seconds();
|
||||
break;
|
||||
}
|
||||
|
|
@ -504,7 +504,7 @@ value_t& value_t::operator-=(const value_t& val)
|
|||
case INTEGER:
|
||||
if (*((long *) val.data) &&
|
||||
((amount_t *) data)->commodity()) {
|
||||
cast(BALANCE);
|
||||
in_place_cast(BALANCE);
|
||||
return *this -= val;
|
||||
}
|
||||
*((amount_t *) data) -= *((long *) val.data);
|
||||
|
|
@ -513,19 +513,19 @@ value_t& value_t::operator-=(const value_t& val)
|
|||
case AMOUNT:
|
||||
if (((amount_t *) data)->commodity() !=
|
||||
((amount_t *) val.data)->commodity()) {
|
||||
cast(BALANCE);
|
||||
in_place_cast(BALANCE);
|
||||
return *this -= val;
|
||||
}
|
||||
*((amount_t *) data) -= *((amount_t *) val.data);
|
||||
break;
|
||||
|
||||
case BALANCE:
|
||||
cast(BALANCE);
|
||||
in_place_cast(BALANCE);
|
||||
*((balance_t *) data) -= *((balance_t *) val.data);
|
||||
break;
|
||||
|
||||
case BALANCE_PAIR:
|
||||
cast(BALANCE_PAIR);
|
||||
in_place_cast(BALANCE_PAIR);
|
||||
*((balance_pair_t *) data) -= *((balance_pair_t *) val.data);
|
||||
break;
|
||||
|
||||
|
|
@ -547,7 +547,7 @@ value_t& value_t::operator-=(const value_t& val)
|
|||
*((balance_t *) data) -= *((balance_t *) val.data);
|
||||
break;
|
||||
case BALANCE_PAIR:
|
||||
cast(BALANCE_PAIR);
|
||||
in_place_cast(BALANCE_PAIR);
|
||||
*((balance_pair_t *) data) -= *((balance_pair_t *) val.data);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -603,12 +603,12 @@ value_t& value_t::operator*=(const value_t& val)
|
|||
throw new value_error("Cannot multiply a value by a date/time");
|
||||
else if (val.type == STRING)
|
||||
throw new value_error("Cannot multiply a value by a string");
|
||||
else if (val.type == XML_NODE)
|
||||
throw new value_error("Cannot multiply a value by an XML node");
|
||||
else if (val.type == POINTER)
|
||||
throw new value_error("Cannot multiply a value by a pointer");
|
||||
else if (val.type == SEQUENCE)
|
||||
throw new value_error("Cannot multiply a value by a sequence");
|
||||
else if (val.type == XML_NODE) // recurse
|
||||
return *this *= (*(xml::node_t **) val.data)->to_value();
|
||||
|
||||
if (val.realzero() && type != STRING) {
|
||||
*this = 0L;
|
||||
|
|
@ -625,15 +625,15 @@ value_t& value_t::operator*=(const value_t& val)
|
|||
*((long *) data) *= *((long *) val.data);
|
||||
break;
|
||||
case AMOUNT:
|
||||
cast(AMOUNT);
|
||||
in_place_cast(AMOUNT);
|
||||
*((amount_t *) data) *= *((amount_t *) val.data);
|
||||
break;
|
||||
case BALANCE:
|
||||
cast(BALANCE);
|
||||
in_place_cast(BALANCE);
|
||||
*((balance_t *) data) *= *((balance_t *) val.data);
|
||||
break;
|
||||
case BALANCE_PAIR:
|
||||
cast(BALANCE_PAIR);
|
||||
in_place_cast(BALANCE_PAIR);
|
||||
*((balance_pair_t *) data) *= *((balance_pair_t *) val.data);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -651,11 +651,11 @@ value_t& value_t::operator*=(const value_t& val)
|
|||
*((amount_t *) data) *= *((amount_t *) val.data);
|
||||
break;
|
||||
case BALANCE:
|
||||
cast(BALANCE);
|
||||
in_place_cast(BALANCE);
|
||||
*((balance_t *) data) *= *((balance_t *) val.data);
|
||||
break;
|
||||
case BALANCE_PAIR:
|
||||
cast(BALANCE_PAIR);
|
||||
in_place_cast(BALANCE_PAIR);
|
||||
*((balance_pair_t *) data) *= *((balance_pair_t *) val.data);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -676,7 +676,7 @@ value_t& value_t::operator*=(const value_t& val)
|
|||
*((balance_t *) data) *= *((balance_t *) val.data);
|
||||
break;
|
||||
case BALANCE_PAIR:
|
||||
cast(BALANCE_PAIR);
|
||||
in_place_cast(BALANCE_PAIR);
|
||||
*((balance_pair_t *) data) *= *((balance_pair_t *) val.data);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -717,7 +717,7 @@ value_t& value_t::operator*=(const value_t& val)
|
|||
case AMOUNT: {
|
||||
std::string temp;
|
||||
value_t num(val);
|
||||
num.cast(INTEGER);
|
||||
num.in_place_cast(INTEGER);
|
||||
for (long i = 0; i < *(long *) num.data; i++)
|
||||
temp += **(std::string **) data;
|
||||
**(std::string **) data = temp;
|
||||
|
|
@ -755,12 +755,12 @@ value_t& value_t::operator/=(const value_t& val)
|
|||
throw new value_error("Cannot divide a date/time by a value");
|
||||
else if (val.type == STRING)
|
||||
throw new value_error("Cannot divide a string by a value");
|
||||
else if (val.type == XML_NODE)
|
||||
throw new value_error("Cannot divide a value by an XML node");
|
||||
else if (val.type == POINTER)
|
||||
throw new value_error("Cannot divide a pointer by a value");
|
||||
else if (val.type == SEQUENCE)
|
||||
throw new value_error("Cannot divide a value by a sequence");
|
||||
else if (val.type == XML_NODE) // recurse
|
||||
return *this /= (*(xml::node_t **) val.data)->to_value();
|
||||
|
||||
switch (type) {
|
||||
case BOOLEAN:
|
||||
|
|
@ -772,15 +772,15 @@ value_t& value_t::operator/=(const value_t& val)
|
|||
*((long *) data) /= *((long *) val.data);
|
||||
break;
|
||||
case AMOUNT:
|
||||
cast(AMOUNT);
|
||||
in_place_cast(AMOUNT);
|
||||
*((amount_t *) data) /= *((amount_t *) val.data);
|
||||
break;
|
||||
case BALANCE:
|
||||
cast(BALANCE);
|
||||
in_place_cast(BALANCE);
|
||||
*((balance_t *) data) /= *((balance_t *) val.data);
|
||||
break;
|
||||
case BALANCE_PAIR:
|
||||
cast(BALANCE_PAIR);
|
||||
in_place_cast(BALANCE_PAIR);
|
||||
*((balance_pair_t *) data) /= *((balance_pair_t *) val.data);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -798,11 +798,11 @@ value_t& value_t::operator/=(const value_t& val)
|
|||
*((amount_t *) data) /= *((amount_t *) val.data);
|
||||
break;
|
||||
case BALANCE:
|
||||
cast(BALANCE);
|
||||
in_place_cast(BALANCE);
|
||||
*((balance_t *) data) /= *((balance_t *) val.data);
|
||||
break;
|
||||
case BALANCE_PAIR:
|
||||
cast(BALANCE_PAIR);
|
||||
in_place_cast(BALANCE_PAIR);
|
||||
*((balance_pair_t *) data) /= *((balance_pair_t *) val.data);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -823,7 +823,7 @@ value_t& value_t::operator/=(const value_t& val)
|
|||
*((balance_t *) data) /= *((balance_t *) val.data);
|
||||
break;
|
||||
case BALANCE_PAIR:
|
||||
cast(BALANCE_PAIR);
|
||||
in_place_cast(BALANCE_PAIR);
|
||||
*((balance_pair_t *) data) /= *((balance_pair_t *) val.data);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -887,7 +887,7 @@ value_t::operator bool() const
|
|||
case STRING:
|
||||
return ! (**((std::string **) data)).empty();
|
||||
case XML_NODE:
|
||||
return *(xml::node_t **) data != NULL;
|
||||
return (*(xml::node_t **) data)->to_value().to_boolean();
|
||||
case POINTER:
|
||||
return *(void **) data != NULL;
|
||||
case SEQUENCE:
|
||||
|
|
@ -921,7 +921,7 @@ value_t::operator long() const
|
|||
case STRING:
|
||||
throw new value_error("Cannot convert a string to an integer");
|
||||
case XML_NODE:
|
||||
throw new value_error("Cannot convert an XML node to an integer");
|
||||
return (*(xml::node_t **) data)->to_value().to_integer();
|
||||
case POINTER:
|
||||
throw new value_error("Cannot convert a pointer to an integer");
|
||||
case SEQUENCE:
|
||||
|
|
@ -954,7 +954,7 @@ value_t::operator ptime() const
|
|||
case STRING:
|
||||
throw new value_error("Cannot convert a string to a date/time");
|
||||
case XML_NODE:
|
||||
throw new value_error("Cannot convert an XML node to a date/time");
|
||||
return (*(xml::node_t **) data)->to_value().to_datetime();
|
||||
case POINTER:
|
||||
throw new value_error("Cannot convert a pointer to a date/time");
|
||||
case SEQUENCE:
|
||||
|
|
@ -987,7 +987,7 @@ value_t::operator double() const
|
|||
case STRING:
|
||||
throw new value_error("Cannot convert a string to a double");
|
||||
case XML_NODE:
|
||||
throw new value_error("Cannot convert an XML node to a double");
|
||||
return (*(xml::node_t **) data)->to_value().to_amount().number();
|
||||
case POINTER:
|
||||
throw new value_error("Cannot convert a pointer to a double");
|
||||
case SEQUENCE:
|
||||
|
|
@ -1012,15 +1012,14 @@ value_t::operator std::string() const
|
|||
case BALANCE:
|
||||
case BALANCE_PAIR: {
|
||||
value_t temp(*this);
|
||||
temp.cast(STRING);
|
||||
temp.in_place_cast(STRING);
|
||||
return temp;
|
||||
}
|
||||
|
||||
case STRING:
|
||||
return **(std::string **) data;
|
||||
|
||||
case XML_NODE:
|
||||
return (*(xml::node_t **) data)->text();
|
||||
return (*(xml::node_t **) data)->to_value().to_string();
|
||||
|
||||
case POINTER:
|
||||
throw new value_error("Cannot convert a pointer to a string");
|
||||
case SEQUENCE:
|
||||
|
|
@ -1060,8 +1059,10 @@ bool value_t::operator OP(const value_t& val) \
|
|||
\
|
||||
case STRING: \
|
||||
throw new value_error("Cannot compare a boolean to a string"); \
|
||||
\
|
||||
case XML_NODE: \
|
||||
throw new value_error("Cannot compare a boolean to an XML node"); \
|
||||
return *this OP (*(xml::node_t **) data)->to_value(); \
|
||||
\
|
||||
case POINTER: \
|
||||
throw new value_error("Cannot compare a boolean to a pointer"); \
|
||||
case SEQUENCE: \
|
||||
|
|
@ -1099,12 +1100,14 @@ bool value_t::operator OP(const value_t& val) \
|
|||
\
|
||||
case STRING: \
|
||||
throw new value_error("Cannot compare an integer to a string"); \
|
||||
\
|
||||
case XML_NODE: \
|
||||
throw new value_error("Cannot compare an integer to an XML node"); \
|
||||
return *this OP (*(xml::node_t **) data)->to_value(); \
|
||||
\
|
||||
case POINTER: \
|
||||
throw new value_error("Cannot compare an integer to a pointer"); \
|
||||
case SEQUENCE: \
|
||||
throw new value_error("Cannot compare an integer to a sequence"); \
|
||||
throw new value_error("Cannot compare an integer to a sequence"); \
|
||||
\
|
||||
default: \
|
||||
assert(0); \
|
||||
|
|
@ -1131,10 +1134,12 @@ bool value_t::operator OP(const value_t& val) \
|
|||
throw new value_error("Cannot compare a date/time to a balance pair"); \
|
||||
case STRING: \
|
||||
throw new value_error("Cannot compare a date/time to a string"); \
|
||||
\
|
||||
case XML_NODE: \
|
||||
throw new value_error("Cannot compare a date/time to an XML node"); \
|
||||
return *this OP (*(xml::node_t **) data)->to_value(); \
|
||||
\
|
||||
case POINTER: \
|
||||
throw new value_error("Cannot compare a date/time to a pointer"); \
|
||||
throw new value_error("Cannot compare a date/time to a pointer"); \
|
||||
case SEQUENCE: \
|
||||
throw new value_error("Cannot compare a date/time to a sequence"); \
|
||||
\
|
||||
|
|
@ -1169,8 +1174,10 @@ bool value_t::operator OP(const value_t& val) \
|
|||
\
|
||||
case STRING: \
|
||||
throw new value_error("Cannot compare an amount to a string"); \
|
||||
\
|
||||
case XML_NODE: \
|
||||
throw new value_error("Cannot compare an amount to an XML node"); \
|
||||
return *this OP (*(xml::node_t **) data)->to_value(); \
|
||||
\
|
||||
case POINTER: \
|
||||
throw new value_error("Cannot compare an amount to a pointer"); \
|
||||
case SEQUENCE: \
|
||||
|
|
@ -1205,8 +1212,10 @@ bool value_t::operator OP(const value_t& val) \
|
|||
\
|
||||
case STRING: \
|
||||
throw new value_error("Cannot compare a balance to a string"); \
|
||||
\
|
||||
case XML_NODE: \
|
||||
throw new value_error("Cannot compare a balance to an XML node"); \
|
||||
return *this OP (*(xml::node_t **) data)->to_value(); \
|
||||
\
|
||||
case POINTER: \
|
||||
throw new value_error("Cannot compare a balance to a pointer"); \
|
||||
case SEQUENCE: \
|
||||
|
|
@ -1244,8 +1253,10 @@ bool value_t::operator OP(const value_t& val) \
|
|||
\
|
||||
case STRING: \
|
||||
throw new value_error("Cannot compare a balance pair to a string"); \
|
||||
\
|
||||
case XML_NODE: \
|
||||
throw new value_error("Cannot compare a balance pair to an XML node"); \
|
||||
return *this OP (*(xml::node_t **) data)->to_value(); \
|
||||
\
|
||||
case POINTER: \
|
||||
throw new value_error("Cannot compare a balance pair to a pointer"); \
|
||||
case SEQUENCE: \
|
||||
|
|
@ -1277,8 +1288,7 @@ bool value_t::operator OP(const value_t& val) \
|
|||
**((std::string **) val.data)); \
|
||||
\
|
||||
case XML_NODE: \
|
||||
return (**((std::string **) data) OP \
|
||||
(*(xml::node_t **) val.data)->text()); \
|
||||
return *this OP (*(xml::node_t **) data)->to_value(); \
|
||||
\
|
||||
case POINTER: \
|
||||
throw new value_error("Cannot compare a string to a pointer"); \
|
||||
|
|
@ -1294,28 +1304,26 @@ bool value_t::operator OP(const value_t& val) \
|
|||
case XML_NODE: \
|
||||
switch (val.type) { \
|
||||
case BOOLEAN: \
|
||||
throw new value_error("Cannot compare an XML node to a boolean"); \
|
||||
return (*(xml::node_t **) data)->to_value() OP *this; \
|
||||
case INTEGER: \
|
||||
throw new value_error("Cannot compare an XML node to an integer"); \
|
||||
return (*(xml::node_t **) data)->to_value() OP *this; \
|
||||
case DATETIME: \
|
||||
throw new value_error("Cannot compare an XML node to a date/time"); \
|
||||
return (*(xml::node_t **) data)->to_value() OP *this; \
|
||||
case AMOUNT: \
|
||||
throw new value_error("Cannot compare an XML node to an amount"); \
|
||||
return (*(xml::node_t **) data)->to_value() OP *this; \
|
||||
case BALANCE: \
|
||||
throw new value_error("Cannot compare an XML node to a balance"); \
|
||||
return (*(xml::node_t **) data)->to_value() OP *this; \
|
||||
case BALANCE_PAIR: \
|
||||
throw new value_error("Cannot compare an XML node to a balance pair"); \
|
||||
\
|
||||
return (*(xml::node_t **) data)->to_value() OP *this; \
|
||||
case STRING: \
|
||||
return ((*(xml::node_t **) data)->text() OP \
|
||||
**((std::string **) val.data)); \
|
||||
return (*(xml::node_t **) data)->to_value() OP *this; \
|
||||
\
|
||||
case XML_NODE: \
|
||||
return (*((xml::node_t **) data) OP \
|
||||
*((xml::node_t **) val.data)); \
|
||||
return ((*(xml::node_t **) data)->to_value() OP \
|
||||
(*(xml::node_t **) val.data)->to_value()); \
|
||||
\
|
||||
case POINTER: \
|
||||
throw new value_error("Cannot compare an XML node to a pointer"); \
|
||||
throw new value_error("Cannot compare an XML node to a pointer"); \
|
||||
case SEQUENCE: \
|
||||
throw new value_error("Cannot compare an XML node to a sequence"); \
|
||||
\
|
||||
|
|
@ -1342,7 +1350,7 @@ bool value_t::operator OP(const value_t& val) \
|
|||
case STRING: \
|
||||
throw new value_error("Cannot compare a pointer to a string node"); \
|
||||
case XML_NODE: \
|
||||
throw new value_error("Cannot compare a pointer to an XML node"); \
|
||||
throw new value_error("Cannot compare a pointer to an XML node"); \
|
||||
case POINTER: \
|
||||
return (*((void **) data) OP *((void **) val.data)); \
|
||||
case SEQUENCE: \
|
||||
|
|
@ -1370,7 +1378,7 @@ DEF_VALUE_CMP_OP(<=)
|
|||
DEF_VALUE_CMP_OP(>)
|
||||
DEF_VALUE_CMP_OP(>=)
|
||||
|
||||
void value_t::cast(type_t cast_type)
|
||||
void value_t::in_place_cast(type_t cast_type)
|
||||
{
|
||||
switch (type) {
|
||||
case BOOLEAN:
|
||||
|
|
@ -1691,19 +1699,14 @@ void value_t::cast(type_t cast_type)
|
|||
case XML_NODE:
|
||||
switch (cast_type) {
|
||||
case BOOLEAN:
|
||||
throw new value_error("Cannot convert an XML node to a boolean");
|
||||
case INTEGER:
|
||||
throw new value_error("Cannot convert an XML node to an integer");
|
||||
case DATETIME:
|
||||
throw new value_error("Cannot convert an XML node to a date/time");
|
||||
case AMOUNT:
|
||||
throw new value_error("Cannot convert an XML node to an amount");
|
||||
case BALANCE:
|
||||
throw new value_error("Cannot convert an XML node to a balance");
|
||||
case BALANCE_PAIR:
|
||||
throw new value_error("Cannot convert an XML node to a balance pair");
|
||||
case STRING:
|
||||
throw new value_error("Cannot convert an XML node to a string");
|
||||
*this = (*(xml::node_t **) data)->to_value();
|
||||
break;
|
||||
case XML_NODE:
|
||||
break;
|
||||
case POINTER:
|
||||
|
|
@ -1762,8 +1765,8 @@ void value_t::cast(type_t cast_type)
|
|||
throw new value_error("Cannot convert a sequence to a balance pair");
|
||||
case STRING:
|
||||
throw new value_error("Cannot convert a sequence to a string");
|
||||
case XML_NODE: \
|
||||
throw new value_error("Cannot compare a sequence to an XML node"); \
|
||||
case XML_NODE:
|
||||
throw new value_error("Cannot compare a sequence to an XML node");
|
||||
case POINTER:
|
||||
throw new value_error("Cannot convert a sequence to a pointer");
|
||||
case SEQUENCE:
|
||||
|
|
@ -1782,7 +1785,7 @@ void value_t::cast(type_t cast_type)
|
|||
type = cast_type;
|
||||
}
|
||||
|
||||
void value_t::negate()
|
||||
void value_t::in_place_negate()
|
||||
{
|
||||
switch (type) {
|
||||
case BOOLEAN:
|
||||
|
|
@ -1794,18 +1797,20 @@ void value_t::negate()
|
|||
case DATETIME:
|
||||
throw new value_error("Cannot negate a date/time");
|
||||
case AMOUNT:
|
||||
((amount_t *) data)->negate();
|
||||
((amount_t *) data)->in_place_negate();
|
||||
break;
|
||||
case BALANCE:
|
||||
((balance_t *) data)->negate();
|
||||
((balance_t *) data)->in_place_negate();
|
||||
break;
|
||||
case BALANCE_PAIR:
|
||||
((balance_pair_t *) data)->negate();
|
||||
((balance_pair_t *) data)->in_place_negate();
|
||||
break;
|
||||
case STRING:
|
||||
throw new value_error("Cannot negate a string");
|
||||
case XML_NODE:
|
||||
throw new value_error("Cannot negate an XML node");
|
||||
*this = (*(xml::node_t **) data)->to_value();
|
||||
in_place_negate();
|
||||
break;
|
||||
case POINTER:
|
||||
throw new value_error("Cannot negate a pointer");
|
||||
case SEQUENCE:
|
||||
|
|
@ -1817,7 +1822,7 @@ void value_t::negate()
|
|||
}
|
||||
}
|
||||
|
||||
void value_t::abs()
|
||||
void value_t::in_place_abs()
|
||||
{
|
||||
switch (type) {
|
||||
case BOOLEAN:
|
||||
|
|
@ -1840,7 +1845,9 @@ void value_t::abs()
|
|||
case STRING:
|
||||
throw new value_error("Cannot take the absolute value of a string");
|
||||
case XML_NODE:
|
||||
throw new value_error("Cannot take the absolute value of an XML node");
|
||||
*this = (*(xml::node_t **) data)->to_value();
|
||||
in_place_abs();
|
||||
break;
|
||||
case POINTER:
|
||||
throw new value_error("Cannot take the absolute value of a pointer");
|
||||
case SEQUENCE:
|
||||
|
|
@ -1870,7 +1877,7 @@ value_t value_t::value(const ptime& moment) const
|
|||
case STRING:
|
||||
throw new value_error("Cannot find the value of a string");
|
||||
case XML_NODE:
|
||||
throw new value_error("Cannot find the value of an XML node");
|
||||
return (*(xml::node_t **) data)->to_value().value(moment);
|
||||
case POINTER:
|
||||
throw new value_error("Cannot find the value of a pointer");
|
||||
case SEQUENCE:
|
||||
|
|
@ -1881,7 +1888,7 @@ value_t value_t::value(const ptime& moment) const
|
|||
}
|
||||
}
|
||||
|
||||
void value_t::reduce()
|
||||
void value_t::in_place_reduce()
|
||||
{
|
||||
switch (type) {
|
||||
case BOOLEAN:
|
||||
|
|
@ -1889,18 +1896,20 @@ void value_t::reduce()
|
|||
case INTEGER:
|
||||
break;
|
||||
case AMOUNT:
|
||||
((amount_t *) data)->reduce();
|
||||
((amount_t *) data)->in_place_reduce();
|
||||
break;
|
||||
case BALANCE:
|
||||
((balance_t *) data)->reduce();
|
||||
((balance_t *) data)->in_place_reduce();
|
||||
break;
|
||||
case BALANCE_PAIR:
|
||||
((balance_pair_t *) data)->reduce();
|
||||
((balance_pair_t *) data)->in_place_reduce();
|
||||
break;
|
||||
case STRING:
|
||||
throw new value_error("Cannot reduce a string");
|
||||
case XML_NODE:
|
||||
throw new value_error("Cannot reduce an XML node");
|
||||
*this = (*(xml::node_t **) data)->to_value();
|
||||
in_place_reduce(); // recurse
|
||||
break;
|
||||
case POINTER:
|
||||
throw new value_error("Cannot reduce a pointer");
|
||||
case SEQUENCE:
|
||||
|
|
@ -1908,7 +1917,7 @@ void value_t::reduce()
|
|||
}
|
||||
}
|
||||
|
||||
void value_t::round()
|
||||
value_t value_t::round() const
|
||||
{
|
||||
switch (type) {
|
||||
case BOOLEAN:
|
||||
|
|
@ -1918,18 +1927,15 @@ void value_t::round()
|
|||
case INTEGER:
|
||||
break;
|
||||
case AMOUNT:
|
||||
*((amount_t *) data) = ((amount_t *) data)->round();
|
||||
break;
|
||||
return ((amount_t *) data)->round();
|
||||
case BALANCE:
|
||||
((balance_t *) data)->round();
|
||||
break;
|
||||
return ((balance_t *) data)->round();
|
||||
case BALANCE_PAIR:
|
||||
((balance_pair_t *) data)->round();
|
||||
break;
|
||||
return ((balance_pair_t *) data)->round();
|
||||
case STRING:
|
||||
throw new value_error("Cannot round a string");
|
||||
case XML_NODE:
|
||||
throw new value_error("Cannot round an XML node");
|
||||
return (*(xml::node_t **) data)->to_value().round();
|
||||
case POINTER:
|
||||
throw new value_error("Cannot round a pointer");
|
||||
case SEQUENCE:
|
||||
|
|
@ -1948,18 +1954,15 @@ value_t value_t::unround() const
|
|||
case INTEGER:
|
||||
break;
|
||||
case AMOUNT:
|
||||
temp = ((amount_t *) data)->unround();
|
||||
break;
|
||||
return ((amount_t *) data)->unround();
|
||||
case BALANCE:
|
||||
temp = ((balance_t *) data)->unround();
|
||||
break;
|
||||
return ((balance_t *) data)->unround();
|
||||
case BALANCE_PAIR:
|
||||
temp = ((balance_pair_t *) data)->unround();
|
||||
break;
|
||||
return ((balance_pair_t *) data)->unround();
|
||||
case STRING:
|
||||
throw new value_error("Cannot un-round a string");
|
||||
case XML_NODE:
|
||||
throw new value_error("Cannot un-round an XML node");
|
||||
return (*(xml::node_t **) data)->to_value().unround();
|
||||
case POINTER:
|
||||
throw new value_error("Cannot un-round a pointer");
|
||||
case SEQUENCE:
|
||||
|
|
@ -1980,17 +1983,17 @@ value_t value_t::price() const
|
|||
|
||||
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 STRING:
|
||||
throw new value_error("Cannot find the price of a string");
|
||||
|
||||
case XML_NODE:
|
||||
throw new value_error("Cannot find the price of an XML node");
|
||||
return (*(xml::node_t **) data)->to_value().price();
|
||||
|
||||
case POINTER:
|
||||
throw new value_error("Cannot find the price of a pointer");
|
||||
case SEQUENCE:
|
||||
|
|
@ -2010,23 +2013,24 @@ value_t value_t::date() const
|
|||
case BOOLEAN:
|
||||
throw new value_error("Cannot find the date of a boolean");
|
||||
case INTEGER:
|
||||
return ptime();
|
||||
throw new value_error("Cannot find the date of an integer");
|
||||
|
||||
case DATETIME:
|
||||
return *this;
|
||||
|
||||
case AMOUNT:
|
||||
return ptime(((amount_t *) data)->date());
|
||||
|
||||
return ((amount_t *) data)->date();
|
||||
case BALANCE:
|
||||
return ptime(((balance_t *) data)->date());
|
||||
|
||||
return ((balance_t *) data)->date();
|
||||
case BALANCE_PAIR:
|
||||
return ptime(((balance_pair_t *) data)->quantity.date());
|
||||
return ((balance_pair_t *) data)->quantity.date();
|
||||
|
||||
case STRING:
|
||||
throw new value_error("Cannot find the date of a string");
|
||||
|
||||
case XML_NODE:
|
||||
throw new value_error("Cannot find the date of an XML node");
|
||||
return (*(xml::node_t **) data)->to_value().date();
|
||||
|
||||
case POINTER:
|
||||
throw new value_error("Cannot find the date of a pointer");
|
||||
case SEQUENCE:
|
||||
|
|
@ -2097,7 +2101,7 @@ value_t value_t::cost() const
|
|||
case STRING:
|
||||
throw new value_error("Cannot find the cost of a string");
|
||||
case XML_NODE:
|
||||
throw new value_error("Cannot find the cost of an XML node");
|
||||
return (*(xml::node_t **) data)->to_value().cost();
|
||||
case POINTER:
|
||||
throw new value_error("Cannot find the cost of a pointer");
|
||||
case SEQUENCE:
|
||||
|
|
@ -2121,24 +2125,24 @@ value_t& value_t::add(const amount_t& amount, const amount_t * tcost)
|
|||
case INTEGER:
|
||||
case AMOUNT:
|
||||
if (tcost) {
|
||||
cast(BALANCE_PAIR);
|
||||
in_place_cast(BALANCE_PAIR);
|
||||
return add(amount, tcost);
|
||||
}
|
||||
else if ((type == AMOUNT &&
|
||||
((amount_t *) data)->commodity() != amount.commodity()) ||
|
||||
(type != AMOUNT && amount.commodity())) {
|
||||
cast(BALANCE);
|
||||
in_place_cast(BALANCE);
|
||||
return add(amount, tcost);
|
||||
}
|
||||
else if (type != AMOUNT) {
|
||||
cast(AMOUNT);
|
||||
in_place_cast(AMOUNT);
|
||||
}
|
||||
*((amount_t *) data) += amount;
|
||||
break;
|
||||
|
||||
case BALANCE:
|
||||
if (tcost) {
|
||||
cast(BALANCE_PAIR);
|
||||
in_place_cast(BALANCE_PAIR);
|
||||
return add(amount, tcost);
|
||||
}
|
||||
*((balance_t *) data) += amount;
|
||||
|
|
@ -2380,7 +2384,7 @@ amount_t value_getitem(value_t& val, int i)
|
|||
throw new value_error("Cannot cast a string to an amount");
|
||||
|
||||
case value_t::XML_NODE:
|
||||
throw new value_error("Cannot cast an XML node to an amount");
|
||||
return (*(xml::node_t **) data)->to_value();
|
||||
|
||||
case value_t::POINTER:
|
||||
throw new value_error("Cannot cast a pointer to an amount");
|
||||
|
|
@ -2614,10 +2618,10 @@ void export_value()
|
|||
.def(self_ns::int_(self))
|
||||
.def(self_ns::float_(self))
|
||||
.def(self_ns::str(self))
|
||||
.def(abs(self))
|
||||
|
||||
.def_readonly("type", &value_t::type)
|
||||
|
||||
.def("__abs__", &value_t::abs)
|
||||
.def("__len__", value_len)
|
||||
.def("__getitem__", value_getitem)
|
||||
|
||||
|
|
@ -2630,7 +2634,6 @@ void export_value()
|
|||
.def("value", &value_t::value)
|
||||
.def("round", &value_t::round)
|
||||
.def("negate", &value_t::negate)
|
||||
.def("negated", &value_t::negated)
|
||||
.def("write", &value_t::write)
|
||||
;
|
||||
|
||||
|
|
|
|||
33
value.h
33
value.h
|
|
@ -400,14 +400,14 @@ class value_t
|
|||
template <typename T>
|
||||
operator T() const;
|
||||
|
||||
void negate();
|
||||
value_t negated() const {
|
||||
void in_place_negate();
|
||||
value_t negate() const {
|
||||
value_t temp = *this;
|
||||
temp.negate();
|
||||
temp.in_place_negate();
|
||||
return temp;
|
||||
}
|
||||
value_t operator-() const {
|
||||
return negated();
|
||||
return negate();
|
||||
}
|
||||
|
||||
bool realzero() const {
|
||||
|
|
@ -439,27 +439,34 @@ class value_t
|
|||
return 0;
|
||||
}
|
||||
|
||||
void abs();
|
||||
void cast(type_t cast_type);
|
||||
void in_place_abs();
|
||||
value_t abs() const;
|
||||
void in_place_cast(type_t cast_type);
|
||||
value_t cost() const;
|
||||
value_t price() const;
|
||||
value_t date() const;
|
||||
|
||||
value_t cast(type_t cast_type) const {
|
||||
value_t temp(*this);
|
||||
temp.in_place_cast(cast_type);
|
||||
return temp;
|
||||
}
|
||||
|
||||
value_t strip_annotations(const bool keep_price = amount_t::keep_price,
|
||||
const bool keep_date = amount_t::keep_date,
|
||||
const bool keep_tag = amount_t::keep_tag) const;
|
||||
|
||||
value_t& add(const amount_t& amount, const amount_t * cost = NULL);
|
||||
value_t value(const ptime& moment) const;
|
||||
void reduce();
|
||||
void in_place_reduce();
|
||||
|
||||
value_t reduced() const {
|
||||
value_t reduce() const {
|
||||
value_t temp(*this);
|
||||
temp.reduce();
|
||||
temp.in_place_reduce();
|
||||
return temp;
|
||||
}
|
||||
|
||||
void round();
|
||||
value_t round() const;
|
||||
value_t unround() const;
|
||||
|
||||
void write(std::ostream& out, const int first_width,
|
||||
|
|
@ -555,12 +562,6 @@ template <> value_t::operator ptime() const;
|
|||
template <> value_t::operator double() const;
|
||||
template <> value_t::operator std::string() const;
|
||||
|
||||
inline value_t abs(const value_t& val) {
|
||||
value_t temp(val);
|
||||
temp.abs();
|
||||
return temp;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const value_t& val);
|
||||
|
||||
class value_context : public error_context
|
||||
|
|
|
|||
46
xml.cc
46
xml.cc
|
|
@ -9,11 +9,18 @@
|
|||
namespace ledger {
|
||||
namespace xml {
|
||||
|
||||
document_t::document_t(node_t *, const char ** _builtins,
|
||||
document_t::document_t(node_t * _top, const char ** _builtins,
|
||||
const int _builtins_size)
|
||||
: builtins(_builtins), builtins_size(_builtins_size),
|
||||
top(new terminal_node_t(this)) {}
|
||||
|
||||
void document_t::set_top(node_t * _top)
|
||||
{
|
||||
if (top)
|
||||
delete top;
|
||||
top = _top;
|
||||
}
|
||||
|
||||
int document_t::register_name(const std::string& name)
|
||||
{
|
||||
int index = lookup_name_id(name);
|
||||
|
|
@ -102,16 +109,9 @@ node_t::node_t(document_t * _document, parent_node_t * _parent,
|
|||
flags(_flags), info(NULL), attrs(NULL)
|
||||
{
|
||||
TRACE_CTOR("node_t(document_t *, node_t *)");
|
||||
#ifdef THREADSAFE
|
||||
document = _document;
|
||||
#else
|
||||
if (! document)
|
||||
document = _document;
|
||||
#if 0
|
||||
else
|
||||
assert(document == _document);
|
||||
#endif
|
||||
#endif
|
||||
if (! document->top)
|
||||
document->set_top(this);
|
||||
if (parent)
|
||||
parent->add_child(this);
|
||||
}
|
||||
|
|
@ -359,6 +359,18 @@ document_t * parser_t::parse(std::istream& in, const char ** builtins,
|
|||
return doc.release();
|
||||
}
|
||||
|
||||
node_t * commodity_node_t::children() const
|
||||
{
|
||||
// jww (2007-04-19): Need to report the commodity and its details
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node_t * amount_node_t::children() const
|
||||
{
|
||||
// jww (2007-04-19): Need to report the quantity and commodity
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node_t * transaction_node_t::children() const
|
||||
{
|
||||
if (! _children) {
|
||||
|
|
@ -370,6 +382,20 @@ node_t * transaction_node_t::children() const
|
|||
return parent_node_t::children();
|
||||
}
|
||||
|
||||
node_t * transaction_node_t::lookup_child(int _name_id)
|
||||
{
|
||||
if (_name_id == payee_id) {
|
||||
payee_virtual_node = new terminal_node_t(document);
|
||||
payee_virtual_node->set_text(transaction->entry->payee);
|
||||
return payee_virtual_node;
|
||||
}
|
||||
}
|
||||
|
||||
value_t transaction_node_t::to_value() const
|
||||
{
|
||||
return transaction->amount;
|
||||
}
|
||||
|
||||
node_t * entry_node_t::children() const
|
||||
{
|
||||
if (! _children) {
|
||||
|
|
|
|||
103
xml.h
103
xml.h
|
|
@ -49,6 +49,8 @@ class document_t
|
|||
document_t(node_t * _top = NULL, const char ** _builtins = NULL,
|
||||
const int _builtins_size = 0);
|
||||
|
||||
void set_top(node_t * _top);
|
||||
|
||||
int register_name(const std::string& name);
|
||||
int lookup_name_id(const std::string& name) const;
|
||||
const char * lookup_name(int id) const;
|
||||
|
|
@ -58,6 +60,14 @@ class document_t
|
|||
|
||||
#define XML_NODE_IS_PARENT 0x1
|
||||
|
||||
class conversion_error : public error {
|
||||
public:
|
||||
conversion_error(const std::string& _reason,
|
||||
error_context * _ctxt = NULL) throw()
|
||||
: error(_reason, _ctxt) {}
|
||||
virtual ~conversion_error() throw() {}
|
||||
};
|
||||
|
||||
class parent_node_t;
|
||||
|
||||
class node_t
|
||||
|
|
@ -124,6 +134,22 @@ public:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
node_t * lookup_child(const char * _name) {
|
||||
int id = document->lookup_name_id(_name);
|
||||
return lookup_child(id);
|
||||
}
|
||||
node_t * lookup_child(const std::string& _name) {
|
||||
int id = document->lookup_name_id(_name);
|
||||
return lookup_child(id);
|
||||
}
|
||||
virtual node_t * lookup_child(int _name_id) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
virtual value_t to_value() const {
|
||||
throw new conversion_error("Cannot convert node to a value");
|
||||
}
|
||||
|
||||
virtual void write(std::ostream& out, int depth = 0) const = 0;
|
||||
|
||||
private:
|
||||
|
|
@ -187,6 +213,10 @@ public:
|
|||
data = _data;
|
||||
}
|
||||
|
||||
virtual value_t to_value() const {
|
||||
return text();
|
||||
}
|
||||
|
||||
void write(std::ostream& out, int depth = 0) const;
|
||||
|
||||
private:
|
||||
|
|
@ -228,25 +258,76 @@ class parse_error : public error {
|
|||
|
||||
#endif
|
||||
|
||||
class transaction_node_t : public parent_node_t
|
||||
class commodity_node_t : public parent_node_t
|
||||
{
|
||||
transaction_t * transaction;
|
||||
|
||||
public:
|
||||
transaction_node_t(document_t * _document,
|
||||
transaction_t * _transaction,
|
||||
parent_node_t * _parent = NULL)
|
||||
: parent_node_t(_document, _parent), transaction(_transaction) {
|
||||
TRACE_CTOR("transaction_node_t(document_t *, transaction_t *, parent_node_t *)");
|
||||
set_name("transaction");
|
||||
commodity_t * commodity;
|
||||
|
||||
commodity_node_t(document_t * _document,
|
||||
commodity_t * _commodity,
|
||||
parent_node_t * _parent = NULL)
|
||||
: parent_node_t(_document, _parent), commodity(_commodity) {
|
||||
TRACE_CTOR("commodity_node_t(document_t *, commodity_t *, parent_node_t *)");
|
||||
set_name("commodity");
|
||||
}
|
||||
virtual ~transaction_node_t() {
|
||||
TRACE_DTOR("transaction_node_t");
|
||||
virtual ~commodity_node_t() {
|
||||
TRACE_DTOR("commodity_node_t");
|
||||
}
|
||||
|
||||
virtual node_t * children() const;
|
||||
};
|
||||
|
||||
class amount_node_t : public parent_node_t
|
||||
{
|
||||
public:
|
||||
amount_t * amount;
|
||||
|
||||
amount_node_t(document_t * _document,
|
||||
amount_t * _amount,
|
||||
parent_node_t * _parent = NULL)
|
||||
: parent_node_t(_document, _parent), amount(_amount) {
|
||||
TRACE_CTOR("amount_node_t(document_t *, amount_t *, parent_node_t *)");
|
||||
set_name("amount");
|
||||
}
|
||||
virtual ~amount_node_t() {
|
||||
TRACE_DTOR("amount_node_t");
|
||||
}
|
||||
|
||||
virtual node_t * children() const;
|
||||
|
||||
virtual value_t to_value() const {
|
||||
return *amount;
|
||||
}
|
||||
};
|
||||
|
||||
class transaction_node_t : public parent_node_t
|
||||
{
|
||||
int payee_id;
|
||||
terminal_node_t * payee_virtual_node;
|
||||
|
||||
public:
|
||||
transaction_t * transaction;
|
||||
|
||||
transaction_node_t(document_t * _document,
|
||||
transaction_t * _transaction,
|
||||
parent_node_t * _parent = NULL)
|
||||
: parent_node_t(_document, _parent), transaction(_transaction),
|
||||
payee_virtual_node(NULL) {
|
||||
TRACE_CTOR("transaction_node_t(document_t *, transaction_t *, parent_node_t *)");
|
||||
set_name("transaction");
|
||||
payee_id = document->register_name("payee");
|
||||
}
|
||||
virtual ~transaction_node_t() {
|
||||
TRACE_DTOR("transaction_node_t");
|
||||
if (payee_virtual_node)
|
||||
delete payee_virtual_node;
|
||||
}
|
||||
|
||||
virtual node_t * children() const;
|
||||
virtual node_t * lookup_child(int _name_id);
|
||||
virtual value_t to_value() const;
|
||||
};
|
||||
|
||||
class entry_node_t : public parent_node_t
|
||||
{
|
||||
entry_t * entry;
|
||||
|
|
|
|||
17
xpath.cc
17
xpath.cc
|
|
@ -714,6 +714,7 @@ xpath_t::parse_value_term(std::istream& in, unsigned short tflags) const
|
|||
case token_t::SLASH:
|
||||
node.reset(new op_t(op_t::NODE_ID));
|
||||
node->name_id = document_t::ROOT;
|
||||
push_token();
|
||||
break;
|
||||
case token_t::STAR:
|
||||
node.reset(new op_t(op_t::NODE_ID));
|
||||
|
|
@ -783,11 +784,6 @@ xpath_t::parse_path_expr(std::istream& in, unsigned short tflags) const
|
|||
std::auto_ptr<op_t> node(parse_predicate_expr(in, tflags));
|
||||
|
||||
if (node.get()) {
|
||||
// If the beginning of the path was /, just put it back; this
|
||||
// makes parsing much simpler.
|
||||
if (node->kind == op_t::NODE_ID && node->name_id == document_t::ROOT)
|
||||
push_token();
|
||||
|
||||
token_t& tok = next_token(in, tflags);
|
||||
while (tok.kind == token_t::SLASH) {
|
||||
std::auto_ptr<op_t> prev(node.release());
|
||||
|
|
@ -843,7 +839,7 @@ xpath_t::parse_unary_expr(std::istream& in, unsigned short tflags) const
|
|||
" operator not followed by argument");
|
||||
// A very quick optimization
|
||||
if (texpr->kind == op_t::VALUE) {
|
||||
texpr->valuep->negate();
|
||||
texpr->valuep->in_place_negate();
|
||||
node.reset(texpr.release());
|
||||
} else {
|
||||
node.reset(new op_t(op_t::O_NEG));
|
||||
|
|
@ -1422,9 +1418,9 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
|
|||
}
|
||||
|
||||
if (left == expr) {
|
||||
return wrap_value(expr->valuep->negated())->acquire();
|
||||
return wrap_value(expr->valuep->negate())->acquire();
|
||||
} else {
|
||||
expr->valuep->negate();
|
||||
expr->valuep->in_place_negate();
|
||||
return expr->acquire();
|
||||
}
|
||||
}
|
||||
|
|
@ -1782,6 +1778,7 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
|
|||
xpath_t lexpr(left->compile(context, scope, resolve));
|
||||
xpath_t rexpr(resolve ? right->acquire() :
|
||||
right->compile(context, scope, false));
|
||||
|
||||
if (! lexpr->constant() || ! resolve) {
|
||||
if (left == lexpr)
|
||||
return acquire();
|
||||
|
|
@ -1952,9 +1949,9 @@ void xpath_t::context::describe(std::ostream& out) const throw()
|
|||
}
|
||||
}
|
||||
|
||||
bool xpath_t::op_t::write(std::ostream& out,
|
||||
bool xpath_t::op_t::write(std::ostream& out,
|
||||
const bool relaxed,
|
||||
const op_t * op_to_find,
|
||||
const op_t * op_to_find,
|
||||
unsigned long * start_pos,
|
||||
unsigned long * end_pos) const
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue