Removed the binary caching code, and the XML, QIF and Gnucash parsers.
This commit is contained in:
parent
9bdcbffb15
commit
3434650848
37 changed files with 6 additions and 2979 deletions
6
.gitmodules
vendored
6
.gitmodules
vendored
|
|
@ -1,12 +1,6 @@
|
|||
[submodule "lib/cppunit"]
|
||||
path = lib/cppunit
|
||||
url = git://github.com/jwiegley/cppunit.git
|
||||
[submodule "lib/libofx"]
|
||||
path = lib/libofx
|
||||
url = git://github.com/jwiegley/libofx.git
|
||||
[submodule "lib/utfcpp"]
|
||||
path = lib/utfcpp
|
||||
url = git://github.com/jwiegley/utfcpp.git
|
||||
[submodule "lib/irrxml"]
|
||||
path = lib/irrxml
|
||||
url = git://github.com/jwiegley/irrxml.git
|
||||
|
|
|
|||
34
Makefile.am
34
Makefile.am
|
|
@ -10,8 +10,7 @@ lib_LTLIBRARIES = \
|
|||
libledger_util.la
|
||||
|
||||
lib_cppflags = -I$(srcdir)/src -I$(srcdir)/lib \
|
||||
-I$(srcdir)/lib/utfcpp/source \
|
||||
-I$(srcdir)/lib/irrxml/src
|
||||
-I$(srcdir)/lib/utfcpp/source
|
||||
|
||||
libledger_util_la_SOURCES = \
|
||||
src/utils.cc \
|
||||
|
|
@ -19,7 +18,6 @@ libledger_util_la_SOURCES = \
|
|||
src/times.cc \
|
||||
src/mask.cc \
|
||||
src/stream.cc \
|
||||
src/binary.cc \
|
||||
lib/sha1.cpp
|
||||
|
||||
libledger_util_la_CPPFLAGS = $(lib_cppflags)
|
||||
|
|
@ -63,16 +61,8 @@ libledger_data_la_LDFLAGS = -release $(VERSION).0
|
|||
|
||||
libledger_parse_la_SOURCES = \
|
||||
src/textual.cc \
|
||||
src/cache.cc \
|
||||
src/xml.cc \
|
||||
src/csv.cc \
|
||||
src/emacs.cc \
|
||||
src/qif.cc \
|
||||
src/gnucash.cc \
|
||||
lib/irrxml/src/irrXML.cpp
|
||||
if HAVE_LIBOFX
|
||||
libledger_parse_la_SOURCES += src/ofx.cc
|
||||
endif
|
||||
src/emacs.cc
|
||||
|
||||
libledger_parse_la_CPPFLAGS = $(lib_cppflags)
|
||||
libledger_parse_la_LDFLAGS = -release $(VERSION).0
|
||||
|
|
@ -103,7 +93,6 @@ pkginclude_HEADERS = \
|
|||
src/times.h \
|
||||
src/mask.h \
|
||||
src/stream.h \
|
||||
src/binary.h \
|
||||
\
|
||||
src/amount.h \
|
||||
src/commodity.h \
|
||||
|
|
@ -130,13 +119,8 @@ pkginclude_HEADERS = \
|
|||
src/compare.h \
|
||||
\
|
||||
src/textual.h \
|
||||
src/cache.h \
|
||||
src/xml.h \
|
||||
src/csv.h \
|
||||
src/emacs.h \
|
||||
src/qif.h \
|
||||
src/gnucash.h \
|
||||
src/ofx.h \
|
||||
\
|
||||
src/session.h \
|
||||
src/report.h \
|
||||
|
|
@ -163,15 +147,7 @@ pkginclude_HEADERS = \
|
|||
lib/utfcpp/source/utf8.h \
|
||||
lib/utfcpp/source/utf8/checked.h \
|
||||
lib/utfcpp/source/utf8/core.h \
|
||||
lib/utfcpp/source/utf8/unchecked.h \
|
||||
\
|
||||
lib/irrxml/src/CXMLReaderImpl.h \
|
||||
lib/irrxml/src/fast_atof.h \
|
||||
lib/irrxml/src/heapsort.h \
|
||||
lib/irrxml/src/irrArray.h \
|
||||
lib/irrxml/src/irrString.h \
|
||||
lib/irrxml/src/irrTypes.h \
|
||||
lib/irrxml/src/irrXML.h
|
||||
lib/utfcpp/source/utf8/unchecked.h
|
||||
|
||||
CLEANFILES =
|
||||
|
||||
|
|
@ -286,10 +262,6 @@ PYLIBS = ledger_python \
|
|||
boost_regex$(BOOST_SUFFIX) \
|
||||
boost_python$(BOOST_SUFFIX)
|
||||
|
||||
if HAVE_LIBOFX
|
||||
PYLIBS += ofx
|
||||
endif
|
||||
|
||||
ledger.so: $(ledger_so_SOURCES) $(ledger_so_DEPENDENCIES)
|
||||
BUILD_DIR=`cd $(top_builddir); pwd`; \
|
||||
SRC_DIR=`cd $(srcdir); pwd`; \
|
||||
|
|
|
|||
22
configure.ac
22
configure.ac
|
|
@ -220,28 +220,6 @@ else
|
|||
AC_MSG_FAILURE("Could not find boost_filesystem library (set CPPFLAGS and LDFLAGS?)")
|
||||
fi
|
||||
|
||||
# check for libofx
|
||||
AC_CACHE_CHECK(
|
||||
[if libofx is available],
|
||||
[libofx_avail_cv_],
|
||||
[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_cv_=true],
|
||||
[libofx_avail_cv_=false])
|
||||
AC_LANG_POP
|
||||
LIBS=$libofx_save_libs])
|
||||
|
||||
if [ test x$libofx_avail_cv_ = xtrue ]; then
|
||||
AC_DEFINE([HAVE_LIBOFX], [1], [Whether libofx is available])
|
||||
LIBS="-lofx $LIBS"
|
||||
fi
|
||||
AM_CONDITIONAL(HAVE_LIBOFX, test x$libofx_avail_cv_ = xtrue)
|
||||
|
||||
# check for Python
|
||||
AM_PATH_PYTHON(2.4,, :)
|
||||
if [test "$PYTHON" != :]; then
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
Subproject commit e0f5ec13193e413ddcfcf70bcb8886c0c6a8a60c
|
||||
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 31ab2c052edb3e72fc1fda385d6d118c479407f3
|
||||
|
|
@ -84,39 +84,6 @@ void py_print(amount_t& amount, object out) {
|
|||
}
|
||||
}
|
||||
|
||||
void py_read_1(amount_t& amount, object in) {
|
||||
if (PyFile_Check(in.ptr())) {
|
||||
pyifstream instr(reinterpret_cast<PyFileObject *>(in.ptr()));
|
||||
amount.read(instr);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_IOError,
|
||||
"Argument to amount.read(file) is not a file object");
|
||||
}
|
||||
}
|
||||
void py_read_2(amount_t& amount, const std::string& str) {
|
||||
const char * p = str.c_str();
|
||||
amount.read(p);
|
||||
}
|
||||
|
||||
void py_write_xml_1(amount_t& amount, object out) {
|
||||
if (PyFile_Check(out.ptr())) {
|
||||
pyofstream outstr(reinterpret_cast<PyFileObject *>(out.ptr()));
|
||||
amount.write_xml(outstr);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_IOError,
|
||||
"Argument to amount.write_xml(file) is not a file object");
|
||||
}
|
||||
}
|
||||
void py_write_xml_2(amount_t& amount, object out, const int depth) {
|
||||
if (PyFile_Check(out.ptr())) {
|
||||
pyofstream outstr(reinterpret_cast<PyFileObject *>(out.ptr()));
|
||||
amount.write_xml(outstr, depth);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_IOError,
|
||||
"Argument to amount.write_xml(file, depth) is not a file object");
|
||||
}
|
||||
}
|
||||
|
||||
#define EXC_TRANSLATOR(type) \
|
||||
void exc_translate_ ## type(const type& err) { \
|
||||
PyErr_SetString(PyExc_ArithmeticError, err.what()); \
|
||||
|
|
@ -338,14 +305,6 @@ internal precision.")
|
|||
|
||||
.def("print_", py_print)
|
||||
|
||||
.def("read", py_read_1)
|
||||
.def("read", py_read_2)
|
||||
.def("write", &amount_t::write)
|
||||
|
||||
.def("read_xml", &amount_t::read_xml)
|
||||
.def("write_xml", py_write_xml_1)
|
||||
.def("write_xml", py_write_xml_2)
|
||||
|
||||
.def("dump", &amount_t::dump)
|
||||
|
||||
.def("valid", &amount_t::valid)
|
||||
|
|
|
|||
|
|
@ -58,20 +58,6 @@ void py_set_string(value_t& amount, const string& str) {
|
|||
return amount.set_string(str);
|
||||
}
|
||||
|
||||
void py_read_1(value_t& amount, object in) {
|
||||
if (PyFile_Check(in.ptr())) {
|
||||
pyifstream instr(reinterpret_cast<PyFileObject *>(in.ptr()));
|
||||
amount.read(instr);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_IOError,
|
||||
"Argument to amount.parse(file) is not a file object");
|
||||
}
|
||||
}
|
||||
void py_read_2(value_t& amount, const std::string& str) {
|
||||
const char * p = str.c_str();
|
||||
amount.read(p);
|
||||
}
|
||||
|
||||
#define EXC_TRANSLATOR(type) \
|
||||
void exc_translate_ ## type(const type& err) { \
|
||||
PyErr_SetString(PyExc_ArithmeticError, err.what()); \
|
||||
|
|
@ -278,10 +264,6 @@ void export_value()
|
|||
.def("dump", &value_t::dump)
|
||||
.def("print", &value_t::print)
|
||||
|
||||
.def("read", py_read_1)
|
||||
.def("read", py_read_2)
|
||||
.def("write", &value_t::write)
|
||||
|
||||
.def("valid", &value_t::valid)
|
||||
;
|
||||
|
||||
|
|
|
|||
220
src/amount.cc
220
src/amount.cc
|
|
@ -30,7 +30,6 @@
|
|||
*/
|
||||
|
||||
#include "amount.h"
|
||||
#include "binary.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
|
|
@ -1021,225 +1020,6 @@ void amount_t::print(std::ostream& _out, bool omit_commodity,
|
|||
_out << out.str();
|
||||
}
|
||||
|
||||
void amount_t::read(std::istream& in)
|
||||
{
|
||||
using namespace ledger::binary;
|
||||
|
||||
// Read in the commodity for this amount
|
||||
|
||||
commodity_t::ident_t ident;
|
||||
read_long(in, ident);
|
||||
if (ident == 0xffffffff)
|
||||
commodity_ = NULL;
|
||||
else if (ident == 0)
|
||||
commodity_ = current_pool->null_commodity;
|
||||
else {
|
||||
commodity_ = current_pool->find(ident);
|
||||
assert(commodity_);
|
||||
}
|
||||
|
||||
// Read in the quantity
|
||||
|
||||
char byte;
|
||||
in.read(&byte, sizeof(byte));
|
||||
|
||||
if (byte < 3) {
|
||||
quantity = new bigint_t;
|
||||
|
||||
unsigned short len;
|
||||
in.read(reinterpret_cast<char *>(&len), sizeof(len));
|
||||
assert(len < 4096);
|
||||
static char buf[4096];
|
||||
in.read(buf, len);
|
||||
|
||||
mpz_import(temp, len / sizeof(short), 1, sizeof(short),
|
||||
0, 0, buf);
|
||||
mpq_set_num(MP(quantity), temp);
|
||||
|
||||
in.read(reinterpret_cast<char *>(&len), sizeof(len));
|
||||
assert(len < 4096);
|
||||
in.read(buf, len);
|
||||
mpz_import(temp, len / sizeof(short), 1, sizeof(short),
|
||||
0, 0, buf);
|
||||
mpq_set_den(MP(quantity), temp);
|
||||
|
||||
char negative;
|
||||
in.read(&negative, sizeof(negative));
|
||||
if (negative)
|
||||
mpq_neg(MP(quantity), MP(quantity));
|
||||
|
||||
in.read(reinterpret_cast<char *>(&quantity->prec), sizeof(quantity->prec));
|
||||
|
||||
bigint_t::flags_t tflags;
|
||||
in.read(reinterpret_cast<char *>(&tflags), sizeof(tflags));
|
||||
quantity->set_flags(tflags);
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
void amount_t::read(const char *& data,
|
||||
char ** pool,
|
||||
char ** pool_next)
|
||||
{
|
||||
using namespace ledger::binary;
|
||||
|
||||
// Read in the commodity for this amount
|
||||
|
||||
commodity_t::ident_t ident;
|
||||
read_long(data, ident);
|
||||
if (ident == 0xffffffff)
|
||||
commodity_ = NULL;
|
||||
else if (ident == 0)
|
||||
commodity_ = current_pool->null_commodity;
|
||||
else {
|
||||
commodity_ = current_pool->find(ident);
|
||||
assert(commodity_);
|
||||
}
|
||||
|
||||
// Read in the quantity
|
||||
|
||||
char byte = *data++;;
|
||||
|
||||
if (byte < 3) {
|
||||
if (byte == 2) {
|
||||
quantity = new(reinterpret_cast<bigint_t *>(*pool_next)) bigint_t;
|
||||
*pool_next += sizeof(bigint_t);
|
||||
} else {
|
||||
quantity = new bigint_t;
|
||||
}
|
||||
|
||||
unsigned short len =
|
||||
*reinterpret_cast<unsigned short *>(const_cast<char *>(data));
|
||||
data += sizeof(unsigned short);
|
||||
mpz_init(temp);
|
||||
mpz_import(temp, len / sizeof(short), 1, sizeof(short),
|
||||
0, 0, data);
|
||||
data += len;
|
||||
|
||||
mpq_set_num(MP(quantity), temp);
|
||||
|
||||
len = *reinterpret_cast<unsigned short *>(const_cast<char *>(data));
|
||||
data += sizeof(unsigned short);
|
||||
mpz_init(temp);
|
||||
mpz_import(temp, len / sizeof(short), 1, sizeof(short),
|
||||
0, 0, data);
|
||||
data += len;
|
||||
|
||||
mpq_set_den(MP(quantity), temp);
|
||||
|
||||
char negative = *data++;
|
||||
if (negative)
|
||||
mpq_neg(MP(quantity), MP(quantity));
|
||||
|
||||
quantity->prec = *reinterpret_cast<precision_t *>(const_cast<char *>(data));
|
||||
data += sizeof(precision_t);
|
||||
quantity->set_flags(*reinterpret_cast<bigint_t::flags_t *>(const_cast<char *>(data)));
|
||||
data += sizeof(bigint_t::flags_t);
|
||||
|
||||
if (byte == 2)
|
||||
quantity->add_flags(BIGINT_BULK_ALLOC);
|
||||
} else {
|
||||
uint_fast32_t index = *reinterpret_cast<uint_fast32_t *>(const_cast<char *>(data));
|
||||
data += sizeof(uint_fast32_t);
|
||||
|
||||
quantity = reinterpret_cast<bigint_t *>(*pool + (index - 1) * sizeof(bigint_t));
|
||||
|
||||
DEBUG("amounts.refs",
|
||||
quantity << " ref++, now " << (quantity->ref + 1));
|
||||
quantity->ref++;
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
void write_bytes(std::ostream& out,
|
||||
const char * buf,
|
||||
const std::size_t size)
|
||||
{
|
||||
unsigned short len = size * sizeof(short);
|
||||
out.write(reinterpret_cast<char *>(&len), sizeof(len));
|
||||
if (len) {
|
||||
assert(len < 4096);
|
||||
out.write(buf, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void amount_t::write(std::ostream& out, std::size_t index) const
|
||||
{
|
||||
using namespace ledger::binary;
|
||||
|
||||
// Write out the commodity for this amount
|
||||
|
||||
if (! quantity)
|
||||
throw_(amount_error, "Cannot serialize an uninitialized amount");
|
||||
|
||||
if (commodity_)
|
||||
write_long(out, commodity_->ident);
|
||||
else
|
||||
write_long<commodity_t::ident_t>(out, 0xffffffff);
|
||||
|
||||
// Write out the quantity
|
||||
|
||||
char byte;
|
||||
|
||||
if (index == 0 || quantity->index == 0) {
|
||||
if (index != 0) {
|
||||
quantity->index = index; // if !optimized, this is garbage
|
||||
byte = 2;
|
||||
} else {
|
||||
byte = 1;
|
||||
}
|
||||
out.write(&byte, sizeof(byte));
|
||||
|
||||
std::size_t size;
|
||||
static char buf[4096];
|
||||
|
||||
mpq_get_num(temp, MP(quantity));
|
||||
mpz_export(buf, &size, 1, sizeof(short), 0, 0, temp);
|
||||
write_bytes(out, buf, size);
|
||||
|
||||
mpq_get_den(temp, MP(quantity));
|
||||
mpz_export(buf, &size, 1, sizeof(short), 0, 0, temp);
|
||||
write_bytes(out, buf, size);
|
||||
|
||||
byte = mpq_sgn(MP(quantity)) < 0 ? 1 : 0;
|
||||
out.write(&byte, sizeof(byte));
|
||||
|
||||
out.write(reinterpret_cast<char *>(&quantity->prec), sizeof(quantity->prec));
|
||||
bigint_t::flags_t tflags = quantity->flags() & ~BIGINT_BULK_ALLOC;
|
||||
assert(sizeof(tflags) == sizeof(bigint_t::flags_t));
|
||||
out.write(reinterpret_cast<char *>(&tflags), sizeof(tflags));
|
||||
} else {
|
||||
assert(quantity->ref > 1);
|
||||
|
||||
// Since this value has already been written, we simply write
|
||||
// out a reference to which one it was.
|
||||
byte = 3;
|
||||
out.write(&byte, sizeof(byte));
|
||||
out.write(reinterpret_cast<char *>(&quantity->index), sizeof(quantity->index));
|
||||
}
|
||||
}
|
||||
|
||||
void amount_t::read_xml(std::istream& in)
|
||||
{
|
||||
}
|
||||
|
||||
void amount_t::write_xml(std::ostream& out, const int depth) const
|
||||
{
|
||||
out << xml_str("<amount>\n", depth);
|
||||
|
||||
if (has_commodity())
|
||||
commodity().write_xml(out, depth + 1);
|
||||
|
||||
out << xml_str("<quantity>", depth + 1)
|
||||
<< quantity_string()
|
||||
<< "</quantity>\n";
|
||||
|
||||
out << xml_str("</amount>\n", depth);
|
||||
}
|
||||
|
||||
bool amount_t::valid() const
|
||||
{
|
||||
if (quantity) {
|
||||
|
|
|
|||
45
src/amount.h
45
src/amount.h
|
|
@ -671,51 +671,6 @@ public:
|
|||
|
||||
/*@}*/
|
||||
|
||||
/** @name Serialization
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
/** An amount may be deserialized from an input stream or a character
|
||||
pointer, and it may be serialized to an output stream. The methods
|
||||
used are:
|
||||
|
||||
read(istream) reads an amount from the given input stream. It
|
||||
must have been put there using `write(ostream)'. The required
|
||||
flow of logic is:
|
||||
amount_t::current_pool->write(out)
|
||||
amount.write(out) // write out all amounts
|
||||
amount_t::current_pool->read(in)
|
||||
amount.read(in)
|
||||
|
||||
read(char *&) reads an amount from data which has been read from
|
||||
an input stream into a buffer. It advances the pointer passed in
|
||||
to the end of the deserialized amount.
|
||||
|
||||
write(ostream, [bool]) writes an amount to an output stream in a
|
||||
compact binary format. If the second parameter is true,
|
||||
quantities with multiple reference counts will be written in an
|
||||
optimized fashion. NOTE: This form of usage is valid only for
|
||||
the binary journal writer, it should not be used otherwise, as it
|
||||
has strict requirements for reading that only the binary reader
|
||||
knows about.
|
||||
*/
|
||||
void read(std::istream& in);
|
||||
void read(const char *& data,
|
||||
char ** pool = NULL,
|
||||
char ** pool_next = NULL);
|
||||
void write(std::ostream& out, std::size_t index = 0) const;
|
||||
|
||||
/*@}*/
|
||||
|
||||
/** @name XML Serialization
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
void read_xml(std::istream& in);
|
||||
void write_xml(std::ostream& out, const int depth = 0) const;
|
||||
|
||||
/*@}*/
|
||||
|
||||
/** @name Debugging
|
||||
*/
|
||||
/*@{*/
|
||||
|
|
|
|||
|
|
@ -252,14 +252,4 @@ void balance_t::print(std::ostream& out,
|
|||
}
|
||||
}
|
||||
|
||||
void balance_t::write_xml(std::ostream& out, const int depth) const
|
||||
{
|
||||
out << xml_str("<balance>\n", depth);
|
||||
|
||||
foreach (const amounts_map::value_type& pair, amounts)
|
||||
pair.second.write_xml(out, depth + 1);
|
||||
|
||||
out << xml_str("</balance>\n", depth);
|
||||
}
|
||||
|
||||
} // namespace ledger
|
||||
|
|
|
|||
|
|
@ -475,15 +475,6 @@ public:
|
|||
void print(std::ostream& out, const int first_width,
|
||||
const int latter_width = -1) const;
|
||||
|
||||
/** @name XML Serialization
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
void read_xml(std::istream& in);
|
||||
void write_xml(std::ostream& out, const int depth = 0) const;
|
||||
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* Debugging methods. There are two methods defined to help with
|
||||
* debugging:
|
||||
|
|
|
|||
|
|
@ -53,15 +53,4 @@ balance_pair_t::value(const optional<datetime_t>& moment,
|
|||
return none;
|
||||
}
|
||||
|
||||
void balance_pair_t::write_xml(std::ostream& out, const int depth) const
|
||||
{
|
||||
out << xml_str("<balance-pair>\n", depth);
|
||||
|
||||
quantity().write_xml(out, depth + 1);
|
||||
if (cost)
|
||||
cost->write_xml(out, depth + 1);
|
||||
|
||||
out << xml_str("</balance-pair>\n", depth);
|
||||
}
|
||||
|
||||
} // namespace ledger
|
||||
|
|
|
|||
|
|
@ -343,15 +343,6 @@ public:
|
|||
return balance_t::operator==(val);
|
||||
}
|
||||
|
||||
/** @name XML Serialization
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
void read_xml(std::istream& in);
|
||||
void write_xml(std::ostream& out, const int depth = 0) const;
|
||||
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* Debugging methods. There is only one method specifically for
|
||||
* balance pairs to help with debugging:
|
||||
|
|
|
|||
188
src/binary.cc
188
src/binary.cc
|
|
@ -1,188 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2009, John Wiegley. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of New Artisans LLC nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "binary.h"
|
||||
|
||||
namespace ledger {
|
||||
namespace binary {
|
||||
|
||||
void read_bool(std::istream& in, bool& num)
|
||||
{
|
||||
read_guard(in, 0x2005);
|
||||
unsigned char val;
|
||||
in.read(reinterpret_cast<char *>(&val), sizeof(val));
|
||||
num = val == 1;
|
||||
read_guard(in, 0x2006);
|
||||
}
|
||||
|
||||
void read_bool(const char *& data, bool& num)
|
||||
{
|
||||
read_guard(data, 0x2005);
|
||||
const unsigned char val = *reinterpret_cast<const unsigned char *>(data);
|
||||
data += sizeof(unsigned char);
|
||||
num = val == 1;
|
||||
read_guard(data, 0x2006);
|
||||
}
|
||||
|
||||
void read_string(std::istream& in, string& str)
|
||||
{
|
||||
read_guard(in, 0x3001);
|
||||
|
||||
unsigned char len;
|
||||
read_number_nocheck(in, len);
|
||||
if (len == 0xff) {
|
||||
unsigned short slen;
|
||||
read_number_nocheck(in, slen);
|
||||
char * buf = new char[slen + 1];
|
||||
in.read(buf, slen);
|
||||
buf[slen] = '\0';
|
||||
str = buf;
|
||||
checked_array_delete(buf);
|
||||
}
|
||||
else if (len) {
|
||||
char buf[256];
|
||||
in.read(buf, len);
|
||||
buf[len] = '\0';
|
||||
str = buf;
|
||||
} else {
|
||||
str = "";
|
||||
}
|
||||
|
||||
read_guard(in, 0x3002);
|
||||
}
|
||||
|
||||
void read_string(const char *& data, string& str)
|
||||
{
|
||||
read_guard(data, 0x3001);
|
||||
|
||||
unsigned char len;
|
||||
read_number_nocheck(data, len);
|
||||
if (len == 0xff) {
|
||||
unsigned short slen;
|
||||
read_number_nocheck(data, slen);
|
||||
str = string(data, slen);
|
||||
data += slen;
|
||||
}
|
||||
else if (len) {
|
||||
str = string(data, len);
|
||||
data += len;
|
||||
}
|
||||
else {
|
||||
str = "";
|
||||
}
|
||||
|
||||
read_guard(data, 0x3002);
|
||||
}
|
||||
|
||||
void read_string(const char *& data, string * str)
|
||||
{
|
||||
read_guard(data, 0x3001);
|
||||
|
||||
unsigned char len;
|
||||
read_number_nocheck(data, len);
|
||||
if (len == 0xff) {
|
||||
unsigned short slen;
|
||||
read_number_nocheck(data, slen);
|
||||
new(str) string(data, slen);
|
||||
data += slen;
|
||||
}
|
||||
else if (len) {
|
||||
new(str) string(data, len);
|
||||
data += len;
|
||||
}
|
||||
else {
|
||||
new(str) string("");
|
||||
}
|
||||
|
||||
read_guard(data, 0x3002);
|
||||
}
|
||||
|
||||
void read_string(std::istream& in, optional<string>& str)
|
||||
{
|
||||
if (read_bool(in)) {
|
||||
string temp;
|
||||
read_string(in, temp);
|
||||
str = temp;
|
||||
} else {
|
||||
str = none;
|
||||
}
|
||||
}
|
||||
|
||||
void read_string(const char *& data, optional<string>& str)
|
||||
{
|
||||
if (read_bool(data)) {
|
||||
string temp;
|
||||
read_string(data, temp);
|
||||
str = temp;
|
||||
} else {
|
||||
str = none;
|
||||
}
|
||||
}
|
||||
|
||||
void write_bool(std::ostream& out, bool num)
|
||||
{
|
||||
write_guard(out, 0x2005);
|
||||
unsigned char val = num ? 1 : 0;
|
||||
out.write(reinterpret_cast<char *>(&val), sizeof(val));
|
||||
write_guard(out, 0x2006);
|
||||
}
|
||||
|
||||
void write_string(std::ostream& out, const string& str)
|
||||
{
|
||||
write_guard(out, 0x3001);
|
||||
|
||||
std::size_t len = str.length();
|
||||
if (len > 255) {
|
||||
assert(len < 65536);
|
||||
write_number_nocheck<unsigned char>(out, 0xff);
|
||||
write_number_nocheck<unsigned short>(out, len);
|
||||
} else {
|
||||
write_number_nocheck<unsigned char>(out, len);
|
||||
}
|
||||
|
||||
if (len)
|
||||
out.write(str.c_str(), len);
|
||||
|
||||
write_guard(out, 0x3002);
|
||||
}
|
||||
|
||||
void write_string(std::ostream& out, const optional<string>& str)
|
||||
{
|
||||
if (str) {
|
||||
write_bool(out, true);
|
||||
write_string(out, *str);
|
||||
} else {
|
||||
write_bool(out, false);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace binary
|
||||
} // namespace ledger
|
||||
286
src/binary.h
286
src/binary.h
|
|
@ -1,286 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2009, John Wiegley. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of New Artisans LLC nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup util
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file binary.h
|
||||
* @author John Wiegley
|
||||
*
|
||||
* @ingroup util
|
||||
*
|
||||
* @brief General binary object streaming.
|
||||
*/
|
||||
#ifndef BINARY_H
|
||||
#define BINARY_H
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
namespace ledger {
|
||||
namespace binary {
|
||||
|
||||
template <typename T>
|
||||
inline void read_number_nocheck(std::istream& in, T& num) {
|
||||
in.read(reinterpret_cast<char *>(&num), sizeof(num));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void read_number_nocheck(const char *& data, T& num) {
|
||||
num = *reinterpret_cast<const T *>(data);
|
||||
data += sizeof(T);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T read_number_nocheck(std::istream& in) {
|
||||
T num;
|
||||
read_number_nocheck(in, num);
|
||||
return num;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T read_number_nocheck(const char *& data) {
|
||||
T num;
|
||||
read_number_nocheck(data, num);
|
||||
return num;
|
||||
}
|
||||
|
||||
#if DEBUG_LEVEL >= ALPHA
|
||||
#define read_guard(in, id) \
|
||||
if (read_number_nocheck<unsigned short>(in) != id) \
|
||||
assert(false);
|
||||
#else
|
||||
#define read_guard(in, id)
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
inline void read_number(std::istream& in, T& num) {
|
||||
read_guard(in, 0x2003);
|
||||
in.read(reinterpret_cast<char *>(&num), sizeof(num));
|
||||
read_guard(in, 0x2004);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void read_number(const char *& data, T& num) {
|
||||
read_guard(data, 0x2003);
|
||||
num = *reinterpret_cast<const T *>(data);
|
||||
data += sizeof(T);
|
||||
read_guard(data, 0x2004);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T read_number(std::istream& in) {
|
||||
T num;
|
||||
read_number(in, num);
|
||||
return num;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T read_number(const char *& data) {
|
||||
T num;
|
||||
read_number(data, num);
|
||||
return num;
|
||||
}
|
||||
|
||||
void read_bool(std::istream& in, bool& num);
|
||||
void read_bool(const char *& data, bool& num);
|
||||
|
||||
inline bool read_bool(std::istream& in) {
|
||||
bool num;
|
||||
read_bool(in, num);
|
||||
return num;
|
||||
}
|
||||
|
||||
inline bool read_bool(const char *& data) {
|
||||
bool num;
|
||||
read_bool(data, num);
|
||||
return num;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void read_long(std::istream& in, T& num)
|
||||
{
|
||||
read_guard(in, 0x2001);
|
||||
|
||||
unsigned char len;
|
||||
read_number_nocheck(in, len);
|
||||
|
||||
num = 0;
|
||||
unsigned char temp;
|
||||
if (len > 3) {
|
||||
read_number_nocheck(in, temp);
|
||||
num |= static_cast<unsigned long>(temp) << 24;
|
||||
}
|
||||
if (len > 2) {
|
||||
read_number_nocheck(in, temp);
|
||||
num |= static_cast<unsigned long>(temp) << 16;
|
||||
}
|
||||
if (len > 1) {
|
||||
read_number_nocheck(in, temp);
|
||||
num |= static_cast<unsigned long>(temp) << 8;
|
||||
}
|
||||
|
||||
read_number_nocheck(in, temp);
|
||||
num |= static_cast<unsigned long>(temp);
|
||||
|
||||
read_guard(in, 0x2002);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void read_long(const char *& data, T& num)
|
||||
{
|
||||
read_guard(data, 0x2001);
|
||||
|
||||
uint_least8_t len;
|
||||
read_number_nocheck(data, len);
|
||||
|
||||
num = static_cast<T>(0);
|
||||
uint_least8_t temp;
|
||||
if (len > 3) {
|
||||
read_number_nocheck(data, temp);
|
||||
num = static_cast<T>(static_cast<uint_least32_t>(num) |
|
||||
(static_cast<uint_least32_t>(temp) << 24));
|
||||
}
|
||||
if (len > 2) {
|
||||
read_number_nocheck(data, temp);
|
||||
num = static_cast<T>(static_cast<uint_least32_t>(num) |
|
||||
(static_cast<uint_least32_t>(temp) << 16));
|
||||
}
|
||||
if (len > 1) {
|
||||
read_number_nocheck(data, temp);
|
||||
num = static_cast<T>(static_cast<uint_least32_t>(num) |
|
||||
(static_cast<uint_least32_t>(temp) << 8));
|
||||
}
|
||||
|
||||
read_number_nocheck(data, temp);
|
||||
num = static_cast<T>(static_cast<uint_least32_t>(num) |
|
||||
static_cast<uint_least32_t>(temp));
|
||||
|
||||
read_guard(data, 0x2002);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T read_long(std::istream& in) {
|
||||
T num;
|
||||
read_long(in, num);
|
||||
return num;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T read_long(const char *& data) {
|
||||
T num;
|
||||
read_long(data, num);
|
||||
return num;
|
||||
}
|
||||
|
||||
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_string(std::istream& in) {
|
||||
string temp;
|
||||
read_string(in, temp);
|
||||
return temp;
|
||||
}
|
||||
|
||||
inline string read_string(const char *& data) {
|
||||
string temp;
|
||||
read_string(data, temp);
|
||||
return temp;
|
||||
}
|
||||
|
||||
void read_string(std::istream& in, optional<string>& str);
|
||||
void read_string(const char *& data, optional<string>& str);
|
||||
|
||||
|
||||
template <typename T>
|
||||
inline void write_number_nocheck(std::ostream& out, T num) {
|
||||
out.write(reinterpret_cast<char *>(&num), sizeof(num));
|
||||
}
|
||||
|
||||
#if DEBUG_LEVEL >= ALPHA
|
||||
#define write_guard(out, id) \
|
||||
write_number_nocheck<unsigned short>(out, id)
|
||||
#else
|
||||
#define write_guard(in, id)
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
inline void write_number(std::ostream& out, T num) {
|
||||
write_guard(out, 0x2003);
|
||||
out.write(reinterpret_cast<char *>(&num), sizeof(num));
|
||||
write_guard(out, 0x2004);
|
||||
}
|
||||
|
||||
void write_bool(std::ostream& out, bool num);
|
||||
|
||||
template <typename T>
|
||||
void write_long(std::ostream& out, T num)
|
||||
{
|
||||
write_guard(out, 0x2001);
|
||||
|
||||
unsigned char len = 4;
|
||||
if (static_cast<unsigned long>(num) < 0x00000100UL)
|
||||
len = 1;
|
||||
else if (static_cast<unsigned long>(num) < 0x00010000UL)
|
||||
len = 2;
|
||||
else if (static_cast<unsigned long>(num) < 0x01000000UL)
|
||||
len = 3;
|
||||
write_number_nocheck<unsigned char>(out, len);
|
||||
|
||||
unsigned char temp;
|
||||
if (len > 3) {
|
||||
temp = (static_cast<unsigned long>(num) & 0xFF000000UL) >> 24;
|
||||
write_number_nocheck(out, temp);
|
||||
}
|
||||
if (len > 2) {
|
||||
temp = (static_cast<unsigned long>(num) & 0x00FF0000UL) >> 16;
|
||||
write_number_nocheck(out, temp);
|
||||
}
|
||||
if (len > 1) {
|
||||
temp = (static_cast<unsigned long>(num) & 0x0000FF00UL) >> 8;
|
||||
write_number_nocheck(out, temp);
|
||||
}
|
||||
|
||||
temp = (static_cast<unsigned long>(num) & 0x000000FFUL);
|
||||
write_number_nocheck(out, temp);
|
||||
|
||||
write_guard(out, 0x2002);
|
||||
}
|
||||
|
||||
void write_string(std::ostream& out, const string& str);
|
||||
void write_string(std::ostream& out, const optional<string>& str);
|
||||
|
||||
} // namespace binary
|
||||
} // namespace ledger
|
||||
|
||||
#endif // BINARY_H
|
||||
896
src/cache.cc
896
src/cache.cc
|
|
@ -1,896 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2009, John Wiegley. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of New Artisans LLC nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "cache.h"
|
||||
#include "binary.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
using namespace binary;
|
||||
|
||||
#if 0
|
||||
void read_xact(const char *& data, xact_t * xact)
|
||||
{
|
||||
read_number(data, xact->_date);
|
||||
read_number(data, xact->_date_eff);
|
||||
xact->account = accounts[read_long<account_t::ident_t>(data) - 1];
|
||||
|
||||
unsigned char flag = read_number<unsigned char>(data);
|
||||
if (flag == 0) {
|
||||
xact->amount.read(data);
|
||||
}
|
||||
else if (flag == 1) {
|
||||
xact->amount.read(data);
|
||||
xact->amount_expr = expr_t();
|
||||
xact->amount_expr->set_text(read_string(data));
|
||||
}
|
||||
else {
|
||||
xact->amount_expr = expr_t();
|
||||
xact->amount_expr->read(data);
|
||||
}
|
||||
|
||||
if (read_bool(data)) {
|
||||
xact->cost = amount_t();
|
||||
xact->cost->read(data);
|
||||
|
||||
xact->cost_expr = expr_t();
|
||||
xact->cost_expr->read(data);
|
||||
} else {
|
||||
xact->cost = none;
|
||||
}
|
||||
|
||||
read_number(data, xact->state);
|
||||
xact->set_flags(read_number<xact_t::flags_t>(data));
|
||||
xact->add_flags(XACT_BULK_ALLOC);
|
||||
read_string(data, xact->note);
|
||||
|
||||
// jww (2009-02-01): Use istream_pos_type
|
||||
xact->beg_pos = read_long<unsigned long>(data);
|
||||
read_long(data, xact->beg_line);
|
||||
xact->end_pos = read_long<unsigned long>(data);
|
||||
read_long(data, xact->end_line);
|
||||
|
||||
xact->data = NULL;
|
||||
|
||||
if (xact->amount_expr)
|
||||
expr_t::compute_amount(xact->amount_expr.get(), xact->amount, xact);
|
||||
}
|
||||
|
||||
void write_amount(std::ostream& out, amount_t& amt)
|
||||
{
|
||||
amt.write(out, ++bigints_index);
|
||||
bigints_count++;
|
||||
}
|
||||
|
||||
void write_xact(std::ostream& out, xact_t * xact,
|
||||
bool ignore_calculated)
|
||||
{
|
||||
write_number(out, xact->_date);
|
||||
write_number(out, xact->_date_eff);
|
||||
write_long(out, xact->account->ident);
|
||||
|
||||
if (ignore_calculated && xact->has_flags(XACT_CALCULATED)) {
|
||||
write_number<unsigned char>(out, 0);
|
||||
amount_t temp;
|
||||
write_amount(out, temp);
|
||||
}
|
||||
else if (xact->amount_expr) {
|
||||
write_number<unsigned char>(out, 2);
|
||||
// jww (2008-07-30): Um, is this right?
|
||||
xact->amount_expr->write(out);
|
||||
}
|
||||
else if (! xact->amount_expr->text().empty()) {
|
||||
write_number<unsigned char>(out, 1);
|
||||
write_amount(out, xact->amount);
|
||||
write_string(out, xact->amount_expr->text());
|
||||
}
|
||||
else {
|
||||
write_number<unsigned char>(out, 0);
|
||||
write_amount(out, xact->amount);
|
||||
}
|
||||
|
||||
if (xact->cost &&
|
||||
(! (ignore_calculated && xact->has_flags(XACT_CALCULATED)))) {
|
||||
write_bool(out, true);
|
||||
write_amount(out, *xact->cost);
|
||||
// jww (2008-07-30): What if there is no cost expression?
|
||||
xact->cost_expr->write(out);
|
||||
} else {
|
||||
write_bool(out, false);
|
||||
}
|
||||
|
||||
write_number(out, xact->state);
|
||||
write_number(out, xact->flags());
|
||||
write_string(out, xact->note);
|
||||
|
||||
write_long(out, xact->beg_pos);
|
||||
write_long(out, xact->beg_line);
|
||||
write_long(out, xact->end_pos);
|
||||
write_long(out, xact->end_line);
|
||||
}
|
||||
|
||||
void read_entry_base(const char *& data, entry_base_t * entry,
|
||||
xact_t *& xact_pool, bool& finalize)
|
||||
{
|
||||
read_long(data, entry->src_idx);
|
||||
// jww (2008-07-31): Use istream_pos_type
|
||||
entry->beg_pos = read_long<unsigned long>(data);
|
||||
read_long(data, entry->beg_line);
|
||||
entry->end_pos = read_long<unsigned long>(data);
|
||||
read_long(data, entry->end_line);
|
||||
|
||||
bool ignore_calculated = read_bool(data);
|
||||
|
||||
for (std::size_t i = 0, count = read_long<std::size_t>(data);
|
||||
i < count;
|
||||
i++) {
|
||||
new(xact_pool) xact_t;
|
||||
read_xact(data, xact_pool);
|
||||
if (ignore_calculated && xact_pool->has_flags(XACT_CALCULATED))
|
||||
finalize = true;
|
||||
entry->add_xact(xact_pool++);
|
||||
}
|
||||
}
|
||||
|
||||
void write_entry_base(std::ostream& out, entry_base_t * entry)
|
||||
{
|
||||
write_long(out, entry->src_idx);
|
||||
write_long(out, entry->beg_pos);
|
||||
write_long(out, entry->beg_line);
|
||||
write_long(out, entry->end_pos);
|
||||
write_long(out, entry->end_line);
|
||||
|
||||
bool ignore_calculated = false;
|
||||
foreach (transaction_t * xact, entry->xacts)
|
||||
if (xact->amount_expr) {
|
||||
ignore_calculated = true;
|
||||
break;
|
||||
}
|
||||
|
||||
write_bool(out, ignore_calculated);
|
||||
|
||||
write_long(out, entry->xacts.size());
|
||||
foreach (transaction_t * xact, entry->xacts)
|
||||
write_xact(out, xact, ignore_calculated);
|
||||
}
|
||||
|
||||
void read_entry(const char *& data, entry_t * entry,
|
||||
xact_t *& xact_pool, bool& finalize)
|
||||
{
|
||||
read_entry_base(data, entry, xact_pool, finalize);
|
||||
read_number(data, entry->_date);
|
||||
read_number(data, entry->_date_eff);
|
||||
read_string(data, entry->code);
|
||||
read_string(data, entry->payee);
|
||||
}
|
||||
|
||||
void write_entry(std::ostream& out, entry_t * entry)
|
||||
{
|
||||
write_entry_base(out, entry);
|
||||
write_number(out, entry->_date);
|
||||
write_number(out, entry->_date_eff);
|
||||
write_string(out, entry->code);
|
||||
write_string(out, entry->payee);
|
||||
}
|
||||
|
||||
void read_auto_entry(const char *& data, auto_entry_t * entry,
|
||||
xact_t *& xact_pool)
|
||||
{
|
||||
bool ignore;
|
||||
read_entry_base(data, entry, xact_pool, ignore);
|
||||
|
||||
expr_t expr;
|
||||
expr.read(data);
|
||||
entry->predicate = item_predicate<xact_t>(expr);
|
||||
}
|
||||
|
||||
void write_auto_entry(std::ostream& out, auto_entry_t * entry)
|
||||
{
|
||||
write_entry_base(out, entry);
|
||||
entry->predicate.predicate.write(out);
|
||||
}
|
||||
|
||||
void read_period_entry(const char *& data, period_entry_t * entry,
|
||||
xact_t *& xact_pool, bool& finalize)
|
||||
{
|
||||
read_entry_base(data, entry, xact_pool, finalize);
|
||||
read_string(data, &entry->period_string);
|
||||
std::istringstream stream(entry->period_string);
|
||||
entry->period.parse(stream);
|
||||
}
|
||||
|
||||
void write_period_entry(std::ostream& out, period_entry_t * entry)
|
||||
{
|
||||
write_entry_base(out, entry);
|
||||
write_string(out, entry->period_string);
|
||||
}
|
||||
|
||||
commodity_t::base_t * read_commodity_base(const char *& data)
|
||||
{
|
||||
string str;
|
||||
|
||||
read_string(data, str);
|
||||
|
||||
std::auto_ptr<commodity_t::base_t> commodity(new commodity_t::base_t(str));
|
||||
|
||||
read_string(data, str);
|
||||
if (! str.empty())
|
||||
commodity->name = str;
|
||||
|
||||
read_string(data, str);
|
||||
if (! str.empty())
|
||||
commodity->note = str;
|
||||
|
||||
read_number(data, commodity->precision);
|
||||
commodity_t::base_t::flags_t flags;
|
||||
read_number(data, flags);
|
||||
commodity->set_flags(flags);
|
||||
|
||||
return commodity.release();
|
||||
}
|
||||
|
||||
void write_commodity_base(std::ostream& out, commodity_t::base_t * commodity)
|
||||
{
|
||||
// jww (2008-04-22): Not using this anymore?
|
||||
//commodity->ident = ++base_commodity_index;
|
||||
|
||||
write_string(out, commodity->symbol);
|
||||
// jww (2008-04-22): What to do with optional members?
|
||||
write_string(out, *commodity->name);
|
||||
write_string(out, *commodity->note);
|
||||
write_number(out, commodity->precision);
|
||||
write_number(out, commodity->flags());
|
||||
}
|
||||
|
||||
void read_commodity_base_extra(const char *& data,
|
||||
commodity_t::ident_t ident)
|
||||
{
|
||||
commodity_t::base_t * commodity = base_commodities[ident];
|
||||
|
||||
bool read_history = false;
|
||||
// jww (2008-07-31): create a function read_size which does
|
||||
// read_long<std::size_t>. Don't use read_number<std::size_t>, but it
|
||||
// wastes too much space.
|
||||
for (std::size_t i = 0, count = read_long<std::size_t>(data);
|
||||
i < count;
|
||||
i++) {
|
||||
datetime_t when;
|
||||
read_number(data, when);
|
||||
amount_t amt;
|
||||
amt.read(data);
|
||||
|
||||
// Upon insertion, amt will be copied, which will cause the amount to be
|
||||
// duplicated (and thus not lost when the journal's item_pool is deleted).
|
||||
if (! commodity->history)
|
||||
commodity->history = commodity_t::history_t();
|
||||
commodity->history->prices.insert(commodity_t::history_t::value_type(when, amt));
|
||||
|
||||
read_history = true;
|
||||
}
|
||||
if (read_history)
|
||||
read_number(data, commodity->history->last_lookup);
|
||||
|
||||
if (read_bool(data)) {
|
||||
amount_t amt;
|
||||
amt.read(data);
|
||||
commodity->smaller = amount_t(amt);
|
||||
}
|
||||
|
||||
if (read_bool(data)) {
|
||||
amount_t amt;
|
||||
amt.read(data);
|
||||
commodity->larger = amount_t(amt);
|
||||
}
|
||||
}
|
||||
|
||||
void write_commodity_base_extra(std::ostream& out,
|
||||
commodity_t::base_t * commodity)
|
||||
{
|
||||
#if 0
|
||||
// jww (2008-04-22): What did bogus_time used to do?
|
||||
if (commodity->history && commodity->history->bogus_time)
|
||||
commodity->remove_price(commodity->history->bogus_time);
|
||||
#endif
|
||||
|
||||
if (! commodity->history) {
|
||||
write_long<std::size_t>(out, 0);
|
||||
} else {
|
||||
write_long<std::size_t>(out, commodity->history->prices.size());
|
||||
foreach (commodity_t::history_map::value_type& pair,
|
||||
commodity->history->prices) {
|
||||
write_number(out, pair.first);
|
||||
write_amount(out, pair.second);
|
||||
}
|
||||
write_number(out, commodity->history->last_lookup);
|
||||
}
|
||||
|
||||
if (commodity->smaller) {
|
||||
write_bool(out, true);
|
||||
write_amount(out, *commodity->smaller);
|
||||
} else {
|
||||
write_bool(out, false);
|
||||
}
|
||||
|
||||
if (commodity->larger) {
|
||||
write_bool(out, true);
|
||||
write_amount(out, *commodity->larger);
|
||||
} else {
|
||||
write_bool(out, false);
|
||||
}
|
||||
}
|
||||
|
||||
commodity_t * read_commodity(const char *& data)
|
||||
{
|
||||
commodity_t::base_t * base =
|
||||
base_commodities[read_long<commodity_t::ident_t>(data) - 1];
|
||||
|
||||
commodity_t * commodity =
|
||||
new commodity_t(amount_t::current_pool,
|
||||
shared_ptr<commodity_t::base_t>(base));
|
||||
|
||||
*commodities_next++ = commodity;
|
||||
|
||||
string str;
|
||||
read_string(data, str);
|
||||
if (! str.empty())
|
||||
commodity->qualified_symbol = str;
|
||||
commodity->annotated = false;
|
||||
|
||||
return commodity;
|
||||
}
|
||||
|
||||
void write_commodity(std::ostream& out, commodity_t * commodity)
|
||||
{
|
||||
commodity->ident = ++commodity_index;
|
||||
|
||||
// jww (2008-04-22): Is this used anymore?
|
||||
//write_long(out, commodity->base->ident);
|
||||
// jww (2008-04-22): Optional!
|
||||
write_string(out, *commodity->qualified_symbol);
|
||||
}
|
||||
|
||||
commodity_t * read_commodity_annotated(const char *& data)
|
||||
{
|
||||
commodity_t * commodity =
|
||||
commodities[read_long<commodity_t::ident_t>(data) - 1];
|
||||
|
||||
annotation_t details;
|
||||
|
||||
string str;
|
||||
read_string(data, str);
|
||||
|
||||
// This read-and-then-assign causes a new amount to be allocated which does
|
||||
// not live within the bulk allocation pool, since that pool will be deleted
|
||||
// *before* the commodities are destroyed.
|
||||
amount_t amt;
|
||||
amt.read(data);
|
||||
details.price = amt;
|
||||
|
||||
#if 0
|
||||
// jww (2008-04-22): These are optional members!
|
||||
read_number(data, details.date);
|
||||
read_string(data, details.tag);
|
||||
#endif
|
||||
|
||||
annotated_commodity_t * ann_comm =
|
||||
new annotated_commodity_t(commodity, details);
|
||||
*commodities_next++ = ann_comm;
|
||||
|
||||
if (! str.empty())
|
||||
ann_comm->qualified_symbol = str;
|
||||
|
||||
return ann_comm;
|
||||
}
|
||||
|
||||
void write_commodity_annotated(std::ostream& out,
|
||||
commodity_t * commodity)
|
||||
{
|
||||
commodity->ident = ++commodity_index;
|
||||
|
||||
// jww (2008-04-22): No longer needed?
|
||||
//write_long(out, commodity->base->ident);
|
||||
// jww (2008-04-22): Optional!
|
||||
write_string(out, *commodity->qualified_symbol);
|
||||
|
||||
annotated_commodity_t * ann_comm =
|
||||
static_cast<annotated_commodity_t *>(commodity);
|
||||
|
||||
// jww (2008-04-22): No longer needed?
|
||||
//write_long(out, ann_comm->base->ident);
|
||||
// jww (2008-04-22): Make a write_annotation_details function; and optional!
|
||||
if (ann_comm->details.price) {
|
||||
write_bool(out, true);
|
||||
write_amount(out, *ann_comm->details.price);
|
||||
} else {
|
||||
write_bool(out, false);
|
||||
}
|
||||
|
||||
if (ann_comm->details.date) {
|
||||
write_bool(out, true);
|
||||
ann_comm->details.date->write(out);
|
||||
} else {
|
||||
write_bool(out, false);
|
||||
}
|
||||
|
||||
if (ann_comm->details.tag) {
|
||||
write_bool(out, true);
|
||||
ann_comm->details.tag->write(out);
|
||||
} else {
|
||||
write_bool(out, false);
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
account_t * read_account(const char *& data, account_t * master = NULL)
|
||||
{
|
||||
account_t * acct = new account_t(NULL);
|
||||
|
||||
accounts[account_ident++] = acct;
|
||||
|
||||
account_t::ident_t id;
|
||||
read_long(data, id); // parent id
|
||||
if (id == 0xffffffff)
|
||||
acct->parent = NULL;
|
||||
else
|
||||
acct->parent = accounts[id - 1];
|
||||
|
||||
read_string(data, acct->name);
|
||||
read_string(data, acct->note);
|
||||
read_number(data, acct->depth);
|
||||
|
||||
// If all of the subaccounts will be added to a different master
|
||||
// account, throw away what we've learned about the recorded
|
||||
// journal's own master account.
|
||||
|
||||
if (master && acct != master) {
|
||||
checked_delete(acct);
|
||||
acct = master;
|
||||
}
|
||||
|
||||
for (std::size_t i = 0, count = read_long<std::size_t>(data);
|
||||
i < count;
|
||||
i++) {
|
||||
account_t * child = read_account(data);
|
||||
child->parent = acct;
|
||||
assert(acct != child);
|
||||
acct->add_account(child);
|
||||
}
|
||||
|
||||
return acct;
|
||||
}
|
||||
|
||||
namespace {
|
||||
inline account_t::ident_t count_accounts(account_t * account)
|
||||
{
|
||||
account_t::ident_t count = 1;
|
||||
|
||||
foreach (accounts_map::value_type& pair, account->accounts)
|
||||
count += count_accounts(pair.second);
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
void write_account(std::ostream& out, account_t * account)
|
||||
{
|
||||
account->ident = ++account_ident;
|
||||
|
||||
if (account->parent)
|
||||
write_long(out, account->parent->ident);
|
||||
else
|
||||
write_long<account_t::ident_t>(out, 0xffffffff);
|
||||
|
||||
write_string(out, account->name);
|
||||
write_string(out, account->note);
|
||||
write_number(out, account->depth);
|
||||
|
||||
write_number<std::size_t>(out, account->accounts.size());
|
||||
|
||||
foreach (accounts_map::value_type& pair, account->accounts)
|
||||
write_account(out, pair.second);
|
||||
}
|
||||
|
||||
std::size_t read_journal(std::istream& in,
|
||||
const path& file,
|
||||
journal_t& journal,
|
||||
account_t * master)
|
||||
{
|
||||
using namespace binary;
|
||||
|
||||
// Read in the files that participated in this journal, so that they
|
||||
// can be checked for changes on reading.
|
||||
|
||||
if (! file.empty()) {
|
||||
for (unsigned short i = 0, count = read_number<unsigned short>(in);
|
||||
i < count;
|
||||
i++) {
|
||||
path pathname = read_string(in);
|
||||
std::time_t old_mtime;
|
||||
read_number(in, old_mtime);
|
||||
struct stat info;
|
||||
// jww (2008-04-22): can this be done differently now?
|
||||
stat(pathname.string().c_str(), &info);
|
||||
if (std::difftime(info.st_mtime, old_mtime) > 0)
|
||||
return 0;
|
||||
|
||||
sources.push_back(pathname);
|
||||
}
|
||||
|
||||
// Make sure that the cache uses the same price database,
|
||||
// otherwise it means that LEDGER_PRICE_DB has been changed, and
|
||||
// we should ignore this cache file.
|
||||
if (read_bool(in)) {
|
||||
string pathname;
|
||||
read_string(in, pathname);
|
||||
if (! price_db ||
|
||||
price_db->string() != std::string(pathname))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// jww (2008-07-31): bind master to session.master
|
||||
|
||||
if (read_bool(data))
|
||||
basket = accounts[read_long<account_t::ident_t>(data) - 1];
|
||||
|
||||
// Read in the entries and xacts
|
||||
|
||||
for (std::size_t i = 0; i < count; i++) {
|
||||
new(entry_pool) entry_t;
|
||||
bool finalize = false;
|
||||
read_entry(data, entry_pool, xact_pool, finalize);
|
||||
entry_pool->journal = &journal;
|
||||
if (finalize && ! entry_pool->finalize())
|
||||
continue;
|
||||
entries.push_back(entry_pool++);
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < auto_count; i++) {
|
||||
auto_entry_t * auto_entry = new auto_entry_t;
|
||||
read_auto_entry(data, auto_entry, xact_pool);
|
||||
auto_entry->journal = &journal;
|
||||
auto_entries.push_back(auto_entry);
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < period_count; i++) {
|
||||
period_entry_t * period_entry = new period_entry_t;
|
||||
bool finalize = false;
|
||||
read_period_entry(data, period_entry, xact_pool, finalize);
|
||||
period_entry->journal = &journal;
|
||||
if (finalize && ! period_entry->finalize())
|
||||
continue;
|
||||
period_entries.push_back(period_entry);
|
||||
}
|
||||
|
||||
VERIFY(journal.valid());
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
std::pair<std::size_t, std::size_t>
|
||||
write_journal(std::ostream& out, const journal_t& journal)
|
||||
{
|
||||
using namespace binary;
|
||||
|
||||
// Write out the files that participated in this journal, so that
|
||||
// they can be checked for changes on reading.
|
||||
|
||||
if (sources.empty()) {
|
||||
write_number<unsigned short>(out, 0);
|
||||
} else {
|
||||
write_number<unsigned short>(out, sources.size());
|
||||
foreach (const path& path, sources) {
|
||||
write_string(out, path.string());
|
||||
struct stat info;
|
||||
stat(path.string().c_str(), &info);
|
||||
write_number(out, std::time_t(info.st_mtime));
|
||||
}
|
||||
|
||||
// Write out the price database that relates to this data file, so
|
||||
// that if it ever changes the cache can be invalidated.
|
||||
if (price_db) {
|
||||
write_bool(out, true);
|
||||
write_string(out, price_db->string());
|
||||
} else {
|
||||
write_bool(out, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Write out the basket accounts
|
||||
|
||||
if (basket) {
|
||||
write_bool(out, true);
|
||||
write_long(out, basket->ident);
|
||||
} else {
|
||||
write_bool(out, false);
|
||||
}
|
||||
|
||||
// Write out the entries and xacts
|
||||
|
||||
std::size_t this_entry_count = 0;
|
||||
std::size_t this_xact_count = 0;
|
||||
|
||||
foreach (entry_t * entry, entries) {
|
||||
write_entry(out, entry);
|
||||
|
||||
this_entry_count++;
|
||||
this_xact_count += entry->xacts.size();
|
||||
}
|
||||
|
||||
foreach (auto_entry_t * entry, auto_entries) {
|
||||
write_auto_entry(out, entry);
|
||||
|
||||
this_entry_count++;
|
||||
this_xact_count += entry->xacts.size();
|
||||
}
|
||||
|
||||
foreach (period_entry_t * entry, period_entries) {
|
||||
write_period_entry(out, entry);
|
||||
|
||||
this_entry_count++;
|
||||
this_xact_count += entry->xacts.size();
|
||||
}
|
||||
|
||||
return std::pair<std::size_t, std::size_t>(this_entry_count,
|
||||
this_xact_count);
|
||||
}
|
||||
|
||||
std::size_t read_session(std::istream& in,
|
||||
const path& file,
|
||||
session_t& session)
|
||||
{
|
||||
using namespace binary;
|
||||
|
||||
// Read all of the data in at once, so that we're just dealing with
|
||||
// a big data buffer.
|
||||
|
||||
std::size_t data_size = read_number<std::size_t>(in);
|
||||
|
||||
scoped_array<char> data_pool(new char[data_size]);
|
||||
|
||||
in.read(data_pool, data_size);
|
||||
|
||||
const char * data = data_pool.get();
|
||||
|
||||
// Read in the accounts
|
||||
|
||||
accounts.resize(read_number<std::size_t>(data));
|
||||
account_ident = 0;
|
||||
|
||||
if (session.master)
|
||||
checked_delete(session.master);
|
||||
session.master = read_account(data);
|
||||
|
||||
// Allocate the memory needed for the entries, xacts and bigints in one
|
||||
// large block, which is then chopped up and custom constructed as
|
||||
// necessary.
|
||||
|
||||
entry_count = read_number<std::size_t>(data);
|
||||
auto_entry_count = read_number<std::size_t>(data);
|
||||
period_entry_count = read_number<std::size_t>(data);
|
||||
xact_count = read_number<std::size_t>(data);
|
||||
bigints_count = read_number<std::size_t>(data);
|
||||
|
||||
#define ENTRIES_SIZE (sizeof(entry_t) * entry_count)
|
||||
#define XACTS_SIZE (sizeof(xact_t) * xact_count)
|
||||
#define BIGINTS_SIZE (amount_t::sizeof_bigint_t() * bigints_count)
|
||||
|
||||
#define ENTRIES_OFFSET 0
|
||||
#define XACTS_OFFSET ENTRIES_SIZE
|
||||
#define BIGINTS_OFFSET (ENTRIES_SIZE + XACTS_SIZE)
|
||||
|
||||
item_pool.reset(new char[ENTRIES_SIZE + XACTS_SIZE + BIGINTS_SIZE]);
|
||||
|
||||
entry_pool = reinterpret_cast<entry_t *>(item_pool.get() + ENTRIES_OFFSET);
|
||||
xact_pool = reinterpret_cast<xact_t *>(item_pool.get() + XACTS_OFFSET);
|
||||
bigints = item_pool.get() + BIGINTS_OFFSET;
|
||||
bigints_next = bigints;
|
||||
bigint_ident = 0;
|
||||
|
||||
#if 0
|
||||
// Read in the base commodities and the derived commodities
|
||||
|
||||
base_commodity_count = read_number<std::size_t>(data);
|
||||
base_commodities.resize(base_commodity_count);
|
||||
|
||||
for (std::size_t i = 0; i < base_commodity_count; i++) {
|
||||
commodity_t::base_t * base = read_commodity_base(data);
|
||||
session.commodity_pool->commodities.push_back(base);
|
||||
|
||||
std::pair<base_commodities_map::iterator, bool> result =
|
||||
commodity_base_t::commodities.insert
|
||||
(base_commodities_pair(commodity->symbol, commodity));
|
||||
if (! result.second) {
|
||||
base_commodities_map::iterator c =
|
||||
commodity_t::base_t::commodities.find(commodity->symbol);
|
||||
|
||||
// It's possible the user might have used a commodity in a value
|
||||
// expression passed to an option, we'll just override the flags, but
|
||||
// keep the commodity pointer intact.
|
||||
if (c == commodity_t::base_t::commodities.end())
|
||||
throw_(cache_error, "Failed to read base commodity from cache: "
|
||||
<< commodity->symbol);
|
||||
|
||||
(*c).second->name = commodity->name;
|
||||
(*c).second->note = commodity->note;
|
||||
(*c).second->precision = commodity->precision;
|
||||
(*c).second->flags = commodity->flags;
|
||||
|
||||
if ((*c).second->smaller)
|
||||
checked_delete((*c).second->smaller);
|
||||
(*c).second->smaller = commodity->smaller;
|
||||
if ((*c).second->larger)
|
||||
checked_delete((*c).second->larger);
|
||||
(*c).second->larger = commodity->larger;
|
||||
|
||||
*(base_commodities_next - 1) = (*c).second;
|
||||
|
||||
checked_delete(commodity);
|
||||
}
|
||||
}
|
||||
|
||||
commodity_count = read_number<std::size_t>(data);
|
||||
commodities.resize(commodity_count);
|
||||
|
||||
for (std::size_t i = 0; i < commodity_count; i++) {
|
||||
commodity_t * commodity;
|
||||
string mapping_key;
|
||||
|
||||
if (! read_bool(data)) {
|
||||
commodity = read_commodity(data);
|
||||
mapping_key = commodity->base->symbol;
|
||||
} else {
|
||||
read_string(data, mapping_key);
|
||||
commodity = read_commodity_annotated(data);
|
||||
}
|
||||
|
||||
session.commodity_pool->commodities.push_back(commodity);
|
||||
|
||||
if (! result.second) {
|
||||
commodities_map::iterator c =
|
||||
commodity_t::commodities.find(mapping_key);
|
||||
if (c == commodity_t::commodities.end())
|
||||
throw_(cache_error, "Failed to read commodity from cache: "
|
||||
<< commodity->symbol());
|
||||
|
||||
*(commodities_next - 1) = (*c).second;
|
||||
checked_delete(commodity);
|
||||
}
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < base_commodity_count; i++)
|
||||
read_commodity_base_extra(data, i);
|
||||
|
||||
commodity_t::ident_t ident = read_number<commodity_t::ident_t>(data);
|
||||
if (ident == 0xffffffff || ident == 0)
|
||||
session.commodity_pool->default_commodity = NULL;
|
||||
else
|
||||
session.commodity_pool->default_commodity = commodities[ident - 1];
|
||||
#endif
|
||||
|
||||
// Clean up and return the number of entries read
|
||||
|
||||
accounts.clear();
|
||||
commodities.clear();
|
||||
|
||||
VERIFY(session.valid());
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void write_session(std::ostream& out, session_t& session)
|
||||
{
|
||||
using namespace binary;
|
||||
|
||||
write_number_nocheck(out, binary_magic_number);
|
||||
write_number_nocheck(out, format_version);
|
||||
|
||||
// This number gets patched at the end of the function
|
||||
ostream_pos_type data_val = out.tellp();
|
||||
write_number<std::size_t>(out, 0);
|
||||
|
||||
// Write out the accounts
|
||||
|
||||
write_number<std::size_t>(out, count_accounts(session.master));
|
||||
write_account(out, session.master);
|
||||
|
||||
// Write out the number of entries, xacts, and amounts
|
||||
|
||||
write_number<std::size_t>(out, entries.size());
|
||||
write_number<std::size_t>(out, auto_entries.size());
|
||||
write_number<std::size_t>(out, period_entries.size());
|
||||
|
||||
// These two numbers get patched at the end of the function
|
||||
ostream_pos_type xacts_val = out.tellp();
|
||||
write_number<std::size_t>(out, 0);
|
||||
ostream_pos_type bigints_val = out.tellp();
|
||||
write_number<std::size_t>(out, 0);
|
||||
|
||||
bigint_ident = 0;
|
||||
|
||||
#if 0
|
||||
// Write out the commodities
|
||||
// jww (2008-04-22): This whole section needs to be reworked
|
||||
|
||||
write_number<std::size_t>(out, session.commodity_pool->commodities.size());
|
||||
write_number<std::size_t>(out, session.commodity_pool->commodities.size());
|
||||
|
||||
for (base_commodities_map::value_type pair, commodity_t::base_t::commodities)
|
||||
write_commodity_base(out, pair.second);
|
||||
|
||||
write_number<commodity_t::ident_t>
|
||||
(out, commodity_t::commodities.size());
|
||||
|
||||
for (commodities_map::value_type pair, commodity_t::commodities) {
|
||||
if (! pair.second->annotated) {
|
||||
write_bool(out, false);
|
||||
write_commodity(out, pair.second);
|
||||
}
|
||||
}
|
||||
|
||||
for (commodities_map::value_type pair, commodity_t::commodities) {
|
||||
if (pair.second->annotated) {
|
||||
write_bool(out, true);
|
||||
write_string(out, pair.first); // the mapping key
|
||||
write_commodity_annotated(out, pair.second);
|
||||
}
|
||||
}
|
||||
|
||||
// Write out the history and smaller/larger convertible links after
|
||||
// both the base and the main commodities have been written, since
|
||||
// the amounts in both will refer to the mains.
|
||||
|
||||
for (base_commodities_map::const_iterator i =
|
||||
commodity_t::base_t::commodities.begin();
|
||||
i != commodity_t::base_t::commodities.end();
|
||||
i++)
|
||||
write_commodity_base_extra(out, (*i).second);
|
||||
|
||||
if (commodity_t::default_commodity)
|
||||
write_number(out, commodity_t::default_commodity->ident);
|
||||
else
|
||||
write_number<commodity_t::ident_t>(out, 0xffffffff);
|
||||
#endif
|
||||
|
||||
// Back-patch several counts which were not known beforehand
|
||||
|
||||
out.seekp(data_val);
|
||||
write_number<std::size_t>(out, (static_cast<std::size_t>(out.tellp()) -
|
||||
static_cast<std::size_t>(data_val) -
|
||||
sizeof(std::size_t)));
|
||||
out.seekp(xacts_val);
|
||||
write_number<std::size_t>(out, xact_count);
|
||||
out.seekp(bigints_val);
|
||||
write_number<std::size_t>(out, bigints_count);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace ledger
|
||||
161
src/cache.h
161
src/cache.h
|
|
@ -1,161 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2009, John Wiegley. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of New Artisans LLC nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup parse
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file cache.h
|
||||
* @author John Wiegley
|
||||
*
|
||||
* @ingroup parse
|
||||
*
|
||||
* @brief Brief
|
||||
*
|
||||
* Long.
|
||||
*/
|
||||
#ifndef CACHE_H
|
||||
#define CACHE_H
|
||||
|
||||
#include "utils.h"
|
||||
#include "session.h"
|
||||
#include "journal.h"
|
||||
#include "account.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
DECLARE_EXCEPTION(cache_error, std::runtime_error);
|
||||
|
||||
/**
|
||||
* @brief Brief
|
||||
*
|
||||
* Long.
|
||||
*/
|
||||
class binary_cache_t
|
||||
{
|
||||
static const unsigned long binary_magic_number = 0xFFEED765;
|
||||
#if defined(DEBUG_ON)
|
||||
static const unsigned long format_version = 0x00030001;
|
||||
#else
|
||||
static const unsigned long format_version = 0x00030000;
|
||||
#endif
|
||||
|
||||
scoped_array<char> item_pool;
|
||||
|
||||
std::vector<account_t *> accounts;
|
||||
account_t::ident_t account_ident;
|
||||
|
||||
entry_t * entry_pool; // points into item_pool
|
||||
std::size_t entry_count;
|
||||
std::size_t auto_entry_count;
|
||||
std::size_t period_entry_count;
|
||||
|
||||
xact_t * xact_pool; // points into item_pool
|
||||
std::size_t xact_count;
|
||||
|
||||
#if 0
|
||||
commodity_base_t ** base_commodities; // allocated
|
||||
commodity_base_t ** base_commodities_next;
|
||||
uint_fast32_t base_commodity_index;
|
||||
std::size_t base_commodity_count;
|
||||
#endif
|
||||
|
||||
commodity_t ** commodities; // allocated
|
||||
commodity_t ** commodities_next;
|
||||
uint_fast32_t commodity_ident;
|
||||
std::size_t commodity_count;
|
||||
|
||||
char * bigints; // points into item_pool
|
||||
char * bigints_next;
|
||||
uint_fast32_t bigints_index;
|
||||
std::size_t bigints_count;
|
||||
|
||||
void read_xact(const char *& data, xact_t * xact);
|
||||
void write_xact(std::ostream& out, xact_t * xact,
|
||||
bool ignore_calculated);
|
||||
|
||||
void read_entry_base(const char *& data, entry_base_t * entry,
|
||||
xact_t *& xact_pool, bool& finalize);
|
||||
void write_entry_base(std::ostream& out, entry_base_t * entry);
|
||||
void read_entry(const char *& data, entry_t * entry,
|
||||
xact_t *& xact_pool, bool& finalize);
|
||||
void write_entry(std::ostream& out, entry_t * entry);
|
||||
void read_auto_entry(const char *& data, auto_entry_t * entry,
|
||||
xact_t *& xact_pool);
|
||||
void write_auto_entry(std::ostream& out, auto_entry_t * entry);
|
||||
void read_period_entry(const char *& data, period_entry_t * entry,
|
||||
xact_t *& xact_pool, bool& finalize);
|
||||
void write_period_entry(std::ostream& out, period_entry_t * entry);
|
||||
|
||||
#if 0
|
||||
commodity_t::base_t * read_commodity_base(const char *& data);
|
||||
void write_commodity_base(std::ostream& out, commodity_t::base_t * commodity);
|
||||
void read_commodity_base_extra(const char *& data,
|
||||
commodity_t::ident_t ident);
|
||||
void write_commodity_base_extra(std::ostream& out,
|
||||
commodity_t::base_t * commodity);
|
||||
#endif
|
||||
|
||||
commodity_t * read_commodity(const char *& data);
|
||||
void write_commodity(std::ostream& out, commodity_t * commodity);
|
||||
commodity_t * read_commodity_annotated(const char *& data);
|
||||
void write_commodity_annotated(std::ostream& out,
|
||||
commodity_t * commodity);
|
||||
|
||||
account_t * read_account(const char *& data, account_t * master = NULL);
|
||||
void write_account(std::ostream& out);
|
||||
|
||||
std::size_t read_journal(std::istream& in,
|
||||
const path& file,
|
||||
journal_t& journal,
|
||||
account_t * master);
|
||||
void write_journal(std::ostream& out,
|
||||
const journal_t& journal);
|
||||
|
||||
public:
|
||||
binary_cache_t()
|
||||
: account_ident(0),
|
||||
#if 0
|
||||
base_commodity_ident(0),
|
||||
#endif
|
||||
commodity_ident(0)
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t read_session(std::istream& in, const path& file);
|
||||
void write_session(std::ostream& out, session_t& session);
|
||||
|
||||
};
|
||||
|
||||
} // namespace ledger
|
||||
|
||||
#endif // CACHE_H
|
||||
|
|
@ -763,33 +763,6 @@ void annotated_commodity_t::write_annotations(std::ostream& out,
|
|||
out << " (" << *info.tag << ')';
|
||||
}
|
||||
|
||||
void commodity_t::read_xml(std::istream& in)
|
||||
{
|
||||
}
|
||||
|
||||
void commodity_t::write_xml(std::ostream& out, const int depth) const
|
||||
{
|
||||
out << xml_str("<commodity flags=\"", depth);
|
||||
if (! (flags() & COMMODITY_STYLE_SUFFIXED)) out << 'P';
|
||||
if (flags() & COMMODITY_STYLE_SEPARATED) out << 'S';
|
||||
if (flags() & COMMODITY_STYLE_THOUSANDS) out << 'T';
|
||||
if (flags() & COMMODITY_STYLE_EUROPEAN) out << 'E';
|
||||
out << "\">\n";
|
||||
|
||||
out << xml_str("<symbol>", depth + 1) << symbol() << "</symbol>\n";
|
||||
|
||||
#if 0
|
||||
// jww (2009-02-01): If this is an annotated commodity, more has to happen
|
||||
if (price) {
|
||||
out << xml_str("<price>", depth + 1);
|
||||
price->write_xml(out, depth + 2);
|
||||
out << xml_str("</price>\n", depth + 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
out << xml_str("</commodity>\n", depth);
|
||||
}
|
||||
|
||||
bool compare_amount_commodities::operator()(const amount_t * left,
|
||||
const amount_t * right) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -364,13 +364,6 @@ public:
|
|||
out << symbol();
|
||||
}
|
||||
|
||||
void read(std::istream& in);
|
||||
void read(char *& data);
|
||||
void write(std::ostream& out) const;
|
||||
|
||||
void read_xml(std::istream& in);
|
||||
void write_xml(std::ostream& out, const int depth = 0) const;
|
||||
|
||||
bool valid() const;
|
||||
};
|
||||
|
||||
|
|
|
|||
10
src/expr.cc
10
src/expr.cc
|
|
@ -182,16 +182,6 @@ void expr_t::dump(std::ostream& out) const
|
|||
if (ptr) ptr->dump(out, 0);
|
||||
}
|
||||
|
||||
void expr_t::read(const char *& data)
|
||||
{
|
||||
if (ptr) ptr->read(data);
|
||||
}
|
||||
|
||||
void expr_t::write(std::ostream& out) const
|
||||
{
|
||||
if (ptr) ptr->write(out);
|
||||
}
|
||||
|
||||
void expr_t::initialize()
|
||||
{
|
||||
parser.reset(new expr_t::parser_t);
|
||||
|
|
|
|||
|
|
@ -145,8 +145,6 @@ public:
|
|||
|
||||
void print(std::ostream& out) const;
|
||||
void dump(std::ostream& out) const;
|
||||
void read(const char *& data);
|
||||
void write(std::ostream& out) const;
|
||||
|
||||
static value_t eval(const string& _expr, scope_t& scope);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -81,13 +81,8 @@
|
|||
#include <compare.h>
|
||||
|
||||
#include <textual.h>
|
||||
#include <cache.h>
|
||||
#include <xml.h>
|
||||
#include <csv.h>
|
||||
#include <emacs.h>
|
||||
#include <qif.h>
|
||||
#include <gnucash.h>
|
||||
#include <ofx.h>
|
||||
|
||||
#include <session.h>
|
||||
#include <report.h>
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@ int main(int argc, char * argv[], char * envp[])
|
|||
// Create the session object, which maintains nearly all state relating to
|
||||
// this invocation of Ledger; and register all known journal parsers.
|
||||
session = new LEDGER_SESSION_T;
|
||||
register_journal_parsers(*session);
|
||||
set_session_context(session);
|
||||
|
||||
// Create the report object, which maintains state relating to each
|
||||
|
|
|
|||
11
src/mask.cc
11
src/mask.cc
|
|
@ -30,7 +30,6 @@
|
|||
*/
|
||||
|
||||
#include "mask.h"
|
||||
#include "binary.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
|
|
@ -46,14 +45,4 @@ mask_t& mask_t::operator=(const string& pat)
|
|||
return *this;
|
||||
}
|
||||
|
||||
void mask_t::read(const char *& data)
|
||||
{
|
||||
*this = binary::read_string(data);
|
||||
}
|
||||
|
||||
void mask_t::write(std::ostream& out) const
|
||||
{
|
||||
binary::write_string(out, expr.str());
|
||||
}
|
||||
|
||||
} // namespace ledger
|
||||
|
|
|
|||
|
|
@ -83,9 +83,6 @@ public:
|
|||
bool empty() const {
|
||||
return expr.empty();
|
||||
}
|
||||
|
||||
void read(const char *& data);
|
||||
void write(std::ostream& out) const;
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const mask_t& mask) {
|
||||
|
|
|
|||
76
src/op.cc
76
src/op.cc
|
|
@ -31,7 +31,6 @@
|
|||
|
||||
#include "op.h"
|
||||
#include "scope.h"
|
||||
#include "binary.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
|
|
@ -501,81 +500,6 @@ void expr_t::op_t::dump(std::ostream& out, const int depth) const
|
|||
}
|
||||
}
|
||||
|
||||
void expr_t::op_t::read(const char *& data)
|
||||
{
|
||||
kind = binary::read_long<kind_t>(data);
|
||||
|
||||
if (kind > TERMINALS) {
|
||||
set_left(new expr_t::op_t());
|
||||
left()->read(data);
|
||||
|
||||
if (kind > UNARY_OPERATORS && binary::read_bool(data)) {
|
||||
set_right(new expr_t::op_t());
|
||||
right()->read(data);
|
||||
}
|
||||
}
|
||||
|
||||
switch (kind) {
|
||||
case VALUE: {
|
||||
value_t temp;
|
||||
temp.read(data);
|
||||
set_value(temp);
|
||||
break;
|
||||
}
|
||||
case IDENT: {
|
||||
string temp;
|
||||
binary::read_string(data, temp);
|
||||
set_ident(temp);
|
||||
break;
|
||||
}
|
||||
case INDEX: {
|
||||
long temp;
|
||||
binary::read_long(data, temp);
|
||||
set_index(temp);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void expr_t::op_t::write(std::ostream& out) const
|
||||
{
|
||||
binary::write_long<kind_t>(out, kind);
|
||||
|
||||
if (kind > TERMINALS) {
|
||||
left()->write(out);
|
||||
|
||||
if (kind > UNARY_OPERATORS) {
|
||||
if (has_right()) {
|
||||
binary::write_bool(out, true);
|
||||
right()->write(out);
|
||||
} else {
|
||||
binary::write_bool(out, false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (kind) {
|
||||
case VALUE:
|
||||
as_value().write(out);
|
||||
break;
|
||||
case IDENT:
|
||||
binary::write_string(out, as_ident());
|
||||
break;
|
||||
case INDEX:
|
||||
binary::write_long(out, as_index());
|
||||
break;
|
||||
|
||||
case FUNCTION:
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string op_context(const expr_t::ptr_op_t op, const expr_t::ptr_op_t goal)
|
||||
{
|
||||
ostream_pos_type start_pos, end_pos;
|
||||
|
|
|
|||
3
src/op.h
3
src/op.h
|
|
@ -301,9 +301,6 @@ public:
|
|||
bool print(std::ostream& out, const context_t& context = context_t()) const;
|
||||
void dump(std::ostream& out, const int depth) const;
|
||||
|
||||
void read(const char *& data);
|
||||
void write(std::ostream& out) const;
|
||||
|
||||
static ptr_op_t wrap_value(const value_t& val);
|
||||
static ptr_op_t wrap_functor(const function_t& fobj);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -66,9 +66,6 @@ value_t parse_command(call_scope_t& args)
|
|||
result.print(out);
|
||||
out << std::endl;
|
||||
|
||||
out << std::endl << "--- Calculated value as XML ---" << std::endl;
|
||||
result.write_xml(out);
|
||||
|
||||
return 0L;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "handler.h"
|
||||
#include "iterators.h"
|
||||
#include "filters.h"
|
||||
#include "textual.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
|
|
@ -129,6 +130,8 @@ session_t::session_t()
|
|||
init_file = home ? *home / ".ledgerrc" : "./.ledgerrc";
|
||||
price_db = home ? *home / ".pricedb" : "./.pricedb";
|
||||
cache_file = home ? *home / ".ledger-cache" : "./.ledger-cache";
|
||||
|
||||
register_parser(new textual_parser_t);
|
||||
}
|
||||
|
||||
session_t::~session_t()
|
||||
|
|
|
|||
|
|
@ -138,13 +138,6 @@ typedef std::ostream::pos_type ostream_pos_type;
|
|||
#include <mpfr.h>
|
||||
#include "sha1.h"
|
||||
|
||||
#include "irrXML.h" // XML parser
|
||||
#include "CXMLReaderImpl.h"
|
||||
|
||||
#if defined(HAVE_LIBOFX)
|
||||
#include <libofx.h>
|
||||
#endif
|
||||
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/any.hpp>
|
||||
|
|
|
|||
36
src/utils.h
36
src/utils.h
|
|
@ -536,42 +536,6 @@ inline char peek_next_nonws(std::istream& in) {
|
|||
return c;
|
||||
}
|
||||
|
||||
inline void xml_space(std::ostream& out, const int depth = 0) {
|
||||
for (int i = 0; i < depth; i++)
|
||||
out << " ";
|
||||
}
|
||||
|
||||
inline void xml_print(std::ostream& out,
|
||||
const string& str,
|
||||
const int depth = 0) {
|
||||
xml_space(out, depth);
|
||||
out << str;
|
||||
}
|
||||
|
||||
struct xml_str
|
||||
{
|
||||
const string& str;
|
||||
const std::size_t depth;
|
||||
|
||||
xml_str(const string& _str, const std::size_t _depth)
|
||||
: str(_str), depth(_depth) {
|
||||
TRACE_CTOR(xml_str, "const string&, const std::size_t");
|
||||
}
|
||||
xml_str(const xml_str& other)
|
||||
: str(other.str), depth(other.depth) {
|
||||
TRACE_CTOR(xml_str, "copy");
|
||||
}
|
||||
~xml_str() throw() {
|
||||
TRACE_DTOR(xml_str);
|
||||
}
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const xml_str& obj) {
|
||||
xml_space(out, obj.depth);
|
||||
out << obj.str;
|
||||
return out;
|
||||
}
|
||||
|
||||
#define READ_INTO(str, targ, size, var, cond) { \
|
||||
char * _p = targ; \
|
||||
var = str.peek(); \
|
||||
|
|
|
|||
146
src/value.cc
146
src/value.cc
|
|
@ -30,7 +30,6 @@
|
|||
*/
|
||||
|
||||
#include "value.h"
|
||||
#include "binary.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
|
|
@ -1767,151 +1766,6 @@ void value_t::print(std::ostream& out, const bool relaxed) const
|
|||
}
|
||||
}
|
||||
|
||||
void value_t::read(std::istream& in)
|
||||
{
|
||||
switch (static_cast<value_t::type_t>(binary::read_long<int>(in))) {
|
||||
case BOOLEAN:
|
||||
set_boolean(binary::read_bool(in));
|
||||
break;
|
||||
case INTEGER:
|
||||
set_long(binary::read_long<long>(in));
|
||||
break;
|
||||
case DATETIME:
|
||||
set_datetime(parse_datetime(binary::read_string(in)));
|
||||
break;
|
||||
case DATE:
|
||||
set_date(parse_date(binary::read_string(in)));
|
||||
break;
|
||||
case AMOUNT: {
|
||||
amount_t temp;
|
||||
temp.read(in);
|
||||
set_amount(temp);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
throw_(value_error, "Cannot read " << label() << " from a stream");
|
||||
}
|
||||
|
||||
void value_t::read(const char *& data)
|
||||
{
|
||||
switch (static_cast<value_t::type_t>(binary::read_long<int>(data))) {
|
||||
case BOOLEAN:
|
||||
set_boolean(binary::read_bool(data));
|
||||
break;
|
||||
case INTEGER:
|
||||
set_long(binary::read_long<long>(data));
|
||||
break;
|
||||
case DATETIME:
|
||||
set_datetime(parse_datetime(binary::read_string(data)));
|
||||
break;
|
||||
case DATE:
|
||||
set_date(parse_date(binary::read_string(data)));
|
||||
break;
|
||||
case AMOUNT: {
|
||||
amount_t temp;
|
||||
temp.read(data);
|
||||
set_amount(temp);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
throw_(value_error, "Cannot read " << label() << " from a stream");
|
||||
}
|
||||
|
||||
void value_t::write(std::ostream& out) const
|
||||
{
|
||||
binary::write_long(out, static_cast<int>(type()));
|
||||
|
||||
switch (type()) {
|
||||
case BOOLEAN:
|
||||
binary::write_bool(out, as_boolean());
|
||||
break;
|
||||
case INTEGER:
|
||||
binary::write_long(out, as_long());
|
||||
break;
|
||||
case DATETIME:
|
||||
binary::write_string(out, format_datetime(as_datetime()));
|
||||
break;
|
||||
case DATE:
|
||||
binary::write_string(out, format_date(as_date()));
|
||||
break;
|
||||
case AMOUNT:
|
||||
as_amount().write(out);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
throw_(value_error, "Cannot write " << label() << " to a stream");
|
||||
}
|
||||
|
||||
void value_t::write_xml(std::ostream& out, const int depth) const
|
||||
{
|
||||
out << xml_str("<value>\n", depth);
|
||||
|
||||
switch (type()) {
|
||||
case VOID:
|
||||
out << xml_str("<void />\n", depth + 1);
|
||||
break;
|
||||
case BOOLEAN:
|
||||
out << xml_str("<bool>", depth + 1)
|
||||
<< (as_boolean() ? "true" : "false")
|
||||
<< "</bool>\n";
|
||||
break;
|
||||
case DATETIME:
|
||||
out << xml_str("<datetime>", depth + 1)
|
||||
<< format_datetime(as_datetime())
|
||||
<< "</datetime>\n";
|
||||
break;
|
||||
case DATE:
|
||||
out << xml_str("<date>", depth + 1)
|
||||
<< format_date(as_date())
|
||||
<< "</date>\n";
|
||||
break;
|
||||
case INTEGER:
|
||||
out << xml_str("<integer>", depth + 1)
|
||||
<< as_long()
|
||||
<< "</integer>\n";
|
||||
break;
|
||||
case AMOUNT:
|
||||
as_amount().write_xml(out, depth + 1);
|
||||
break;
|
||||
case BALANCE:
|
||||
as_balance().write_xml(out, depth + 1);
|
||||
break;
|
||||
case BALANCE_PAIR:
|
||||
as_balance_pair().write_xml(out, depth + 1);
|
||||
break;
|
||||
case STRING:
|
||||
out << xml_str("<string>", depth + 1)
|
||||
<< as_string()
|
||||
<< "</string>\n";
|
||||
break;
|
||||
case MASK:
|
||||
out << xml_str("<mask>", depth + 1)
|
||||
<< as_mask()
|
||||
<< "</mask>\n";
|
||||
break;
|
||||
case SEQUENCE:
|
||||
out << xml_str("<sequence>\n", depth + 1);
|
||||
foreach (const value_t& v, as_sequence())
|
||||
v.write_xml(out, depth + 2);
|
||||
out << xml_str("</sequence>\n", depth + 1);
|
||||
break;
|
||||
case POINTER:
|
||||
default:
|
||||
throw_(value_error, "Cannot output " << label() << " as XML");
|
||||
break;
|
||||
}
|
||||
|
||||
out << xml_str("</value>\n", depth);
|
||||
}
|
||||
|
||||
bool value_t::valid() const
|
||||
{
|
||||
switch (type()) {
|
||||
|
|
|
|||
18
src/value.h
18
src/value.h
|
|
@ -929,24 +929,6 @@ public:
|
|||
const int latter_width = -1) const;
|
||||
void print(std::ostream& out, const bool relaxed = true) const;
|
||||
|
||||
/**
|
||||
* Serialization methods. A value may be deserialized from an input
|
||||
* stream or a character pointer, and it may be serialized to an
|
||||
* output stream. The methods used are:
|
||||
*/
|
||||
void read(std::istream& in);
|
||||
void read(const char *& data);
|
||||
void write(std::ostream& out) const;
|
||||
|
||||
/** @name XML Serialization
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
void read_xml(std::istream& in);
|
||||
void write_xml(std::ostream& out, const int depth = 0) const;
|
||||
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* Debugging methods.
|
||||
*/
|
||||
|
|
|
|||
14
src/work.cc
14
src/work.cc
|
|
@ -74,20 +74,6 @@ void handle_debug_options(int argc, char * argv[])
|
|||
}
|
||||
}
|
||||
|
||||
void register_journal_parsers(session_t& session)
|
||||
{
|
||||
#if 0
|
||||
session.register_parser(new journal_t::binary_parser_t);
|
||||
#endif
|
||||
session.register_parser(new xml_parser_t);
|
||||
session.register_parser(new gnucash_parser_t);
|
||||
#ifdef HAVE_LIBOFX
|
||||
session.register_parser(new ofx_parser_t);
|
||||
#endif
|
||||
session.register_parser(new qif_parser_t);
|
||||
session.register_parser(new textual_parser_t);
|
||||
}
|
||||
|
||||
void read_environment_settings(report_t& report, char * envp[])
|
||||
{
|
||||
TRACE_START(environment, 1, "Processed environment variables");
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ typedef strings_list::iterator string_iterator;
|
|||
typedef std::pair<string_iterator, string_iterator> string_iterator_pair;
|
||||
|
||||
void handle_debug_options(int argc, char * argv[]);
|
||||
void register_journal_parsers(session_t& session);
|
||||
void read_environment_settings(report_t& report, char * envp[]);
|
||||
strings_list read_command_line_arguments(report_t& report,
|
||||
int argc, char * argv[]);
|
||||
|
|
|
|||
512
src/xml.cc
512
src/xml.cc
|
|
@ -1,512 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2009, John Wiegley. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of New Artisans LLC nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "xml.h"
|
||||
#include "journal.h"
|
||||
#include "utils.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
static irr::io::IrrXMLReader * current_parser;
|
||||
static std::size_t count;
|
||||
|
||||
static journal_t * curr_journal;
|
||||
static entry_t * curr_entry;
|
||||
static commodity_t * curr_comm;
|
||||
static string comm_flags;
|
||||
|
||||
static xact_t::state_t curr_state;
|
||||
|
||||
static string data;
|
||||
static bool ignore;
|
||||
static string have_error;
|
||||
|
||||
static void startElement(const char *name)
|
||||
{
|
||||
if (ignore)
|
||||
return;
|
||||
|
||||
if (std::strcmp(name, "entry") == 0) {
|
||||
assert(! curr_entry);
|
||||
curr_entry = new entry_t;
|
||||
curr_state = xact_t::UNCLEARED;
|
||||
}
|
||||
else if (std::strcmp(name, "xact") == 0) {
|
||||
assert(curr_entry);
|
||||
curr_entry->add_xact(new xact_t);
|
||||
if (curr_state != item_t::UNCLEARED)
|
||||
curr_entry->xacts.back()->set_state(curr_state);
|
||||
}
|
||||
else if (std::strcmp(name, "commodity") == 0) {
|
||||
if (const char * p = current_parser->getAttributeValue("flags"))
|
||||
comm_flags = p;
|
||||
}
|
||||
else if (std::strcmp(name, "total") == 0) {
|
||||
ignore = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void endElement(const char *name)
|
||||
{
|
||||
if (ignore) {
|
||||
if (std::strcmp(name, "total") == 0)
|
||||
ignore = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (std::strcmp(name, "entry") == 0) {
|
||||
assert(curr_entry);
|
||||
if (curr_journal->add_entry(curr_entry)) {
|
||||
count++;
|
||||
} else {
|
||||
account_t * acct = curr_journal->find_account("<Unknown>");
|
||||
curr_entry->add_xact(new xact_t(acct));
|
||||
if (curr_journal->add_entry(curr_entry)) {
|
||||
count++;
|
||||
} else {
|
||||
checked_delete(curr_entry);
|
||||
have_error = "Entry cannot be balanced";
|
||||
}
|
||||
}
|
||||
curr_entry = NULL;
|
||||
}
|
||||
else if (std::strcmp(name, "en:date") == 0) {
|
||||
curr_entry->_date = parse_date(data);
|
||||
}
|
||||
else if (std::strcmp(name, "en:date_eff") == 0) {
|
||||
curr_entry->_date_eff = parse_date(data);
|
||||
}
|
||||
else if (std::strcmp(name, "en:code") == 0) {
|
||||
curr_entry->code = data;
|
||||
}
|
||||
else if (std::strcmp(name, "en:cleared") == 0) {
|
||||
curr_state = xact_t::CLEARED;
|
||||
}
|
||||
else if (std::strcmp(name, "en:pending") == 0) {
|
||||
curr_state = xact_t::PENDING;
|
||||
}
|
||||
else if (std::strcmp(name, "en:payee") == 0) {
|
||||
curr_entry->payee = data;
|
||||
}
|
||||
else if (std::strcmp(name, "tr:account") == 0) {
|
||||
curr_entry->xacts.back()->account = curr_journal->find_account(data);
|
||||
}
|
||||
else if (std::strcmp(name, "tr:cleared") == 0) {
|
||||
curr_entry->xacts.back()->set_state(item_t::CLEARED);
|
||||
}
|
||||
else if (std::strcmp(name, "tr:pending") == 0) {
|
||||
curr_entry->xacts.back()->set_state(item_t::PENDING);
|
||||
}
|
||||
else if (std::strcmp(name, "tr:virtual") == 0) {
|
||||
curr_entry->xacts.back()->add_flags(XACT_VIRTUAL);
|
||||
}
|
||||
else if (std::strcmp(name, "tr:generated") == 0) {
|
||||
curr_entry->xacts.back()->add_flags(XACT_AUTO);
|
||||
}
|
||||
else if (std::strcmp(name, "symbol") == 0) {
|
||||
assert(! curr_comm);
|
||||
curr_comm = amount_t::current_pool->find_or_create(data);
|
||||
assert(curr_comm);
|
||||
curr_comm->add_flags(COMMODITY_STYLE_SUFFIXED);
|
||||
if (! comm_flags.empty()) {
|
||||
for (string::size_type i = 0, l = comm_flags.length(); i < l; i++) {
|
||||
switch (comm_flags[i]) {
|
||||
case 'P': curr_comm->drop_flags(COMMODITY_STYLE_SUFFIXED); break;
|
||||
case 'S': curr_comm->add_flags(COMMODITY_STYLE_SEPARATED); break;
|
||||
case 'T': curr_comm->add_flags(COMMODITY_STYLE_THOUSANDS); break;
|
||||
case 'E': curr_comm->add_flags(COMMODITY_STYLE_EUROPEAN); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
// jww (2006-03-02): !!!
|
||||
else if (std::strcmp(name, "price") == 0) {
|
||||
assert(curr_comm);
|
||||
amount_t * price = new amount_t(data);
|
||||
std::ostringstream symstr;
|
||||
symstr << curr_comm->symbol << " {" << *price << "}";
|
||||
commodity_t * priced_comm =
|
||||
commodity_t::find_commodity(symstr.str(), true);
|
||||
priced_comm->price = price;
|
||||
priced_comm->base = curr_comm;
|
||||
curr_comm = priced_comm;
|
||||
}
|
||||
#endif
|
||||
else if (std::strcmp(name, "quantity") == 0) {
|
||||
curr_entry->xacts.back()->amount.parse(data);
|
||||
if (curr_comm) {
|
||||
string::size_type i = data.find('.');
|
||||
if (i != string::npos) {
|
||||
int precision = data.length() - i - 1;
|
||||
if (precision > curr_comm->precision())
|
||||
curr_comm->set_precision(precision);
|
||||
}
|
||||
curr_entry->xacts.back()->amount.set_commodity(*curr_comm);
|
||||
curr_comm = NULL;
|
||||
}
|
||||
}
|
||||
else if (std::strcmp(name, "tr:amount") == 0) {
|
||||
curr_comm = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool xml_parser_t::test(std::istream& in) const
|
||||
{
|
||||
char buf[80];
|
||||
char * p;
|
||||
|
||||
DEBUG("xml.parse", "Testing whether the file is XML...");
|
||||
|
||||
in.read(buf, 10);
|
||||
if (utf8::is_bom(buf))
|
||||
p = &buf[3];
|
||||
else
|
||||
p = buf;
|
||||
|
||||
if (std::strncmp(p, "<?xml", 5) != 0) {
|
||||
in.clear();
|
||||
in.seekg(0, std::ios::beg);
|
||||
DEBUG("xml.parse", "Does not begin with <?xml");
|
||||
return false;
|
||||
}
|
||||
|
||||
in.getline(buf, 79); // skip rest of <?xml line
|
||||
in.getline(buf, 79);
|
||||
if (! std::strstr(buf, "<ledger")) {
|
||||
in.clear();
|
||||
in.seekg(0, std::ios::beg);
|
||||
DEBUG("xml.parse", "Next line does not begin with <ledger");
|
||||
return false;
|
||||
}
|
||||
|
||||
in.clear();
|
||||
in.seekg(0, std::ios::beg);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::size_t xml_parser_t::parse(std::istream& in,
|
||||
session_t& session,
|
||||
journal_t& journal,
|
||||
account_t * master,
|
||||
const path * original_file)
|
||||
{
|
||||
TRACE_START(xml_parsing_total, 1, "Total time spent parsing XML:");
|
||||
|
||||
char buf[BUFSIZ];
|
||||
|
||||
count = 0;
|
||||
curr_journal = &journal;
|
||||
curr_entry = NULL;
|
||||
curr_comm = NULL;
|
||||
ignore = false;
|
||||
|
||||
irr::io::IrrXMLReader * parser =
|
||||
new irr::io::CXMLReaderImpl<char, irr::io::IXMLBase>(new CStreamReadCallBack(in));
|
||||
current_parser = parser;
|
||||
|
||||
while (parser->read()) {
|
||||
switch (parser->getNodeType()) {
|
||||
case irr::io::EXN_TEXT:
|
||||
DEBUG("xml.parse", "Read text: " << parser->getNodeData());
|
||||
if (! ignore) {
|
||||
DEBUG("xml.parse", " but ignoring it");
|
||||
data = parser->getNodeData();
|
||||
}
|
||||
break;
|
||||
|
||||
case irr::io::EXN_ELEMENT:
|
||||
DEBUG("xml.parse", "Read element: " << parser->getNodeName());
|
||||
startElement(parser->getNodeName());
|
||||
break;
|
||||
case irr::io::EXN_ELEMENT_END:
|
||||
DEBUG("xml.parse", "End element: " << parser->getNodeName());
|
||||
endElement(parser->getNodeName());
|
||||
break;
|
||||
|
||||
default: // ignore: COMMENT, CDATA, UNKNOWN
|
||||
break;
|
||||
}
|
||||
|
||||
if (! have_error.empty()) {
|
||||
parse_error err(have_error);
|
||||
std::cerr << "Error: " << err.what() << std::endl;
|
||||
have_error = "";
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (! result) {
|
||||
const char * err = XML_ErrorString(XML_GetErrorCode(parser));
|
||||
XML_ParserFree(parser);
|
||||
throw parse_error(err);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
delete parser;
|
||||
|
||||
TRACE_FINISH(xml_parsing_total, 1);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void xml_write_amount(std::ostream& out, const amount_t& amount,
|
||||
const int depth = 0)
|
||||
{
|
||||
for (int i = 0; i < depth; i++) out << ' ';
|
||||
out << "<amount>\n";
|
||||
|
||||
commodity_t& c = amount.commodity();
|
||||
for (int i = 0; i < depth + 2; i++) out << ' ';
|
||||
out << "<commodity flags=\"";
|
||||
if (! (c.flags() & COMMODITY_STYLE_SUFFIXED)) out << 'P';
|
||||
if (c.flags() & COMMODITY_STYLE_SEPARATED) out << 'S';
|
||||
if (c.flags() & COMMODITY_STYLE_THOUSANDS) out << 'T';
|
||||
if (c.flags() & COMMODITY_STYLE_EUROPEAN) out << 'E';
|
||||
out << "\">\n";
|
||||
for (int i = 0; i < depth + 4; i++) out << ' ';
|
||||
#if 0
|
||||
// jww (2006-03-02): !!!
|
||||
if (c.price) {
|
||||
out << "<symbol>" << c.base->symbol << "</symbol>\n";
|
||||
for (int i = 0; i < depth + 4; i++) out << ' ';
|
||||
out << "<price>\n";
|
||||
xml_write_amount(out, *c.price, depth + 6);
|
||||
for (int i = 0; i < depth + 4; i++) out << ' ';
|
||||
out << "</price>\n";
|
||||
} else {
|
||||
out << "<symbol>" << c.symbol << "</symbol>\n";
|
||||
}
|
||||
#endif
|
||||
for (int i = 0; i < depth + 2; i++) out << ' ';
|
||||
out << "</commodity>\n";
|
||||
|
||||
for (int i = 0; i < depth + 2; i++) out << ' ';
|
||||
out << "<quantity>";
|
||||
out << amount.quantity_string() << "</quantity>\n";
|
||||
|
||||
for (int i = 0; i < depth; i++) out << ' ';
|
||||
out << "</amount>\n";
|
||||
}
|
||||
|
||||
void xml_write_value(std::ostream& out, const value_t& value,
|
||||
const int depth = 0)
|
||||
{
|
||||
const balance_t * bal = NULL;
|
||||
|
||||
for (int i = 0; i < depth; i++) out << ' ';
|
||||
out << "<value type=\"";
|
||||
switch (value.type()) {
|
||||
case value_t::BOOLEAN: out << "boolean"; break;
|
||||
case value_t::INTEGER: out << "integer"; break;
|
||||
case value_t::AMOUNT: out << "amount"; break;
|
||||
case value_t::BALANCE:
|
||||
case value_t::BALANCE_PAIR: out << "balance"; break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
out << "\">\n";
|
||||
|
||||
switch (value.type()) {
|
||||
case value_t::BOOLEAN:
|
||||
for (int i = 0; i < depth + 2; i++) out << ' ';
|
||||
out << "<boolean>" << value.as_boolean() << "</boolean>\n";
|
||||
break;
|
||||
|
||||
case value_t::INTEGER:
|
||||
for (int i = 0; i < depth + 2; i++) out << ' ';
|
||||
out << "<integer>" << value.as_long() << "</integer>\n";
|
||||
break;
|
||||
|
||||
case value_t::AMOUNT:
|
||||
xml_write_amount(out, value.as_amount(), depth + 2);
|
||||
break;
|
||||
|
||||
case value_t::BALANCE:
|
||||
bal = &(value.as_balance());
|
||||
// fall through...
|
||||
|
||||
case value_t::BALANCE_PAIR:
|
||||
if (! bal)
|
||||
bal = &(value.as_balance_pair().quantity());
|
||||
|
||||
for (int i = 0; i < depth + 2; i++) out << ' ';
|
||||
out << "<balance>\n";
|
||||
|
||||
foreach (const balance_t::amounts_map::value_type& pair, bal->amounts)
|
||||
xml_write_amount(out, pair.second, depth + 4);
|
||||
|
||||
for (int i = 0; i < depth + 2; i++) out << ' ';
|
||||
out << "</balance>\n";
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < depth; i++) out << ' ';
|
||||
out << "</value>\n";
|
||||
}
|
||||
|
||||
void output_xml_string(std::ostream& out, const string& str)
|
||||
{
|
||||
for (const char * s = str.c_str(); *s; s++) {
|
||||
switch (*s) {
|
||||
case '<':
|
||||
out << "<";
|
||||
break;
|
||||
case '>':
|
||||
out << "&rt;";
|
||||
break;
|
||||
case '&':
|
||||
out << "&";
|
||||
break;
|
||||
default:
|
||||
out << *s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void format_xml_entries::format_last_entry()
|
||||
{
|
||||
std::ostream& out(report.output_stream);
|
||||
|
||||
#if 0
|
||||
// jww (2008-05-08): Need to format these dates
|
||||
out << " <entry>\n"
|
||||
<< " <en:date>" << last_entry->_date.to_string("%Y/%m/%d")
|
||||
<< "</en:date>\n";
|
||||
|
||||
if (is_valid(last_entry->_date_eff))
|
||||
out << " <en:date_eff>"
|
||||
<< last_entry->_date_eff.to_string("%Y/%m/%d")
|
||||
<< "</en:date_eff>\n";
|
||||
#endif
|
||||
|
||||
if (last_entry->code) {
|
||||
out << " <en:code>";
|
||||
output_xml_string(out, *last_entry->code);
|
||||
out << "</en:code>\n";
|
||||
}
|
||||
|
||||
if (! last_entry->payee.empty()) {
|
||||
out << " <en:payee>";
|
||||
output_xml_string(out, last_entry->payee);
|
||||
out << "</en:payee>\n";
|
||||
}
|
||||
|
||||
bool first = true;
|
||||
foreach (xact_t * xact, last_entry->xacts) {
|
||||
if (xact->has_xdata() &&
|
||||
xact->xdata().has_flags(XACT_EXT_TO_DISPLAY)) {
|
||||
if (first) {
|
||||
out << " <en:xacts>\n";
|
||||
first = false;
|
||||
}
|
||||
|
||||
out << " <xact>\n";
|
||||
|
||||
#if 0
|
||||
// jww (2008-05-08): Need to format these
|
||||
if (xact->_date)
|
||||
out << " <tr:date>"
|
||||
<< xact->_date.to_string("%Y/%m/%d")
|
||||
<< "</tr:date>\n";
|
||||
|
||||
if (is_valid(xact->_date_eff))
|
||||
out << " <tr:date_eff>"
|
||||
<< xact->_date_eff.to_string("%Y/%m/%d")
|
||||
<< "</tr:date_eff>\n";
|
||||
#endif
|
||||
|
||||
if (xact->state() == item_t::CLEARED)
|
||||
out << " <tr:cleared/>\n";
|
||||
else if (xact->state() == xact_t::PENDING)
|
||||
out << " <tr:pending/>\n";
|
||||
|
||||
if (xact->has_flags(XACT_VIRTUAL))
|
||||
out << " <tr:virtual/>\n";
|
||||
if (xact->has_flags(XACT_AUTO))
|
||||
out << " <tr:generated/>\n";
|
||||
|
||||
if (xact->account) {
|
||||
string name = xact->account->fullname();
|
||||
if (name == "<Total>")
|
||||
name = "[TOTAL]";
|
||||
else if (name == "<Unknown>")
|
||||
name = "[UNKNOWN]";
|
||||
|
||||
out << " <tr:account>";
|
||||
output_xml_string(out, name);
|
||||
out << "</tr:account>\n";
|
||||
}
|
||||
|
||||
out << " <tr:amount>\n";
|
||||
if (xact->xdata().has_flags(XACT_EXT_COMPOUND))
|
||||
xml_write_value(out, xact->xdata().value, 10);
|
||||
else
|
||||
xml_write_value(out, value_t(xact->amount), 10);
|
||||
out << " </tr:amount>\n";
|
||||
|
||||
if (xact->cost) {
|
||||
out << " <tr:cost>\n";
|
||||
xml_write_value(out, value_t(*xact->cost), 10);
|
||||
out << " </tr:cost>\n";
|
||||
}
|
||||
|
||||
if (xact->note) {
|
||||
out << " <tr:note>";
|
||||
output_xml_string(out, *xact->note);
|
||||
out << "</tr:note>\n";
|
||||
}
|
||||
|
||||
if (show_totals) {
|
||||
out << " <total>\n";
|
||||
xml_write_value(out, xact->xdata().total, 10);
|
||||
out << " </total>\n";
|
||||
}
|
||||
|
||||
out << " </xact>\n";
|
||||
|
||||
xact->xdata().add_flags(XACT_EXT_DISPLAYED);
|
||||
}
|
||||
}
|
||||
|
||||
if (! first)
|
||||
out << " </en:xacts>\n";
|
||||
|
||||
out << " </entry>\n";
|
||||
}
|
||||
|
||||
} // namespace ledger
|
||||
142
src/xml.h
142
src/xml.h
|
|
@ -1,142 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2009, John Wiegley. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of New Artisans LLC nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup parse
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file xml.h
|
||||
* @author John Wiegley
|
||||
*
|
||||
* @ingroup parse
|
||||
*
|
||||
* @brief Brief
|
||||
*
|
||||
* Long.
|
||||
*/
|
||||
#ifndef _XML_H
|
||||
#define _XML_H
|
||||
|
||||
#include "journal.h"
|
||||
#include "report.h"
|
||||
#include "output.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
/**
|
||||
* @brief Brief
|
||||
*
|
||||
* Long.
|
||||
*/
|
||||
class CStreamReadCallBack : public irr::io::IFileReadCallBack
|
||||
{
|
||||
std::istream& in;
|
||||
std::size_t size;
|
||||
|
||||
public:
|
||||
//! construct from filename
|
||||
CStreamReadCallBack(std::istream& _in) : in(_in), size(0) {
|
||||
TRACE_CTOR(CStreamReadCallBack, "std::istream&");
|
||||
}
|
||||
virtual ~CStreamReadCallBack() {
|
||||
TRACE_DTOR(CStreamReadCallBack);
|
||||
}
|
||||
|
||||
virtual int read(void * buffer, int sizeToRead)
|
||||
{
|
||||
in.read(static_cast<char *>(buffer), sizeToRead);
|
||||
return in.gcount();
|
||||
}
|
||||
|
||||
virtual int getSize()
|
||||
{
|
||||
if (size == 0) {
|
||||
std::ifstream::pos_type pos = in.tellg();
|
||||
in.seekg(0, std::ios_base::end);
|
||||
size = in.tellg() - pos;
|
||||
in.seekg(pos, std::ios_base::beg);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Brief
|
||||
*
|
||||
* Long.
|
||||
*/
|
||||
class xml_parser_t : public journal_t::parser_t
|
||||
{
|
||||
public:
|
||||
virtual bool test(std::istream& in) const;
|
||||
|
||||
virtual std::size_t parse(std::istream& in,
|
||||
session_t& session,
|
||||
journal_t& journal,
|
||||
account_t * master = NULL,
|
||||
const path * original_file = NULL);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Brief
|
||||
*
|
||||
* Long.
|
||||
*/
|
||||
class format_xml_entries : public format_entries
|
||||
{
|
||||
bool show_totals;
|
||||
|
||||
format_xml_entries();
|
||||
|
||||
public:
|
||||
format_xml_entries(report_t& _report,
|
||||
const bool _show_totals = false)
|
||||
: format_entries(_report, ""), show_totals(_show_totals) {
|
||||
TRACE_CTOR(format_xml_entries, "std::ostream&, const bool");
|
||||
report.output_stream << "<?xml version=\"1.0\"?>\n"
|
||||
<< "<ledger version=\"2.5\">\n";
|
||||
}
|
||||
virtual ~format_xml_entries() throw() {
|
||||
TRACE_DTOR(format_xml_entries);
|
||||
}
|
||||
|
||||
virtual void flush() {
|
||||
format_entries::flush();
|
||||
report.output_stream << "</ledger>" << std::endl;
|
||||
}
|
||||
|
||||
virtual void format_last_entry();
|
||||
};
|
||||
|
||||
} // namespace ledger
|
||||
|
||||
#endif // _XML_H
|
||||
Loading…
Add table
Reference in a new issue