Many changes.

This commit is contained in:
John Wiegley 2007-05-21 20:42:05 +00:00
parent f12d41f233
commit 7380da43ab
62 changed files with 392 additions and 1313 deletions

View file

@ -9,15 +9,11 @@ ESC_srcdir=`echo "$(srcdir)" | sed 's/\//\\\\\//g'`
ESC_builddir=`echo "$(top_builddir)" | sed 's/\//\\\\\//g'`
ESC_distdir=`echo "$(distdir)" | sed 's/\//\\\\\//g'`
#(cd $(distdir)/docs; zip -r doxygen-html.zip html; rm -fr html)
dist-hook:
rm -fr `find $(distdir) -name .svn`
lib_LTLIBRARIES = libledger.la
if HAVE_BOOST_PYTHON
lib_LTLIBRARIES += libpyledger.la
endif
AM_YFLAGS = -d
AM_LFLAGS = -o $(LEX_OUTPUT_ROOT).c
@ -34,38 +30,42 @@ libledger_la_CPPFLAGS = -I$(top_builddir)/gdtoa -I$(srcdir)/gdtoa \
libledger_la_LDFLAGS = -release $(PACKAGE_VERSION)
libledger_la_SOURCES = \
src/utils.cc \
src/times.cc \
src/mask.cc \
src/abbrev.cc \
src/commodity.cc \
src/amount.cc \
src/balance.cc \
src/value.cc \
src/document.cc \
src/node.cc \
src/compile.cc \
src/jbuilder.cc \
src/xpath.cc \
src/journal.cc \
src/textual.cc \
src/binary.cc \
src/transform.cc \
src/report.cc \
src/session.cc
src/utility/utils.cc \
src/utility/times.cc \
src/utility/binary.cc \
src/utility/mask.cc \
src/numerics/commodity.cc \
src/numerics/amount.cc \
src/numerics/balance.cc \
src/numerics/value.cc \
src/data/document.cc \
src/data/node.cc \
src/data/textual.cc \
src/data/compile.cc \
src/data/journal.cc \
src/data/jbuilder.cc \
src/traversal/xpath.cc \
src/traversal/transform.cc \
src/traversal/abbrev.cc \
src/driver/session.cc \
src/driver/report.cc
#if HAVE_EXPAT
#libledger_la_CPPFLAGS += -DHAVE_EXPAT=1
#libledger_la_SOURCES += src/gnucash.cc
#endif
#if HAVE_XMLPARSE
#libledger_la_CPPFLAGS += -DHAVE_XMLPARSE=1
#libledger_la_SOURCES += src/gnucash.cc
#endif
#if HAVE_LIBOFX
#libledger_la_CPPFLAGS += -DHAVE_LIBOFX=1
#libledger_la_SOURCES += src/ofx.cc
#endif
if HAVE_BOOST_PYTHON
Python_SRC = \
src/python/pyinterp.cc \
src/python/pyledger.cc \
src/python/py_amount.cc \
src/python/py_commodity.cc \
src/python/py_times.cc \
src/python/py_utils.cc
libledger_la_SOURCES += $(Python_SRC)
endif
if HAVE_LIBOFX
libledger_la_CPPFLAGS += -DHAVE_LIBOFX=1
libledger_la_SOURCES += src/ofx.cc
endif
if DEBUG
libledger_la_CPPFLAGS += -DDEBUG_MODE
endif
@ -76,60 +76,45 @@ nodist_libledger_la_SOURCES = system.hh.gch
BUILT_SOURCES += system.hh.gch
CLEANFILES += system.hh.gch system.hh
$(top_builddir)/system.hh.gch: $(srcdir)/src/system.hh acconf.h
$(top_builddir)/system.hh.gch: $(srcdir)/src/utility/system.hh acconf.h
echo "#include \"src/system.hh\"" > $(top_builddir)/system.hh
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(libledger_la_CPPFLAGS) \
-o $@ $(srcdir)/src/system.hh
-o $@ $(srcdir)/src/utility/system.hh
endif
libpyledger_la_CPPFLAGS = $(libledger_la_CPPFLAGS)
libpyledger_la_LDFLAGS = -release $(PACKAGE_VERSION)
libpyledger_la_SOURCES = \
src/pyinterp.cc \
src/py_utils.cc \
src/py_times.cc \
src/py_commodity.cc \
src/py_amount.cc
pkginclude_HEADERS = \
src/abbrev.h \
src/amount.h \
src/balance.h \
src/balpair.h \
src/binary.h \
src/builder.h \
src/jbuilder.h \
src/commodity.h \
src/compile.h \
src/context.h \
src/document.h \
src/fdstream.hpp \
src/flags.h \
src/format.h \
src/journal.h \
src/ledger.h \
src/mask.h \
src/node.h \
src/option.h \
src/parser.h \
src/pyfstream.h \
src/pyinterp.h \
src/pyledger.h \
src/pyutils.h \
src/report.h \
src/scoped_execute.h \
src/session.h \
src/system.hh \
src/textual.h \
src/times.h \
src/transform.h \
src/tuples.hpp \
src/utils.h \
src/value.h \
src/xpath.h
src/ledger.h \
src/utility/binary.h \
src/utility/context.h \
src/utility/flags.h \
src/utility/mask.h \
src/utility/pushvar.h \
src/utility/times.h \
src/utility/utils.h \
src/numerics/amount.h \
src/numerics/balance.h \
src/numerics/balpair.h \
src/numerics/commodity.h \
src/numerics/value.h \
src/data/builder.h \
src/data/compile.h \
src/data/document.h \
src/data/jbuilder.h \
src/data/journal.h \
src/data/node.h \
src/data/parser.h \
src/data/textual.h \
src/traversal/abbrev.h \
src/traversal/transform.h \
src/traversal/xpath.h \
src/driver/option.h \
src/driver/report.h \
src/driver/session.h \
src/python/pyfstream.h \
src/python/pyinterp.h \
src/python/pyledger.h \
src/python/pyutils.h
###############################################################################
@ -138,14 +123,7 @@ bin_PROGRAMS = ledger
ledger_CPPFLAGS = $(libledger_la_CPPFLAGS)
ledger_LDADD = $(LIBOBJS) libledger.la gdtoa/libgdtoa.la $(LEXLIB)
ledger_LDFLAGS = -static # for the sake of command-line speed
ledger_SOURCES = \
src/option.cc \
src/main.cc
if HAVE_BOOST_PYTHON
ledger_LDADD += libpyledger.la
endif
ledger_SOURCES = src/driver/option.cc src/driver/main.cc
nodist_info_TEXINFOS = docs/ledger.texi
@ -166,31 +144,18 @@ CLEANFILES += ledger.so
clean-local:
rm -fr build
ledger_so_SOURCES = \
src/pyledger.cc \
src/pyinterp.cc \
src/py_utils.cc \
src/py_times.cc \
src/py_commodity.cc \
src/py_amount.cc
ledger_so_SOURCES = $(Python_SRC)
ledger_so_DEPENDENCIES = libledger.la gdtoa/libgdtoa.la
ledger_so_DEPENDENCIES = libledger.la gdtoa/libgdtoa.la libpyledger.la
PYLIBS = pyledger ledger gdtoa gmp
PYLIBS += boost_date_time$(BOOST_SUFFIX) \
PYLIBS = ledger gdtoa gmp \
boost_date_time$(BOOST_SUFFIX) \
boost_filesystem$(BOOST_SUFFIX) \
boost_regex$(BOOST_SUFFIX) \
boost_python$(BOOST_SUFFIX)
#if HAVE_EXPAT
#PYLIBS += expat
#endif
#if HAVE_XMLPARSE
#PYLIBS += xmlparse xmltok
#endif
#if HAVE_LIBOFX
#PYLIBS += ofx
#endif
if HAVE_LIBOFX
PYLIBS += ofx
endif
ledger.so: $(ledger_so_SOURCES) $(ledger_so_DEPENDENCIES)
CFLAGS="$(CPPFLAGS) -I$(srcdir) $(libledger_la_CPPFLAGS)" \

