Initial implementation of document_builder_t.
This commit is contained in:
parent
77db7eb92f
commit
59fc3d1bdb
45 changed files with 832 additions and 3946 deletions
12
Makefile.am
12
Makefile.am
|
|
@ -41,11 +41,13 @@ libledger_la_SOURCES = \
|
|||
src/amount.cc \
|
||||
src/balance.cc \
|
||||
src/value.cc \
|
||||
src/xml.cc \
|
||||
src/document.cc \
|
||||
src/node.cc \
|
||||
src/xpath.cc \
|
||||
src/builder.cc \
|
||||
src/journal.cc \
|
||||
src/textual.cc \
|
||||
src/binary.cc \
|
||||
src/transform.cc \
|
||||
src/register.cc \
|
||||
src/report.cc \
|
||||
|
|
@ -99,26 +101,18 @@ pkginclude_HEADERS = \
|
|||
src/builder.h \
|
||||
src/commodity.h \
|
||||
src/context.h \
|
||||
src/csv.h \
|
||||
src/derive.h \
|
||||
src/emacs.h \
|
||||
src/fdstream.hpp \
|
||||
src/flags.h \
|
||||
src/format.h \
|
||||
src/gnucash.h \
|
||||
src/journal.h \
|
||||
src/ledger.h \
|
||||
src/mask.h \
|
||||
src/ofx.h \
|
||||
src/option.h \
|
||||
src/parser.h \
|
||||
src/pyfstream.h \
|
||||
src/pyinterp.h \
|
||||
src/pyledger.h \
|
||||
src/pyutils.h \
|
||||
src/qif.h \
|
||||
src/quotes.h \
|
||||
src/reconcile.h \
|
||||
src/register.h \
|
||||
src/report.h \
|
||||
src/scoped_execute.h \
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef _BUILDER_H
|
||||
#define _BUILDER_H
|
||||
|
||||
#include "xml.h"
|
||||
#include "document.h"
|
||||
|
||||
namespace ledger {
|
||||
namespace xml {
|
||||
|
|
@ -44,8 +44,8 @@ public:
|
|||
virtual void push_attr(const node_t::nameid_t name_id,
|
||||
const string& value) = 0;
|
||||
|
||||
virtual void begin_node(const string& name) = 0;
|
||||
virtual void begin_node(const node_t::nameid_t name_id) = 0;
|
||||
virtual void begin_node(const string& name, bool terminal = false) = 0;
|
||||
virtual void begin_node(const node_t::nameid_t name_id, bool terminal = false) = 0;
|
||||
|
||||
virtual void push_node(const string& name,
|
||||
const optional<position_t>& end_pos = none) = 0;
|
||||
|
|
@ -70,8 +70,71 @@ public:
|
|||
* This builder can be used to parse ordinary XML into a document
|
||||
* object structure which can then be traversed in memory.
|
||||
*/
|
||||
class xml_builder_t : public builder_t
|
||||
class document_builder_t : public builder_t
|
||||
{
|
||||
public:
|
||||
typedef std::list<std::pair<node_t::nameid_t, string> > attrs_list;
|
||||
|
||||
document_t& document;
|
||||
attrs_list current_attrs;
|
||||
node_t * current;
|
||||
string current_text;
|
||||
|
||||
document_builder_t(document_t& _document)
|
||||
: document(_document), current(&document) {}
|
||||
|
||||
virtual void push_attr(const string& name,
|
||||
const string& value) {
|
||||
push_attr(document.register_name(name), value);
|
||||
}
|
||||
virtual void push_attr(const node_t::nameid_t name_id,
|
||||
const string& value) {
|
||||
current_attrs.push_back(attrs_list::value_type(name_id, value.c_str()));
|
||||
}
|
||||
|
||||
virtual void begin_node(const string& name, bool terminal = false) {
|
||||
begin_node(document.register_name(name), terminal);
|
||||
}
|
||||
virtual void begin_node(const node_t::nameid_t name_id,
|
||||
bool terminal = false) {
|
||||
if (terminal)
|
||||
current = current->as_parent_node().create_child<terminal_node_t>(name_id);
|
||||
else
|
||||
current = current->as_parent_node().create_child<parent_node_t>(name_id);
|
||||
|
||||
foreach (const attrs_list::value_type& pair, current_attrs)
|
||||
current->set_attr(pair.first, pair.second.c_str());
|
||||
current_attrs.clear();
|
||||
}
|
||||
|
||||
virtual void push_node(const string& name,
|
||||
const optional<position_t>& end_pos = none) {
|
||||
begin_node(name, true);
|
||||
end_node(name, end_pos);
|
||||
}
|
||||
virtual void push_node(const node_t::nameid_t name_id,
|
||||
const optional<position_t>& end_pos = none) {
|
||||
begin_node(name_id, true);
|
||||
end_node(name_id, end_pos);
|
||||
}
|
||||
|
||||
virtual node_t * current_node() {
|
||||
return current;
|
||||
}
|
||||
|
||||
virtual void append_text(const string& text) {
|
||||
assert(! current->is_parent_node());
|
||||
polymorphic_downcast<terminal_node_t *>(current)->set_text(text);
|
||||
}
|
||||
|
||||
virtual node_t * end_node(const string& name,
|
||||
const optional<position_t>& end_pos = none) {
|
||||
current = &*current->parent();
|
||||
}
|
||||
virtual node_t * end_node(const node_t::nameid_t name_id,
|
||||
const optional<position_t>& end_pos = none) {
|
||||
current = &*current->parent();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -91,7 +154,7 @@ class xml_builder_t : public builder_t
|
|||
* constructed on the fly, as if they'd been created in the first
|
||||
* place by a regular xml_builder_t.
|
||||
*/
|
||||
class journal_builder_t : public xml_builder_t
|
||||
class journal_builder_t : public document_builder_t
|
||||
{
|
||||
public:
|
||||
virtual void set_start_position(std::istream& in) {
|
||||
|
|
@ -138,20 +201,20 @@ public:
|
|||
push_attr("hello", value);
|
||||
}
|
||||
|
||||
virtual void begin_node(const string& name) {
|
||||
virtual void begin_node(const string& name, bool terminal = false) {
|
||||
outs << '<' << name;
|
||||
foreach (const attrs_list::value_type& attr, current_attrs)
|
||||
outs << ' ' << attr.first << "=\"" << attr.second << "\"";
|
||||
current_attrs.clear();
|
||||
outs << '>';
|
||||
}
|
||||
virtual void begin_node(const node_t::nameid_t name_id) {
|
||||
virtual void begin_node(const node_t::nameid_t name_id, bool terminal = false) {
|
||||
begin_node("hello");
|
||||
}
|
||||
|
||||
virtual void push_node(const string& name,
|
||||
const optional<position_t>& end_pos = none) {
|
||||
begin_node(name);
|
||||
begin_node(name, true);
|
||||
end_node(name, end_pos);
|
||||
}
|
||||
virtual void push_node(const node_t::nameid_t name_id,
|
||||
|
|
|
|||
|
|
@ -455,14 +455,8 @@ commodity_t * commodity_pool_t::create(const string& symbol)
|
|||
|
||||
commodity->ident = commodities.size();
|
||||
|
||||
std::pair<commodities_t::iterator, bool> result =
|
||||
commodities.insert(commodity.get());
|
||||
if (! result.second) {
|
||||
assert(false);
|
||||
return NULL;
|
||||
} else {
|
||||
return commodity.release();
|
||||
}
|
||||
commodities.push_back(commodity.get());
|
||||
return commodity.release();
|
||||
}
|
||||
|
||||
commodity_t * commodity_pool_t::find_or_create(const string& symbol)
|
||||
|
|
@ -498,11 +492,7 @@ commodity_t * commodity_pool_t::find(const commodity_t::ident_t ident)
|
|||
commodities_by_ident;
|
||||
|
||||
commodities_by_ident& ident_index = commodities.get<0>();
|
||||
commodities_by_ident::iterator i = ident_index.find(ident);
|
||||
if (i != ident_index.end())
|
||||
return *i;
|
||||
else
|
||||
return NULL;
|
||||
return ident_index[ident];
|
||||
}
|
||||
|
||||
commodity_t *
|
||||
|
|
@ -598,14 +588,8 @@ commodity_pool_t::create(commodity_t& comm,
|
|||
commodity->ident = commodities.size();
|
||||
commodity->mapping_key_ = mapping_key;
|
||||
|
||||
std::pair<commodities_t::iterator, bool> result
|
||||
= commodities.insert(commodity.get());
|
||||
if (! result.second) {
|
||||
assert(false);
|
||||
return NULL;
|
||||
} else {
|
||||
return commodity.release();
|
||||
}
|
||||
commodities.push_back(commodity.get());
|
||||
return commodity.release();
|
||||
}
|
||||
|
||||
commodity_t * commodity_pool_t::find_or_create(commodity_t& comm,
|
||||
|
|
|
|||
|
|
@ -318,9 +318,7 @@ class commodity_pool_t : public noncopyable
|
|||
typedef multi_index_container<
|
||||
commodity_t *,
|
||||
multi_index::indexed_by<
|
||||
multi_index::ordered_unique<
|
||||
multi_index::member<commodity_t,
|
||||
commodity_t::ident_t, &commodity_t::ident> >,
|
||||
multi_index::random_access<>,
|
||||
multi_index::hashed_unique<
|
||||
multi_index::const_mem_fun<commodity_t,
|
||||
string, &commodity_t::mapping_key> >
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _XML_H
|
||||
#define _XML_H
|
||||
#ifndef _NODE_H
|
||||
#define _NODE_H
|
||||
|
||||
#include "journal.h"
|
||||
#include "value.h"
|
||||
|
|
@ -507,4 +507,4 @@ wrap_node(document_t * doc, journal_t * journal, void * parent_node) {
|
|||
} // namespace xml
|
||||
} // namespace ledger
|
||||
|
||||
#endif // _XML_H
|
||||
#endif // _NODE_H
|
||||
31
src/csv.cc
31
src/csv.cc
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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.
|
||||
*/
|
||||
|
||||
31
src/csv.h
31
src/csv.h
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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.
|
||||
*/
|
||||
|
||||
209
src/derive.cc
209
src/derive.cc
|
|
@ -1,209 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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 "derive.h"
|
||||
#include "mask.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
void derive_command::operator()
|
||||
(value_t& result, xml::xpath_t::scope_t * locals)
|
||||
{
|
||||
#if 0
|
||||
std::ostream& out = *get_ptr<std::ostream>(locals, 0);
|
||||
repitem_t * items = get_ptr<repitem_t>(locals, 1);
|
||||
strings_list& args = *get_ptr<strings_list *>(locals, 2);
|
||||
|
||||
std::auto_ptr<entry_t> added(new entry_t);
|
||||
|
||||
entry_t * matching = NULL;
|
||||
|
||||
strings_list::iterator i = args.begin();
|
||||
|
||||
added->_date = *i++;
|
||||
if (i == args.end())
|
||||
throw new error("Too few arguments to 'entry'");
|
||||
|
||||
mask_t regexp(*i++);
|
||||
|
||||
entries_list::reverse_iterator j;
|
||||
for (j = journal.entries.rbegin();
|
||||
j != journal.entries.rend();
|
||||
j++)
|
||||
if (regexp.match((*j)->payee)) {
|
||||
matching = *j;
|
||||
break;
|
||||
}
|
||||
|
||||
added->payee = matching ? matching->payee : regexp.pattern;
|
||||
|
||||
if (! matching) {
|
||||
account_t * acct;
|
||||
if (i == args.end() || ((*i)[0] == '-' || std::isdigit((*i)[0]))) {
|
||||
acct = journal.find_account("Expenses");
|
||||
}
|
||||
else if (i != args.end()) {
|
||||
acct = journal.find_account_re(*i);
|
||||
if (! acct)
|
||||
acct = journal.find_account(*i);
|
||||
assert(acct);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i == args.end()) {
|
||||
added->add_transaction(new transaction_t(acct));
|
||||
} else {
|
||||
transaction_t * xact = new transaction_t(acct, amount_t(*i++));
|
||||
added->add_transaction(xact);
|
||||
|
||||
if (! xact->amount.commodity()) {
|
||||
// If the amount has no commodity, we can determine it given
|
||||
// the account by creating a final for the account and then
|
||||
// checking if it contains only a single commodity. An
|
||||
// account to which only dollars are applied would imply that
|
||||
// dollars are wanted now too.
|
||||
|
||||
std::auto_ptr<item_handler<transaction_t> > formatter;
|
||||
formatter.reset(new set_account_value);
|
||||
walk_entries(journal.entries, *formatter.get());
|
||||
formatter->flush();
|
||||
|
||||
sum_accounts(*journal.master);
|
||||
|
||||
value_t total = account_xdata(*acct).total;
|
||||
if (total.type == value_t::AMOUNT)
|
||||
xact->amount.set_commodity(((amount_t *) total.data)->commodity());
|
||||
}
|
||||
}
|
||||
|
||||
if (journal.basket)
|
||||
acct = journal.basket;
|
||||
else
|
||||
acct = journal.find_account("Equity");
|
||||
|
||||
added->add_transaction(new transaction_t(acct));
|
||||
}
|
||||
else if (i == args.end()) {
|
||||
// If no argument were given but the payee, assume the user wants
|
||||
// to see the same transaction as last time.
|
||||
added->code = matching->code;
|
||||
|
||||
for (transactions_list::iterator k = matching->transactions.begin();
|
||||
k != matching->transactions.end();
|
||||
k++)
|
||||
added->add_transaction(new transaction_t(**k));
|
||||
}
|
||||
else if ((*i)[0] == '-' || std::isdigit((*i)[0])) {
|
||||
transaction_t * m_xact, * xact, * first;
|
||||
m_xact = matching->transactions.front();
|
||||
|
||||
first = xact = new transaction_t(m_xact->account, amount_t(*i++));
|
||||
added->add_transaction(xact);
|
||||
|
||||
if (! xact->amount.commodity())
|
||||
xact->amount.set_commodity(m_xact->amount.commodity());
|
||||
|
||||
m_xact = matching->transactions.back();
|
||||
|
||||
xact = new transaction_t(m_xact->account, - first->amount);
|
||||
added->add_transaction(xact);
|
||||
|
||||
if (i != args.end()) {
|
||||
account_t * acct = journal.find_account_re(*i);
|
||||
if (! acct)
|
||||
acct = journal.find_account(*i);
|
||||
assert(acct);
|
||||
added->transactions.back()->account = acct;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while (i != args.end()) {
|
||||
string& re_pat(*i++);
|
||||
account_t * acct = NULL;
|
||||
amount_t * amt = NULL;
|
||||
|
||||
mask_t acct_regex(re_pat);
|
||||
|
||||
for (; j != journal.entries.rend(); j++)
|
||||
if (regexp.match((*j)->payee)) {
|
||||
entry_t * entry = *j;
|
||||
for (transactions_list::const_iterator x =
|
||||
entry->transactions.begin();
|
||||
x != entry->transactions.end();
|
||||
x++)
|
||||
if (acct_regex.match((*x)->account->fullname())) {
|
||||
acct = (*x)->account;
|
||||
amt = &(*x)->amount;
|
||||
matching = entry;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
|
||||
found:
|
||||
if (! acct)
|
||||
acct = journal.find_account_re(re_pat);
|
||||
if (! acct)
|
||||
acct = journal.find_account(re_pat);
|
||||
|
||||
transaction_t * xact;
|
||||
if (i == args.end()) {
|
||||
if (amt)
|
||||
xact = new transaction_t(acct, *amt);
|
||||
else
|
||||
xact = new transaction_t(acct);
|
||||
} else {
|
||||
xact = new transaction_t(acct, amount_t(*i++));
|
||||
if (! xact->amount.commodity()) {
|
||||
if (amt)
|
||||
xact->amount.set_commodity(amt->commodity());
|
||||
else if (commodity_t::default_commodity)
|
||||
xact->amount.set_commodity(*commodity_t::default_commodity);
|
||||
}
|
||||
}
|
||||
added->add_transaction(xact);
|
||||
}
|
||||
|
||||
assert(matching->transactions.back()->account);
|
||||
if (account_t * draw_acct = matching->transactions.back()->account)
|
||||
added->add_transaction(new transaction_t(draw_acct));
|
||||
}
|
||||
|
||||
done:
|
||||
if (! run_hooks(journal.entry_finalize_hooks, *added, false) ||
|
||||
! added->finalize() ||
|
||||
! run_hooks(journal.entry_finalize_hooks, *added, true))
|
||||
throw new error("Failed to finalize derived entry (check commodities)");
|
||||
|
||||
return added.release();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace ledger
|
||||
49
src/derive.h
49
src/derive.h
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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.
|
||||
*/
|
||||
|
||||
#ifndef _DERIVE_H
|
||||
#define _DERIVE_H
|
||||
|
||||
#include "xpath.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
class derive_command : public xml::xpath_t::functor_t
|
||||
{
|
||||
public:
|
||||
derive_command() : xml::xpath_t::functor_t("entry", true) {}
|
||||
|
||||
virtual void operator()(value_t& result, xml::xpath_t::scope_t * locals);
|
||||
};
|
||||
|
||||
} // namespace ledger
|
||||
|
||||
#endif // _DERIVE_H
|
||||
177
src/document.cc
Normal file
177
src/document.cc
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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 "document.h"
|
||||
|
||||
namespace ledger {
|
||||
namespace xml {
|
||||
|
||||
namespace {
|
||||
const std::size_t ledger_builtins_size = 39;
|
||||
const char * ledger_builtins[] = {
|
||||
"account",
|
||||
"account-path",
|
||||
"amount",
|
||||
"amount-expr",
|
||||
"arg",
|
||||
"auto-entry",
|
||||
"balance",
|
||||
"checkin",
|
||||
"cleared",
|
||||
"code",
|
||||
"commodity",
|
||||
"commodity-conversion",
|
||||
"commodity-nomarket",
|
||||
"commodity-template",
|
||||
"current-year",
|
||||
"date",
|
||||
"default-account",
|
||||
"directive",
|
||||
"effective",
|
||||
"entries",
|
||||
"entry",
|
||||
"from",
|
||||
"journal",
|
||||
"ledger",
|
||||
"name",
|
||||
"note",
|
||||
"payee",
|
||||
"pending",
|
||||
"period",
|
||||
"period-entry",
|
||||
"price",
|
||||
"price-history",
|
||||
"rule",
|
||||
"symbol",
|
||||
"template",
|
||||
"time",
|
||||
"to",
|
||||
"transaction",
|
||||
"virtual",
|
||||
"year"
|
||||
};
|
||||
}
|
||||
|
||||
node_t::nameid_t document_t::register_name(const string& name)
|
||||
{
|
||||
optional<nameid_t> index = lookup_name_id(name);
|
||||
if (index)
|
||||
return *index;
|
||||
|
||||
if (! names)
|
||||
names = names_t();
|
||||
|
||||
nameid_t real_index = names->size() + 1000;
|
||||
names->push_back(name_pair(name, real_index));
|
||||
DEBUG("xml.lookup", this << " Inserted name: " << name);
|
||||
|
||||
return real_index;
|
||||
}
|
||||
|
||||
optional<node_t::nameid_t> document_t::lookup_name_id(const string& name) const
|
||||
{
|
||||
if (optional<node_t::nameid_t> id = lookup_builtin_id(name))
|
||||
return id;
|
||||
|
||||
if (! names)
|
||||
return none;
|
||||
|
||||
DEBUG("xml.lookup", this << " Finding name: " << name);
|
||||
|
||||
typedef names_t::nth_index<1>::type names_by_name;
|
||||
|
||||
const names_by_name& name_index = names->get<1>();
|
||||
names_by_name::const_iterator i = name_index.find(name);
|
||||
if (i != name_index.end())
|
||||
return (*i).second;
|
||||
|
||||
return none;
|
||||
}
|
||||
|
||||
optional<node_t::nameid_t> document_t::lookup_builtin_id(const string& name)
|
||||
{
|
||||
int first = 0;
|
||||
int last = (int)ledger_builtins_size;
|
||||
|
||||
while (first <= last) {
|
||||
int mid = (first + last) / 2; // compute mid point.
|
||||
|
||||
int result;
|
||||
if ((result = (int)name[0] - (int)ledger_builtins[mid][0]) == 0)
|
||||
result = std::strcmp(name.c_str(), ledger_builtins[mid]);
|
||||
|
||||
if (result > 0)
|
||||
first = mid + 1; // repeat search in top half.
|
||||
else if (result < 0)
|
||||
last = mid - 1; // repeat search in bottom half.
|
||||
else
|
||||
return nameid_t(mid + 10);
|
||||
}
|
||||
|
||||
return none;
|
||||
}
|
||||
|
||||
optional<const char *> document_t::lookup_name(nameid_t id) const
|
||||
{
|
||||
if (id < 1000) {
|
||||
switch (id) {
|
||||
case CURRENT:
|
||||
return "CURRENT";
|
||||
case PARENT:
|
||||
return "PARENT";
|
||||
case ROOT:
|
||||
return "ROOT";
|
||||
case ALL:
|
||||
return "ALL";
|
||||
|
||||
default:
|
||||
assert(id >= 10);
|
||||
return ledger_builtins[id - 10];
|
||||
}
|
||||
}
|
||||
else if (names) {
|
||||
int index = id - 1000;
|
||||
typedef names_t::nth_index<0>::type names_by_random_access;
|
||||
const names_by_random_access& random_access = names->get<0>();
|
||||
if (index < random_access.size())
|
||||
return random_access[index].first.c_str();
|
||||
}
|
||||
return none;
|
||||
}
|
||||
|
||||
void document_t::print(std::ostream& out) const
|
||||
{
|
||||
out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
|
||||
parent_node_t::print(out);
|
||||
}
|
||||
|
||||
} // namespace xml
|
||||
} // namespace ledger
|
||||
150
src/document.h
Normal file
150
src/document.h
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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.
|
||||
*/
|
||||
|
||||
#ifndef _DOCUMENT_H
|
||||
#define _DOCUMENT_H
|
||||
|
||||
#include "node.h"
|
||||
#include "value.h"
|
||||
|
||||
namespace ledger {
|
||||
namespace xml {
|
||||
|
||||
enum ledger_builtins_t {
|
||||
ACCOUNT_ATTR = 10,
|
||||
ACCOUNT_PATH_NODE,
|
||||
AMOUNT_NODE,
|
||||
AMOUNT_EXPR_NODE,
|
||||
ARG_ATTR,
|
||||
AUTO_ENTRY_NODE,
|
||||
BALANCE_ATTR,
|
||||
CHECKIN_NODE,
|
||||
CLEARED_ATTR,
|
||||
CODE_ATTR,
|
||||
COMMODITY_NODE,
|
||||
COMMODITY_CONVERSION_NODE,
|
||||
COMMODITY_NOMARKET_NODE,
|
||||
COMMODITY_TEMPLATE_NODE,
|
||||
CURRENT_YEAR_NODE,
|
||||
DATE_ATTR,
|
||||
DEFAULT_ACCOUNT_NODE,
|
||||
DIRECTIVE_NODE,
|
||||
EFF_DATE_ATTR,
|
||||
ENTRIES_NODE,
|
||||
ENTRY_NODE,
|
||||
FROM_ATTR,
|
||||
JOURNAL_NODE,
|
||||
LEDGER_NODE,
|
||||
NAME_ATTR,
|
||||
NOTE_NODE,
|
||||
PAYEE_NODE,
|
||||
PENDING_ATTR,
|
||||
PERIOD_NODE,
|
||||
PERIOD_ENTRY_NODE,
|
||||
PRICE_ATTR,
|
||||
PRICE_HISTORY_NODE,
|
||||
RULE_NODE,
|
||||
SYMBOL_ATTR,
|
||||
TEMPLATE_ATTR,
|
||||
TIME_ATTR,
|
||||
TO_ATTR,
|
||||
TRANSACTION_NODE,
|
||||
VIRTUAL_ATTR,
|
||||
YEAR_ATTR
|
||||
};
|
||||
|
||||
class document_t : public parent_node_t
|
||||
{
|
||||
typedef std::pair<string, nameid_t> name_pair;
|
||||
|
||||
typedef multi_index_container<
|
||||
name_pair,
|
||||
multi_index::indexed_by<
|
||||
multi_index::random_access<>,
|
||||
multi_index::hashed_unique<
|
||||
multi_index::member<name_pair, string, &name_pair::first> >
|
||||
>
|
||||
> names_t;
|
||||
|
||||
optional<names_t> names;
|
||||
|
||||
public:
|
||||
// Ids 0-9 are reserved. 10-999 are for "builtin" names. 1000+ are
|
||||
// for dynamically registered names.
|
||||
enum special_names_t {
|
||||
CURRENT, PARENT, ROOT, ALL
|
||||
};
|
||||
|
||||
document_t(node_t::nameid_t _name_id)
|
||||
: parent_node_t(_name_id, *this) {
|
||||
TRACE_CTOR(xml::document_t, "node_t::nameid_t");
|
||||
}
|
||||
~document_t() {
|
||||
TRACE_DTOR(xml::document_t);
|
||||
}
|
||||
|
||||
nameid_t register_name(const string& name);
|
||||
|
||||
optional<nameid_t> lookup_name_id(const string& name) const;
|
||||
static optional<nameid_t> lookup_builtin_id(const string& name);
|
||||
optional<const char *> lookup_name(nameid_t id) const;
|
||||
|
||||
void print(std::ostream& out) const;
|
||||
|
||||
#if 0
|
||||
#if defined(HAVE_EXPAT) || defined(HAVE_XMLPARSE)
|
||||
class parser_t
|
||||
{
|
||||
public:
|
||||
document_t * document;
|
||||
XML_Parser parser;
|
||||
string have_error;
|
||||
const char * pending;
|
||||
node_t::attrs_map * pending_attrs;
|
||||
bool handled_data;
|
||||
|
||||
std::list<parent_node_t *> node_stack;
|
||||
|
||||
parser_t() : document(NULL), pending(NULL), pending_attrs(NULL),
|
||||
handled_data(false) {}
|
||||
virtual ~parser_t() {}
|
||||
|
||||
virtual bool test(std::istream& in) const;
|
||||
virtual document_t * parse(std::istream& in);
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace xml
|
||||
} // namespace ledger
|
||||
|
||||
#endif // _DOCUMENT_H
|
||||
31
src/emacs.cc
31
src/emacs.cc
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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.
|
||||
*/
|
||||
|
||||
31
src/emacs.h
31
src/emacs.h
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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.
|
||||
*/
|
||||
|
||||
397
src/gnucash.cc
397
src/gnucash.cc
|
|
@ -1,397 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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 "gnucash.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
void startElement(void *userData, const char *name, const char ** /* attrs */)
|
||||
{
|
||||
gnucash_parser_t * parser = static_cast<gnucash_parser_t *>(userData);
|
||||
|
||||
if (std::strcmp(name, "gnc:account") == 0) {
|
||||
parser->curr_account = new account_t(parser->master_account);
|
||||
}
|
||||
else if (std::strcmp(name, "act:name") == 0)
|
||||
parser->action = gnucash_parser_t::ACCOUNT_NAME;
|
||||
else if (std::strcmp(name, "act:id") == 0)
|
||||
parser->action = gnucash_parser_t::ACCOUNT_ID;
|
||||
else if (std::strcmp(name, "act:parent") == 0)
|
||||
parser->action = gnucash_parser_t::ACCOUNT_PARENT;
|
||||
else if (std::strcmp(name, "gnc:commodity") == 0)
|
||||
parser->curr_comm = NULL;
|
||||
else if (std::strcmp(name, "cmdty:id") == 0)
|
||||
parser->action = gnucash_parser_t::COMM_SYM;
|
||||
else if (std::strcmp(name, "cmdty:name") == 0)
|
||||
parser->action = gnucash_parser_t::COMM_NAME;
|
||||
else if (std::strcmp(name, "cmdty:fraction") == 0)
|
||||
parser->action = gnucash_parser_t::COMM_PREC;
|
||||
else if (std::strcmp(name, "gnc:transaction") == 0) {
|
||||
assert(! parser->curr_entry);
|
||||
parser->curr_entry = new entry_t;
|
||||
}
|
||||
else if (std::strcmp(name, "trn:num") == 0)
|
||||
parser->action = gnucash_parser_t::ENTRY_NUM;
|
||||
else if (std::strcmp(name, "trn:date-posted") == 0)
|
||||
parser->action = gnucash_parser_t::ALMOST_ENTRY_DATE;
|
||||
else if (parser->action == gnucash_parser_t::ALMOST_ENTRY_DATE &&
|
||||
std::strcmp(name, "ts:date") == 0)
|
||||
parser->action = gnucash_parser_t::ENTRY_DATE;
|
||||
else if (std::strcmp(name, "trn:description") == 0)
|
||||
parser->action = gnucash_parser_t::ENTRY_DESC;
|
||||
else if (std::strcmp(name, "trn:split") == 0) {
|
||||
assert(parser->curr_entry);
|
||||
parser->curr_entry->add_transaction(new transaction_t(parser->curr_account));
|
||||
}
|
||||
else if (std::strcmp(name, "split:reconciled-state") == 0)
|
||||
parser->action = gnucash_parser_t::XACT_STATE;
|
||||
else if (std::strcmp(name, "split:amount") == 0)
|
||||
parser->action = gnucash_parser_t::XACT_AMOUNT;
|
||||
else if (std::strcmp(name, "split:value") == 0)
|
||||
parser->action = gnucash_parser_t::XACT_VALUE;
|
||||
else if (std::strcmp(name, "split:quantity") == 0)
|
||||
parser->action = gnucash_parser_t::XACT_QUANTITY;
|
||||
else if (std::strcmp(name, "split:account") == 0)
|
||||
parser->action = gnucash_parser_t::XACT_ACCOUNT;
|
||||
else if (std::strcmp(name, "split:memo") == 0)
|
||||
parser->action = gnucash_parser_t::XACT_NOTE;
|
||||
}
|
||||
|
||||
void endElement(void *userData, const char *name)
|
||||
{
|
||||
gnucash_parser_t * parser = static_cast<gnucash_parser_t *>(userData);
|
||||
|
||||
if (std::strcmp(name, "gnc:account") == 0) {
|
||||
assert(parser->curr_account);
|
||||
if (parser->curr_account->parent == parser->master_account)
|
||||
parser->curr_journal->add_account(parser->curr_account);
|
||||
parser->accounts_by_id.insert
|
||||
(accounts_map::value_type(parser->curr_account_id, parser->curr_account));
|
||||
parser->curr_account = NULL;
|
||||
}
|
||||
else if (std::strcmp(name, "gnc:commodity") == 0) {
|
||||
parser->curr_comm = NULL;
|
||||
}
|
||||
else if (std::strcmp(name, "gnc:transaction") == 0) {
|
||||
assert(parser->curr_entry);
|
||||
|
||||
// Add the new entry (what gnucash calls a 'transaction') to the
|
||||
// journal
|
||||
if (! parser->curr_journal->add_entry(parser->curr_entry)) {
|
||||
print_entry(std::cerr, *parser->curr_entry);
|
||||
parser->have_error = "The above entry does not balance";
|
||||
checked_delete(parser->curr_entry);
|
||||
} else {
|
||||
parser->curr_entry->src_idx = parser->src_idx;
|
||||
parser->curr_entry->beg_pos = parser->beg_pos;
|
||||
parser->curr_entry->beg_line = parser->beg_line;
|
||||
parser->curr_entry->end_pos = parser->instreamp->tellg();
|
||||
parser->curr_entry->end_line =
|
||||
XML_GetCurrentLineNumber(parser->expat_parser) - parser->offset;
|
||||
parser->count++;
|
||||
}
|
||||
|
||||
// Clear the relevant variables for the next run
|
||||
parser->curr_entry = NULL;
|
||||
parser->entry_comm = NULL;
|
||||
}
|
||||
else if (std::strcmp(name, "trn:split") == 0) {
|
||||
transaction_t * xact = parser->curr_entry->transactions.back();
|
||||
|
||||
// Identify the commodity to use for the value of this
|
||||
// transaction. The quantity indicates how many times that value
|
||||
// the transaction is worth.
|
||||
amount_t value;
|
||||
commodity_t * default_commodity = NULL;
|
||||
if (parser->entry_comm) {
|
||||
default_commodity = parser->entry_comm;
|
||||
} else {
|
||||
gnucash_parser_t::account_comm_map::iterator ac =
|
||||
parser->account_comms.find(xact->account);
|
||||
if (ac != parser->account_comms.end())
|
||||
default_commodity = (*ac).second;
|
||||
}
|
||||
|
||||
if (default_commodity) {
|
||||
parser->curr_quant.set_commodity(*default_commodity);
|
||||
value = parser->curr_quant.round();
|
||||
|
||||
if (parser->curr_value.commodity() == *default_commodity)
|
||||
parser->curr_value = value;
|
||||
} else {
|
||||
value = parser->curr_quant;
|
||||
}
|
||||
|
||||
xact->state = parser->curr_state;
|
||||
xact->amount = value;
|
||||
if (value != parser->curr_value)
|
||||
xact->cost = amount_t(parser->curr_value);
|
||||
|
||||
xact->beg_pos = parser->beg_pos;
|
||||
xact->beg_line = parser->beg_line;
|
||||
xact->end_pos = parser->instreamp->tellg();
|
||||
xact->end_line =
|
||||
XML_GetCurrentLineNumber(parser->expat_parser) - parser->offset;
|
||||
|
||||
// Clear the relevant variables for the next run
|
||||
parser->curr_state = transaction_t::UNCLEARED;
|
||||
parser->curr_value = amount_t();
|
||||
parser->curr_quant = amount_t();
|
||||
}
|
||||
|
||||
parser->action = gnucash_parser_t::NO_ACTION;
|
||||
}
|
||||
|
||||
amount_t gnucash_parser_t::convert_number(const string& number,
|
||||
int * precision)
|
||||
{
|
||||
const char * num = number.c_str();
|
||||
|
||||
if (char * p = std::strchr(num, '/')) {
|
||||
string numer_str(num, p - num);
|
||||
string denom_str(p + 1);
|
||||
|
||||
amount_t amt(numer_str);
|
||||
amount_t den(denom_str);
|
||||
|
||||
if (precision)
|
||||
*precision = denom_str.length() - 1;
|
||||
|
||||
if (! den) {
|
||||
have_error = "Denominator in entry is zero!";
|
||||
return amt;
|
||||
} else {
|
||||
return amt / den;
|
||||
}
|
||||
} else {
|
||||
return amount_t(number);
|
||||
}
|
||||
}
|
||||
|
||||
void dataHandler(void *userData, const char *s, int len)
|
||||
{
|
||||
gnucash_parser_t * parser = static_cast<gnucash_parser_t *>(userData);
|
||||
|
||||
switch (parser->action) {
|
||||
case gnucash_parser_t::ACCOUNT_NAME:
|
||||
parser->curr_account->name = string(s, len);
|
||||
break;
|
||||
|
||||
case gnucash_parser_t::ACCOUNT_ID:
|
||||
parser->curr_account_id = string(s, len);
|
||||
break;
|
||||
|
||||
case gnucash_parser_t::ACCOUNT_PARENT: {
|
||||
accounts_map::iterator i = parser->accounts_by_id.find(string(s, len));
|
||||
assert(i != parser->accounts_by_id.end());
|
||||
parser->curr_account->parent = (*i).second;
|
||||
parser->curr_account->depth = parser->curr_account->parent->depth + 1;
|
||||
(*i).second->add_account(parser->curr_account);
|
||||
break;
|
||||
}
|
||||
|
||||
case gnucash_parser_t::COMM_SYM: {
|
||||
string symbol(s, len);
|
||||
if (symbol == "USD") symbol = "$";
|
||||
|
||||
parser->curr_comm = amount_t::current_pool->find_or_create(symbol);
|
||||
assert(parser->curr_comm);
|
||||
|
||||
if (symbol != "$")
|
||||
parser->curr_comm->add_flags(COMMODITY_STYLE_SEPARATED);
|
||||
|
||||
if (parser->curr_account)
|
||||
parser->account_comms.insert
|
||||
(gnucash_parser_t::account_comm_map::value_type
|
||||
(parser->curr_account, parser->curr_comm));
|
||||
else if (parser->curr_entry)
|
||||
parser->entry_comm = parser->curr_comm;
|
||||
break;
|
||||
}
|
||||
|
||||
case gnucash_parser_t::COMM_NAME:
|
||||
parser->curr_comm->set_name(string(s, len));
|
||||
break;
|
||||
|
||||
case gnucash_parser_t::COMM_PREC:
|
||||
parser->curr_comm->set_precision(len - 1);
|
||||
break;
|
||||
|
||||
case gnucash_parser_t::ENTRY_NUM:
|
||||
parser->curr_entry->code = string(s, len);
|
||||
break;
|
||||
|
||||
case gnucash_parser_t::ENTRY_DATE:
|
||||
parser->curr_entry->_date = parse_datetime(string(s, len));
|
||||
break;
|
||||
|
||||
case gnucash_parser_t::ENTRY_DESC:
|
||||
parser->curr_entry->payee = string(s, len);
|
||||
break;
|
||||
|
||||
case gnucash_parser_t::XACT_STATE:
|
||||
if (*s == 'y')
|
||||
parser->curr_state = transaction_t::CLEARED;
|
||||
else if (*s == 'n')
|
||||
parser->curr_state = transaction_t::UNCLEARED;
|
||||
else
|
||||
parser->curr_state = transaction_t::PENDING;
|
||||
break;
|
||||
|
||||
case gnucash_parser_t::XACT_VALUE: {
|
||||
int precision;
|
||||
assert(parser->entry_comm);
|
||||
parser->curr_value = parser->convert_number(string(s, len), &precision);
|
||||
parser->curr_value.set_commodity(*parser->entry_comm);
|
||||
|
||||
if (precision > parser->entry_comm->precision())
|
||||
parser->entry_comm->set_precision(precision);
|
||||
break;
|
||||
}
|
||||
|
||||
case gnucash_parser_t::XACT_QUANTITY:
|
||||
parser->curr_quant = parser->convert_number(string(s, len));
|
||||
break;
|
||||
|
||||
case gnucash_parser_t::XACT_ACCOUNT: {
|
||||
transaction_t * xact = parser->curr_entry->transactions.back();
|
||||
|
||||
accounts_map::iterator i =
|
||||
parser->accounts_by_id.find(string(s, len));
|
||||
if (i != parser->accounts_by_id.end()) {
|
||||
xact->account = (*i).second;
|
||||
} else {
|
||||
xact->account = parser->curr_journal->find_account("<Unknown>");
|
||||
|
||||
parser->have_error = (string("Could not find account ") +
|
||||
string(s, len));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case gnucash_parser_t::XACT_NOTE:
|
||||
parser->curr_entry->transactions.back()->note = string(s, len);
|
||||
break;
|
||||
|
||||
case gnucash_parser_t::NO_ACTION:
|
||||
case gnucash_parser_t::ALMOST_ENTRY_DATE:
|
||||
case gnucash_parser_t::XACT_AMOUNT:
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool gnucash_parser_t::test(std::istream& in) const
|
||||
{
|
||||
char buf[5];
|
||||
in.read(buf, 5);
|
||||
in.clear();
|
||||
in.seekg(0, std::ios::beg);
|
||||
|
||||
return std::strncmp(buf, "<?xml", 5) == 0;
|
||||
}
|
||||
|
||||
unsigned int gnucash_parser_t::parse(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master,
|
||||
const optional<path>& original_file)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
|
||||
// This is the date format used by Gnucash, so override whatever the
|
||||
// user specified.
|
||||
//
|
||||
// jww (2006-09-13): Make this parser local somehow.
|
||||
//date_t::input_format = "%Y-%m-%d %H:%M:%S %z";
|
||||
|
||||
count = 0;
|
||||
action = NO_ACTION;
|
||||
curr_journal = journal;
|
||||
master_account = master ? master : journal->master;
|
||||
curr_account = NULL;
|
||||
curr_entry = NULL;
|
||||
curr_comm = NULL;
|
||||
entry_comm = NULL;
|
||||
curr_state = transaction_t::UNCLEARED;
|
||||
|
||||
instreamp = ∈
|
||||
pathname = original_file ? *original_file : "<gnucash>";
|
||||
src_idx = journal->sources.size() - 1;
|
||||
|
||||
// GnuCash uses the USD commodity without defining it, which really
|
||||
// means $.
|
||||
commodity_t * usd = amount_t::current_pool->find_or_create("$");
|
||||
usd->set_precision(2);
|
||||
usd->add_flags(COMMODITY_STYLE_THOUSANDS);
|
||||
|
||||
offset = 2;
|
||||
expat_parser = XML_ParserCreate(NULL);
|
||||
|
||||
XML_SetElementHandler(parser, startElement, endElement);
|
||||
XML_SetCharacterDataHandler(parser, dataHandler);
|
||||
XML_SetUserData(parser, this);
|
||||
|
||||
while (in.good() && ! in.eof()) {
|
||||
beg_pos = in.tellg();
|
||||
beg_line = (XML_GetCurrentLineNumber(parser) - offset) + 1;
|
||||
|
||||
in.getline(buf, BUFSIZ - 1);
|
||||
std::strcat(buf, "\n");
|
||||
if (! XML_Parse(parser, buf, std::strlen(buf), in.eof())) {
|
||||
//unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
|
||||
const char * msg = XML_ErrorString(XML_GetErrorCode(parser));
|
||||
XML_ParserFree(parser);
|
||||
throw_(parse_error, msg);
|
||||
}
|
||||
|
||||
if (! have_error.empty()) {
|
||||
//unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
|
||||
#if 0
|
||||
// jww (2007-04-26): What is this doing?
|
||||
parse_error err(have_error);
|
||||
std::cerr << "Error: " << err.what() << std::endl;
|
||||
#endif
|
||||
have_error = "";
|
||||
}
|
||||
}
|
||||
|
||||
XML_ParserFree(parser);
|
||||
|
||||
accounts_by_id.clear();
|
||||
curr_account_id.clear();
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
} // namespace ledger
|
||||
103
src/gnucash.h
103
src/gnucash.h
|
|
@ -1,103 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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.
|
||||
*/
|
||||
|
||||
#ifndef _GNUCASH_H
|
||||
#define _GNUCASH_H
|
||||
|
||||
#include "parser.h"
|
||||
#include "journal.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
struct gnucash_parser_t : public parser_t
|
||||
{
|
||||
typedef std::map<const string, account_t *> accounts_map;
|
||||
typedef std::map<account_t *, commodity_t *> account_comm_map;
|
||||
|
||||
journal_t * curr_journal;
|
||||
account_t * master_account;
|
||||
account_t * curr_account;
|
||||
string curr_account_id;
|
||||
entry_t * curr_entry;
|
||||
commodity_t * entry_comm;
|
||||
commodity_t * curr_comm;
|
||||
amount_t curr_value;
|
||||
amount_t curr_quant;
|
||||
XML_Parser expat_parser;
|
||||
accounts_map accounts_by_id;
|
||||
account_comm_map account_comms;
|
||||
unsigned int count;
|
||||
string have_error;
|
||||
|
||||
std::istream * instreamp;
|
||||
unsigned int offset;
|
||||
XML_Parser parser;
|
||||
path pathname;
|
||||
unsigned int src_idx;
|
||||
unsigned long beg_pos;
|
||||
unsigned long beg_line;
|
||||
|
||||
transaction_t::state_t curr_state;
|
||||
|
||||
enum action_t {
|
||||
NO_ACTION,
|
||||
ACCOUNT_NAME,
|
||||
ACCOUNT_ID,
|
||||
ACCOUNT_PARENT,
|
||||
COMM_SYM,
|
||||
COMM_NAME,
|
||||
COMM_PREC,
|
||||
ENTRY_NUM,
|
||||
ALMOST_ENTRY_DATE,
|
||||
ENTRY_DATE,
|
||||
ENTRY_DESC,
|
||||
XACT_STATE,
|
||||
XACT_AMOUNT,
|
||||
XACT_VALUE,
|
||||
XACT_QUANTITY,
|
||||
XACT_ACCOUNT,
|
||||
XACT_NOTE
|
||||
} action;
|
||||
|
||||
public:
|
||||
virtual bool test(std::istream& in) const;
|
||||
|
||||
virtual unsigned int parse(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master = NULL,
|
||||
const optional<path>& original = none);
|
||||
|
||||
amount_t convert_number(const string& number, int * precision = NULL);
|
||||
};
|
||||
|
||||
} // namespace ledger
|
||||
|
||||
#endif // _GNUCASH_H
|
||||
|
|
@ -364,6 +364,7 @@ auto_entry_t::~auto_entry_t() {
|
|||
|
||||
void auto_entry_t::extend_entry(entry_base_t& entry, bool post)
|
||||
{
|
||||
#if 0
|
||||
transactions_list initial_xacts(entry.transactions.begin(),
|
||||
entry.transactions.end());
|
||||
|
||||
|
|
@ -400,6 +401,7 @@ void auto_entry_t::extend_entry(entry_base_t& entry, bool post)
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
account_t::~account_t()
|
||||
|
|
|
|||
|
|
@ -44,10 +44,9 @@
|
|||
#include <amount.h>
|
||||
#include <balance.h>
|
||||
#include <value.h>
|
||||
#include <xml.h>
|
||||
#include <xpath.h>
|
||||
#include <format.h>
|
||||
#include <quotes.h>
|
||||
//#include <quotes.h>
|
||||
|
||||
#include <session.h>
|
||||
#include <journal.h>
|
||||
|
|
|
|||
16
src/main.cc
16
src/main.cc
|
|
@ -186,8 +186,8 @@ static int read_and_report(report_t * report, int argc, char * argv[],
|
|||
std::cout << "Result of calculation: ";
|
||||
}
|
||||
|
||||
std::cout << expr.calc((xml::document_t *)NULL, report).
|
||||
strip_annotations() << std::endl;
|
||||
xml::document_t temp(xml::LEDGER_NODE);
|
||||
std::cout << expr.calc(temp, report).strip_annotations() << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -215,8 +215,16 @@ static int read_and_report(report_t * report, int argc, char * argv[],
|
|||
{
|
||||
textual_parser_t text_parser;
|
||||
ifstream input(session.data_file);
|
||||
|
||||
#if 1
|
||||
xml::document_t temp(xml::LEDGER_NODE);
|
||||
xml::document_builder_t builder(temp);
|
||||
text_parser.parse(input, session.data_file, builder);
|
||||
temp.print(std::cout);
|
||||
#else
|
||||
xml::xml_writer_t writer(std::cout);
|
||||
text_parser.parse(input, session.data_file, writer);
|
||||
#endif
|
||||
}
|
||||
INFO_FINISH(journal);
|
||||
return 0;
|
||||
|
|
@ -292,8 +300,8 @@ static int read_and_report(report_t * report, int argc, char * argv[],
|
|||
*out << "Result of calculation: ";
|
||||
}
|
||||
|
||||
*out << expr.calc((xml::document_t *)NULL, report).
|
||||
strip_annotations() << std::endl;
|
||||
xml::document_t temp(xml::LEDGER_NODE);
|
||||
*out << expr.calc(temp, report).strip_annotations() << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,35 +29,72 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _QUOTES_H
|
||||
#define _QUOTES_H
|
||||
|
||||
#include "amount.h"
|
||||
#include "node.h"
|
||||
#include "document.h"
|
||||
|
||||
namespace ledger {
|
||||
namespace xml {
|
||||
|
||||
class quotes_by_script
|
||||
const char * node_t::name() const
|
||||
{
|
||||
path price_db;
|
||||
time_duration pricing_leeway;
|
||||
bool& cache_dirty;
|
||||
return *document().lookup_name(name_id());
|
||||
}
|
||||
|
||||
public:
|
||||
quotes_by_script(path _price_db,
|
||||
time_duration _pricing_leeway,
|
||||
bool& _cache_dirty)
|
||||
: price_db(_price_db), pricing_leeway(_pricing_leeway),
|
||||
cache_dirty(_cache_dirty) {}
|
||||
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 << ">";
|
||||
break;
|
||||
case '&':
|
||||
out << "&";
|
||||
break;
|
||||
default:
|
||||
out << *s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual optional<amount_t>
|
||||
operator()(commodity_t& commodity,
|
||||
const optional<moment_t>& date,
|
||||
const optional<moment_t>& moment,
|
||||
const optional<moment_t>& last);
|
||||
};
|
||||
void parent_node_t::print(std::ostream& out) const
|
||||
{
|
||||
out << '<' << name();
|
||||
if (attributes) {
|
||||
typedef attributes_t::nth_index<0>::type attributes_by_order;
|
||||
foreach (const attr_pair& attr, attributes->get<0>())
|
||||
out << ' ' << document().lookup_name(attr.first)
|
||||
<< "=\"" << attr.second << "\"";
|
||||
}
|
||||
IF_VERIFY()
|
||||
out << " type=\"parent_node_t\"";
|
||||
out << '>';
|
||||
|
||||
DECLARE_EXCEPTION(download_error);
|
||||
foreach (node_t * child, *this)
|
||||
child->print(out);
|
||||
|
||||
out << "</" << name() << '>';
|
||||
}
|
||||
|
||||
void terminal_node_t::print(std::ostream& out) const
|
||||
{
|
||||
if (data.empty()) {
|
||||
out << '<' << name();
|
||||
IF_VERIFY()
|
||||
out << " type=\"terminal_node_t\"";
|
||||
out << " />";
|
||||
} else {
|
||||
out << '<' << name();
|
||||
IF_VERIFY()
|
||||
out << " type=\"terminal_node_t\"";
|
||||
out << '>';
|
||||
output_xml_string(out, text());
|
||||
out << "</" << name() << '>';
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace xml
|
||||
} // namespace ledger
|
||||
|
||||
#endif // _QUOTES_H
|
||||
276
src/node.h
Normal file
276
src/node.h
Normal file
|
|
@ -0,0 +1,276 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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.
|
||||
*/
|
||||
|
||||
#ifndef _NODE_H
|
||||
#define _NODE_H
|
||||
|
||||
#include "journal.h"
|
||||
#include "value.h"
|
||||
//#include "parser.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
class transaction_t;
|
||||
class entry_t;
|
||||
class account_t;
|
||||
class journal_t;
|
||||
|
||||
namespace xml {
|
||||
|
||||
#define XML_NODE_IS_PARENT 0x1
|
||||
|
||||
DECLARE_EXCEPTION(conversion_error);
|
||||
|
||||
class parent_node_t;
|
||||
class document_t;
|
||||
|
||||
class node_t : public supports_flags<>, public noncopyable
|
||||
{
|
||||
public:
|
||||
typedef uint_fast16_t nameid_t;
|
||||
|
||||
nameid_t name_id_;
|
||||
|
||||
protected:
|
||||
document_t& document_;
|
||||
optional<parent_node_t&> parent_;
|
||||
|
||||
typedef std::pair<nameid_t, string> attr_pair;
|
||||
|
||||
typedef multi_index_container<
|
||||
attr_pair,
|
||||
multi_index::indexed_by<
|
||||
multi_index::sequenced<>,
|
||||
multi_index::hashed_unique<
|
||||
multi_index::member<attr_pair, nameid_t, &attr_pair::first> >
|
||||
>
|
||||
> attributes_t;
|
||||
|
||||
optional<attributes_t> attributes;
|
||||
|
||||
public:
|
||||
node_t(nameid_t _name_id, document_t& _document,
|
||||
const optional<parent_node_t&>& _parent = none, flags_t _flags = 0)
|
||||
: supports_flags<>(_flags), name_id_(_name_id),
|
||||
document_(_document), parent_(_parent) {
|
||||
TRACE_CTOR(node_t, "document_t&, parent_node_t&, nameid_t, flags_t");
|
||||
}
|
||||
|
||||
virtual ~node_t() {
|
||||
TRACE_DTOR(node_t);
|
||||
}
|
||||
|
||||
bool is_parent_node() const {
|
||||
return has_flags(XML_NODE_IS_PARENT);
|
||||
}
|
||||
parent_node_t& as_parent_node() {
|
||||
if (! is_parent_node())
|
||||
throw_(std::logic_error, "Request to cast leaf node to a parent node");
|
||||
return *polymorphic_downcast<parent_node_t *>(this);
|
||||
}
|
||||
const parent_node_t& as_parent_node() const {
|
||||
if (! is_parent_node())
|
||||
throw_(std::logic_error, "Request to cast leaf node to a parent node");
|
||||
return *polymorphic_downcast<const parent_node_t *>(this);
|
||||
}
|
||||
|
||||
virtual value_t to_value() const = 0;
|
||||
virtual void print(std::ostream& out) const = 0;
|
||||
|
||||
const char * name() const;
|
||||
nameid_t name_id() const {
|
||||
return name_id_;
|
||||
}
|
||||
|
||||
document_t& document() const {
|
||||
return document_;
|
||||
}
|
||||
optional<parent_node_t&> parent() const {
|
||||
return parent_;
|
||||
}
|
||||
|
||||
void set_attr(const nameid_t _name_id, const char * value) {
|
||||
if (! attributes)
|
||||
attributes = attributes_t();
|
||||
attributes->push_back(attr_pair(_name_id, value));
|
||||
}
|
||||
optional<const string&> get_attr(const nameid_t _name_id) {
|
||||
if (attributes) {
|
||||
typedef attributes_t::nth_index<1>::type attributes_by_name;
|
||||
|
||||
attributes_by_name& name_index = attributes->get<1>();
|
||||
attributes_by_name::iterator i = name_index.find(_name_id);
|
||||
if (i != name_index.end())
|
||||
return (*i).second;
|
||||
}
|
||||
return none;
|
||||
}
|
||||
};
|
||||
|
||||
class parent_node_t : public node_t
|
||||
{
|
||||
typedef multi_index_container<
|
||||
node_t *,
|
||||
multi_index::indexed_by<
|
||||
multi_index::sequenced<>,
|
||||
multi_index::hashed_non_unique<
|
||||
multi_index::member<node_t, nameid_t, &node_t::name_id_> >,
|
||||
multi_index::hashed_unique<multi_index::identity<node_t *> >
|
||||
>
|
||||
> children_t;
|
||||
|
||||
children_t children;
|
||||
|
||||
public:
|
||||
typedef children_t::nth_index<0>::type children_by_order;
|
||||
typedef children_t::nth_index<1>::type children_by_nameid;
|
||||
typedef children_t::nth_index<2>::type children_by_ptr;
|
||||
|
||||
parent_node_t(nameid_t _name_id, document_t& _document,
|
||||
const optional<parent_node_t&>& _parent = none)
|
||||
: node_t(_name_id, _document, _parent, XML_NODE_IS_PARENT) {
|
||||
TRACE_CTOR(parent_node_t, "document_t *, parent_node_t *");
|
||||
}
|
||||
virtual ~parent_node_t() {
|
||||
TRACE_DTOR(parent_node_t);
|
||||
clear_children();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T * create_child(nameid_t _name_id) {
|
||||
T * child = new T(_name_id, document(), *this);
|
||||
children.push_back(child);
|
||||
}
|
||||
|
||||
void delete_child(node_t * child) {
|
||||
children_by_ptr& ptr_index = children.get<2>();
|
||||
children_by_ptr::iterator i = ptr_index.find(child);
|
||||
if (i == ptr_index.end())
|
||||
throw_(std::logic_error, "Request to delete node which is not a child");
|
||||
node_t * ptr = *i;
|
||||
ptr_index.erase(i);
|
||||
checked_delete(ptr);
|
||||
}
|
||||
|
||||
struct match_nameid {
|
||||
nameid_t nameid;
|
||||
match_nameid(nameid_t _nameid) : nameid(_nameid) {}
|
||||
bool operator()(const node_t * node) const {
|
||||
return node->name_id() == nameid;
|
||||
}
|
||||
};
|
||||
|
||||
typedef children_by_order::iterator iterator;
|
||||
typedef children_by_order::iterator const_iterator;
|
||||
|
||||
children_by_order::iterator begin() {
|
||||
return children.get<0>().begin();
|
||||
}
|
||||
children_by_order::const_iterator begin() const {
|
||||
return children.get<0>().begin();
|
||||
}
|
||||
children_by_order::iterator end() {
|
||||
return children.get<0>().end();
|
||||
}
|
||||
children_by_order::const_iterator end() const {
|
||||
return children.get<0>().end();
|
||||
}
|
||||
|
||||
children_by_nameid::iterator begin(nameid_t _name_id) {
|
||||
return std::find_if(children.get<1>().begin(),
|
||||
children.get<1>().end(), match_nameid(_name_id));
|
||||
}
|
||||
children_by_nameid::const_iterator begin(nameid_t _name_id) const {
|
||||
return std::find_if(children.get<1>().begin(),
|
||||
children.get<1>().end(), match_nameid(_name_id));
|
||||
}
|
||||
children_by_nameid::iterator end(nameid_t) {
|
||||
return children.get<1>().end();
|
||||
}
|
||||
children_by_nameid::const_iterator end(nameid_t) const {
|
||||
return children.get<1>().end();
|
||||
}
|
||||
|
||||
void clear_children() {
|
||||
typedef children_t::nth_index<0>::type children_by_index;
|
||||
|
||||
children_by_index& child_index = children.get<0>();
|
||||
for (children_by_index::iterator i = child_index.begin();
|
||||
i != child_index.end();
|
||||
i++)
|
||||
checked_delete(*i);
|
||||
|
||||
children.clear();
|
||||
}
|
||||
|
||||
virtual value_t to_value() const {
|
||||
throw_(std::logic_error, "Cannot convert parent node to a value");
|
||||
}
|
||||
|
||||
void print(std::ostream& out) const;
|
||||
};
|
||||
|
||||
class terminal_node_t : public node_t
|
||||
{
|
||||
string data;
|
||||
|
||||
public:
|
||||
terminal_node_t(nameid_t _name_id, document_t& _document,
|
||||
const optional<parent_node_t&>& _parent = none)
|
||||
: node_t(_name_id, _document, _parent)
|
||||
{
|
||||
TRACE_CTOR(terminal_node_t, "document_t *, parent_node_t *");
|
||||
}
|
||||
virtual ~terminal_node_t() {
|
||||
TRACE_DTOR(terminal_node_t);
|
||||
}
|
||||
|
||||
const char * text() const {
|
||||
return data.c_str();
|
||||
}
|
||||
void set_text(const string& _data) {
|
||||
data = _data;
|
||||
}
|
||||
void set_text(const char * _data) {
|
||||
data = _data;
|
||||
}
|
||||
|
||||
virtual value_t to_value() const {
|
||||
return text();
|
||||
}
|
||||
|
||||
void print(std::ostream& out) const;
|
||||
};
|
||||
|
||||
} // namespace xml
|
||||
} // namespace ledger
|
||||
|
||||
#endif // _NODE_H
|
||||
246
src/ofx.cc
246
src/ofx.cc
|
|
@ -1,246 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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 "ofx.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
typedef std::map<const string, account_t *> accounts_map;
|
||||
typedef std::map<const string, commodity_t *> commodities_map;
|
||||
|
||||
journal_t * curr_journal;
|
||||
accounts_map ofx_accounts;
|
||||
commodities_map ofx_account_currencies;
|
||||
commodities_map ofx_securities;
|
||||
account_t * master_account;
|
||||
|
||||
int ofx_proc_statement_cb(struct OfxStatementData data, void * statement_data)
|
||||
{
|
||||
}
|
||||
|
||||
int ofx_proc_account_cb(struct OfxAccountData data, void * account_data)
|
||||
{
|
||||
if (! data.account_id_valid)
|
||||
return -1;
|
||||
|
||||
DEBUG("ledger.ofx.parse", "account " << data.account_name);
|
||||
account_t * account = new account_t(master_account, data.account_name);
|
||||
curr_journal->add_account(account);
|
||||
ofx_accounts.insert(accounts_pair(data.account_id, account));
|
||||
|
||||
if (data.currency_valid) {
|
||||
commodity_t * commodity = commodity_t::find_or_create(data.currency);
|
||||
commodity->add_flags(COMMODITY_STYLE_SUFFIXED | COMMODITY_STYLE_SEPARATED);
|
||||
|
||||
commodities_map::iterator i = ofx_account_currencies.find(data.account_id);
|
||||
if (i == ofx_account_currencies.end())
|
||||
ofx_account_currencies.insert(commodities_pair(data.account_id,
|
||||
commodity));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ofx_proc_transaction_cb(struct OfxTransactionData data,
|
||||
void * transaction_data)
|
||||
{
|
||||
if (! data.account_id_valid || ! data.units_valid)
|
||||
return -1;
|
||||
|
||||
accounts_map::iterator i = ofx_accounts.find(data.account_id);
|
||||
assert(i != ofx_accounts.end());
|
||||
account_t * account = (*i).second;
|
||||
|
||||
entry_t * entry = new entry_t;
|
||||
|
||||
entry->add_transaction(new transaction_t(account));
|
||||
transaction_t * xact = entry->transactions.back();
|
||||
|
||||
// get the account's default currency
|
||||
commodities_map::iterator ac = ofx_account_currencies.find(data.account_id);
|
||||
assert(ac != ofx_account_currencies.end());
|
||||
commodity_t * default_commodity = (*ac).second;
|
||||
|
||||
std::ostringstream stream;
|
||||
stream << - data.units;
|
||||
|
||||
// jww (2005-02-09): what if the amount contains fees?
|
||||
|
||||
if (data.unique_id_valid) {
|
||||
commodities_map::iterator s = ofx_securities.find(data.unique_id);
|
||||
assert(s != ofx_securities.end());
|
||||
xact->amount = stream.str() + " " + (*s).second->base_symbol();
|
||||
} else {
|
||||
xact->amount = stream.str() + " " + default_commodity->base_symbol();
|
||||
}
|
||||
|
||||
if (data.unitprice_valid && data.unitprice != 1.0) {
|
||||
std::ostringstream cstream;
|
||||
stream << - data.unitprice << " " << default_commodity->base_symbol();
|
||||
xact->cost = new amount_t(stream.str());
|
||||
}
|
||||
|
||||
DEBUG("ofx.parse", "xact " << xact->amount << " from " << *xact->account);
|
||||
|
||||
if (data.date_initiated_valid)
|
||||
entry->_date = data.date_initiated;
|
||||
else if (data.date_posted_valid)
|
||||
entry->_date = data.date_posted;
|
||||
|
||||
if (data.check_number_valid)
|
||||
entry->code = data.check_number;
|
||||
else if (data.reference_number_valid)
|
||||
entry->code = data.reference_number;
|
||||
|
||||
if (data.name_valid)
|
||||
entry->payee = data.name;
|
||||
|
||||
if (data.memo_valid)
|
||||
xact->note = data.memo;
|
||||
|
||||
// jww (2005-02-09): check for fi_id_corrected? or is this handled
|
||||
// by the library?
|
||||
|
||||
// Balance all entries into <Unknown>, since it is not specified.
|
||||
account = curr_journal->find_account("<Unknown>");
|
||||
entry->add_transaction(new transaction_t(account));
|
||||
|
||||
if (! curr_journal->add_entry(entry)) {
|
||||
print_entry(std::cerr, *entry);
|
||||
#if 0
|
||||
// jww (2005-02-09): uncomment
|
||||
have_error = "The above entry does not balance";
|
||||
#endif
|
||||
checked_delete(entry);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ofx_proc_security_cb(struct OfxSecurityData data, void * security_data)
|
||||
{
|
||||
if (! data.unique_id_valid)
|
||||
return -1;
|
||||
|
||||
string symbol;
|
||||
if (data.ticker_valid)
|
||||
symbol = data.ticker;
|
||||
else if (data.currency_valid)
|
||||
symbol = data.currency;
|
||||
else
|
||||
return -1;
|
||||
|
||||
commodity_t * commodity = commodity_t::find_or_create(symbol);
|
||||
commodity->add_flags(COMMODITY_STYLE_SUFFIXED | COMMODITY_STYLE_SEPARATED);
|
||||
|
||||
if (data.secname_valid)
|
||||
commodity->set_name(data.secname);
|
||||
|
||||
if (data.memo_valid)
|
||||
commodity->set_note(data.memo);
|
||||
|
||||
commodities_map::iterator i = ofx_securities.find(data.unique_id);
|
||||
if (i == ofx_securities.end()) {
|
||||
DEBUG("ledger.ofx.parse", "security " << symbol);
|
||||
ofx_securities.insert(commodities_pair(data.unique_id, commodity));
|
||||
}
|
||||
|
||||
// jww (2005-02-09): What is the commodity for data.unitprice?
|
||||
if (data.date_unitprice_valid && data.unitprice_valid) {
|
||||
DEBUG("ledger.ofx.parse", " price " << data.unitprice);
|
||||
commodity->add_price(data.date_unitprice, amount_t(data.unitprice));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ofx_proc_status_cb(struct OfxStatusData data, void * status_data)
|
||||
{
|
||||
}
|
||||
|
||||
bool ofx_parser_t::test(std::istream& in) const
|
||||
{
|
||||
char buf[80];
|
||||
|
||||
in.getline(buf, 79);
|
||||
if (std::strncmp(buf, "OFXHEADER", 9) == 0) {
|
||||
in.clear();
|
||||
in.seekg(0, std::ios::beg);
|
||||
return true;
|
||||
}
|
||||
else if (std::strncmp(buf, "<?xml", 5) != 0) {
|
||||
in.clear();
|
||||
in.seekg(0, std::ios::beg);
|
||||
return false;
|
||||
}
|
||||
|
||||
in.getline(buf, 79);
|
||||
if (std::strncmp(buf, "<?OFX", 5) != 0 &&
|
||||
std::strncmp(buf, "<?ofx", 5) != 0) {
|
||||
in.clear();
|
||||
in.seekg(0, std::ios::beg);
|
||||
return false;
|
||||
}
|
||||
|
||||
in.clear();
|
||||
in.seekg(0, std::ios::beg);
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int ofx_parser_t::parse(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master,
|
||||
const string * original_file)
|
||||
{
|
||||
if (! original_file)
|
||||
return 0;
|
||||
|
||||
curr_journal = journal;
|
||||
master_account = master ? master : journal->master;
|
||||
|
||||
LibofxContextPtr libofx_context = libofx_get_new_context();
|
||||
|
||||
ofx_set_statement_cb (libofx_context, ofx_proc_statement_cb, 0);
|
||||
ofx_set_account_cb (libofx_context, ofx_proc_account_cb, 0);
|
||||
ofx_set_transaction_cb(libofx_context, ofx_proc_transaction_cb, 0);
|
||||
ofx_set_security_cb (libofx_context, ofx_proc_security_cb, 0);
|
||||
ofx_set_status_cb (libofx_context, ofx_proc_status_cb, 0);
|
||||
|
||||
// The processing is done by way of callbacks, which are all defined
|
||||
// above.
|
||||
libofx_proc_file(libofx_context, original_file->c_str(), AUTODETECT);
|
||||
|
||||
libofx_free_context(libofx_context);
|
||||
|
||||
return 1; // jww (2005-02-09): count;
|
||||
}
|
||||
|
||||
} // namespace ledger
|
||||
52
src/ofx.h
52
src/ofx.h
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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.
|
||||
*/
|
||||
|
||||
#ifndef _OFX_H
|
||||
#define _OFX_H
|
||||
|
||||
#include "parser.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
class ofx_parser_t : public parser_t
|
||||
{
|
||||
public:
|
||||
virtual bool test(std::istream& in) const;
|
||||
|
||||
virtual unsigned int parse(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master = NULL,
|
||||
const optional<path>& original = none);
|
||||
};
|
||||
|
||||
} // namespace ledger
|
||||
|
||||
#endif // _OFX_H
|
||||
|
|
@ -1,233 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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.
|
||||
*/
|
||||
|
||||
using namespace boost::python;
|
||||
using namespace ledger;
|
||||
|
||||
unsigned int balance_len(balance_t& bal)
|
||||
{
|
||||
return bal.amounts.size();
|
||||
}
|
||||
|
||||
amount_t balance_getitem(balance_t& bal, int i)
|
||||
{
|
||||
std::size_t len = bal.amounts.size();
|
||||
|
||||
if (abs(i) >= len) {
|
||||
PyErr_SetString(PyExc_IndexError, "Index out of range");
|
||||
throw_error_already_set();
|
||||
}
|
||||
|
||||
int x = i < 0 ? len + i : i;
|
||||
balance_t::amounts_map::iterator elem = bal.amounts.begin();
|
||||
while (--x >= 0)
|
||||
elem++;
|
||||
|
||||
return (*elem).second;
|
||||
}
|
||||
|
||||
unsigned int balance_pair_len(balance_pair_t& bal_pair)
|
||||
{
|
||||
return balance_len(bal_pair.quantity);
|
||||
}
|
||||
|
||||
amount_t balance_pair_getitem(balance_pair_t& bal_pair, int i)
|
||||
{
|
||||
return balance_getitem(bal_pair.quantity, i);
|
||||
}
|
||||
|
||||
void export_balance()
|
||||
{
|
||||
class_< balance_t > ("Balance")
|
||||
.def(init<balance_t>())
|
||||
.def(init<amount_t>())
|
||||
.def(init<long>())
|
||||
.def(init<unsigned long>())
|
||||
.def(init<double>())
|
||||
|
||||
.def(self += self)
|
||||
.def(self += other<amount_t>())
|
||||
.def(self += long())
|
||||
.def(self + self)
|
||||
.def(self + other<amount_t>())
|
||||
.def(self + long())
|
||||
.def(self -= self)
|
||||
.def(self -= other<amount_t>())
|
||||
.def(self -= long())
|
||||
.def(self - self)
|
||||
.def(self - other<amount_t>())
|
||||
.def(self - long())
|
||||
.def(self *= self)
|
||||
.def(self *= other<amount_t>())
|
||||
.def(self *= long())
|
||||
.def(self * self)
|
||||
.def(self * other<amount_t>())
|
||||
.def(self * long())
|
||||
.def(self /= self)
|
||||
.def(self /= other<amount_t>())
|
||||
.def(self /= long())
|
||||
.def(self / self)
|
||||
.def(self / other<amount_t>())
|
||||
.def(self / long())
|
||||
.def(- self)
|
||||
|
||||
.def(self < self)
|
||||
.def(self < other<amount_t>())
|
||||
.def(self < long())
|
||||
.def(self <= self)
|
||||
.def(self <= other<amount_t>())
|
||||
.def(self <= long())
|
||||
.def(self > self)
|
||||
.def(self > other<amount_t>())
|
||||
.def(self > long())
|
||||
.def(self >= self)
|
||||
.def(self >= other<amount_t>())
|
||||
.def(self >= long())
|
||||
.def(self == self)
|
||||
.def(self == other<amount_t>())
|
||||
.def(self == long())
|
||||
.def(self != self)
|
||||
.def(self != other<amount_t>())
|
||||
.def(self != long())
|
||||
.def(! self)
|
||||
|
||||
.def(self_ns::str(self))
|
||||
|
||||
.def("__abs__", &balance_t::abs)
|
||||
.def("__len__", balance_len)
|
||||
.def("__getitem__", balance_getitem)
|
||||
|
||||
.def("valid", &balance_t::valid)
|
||||
|
||||
.def("realzero", &balance_t::realzero)
|
||||
.def("amount", &balance_t::amount)
|
||||
.def("value", &balance_t::value)
|
||||
.def("price", &balance_t::price)
|
||||
.def("date", &balance_t::date)
|
||||
.def("strip_annotations", &balance_t::strip_annotations)
|
||||
.def("write", &balance_t::write)
|
||||
.def("round", &balance_t::round)
|
||||
.def("negate", &balance_t::negate)
|
||||
.def("negated", &balance_t::negated)
|
||||
;
|
||||
|
||||
class_< balance_pair_t > ("BalancePair")
|
||||
.def(init<balance_pair_t>())
|
||||
.def(init<balance_t>())
|
||||
.def(init<amount_t>())
|
||||
.def(init<long>())
|
||||
.def(init<unsigned long>())
|
||||
.def(init<double>())
|
||||
|
||||
.def(self += self)
|
||||
.def(self += other<balance_t>())
|
||||
.def(self += other<amount_t>())
|
||||
.def(self += long())
|
||||
.def(self + self)
|
||||
.def(self + other<balance_t>())
|
||||
.def(self + other<amount_t>())
|
||||
.def(self + long())
|
||||
.def(self -= self)
|
||||
.def(self -= other<balance_t>())
|
||||
.def(self -= other<amount_t>())
|
||||
.def(self -= long())
|
||||
.def(self - self)
|
||||
.def(self - other<balance_t>())
|
||||
.def(self - other<amount_t>())
|
||||
.def(self - long())
|
||||
.def(self *= self)
|
||||
.def(self *= other<balance_t>())
|
||||
.def(self *= other<amount_t>())
|
||||
.def(self *= long())
|
||||
.def(self * self)
|
||||
.def(self * other<balance_t>())
|
||||
.def(self * other<amount_t>())
|
||||
.def(self * long())
|
||||
.def(self /= self)
|
||||
.def(self /= other<balance_t>())
|
||||
.def(self /= other<amount_t>())
|
||||
.def(self /= long())
|
||||
.def(self / self)
|
||||
.def(self / other<balance_t>())
|
||||
.def(self / other<amount_t>())
|
||||
.def(self / long())
|
||||
.def(- self)
|
||||
|
||||
.def(self < self)
|
||||
.def(self < other<balance_t>())
|
||||
.def(self < other<amount_t>())
|
||||
.def(self < long())
|
||||
.def(self <= self)
|
||||
.def(self <= other<balance_t>())
|
||||
.def(self <= other<amount_t>())
|
||||
.def(self <= long())
|
||||
.def(self > self)
|
||||
.def(self > other<balance_t>())
|
||||
.def(self > other<amount_t>())
|
||||
.def(self > long())
|
||||
.def(self >= self)
|
||||
.def(self >= other<balance_t>())
|
||||
.def(self >= other<amount_t>())
|
||||
.def(self >= long())
|
||||
.def(self == self)
|
||||
.def(self == other<balance_t>())
|
||||
.def(self == other<amount_t>())
|
||||
.def(self == long())
|
||||
.def(self != self)
|
||||
.def(self != other<balance_t>())
|
||||
.def(self != other<amount_t>())
|
||||
.def(self != long())
|
||||
.def(! self)
|
||||
|
||||
.def(self_ns::str(self))
|
||||
|
||||
.def("__abs__", &balance_pair_t::abs)
|
||||
.def("__len__", balance_pair_len)
|
||||
.def("__getitem__", balance_pair_getitem)
|
||||
|
||||
.def("valid", &balance_pair_t::valid)
|
||||
|
||||
.def("realzero", &balance_pair_t::realzero)
|
||||
.def("amount", &balance_pair_t::amount)
|
||||
.def("value", &balance_pair_t::value)
|
||||
.def("price", &balance_pair_t::price)
|
||||
.def("date", &balance_pair_t::date)
|
||||
.def("strip_annotations", &balance_pair_t::strip_annotations)
|
||||
.def("write", &balance_pair_t::write)
|
||||
.def("round", &balance_pair_t::round)
|
||||
.def("negate", &balance_pair_t::negate)
|
||||
.def("negated", &balance_pair_t::negated)
|
||||
|
||||
.add_property("cost",
|
||||
make_getter(&balance_pair_t::cost,
|
||||
return_value_policy<reference_existing_object>()))
|
||||
;
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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.
|
||||
*/
|
||||
|
||||
using namespace boost::python;
|
||||
using namespace ledger;
|
||||
|
||||
void export_format()
|
||||
{
|
||||
class_< format_t > ("Format")
|
||||
.def(init<string>())
|
||||
.def("parse", &format_t::parse)
|
||||
.def("format", &format_t::format)
|
||||
;
|
||||
}
|
||||
|
|
@ -1,404 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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.
|
||||
*/
|
||||
|
||||
using namespace boost::python;
|
||||
using namespace ledger;
|
||||
|
||||
entry_t& transaction_entry(const transaction_t& xact)
|
||||
{
|
||||
return *xact.entry;
|
||||
}
|
||||
|
||||
unsigned int transactions_len(entry_base_t& entry)
|
||||
{
|
||||
return entry.transactions.size();
|
||||
}
|
||||
|
||||
transaction_t& transactions_getitem(entry_base_t& entry, int i)
|
||||
{
|
||||
static int last_index = 0;
|
||||
static entry_base_t * last_entry = NULL;
|
||||
static transactions_list::iterator elem;
|
||||
|
||||
std::size_t len = entry.transactions.size();
|
||||
|
||||
if (abs(i) >= len) {
|
||||
PyErr_SetString(PyExc_IndexError, "Index out of range");
|
||||
throw_error_already_set();
|
||||
}
|
||||
|
||||
if (&entry == last_entry && i == last_index + 1) {
|
||||
last_index = i;
|
||||
return **++elem;
|
||||
}
|
||||
|
||||
int x = i < 0 ? len + i : i;
|
||||
elem = entry.transactions.begin();
|
||||
while (--x >= 0)
|
||||
elem++;
|
||||
|
||||
last_entry = &entry;
|
||||
last_index = i;
|
||||
|
||||
return **elem;
|
||||
}
|
||||
|
||||
unsigned int entries_len(journal_t& journal)
|
||||
{
|
||||
return journal.entries.size();
|
||||
}
|
||||
|
||||
entry_t& entries_getitem(journal_t& journal, int i)
|
||||
{
|
||||
static int last_index = 0;
|
||||
static journal_t * last_journal = NULL;
|
||||
static entries_list::iterator elem;
|
||||
|
||||
std::size_t len = journal.entries.size();
|
||||
|
||||
if (abs(i) >= len) {
|
||||
PyErr_SetString(PyExc_IndexError, "Index out of range");
|
||||
throw_error_already_set();
|
||||
}
|
||||
|
||||
if (&journal == last_journal && i == last_index + 1) {
|
||||
last_index = i;
|
||||
return **++elem;
|
||||
}
|
||||
|
||||
int x = i < 0 ? len + i : i;
|
||||
elem = journal.entries.begin();
|
||||
while (--x >= 0)
|
||||
elem++;
|
||||
|
||||
last_journal = &journal;
|
||||
last_index = i;
|
||||
|
||||
return **elem;
|
||||
}
|
||||
|
||||
unsigned int accounts_len(account_t& account)
|
||||
{
|
||||
return account.accounts.size();
|
||||
}
|
||||
|
||||
account_t& accounts_getitem(account_t& account, int i)
|
||||
{
|
||||
static int last_index = 0;
|
||||
static account_t * last_account = NULL;
|
||||
static accounts_map::iterator elem;
|
||||
|
||||
std::size_t len = account.accounts.size();
|
||||
|
||||
if (abs(i) >= len) {
|
||||
PyErr_SetString(PyExc_IndexError, "Index out of range");
|
||||
throw_error_already_set();
|
||||
}
|
||||
|
||||
if (&account == last_account && i == last_index + 1) {
|
||||
last_index = i;
|
||||
return *(*++elem).second;
|
||||
}
|
||||
|
||||
int x = i < 0 ? len + i : i;
|
||||
elem = account.accounts.begin();
|
||||
while (--x >= 0)
|
||||
elem++;
|
||||
|
||||
last_account = &account;
|
||||
last_index = i;
|
||||
|
||||
return *(*elem).second;
|
||||
}
|
||||
|
||||
PyObject * py_account_get_data(account_t& account)
|
||||
{
|
||||
return (PyObject *) account.data;
|
||||
}
|
||||
|
||||
void py_account_set_data(account_t& account, PyObject * obj)
|
||||
{
|
||||
account.data = obj;
|
||||
}
|
||||
|
||||
account_t * py_find_account_1(journal_t& journal, const string& name)
|
||||
{
|
||||
return journal.find_account(name);
|
||||
}
|
||||
|
||||
account_t * py_find_account_2(journal_t& journal, const string& name,
|
||||
const bool auto_create)
|
||||
{
|
||||
return journal.find_account(name, auto_create);
|
||||
}
|
||||
|
||||
bool py_add_entry(journal_t& journal, entry_t * entry) {
|
||||
return journal.add_entry(new entry_t(*entry));
|
||||
}
|
||||
|
||||
void py_add_transaction(entry_base_t& entry, transaction_t * xact) {
|
||||
return entry.add_transaction(new transaction_t(*xact));
|
||||
}
|
||||
|
||||
struct entry_base_wrap : public entry_base_t
|
||||
{
|
||||
PyObject * self;
|
||||
entry_base_wrap(PyObject * self_) : self(self_) {}
|
||||
|
||||
virtual bool valid() const {
|
||||
return call_method<bool>(self, "valid");
|
||||
}
|
||||
};
|
||||
|
||||
struct py_entry_finalizer_t : public entry_finalizer_t {
|
||||
object pyobj;
|
||||
py_entry_finalizer_t() {}
|
||||
py_entry_finalizer_t(object obj) : pyobj(obj) {}
|
||||
py_entry_finalizer_t(const py_entry_finalizer_t& other)
|
||||
: pyobj(other.pyobj) {}
|
||||
virtual bool operator()(entry_t& entry, bool post) {
|
||||
return call<bool>(pyobj.ptr(), entry, post);
|
||||
}
|
||||
};
|
||||
|
||||
std::list<py_entry_finalizer_t> py_finalizers;
|
||||
|
||||
void py_add_entry_finalizer(journal_t& journal, object x)
|
||||
{
|
||||
py_finalizers.push_back(py_entry_finalizer_t(x));
|
||||
journal.add_entry_finalizer(&py_finalizers.back());
|
||||
}
|
||||
|
||||
void py_remove_entry_finalizer(journal_t& journal, object x)
|
||||
{
|
||||
for (std::list<py_entry_finalizer_t>::iterator i = py_finalizers.begin();
|
||||
i != py_finalizers.end();
|
||||
i++)
|
||||
if ((*i).pyobj == x) {
|
||||
journal.remove_entry_finalizer(&(*i));
|
||||
py_finalizers.erase(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void py_run_entry_finalizers(journal_t& journal, entry_t& entry, bool post)
|
||||
{
|
||||
run_hooks(journal.entry_finalize_hooks, entry, post);
|
||||
}
|
||||
|
||||
#define EXC_TRANSLATOR(type) \
|
||||
void exc_translate_ ## type(const type& err) { \
|
||||
PyErr_SetString(PyExc_RuntimeError, err.what()); \
|
||||
}
|
||||
|
||||
EXC_TRANSLATOR(balance_error)
|
||||
EXC_TRANSLATOR(interval_expr_error)
|
||||
EXC_TRANSLATOR(format_error)
|
||||
EXC_TRANSLATOR(parse_error)
|
||||
|
||||
value_t py_transaction_amount(transaction_t * xact) {
|
||||
return value_t(xact->amount);
|
||||
}
|
||||
|
||||
transaction_t::state_t py_entry_state(entry_t * entry) {
|
||||
transaction_t::state_t state;
|
||||
if (entry->get_state(&state))
|
||||
return state;
|
||||
else
|
||||
return transaction_t::UNCLEARED;
|
||||
}
|
||||
|
||||
void export_journal()
|
||||
{
|
||||
scope().attr("TRANSACTION_NORMAL") = TRANSACTION_NORMAL;
|
||||
scope().attr("TRANSACTION_VIRTUAL") = TRANSACTION_VIRTUAL;
|
||||
scope().attr("TRANSACTION_BALANCE") = TRANSACTION_BALANCE;
|
||||
scope().attr("TRANSACTION_AUTO") = TRANSACTION_AUTO;
|
||||
scope().attr("TRANSACTION_BULK_ALLOC") = TRANSACTION_BULK_ALLOC;
|
||||
scope().attr("TRANSACTION_CALCULATED") = TRANSACTION_CALCULATED;
|
||||
|
||||
enum_< transaction_t::state_t > ("State")
|
||||
.value("Uncleared", transaction_t::UNCLEARED)
|
||||
.value("Cleared", transaction_t::CLEARED)
|
||||
.value("Pending", transaction_t::PENDING)
|
||||
;
|
||||
|
||||
class_< transaction_t > ("Transaction")
|
||||
.def(init<optional<account_t *> >())
|
||||
.def(init<account_t *, amount_t, optional<unsigned int, const string&> >())
|
||||
|
||||
.def(self == self)
|
||||
.def(self != self)
|
||||
|
||||
.add_property("entry",
|
||||
make_getter(&transaction_t::entry,
|
||||
return_value_policy<reference_existing_object>()))
|
||||
.add_property("account",
|
||||
make_getter(&transaction_t::account,
|
||||
return_value_policy<reference_existing_object>()))
|
||||
|
||||
.add_property("amount", &py_transaction_amount)
|
||||
.def_readonly("amount_expr", &transaction_t::amount_expr)
|
||||
.add_property("cost",
|
||||
make_getter(&transaction_t::cost,
|
||||
return_internal_reference<1>()))
|
||||
.def_readonly("cost_expr", &transaction_t::cost_expr)
|
||||
|
||||
.def_readwrite("state", &transaction_t::state)
|
||||
.def_readwrite("flags", &transaction_t::flags)
|
||||
.def_readwrite("note", &transaction_t::note)
|
||||
|
||||
.def_readonly("beg_pos", &transaction_t::beg_pos)
|
||||
.def_readonly("beg_line", &transaction_t::beg_line)
|
||||
.def_readonly("end_pos", &transaction_t::end_pos)
|
||||
.def_readonly("end_line", &transaction_t::end_line)
|
||||
|
||||
.def("actual_date", &transaction_t::actual_date)
|
||||
.def("effective_date", &transaction_t::effective_date)
|
||||
.def("date", &transaction_t::date)
|
||||
|
||||
.def("use_effective_date", &transaction_t::use_effective_date)
|
||||
|
||||
.def("valid", &transaction_t::valid)
|
||||
;
|
||||
|
||||
class_< account_t >
|
||||
("Account", init<optional<account_t *, string, string> >()
|
||||
[with_custodian_and_ward<1, 2>()])
|
||||
.def(self == self)
|
||||
.def(self != self)
|
||||
|
||||
.def(self_ns::str(self))
|
||||
|
||||
.def("__len__", accounts_len)
|
||||
.def("__getitem__", accounts_getitem, return_internal_reference<1>())
|
||||
|
||||
.add_property("journal",
|
||||
make_getter(&account_t::journal,
|
||||
return_value_policy<reference_existing_object>()))
|
||||
.add_property("parent",
|
||||
make_getter(&account_t::parent,
|
||||
return_value_policy<reference_existing_object>()))
|
||||
.def_readwrite("name", &account_t::name)
|
||||
.def_readwrite("note", &account_t::note)
|
||||
.def_readonly("depth", &account_t::depth)
|
||||
.add_property("data", py_account_get_data, py_account_set_data)
|
||||
.def_readonly("ident", &account_t::ident)
|
||||
|
||||
.def("fullname", &account_t::fullname)
|
||||
|
||||
.def("add_account", &account_t::add_account)
|
||||
.def("remove_account", &account_t::remove_account)
|
||||
|
||||
.def("find_account", &account_t::find_account,
|
||||
return_value_policy<reference_existing_object>())
|
||||
|
||||
.def("valid", &account_t::valid)
|
||||
;
|
||||
|
||||
class_< journal_t > ("Journal")
|
||||
.def(self == self)
|
||||
.def(self != self)
|
||||
|
||||
.def("__len__", entries_len)
|
||||
.def("__getitem__", entries_getitem, return_internal_reference<1>())
|
||||
|
||||
.add_property("master", make_getter(&journal_t::master,
|
||||
return_internal_reference<1>()))
|
||||
.add_property("basket", make_getter(&journal_t::basket,
|
||||
return_internal_reference<1>()))
|
||||
|
||||
.def_readonly("sources", &journal_t::sources)
|
||||
|
||||
.def_readwrite("price_db", &journal_t::price_db)
|
||||
|
||||
.def("add_account", &journal_t::add_account)
|
||||
.def("remove_account", &journal_t::remove_account)
|
||||
|
||||
.def("find_account", py_find_account_1, return_internal_reference<1>())
|
||||
.def("find_account", py_find_account_2, return_internal_reference<1>())
|
||||
.def("find_account_re", &journal_t::find_account_re,
|
||||
return_internal_reference<1>())
|
||||
|
||||
.def("add_entry", py_add_entry)
|
||||
.def("remove_entry", &journal_t::remove_entry)
|
||||
|
||||
.def("add_entry_finalizer", py_add_entry_finalizer)
|
||||
.def("remove_entry_finalizer", py_remove_entry_finalizer)
|
||||
.def("run_entry_finalizers", py_run_entry_finalizers)
|
||||
|
||||
.def("valid", &journal_t::valid)
|
||||
;
|
||||
|
||||
class_< entry_base_t, entry_base_wrap, boost::noncopyable > ("EntryBase")
|
||||
.def("__len__", transactions_len)
|
||||
.def("__getitem__", transactions_getitem,
|
||||
return_internal_reference<1>())
|
||||
|
||||
.def_readonly("journal", &entry_base_t::journal)
|
||||
|
||||
.def_readonly("src_idx", &entry_base_t::src_idx)
|
||||
.def_readonly("beg_pos", &entry_base_t::beg_pos)
|
||||
.def_readonly("beg_line", &entry_base_t::beg_line)
|
||||
.def_readonly("end_pos", &entry_base_t::end_pos)
|
||||
.def_readonly("end_line", &entry_base_t::end_line)
|
||||
|
||||
.def("add_transaction", py_add_transaction)
|
||||
.def("remove_transaction", &entry_base_t::remove_transaction)
|
||||
|
||||
.def(self == self)
|
||||
.def(self != self)
|
||||
|
||||
.def("finalize", &entry_base_t::finalize)
|
||||
.def("valid", &entry_base_t::valid)
|
||||
;
|
||||
|
||||
class_< entry_t, bases<entry_base_t> > ("Entry")
|
||||
.add_property("date", &entry_t::date)
|
||||
.add_property("effective_date", &entry_t::effective_date)
|
||||
.add_property("actual_date", &entry_t::actual_date)
|
||||
|
||||
.def_readwrite("code", &entry_t::code)
|
||||
.def_readwrite("payee", &entry_t::payee)
|
||||
|
||||
.add_property("state", &py_entry_state)
|
||||
|
||||
.def("valid", &entry_t::valid)
|
||||
;
|
||||
|
||||
#define EXC_TRANSLATE(type) \
|
||||
register_error_translator<type>(&exc_translate_ ## type);
|
||||
|
||||
EXC_TRANSLATE(balance_error);
|
||||
EXC_TRANSLATE(interval_expr_error);
|
||||
EXC_TRANSLATE(format_error);
|
||||
EXC_TRANSLATE(parse_error);
|
||||
}
|
||||
103
src/py_option.cc
103
src/py_option.cc
|
|
@ -1,103 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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.
|
||||
*/
|
||||
|
||||
using namespace boost::python;
|
||||
using namespace ledger;
|
||||
|
||||
struct py_option_t : public option_t
|
||||
{
|
||||
PyObject * self;
|
||||
|
||||
py_option_t(PyObject * self_,
|
||||
const string& long_opt,
|
||||
const bool wants_arg)
|
||||
: self(self_), option_t(long_opt, wants_arg) {}
|
||||
|
||||
virtual ~py_option_t() {}
|
||||
|
||||
virtual bool check(option_source_t source) {
|
||||
return call_method<bool>(self, "check", source);
|
||||
}
|
||||
|
||||
virtual void select(report_t * report, const char * optarg = NULL) {
|
||||
if (optarg)
|
||||
return call_method<void>(self, "select", report, optarg);
|
||||
else
|
||||
return call_method<void>(self, "select", report);
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(option_select_overloads,
|
||||
py_option_t::select, 1, 2)
|
||||
|
||||
typedef std::map<const string, object> options_map;
|
||||
|
||||
options_map options;
|
||||
|
||||
static option_t * find_option(const string& name)
|
||||
{
|
||||
options_map::const_iterator i = options.find(name);
|
||||
if (i != options.end())
|
||||
return extract<py_option_t *>((*i).second.ptr());
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void shutdown_option()
|
||||
{
|
||||
options.clear();
|
||||
}
|
||||
|
||||
void export_option()
|
||||
{
|
||||
class_< option_t, py_option_t, boost::noncopyable >
|
||||
("Option", init<const string&, bool>())
|
||||
.def_readonly("long_opt", &py_option_t::long_opt)
|
||||
.def_readonly("short_opt", &py_option_t::short_opt)
|
||||
.def_readonly("wants_arg", &py_option_t::wants_arg)
|
||||
.def_readwrite("handled", &py_option_t::handled)
|
||||
.def("check", &py_option_t::check)
|
||||
.def("select", &py_option_t::select, option_select_overloads())
|
||||
;
|
||||
|
||||
enum_< option_t::option_source_t > ("OptionSource")
|
||||
.value("InitFile", option_t::INIT_FILE)
|
||||
.value("Environment", option_t::ENVIRONMENT)
|
||||
.value("DataFile", option_t::DATA_FILE)
|
||||
.value("CommandLine", option_t::COMMAND_LINE)
|
||||
;
|
||||
|
||||
class_< options_map > ("OptionsMap")
|
||||
.def(map_indexing_suite<options_map>())
|
||||
;
|
||||
|
||||
scope().attr("options") = ptr(&options);
|
||||
}
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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 "parser.h"
|
||||
|
||||
#if 0
|
||||
#ifdef USE_BOOST_PYTHON
|
||||
|
||||
using namespace boost::python;
|
||||
using namespace ledger;
|
||||
|
||||
struct py_parser_t : public parser_t
|
||||
{
|
||||
PyObject * self;
|
||||
py_parser_t(PyObject * self_) : self(self_) {}
|
||||
|
||||
virtual bool test(std::istream& in) const {
|
||||
return call_method<bool>(self, "test", in);
|
||||
}
|
||||
|
||||
virtual repitem_t * parse(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master = NULL,
|
||||
const string * original_file = NULL) {
|
||||
return call_method<unsigned int>(self, "parse", in, journal, master,
|
||||
original_file);
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(parser_parse_overloads,
|
||||
py_parser_t::parse, 2, 4)
|
||||
|
||||
BOOST_PYTHON_FUNCTION_OVERLOADS(parse_journal_overloads, parse_journal, 2, 4)
|
||||
BOOST_PYTHON_FUNCTION_OVERLOADS(parse_journal_file_overloads,
|
||||
parse_journal_file, 2, 4)
|
||||
|
||||
void export_parser() {
|
||||
class_< parser_t, py_parser_t, boost::noncopyable > ("Parser")
|
||||
.def("test", &py_parser_t::test)
|
||||
.def("parse", &py_parser_t::parse, parser_parse_overloads())
|
||||
;
|
||||
|
||||
def("register_parser", register_parser);
|
||||
def("unregister_parser", unregister_parser);
|
||||
|
||||
def("parse_journal", parse_journal, parse_journal_overloads());
|
||||
def("parse_journal_file", parse_journal_file, parse_journal_file_overloads());
|
||||
}
|
||||
|
||||
#endif // USE_BOOST_PYTHON
|
||||
#endif
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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.
|
||||
*/
|
||||
|
||||
using namespace boost::python;
|
||||
using namespace ledger;
|
||||
|
||||
void export_report()
|
||||
{
|
||||
class_< report_t > ("Report")
|
||||
.add_property("session",
|
||||
make_getter(&report_t::session,
|
||||
return_value_policy<reference_existing_object>()))
|
||||
|
||||
.def("apply_transforms", &report_t::apply_transforms)
|
||||
;
|
||||
}
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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.
|
||||
*/
|
||||
|
||||
using namespace boost::python;
|
||||
using namespace ledger;
|
||||
|
||||
void export_session()
|
||||
{
|
||||
class_< session_t > ("Session")
|
||||
.def_readwrite("init_file", &session_t::init_file)
|
||||
.def_readwrite("data_file", &session_t::data_file)
|
||||
.def_readwrite("cache_file", &session_t::cache_file)
|
||||
.def_readwrite("price_db", &session_t::price_db)
|
||||
|
||||
.def_readwrite("balance_format", &session_t::balance_format)
|
||||
.def_readwrite("register_format", &session_t::register_format)
|
||||
.def_readwrite("wide_register_format", &session_t::wide_register_format)
|
||||
.def_readwrite("plot_amount_format", &session_t::plot_amount_format)
|
||||
.def_readwrite("plot_total_format", &session_t::plot_total_format)
|
||||
.def_readwrite("print_format", &session_t::print_format)
|
||||
.def_readwrite("write_hdr_format", &session_t::write_hdr_format)
|
||||
.def_readwrite("write_xact_format", &session_t::write_xact_format)
|
||||
.def_readwrite("equity_format", &session_t::equity_format)
|
||||
.def_readwrite("prices_format", &session_t::prices_format)
|
||||
.def_readwrite("pricesdb_format", &session_t::pricesdb_format)
|
||||
|
||||
.def_readwrite("pricing_leeway", &session_t::pricing_leeway)
|
||||
|
||||
.def_readwrite("download_quotes", &session_t::download_quotes)
|
||||
.def_readwrite("use_cache", &session_t::use_cache)
|
||||
.def_readwrite("cache_dirty", &session_t::cache_dirty)
|
||||
.def_readwrite("debug_mode", &session_t::debug_mode)
|
||||
.def_readwrite("verbose_mode", &session_t::verbose_mode)
|
||||
.def_readwrite("trace_alloc_mode", &session_t::trace_alloc_mode)
|
||||
.def_readwrite("trace_class_mode", &session_t::trace_class_mode)
|
||||
|
||||
.def_readwrite("journals", &session_t::journals)
|
||||
;
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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.
|
||||
*/
|
||||
|
||||
using namespace boost::python;
|
||||
using namespace ledger;
|
||||
|
||||
void export_transform()
|
||||
{
|
||||
class_< repitem_t > ("Transform")
|
||||
;
|
||||
}
|
||||
368
src/py_value.cc
368
src/py_value.cc
|
|
@ -1,368 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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.
|
||||
*/
|
||||
|
||||
using namespace boost::python;
|
||||
using namespace ledger;
|
||||
|
||||
long balance_len(balance_t& bal);
|
||||
amount_t balance_getitem(balance_t& bal, int i);
|
||||
long balance_pair_len(balance_pair_t& bal_pair);
|
||||
amount_t balance_pair_getitem(balance_pair_t& bal_pair, int i);
|
||||
|
||||
long value_len(value_t& val)
|
||||
{
|
||||
switch (val.type) {
|
||||
case value_t::BOOLEAN:
|
||||
case value_t::INTEGER:
|
||||
case value_t::DATETIME:
|
||||
case value_t::AMOUNT:
|
||||
return 1;
|
||||
|
||||
case value_t::BALANCE:
|
||||
return balance_len(*((balance_t *) val.data));
|
||||
|
||||
case value_t::BALANCE_PAIR:
|
||||
return balance_pair_len(*((balance_pair_t *) val.data));
|
||||
|
||||
case value_t::STRING:
|
||||
case value_t::XML_NODE:
|
||||
case value_t::POINTER:
|
||||
return 1;
|
||||
|
||||
case value_t::SEQUENCE:
|
||||
return (*(value_t::sequence_t **) val.data)->size();
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
amount_t value_getitem(value_t& val, int i)
|
||||
{
|
||||
std::size_t len = value_len(val);
|
||||
|
||||
if (abs(i) >= len) {
|
||||
PyErr_SetString(PyExc_IndexError, "Index out of range");
|
||||
throw_error_already_set();
|
||||
}
|
||||
|
||||
switch (val.type) {
|
||||
case value_t::BOOLEAN:
|
||||
throw_(value_error, "Cannot cast a boolean to an amount");
|
||||
|
||||
case value_t::INTEGER:
|
||||
return long(val);
|
||||
|
||||
case value_t::DATETIME:
|
||||
throw_(value_error, "Cannot cast a date/time to an amount");
|
||||
|
||||
case value_t::AMOUNT:
|
||||
return *((amount_t *) val.data);
|
||||
|
||||
case value_t::BALANCE:
|
||||
return balance_getitem(*((balance_t *) val.data), i);
|
||||
|
||||
case value_t::BALANCE_PAIR:
|
||||
return balance_pair_getitem(*((balance_pair_t *) val.data), i);
|
||||
|
||||
case value_t::STRING:
|
||||
throw_(value_error, "Cannot cast a string to an amount");
|
||||
|
||||
case value_t::XML_NODE:
|
||||
return (*(xml::node_t **) data)->to_value();
|
||||
|
||||
case value_t::POINTER:
|
||||
throw_(value_error, "Cannot cast a pointer to an amount");
|
||||
|
||||
case value_t::SEQUENCE:
|
||||
return (*(value_t::sequence_t **) val.data)[i];
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
assert(false);
|
||||
return 0L;
|
||||
}
|
||||
|
||||
double py_to_float(value_t& val)
|
||||
{
|
||||
return double(val);
|
||||
}
|
||||
|
||||
void export_value()
|
||||
{
|
||||
class_< value_t > ("value")
|
||||
.def(init<value_t>())
|
||||
.def(init<balance_pair_t>())
|
||||
.def(init<balance_t>())
|
||||
.def(init<amount_t>())
|
||||
.def(init<string>())
|
||||
.def(init<double>())
|
||||
.def(init<long>())
|
||||
.def(initmoment_t())
|
||||
|
||||
.def(self + self)
|
||||
.def(self + other<string>())
|
||||
.def(self + other<balance_pair_t>())
|
||||
.def(self + other<balance_t>())
|
||||
.def(self + other<amount_t>())
|
||||
.def(self + long())
|
||||
.def(self + double())
|
||||
|
||||
.def(other<string>() + self)
|
||||
.def(other<balance_pair_t>() + self)
|
||||
.def(other<balance_t>() + self)
|
||||
.def(other<amount_t>() + self)
|
||||
.def(long() + self)
|
||||
.def(double() + self)
|
||||
|
||||
.def(self - self)
|
||||
.def(self - other<string>())
|
||||
.def(self - other<balance_pair_t>())
|
||||
.def(self - other<balance_t>())
|
||||
.def(self - other<amount_t>())
|
||||
.def(self - long())
|
||||
.def(self - double())
|
||||
|
||||
.def(other<string>() - self)
|
||||
.def(other<balance_pair_t>() - self)
|
||||
.def(other<balance_t>() - self)
|
||||
.def(other<amount_t>() - self)
|
||||
.def(long() - self)
|
||||
.def(double() - self)
|
||||
|
||||
.def(self * self)
|
||||
.def(self * other<string>())
|
||||
.def(self * other<balance_pair_t>())
|
||||
.def(self * other<balance_t>())
|
||||
.def(self * other<amount_t>())
|
||||
.def(self * long())
|
||||
.def(self * double())
|
||||
|
||||
.def(other<string>() * self)
|
||||
.def(other<balance_pair_t>() * self)
|
||||
.def(other<balance_t>() * self)
|
||||
.def(other<amount_t>() * self)
|
||||
.def(long() * self)
|
||||
.def(double() * self)
|
||||
|
||||
.def(self / self)
|
||||
.def(self / other<string>())
|
||||
.def(self / other<balance_pair_t>())
|
||||
.def(self / other<balance_t>())
|
||||
.def(self / other<amount_t>())
|
||||
.def(self / long())
|
||||
.def(self / double())
|
||||
|
||||
.def(other<string>() / self)
|
||||
.def(other<balance_pair_t>() / self)
|
||||
.def(other<balance_t>() / self)
|
||||
.def(other<amount_t>() / self)
|
||||
.def(long() / self)
|
||||
.def(double() / self)
|
||||
|
||||
.def(- self)
|
||||
|
||||
.def(self += self)
|
||||
.def(self += other<string>())
|
||||
.def(self += other<balance_pair_t>())
|
||||
.def(self += other<balance_t>())
|
||||
.def(self += other<amount_t>())
|
||||
.def(self += long())
|
||||
.def(self += double())
|
||||
|
||||
.def(self -= self)
|
||||
.def(self -= other<string>())
|
||||
.def(self -= other<balance_pair_t>())
|
||||
.def(self -= other<balance_t>())
|
||||
.def(self -= other<amount_t>())
|
||||
.def(self -= long())
|
||||
.def(self -= double())
|
||||
|
||||
.def(self *= self)
|
||||
.def(self *= other<string>())
|
||||
.def(self *= other<balance_pair_t>())
|
||||
.def(self *= other<balance_t>())
|
||||
.def(self *= other<amount_t>())
|
||||
.def(self *= long())
|
||||
.def(self *= double())
|
||||
|
||||
.def(self /= self)
|
||||
.def(self /= other<string>())
|
||||
.def(self /= other<balance_pair_t>())
|
||||
.def(self /= other<balance_t>())
|
||||
.def(self /= other<amount_t>())
|
||||
.def(self /= long())
|
||||
.def(self /= double())
|
||||
|
||||
.def(self < self)
|
||||
.def(self < other<string>())
|
||||
.def(self < other<balance_pair_t>())
|
||||
.def(self < other<balance_t>())
|
||||
.def(self < other<amount_t>())
|
||||
.def(self < long())
|
||||
.def(self < othermoment_t())
|
||||
.def(self < double())
|
||||
|
||||
.def(other<string>() < self)
|
||||
.def(other<balance_pair_t>() < self)
|
||||
.def(other<balance_t>() < self)
|
||||
.def(other<amount_t>() < self)
|
||||
.def(long() < self)
|
||||
.def(othermoment_t() < self)
|
||||
.def(double() < self)
|
||||
|
||||
.def(self <= self)
|
||||
.def(self <= other<string>())
|
||||
.def(self <= other<balance_pair_t>())
|
||||
.def(self <= other<balance_t>())
|
||||
.def(self <= other<amount_t>())
|
||||
.def(self <= long())
|
||||
.def(self <= othermoment_t())
|
||||
.def(self <= double())
|
||||
|
||||
.def(other<string>() <= self)
|
||||
.def(other<balance_pair_t>() <= self)
|
||||
.def(other<balance_t>() <= self)
|
||||
.def(other<amount_t>() <= self)
|
||||
.def(long() <= self)
|
||||
.def(othermoment_t() <= self)
|
||||
.def(double() <= self)
|
||||
|
||||
.def(self > self)
|
||||
.def(self > other<string>())
|
||||
.def(self > other<balance_pair_t>())
|
||||
.def(self > other<balance_t>())
|
||||
.def(self > other<amount_t>())
|
||||
.def(self > long())
|
||||
.def(self > othermoment_t())
|
||||
.def(self > double())
|
||||
|
||||
.def(other<string>() > self)
|
||||
.def(other<balance_pair_t>() > self)
|
||||
.def(other<balance_t>() > self)
|
||||
.def(other<amount_t>() > self)
|
||||
.def(long() > self)
|
||||
.def(othermoment_t() > self)
|
||||
.def(double() > self)
|
||||
|
||||
.def(self >= self)
|
||||
.def(self >= other<string>())
|
||||
.def(self >= other<balance_pair_t>())
|
||||
.def(self >= other<balance_t>())
|
||||
.def(self >= other<amount_t>())
|
||||
.def(self >= long())
|
||||
.def(self >= othermoment_t())
|
||||
.def(self >= double())
|
||||
|
||||
.def(other<string>() >= self)
|
||||
.def(other<balance_pair_t>() >= self)
|
||||
.def(other<balance_t>() >= self)
|
||||
.def(other<amount_t>() >= self)
|
||||
.def(long() >= self)
|
||||
.def(othermoment_t() >= self)
|
||||
.def(double() >= self)
|
||||
|
||||
.def(self == self)
|
||||
.def(self == other<string>())
|
||||
.def(self == other<balance_pair_t>())
|
||||
.def(self == other<balance_t>())
|
||||
.def(self == other<amount_t>())
|
||||
.def(self == long())
|
||||
.def(self == othermoment_t())
|
||||
.def(self == double())
|
||||
|
||||
.def(other<string>() == self)
|
||||
.def(other<balance_pair_t>() == self)
|
||||
.def(other<balance_t>() == self)
|
||||
.def(other<amount_t>() == self)
|
||||
.def(long() == self)
|
||||
.def(othermoment_t() == self)
|
||||
.def(double() == self)
|
||||
|
||||
.def(self != self)
|
||||
.def(self != other<string>())
|
||||
.def(self != other<balance_pair_t>())
|
||||
.def(self != other<balance_t>())
|
||||
.def(self != other<amount_t>())
|
||||
.def(self != long())
|
||||
.def(self != othermoment_t())
|
||||
.def(self != double())
|
||||
|
||||
.def(other<string>() != self)
|
||||
.def(other<balance_pair_t>() != self)
|
||||
.def(other<balance_t>() != self)
|
||||
.def(other<amount_t>() != self)
|
||||
.def(long() != self)
|
||||
.def(othermoment_t() != self)
|
||||
.def(double() != self)
|
||||
|
||||
.def(! self)
|
||||
|
||||
.def(self_ns::int_(self))
|
||||
.def(self_ns::float_(self))
|
||||
.def(self_ns::str(self))
|
||||
|
||||
.def_readonly("type", &value_t::type)
|
||||
|
||||
.def("__abs__", &value_t::abs)
|
||||
.def("__len__", value_len)
|
||||
.def("__getitem__", value_getitem)
|
||||
|
||||
.def("cast", &value_t::cast)
|
||||
.def("cost", &value_t::cost)
|
||||
.def("price", &value_t::price)
|
||||
.def("date", &value_t::date)
|
||||
.def("strip_annotations", &value_t::strip_annotations)
|
||||
.def("add", &value_t::add, return_internal_reference<>())
|
||||
.def("value", &value_t::value)
|
||||
.def("round", &value_t::round)
|
||||
.def("negate", &value_t::negate)
|
||||
.def("write", &value_t::write)
|
||||
;
|
||||
|
||||
enum_< value_t::type_t > ("ValueType")
|
||||
.value("Boolean", value_t::BOOLEAN)
|
||||
.value("Integer", value_t::INTEGER)
|
||||
.value("DateTime", value_t::DATETIME)
|
||||
.value("Amount", value_t::AMOUNT)
|
||||
.value("Balance", value_t::BALANCE)
|
||||
.value("BalancePair", value_t::BALANCE_PAIR)
|
||||
.value("String", value_t::STRING)
|
||||
.value("XmlNode", value_t::XML_NODE)
|
||||
.value("Pointer", value_t::POINTER)
|
||||
.value("Sequence", value_t::SEQUENCE)
|
||||
;
|
||||
}
|
||||
110
src/py_xpath.cc
110
src/py_xpath.cc
|
|
@ -1,110 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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.
|
||||
*/
|
||||
|
||||
using namespace boost::python;
|
||||
using namespace ledger;
|
||||
|
||||
value_t py_calc_1(xpath_t::op_t& xpath_t, const details_t& item)
|
||||
{
|
||||
value_t result;
|
||||
xpath_t.calc(result, item);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
value_t py_calc(xpath_t::op_t& xpath_t, const T& item)
|
||||
{
|
||||
value_t result;
|
||||
xpath_t.calc(result, details_t(item));
|
||||
return result;
|
||||
}
|
||||
|
||||
xpath_t::op_t * py_parse_xpath_t_1(const string& str)
|
||||
{
|
||||
return parse_xpath_t(str);
|
||||
}
|
||||
|
||||
#define EXC_TRANSLATOR(type) \
|
||||
void exc_translate_ ## type(const type& err) { \
|
||||
PyErr_SetString(PyExc_RuntimeError, err.what()); \
|
||||
}
|
||||
|
||||
EXC_TRANSLATOR(xpath_t_error)
|
||||
EXC_TRANSLATOR(calc_error)
|
||||
#if 0
|
||||
EXC_TRANSLATOR(mask_error)
|
||||
#endif
|
||||
|
||||
void export_xpath()
|
||||
{
|
||||
class_< details_t > ("Details", init<const entry_t&>())
|
||||
.def(init<const transaction_t&>())
|
||||
.def(init<const account_t&>())
|
||||
.add_property("entry",
|
||||
make_getter(&details_t::entry,
|
||||
return_value_policy<reference_existing_object>()))
|
||||
.add_property("xact",
|
||||
make_getter(&details_t::xact,
|
||||
return_value_policy<reference_existing_object>()))
|
||||
.add_property("account",
|
||||
make_getter(&details_t::account,
|
||||
return_value_policy<reference_existing_object>()))
|
||||
;
|
||||
|
||||
class_< xpath_t::op_t > ("ValueExpr", init<xpath_t::op_t::kind_t>())
|
||||
.def("calc", py_calc_1)
|
||||
.def("calc", py_calc<account_t>)
|
||||
.def("calc", py_calc<entry_t>)
|
||||
.def("calc", py_calc<transaction_t>)
|
||||
;
|
||||
|
||||
def("parse_xpath_t", py_parse_xpath_t_1,
|
||||
return_value_policy<manage_new_object>());
|
||||
|
||||
class_< item_predicate<transaction_t> >
|
||||
("TransactionPredicate", init<string>())
|
||||
.def("__call__", &item_predicate<transaction_t>::operator())
|
||||
;
|
||||
|
||||
class_< item_predicate<account_t> >
|
||||
("AccountPredicate", init<string>())
|
||||
.def("__call__", &item_predicate<account_t>::operator())
|
||||
;
|
||||
|
||||
#define EXC_TRANSLATE(type) \
|
||||
register_error_translator<type>(&exc_translate_ ## type);
|
||||
|
||||
EXC_TRANSLATE(xpath_t_error);
|
||||
EXC_TRANSLATE(calc_error);
|
||||
#if 0
|
||||
EXC_TRANSLATE(mask_error);
|
||||
#endif
|
||||
}
|
||||
274
src/qif.cc
274
src/qif.cc
|
|
@ -1,274 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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 "qif.h"
|
||||
#include "journal.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
#define MAX_LINE 1024
|
||||
|
||||
static char line[MAX_LINE + 1];
|
||||
static path pathname;
|
||||
static unsigned int src_idx;
|
||||
static unsigned int linenum;
|
||||
|
||||
static inline char * get_line(std::istream& in) {
|
||||
in.getline(line, MAX_LINE);
|
||||
int len = std::strlen(line);
|
||||
if (line[len - 1] == '\r')
|
||||
line[len - 1] = '\0';
|
||||
linenum++;
|
||||
return line;
|
||||
}
|
||||
|
||||
bool qif_parser_t::test(std::istream& in) const
|
||||
{
|
||||
char magic[sizeof(unsigned int) + 1];
|
||||
in.read(magic, sizeof(unsigned int));
|
||||
magic[sizeof(unsigned int)] = '\0';
|
||||
in.clear();
|
||||
in.seekg(0, std::ios::beg);
|
||||
|
||||
return (std::strcmp(magic, "!Typ") == 0 ||
|
||||
std::strcmp(magic, "\n!Ty") == 0 ||
|
||||
std::strcmp(magic, "\r\n!T") == 0);
|
||||
}
|
||||
|
||||
unsigned int qif_parser_t::parse(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master,
|
||||
const optional<path>&)
|
||||
{
|
||||
std::auto_ptr<entry_t> entry;
|
||||
std::auto_ptr<amount_t> amount;
|
||||
|
||||
transaction_t * xact;
|
||||
unsigned int count = 0;
|
||||
account_t * misc = NULL;
|
||||
commodity_t * def_commodity = NULL;
|
||||
bool saw_splits = false;
|
||||
bool saw_category = false;
|
||||
transaction_t * total = NULL;
|
||||
|
||||
entry.reset(new entry_t);
|
||||
xact = new transaction_t(master);
|
||||
entry->add_transaction(xact);
|
||||
|
||||
pathname = journal->sources.back();
|
||||
src_idx = journal->sources.size() - 1;
|
||||
linenum = 1;
|
||||
|
||||
unsigned long beg_pos = 0;
|
||||
unsigned long beg_line = 0;
|
||||
|
||||
#define SET_BEG_POS_AND_LINE() \
|
||||
if (! beg_line) { \
|
||||
beg_pos = in.tellg(); \
|
||||
beg_line = linenum; \
|
||||
}
|
||||
|
||||
while (in.good() && ! in.eof()) {
|
||||
char c;
|
||||
in.get(c);
|
||||
switch (c) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
if (peek_next_nonws(in) != '\n') {
|
||||
get_line(in);
|
||||
throw_(parse_error, "Line begins with whitespace");
|
||||
}
|
||||
// fall through...
|
||||
|
||||
case '\n':
|
||||
linenum++;
|
||||
case '\r': // skip blank lines
|
||||
break;
|
||||
|
||||
case '!':
|
||||
get_line(in);
|
||||
|
||||
if (std::strcmp(line, "Type:Invst") == 0 ||
|
||||
std::strcmp(line, "Account") == 0 ||
|
||||
std::strcmp(line, "Type:Cat") == 0 ||
|
||||
std::strcmp(line, "Type:Class") == 0 ||
|
||||
std::strcmp(line, "Type:Memorized") == 0)
|
||||
throw_(parse_error,
|
||||
"QIF files of type " << line << " are not supported.");
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
SET_BEG_POS_AND_LINE();
|
||||
get_line(in);
|
||||
entry->_date = parse_datetime(line);
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
case '$': {
|
||||
SET_BEG_POS_AND_LINE();
|
||||
get_line(in);
|
||||
xact->amount = amount_t(line);
|
||||
|
||||
unsigned char flags = xact->amount->commodity().flags();
|
||||
unsigned char prec = xact->amount->commodity().precision();
|
||||
|
||||
if (! def_commodity) {
|
||||
def_commodity = amount_t::current_pool->find_or_create("$");
|
||||
assert(def_commodity);
|
||||
}
|
||||
xact->amount->set_commodity(*def_commodity);
|
||||
|
||||
def_commodity->add_flags(flags);
|
||||
if (prec > def_commodity->precision())
|
||||
def_commodity->set_precision(prec);
|
||||
|
||||
if (c == '$') {
|
||||
saw_splits = true;
|
||||
xact->amount->in_place_negate();
|
||||
} else {
|
||||
total = xact;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'C':
|
||||
SET_BEG_POS_AND_LINE();
|
||||
c = in.peek();
|
||||
if (c == '*' || c == 'X') {
|
||||
in.get(c);
|
||||
xact->state = transaction_t::CLEARED;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
SET_BEG_POS_AND_LINE();
|
||||
get_line(in);
|
||||
entry->code = line;
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
case 'M':
|
||||
case 'L':
|
||||
case 'S':
|
||||
case 'E': {
|
||||
SET_BEG_POS_AND_LINE();
|
||||
get_line(in);
|
||||
|
||||
switch (c) {
|
||||
case 'P':
|
||||
entry->payee = line;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
xact = new transaction_t(NULL);
|
||||
entry->add_transaction(xact);
|
||||
// fall through...
|
||||
case 'L': {
|
||||
int len = std::strlen(line);
|
||||
if (line[len - 1] == ']')
|
||||
line[len - 1] = '\0';
|
||||
xact->account = journal->find_account(line[0] == '[' ?
|
||||
line + 1 : line);
|
||||
if (c == 'L')
|
||||
saw_category = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'M':
|
||||
case 'E':
|
||||
xact->note = line;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'A':
|
||||
SET_BEG_POS_AND_LINE();
|
||||
// jww (2004-08-19): these are ignored right now
|
||||
get_line(in);
|
||||
break;
|
||||
|
||||
case '^': {
|
||||
account_t * other;
|
||||
if (xact->account == master) {
|
||||
if (! misc)
|
||||
misc = journal->find_account("Miscellaneous");
|
||||
other = misc;
|
||||
} else {
|
||||
other = master;
|
||||
}
|
||||
|
||||
if (total && saw_category) {
|
||||
if (! saw_splits)
|
||||
total->amount->in_place_negate(); // negate, to show correct flow
|
||||
else
|
||||
total->account = other;
|
||||
}
|
||||
|
||||
if (! saw_splits) {
|
||||
transaction_t * nxact = new transaction_t(other);
|
||||
// The amount doesn't need to be set because the code below
|
||||
// will balance this transaction against the other.
|
||||
entry->add_transaction(nxact);
|
||||
}
|
||||
|
||||
if (journal->add_entry(entry.get())) {
|
||||
entry->src_idx = src_idx;
|
||||
entry->beg_pos = beg_pos;
|
||||
entry->beg_line = beg_line;
|
||||
entry->end_pos = in.tellg();
|
||||
entry->end_line = linenum;
|
||||
entry.release();
|
||||
count++;
|
||||
}
|
||||
|
||||
// reset things for the next entry
|
||||
entry.reset(new entry_t);
|
||||
xact = new transaction_t(master);
|
||||
entry->add_transaction(xact);
|
||||
|
||||
saw_splits = false;
|
||||
saw_category = false;
|
||||
total = NULL;
|
||||
beg_line = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
get_line(in);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
} // namespace ledger
|
||||
52
src/qif.h
52
src/qif.h
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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.
|
||||
*/
|
||||
|
||||
#ifndef _QIF_H
|
||||
#define _QIF_H
|
||||
|
||||
#include "parser.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
class qif_parser_t : public parser_t
|
||||
{
|
||||
public:
|
||||
virtual bool test(std::istream& in) const;
|
||||
|
||||
virtual unsigned int parse(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master = NULL,
|
||||
const optional<path>& original = none);
|
||||
};
|
||||
|
||||
} // namespace ledger
|
||||
|
||||
#endif // _QIF_H
|
||||
117
src/quotes.cc
117
src/quotes.cc
|
|
@ -1,117 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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 "quotes.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
optional<amount_t>
|
||||
quotes_by_script::operator()(commodity_t& commodity,
|
||||
const optional<moment_t>& date,
|
||||
const optional<moment_t>& moment,
|
||||
const optional<moment_t>& last)
|
||||
{
|
||||
LOGGER("quotes.download");
|
||||
|
||||
IF_DEBUG_() {
|
||||
DEBUG_("commodity: " << commodity.symbol());
|
||||
DEBUG_(" now: " << now);
|
||||
if (date)
|
||||
DEBUG_(" date: " << date);
|
||||
if (moment)
|
||||
DEBUG_(" moment: " << moment);
|
||||
if (last)
|
||||
DEBUG_(" last: " << last);
|
||||
if (commodity.history())
|
||||
DEBUG_("last_lookup: " << commodity.history()->last_lookup);
|
||||
}
|
||||
DEBUG_("pricing_leeway is " << pricing_leeway);
|
||||
|
||||
if ((commodity.history() &&
|
||||
(now - commodity.history()->last_lookup) < pricing_leeway) ||
|
||||
(last && (now - *last) < pricing_leeway) ||
|
||||
(moment && date && *moment > *date &&
|
||||
(*moment - *date) <= pricing_leeway))
|
||||
return none;
|
||||
|
||||
DEBUG_("downloading quote for symbol " << commodity.symbol());
|
||||
|
||||
char buf[256];
|
||||
buf[0] = '\0';
|
||||
|
||||
bool success = true;
|
||||
|
||||
if (FILE * fp = popen((string("getquote \"") +
|
||||
commodity.base_symbol() + "\"").c_str(), "r")) {
|
||||
if (feof(fp) || ! fgets(buf, 255, fp))
|
||||
success = false;
|
||||
if (pclose(fp) != 0)
|
||||
success = false;
|
||||
} else {
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (success && buf[0]) {
|
||||
char * p = strchr(buf, '\n');
|
||||
if (p) *p = '\0';
|
||||
|
||||
DEBUG_("downloaded quote: " << buf);
|
||||
|
||||
amount_t price;
|
||||
price.parse(buf);
|
||||
commodity.add_price(now, price);
|
||||
|
||||
commodity.history()->last_lookup = now;
|
||||
cache_dirty = true;
|
||||
|
||||
assert(! price_db.empty());
|
||||
|
||||
#if defined(__GNUG__) && __GNUG__ < 3
|
||||
ofstream database(price_db, ios::out | ios::app);
|
||||
#else
|
||||
ofstream database(price_db, std::ios_base::out | std::ios_base::app);
|
||||
#endif
|
||||
#if 0
|
||||
// jww (2007-04-18): Need to convert to local time and print
|
||||
// here, print with UTC timezone specifier
|
||||
database << "P " << now.to_string("%Y/%m/%d %H:%M:%S")
|
||||
<< " " << commodity.symbol << " " << price << endl;
|
||||
#endif
|
||||
return price;
|
||||
} else {
|
||||
throw_(download_error,
|
||||
"Failed to download price for '" << commodity.symbol() <<
|
||||
"' (command: \"getquote " << commodity.base_symbol() << "\")");
|
||||
}
|
||||
return none;
|
||||
}
|
||||
|
||||
} // namespace ledger
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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.
|
||||
*/
|
||||
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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.
|
||||
*/
|
||||
|
||||
|
|
@ -125,15 +125,12 @@ string abbreviate(const string& str,
|
|||
|
||||
static void scan_for_transactions(std::ostream& out, const xml::node_t * node)
|
||||
{
|
||||
#if 0
|
||||
if (! node->has_flags(XML_NODE_IS_PARENT))
|
||||
return;
|
||||
|
||||
const xml::parent_node_t * parent = node->as_parent_node();
|
||||
|
||||
for (const xml::node_t * child = parent->children();
|
||||
child;
|
||||
child = child->next)
|
||||
if (child->name_id == xml::document_t::TRANSACTION) {
|
||||
foreach (const xml::node_t * child, node->as_parent_node()) {
|
||||
if (child->name_id == xml::TRANSACTION_NODE) {
|
||||
const xml::transaction_node_t * xact_node =
|
||||
dynamic_cast<const xml::transaction_node_t *>(child);
|
||||
assert(xact_node);
|
||||
|
|
@ -154,13 +151,14 @@ static void scan_for_transactions(std::ostream& out, const xml::node_t * node)
|
|||
} else {
|
||||
scan_for_transactions(out, child);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void register_command::print_document(std::ostream& out,
|
||||
xml::document_t * doc)
|
||||
{
|
||||
#if 1
|
||||
scan_for_transactions(out, doc->top);
|
||||
scan_for_transactions(out, doc);
|
||||
out.flush();
|
||||
#else
|
||||
value_t nodelist;
|
||||
|
|
|
|||
|
|
@ -88,7 +88,9 @@ class report_t : public xml::xpath_t::scope_t
|
|||
//
|
||||
|
||||
void eval(const string& expr) {
|
||||
#if 0
|
||||
xml::xpath_t(expr).compile((xml::document_t *)NULL, this);
|
||||
#endif
|
||||
}
|
||||
void option_eval(value_t&, xml::xpath_t::scope_t * locals) {
|
||||
eval(locals->args[0].as_string());
|
||||
|
|
|
|||
|
|
@ -146,6 +146,8 @@ extern "C" {
|
|||
#include <boost/multi_index/hashed_index.hpp>
|
||||
#include <boost/multi_index/key_extractors.hpp>
|
||||
#include <boost/multi_index/ordered_index.hpp>
|
||||
#include <boost/multi_index/random_access_index.hpp>
|
||||
#include <boost/multi_index/sequenced_index.hpp>
|
||||
#include <boost/multi_index_container.hpp>
|
||||
#include <boost/operators.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
|
|
|
|||
|
|
@ -33,13 +33,15 @@
|
|||
|
||||
namespace ledger {
|
||||
|
||||
using namespace xml;
|
||||
|
||||
#define MAX_LINE 1024
|
||||
|
||||
typedef xml::builder_t::position_t position_t;
|
||||
typedef builder_t::position_t position_t;
|
||||
|
||||
void parse_transaction(xml::builder_t& builder,
|
||||
char * line,
|
||||
position_t& end_of_line)
|
||||
void parse_transaction(builder_t& builder,
|
||||
char * line,
|
||||
position_t& end_of_line)
|
||||
{
|
||||
// First cut up the input line into its various parts.
|
||||
|
||||
|
|
@ -125,7 +127,7 @@ void parse_transaction(xml::builder_t& builder,
|
|||
builder.end_node(TRANSACTION_NODE, end_of_line);
|
||||
}
|
||||
|
||||
bool parse_transactions(std::istream& in, xml::builder_t& builder)
|
||||
bool parse_transactions(std::istream& in, builder_t& builder)
|
||||
{
|
||||
TRACE_START(entry_xacts, 1, "Time spent parsing transactions:");
|
||||
|
||||
|
|
@ -155,10 +157,10 @@ bool parse_transactions(std::istream& in, xml::builder_t& builder)
|
|||
return added;
|
||||
}
|
||||
|
||||
void parse_entry(std::istream& in,
|
||||
xml::builder_t& builder,
|
||||
char * line,
|
||||
position_t& end_of_line)
|
||||
void parse_entry(std::istream& in,
|
||||
builder_t& builder,
|
||||
char * line,
|
||||
position_t& end_of_line)
|
||||
{
|
||||
TRACE_START(entry_text, 1, "Time spent preparing entry text:");
|
||||
|
||||
|
|
@ -226,7 +228,7 @@ void parse_entry(std::istream& in,
|
|||
builder.push_attr(DATE_ATTR, date);
|
||||
|
||||
if (date_eff)
|
||||
builder.push_attr(DATE_EFF_ATTR, date_eff);
|
||||
builder.push_attr(EFF_DATE_ATTR, date_eff);
|
||||
|
||||
if (statep) {
|
||||
switch (*statep) {
|
||||
|
|
@ -273,9 +275,9 @@ bool textual_parser_t::test(std::istream& in) const
|
|||
return true;
|
||||
}
|
||||
|
||||
void textual_parser_t::parse(std::istream& in,
|
||||
const path& pathname,
|
||||
xml::builder_t& builder)
|
||||
void textual_parser_t::parse(std::istream& in,
|
||||
const path& pathname,
|
||||
builder_t& builder)
|
||||
{
|
||||
TRACE_START(parsing_total, 1, "Total time spent parsing text:");
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
*/
|
||||
|
||||
#include "value.h"
|
||||
#include "xml.h"
|
||||
#include "node.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
|
|
@ -1610,7 +1610,7 @@ std::ostream& operator<<(std::ostream& out, const value_t& val)
|
|||
if (val.as_xml_node()->has_flags(XML_NODE_IS_PARENT))
|
||||
out << '<' << val.as_xml_node()->name() << '>';
|
||||
else
|
||||
out << val.as_xml_node()->text();
|
||||
out << val.as_xml_node()->to_value();
|
||||
break;
|
||||
|
||||
case value_t::POINTER:
|
||||
|
|
|
|||
584
src/xml.cc
584
src/xml.cc
|
|
@ -1,584 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007, 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"
|
||||
|
||||
namespace ledger {
|
||||
namespace xml {
|
||||
|
||||
const std::size_t document_t::ledger_builtins_size = 12;
|
||||
const char * document_t::ledger_builtins[] = {
|
||||
"account",
|
||||
"account-path",
|
||||
"amount",
|
||||
"code",
|
||||
"commodity",
|
||||
"entries",
|
||||
"entry",
|
||||
"journal",
|
||||
"name",
|
||||
"note",
|
||||
"payee",
|
||||
"transaction"
|
||||
};
|
||||
|
||||
document_t::~document_t()
|
||||
{
|
||||
TRACE_DTOR(xml::document_t);
|
||||
if (top && top != &stub)
|
||||
checked_delete(top);
|
||||
}
|
||||
|
||||
void document_t::set_top(node_t * _top)
|
||||
{
|
||||
if (top && top != &stub)
|
||||
checked_delete(top);
|
||||
top = _top;
|
||||
}
|
||||
|
||||
int document_t::register_name(const string& name)
|
||||
{
|
||||
int index = lookup_name_id(name);
|
||||
if (index != -1)
|
||||
return index;
|
||||
|
||||
names.push_back(name);
|
||||
index = names.size() - 1;
|
||||
|
||||
DEBUG("xml.lookup", this << " Inserting name: " << names.back());
|
||||
|
||||
std::pair<names_map::iterator, bool> result =
|
||||
names_index.insert(names_map::value_type(names.back(), index));
|
||||
assert(result.second);
|
||||
|
||||
return index + 1000;
|
||||
}
|
||||
|
||||
int document_t::lookup_name_id(const string& name) const
|
||||
{
|
||||
int id;
|
||||
if ((id = lookup_builtin_id(name)) != -1)
|
||||
return id;
|
||||
|
||||
DEBUG("xml.lookup", this << " Finding name: " << name);
|
||||
|
||||
names_map::const_iterator i = names_index.find(name);
|
||||
if (i != names_index.end())
|
||||
return (*i).second + 1000;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int document_t::lookup_builtin_id(const string& name)
|
||||
{
|
||||
int first = 0;
|
||||
int last = (int)ledger_builtins_size;
|
||||
|
||||
while (first <= last) {
|
||||
int mid = (first + last) / 2; // compute mid point.
|
||||
|
||||
int result;
|
||||
if ((result = (int)name[0] - (int)ledger_builtins[mid][0]) == 0)
|
||||
result = std::strcmp(name.c_str(), ledger_builtins[mid]);
|
||||
|
||||
if (result > 0)
|
||||
first = mid + 1; // repeat search in top half.
|
||||
else if (result < 0)
|
||||
last = mid - 1; // repeat search in bottom half.
|
||||
else
|
||||
return mid + 10;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char * document_t::lookup_name(int id) const
|
||||
{
|
||||
if (id < 1000) {
|
||||
switch (id) {
|
||||
case CURRENT:
|
||||
return "CURRENT";
|
||||
case PARENT:
|
||||
return "PARENT";
|
||||
case ROOT:
|
||||
return "ROOT";
|
||||
case ALL:
|
||||
return "ALL";
|
||||
default:
|
||||
assert(id >= 10);
|
||||
return ledger_builtins[id - 10];
|
||||
}
|
||||
} else {
|
||||
return names[id - 1000].c_str();
|
||||
}
|
||||
}
|
||||
|
||||
void document_t::print(std::ostream& out) const
|
||||
{
|
||||
if (top) {
|
||||
out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
|
||||
top->print(out);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef THREADSAFE
|
||||
document_t * node_t::document = NULL;
|
||||
#endif
|
||||
|
||||
node_t::node_t(document_t * _document, parent_node_t * _parent, flags_t _flags)
|
||||
: supports_flags<>(_flags), name_id(0), parent(_parent),
|
||||
next(NULL), prev(NULL), attrs(NULL)
|
||||
{
|
||||
TRACE_CTOR(node_t, "document_t *, node_t *");
|
||||
document = _document;
|
||||
if (document && ! document->top)
|
||||
document->set_top(this);
|
||||
if (parent)
|
||||
parent->add_child(this);
|
||||
}
|
||||
|
||||
void node_t::extract()
|
||||
{
|
||||
if (prev)
|
||||
prev->next = next;
|
||||
|
||||
if (parent) {
|
||||
if (parent->_children == this)
|
||||
parent->_children = next;
|
||||
|
||||
if (parent->_last_child == this)
|
||||
parent->_last_child = prev;
|
||||
|
||||
parent = NULL;
|
||||
}
|
||||
|
||||
if (next)
|
||||
next->prev = prev;
|
||||
|
||||
next = NULL;
|
||||
prev = NULL;
|
||||
}
|
||||
|
||||
const char * node_t::name() const
|
||||
{
|
||||
return document->lookup_name(name_id);
|
||||
}
|
||||
|
||||
int node_t::set_name(const char * _name)
|
||||
{
|
||||
name_id = document->register_name(_name);
|
||||
return name_id;
|
||||
}
|
||||
|
||||
node_t * node_t::lookup_child(const char * _name) const
|
||||
{
|
||||
int id = document->lookup_name_id(_name);
|
||||
return lookup_child(id);
|
||||
}
|
||||
|
||||
node_t * node_t::lookup_child(const string& _name) const
|
||||
{
|
||||
int id = document->lookup_name_id(_name);
|
||||
return lookup_child(id);
|
||||
}
|
||||
|
||||
void parent_node_t::clear()
|
||||
{
|
||||
node_t * child = _children;
|
||||
while (child) {
|
||||
node_t * tnext = child->next;
|
||||
checked_delete(child);
|
||||
child = tnext;
|
||||
}
|
||||
}
|
||||
|
||||
void parent_node_t::add_child(node_t * node)
|
||||
{
|
||||
// It is important that this node is not called before children(),
|
||||
// otherwise, this node will not get auto-populated.
|
||||
if (_children == NULL) {
|
||||
assert(_last_child == NULL);
|
||||
_children = node;
|
||||
node->prev = NULL;
|
||||
} else {
|
||||
assert(_last_child != NULL);
|
||||
_last_child->next = node;
|
||||
node->prev = _last_child;
|
||||
}
|
||||
|
||||
node->parent = this;
|
||||
|
||||
while (node->next) {
|
||||
node_t * next_node = node->next;
|
||||
assert(next_node->prev == node);
|
||||
next_node->parent = this;
|
||||
node = next_node;
|
||||
}
|
||||
|
||||
_last_child = node;
|
||||
}
|
||||
|
||||
void parent_node_t::print(std::ostream& out, int depth) const
|
||||
{
|
||||
for (int i = 0; i < depth; i++) out << " ";
|
||||
out << '<' << name() << ">\n";
|
||||
|
||||
for (node_t * child = children(); child; child = child->next)
|
||||
child->print(out, depth + 1);
|
||||
|
||||
for (int i = 0; i < depth; i++) out << " ";
|
||||
out << "</" << name() << ">\n";
|
||||
}
|
||||
|
||||
void terminal_node_t::print(std::ostream& out, int depth) const
|
||||
{
|
||||
for (int i = 0; i < depth; i++) out << " ";
|
||||
|
||||
if (data.empty()) {
|
||||
out << '<' << name() << " />\n";
|
||||
} else {
|
||||
out << '<' << name() << ">"
|
||||
<< text()
|
||||
<< "</" << name() << ">\n";
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(HAVE_EXPAT) || defined(HAVE_XMLPARSE)
|
||||
|
||||
template <typename T>
|
||||
inline T * create_node(document_t::parser_t * parser)
|
||||
{
|
||||
T * node = new T(parser->document, parser->node_stack.empty() ?
|
||||
NULL : parser->node_stack.front());
|
||||
|
||||
node->set_name(parser->pending);
|
||||
node->attrs = parser->pending_attrs;
|
||||
|
||||
parser->pending = NULL;
|
||||
parser->pending_attrs = NULL;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static void startElement(void *userData, const char *name, const char **attrs)
|
||||
{
|
||||
document_t::parser_t * parser = static_cast<document_t::parser_t *>(userData);
|
||||
|
||||
DEBUG("xml.parse", "startElement(" << name << ")");
|
||||
|
||||
if (parser->pending) {
|
||||
parent_node_t * node = create_node<parent_node_t>(parser);
|
||||
if (parser->node_stack.empty())
|
||||
parser->document->top = node;
|
||||
parser->node_stack.push_front(node);
|
||||
}
|
||||
|
||||
parser->pending = name;
|
||||
|
||||
if (attrs) {
|
||||
for (const char ** p = attrs; *p; p += 2) {
|
||||
if (! parser->pending_attrs)
|
||||
parser->pending_attrs = new node_t::attrs_map;
|
||||
|
||||
std::pair<node_t::attrs_map::iterator, bool> result
|
||||
= parser->pending_attrs->insert
|
||||
(node_t::attrs_map::value_type(*p, *(p + 1)));
|
||||
assert(result.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void endElement(void *userData, const char *name)
|
||||
{
|
||||
document_t::parser_t * parser = static_cast<document_t::parser_t *>(userData);
|
||||
|
||||
DEBUG("xml.parse", "endElement(" << name << ")");
|
||||
|
||||
if (parser->pending) {
|
||||
terminal_node_t * node = create_node<terminal_node_t>(parser);
|
||||
if (parser->node_stack.empty()) {
|
||||
parser->document->top = node;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (! parser->handled_data) {
|
||||
assert(! parser->node_stack.empty());
|
||||
parser->node_stack.pop_front();
|
||||
}
|
||||
else {
|
||||
parser->handled_data = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void dataHandler(void *userData, const char *s, int len)
|
||||
{
|
||||
document_t::parser_t * parser = static_cast<document_t::parser_t *>(userData);
|
||||
|
||||
DEBUG("xml.parse", "dataHandler(" << string(s, len) << ")");
|
||||
|
||||
bool all_whitespace = true;
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (! std::isspace(s[i])) {
|
||||
all_whitespace = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// jww (2006-09-28): I currently do not support text nodes within a
|
||||
// node that has children.
|
||||
|
||||
if (! all_whitespace) {
|
||||
terminal_node_t * node = create_node<terminal_node_t>(parser);
|
||||
|
||||
node->set_text(string(s, len));
|
||||
parser->handled_data = true;
|
||||
|
||||
if (parser->node_stack.empty()) {
|
||||
parser->document->top = node;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool document_t::parser_t::test(std::istream& in) const
|
||||
{
|
||||
char buf[80];
|
||||
|
||||
in.getline(buf, 79);
|
||||
if (std::strncmp(buf, "<?xml", 5) != 0) {
|
||||
in.clear();
|
||||
in.seekg(0, std::ios::beg);
|
||||
return false;
|
||||
}
|
||||
|
||||
in.clear();
|
||||
in.seekg(0, std::ios::beg);
|
||||
return true;
|
||||
}
|
||||
|
||||
document_t * document_t::parser_t::parse(std::istream& in)
|
||||
{
|
||||
std::auto_ptr<document_t> doc(new document_t);
|
||||
|
||||
document = doc.get();
|
||||
|
||||
parser = XML_ParserCreate(NULL);
|
||||
|
||||
XML_SetElementHandler(parser, startElement, endElement);
|
||||
XML_SetCharacterDataHandler(parser, dataHandler);
|
||||
XML_SetUserData(parser, this);
|
||||
|
||||
char buf[BUFSIZ];
|
||||
while (! in.eof()) {
|
||||
in.getline(buf, BUFSIZ - 1);
|
||||
std::strcat(buf, "\n");
|
||||
bool result;
|
||||
try {
|
||||
result = XML_Parse(parser, buf, std::strlen(buf), in.eof());
|
||||
}
|
||||
catch (const std::exception& err) {
|
||||
//unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
|
||||
XML_ParserFree(parser);
|
||||
throw_(parse_error, err.what());
|
||||
}
|
||||
|
||||
if (! have_error.empty()) {
|
||||
//unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
|
||||
#if 0
|
||||
// jww (2007-04-26): What is this doing??
|
||||
parse_error err(have_error);
|
||||
std::cerr << "Error: " << err.what() << std::endl;
|
||||
#endif
|
||||
have_error = "";
|
||||
}
|
||||
|
||||
if (! result) {
|
||||
//unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
|
||||
const char * err = XML_ErrorString(XML_GetErrorCode(parser));
|
||||
XML_ParserFree(parser);
|
||||
throw_(parse_error, err);
|
||||
}
|
||||
}
|
||||
|
||||
XML_ParserFree(parser);
|
||||
|
||||
document = NULL;
|
||||
return doc.release();
|
||||
}
|
||||
|
||||
#endif // HAVE_EXPAT || HAVE_XMLPARSE
|
||||
|
||||
node_t * commodity_node_t::children() const
|
||||
{
|
||||
// jww (2007-04-19): Need to report the commodity and its details
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node_t * amount_node_t::children() const
|
||||
{
|
||||
// jww (2007-04-19): Need to report the quantity and commodity
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node_t * transaction_node_t::children() const
|
||||
{
|
||||
return parent_node_t::children();
|
||||
}
|
||||
|
||||
node_t * transaction_node_t::lookup_child(int _name_id) const
|
||||
{
|
||||
switch (_name_id) {
|
||||
case document_t::PAYEE:
|
||||
payee_virtual_node = new terminal_node_t(document);
|
||||
payee_virtual_node->set_text(transaction->entry->payee);
|
||||
return payee_virtual_node;
|
||||
|
||||
case document_t::ACCOUNT:
|
||||
return new account_node_t(document, transaction->account,
|
||||
const_cast<transaction_node_t *>(this));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
value_t transaction_node_t::to_value() const
|
||||
{
|
||||
if (transaction->amount)
|
||||
return *transaction->amount;
|
||||
else
|
||||
return value_t();
|
||||
}
|
||||
|
||||
node_t * entry_node_t::children() const
|
||||
{
|
||||
if (! _children)
|
||||
for (transactions_list::iterator i = entry->transactions.begin();
|
||||
i != entry->transactions.end();
|
||||
i++)
|
||||
new transaction_node_t(document, *i, const_cast<entry_node_t *>(this));
|
||||
|
||||
return parent_node_t::children();
|
||||
}
|
||||
|
||||
node_t * entry_node_t::lookup_child(int _name_id) const
|
||||
{
|
||||
switch (_name_id) {
|
||||
case document_t::CODE: {
|
||||
if (! entry->code)
|
||||
break;
|
||||
|
||||
// jww (2007-04-20): I have to save this and then delete it later
|
||||
terminal_node_t * code_node =
|
||||
new terminal_node_t(document, const_cast<entry_node_t *>(this));
|
||||
code_node->set_name(document_t::CODE);
|
||||
code_node->set_text(*entry->code);
|
||||
return code_node;
|
||||
}
|
||||
|
||||
case document_t::PAYEE: {
|
||||
// jww (2007-04-20): I have to save this and then delete it later
|
||||
terminal_node_t * payee_node =
|
||||
new terminal_node_t(document, const_cast<entry_node_t *>(this));
|
||||
payee_node->set_name(document_t::PAYEE);
|
||||
payee_node->set_text(entry->payee);
|
||||
return payee_node;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node_t * account_node_t::children() const
|
||||
{
|
||||
if (! _children) {
|
||||
if (! account->name.empty()) {
|
||||
terminal_node_t * name_node =
|
||||
new terminal_node_t(document, const_cast<account_node_t *>(this));
|
||||
name_node->set_name(document_t::NAME);
|
||||
name_node->set_text(account->name);
|
||||
}
|
||||
|
||||
if (account->note) {
|
||||
terminal_node_t * note_node =
|
||||
new terminal_node_t(document, const_cast<account_node_t *>(this));
|
||||
note_node->set_name(document_t::NOTE);
|
||||
note_node->set_text(*account->note);
|
||||
}
|
||||
|
||||
for (accounts_map::iterator i = account->accounts.begin();
|
||||
i != account->accounts.end();
|
||||
i++)
|
||||
new account_node_t(document, (*i).second, const_cast<account_node_t *>(this));
|
||||
}
|
||||
return parent_node_t::children();
|
||||
}
|
||||
|
||||
node_t * journal_node_t::children() const
|
||||
{
|
||||
if (! _children) {
|
||||
#if 0
|
||||
account_node_t * master_account =
|
||||
new account_node_t(document, journal->master, const_cast<journal_node_t *>(this));
|
||||
#endif
|
||||
|
||||
parent_node_t * entries =
|
||||
new parent_node_t(document, const_cast<journal_node_t *>(this));
|
||||
entries->set_name(document_t::ENTRIES);
|
||||
|
||||
for (entries_list::iterator i = journal->entries.begin();
|
||||
i != journal->entries.end();
|
||||
i++)
|
||||
new entry_node_t(document, *i, const_cast<journal_node_t *>(this));
|
||||
}
|
||||
return parent_node_t::children();
|
||||
}
|
||||
|
||||
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 << ">";
|
||||
break;
|
||||
case '&':
|
||||
out << "&";
|
||||
break;
|
||||
default:
|
||||
out << *s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace xml
|
||||
} // namespace ledger
|
||||
83
src/xpath.cc
83
src/xpath.cc
|
|
@ -562,7 +562,7 @@ bool xpath_t::function_scope_t::resolve(const string& name,
|
|||
case 't':
|
||||
if (name == "text") {
|
||||
if (value->type == value_t::XML_NODE)
|
||||
result.set_string(value->as_xml_node()->text());
|
||||
result = value->as_xml_node()->to_value();
|
||||
else
|
||||
throw_(calc_error, "Attempt to call text() on a non-node value");
|
||||
return true;
|
||||
|
|
@ -679,14 +679,14 @@ xpath_t::parse_value_term(std::istream& in, unsigned short tflags) const
|
|||
#endif
|
||||
|
||||
string ident = tok.value.as_string();
|
||||
int id = -1;
|
||||
if (std::isdigit(ident[0])) {
|
||||
node.reset(new op_t(op_t::ARG_INDEX));
|
||||
node->arg_index = lexical_cast<unsigned int>(ident.c_str());
|
||||
}
|
||||
else if ((id = document_t::lookup_builtin_id(ident)) != -1) {
|
||||
else if (optional<node_t::nameid_t> id =
|
||||
document_t::lookup_builtin_id(ident)) {
|
||||
node.reset(new op_t(op_t::NODE_ID));
|
||||
node->name_id = id;
|
||||
node->name_id = *id;
|
||||
}
|
||||
else {
|
||||
node.reset(new op_t(op_t::NODE_NAME));
|
||||
|
|
@ -1213,11 +1213,8 @@ void xpath_t::op_t::find_values(value_t * context, scope_t * scope,
|
|||
if (recursive) {
|
||||
if (context->type == value_t::XML_NODE) {
|
||||
node_t * ptr = context->as_xml_node();
|
||||
if (ptr->has_flags(XML_NODE_IS_PARENT)) {
|
||||
parent_node_t * parent = static_cast<parent_node_t *>(ptr);
|
||||
for (node_t * node = parent->children();
|
||||
node;
|
||||
node = node->next) {
|
||||
if (ptr->is_parent_node()) {
|
||||
foreach (node_t * node, ptr->as_parent_node()) {
|
||||
value_t temp(node);
|
||||
find_values(&temp, scope, result_seq, recursive);
|
||||
}
|
||||
|
|
@ -1308,8 +1305,8 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
|
|||
case document_t::PARENT:
|
||||
if (context->type != value_t::XML_NODE)
|
||||
throw_(compile_error, "Referencing parent node from a non-node value");
|
||||
else if (context->as_xml_node()->parent)
|
||||
return wrap_value(context->as_xml_node()->parent)->acquire();
|
||||
else if (context->as_xml_node()->parent())
|
||||
return wrap_value(&*context->as_xml_node()->parent())->acquire();
|
||||
else
|
||||
throw_(compile_error, "Referencing parent node from the root node");
|
||||
|
||||
|
|
@ -1317,15 +1314,14 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
|
|||
if (context->type != value_t::XML_NODE)
|
||||
throw_(compile_error, "Referencing root node from a non-node value");
|
||||
else
|
||||
return wrap_value(context->as_xml_node()->document->top)->acquire();
|
||||
return wrap_value(&context->as_xml_node()->document())->acquire();
|
||||
|
||||
case document_t::ALL: {
|
||||
if (context->type != value_t::XML_NODE)
|
||||
throw_(compile_error, "Referencing child nodes from a non-node value");
|
||||
|
||||
parent_node_t * parent = context->as_xml_node()->as_parent_node();
|
||||
value_t::sequence_t nodes;
|
||||
for (node_t * node = parent->children(); node; node = node->next)
|
||||
foreach (node_t * node, context->as_xml_node()->as_parent_node())
|
||||
nodes.push_back(node);
|
||||
|
||||
return wrap_value(nodes)->acquire();
|
||||
|
|
@ -1343,37 +1339,37 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
|
|||
// First, look up the symbol as a node name within the current
|
||||
// context. If any exist, then return the set of names.
|
||||
|
||||
value_t::sequence_t nodes;
|
||||
if (ptr->is_parent_node()) {
|
||||
value_t::sequence_t nodes;
|
||||
|
||||
if (ptr->has_flags(XML_NODE_IS_PARENT)) {
|
||||
parent_node_t * parent = static_cast<parent_node_t *>(ptr);
|
||||
for (node_t * node = parent->children();
|
||||
node;
|
||||
node = node->next) {
|
||||
foreach (node_t * node, ptr->as_parent_node()) {
|
||||
if ((kind == NODE_NAME &&
|
||||
std::strcmp(name->c_str(), node->name()) == 0) ||
|
||||
(kind == NODE_ID && name_id == node->name_id))
|
||||
(kind == NODE_ID && name_id == node->name_id()))
|
||||
nodes.push_back(node);
|
||||
}
|
||||
return wrap_value(nodes)->acquire();
|
||||
}
|
||||
return wrap_value(nodes)->acquire();
|
||||
} else {
|
||||
assert(ptr);
|
||||
int id = ptr->document->lookup_name_id(*name);
|
||||
if (id != -1) {
|
||||
if (optional<node_t::nameid_t> id =
|
||||
ptr->document().lookup_name_id(*name)) {
|
||||
op_t * node = new_node(NODE_ID);
|
||||
node->name_id = id;
|
||||
node->name_id = *id;
|
||||
return node->acquire();
|
||||
}
|
||||
}
|
||||
}
|
||||
return acquire();
|
||||
|
||||
case ATTR_NAME: {
|
||||
// jww (2006-09-29): Attrs should map strings to values, not strings
|
||||
const char * value = context->as_xml_node()->get_attr(name->c_str());
|
||||
return wrap_value(value)->acquire();
|
||||
}
|
||||
case ATTR_NAME:
|
||||
if (optional<node_t::nameid_t> id =
|
||||
context->as_xml_node()->document().lookup_name_id(*name)) {
|
||||
optional<const string&> value = context->as_xml_node()->get_attr(*id);
|
||||
if (value)
|
||||
return wrap_value(*value)->acquire();
|
||||
}
|
||||
return acquire();
|
||||
|
||||
case VAR_NAME:
|
||||
case FUNC_NAME:
|
||||
|
|
@ -1903,23 +1899,16 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void xpath_t::calc(value_t& result, node_t * node, scope_t * scope) const
|
||||
void xpath_t::calc(value_t& result, node_t& node, scope_t * scope) const
|
||||
{
|
||||
#if 0
|
||||
try {
|
||||
#endif
|
||||
if (node) {
|
||||
value_t context_node(node);
|
||||
xpath_t final(ptr->compile(&context_node, scope, true));
|
||||
// jww (2006-09-09): Give a better error here if this is not
|
||||
// actually a value
|
||||
final->get_value(result);
|
||||
} else {
|
||||
std::auto_ptr<terminal_node_t> fake_node(new terminal_node_t(NULL));
|
||||
value_t context_node(fake_node.get());
|
||||
xpath_t final(ptr->compile(&context_node, scope, true));
|
||||
final->get_value(result);
|
||||
}
|
||||
value_t context_node(&node);
|
||||
xpath_t final(ptr->compile(&context_node, scope, true));
|
||||
// jww (2006-09-09): Give a better error here if this is not
|
||||
// actually a value
|
||||
final->get_value(result);
|
||||
#if 0
|
||||
}
|
||||
catch (error * err) {
|
||||
|
|
@ -2041,11 +2030,7 @@ bool xpath_t::op_t::print(std::ostream& out,
|
|||
break;
|
||||
|
||||
case NODE_ID:
|
||||
#ifdef THREADSAFE
|
||||
out << '%' << name_id;
|
||||
#else
|
||||
out << node_t::document->lookup_name(name_id);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case NODE_NAME:
|
||||
|
|
@ -2331,11 +2316,7 @@ void xpath_t::op_t::dump(std::ostream& out, const int depth) const
|
|||
break;
|
||||
|
||||
case NODE_ID:
|
||||
#ifdef THREADSAFE
|
||||
out << "NODE_ID - " << name_id;
|
||||
#else
|
||||
out << "NODE_ID - " << node_t::document->lookup_name(name_id);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case ATTR_NAME:
|
||||
|
|
|
|||
55
src/xpath.h
55
src/xpath.h
|
|
@ -32,7 +32,7 @@
|
|||
#ifndef _XPATH_H
|
||||
#define _XPATH_H
|
||||
|
||||
#include "xml.h"
|
||||
#include "document.h"
|
||||
|
||||
namespace ledger {
|
||||
namespace xml {
|
||||
|
|
@ -123,8 +123,7 @@ public:
|
|||
void (T::*_mptr)(value_t& result))
|
||||
: functor_t(_name, false), ptr(_ptr), mptr(_mptr) {}
|
||||
|
||||
virtual void operator()(value_t& result,
|
||||
scope_t * locals = NULL) {
|
||||
virtual void operator()(value_t& result, scope_t * locals = NULL) {
|
||||
assert(ptr);
|
||||
assert(mptr);
|
||||
assert(locals || locals == NULL);
|
||||
|
|
@ -430,7 +429,7 @@ public:
|
|||
string * name; // used by constant SYMBOL
|
||||
unsigned int arg_index; // used by ARG_INDEX and O_ARG
|
||||
functor_t * functor; // used by terminal FUNCTOR
|
||||
unsigned int name_id; // used by NODE_NAME and ATTR_NAME
|
||||
node_t::nameid_t name_id; // used by NODE_NAME and ATTR_NAME
|
||||
#if 0
|
||||
mask_t * mask; // used by terminal MASK
|
||||
#endif
|
||||
|
|
@ -720,30 +719,9 @@ public:
|
|||
reset(tmp ? tmp->acquire() : NULL);
|
||||
}
|
||||
|
||||
void compile(const string& _expr, scope_t * scope = NULL,
|
||||
unsigned short _flags = XPATH_PARSE_RELAXED) {
|
||||
parse(_expr, _flags);
|
||||
// jww (2006-09-24): fix
|
||||
compile((node_t *)NULL, scope);
|
||||
}
|
||||
void compile(std::istream& in, scope_t * scope = NULL,
|
||||
unsigned short _flags = XPATH_PARSE_RELAXED) {
|
||||
parse(in, _flags);
|
||||
// jww (2006-09-24): fix
|
||||
compile((node_t *)NULL, scope);
|
||||
}
|
||||
|
||||
void compile(document_t * document, scope_t * scope = NULL) {
|
||||
if (! document) {
|
||||
document_t tdoc;
|
||||
compile(tdoc.top, scope);
|
||||
} else {
|
||||
compile(document->top, scope);
|
||||
}
|
||||
}
|
||||
void compile(node_t * top_node, scope_t * scope = NULL) {
|
||||
void compile(node_t& top_node, scope_t * scope = NULL) {
|
||||
if (ptr) {
|
||||
value_t noderef(top_node);
|
||||
value_t noderef(&top_node);
|
||||
op_t * compiled = ptr->compile(&noderef, scope);
|
||||
if (compiled == ptr)
|
||||
compiled->release();
|
||||
|
|
@ -752,16 +730,9 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void calc(value_t& result, node_t * node, scope_t * scope = NULL) const;
|
||||
|
||||
virtual value_t calc(document_t * document, scope_t * scope = NULL) const {
|
||||
if (! ptr)
|
||||
return 0L;
|
||||
value_t temp;
|
||||
calc(temp, document ? document->top : NULL, scope);
|
||||
return temp;
|
||||
}
|
||||
virtual value_t calc(node_t * tcontext, scope_t * scope = NULL) const {
|
||||
virtual void calc(value_t& result, node_t& node,
|
||||
scope_t * scope = NULL) const;
|
||||
virtual value_t calc(node_t& tcontext, scope_t * scope = NULL) const {
|
||||
if (! ptr)
|
||||
return 0L;
|
||||
value_t temp;
|
||||
|
|
@ -769,15 +740,15 @@ public:
|
|||
return temp;
|
||||
}
|
||||
|
||||
static void eval(value_t& result, const string& _expr,
|
||||
document_t * document, scope_t * scope = NULL) {
|
||||
static void eval(value_t& result, const string& _expr, node_t& top,
|
||||
scope_t * scope = NULL) {
|
||||
xpath_t temp(_expr);
|
||||
temp.calc(result, document->top, scope);
|
||||
temp.calc(result, top, scope);
|
||||
}
|
||||
static value_t eval(const string& _expr, document_t * document,
|
||||
static value_t eval(const string& _expr, node_t& top,
|
||||
scope_t * scope = NULL) {
|
||||
xpath_t temp(_expr);
|
||||
return temp.calc(document, scope);
|
||||
return temp.calc(top, scope);
|
||||
}
|
||||
|
||||
void print(std::ostream& out) const {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue