diff options
author | John Wiegley <johnw@newartisans.com> | 2007-05-14 11:09:28 +0000 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2008-04-13 03:38:50 -0400 |
commit | 59fc3d1bdb01b7195a0f9745fe9914ac31b8a3a5 (patch) | |
tree | b925cd5f52bed29606364c76a08c0b7795ebcedd /src | |
parent | 77db7eb92f730af315d4bcdf831cc67acb386b58 (diff) | |
download | fork-ledger-59fc3d1bdb01b7195a0f9745fe9914ac31b8a3a5.tar.gz fork-ledger-59fc3d1bdb01b7195a0f9745fe9914ac31b8a3a5.tar.bz2 fork-ledger-59fc3d1bdb01b7195a0f9745fe9914ac31b8a3a5.zip |
Initial implementation of document_builder_t.
Diffstat (limited to 'src')
-rw-r--r-- | src/builder.h | 79 | ||||
-rw-r--r-- | src/commodity.cc | 26 | ||||
-rw-r--r-- | src/commodity.h | 4 | ||||
-rw-r--r-- | src/compile.h (renamed from src/xml.h) | 6 | ||||
-rw-r--r-- | src/csv.cc | 31 | ||||
-rw-r--r-- | src/csv.h | 31 | ||||
-rw-r--r-- | src/derive.cc | 209 | ||||
-rw-r--r-- | src/derive.h | 49 | ||||
-rw-r--r-- | src/document.cc | 177 | ||||
-rw-r--r-- | src/document.h | 150 | ||||
-rw-r--r-- | src/emacs.cc | 31 | ||||
-rw-r--r-- | src/emacs.h | 31 | ||||
-rw-r--r-- | src/gnucash.cc | 397 | ||||
-rw-r--r-- | src/gnucash.h | 103 | ||||
-rw-r--r-- | src/journal.cc | 2 | ||||
-rw-r--r-- | src/ledger.h | 3 | ||||
-rw-r--r-- | src/main.cc | 16 | ||||
-rw-r--r-- | src/node.cc (renamed from src/quotes.h) | 89 | ||||
-rw-r--r-- | src/node.h | 276 | ||||
-rw-r--r-- | src/ofx.cc | 246 | ||||
-rw-r--r-- | src/ofx.h | 52 | ||||
-rw-r--r-- | src/py_balance.cc | 233 | ||||
-rw-r--r-- | src/py_format.cc | 42 | ||||
-rw-r--r-- | src/py_journal.cc | 404 | ||||
-rw-r--r-- | src/py_option.cc | 103 | ||||
-rw-r--r-- | src/py_parser.cc | 79 | ||||
-rw-r--r-- | src/py_report.cc | 44 | ||||
-rw-r--r-- | src/py_session.cc | 67 | ||||
-rw-r--r-- | src/py_transform.cc | 39 | ||||
-rw-r--r-- | src/py_value.cc | 368 | ||||
-rw-r--r-- | src/py_xpath.cc | 110 | ||||
-rw-r--r-- | src/qif.cc | 274 | ||||
-rw-r--r-- | src/qif.h | 52 | ||||
-rw-r--r-- | src/quotes.cc | 117 | ||||
-rw-r--r-- | src/reconcile.cc | 31 | ||||
-rw-r--r-- | src/reconcile.h | 31 | ||||
-rw-r--r-- | src/register.cc | 12 | ||||
-rw-r--r-- | src/report.h | 2 | ||||
-rw-r--r-- | src/system.hh | 2 | ||||
-rw-r--r-- | src/textual.cc | 28 | ||||
-rw-r--r-- | src/value.cc | 4 | ||||
-rw-r--r-- | src/xml.cc | 584 | ||||
-rw-r--r-- | src/xpath.cc | 83 | ||||
-rw-r--r-- | src/xpath.h | 55 |
44 files changed, 832 insertions, 3940 deletions
diff --git a/src/builder.h b/src/builder.h index 69fec3d9..ea340242 100644 --- a/src/builder.h +++ b/src/builder.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, diff --git a/src/commodity.cc b/src/commodity.cc index 4cc38e06..48609577 100644 --- a/src/commodity.cc +++ b/src/commodity.cc @@ -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, diff --git a/src/commodity.h b/src/commodity.h index 84ca5fff..6212e743 100644 --- a/src/commodity.h +++ b/src/commodity.h @@ -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> > diff --git a/src/xml.h b/src/compile.h index a247260b..25e12183 100644 --- a/src/xml.h +++ b/src/compile.h @@ -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 diff --git a/src/csv.cc b/src/csv.cc deleted file mode 100644 index 0b623407..00000000 --- a/src/csv.cc +++ /dev/null @@ -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. - */ - diff --git a/src/csv.h b/src/csv.h deleted file mode 100644 index 0b623407..00000000 --- a/src/csv.h +++ /dev/null @@ -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. - */ - diff --git a/src/derive.cc b/src/derive.cc deleted file mode 100644 index 73c4cdf0..00000000 --- a/src/derive.cc +++ /dev/null @@ -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 diff --git a/src/derive.h b/src/derive.h deleted file mode 100644 index 422248d8..00000000 --- a/src/derive.h +++ /dev/null @@ -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 diff --git a/src/document.cc b/src/document.cc new file mode 100644 index 00000000..e48462da --- /dev/null +++ b/src/document.cc @@ -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 diff --git a/src/document.h b/src/document.h new file mode 100644 index 00000000..1b6f0924 --- /dev/null +++ b/src/document.h @@ -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 diff --git a/src/emacs.cc b/src/emacs.cc deleted file mode 100644 index 0b623407..00000000 --- a/src/emacs.cc +++ /dev/null @@ -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. - */ - diff --git a/src/emacs.h b/src/emacs.h deleted file mode 100644 index 0b623407..00000000 --- a/src/emacs.h +++ /dev/null @@ -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. - */ - diff --git a/src/gnucash.cc b/src/gnucash.cc deleted file mode 100644 index 8fa5a524..00000000 --- a/src/gnucash.cc +++ /dev/null @@ -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 diff --git a/src/gnucash.h b/src/gnucash.h deleted file mode 100644 index ce46eec7..00000000 --- a/src/gnucash.h +++ /dev/null @@ -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 diff --git a/src/journal.cc b/src/journal.cc index 7a6f3354..7fe6b285 100644 --- a/src/journal.cc +++ b/src/journal.cc @@ -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() diff --git a/src/ledger.h b/src/ledger.h index d4bdcabe..c9f0f9c4 100644 --- a/src/ledger.h +++ b/src/ledger.h @@ -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> diff --git a/src/main.cc b/src/main.cc index 010abd3c..945587b1 100644 --- a/src/main.cc +++ b/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; } diff --git a/src/quotes.h b/src/node.cc index c94b405b..390ef988 100644 --- a/src/quotes.h +++ b/src/node.cc @@ -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; - - 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) {} - - virtual optional<amount_t> - operator()(commodity_t& commodity, - const optional<moment_t>& date, - const optional<moment_t>& moment, - const optional<moment_t>& last); -}; - -DECLARE_EXCEPTION(download_error); + return *document().lookup_name(name_id()); +} -} // namespace ledger +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; + } + } +} + +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 << '>'; -#endif // _QUOTES_H + 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 diff --git a/src/node.h b/src/node.h new file mode 100644 index 00000000..86b468e8 --- /dev/null +++ b/src/node.h @@ -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 diff --git a/src/ofx.cc b/src/ofx.cc deleted file mode 100644 index 24be9409..00000000 --- a/src/ofx.cc +++ /dev/null @@ -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 diff --git a/src/ofx.h b/src/ofx.h deleted file mode 100644 index 5a55d75c..00000000 --- a/src/ofx.h +++ /dev/null @@ -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 diff --git a/src/py_balance.cc b/src/py_balance.cc deleted file mode 100644 index 90712d12..00000000 --- a/src/py_balance.cc +++ /dev/null @@ -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>())) - ; -} diff --git a/src/py_format.cc b/src/py_format.cc deleted file mode 100644 index 819a0ac7..00000000 --- a/src/py_format.cc +++ /dev/null @@ -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) - ; -} diff --git a/src/py_journal.cc b/src/py_journal.cc deleted file mode 100644 index e7cd600a..00000000 --- a/src/py_journal.cc +++ /dev/null @@ -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); -} diff --git a/src/py_option.cc b/src/py_option.cc deleted file mode 100644 index 2e298272..00000000 --- a/src/py_option.cc +++ /dev/null @@ -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); -} diff --git a/src/py_parser.cc b/src/py_parser.cc deleted file mode 100644 index df3f8209..00000000 --- a/src/py_parser.cc +++ /dev/null @@ -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 diff --git a/src/py_report.cc b/src/py_report.cc deleted file mode 100644 index 5816b398..00000000 --- a/src/py_report.cc +++ /dev/null @@ -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) - ; -} diff --git a/src/py_session.cc b/src/py_session.cc deleted file mode 100644 index eb0e1b7d..00000000 --- a/src/py_session.cc +++ /dev/null @@ -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) - ; -} diff --git a/src/py_transform.cc b/src/py_transform.cc deleted file mode 100644 index 4ab2e9f6..00000000 --- a/src/py_transform.cc +++ /dev/null @@ -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") - ; -} diff --git a/src/py_value.cc b/src/py_value.cc deleted file mode 100644 index f85eef1e..00000000 --- a/src/py_value.cc +++ /dev/null @@ -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) - ; -} diff --git a/src/py_xpath.cc b/src/py_xpath.cc deleted file mode 100644 index 55a68b12..00000000 --- a/src/py_xpath.cc +++ /dev/null @@ -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 -} diff --git a/src/qif.cc b/src/qif.cc deleted file mode 100644 index 20d7d2e1..00000000 --- a/src/qif.cc +++ /dev/null @@ -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 diff --git a/src/qif.h b/src/qif.h deleted file mode 100644 index 6cce6520..00000000 --- a/src/qif.h +++ /dev/null @@ -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 diff --git a/src/quotes.cc b/src/quotes.cc deleted file mode 100644 index 07417800..00000000 --- a/src/quotes.cc +++ /dev/null @@ -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 diff --git a/src/reconcile.cc b/src/reconcile.cc deleted file mode 100644 index 0b623407..00000000 --- a/src/reconcile.cc +++ /dev/null @@ -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. - */ - diff --git a/src/reconcile.h b/src/reconcile.h deleted file mode 100644 index 0b623407..00000000 --- a/src/reconcile.h +++ /dev/null @@ -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. - */ - diff --git a/src/register.cc b/src/register.cc index d3843887..98aafee1 100644 --- a/src/register.cc +++ b/src/register.cc @@ -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; diff --git a/src/report.h b/src/report.h index d6cfef3c..51ee9386 100644 --- a/src/report.h +++ b/src/report.h @@ -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()); diff --git a/src/system.hh b/src/system.hh index 217b1235..1c645794 100644 --- a/src/system.hh +++ b/src/system.hh @@ -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> diff --git a/src/textual.cc b/src/textual.cc index 914b63c3..82c8fcbf 100644 --- a/src/textual.cc +++ b/src/textual.cc @@ -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:"); diff --git a/src/value.cc b/src/value.cc index 63719266..12c6379d 100644 --- a/src/value.cc +++ b/src/value.cc @@ -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: diff --git a/src/xml.cc b/src/xml.cc deleted file mode 100644 index 9b14f97c..00000000 --- a/src/xml.cc +++ /dev/null @@ -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 diff --git a/src/xpath.cc b/src/xpath.cc index a59126ae..caa7806a 100644 --- a/src/xpath.cc +++ b/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: diff --git a/src/xpath.h b/src/xpath.h index a7e2dea0..8819d49e 100644 --- a/src/xpath.h +++ b/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 { |