View file

@ -7,7 +7,7 @@ AC_INIT([ledger],[3.0],[johnw@newartisans.com])
AC_CONFIG_SRCDIR(ledger)
AM_INIT_AUTOMAKE([dist-bzip2])
AC_CONFIG_SRCDIR([src/main.cc])
AC_CONFIG_SRCDIR([src/driver/main.cc])
AC_CONFIG_HEADER([acconf.h])
AC_CONFIG_SUBDIRS([gdtoa])
@ -17,14 +17,6 @@ AC_PROG_MAKE_SET
AC_PROG_LIBTOOL
AM_PROG_LIBTOOL
#AC_PROG_YACC
#AC_PROG_LEX
#if test "$LEX" != flex; then
# LEX="$SHELL $missing_dir/missing flex"
# AC_SUBST(LEX_OUTPUT_ROOT, lex.yy)
# AC_SUBST(LEXLIB, '')
#fi
# Checks for emacs lisp path
AM_PATH_LISPDIR
@ -61,30 +53,35 @@ AC_CACHE_CHECK(
[if pipes can be used],
[pipes_avail],
[AC_LANG_PUSH(C++)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>]], [[int status, pfd[2];
status = pipe(pfd);
status = fork();
if (status < 0) {
;
} else if (status == 0) {
char *arg0;
status = dup2(pfd[0], STDIN_FILENO);
close(pfd[1]);
close(pfd[0]);
execlp("", arg0, (char *)0);
perror("execl");
exit(1);
} else {
close(pfd[0]);
}]])],[pipes_avail=true],[pipes_avail=false])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>]],
[[int status, pfd[2];
status = pipe(pfd);
status = fork();
if (status < 0) {
;
} else if (status == 0) {
char *arg0;
status = dup2(pfd[0], STDIN_FILENO);
close(pfd[1]);
close(pfd[0]);
execlp("", arg0, (char *)0);
perror("execl");
exit(1);
} else {
close(pfd[0]);
}]])],
[pipes_avail=true],
[pipes_avail=false])
AC_LANG_POP])
if [test x$pipes_avail = xtrue ]; then
@ -98,7 +95,12 @@ AC_CACHE_CHECK(
[boost_regex_save_libs=$LIBS
LIBS="-lboost_regex$BOOST_SUFFIX $LIBS"
AC_LANG_PUSH(C++)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <boost/regex.hpp>]], [[boost::regex foo_regexp("Hello, world!");]])],[boost_regex_avail=true],[boost_regex_avail=false])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <boost/regex.hpp>]],
[[boost::regex foo_regexp("Hello, world!");]])],
[boost_regex_avail=true],
[boost_regex_avail=false])
AC_LANG_POP
LIBS=$boost_regex_save_libs])
@ -115,25 +117,30 @@ AC_CACHE_CHECK(
[boost_date_time_save_libs=$LIBS
LIBS="-lboost_date_time$BOOST_SUFFIX $LIBS"
AC_LANG_PUSH(C++)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#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));
}]], [[ptime t10 = ptime(boost::gregorian::from_string("2007-01-15"),
ptime::time_duration_type());
ptime t12 = time_to_system_local(t10);
return t10 != t12;]])],[boost_date_time_cpplib_avail=true],[boost_date_time_cpplib_avail=false])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#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));
}]],
[[ptime t10 = ptime(boost::gregorian::from_string("2007-01-15"),
ptime::time_duration_type());
ptime t12 = time_to_system_local(t10);
return t10 != t12;]])],
[boost_date_time_cpplib_avail=true],
[boost_date_time_cpplib_avail=false])
AC_LANG_POP
LIBS=$boost_date_time_save_libs])
@ -150,7 +157,12 @@ AC_CACHE_CHECK(
[boost_filesystem_save_libs=$LIBS
LIBS="-lboost_filesystem$BOOST_SUFFIX $LIBS"
AC_LANG_PUSH(C++)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <boost/filesystem/path.hpp>]], [[boost::filesystem::path this_path("Hello");]])],[boost_filesystem_cpplib_avail=true],[boost_filesystem_cpplib_avail=false])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <boost/filesystem/path.hpp>]],
[[boost::filesystem::path this_path("Hello");]])],
[boost_filesystem_cpplib_avail=true],
[boost_filesystem_cpplib_avail=false])
AC_LANG_POP
LIBS=$boost_filesystem_save_libs])
@ -167,7 +179,12 @@ fi
# [boost_signals_save_libs=$LIBS
# LIBS="-lboost_signals$BOOST_SUFFIX $LIBS"
# AC_LANG_PUSH(C++)
# AC_LINK_IFELSE([AC_LANG_PROGRAM([[# #include <boost/signal.hpp>]], [[# boost::signal<void (void)> this_signal;]])],[# boost_signals_cpplib_avail=true],[# boost_signals_cpplib_avail=false])
# AC_LINK_IFELSE(
# [AC_LANG_PROGRAM(
# [[#include <boost/signal.hpp>]],
# [[boost::signal<void (void)> this_signal;]])],
# [boost_signals_cpplib_avail=true],
# [boost_signals_cpplib_avail=false])
# AC_LANG_POP
# LIBS=$boost_signals_save_libs])
#
@ -196,71 +213,6 @@ 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],
# [case "${enableval}" in
# yes) xml=true ;;
# no) xml=false ;;
# *) AC_MSG_ERROR(bad value ${enableval} for --enable-xml) ;;
# esac],[xml=true])
#
#AM_CONDITIONAL(USE_XML, test x$xml = xtrue)
#
#if [test x$xml = xtrue ]; then
# AC_CACHE_CHECK(
# [if libexpat is available],
# [libexpat_avail],
# [libexpat_save_libs=$LIBS
# LIBS="-lexpat $LIBS"
# AC_LANG_PUSH(C++)
# AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <stdio.h>
# extern "C" {
# #include <expat.h> // expat XML parser
# }]], [[XML_Parser parser = XML_ParserCreate(NULL);
# return parser != NULL;]])],[libexpat_avail=true],[libexpat_avail=false])
# AC_LANG_POP
# LIBS=$libexpat_save_libs])
#
# if [test x$libexpat_avail = xtrue ]; then
# AM_CONDITIONAL(HAVE_EXPAT, true)
# LIBS="-lexpat $LIBS"
# else
# AM_CONDITIONAL(HAVE_EXPAT, false)
# fi
#else
# AM_CONDITIONAL(HAVE_EXPAT, false)
#fi
#
#if [test x$xml = xtrue ]; then
# if [test x$libexpat_avail = xfalse ]; then
# AC_CACHE_CHECK(
# [if libxmlparse is available],
# [libxmlparse_avail],
# [libxmlparse_save_libs=$LIBS
# LIBS="-lxmlparse -lxmltok $LIBS"
# AC_LANG_PUSH(C++)
# AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <stdio.h>
# extern "C" {
# #include <xmlparse.h> // expat XML parser
# }]], [[XML_Parser parser = XML_ParserCreate(NULL);
# return parser != NULL;]])],[libxmlparse_avail=true],[libxmlparse_avail=false])
# AC_LANG_POP
# LIBS=$libxmlparse_save_libs])
#
# if [test x$libxmlparse_avail = xtrue ]; then
# AM_CONDITIONAL(HAVE_XMLPARSE, true)
# LIBS="-lxmlparse -lxmltok $LIBS"
# else
# AM_CONDITIONAL(HAVE_XMLPARSE, false)
# fi
# else
# AM_CONDITIONAL(HAVE_XMLPARSE, false)
# fi
#else
# AM_CONDITIONAL(HAVE_XMLPARSE, false)
#fi
# check for libofx
AC_ARG_ENABLE(ofx,
[ --enable-ofx Turn on support for OFX/OCF parsing],
@ -279,7 +231,12 @@ if [test x$ofx = xtrue ]; then
[libofx_save_libs=$LIBS
LIBS="-lofx $LIBS"
AC_LANG_PUSH(C++)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <libofx.h>]], [[ LibofxContextPtr libofx_context = libofx_get_new_context();]])],[libofx_avail=true],[libofx_avail=false])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <libofx.h>]],
[[LibofxContextPtr libofx_context = libofx_get_new_context();]])],
[libofx_avail=true],
[libofx_avail=false])
AC_LANG_POP
LIBS=$libofx_save_libs])
@ -313,12 +270,17 @@ if [test x$python = xtrue ]; then
[boost_python_save_libs=$LIBS
LIBS="-lboost_python$BOOST_SUFFIX -lpython$PYTHON_VERSION $LIBS"
AC_LANG_PUSH(C++)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <boost/python.hpp>
using namespace boost::python;
class foo {};
BOOST_PYTHON_MODULE(samp) {
class_< foo > ("foo") ;
}]], [[return 0]])],[boost_python_cpplib_avail=true],[boost_python_cpplib_avail=false])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <boost/python.hpp>
using namespace boost::python;
class foo {};
BOOST_PYTHON_MODULE(samp) {
class_< foo > ("foo") ;
}]],
[[return 0]])],
[boost_python_cpplib_avail=true],
[boost_python_cpplib_avail=false])
AC_LANG_POP
LIBS=$boost_python_save_libs])
@ -342,15 +304,20 @@ AC_CACHE_CHECK(
[cppunit_save_libs=$LIBS
LIBS="-lcppunit $LIBS"
AC_LANG_PUSH(C++)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <cppunit/CompilerOutputter.h>
#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/TestRunner.h>
#include <cppunit/TextTestProgressListener.h>
#include <cppunit/BriefTestProgressListener.h>
#include <cppunit/XmlOutputter.h>
#include <cppunit/extensions/TestFactoryRegistry.h>]], [[CPPUNIT_NS::TestResult controller;
CPPUNIT_NS::TestResultCollector result;]])],[cppunit_avail=true],[cppunit_avail=false])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <cppunit/CompilerOutputter.h>
#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/TestRunner.h>
#include <cppunit/TextTestProgressListener.h>
#include <cppunit/BriefTestProgressListener.h>
#include <cppunit/XmlOutputter.h>
#include <cppunit/extensions/TestFactoryRegistry.h>]],
[[CPPUNIT_NS::TestResult controller;
CPPUNIT_NS::TestResultCollector result;]])],
[cppunit_avail=true],
[cppunit_avail=false])
AC_LANG_POP
LIBS=$cppunit_save_libs])

