summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am4
-rw-r--r--Makefile.in33
-rw-r--r--README4
-rw-r--r--acconf.h.in6
-rwxr-xr-xacprep2
-rw-r--r--amount.cc18
-rw-r--r--amount.h26
-rw-r--r--balance.cc4
-rw-r--r--balance.h110
-rwxr-xr-xconfigure148
-rw-r--r--configure.in78
-rw-r--r--debug.cc9
-rw-r--r--debug.h3
-rw-r--r--journal.cc16
-rw-r--r--journal.h8
-rw-r--r--ledger.el1
-rw-r--r--ledger.h2
-rw-r--r--main.cc36
-rw-r--r--mask.cc39
-rw-r--r--mask.h14
-rw-r--r--parsetime.yy105
-rw-r--r--py_amount.cc5
-rw-r--r--qif.cc4
-rw-r--r--register.cc31
-rw-r--r--register.h25
-rw-r--r--tests/corelib/numerics/BasicAmount.cc19
-rw-r--r--tests/corelib/numerics/CommodityAmount.cc30
-rw-r--r--tests/corelib/numerics/DateTime.cc2
-rw-r--r--tests/python/corelib/numerics/BasicAmount.py13
-rw-r--r--tests/python/corelib/numerics/CommodityAmount.py24
-rw-r--r--textual.cc21
-rw-r--r--times.cc16
-rw-r--r--util.h9
-rw-r--r--value.cc271
-rw-r--r--value.h33
-rw-r--r--xml.cc46
-rw-r--r--xml.h85
-rw-r--r--xpath.cc17
38 files changed, 687 insertions, 630 deletions
diff --git a/Makefile.am b/Makefile.am
index 3b84ae37..4e5cdb86 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -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
diff --git a/Makefile.in b/Makefile.in
index 562f2c18..c1d52aab 100644
--- a/Makefile.in
+++ b/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
diff --git a/README b/README
index 8a2406d9..28145c4b 100644
--- a/README
+++ b/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").
diff --git a/acconf.h.in b/acconf.h.in
index 9c64213f..94fef0ac 100644
--- a/acconf.h.in
+++ b/acconf.h.in
@@ -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
diff --git a/acprep b/acprep
index 2a8cd1d9..642b6a93 100755
--- a/acprep
+++ b/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" ;;
diff --git a/amount.cc b/amount.cc
index 5d2cdccd..ff1bcc6b 100644
--- a/amount.cc
+++ b/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;
diff --git a/amount.h b/amount.h
index 6f88229b..4afe038d 100644
--- a/amount.h
+++ b/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); \
diff --git a/balance.cc b/balance.cc
index 3d31bc5d..71daf0f7 100644
--- a/balance.cc
+++ b/balance.cc
@@ -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)
diff --git a/balance.h b/balance.h
index d50cfa78..5270c1a0 100644
--- a/balance.h
+++ b/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();
+ }
+ balance_t abs() const {
+ balance_t temp = *this;
+ temp.in_place_abs();
+ return temp;
}
- void reduce() {
+ void in_place_reduce() {
for (amounts_map::iterator i = amounts.begin();
i != amounts.end();
i++)
- (*i).second.reduce();
+ (*i).second.in_place_reduce();
}
-
- balance_t reduced() const {
+ balance_t reduce() const {
balance_t temp(*this);
- temp.reduce();
+ temp.in_place_reduce();
return temp;
}
- void round() {
+ void in_place_round() {
for (amounts_map::iterator i = amounts.begin();
i != amounts.end();
i++)
- if ((*i).second.commodity())
- (*i).second = (*i).second.round();
+ (*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);
diff --git a/configure b/configure
index 2c3280fc..91c8d2c8 100755
--- a/configure
+++ b/configure
@@ -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,29 +19759,29 @@ 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
+# 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
echo $ECHO_N "(cached) $ECHO_C" >&6
else
- libpcre_save_libs=$LIBS
- LIBS="-lpcre $LIBS"
+ boost_date_time_save_libs=$LIBS
+ LIBS="-lboost_date_time $LIBS"
ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -19796,11 +19794,29 @@ _ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
-#include <pcre.h>
+#include <boost/date_time/posix_time/posix_time.hpp>
+ #include <boost/date_time/gregorian/gregorian.hpp>
+ #include <boost/date_time/local_time_adjustor.hpp>
+ #include <boost/date_time/time_duration.hpp>
+
+ using namespace boost::posix_time;
+ using namespace boost::date_time;
+
+ #include <ctime>
+
+ inline ptime time_to_system_local(const ptime& when) {
+ struct std::tm tm_gmt = to_tm(when);
+ return from_time_t(mktime(&tm_gmt));
+ }
int
main ()
{
-pcre_free((pcre *)NULL);
+ptime t10 = ptime(boost::gregorian::from_string("2007-01-15"),
+ ptime::time_duration_type());
+
+ ptime t12 = time_to_system_local(t10);
+
+ return t10 != t12;
;
return 0;
}
@@ -19823,12 +19839,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
- libpcre_avail=true
+ boost_date_time_cpplib_avail=true
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
- libpcre_avail=false
+ boost_date_time_cpplib_avail=false
fi
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
@@ -19839,29 +19855,29 @@ 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
+ LIBS=$boost_date_time_save_libs
fi
-{ echo "$as_me:$LINENO: result: $libpcre_avail" >&5
-echo "${ECHO_T}$libpcre_avail" >&6; }
+{ echo "$as_me:$LINENO: result: $boost_date_time_cpplib_avail" >&5
+echo "${ECHO_T}$boost_date_time_cpplib_avail" >&6; }
-if test x$libpcre_avail = xtrue ; then
- LIBS="-lpcre $LIBS"
+if test x$boost_date_time_cpplib_avail = xtrue ; then
+ LIBS="-lboost_date_time $LIBS"
else
- { { echo "$as_me:$LINENO: error: \"Could not find pcre library (set CPPFLAGS and LDFLAGS?)\"
+ { { echo "$as_me:$LINENO: error: \"Could not find boost_date_time 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?)\"
+echo "$as_me: error: \"Could not find boost_date_time library (set CPPFLAGS and LDFLAGS?)\"
See \`config.log' for more details." >&2;}
{ (exit 1); exit 1; }; }
fi
-# 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
+# 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
- boost_date_time_save_libs=$LIBS
- LIBS="-lboost_date_time $LIBS"
+ libgmp_save_libs=$LIBS
+ LIBS="-lgmp $LIBS"
ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -19874,29 +19890,13 @@ _ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
-#include <boost/date_time/posix_time/posix_time.hpp>
- #include <boost/date_time/gregorian/gregorian.hpp>
- #include <boost/date_time/local_time_adjustor.hpp>
- #include <boost/date_time/time_duration.hpp>
-
- using namespace boost::posix_time;
- using namespace boost::date_time;
-
- #include <ctime>
-
- inline ptime time_to_system_local(const ptime& when) {
- struct std::tm tm_gmt = to_tm(when);
- return from_time_t(mktime(&tm_gmt));
- }
+#include <gmp.h>
int
main ()
{
-ptime t10 = ptime(boost::gregorian::from_string("2007-01-15"),
- ptime::time_duration_type());
-
- ptime t12 = time_to_system_local(t10);
-
- return t10 != t12;
+mpz_t bar;
+ mpz_init(bar);
+ mpz_clear(bar);
;
return 0;
}
@@ -19919,12 +19919,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
- boost_date_time_cpplib_avail=true
+ libgmp_avail=true
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
- boost_date_time_cpplib_avail=false
+ libgmp_avail=false
fi
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
@@ -19935,17 +19935,17 @@ 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=$boost_date_time_save_libs
+ LIBS=$libgmp_save_libs
fi
-{ echo "$as_me:$LINENO: result: $boost_date_time_cpplib_avail" >&5
-echo "${ECHO_T}$boost_date_time_cpplib_avail" >&6; }
+{ echo "$as_me:$LINENO: result: $libgmp_avail" >&5
+echo "${ECHO_T}$libgmp_avail" >&6; }
-if test x$boost_date_time_cpplib_avail = xtrue ; then
- LIBS="-lboost_date_time $LIBS"
+if test x$libgmp_avail = xtrue ; then
+ LIBS="-lgmp $LIBS"
else
- { { echo "$as_me:$LINENO: error: \"Could not find boost_date_time library (set CPPFLAGS and LDFLAGS?)\"
+ { { 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 boost_date_time library (set CPPFLAGS and LDFLAGS?)\"
+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
@@ -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
diff --git a/configure.in b/configure.in
index d1f953e2..8bb6247f 100644
--- a/configure.in
+++ b/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
-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 pcre
+# check for boost_regex
AC_CACHE_CHECK(
- [if libpcre is available],
- [libpcre_avail],
- [libpcre_save_libs=$LIBS
- LIBS="-lpcre $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 <pcre.h>],
- [pcre_free((pcre *)NULL);],
- [libpcre_avail=true],
- [libpcre_avail=false])
+ [#include <boost/regex.hpp>],
+ [boost::regex foo_regexp("Hello, world!");],
+ [boost_regex_avail=true],
+ [boost_regex_avail=false])
AC_LANG_POP
- LIBS=$libpcre_save_libs])
+ LIBS=$boost_regex_save_libs])
-if [test x$libpcre_avail = xtrue ]; then
- LIBS="-lpcre $LIBS"
+if [test x$boost_regex_avail = xtrue ]; then
+ LIBS="-lboost_regex $LIBS"
else
- AC_MSG_FAILURE("Could not find pcre library (set CPPFLAGS and LDFLAGS?)")
+ AC_MSG_FAILURE("Could not find boost_regex 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
diff --git a/debug.cc b/debug.cc
index b3b140bc..3b996045 100644
--- a/debug.cc
+++ b/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;
}
diff --git a/debug.h b/debug.h
index ae4c52c1..842b0e4d 100644
--- a/debug.h
+++ b/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;
diff --git a/journal.cc b/journal.cc
index 0b9f3909..1bf31dd6 100644
--- a/journal.cc
+++ b/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;
}
diff --git a/journal.h b/journal.h
index 5506421d..5f1a8091 100644
--- a/journal.h
+++ b/journal.h
@@ -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;
diff --git a/ledger.el b/ledger.el
index 00a32892..0812f8f6 100644
--- a/ledger.el
+++ b/ledger.el
@@ -71,6 +71,7 @@
(require 'esh-util)
(require 'esh-arg)
+(require 'pcomplete)
(defvar ledger-version "1.2"
"The version of ledger.el currently loaded")
diff --git a/ledger.h b/ledger.h
index 39e78021..e5988bbc 100644
--- a/ledger.h
+++ b/ledger.h
@@ -34,6 +34,8 @@
#include <report.h>
#include <transform.h>
+#include <register.h>
+
#if 0
#include <emacs.h>
#include <csv.h>
diff --git a/main.cc b/main.cc
index b8e25813..473ff5fa 100644
--- a/main.cc
+++ b/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);
diff --git a/mask.cc b/mask.cc
index ea621206..11700a51 100644
--- a/mask.cc
+++ b/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);
}
diff --git a/mask.h b/mask.h
index ed00806e..e7febeb0 100644
--- a/mask.h
+++ b/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 {
diff --git a/parsetime.yy b/parsetime.yy
index f2b204c9..5700e8db 100644
--- a/parsetime.yy
+++ b/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 ;
diff --git a/py_amount.cc b/py_amount.cc
index ef69d2b9..7c27e095 100644
--- a/py_amount.cc
+++ b/py_amount.cc
@@ -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)
diff --git a/qif.cc b/qif.cc
index 393d1939..75c927f6 100644
--- a/qif.cc
+++ b/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;
}
diff --git a/register.cc b/register.cc
new file mode 100644
index 00000000..3e261522
--- /dev/null
+++ b/register.cc
@@ -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
diff --git a/register.h b/register.h
new file mode 100644
index 00000000..73078892
--- /dev/null
+++ b/register.h
@@ -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
diff --git a/tests/corelib/numerics/BasicAmount.cc b/tests/corelib/numerics/BasicAmount.cc
index 84692a90..972dcbcc 100644
--- a/tests/corelib/numerics/BasicAmount.cc
+++ b/tests/corelib/numerics/BasicAmount.cc
@@ -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());
diff --git a/tests/corelib/numerics/CommodityAmount.cc b/tests/corelib/numerics/CommodityAmount.cc
index c41b33d4..860e7b1c 100644
--- a/tests/corelib/numerics/CommodityAmount.cc
+++ b/tests/corelib/numerics/CommodityAmount.cc
@@ -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);
diff --git a/tests/corelib/numerics/DateTime.cc b/tests/corelib/numerics/DateTime.cc
index 02dd7a0d..e62db8dc 100644
--- a/tests/corelib/numerics/DateTime.cc
+++ b/tests/corelib/numerics/DateTime.cc
@@ -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 *);
diff --git a/tests/python/corelib/numerics/BasicAmount.py b/tests/python/corelib/numerics/BasicAmount.py
index df522f09..2ce532d9 100644
--- a/tests/python/corelib/numerics/BasicAmount.py
+++ b/tests/python/corelib/numerics/BasicAmount.py
@@ -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())
diff --git a/tests/python/corelib/numerics/CommodityAmount.py b/tests/python/corelib/numerics/CommodityAmount.py
index 417652e4..e29d091a 100644
--- a/tests/python/corelib/numerics/CommodityAmount.py
+++ b/tests/python/corelib/numerics/CommodityAmount.py
@@ -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)
diff --git a/textual.cc b/textual.cc
index ce203de6..647e010d 100644
--- a/textual.cc
+++ b/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)) {
diff --git a/times.cc b/times.cc
index bb75f8d9..e6d0540f 100644
--- a/times.cc
+++ b/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
diff --git a/util.h b/util.h
index 842879e5..dc14547a 100644
--- a/util.h
+++ b/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
diff --git a/value.cc b/value.cc
index 5eab7aee..7924ec42 100644
--- a/value.cc
+++ b/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)
;
diff --git a/value.h b/value.h
index 81fb9371..87f9d2ba 100644
--- a/value.h
+++ b/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
diff --git a/xml.cc b/xml.cc
index 33f98666..c56e9766 100644
--- a/xml.cc
+++ b/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) {
diff --git a/xml.h b/xml.h
index b3481d5a..09b3180e 100644
--- a/xml.h
+++ b/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,23 +258,74 @@ class parse_error : public error {
#endif
+class commodity_node_t : public parent_node_t
+{
+public:
+ 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 ~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
{
- transaction_t * transaction;
+ 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) {
+ : 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
diff --git a/xpath.cc b/xpath.cc
index 66880b5a..3da4e614 100644
--- a/xpath.cc
+++ b/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
{