View file

@ -1,14 +1,12 @@
- What does SEQUENCE + VALUE mean in XPath? Does it add VALUE to
every member of SEQUENCE?
- Add tracing code for functions that records call count and total
time spent, as well as average time per call. This would implement
selective profiling.
Answer: No, it doesn't; this should throw an error
- Make sure that if any constructors cause memory to be allocated,
that the memory is held by an auto_ptr until the constructor is
done; otherwise, an exception raised from within the constructor
will not call the destructor to free the memory.
- Make sure that if any constructors cause memory to be allocated, the
memory is held by an auto_ptr until the constructor is done;
otherwise, an exception raised from within the constructor will not
call the destructor to free the memory.
- Using mmap for the binary reader; or determine if the performance is
even worth the maintenance headaches of that code altogether.

View file

@ -585,29 +585,35 @@ amount_t& amount_t::in_place_negate()
return *this;
}
amount_t amount_t::round(precision_t prec) const
amount_t amount_t::round(const optional<precision_t>& prec) const
{
if (! quantity)
throw_(amount_error, "Cannot round an uninitialized amount");
amount_t t(*this);
if (! prec) {
if (! has_commodity())
return *this;
return round(commodity().precision());
} else {
amount_t t(*this);
if (quantity->prec <= prec) {
if (quantity && quantity->has_flags(BIGINT_KEEP_PREC)) {
t._dup();
t.quantity->drop_flags(BIGINT_KEEP_PREC);
if (quantity->prec <= *prec) {
if (quantity && quantity->has_flags(BIGINT_KEEP_PREC)) {
t._dup();
t.quantity->drop_flags(BIGINT_KEEP_PREC);
}
return t;
}
t._dup();
mpz_round(MPZ(t.quantity), MPZ(t.quantity), t.quantity->prec, *prec);
t.quantity->prec = *prec;
t.quantity->drop_flags(BIGINT_KEEP_PREC);
return t;
}
t._dup();
mpz_round(MPZ(t.quantity), MPZ(t.quantity), t.quantity->prec, prec);
t.quantity->prec = prec;
t.quantity->drop_flags(BIGINT_KEEP_PREC);
return t;
}
amount_t amount_t::unround() const
@ -1212,10 +1218,12 @@ namespace {
void amount_t::read(std::istream& in)
{
using ledger::binary;
// Read in the commodity for this amount
commodity_t::ident_t ident;
read_binary_long(in, ident);
read_long(in, ident);
if (ident == 0xffffffff)
commodity_ = NULL;
else if (ident == 0)
@ -1258,10 +1266,12 @@ void amount_t::read(std::istream& in)
void amount_t::read(const char *& data)
{
using ledger::binary;
// Read in the commodity for this amount
commodity_t::ident_t ident;
read_binary_long(data, ident);
read_long(data, ident);
if (ident == 0xffffffff)
commodity_ = NULL;
else if (ident == 0)
@ -1313,15 +1323,17 @@ void amount_t::read(const char *& data)
void amount_t::write(std::ostream& out, bool optimized) const
{
using ledger::binary;
// Write out the commodity for this amount
if (! quantity)
throw_(amount_error, "Cannot serialize an uninitialized amount");
if (commodity_)
write_binary_long(out, commodity_->ident);
write_long(out, commodity_->ident);
else
write_binary_long<commodity_t::ident_t>(out, 0xffffffff);
write_long<commodity_t::ident_t>(out, 0xffffffff);
// Write out the quantity

View file

@ -294,11 +294,11 @@ public:
* abs() returns the absolute value of an amount. It is equivalent
* to: `(x < 0) ? - x : x'.
*
* round(precision_t) rounds an amount's internal value to the given
* precision.
*
* round() rounds an amount to its commodity's current display
* precision. This also changes the internal value of the amount.
* round(optional<precision_t>) rounds an amount's internal value to
* the given precision, or to the commodity's current display
* precision if no precision value is given. This method changes
* the internal value of the amount, if it's internal precision was
* greater than the rounding precision.
*
* unround() yields an amount whose display precision is never
* truncated, even though its commodity normally displays only
@ -347,8 +347,7 @@ public:
return *this;
}
amount_t round(precision_t prec) const;
amount_t round() const;
amount_t round(const optional<precision_t>& prec) const;
amount_t unround() const;
amount_t reduce() const {
@ -700,16 +699,7 @@ inline bool amount_t::operator==(const amount_t& amt) const {
return compare(amt) == 0;
}
inline amount_t amount_t::round() const {
if (! quantity)
throw_(amount_error, "Cannot round an uninitialized amount");
if (! has_commodity())
return *this;
return round(commodity().precision());
}
inline commodity_t& amount_t::commodity() const {
// jww (2007-05-02): Should be a way to access null_commodity better
return has_commodity() ? *commodity_ : *current_pool->null_commodity;
}

View file

@ -234,7 +234,26 @@ public:
balance_t& operator-=(const amount_t& amt);
balance_t& operator*=(const amount_t& amt);
balance_t& operator*=(const double val) {
return *this *= amount_t(val);
}
balance_t& operator*=(const unsigned long val) {
return *this *= amount_t(val);
}
balance_t& operator*=(const long val) {
return *this *= amount_t(val);
}
balance_t& operator/=(const amount_t& amt);
balance_t& operator/=(const double val) {
return *this /= amount_t(val);
}
balance_t& operator/=(const unsigned long val) {
return *this /= amount_t(val);
}
balance_t& operator/=(const long val) {
return *this /= amount_t(val);
}
/**
* Unary arithmetic operators. There are only a few unary methods

View file

@ -167,21 +167,50 @@ public:
return *this = balance_t(str);
}
// in-place arithmetic
/**
* Binary arithmetic operators. Balances support addition and
* subtraction of other balance pairs, balances or amounts, but
* multiplication and division are restricted to uncommoditized
* amounts only.
*/
balance_pair_t& operator+=(const balance_pair_t& bal_pair) {
if (bal_pair.cost && ! cost)
cost = quantity;
quantity += bal_pair.quantity;
if (cost)
*cost += bal_pair.cost ? *bal_pair.cost : bal_pair.quantity;
balance_t::operator+=(bal_pair);
if (bal_pair.cost) {
if (! cost)
*cost = quantity();
*cost += *bal_pair.cost;
}
return *this;
}
balance_pair_t& operator-=(const balance_pair_t& bal_pair) {
if (bal_pair.cost && ! cost)
cost = quantity;
quantity -= bal_pair.quantity;
balance_t::operator+=(bal_pair);
if (bal_pair.cost) {
if (! cost)
*cost = quantity();
*cost += *bal_pair.cost;
}
return *this;
}
balance_pair_t& operator*=(const amount_t& amt) {
balance_t::operator*=(amt);
if (cost)
*cost -= bal_pair.cost ? *bal_pair.cost : bal_pair.quantity;
*cost *= amt;
return *this;
}
balance_pair_t& operator*=(const double val) {
return *this *= amount_t(val);
}
balance_pair_t& operator*=(const unsigned long val) {
return *this *= amount_t(val);
}
balance_pair_t& operator*=(const long val) {
return *this *= amount_t(val);
}
balance_pair_t& operator/=(const amount_t& amt) {
balance_t::operator/=(amt);
if (cost)
*cost /= amt;
return *this;
}

File diff suppressed because it is too large Load diff

View file

@ -29,217 +29,203 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _BINARY_H
#define _BINARY_H
#include "parser.h"
#ifndef BINARY_H
#define BINARY_H
namespace ledger {
#if 0
class binary_parser_t : public parser_t
{
public:
virtual bool test(std::istream& in) const;
virtual unsigned int parse(std::istream& in,
journal_t * journal,
account_t * master = NULL,
const string * original_file = NULL);
};
#endif
namespace binary {
template <typename T>
inline void read_binary_number_nocheck(std::istream& in, T& num) {
inline void read_number_nocheck(std::istream& in, T& num) {
in.read((char *)&num, sizeof(num));
}
template <typename T>
inline void read_binary_number_nocheck(const char *& data, T& num) {
inline void read_number_nocheck(const char *& data, T& num) {
num = *((T *) data);
data += sizeof(T);
}
template <typename T>
inline T read_binary_number_nocheck(std::istream& in) {
inline T read_number_nocheck(std::istream& in) {
T num;
read_binary_number_nocheck(in, num);
read_number_nocheck(in, num);
return num;
}
template <typename T>
inline T read_binary_number_nocheck(const char *& data) {
inline T read_number_nocheck(const char *& data) {
T num;
read_binary_number_nocheck(data, num);
read_number_nocheck(data, num);
return num;
}
#if DEBUG_LEVEL >= ALPHA
#define read_binary_guard(in, id) \
if (read_binary_number_nocheck<unsigned short>(in) != id) \
#define read_guard(in, id) \
if (read_number_nocheck<unsigned short>(in) != id) \
assert(false);
#else
#define read_binary_guard(in, id)
#define read_guard(in, id)
#endif
template <typename T>
inline void read_binary_number(std::istream& in, T& num) {
read_binary_guard(in, 0x2003);
inline void read_number(std::istream& in, T& num) {
read_guard(in, 0x2003);
in.read((char *)&num, sizeof(num));
read_binary_guard(in, 0x2004);
read_guard(in, 0x2004);
}
template <typename T>
inline void read_binary_number(const char *& data, T& num) {
read_binary_guard(data, 0x2003);
inline void read_number(const char *& data, T& num) {
read_guard(data, 0x2003);
num = *((T *) data);
data += sizeof(T);
read_binary_guard(data, 0x2004);
read_guard(data, 0x2004);
}
template <typename T>
inline T read_binary_number(std::istream& in) {
inline T read_number(std::istream& in) {
T num;
read_binary_number(in, num);
read_number(in, num);
return num;
}
template <typename T>
inline T read_binary_number(const char *& data) {
inline T read_number(const char *& data) {
T num;
read_binary_number(data, num);
read_number(data, num);
return num;
}
void read_binary_bool(std::istream& in, bool& num);
void read_binary_bool(const char *& data, bool& num);
void read_bool(std::istream& in, bool& num);
void read_bool(const char *& data, bool& num);
inline bool read_binary_bool(std::istream& in) {
inline bool read_bool(std::istream& in) {
bool num;
read_binary_bool(in, num);
read_bool(in, num);
return num;
}
inline bool read_binary_bool(const char *& data) {
inline bool read_bool(const char *& data) {
bool num;
read_binary_bool(data, num);
read_bool(data, num);
return num;
}
template <typename T>
void read_binary_long(std::istream& in, T& num)
void read_long(std::istream& in, T& num)
{
read_binary_guard(in, 0x2001);
read_guard(in, 0x2001);
unsigned char len;
read_binary_number_nocheck(in, len);
read_number_nocheck(in, len);
num = 0;
unsigned char temp;
if (len > 3) {
read_binary_number_nocheck(in, temp);
read_number_nocheck(in, temp);
num |= ((unsigned long)temp) << 24;
}
if (len > 2) {
read_binary_number_nocheck(in, temp);
read_number_nocheck(in, temp);
num |= ((unsigned long)temp) << 16;
}
if (len > 1) {
read_binary_number_nocheck(in, temp);
read_number_nocheck(in, temp);
num |= ((unsigned long)temp) << 8;
}
read_binary_number_nocheck(in, temp);
read_number_nocheck(in, temp);
num |= ((unsigned long)temp);
read_binary_guard(in, 0x2002);
read_guard(in, 0x2002);
}
template <typename T>
void read_binary_long(const char *& data, T& num)
void read_long(const char *& data, T& num)
{
read_binary_guard(data, 0x2001);
read_guard(data, 0x2001);
unsigned char len;
read_binary_number_nocheck(data, len);
read_number_nocheck(data, len);
num = 0;
unsigned char temp;
if (len > 3) {
read_binary_number_nocheck(data, temp);
read_number_nocheck(data, temp);
num |= ((unsigned long)temp) << 24;
}
if (len > 2) {
read_binary_number_nocheck(data, temp);
read_number_nocheck(data, temp);
num |= ((unsigned long)temp) << 16;
}
if (len > 1) {
read_binary_number_nocheck(data, temp);
read_number_nocheck(data, temp);
num |= ((unsigned long)temp) << 8;
}
read_binary_number_nocheck(data, temp);
read_number_nocheck(data, temp);
num |= ((unsigned long)temp);
read_binary_guard(data, 0x2002);
read_guard(data, 0x2002);
}
template <typename T>
inline T read_binary_long(std::istream& in) {
inline T read_long(std::istream& in) {
T num;
read_binary_long(in, num);
read_long(in, num);
return num;
}
template <typename T>
inline T read_binary_long(const char *& data) {
inline T read_long(const char *& data) {
T num;
read_binary_long(data, num);
read_long(data, num);
return num;
}
void read_binary_string(std::istream& in, string& str);
void read_binary_string(const char *& data, string& str);
void read_binary_string(const char *& data, string * str);
void read_string(std::istream& in, string& str);
void read_string(const char *& data, string& str);
void read_string(const char *& data, string * str);
inline string read_binary_string(std::istream& in) {
inline string read_string(std::istream& in) {
string temp;
read_binary_string(in, temp);
read_string(in, temp);
return temp;
}
inline string read_binary_string(const char *& data) {
inline string read_string(const char *& data) {
string temp;
read_binary_string(data, temp);
read_string(data, temp);
return temp;
}
template <typename T>
inline void write_binary_number_nocheck(std::ostream& out, T num) {
inline void write_number_nocheck(std::ostream& out, T num) {
out.write((char *)&num, sizeof(num));
}
#if DEBUG_LEVEL >= ALPHA
#define write_binary_guard(out, id) \
write_binary_number_nocheck<unsigned short>(out, id)
#define write_guard(out, id) \
write_number_nocheck<unsigned short>(out, id)
#else
#define write_binary_guard(in, id)
#define write_guard(in, id)
#endif
template <typename T>
inline void write_binary_number(std::ostream& out, T num) {
write_binary_guard(out, 0x2003);
inline void write_number(std::ostream& out, T num) {
write_guard(out, 0x2003);
out.write((char *)&num, sizeof(num));
write_binary_guard(out, 0x2004);
write_guard(out, 0x2004);
}
void write_binary_bool(std::ostream& out, bool num);
void write_bool(std::ostream& out, bool num);
template <typename T>
void write_binary_long(std::ostream& out, T num)
void write_long(std::ostream& out, T num)
{
write_binary_guard(out, 0x2001);
write_guard(out, 0x2001);
unsigned char len = 4;
if (((unsigned long)num) < 0x00000100UL)
@ -248,36 +234,36 @@ void write_binary_long(std::ostream& out, T num)
len = 2;
else if (((unsigned long)num) < 0x01000000UL)
len = 3;
write_binary_number_nocheck<unsigned char>(out, len);
write_number_nocheck<unsigned char>(out, len);
unsigned char temp;
if (len > 3) {
temp = (((unsigned long)num) & 0xFF000000UL) >> 24;
write_binary_number_nocheck(out, temp);
write_number_nocheck(out, temp);
}
if (len > 2) {
temp = (((unsigned long)num) & 0x00FF0000UL) >> 16;
write_binary_number_nocheck(out, temp);
write_number_nocheck(out, temp);
}
if (len > 1) {
temp = (((unsigned long)num) & 0x0000FF00UL) >> 8;
write_binary_number_nocheck(out, temp);
write_number_nocheck(out, temp);
}
temp = (((unsigned long)num) & 0x000000FFUL);
write_binary_number_nocheck(out, temp);
write_number_nocheck(out, temp);
write_binary_guard(out, 0x2002);
write_guard(out, 0x2002);
}
void write_binary_string(std::ostream& out, const string& str);
void write_string(std::ostream& out, const string& str);
template <typename T>
inline void write_object(std::ostream& out, const T& journal) {
assert(false);
}
#if 0
void write_binary_journal(std::ostream& out, journal_t * journal);
#endif
} // namespace binary
} // namespace ledger
#endif // _BINARY_H
#endif // BINARY_H

View file

@ -49,7 +49,7 @@
* - exception framework
* - date/time type
* - supports_flags<> for objects that use flags
* - scoped_execute<> for guaranteeing code execution
* - push_variable<> for restoring variable values
*/
#ifndef _UTILS_H
@ -512,7 +512,7 @@ inline void throw_unexpected_error(char, char) {
#include "times.h"
#include "flags.h"
#include "scoped_execute.h"
#include "pushvar.h"
/**********************************************************************
*