diff options
Diffstat (limited to 'src/data')
-rw-r--r-- | src/data/builder.h | 256 | ||||
-rw-r--r-- | src/data/compile.cc | 235 | ||||
-rw-r--r-- | src/data/compile.h | 206 | ||||
-rw-r--r-- | src/data/document.cc | 181 | ||||
-rw-r--r-- | src/data/document.h | 152 | ||||
-rw-r--r-- | src/data/jbuilder.cc | 67 | ||||
-rw-r--r-- | src/data/jbuilder.h | 81 | ||||
-rw-r--r-- | src/data/journal.cc | 702 | ||||
-rw-r--r-- | src/data/journal.h | 439 | ||||
-rw-r--r-- | src/data/node.cc | 130 | ||||
-rw-r--r-- | src/data/node.h | 352 | ||||
-rw-r--r-- | src/data/parser.h | 138 | ||||
-rw-r--r-- | src/data/textual.cc | 480 | ||||
-rw-r--r-- | src/data/textual.h | 51 |
14 files changed, 0 insertions, 3470 deletions
diff --git a/src/data/builder.h b/src/data/builder.h deleted file mode 100644 index a193879e..00000000 --- a/src/data/builder.h +++ /dev/null @@ -1,256 +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 _BUILDER_H -#define _BUILDER_H - -#include "document.h" - -namespace ledger { -namespace xml { - -/** - * @class builder_t - * - * @brief Represents an interface for building a data hierarchy. - * - * This interface is much like .NET's XmlWriter facility. It - * abstracts the kind of hierarchy we're building, instead focusing - * only on the relationships. - */ -class builder_t -{ -public: - struct position_t - { - typedef uint_least32_t file_pos_t; - typedef uint_least32_t file_line_t; - - file_pos_t offset; - file_line_t linenum; - - position_t() : offset(0), linenum(0) {} - - explicit position_t(file_pos_t _offset, - file_line_t _linenum) - : offset(_offset), linenum(_linenum) {} - }; - -protected: - position_t current_position; - -public: - virtual ~builder_t() {} - - virtual void set_start_position(std::istream& in) {} - virtual void set_position(const position_t& position) {} - virtual position_t& position() { return current_position; } - - virtual void push_attr(const string& name, - const string& value) = 0; - virtual void push_attr(const node_t::nameid_t name_id, - const string& value) = 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; - virtual void push_node(const node_t::nameid_t name_id, - const optional<position_t>& end_pos = none) = 0; - - virtual node_t * current_node() = 0; - - virtual void append_text(const string& text) = 0; - - virtual node_t * end_node(const string& name, - const optional<position_t>& end_pos = none) = 0; - virtual node_t * end_node(const node_t::nameid_t name_id, - const optional<position_t>& end_pos = none) = 0; -}; - -/** - * @class xml_builder_t - * - * @brief Build a generic node_t hierarchy. - * - * This builder can be used to parse ordinary XML into a document - * object structure which can then be traversed in memory. - */ -class document_builder_t : public builder_t -{ -protected: - 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; - -public: - 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 document_t& document() { - return document_; - } - 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) { - return current = &*current->parent(); - } - virtual node_t * end_node(const node_t::nameid_t name_id, - const optional<position_t>& end_pos = none) { - return current = &*current->parent(); - } -}; - -/** - * @class xml_writer_t - * - * @brief Create textual XML on the given output stream. - * - * This builder, rather than manipulating data structures in memory, - * simply streams its contents on the fly to the given output stream. - * It uses only enough memory to remember the currently push - * attributes and text. - */ -class xml_writer_t : public builder_t -{ - typedef std::list<std::pair<string, string> > attrs_list; - - attrs_list current_attrs; - std::ostream& outs; - -public: - xml_writer_t(std::ostream& _outs) : outs(_outs) { - outs << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; - begin_node("ledger"); - } - ~xml_writer_t() { - end_node("ledger"); - } - - virtual void push_attr(const string& name, - const string& value) { - current_attrs.push_back(attrs_list::value_type(name, value)); - } - virtual void push_attr(const node_t::nameid_t name_id, - const string& value) { - push_attr("hello", value); - } - - 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, bool terminal = false) { - begin_node("hello"); - } - - 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) { - push_node("hello", end_pos); - } - - virtual node_t * current_node() { return NULL; } - - virtual void append_text(const string& text) { - outs << text; - } - - virtual node_t * end_node(const string& name, - const optional<position_t>& end_pos = none) { - outs << "</" << name << '>'; - return NULL; - } - virtual node_t * end_node(const node_t::nameid_t name_id, - const optional<position_t>& end_pos = none) { - end_node("hello", end_pos); - return NULL; - } -}; - -} // namespace xml -} // namespace ledger - -#endif // _BUILDER_H diff --git a/src/data/compile.cc b/src/data/compile.cc deleted file mode 100644 index 07ce9394..00000000 --- a/src/data/compile.cc +++ /dev/null @@ -1,235 +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 "compile.h" -#include "parser.h" - -namespace ledger { -namespace xml { - -void compile_node(node_t& node, xpath_t::scope_t& scope) -{ - switch (node.name_id()) { - case JOURNAL_NODE: - downcast<journal_node_t>(node).compile(scope); - break; - case ENTRY_NODE: - downcast<entry_node_t>(node).compile(scope); - break; - case TRANSACTION_NODE: - downcast<transaction_node_t>(node).compile(scope); - break; - - default: - break; - } - - node.compiled = true; - - if (node.is_parent_node()) - foreach (node_t * child, node.as_parent_node()) - compile_node(*child, scope); -} - -void journal_node_t::compile(xpath_t::scope_t& scope) -{ - if (! journal.get()) - journal.reset(new journal_t); -} - -void entry_node_t::compile(xpath_t::scope_t& scope) -{ - parent_node_t& parent_node(*parent()); - - assert(parent_node.name_id() == JOURNAL_NODE); - assert(parent_node.is_compiled()); - - journal_t * journal = downcast<journal_node_t>(parent_node).journal.get(); - - if (! entry.get()) { - entry.reset(new entry_t); -#if 0 - journal->add_entry(entry.get()); -#endif - } - entry->journal = journal; - - foreach (attr_pair& attr, *attributes) { - if (attr.first == DATE_ATTR && attr.second.is_string()) - entry->_date = parse_datetime(attr.second.as_string().c_str()); - else if (attr.first == EFF_DATE_ATTR && attr.second.is_string()) - entry->_date_eff = parse_datetime(attr.second.as_string().c_str()); - else if (attr.first == CODE_ATTR) - entry->code = attr.second.as_string(); - } -} - -void transaction_node_t::parse_amount_expr(xpath_t::scope_t& scope, - const char * amount_expr) -{ - value_t * amount; - - std::istringstream in(amount_expr); - - PUSH_CONTEXT(); - - // jww (2006-09-15): Make sure it doesn't gobble up the upcoming @ symbol - - unsigned long beg = (long)in.tellg(); - - amount_t temp; - temp.parse(in, AMOUNT_PARSE_NO_REDUCE); - - char c; - if (! in.eof() && (c = peek_next_nonws(in)) != '@' && - c != ';' && ! in.eof()) { - in.seekg(beg, std::ios::beg); - - xpath_t xpath(in, (XPATH_PARSE_NO_REDUCE | XPATH_PARSE_RELAXED | - XPATH_PARSE_PARTIAL)); - - xpath_t::context_scope_t node_scope(scope, this); - amount = &set_attr(AMOUNT_ATTR, xpath.calc(node_scope)); - - //unsigned long end = (long)in.tellg(); - } else { - amount = &set_attr(AMOUNT_ATTR, temp); - } - - // jww (2007-04-30): This should be a string context, or perhaps a - // file context - POP_CONTEXT(context("While parsing transaction amount")); - - // Parse the optional cost (@ PER-UNIT-COST, @@ TOTAL-COST) - - if (in.good() && ! in.eof()) { - char c = peek_next_nonws(in); - if (c == '@') { - DEBUG("ledger.textual.parse", "Found a price indicator"); - bool per_unit = true; - in.get(c); - if (in.peek() == '@') { - in.get(c); - per_unit = false; - DEBUG("ledger.textual.parse", "And it's for a total price"); - } - - if (in.good() && ! in.eof()) { - amount_t temp; - - PUSH_CONTEXT(); - - //unsigned long beg = (long)in.tellg(); - - temp.parse(in); - - if (temp.sign() < 0) - throw_(parse_error, "A transaction's cost may not be negative"); - - //unsigned long end = (long)in.tellg(); - - POP_CONTEXT(context("While parsing transaction cost")); - - amount_t per_unit_cost(temp); - amount_t& base_amount(amount->as_amount_lval()); - if (per_unit) - temp *= base_amount.number(); - else - per_unit_cost /= base_amount.number(); - - value_t& cost = set_attr(COST_ATTR, temp); - - if (base_amount.commodity() && ! base_amount.commodity().annotated) { - assert(transaction); - assert(transaction->entry); - base_amount.annotate_commodity - (annotation_t(per_unit_cost, transaction->entry->actual_date(), - transaction->entry->code)); - } - - DEBUG("ledger.textual.parse", "Total cost is " << cost); - DEBUG("ledger.textual.parse", "Per-unit cost is " << per_unit_cost); - DEBUG("ledger.textual.parse", "Annotated amount is " << base_amount); - DEBUG("ledger.textual.parse", "Bare amount is " << base_amount.number()); - } - } - } - - amount->in_place_reduce(); - - DEBUG("ledger.textual.parse", "Reduced amount is " << *amount); -} - -void transaction_node_t::compile(xpath_t::scope_t& scope) -{ - parent_node_t& parent_node(*parent()); - - assert(parent_node.name_id() == ENTRY_NODE); - assert(parent_node.is_compiled()); - - entry_t * entry = downcast<entry_node_t>(parent_node).entry.get(); - - if (! transaction.get()) { - transaction.reset(new transaction_t); -#if 0 - entry->add_transaction(transaction.get()); -#endif - } - transaction->entry = entry; - - foreach (node_t * child, *this) { - switch (child->name_id()) { - case AMOUNT_EXPR_NODE: - parse_amount_expr(scope, child->as_terminal_node().text()); - break; - - case ACCOUNT_PATH_NODE: { - assert(entry); - - journal_t * journal = entry->journal; - assert(journal); - - transaction->account = - journal->find_account(child->as_terminal_node().text()); - - // jww (2007-05-18): Need to set an attribute that refers to the - // unique id of the account - break; - } - - default: - break; - } - } -} - -} // namespace xml -} // namespace ledger diff --git a/src/data/compile.h b/src/data/compile.h deleted file mode 100644 index d8b9f536..00000000 --- a/src/data/compile.h +++ /dev/null @@ -1,206 +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 _COMPILE_H -#define _COMPILE_H - -#include "node.h" -#include "journal.h" - -namespace ledger { -namespace xml { - -void compile_node(node_t& node, xml::xpath_t::scope_t& scope); - -#if 0 -class commodity_node_t : public parent_node_t -{ -public: - commodity_t * commodity; - - commodity_node_t(document_t * _document, - commodity_t * _commodity, - parent_node_t * _parent = NULL) - : parent_node_t(_document, _parent), commodity(_commodity) { - TRACE_CTOR(commodity_node_t, "document_t *, commodity_t *, parent_node_t *"); - set_name(document_t::COMMODITY); - } - virtual ~commodity_node_t() { - TRACE_DTOR(commodity_node_t); - } - - virtual node_t * children() const; -}; - -class amount_node_t : public parent_node_t -{ -public: - amount_t * amount; - - amount_node_t(document_t * _document, - amount_t * _amount, - parent_node_t * _parent = NULL) - : parent_node_t(_document, _parent), amount(_amount) { - TRACE_CTOR(amount_node_t, "document_t *, amount_t *, parent_node_t *"); - set_name(document_t::AMOUNT); - } - virtual ~amount_node_t() { - TRACE_DTOR(amount_node_t); - } - - virtual node_t * children() const; - - virtual value_t to_value() const { - return *amount; - } -}; -#endif - -class journal_node_t : public parent_node_t -{ -public: - shared_ptr<journal_t> journal; - - journal_node_t(nameid_t _name_id, - document_t& _document, - const optional<parent_node_t&>& _parent = none, - journal_t * _journal = NULL) - : parent_node_t(_name_id, _document, _parent), journal(_journal) { - TRACE_CTOR(journal_node_t, "document_t *, journal_t *, parent_node_t *"); - } - virtual ~journal_node_t() { - TRACE_DTOR(journal_node_t); - } - - void compile(xpath_t::scope_t& scope); -}; - -class entry_node_t : public parent_node_t -{ -public: - shared_ptr<entry_t> entry; - - entry_node_t(nameid_t _name_id, - document_t& _document, - const optional<parent_node_t&>& _parent = none, - entry_t * _entry = NULL) - : parent_node_t(_name_id, _document, _parent), entry(_entry) { - TRACE_CTOR(entry_node_t, "document_t&, parent_node_t, entry_t *"); - assert(_name_id == ENTRY_NODE); - } - virtual ~entry_node_t() { - TRACE_DTOR(entry_node_t); - } - - void compile(xpath_t::scope_t& scope); -}; - -class transaction_node_t : public parent_node_t -{ -public: - shared_ptr<transaction_t> transaction; - - transaction_node_t(nameid_t _name_id, - document_t& _document, - const optional<parent_node_t&>& _parent = none, - transaction_t * _transaction = NULL) - : parent_node_t(_name_id, _document, _parent), - transaction(_transaction) { - TRACE_CTOR(transaction_node_t, - "document_t&, parent_node_t, transaction_t *"); - assert(_name_id == TRANSACTION_NODE); - } - virtual ~transaction_node_t() { - TRACE_DTOR(transaction_node_t); - } - - void compile(xpath_t::scope_t& scope); - -private: - void parse_amount_expr(xpath_t::scope_t& scope, - const char * amount_expr); -}; - -#if 0 -class account_node_t : public parent_node_t -{ - account_t * account; - -public: - account_node_t(document_t * _document, account_t * _account, - parent_node_t * _parent = NULL) - : parent_node_t(_document, _parent), account(_account) { - TRACE_CTOR(account_node_t, "document_t *, account_t *, parent_node_t *"); - set_name(document_t::ACCOUNT); - } - virtual ~account_node_t() { - TRACE_DTOR(account_node_t); - } - - virtual node_t * children() const; -}; - -template <typename T> -inline typename T::node_type * -wrap_node(document_t * doc, T * item, void * parent_node = NULL) { - assert(false); - return NULL; -} - -template <> -inline transaction_t::node_type * -wrap_node(document_t * doc, transaction_t * xact, void * parent_node) { - return new transaction_node_t(doc, xact, (parent_node_t *)parent_node); -} - -template <> -inline entry_t::node_type * -wrap_node(document_t * doc, entry_t * entry, void * parent_node) { - return new entry_node_t(doc, entry, (parent_node_t *)parent_node); -} - -template <> -inline account_t::node_type * -wrap_node(document_t * doc, account_t * account, void * parent_node) { - return new account_node_t(doc, account, (parent_node_t *)parent_node); -} - -template <> -inline journal_t::node_type * -wrap_node(document_t * doc, journal_t * journal, void * parent_node) { - return new journal_node_t(doc, journal, (parent_node_t *)parent_node); -} -#endif - -} // namespace xml -} // namespace ledger - -#endif // _COMPILE_H diff --git a/src/data/document.cc b/src/data/document.cc deleted file mode 100644 index 41bf77a3..00000000 --- a/src/data/document.cc +++ /dev/null @@ -1,181 +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 "document.h" - -namespace ledger { -namespace xml { - -namespace { - const std::size_t ledger_builtins_size = 39; - const char * ledger_builtins[] = { - "account", - "account-path", - "amount", - "amount", - "amount-expr", - "arg", - "auto-entry", - "balance", - "checkin", - "cleared", - "code", - "commodity", - "commodity-conversion", - "commodity-nomarket", - "commodity-template", - "cost", - "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 = static_cast<int>(ledger_builtins_size); - - while (first <= last) { - int mid = (first + last) / 2; // compute mid point. - - int result; - if ((result = (static_cast<int>(name[0]) - - static_cast<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 "."; - case PARENT: - return ".."; - case ROOT: - return ""; - case ALL: - return "*"; - - default: - assert(id >= 10); - return ledger_builtins[id - 10]; - } - } - else if (names) { - assert(id >= 1000); - std::size_t 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/data/document.h b/src/data/document.h deleted file mode 100644 index 2eac4043..00000000 --- a/src/data/document.h +++ /dev/null @@ -1,152 +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 _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_ATTR, - 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, - COST_ATTR, - 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, LAST_BUILTIN = 10 - }; - - 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/data/jbuilder.cc b/src/data/jbuilder.cc deleted file mode 100644 index f37abca5..00000000 --- a/src/data/jbuilder.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. - */ - -#include "jbuilder.h" -#include "compile.h" - -namespace ledger { -namespace xml { - -void journal_builder_t::begin_node(const node_t::nameid_t name_id, - bool terminal) -{ - switch (name_id) { - case JOURNAL_NODE: - current = current->as_parent_node().create_child<journal_node_t>(name_id); - break; - case ENTRY_NODE: - current = current->as_parent_node().create_child<entry_node_t>(name_id); - break; - case TRANSACTION_NODE: - current = current->as_parent_node().create_child<transaction_node_t>(name_id); - break; - - default: - 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); - break; - } - - foreach (const attrs_list::value_type& pair, current_attrs) - current->set_attr(pair.first, pair.second.c_str()); - - current_attrs.clear(); -} - -} // namespace xml -} // namespace ledger diff --git a/src/data/jbuilder.h b/src/data/jbuilder.h deleted file mode 100644 index 4e109a35..00000000 --- a/src/data/jbuilder.h +++ /dev/null @@ -1,81 +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 _JBUILDER_H -#define _JBUILDER_H - -#include "builder.h" -#include "journal.h" - -namespace ledger { -namespace xml { - -/** - * @class journal_builder_t - * - * @brief This custom builder creates an XML-mirrored Ledger journal. - * - * Rather than simply creating a node_t hierarchy, as xml_builder_t - * does, this code creates the associated journal elements referred to - * by those nodes, and then refers to those elements via minimalist - * "shadow nodes". - * - * Thus, after building a <transaction> element, the element itself - * will have no children, but instead will point to a transaction_t - * object. If later an XPath expression desires to traverse the - * <transaction> element, all of the appropriate child nodes will be - * 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 document_builder_t -{ -public: - journal_t * journal; - - journal_builder_t(document_t& _document, journal_t * _journal) - : document_builder_t(_document), journal(_journal) {} - - virtual void set_start_position(std::istream& in) { - set_position(position_t(in.tellg(), 1)); - } - - virtual void set_position(const position_t& position) { - current_position = position; - } - - virtual void begin_node(const node_t::nameid_t name_id, - bool terminal = false); -}; - -} // namespace xml -} // namespace ledger - -#endif // _JBUILDER_H diff --git a/src/data/journal.cc b/src/data/journal.cc deleted file mode 100644 index bb33f4dc..00000000 --- a/src/data/journal.cc +++ /dev/null @@ -1,702 +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 "journal.h" -#include "xpath.h" -#include "mask.h" - -namespace ledger { - -const string version = PACKAGE_VERSION; - -bool transaction_t::use_effective_date = false; - -transaction_t::~transaction_t() -{ - TRACE_DTOR(transaction_t); -} - -moment_t transaction_t::actual_date() const -{ - if (! _date && entry) - return entry->actual_date(); - return *_date; -} - -moment_t transaction_t::effective_date() const -{ - if (! _date_eff && entry) - return entry->effective_date(); - return *_date_eff; -} - -bool transaction_t::valid() const -{ - if (! entry) { - DEBUG("ledger.validate", "transaction_t: ! entry"); - return false; - } - - if (state != UNCLEARED && state != CLEARED && state != PENDING) { - DEBUG("ledger.validate", "transaction_t: state is bad"); - return false; - } - - transactions_list::const_iterator i = - std::find(entry->transactions.begin(), - entry->transactions.end(), this); - if (i == entry->transactions.end()) { - DEBUG("ledger.validate", "transaction_t: ! found"); - return false; - } - - if (! account) { - DEBUG("ledger.validate", "transaction_t: ! account"); - return false; - } - - if (! amount.valid()) { - DEBUG("ledger.validate", "transaction_t: ! amount.valid()"); - return false; - } - - if (cost && ! cost->valid()) { - DEBUG("ledger.validate", "transaction_t: cost && ! cost->valid()"); - return false; - } - - return true; -} - -void entry_base_t::add_transaction(transaction_t * xact) -{ - transactions.push_back(xact); -} - -bool entry_base_t::remove_transaction(transaction_t * xact) -{ - transactions.remove(xact); - return true; -} - -bool entry_base_t::finalize() -{ - // Scan through and compute the total balance for the entry. This - // is used for auto-calculating the value of entries with no cost, - // and the per-unit price of unpriced commodities. - - value_t balance; - bool no_amounts = true; - bool saw_null = false; - - for (transactions_list::const_iterator x = transactions.begin(); - x != transactions.end(); - x++) - if (! (*x)->has_flags(TRANSACTION_VIRTUAL) || - (*x)->has_flags(TRANSACTION_BALANCE)) { - amount_t& p((*x)->cost ? *(*x)->cost : (*x)->amount); - if (p) { - if (no_amounts) { - balance = p; - no_amounts = false; - } else { - balance += p; - } - - assert((*x)->amount); - if ((*x)->cost && (*x)->amount.commodity().annotated) { - annotated_commodity_t& - ann_comm(static_cast<annotated_commodity_t&> - ((*x)->amount.commodity())); - if (ann_comm.details.price) - balance += (*ann_comm.details.price * (*x)->amount.number() - - *((*x)->cost)); - } - } else { - saw_null = true; - } - } - - // If it's a null entry, then let the user have their fun - if (no_amounts) - return true; - - // If there is only one transaction, balance against the basket - // account if one has been set. - - if (journal && journal->basket && transactions.size() == 1) { - assert(balance.is_amount()); - transaction_t * nxact = new transaction_t(journal->basket); - // The amount doesn't need to be set because the code below will - // balance this transaction against the other. - add_transaction(nxact); - nxact->add_flags(TRANSACTION_CALCULATED); - } - - // If the first transaction of a two-transaction entry is of a - // different commodity than the other, and it has no per-unit price, - // determine its price by dividing the unit count into the value of - // the balance. This is done for the last eligible commodity. - - if (! saw_null && balance && balance.is_balance() && - balance.as_balance().amounts.size() == 2) { - transactions_list::const_iterator x = transactions.begin(); - assert((*x)->amount); - commodity_t& this_comm = (*x)->amount.commodity(); - - balance_t::amounts_map::const_iterator this_bal = - balance.as_balance().amounts.find(&this_comm); - balance_t::amounts_map::const_iterator other_bal = - balance.as_balance().amounts.begin(); - if (this_bal == other_bal) - other_bal++; - - amount_t per_unit_cost = - amount_t((*other_bal).second / (*this_bal).second.number()).unround(); - - for (; x != transactions.end(); x++) { - if ((*x)->cost || (*x)->has_flags(TRANSACTION_VIRTUAL) || - (*x)->amount.commodity() != this_comm) - continue; - - balance -= (*x)->amount; - - entry_t * entry = dynamic_cast<entry_t *>(this); - - if ((*x)->amount.commodity() && - ! (*x)->amount.commodity().annotated) - (*x)->amount.annotate_commodity - (annotation_t(per_unit_cost.abs(), - entry ? entry->actual_date() : optional<moment_t>(), - entry ? entry->code : optional<string>())); - - (*x)->cost = - (per_unit_cost * (*x)->amount.number()); - balance += *(*x)->cost; - } - } - - // Walk through each of the transactions, fixing up any that we - // can, and performing any on-the-fly calculations. - - bool empty_allowed = true; - - for (transactions_list::const_iterator x = transactions.begin(); - x != transactions.end(); - x++) { - if ((*x)->amount || - ((*x)->has_flags(TRANSACTION_VIRTUAL) && - ! (*x)->has_flags(TRANSACTION_BALANCE))) - continue; - - if (! empty_allowed) - throw_(std::logic_error, - "Only one transaction with null amount allowed per entry"); - empty_allowed = false; - - // If one transaction gives no value at all, its value will become - // the inverse of the value of the others. If multiple - // commodities are involved, multiple transactions will be - // generated to balance them all. - - const balance_t * bal = NULL; - switch (balance.type()) { - case value_t::BALANCE_PAIR: - bal = &balance.as_balance_pair().quantity(); - // fall through... - - case value_t::BALANCE: - if (! bal) - bal = &balance.as_balance(); - - if (bal->amounts.size() < 2) { - balance.cast(value_t::AMOUNT); - } else { - bool first = true; - for (balance_t::amounts_map::const_iterator - i = bal->amounts.begin(); - i != bal->amounts.end(); - i++) { - amount_t amt = (*i).second.negate(); - - if (first) { - (*x)->amount = amt; - first = false; - } else { - transaction_t * nxact = new transaction_t((*x)->account); - add_transaction(nxact); - nxact->add_flags(TRANSACTION_CALCULATED); - nxact->amount = amt; - } - - balance += amt; - } - break; - } - // fall through... - - case value_t::AMOUNT: - (*x)->amount = balance.as_amount().negate(); - (*x)->add_flags(TRANSACTION_CALCULATED); - - balance += (*x)->amount; - break; - - default: - break; - } - } - - if (balance) { -#if 1 - throw_(balance_error, "Entry does not balance"); -#else - error * err = - new balance_error("Entry does not balance", - new entry_context(*this, "While balancing entry:")); - err->context.push_front - (new value_context(balance, "Unbalanced remainder is:")); - throw err; -#endif - } - - return true; -} - -entry_t::entry_t(const entry_t& e) - : entry_base_t(e), _date(e._date), _date_eff(e._date_eff), - code(e.code), payee(e.payee) -{ - TRACE_CTOR(entry_t, "copy"); - for (transactions_list::const_iterator i = transactions.begin(); - i != transactions.end(); - i++) - (*i)->entry = this; -} - -bool entry_t::get_state(transaction_t::state_t * state) const -{ - bool first = true; - bool hetero = false; - - for (transactions_list::const_iterator i = transactions.begin(); - i != transactions.end(); - i++) { - if (first) { - *state = (*i)->state; - first = false; - } - else if (*state != (*i)->state) { - hetero = true; - break; - } - } - - return ! hetero; -} - -void entry_t::add_transaction(transaction_t * xact) -{ - xact->entry = this; - entry_base_t::add_transaction(xact); -} - -bool entry_t::valid() const -{ - if (! is_valid_moment(_date) || ! journal) { - DEBUG("ledger.validate", "entry_t: ! _date || ! journal"); - return false; - } - - for (transactions_list::const_iterator i = transactions.begin(); - i != transactions.end(); - i++) - if ((*i)->entry != this || ! (*i)->valid()) { - DEBUG("ledger.validate", "entry_t: transaction not valid"); - return false; - } - - return true; -} - -auto_entry_t::auto_entry_t() -{ - TRACE_CTOR(auto_entry_t, ""); -} - -auto_entry_t::auto_entry_t(const string& _predicate) - : predicate(new xml::xpath_t(_predicate)) -{ - TRACE_CTOR(auto_entry_t, "const string&"); -} - -auto_entry_t::~auto_entry_t() { - TRACE_DTOR(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()); - - for (transactions_list::iterator i = initial_xacts.begin(); - i != initial_xacts.end(); - i++) { - // jww (2006-09-10): Create a scope here based on entry - if (predicate->calc((xml::node_t *) NULL)) { - for (transactions_list::iterator t = transactions.begin(); - t != transactions.end(); - t++) { - amount_t amt; - assert((*t)->amount); - if (! (*t)->amount.commodity()) { - if (! post) - continue; - assert((*i)->amount); - amt = *(*i)->amount * *(*t)->amount; - } else { - if (post) - continue; - amt = *(*t)->amount; - } - - account_t * account = (*t)->account; - string fullname = account->fullname(); - assert(! fullname.empty()); - if (fullname == "$account" || fullname == "@account") - account = (*i)->account; - - transaction_t * xact - = new transaction_t(account, amt, (*t)->flags() | TRANSACTION_AUTO); - entry.add_transaction(xact); - } - } - } -#endif -} - -account_t::~account_t() -{ - TRACE_DTOR(account_t); - - for (accounts_map::iterator i = accounts.begin(); - i != accounts.end(); - i++) - checked_delete((*i).second); -} - -account_t * account_t::find_account(const string& name, - const bool auto_create) -{ - accounts_map::const_iterator i = accounts.find(name); - if (i != accounts.end()) - return (*i).second; - - char buf[256]; - - string::size_type sep = name.find(':'); - assert(sep < 256|| sep == string::npos); - - const char * first, * rest; - if (sep == string::npos) { - first = name.c_str(); - rest = NULL; - } else { - std::strncpy(buf, name.c_str(), sep); - buf[sep] = '\0'; - - first = buf; - rest = name.c_str() + sep + 1; - } - - account_t * account; - - i = accounts.find(first); - if (i == accounts.end()) { - if (! auto_create) - return NULL; - - account = new account_t(this, first); - account->journal = journal; - - std::pair<accounts_map::iterator, bool> result - = accounts.insert(accounts_map::value_type(first, account)); - assert(result.second); - } else { - account = (*i).second; - } - - if (rest) - account = account->find_account(rest, auto_create); - - return account; -} - -static inline -account_t * find_account_re_(account_t * account, const mask_t& regexp) -{ - if (regexp.match(account->fullname())) - return account; - - for (accounts_map::iterator i = account->accounts.begin(); - i != account->accounts.end(); - i++) - if (account_t * a = find_account_re_((*i).second, regexp)) - return a; - - return NULL; -} - -account_t * journal_t::find_account_re(const string& regexp) -{ - return find_account_re_(master, mask_t(regexp)); -} - -string account_t::fullname() const -{ - if (! _fullname.empty()) { - return _fullname; - } else { - const account_t * first = this; - string fullname = name; - - while (first->parent) { - first = first->parent; - if (! first->name.empty()) - fullname = first->name + ":" + fullname; - } - - _fullname = fullname; - - return fullname; - } -} - -std::ostream& operator<<(std::ostream& out, const account_t& account) -{ - out << account.fullname(); - return out; -} - -bool account_t::valid() const -{ - if (depth > 256 || ! journal) { - DEBUG("ledger.validate", "account_t: depth > 256 || ! journal"); - return false; - } - - for (accounts_map::const_iterator i = accounts.begin(); - i != accounts.end(); - i++) { - if (this == (*i).second) { - DEBUG("ledger.validate", "account_t: parent refers to itself!"); - return false; - } - - if (! (*i).second->valid()) { - DEBUG("ledger.validate", "account_t: child not valid"); - return false; - } - } - - return true; -} - -journal_t::~journal_t() -{ - TRACE_DTOR(journal_t); - - assert(master); - checked_delete(master); - - // Don't bother unhooking each entry's transactions from the - // accounts they refer to, because all accounts are about to - // be deleted. - for (entries_list::iterator i = entries.begin(); - i != entries.end(); - i++) { - if (! item_pool || - reinterpret_cast<char *>(*i) < item_pool || - reinterpret_cast<char *>(*i) >= item_pool_end) { - checked_delete(*i); - } else { - (*i)->~entry_t(); - } - } - - for (auto_entries_list::iterator i = auto_entries.begin(); - i != auto_entries.end(); - i++) - if (! item_pool || - reinterpret_cast<char *>(*i) < item_pool || - reinterpret_cast<char *>(*i) >= item_pool_end) - checked_delete(*i); - else - (*i)->~auto_entry_t(); - - for (period_entries_list::iterator i = period_entries.begin(); - i != period_entries.end(); - i++) - if (! item_pool || - reinterpret_cast<char *>(*i) < item_pool || - reinterpret_cast<char *>(*i) >= item_pool_end) - checked_delete(*i); - else - (*i)->~period_entry_t(); - - if (item_pool) - checked_array_delete(item_pool); -} - -bool journal_t::add_entry(entry_t * entry) -{ - entry->journal = this; - - if (! run_hooks(entry_finalize_hooks, *entry, false) || - ! entry->finalize() || - ! run_hooks(entry_finalize_hooks, *entry, true)) { - entry->journal = NULL; - return false; - } - - entries.push_back(entry); - - for (transactions_list::const_iterator i = entry->transactions.begin(); - i != entry->transactions.end(); - i++) - if ((*i)->cost) { - assert((*i)->amount); - (*i)->amount.commodity().add_price(entry->date(), - *(*i)->cost / (*i)->amount.number()); - } - - return true; -} - -bool journal_t::remove_entry(entry_t * entry) -{ - bool found = false; - entries_list::iterator i; - for (i = entries.begin(); i != entries.end(); i++) - if (*i == entry) { - found = true; - break; - } - if (! found) - return false; - - entries.erase(i); - entry->journal = NULL; - - return true; -} - -bool journal_t::valid() const -{ - if (! master->valid()) { - DEBUG("ledger.validate", "journal_t: master not valid"); - return false; - } - - for (entries_list::const_iterator i = entries.begin(); - i != entries.end(); - i++) - if (! (*i)->valid()) { - DEBUG("ledger.validate", "journal_t: entry not valid"); - return false; - } - - return true; -} - -void print_entry(std::ostream& out, const entry_base_t& entry_base, - const string& prefix) -{ - string print_format; - - if (dynamic_cast<const entry_t *>(&entry_base)) { - print_format = (prefix + "%D %X%C%P\n" + - prefix + " %-34A %12o\n%/" + - prefix + " %-34A %12o\n"); - } - else if (const auto_entry_t * entry = - dynamic_cast<const auto_entry_t *>(&entry_base)) { - out << "= " << entry->predicate->expr << '\n'; - print_format = prefix + " %-34A %12o\n"; - } - else if (const period_entry_t * entry = - dynamic_cast<const period_entry_t *>(&entry_base)) { - out << "~ " << entry->period_string << '\n'; - print_format = prefix + " %-34A %12o\n"; - } - else { - assert(false); - } - -#if 0 - format_entries formatter(out, print_format); - walk_transactions(const_cast<transactions_list&>(entry_base.transactions), - formatter); - formatter.flush(); - - clear_transaction_xdata cleaner; - walk_transactions(const_cast<transactions_list&>(entry_base.transactions), - cleaner); -#endif -} - -#if 0 -void entry_context::describe(std::ostream& out) const throw() -{ - if (! desc.empty()) - out << desc << std::endl; - - print_entry(out, entry, " "); -} - -xact_context::xact_context(const ledger::transaction_t& _xact, - const string& desc) throw() - : file_context("", 0, desc), xact(_xact) -{ - const ledger::strings_list& sources(xact.entry->journal->sources); - unsigned int x = 0; - for (ledger::strings_list::const_iterator i = sources.begin(); - i != sources.end(); - i++, x++) - if (x == xact.entry->src_idx) { - file = *i; - break; - } - line = xact.beg_line; -} -#endif - -} // namespace ledger diff --git a/src/data/journal.h b/src/data/journal.h deleted file mode 100644 index 821f6910..00000000 --- a/src/data/journal.h +++ /dev/null @@ -1,439 +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 _JOURNAL_H -#define _JOURNAL_H - -#include "amount.h" -#include "xpath.h" - -namespace ledger { - -// These flags persist with the object -#define TRANSACTION_NORMAL 0x0000 -#define TRANSACTION_VIRTUAL 0x0001 -#define TRANSACTION_BALANCE 0x0002 -#define TRANSACTION_AUTO 0x0004 -#define TRANSACTION_BULK_ALLOC 0x0008 -#define TRANSACTION_CALCULATED 0x0010 - -class entry_t; -class account_t; - -class transaction_t : public supports_flags<> -{ - public: - enum state_t { UNCLEARED, CLEARED, PENDING }; - - entry_t * entry; - state_t state; - account_t * account; - optional<moment_t> _date; - optional<moment_t> _date_eff; - amount_t amount; - optional<amount_t> cost; - optional<string> note; - - static bool use_effective_date; - - explicit transaction_t(account_t * _account = NULL) - : supports_flags<>(TRANSACTION_NORMAL), entry(NULL), - state(UNCLEARED), account(_account) { - TRACE_CTOR(transaction_t, "account_t *"); - } - explicit transaction_t(account_t * _account, - const amount_t& _amount, - unsigned int _flags = TRANSACTION_NORMAL, - const optional<string> _note = none) - : supports_flags<>(_flags), entry(NULL), state(UNCLEARED), - account(_account), amount(_amount), note(_note) { - TRACE_CTOR(transaction_t, - "account_t *, const amount_t&, unsigned int, const string&"); - } - explicit transaction_t(const transaction_t& xact) - : supports_flags<>(xact), - entry(xact.entry), - state(xact.state), - account(xact.account), - _date(xact._date), - _date_eff(xact._date_eff), - amount(xact.amount), - cost(xact.cost), - note(xact.note) { - TRACE_CTOR(transaction_t, "copy"); - } - ~transaction_t(); - - moment_t actual_date() const; - moment_t effective_date() const; - moment_t date() const { - if (use_effective_date) - return effective_date(); - else - return actual_date(); - } - - bool valid() const; -}; - -#if 0 -class xact_context : public file_context { - public: - const transaction_t& xact; - - xact_context(const transaction_t& _xact, - const string& desc = "") throw(); - virtual ~xact_context() throw() {} -}; -#endif - -class journal_t; - -typedef std::list<transaction_t *> transactions_list; - -class entry_base_t -{ - public: - journal_t * journal; - transactions_list transactions; - - entry_base_t() : journal(NULL) { - TRACE_CTOR(entry_base_t, ""); - } - entry_base_t(const entry_base_t& e) : journal(NULL) - { - TRACE_CTOR(entry_base_t, "copy"); - for (transactions_list::const_iterator i = e.transactions.begin(); - i != e.transactions.end(); - i++) - transactions.push_back(new transaction_t(**i)); - } - virtual ~entry_base_t() { - TRACE_DTOR(entry_base_t); - for (transactions_list::iterator i = transactions.begin(); - i != transactions.end(); - i++) - if (! (*i)->has_flags(TRANSACTION_BULK_ALLOC)) - checked_delete(*i); - else - (*i)->~transaction_t(); - } - - bool operator==(const entry_base_t& entry) { - return this == &entry; - } - bool operator!=(const entry_base_t& entry) { - return ! (*this == entry); - } - - virtual void add_transaction(transaction_t * xact); - virtual bool remove_transaction(transaction_t * xact); - - virtual bool finalize(); - virtual bool valid() const = 0; -}; - -class entry_t : public entry_base_t -{ -public: - moment_t _date; - optional<moment_t> _date_eff; - optional<string> code; - string payee; - - entry_t() { - TRACE_CTOR(entry_t, ""); - } - entry_t(const entry_t& e); - - virtual ~entry_t() { - TRACE_DTOR(entry_t); - } - - moment_t actual_date() const { - return _date; - } - moment_t effective_date() const { - return _date_eff ? *_date_eff : _date; - } - moment_t date() const { - if (transaction_t::use_effective_date) - return effective_date(); - else - return actual_date(); - } - - virtual void add_transaction(transaction_t * xact); - virtual bool valid() const; - - bool get_state(transaction_t::state_t * state) const; -}; - -struct entry_finalizer_t { - virtual ~entry_finalizer_t() {} - virtual bool operator()(entry_t& entry, bool post) = 0; -}; - -void print_entry(std::ostream& out, const entry_base_t& entry, - const string& prefix = ""); - -#if 0 -class entry_context : public error_context { - public: - const entry_base_t& entry; - - entry_context(const entry_base_t& _entry, - const string& _desc = "") throw() - : error_context(_desc), entry(_entry) {} - virtual ~entry_context() throw() {} - - virtual void describe(std::ostream& out) const throw(); -}; -#endif - -class auto_entry_t : public entry_base_t -{ -public: - scoped_ptr<xml::xpath_t> predicate; - - auto_entry_t(); - auto_entry_t(const string& _predicate); - virtual ~auto_entry_t(); - - virtual void extend_entry(entry_base_t& entry, bool post); - virtual bool valid() const { - return true; - } -}; - -struct auto_entry_finalizer_t : public entry_finalizer_t { - journal_t * journal; - auto_entry_finalizer_t(journal_t * _journal) : journal(_journal) {} - virtual bool operator()(entry_t& entry, bool post); -}; - - -class period_entry_t : public entry_base_t -{ - public: - interval_t period; - string period_string; - - period_entry_t() { - TRACE_CTOR(period_entry_t, ""); - } - period_entry_t(const string& _period) - : period(_period), period_string(_period) { - TRACE_CTOR(period_entry_t, "const string&"); - } - period_entry_t(const period_entry_t& e) - : entry_base_t(e), period(e.period), period_string(e.period_string) { - TRACE_CTOR(period_entry_t, "copy"); - } - - virtual ~period_entry_t() { - TRACE_DTOR(period_entry_t); - } - - virtual bool valid() const { - return period; - } -}; - - -typedef std::map<const string, account_t *> accounts_map; - -class account_t -{ - public: - typedef unsigned long ident_t; - - journal_t * journal; - account_t * parent; - string name; - optional<string> note; - unsigned short depth; - accounts_map accounts; - - mutable ident_t ident; - mutable string _fullname; - - account_t(account_t * _parent = NULL, - const string& _name = "", - const optional<string> _note = none) - : parent(_parent), name(_name), note(_note), - depth(parent ? parent->depth + 1 : 0), ident(0) { - TRACE_CTOR(account_t, "account_t *, const string&, const string&"); - } - ~account_t(); - - operator string() const { - return fullname(); - } - string fullname() const; - - void add_account(account_t * acct) { - accounts.insert(accounts_map::value_type(acct->name, acct)); - acct->journal = journal; - } - bool remove_account(account_t * acct) { - accounts_map::size_type n = accounts.erase(acct->name); - acct->journal = NULL; - return n > 0; - } - - account_t * find_account(const string& name, bool auto_create = true); - - bool valid() const; - - friend class journal_t; -}; - -std::ostream& operator<<(std::ostream& out, const account_t& account); - - -struct func_finalizer_t : public entry_finalizer_t { - typedef bool (*func_t)(entry_t& entry, bool post); - func_t func; - func_finalizer_t(func_t _func) : func(_func) {} - func_finalizer_t(const func_finalizer_t& other) : - entry_finalizer_t(), func(other.func) {} - virtual bool operator()(entry_t& entry, bool post) { - return func(entry, post); - } -}; - -template <typename T> -void add_hook(std::list<T>& list, T obj, const bool prepend = false) { - if (prepend) - list.push_front(obj); - else - list.push_back(obj); -} - -template <typename T> -void remove_hook(std::list<T>& list, T obj) { - list.remove(obj); -} - -template <typename T, typename Data> -bool run_hooks(std::list<T>& list, Data& item, bool post) { - for (typename std::list<T>::const_iterator i = list.begin(); - i != list.end(); - i++) - if (! (*(*i))(item, post)) - return false; - return true; -} - - -typedef std::list<entry_t *> entries_list; -typedef std::list<auto_entry_t *> auto_entries_list; -typedef std::list<period_entry_t *> period_entries_list; -typedef std::list<path> path_list; -typedef std::list<string> strings_list; - -class journal_t -{ - public: - account_t * master; - account_t * basket; - entries_list entries; - path_list sources; - optional<path> price_db; - char * item_pool; - char * item_pool_end; - - auto_entries_list auto_entries; - period_entries_list period_entries; - mutable accounts_map accounts_cache; - - std::list<entry_finalizer_t *> entry_finalize_hooks; - - journal_t() : basket(NULL), item_pool(NULL), item_pool_end(NULL) { - TRACE_CTOR(journal_t, ""); - master = new account_t(NULL, ""); - master->journal = this; - } - ~journal_t(); - - void add_account(account_t * acct) { - master->add_account(acct); - acct->journal = this; - } - bool remove_account(account_t * acct) { - return master->remove_account(acct); - acct->journal = NULL; - } - - account_t * find_account(const string& name, bool auto_create = true) { - accounts_map::iterator c = accounts_cache.find(name); - if (c != accounts_cache.end()) - return (*c).second; - - account_t * account = master->find_account(name, auto_create); - accounts_cache.insert(accounts_map::value_type(name, account)); - account->journal = this; - return account; - } - account_t * find_account_re(const string& regexp); - - bool add_entry(entry_t * entry); - bool remove_entry(entry_t * entry); - - void add_entry_finalizer(entry_finalizer_t * finalizer) { - add_hook<entry_finalizer_t *>(entry_finalize_hooks, finalizer); - } - void remove_entry_finalizer(entry_finalizer_t * finalizer) { - remove_hook<entry_finalizer_t *>(entry_finalize_hooks, finalizer); - } - - bool valid() const; -}; - -inline void extend_entry_base(journal_t * journal, entry_base_t& entry, - bool post) { - for (auto_entries_list::iterator i = journal->auto_entries.begin(); - i != journal->auto_entries.end(); - i++) - (*i)->extend_entry(entry, post); -} - -inline bool auto_entry_finalizer_t::operator()(entry_t& entry, bool post) { - extend_entry_base(journal, entry, post); - return true; -} - -extern const string version; - -} // namespace ledger - -#endif // _JOURNAL_H diff --git a/src/data/node.cc b/src/data/node.cc deleted file mode 100644 index 0ca0a04c..00000000 --- a/src/data/node.cc +++ /dev/null @@ -1,130 +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 "node.h" -#include "document.h" - -namespace ledger { -namespace xml { - -const char * node_t::name() const -{ - return *document().lookup_name(name_id()); -} - -value_t& node_t::set_attr(const string& _name, const char * value) -{ - nameid_t name_id = document().register_name(_name); - return set_attr(name_id, value); -} - -value_t& node_t::set_attr(const string& _name, const value_t& value) -{ - nameid_t name_id = document().register_name(_name); - return set_attr(name_id, value); -} - -optional<value_t&> node_t::get_attr(const string& _name) -{ - optional<nameid_t> name_id = document().lookup_name_id(_name); - if (name_id) - return get_attr(*name_id); - else - return none; -} - -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 node_t::print_attributes(std::ostream& out) const -{ - if (attributes) { -#if 1 - foreach (const attr_pair& attr, *attributes) - out << ' ' << *document().lookup_name(attr.first) - << "=\"" << attr.second << "\""; -#else - foreach (const attr_pair& attr, attributes->get<0>()) - out << ' ' << *document().lookup_name(attr.first) - << "=\"" << attr.second << "\""; -#endif - } - - IF_VERIFY() - out << " type=\"parent_node_t\""; -} - -void parent_node_t::print(std::ostream& out) const -{ - out << '<' << name(); - print_attributes(out); - out << '>'; - - foreach (node_t * child, *this) - child->print(out); - - out << "</" << name() << '>'; -} - -void terminal_node_t::print(std::ostream& out) const -{ - if (data.empty()) { - out << '<' << name(); - print_attributes(out); - out << " />"; - } else { - out << '<' << name(); - print_attributes(out); - out << '>'; - output_xml_string(out, text()); - out << "</" << name() << '>'; - } -} - -} // namespace xml -} // namespace ledger diff --git a/src/data/node.h b/src/data/node.h deleted file mode 100644 index 36964bdf..00000000 --- a/src/data/node.h +++ /dev/null @@ -1,352 +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 _NODE_H -#define _NODE_H - -#include "value.h" - -namespace ledger { -namespace xml { - -#define XML_NODE_IS_PARENT 0x1 - -DECLARE_EXCEPTION(conversion_error); - -class document_t; -class parent_node_t; -class terminal_node_t; - -class node_t : public supports_flags<>, public noncopyable -{ -public: - typedef uint_fast16_t nameid_t; - - // This has to be public so that multi_index_container can reference - // it in parent_node_t. - nameid_t name_id_; - -protected: - document_t& document_; - optional<parent_node_t&> parent_; - -#if 1 - typedef std::map<const nameid_t, value_t> attributes_t; - typedef std::pair<const nameid_t, value_t> attr_pair; -#else - typedef std::pair<nameid_t, value_t> 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; - - typedef attributes_t::nth_index<0>::type attributes_by_order; - typedef attributes_t::nth_index<1>::type attributes_hashed; -#endif - - optional<attributes_t> attributes; - -public: - bool compiled; // so that compile_node() can access it - - 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); - } - - void extract(); - - bool is_compiled() const { - return compiled; - } - - 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 downcast<parent_node_t>(*this); - } - const parent_node_t& as_parent_node() const { - return const_cast<node_t *>(this)->as_parent_node(); - } - - bool is_terminal_node() const { - return ! has_flags(XML_NODE_IS_PARENT); - } - terminal_node_t& as_terminal_node() { - if (! is_terminal_node()) - throw_(std::logic_error, "Request to cast parent node to a leaf node"); - return downcast<terminal_node_t>(*this); - } - const terminal_node_t& as_terminal_node() const { - return const_cast<node_t *>(this)->as_terminal_node(); - } - - virtual value_t to_value() const = 0; - virtual void print(std::ostream& out) const = 0; - virtual void print_attributes(std::ostream& out) const; - - 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_; - } - - value_t& set_attr(const string& _name, const char * value); - value_t& set_attr(const string& _name, const value_t& value); - - value_t& set_attr(const nameid_t _name_id, const char * value) { - return set_attr(_name_id, string_value(value)); - } - value_t& set_attr(const nameid_t _name_id, const value_t& value) { - if (! attributes) - attributes = attributes_t(); - - attributes_t::iterator i = attributes->find(_name_id); - if (i == attributes->end()) { - std::pair<attributes_t::iterator, bool> result = - attributes->insert(attr_pair(_name_id, value)); - assert(result.second); - return (*result.first).second; - } else { - i->second = value; - return i->second; - } - } - - optional<value_t&> get_attr(const string& _name); - optional<value_t&> get_attr(const nameid_t _name_id) { - if (attributes) { -#if 1 - attributes_t::iterator i = attributes->find(_name_id); - if (i != attributes->end()) - return (*i).second; -#else - typedef attributes_t::nth_index<1>::type attributes_by_name; - - const 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; -#endif - } - return none; - } - - optional<const value_t&> get_attr(const string& _name) const { - if (optional<value_t&> value = - const_cast<node_t *>(this)->get_attr(_name)) - return *value; - else - return none; - } - optional<const value_t&> get_attr(const nameid_t _name_id) const { - if (optional<value_t&> value = - const_cast<node_t *>(this)->get_attr(_name_id)) - return *value; - else - 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); - return child; - } - - void remove_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"); - ptr_index.erase(i); - } - - void delete_child(node_t * child) { - remove_child(child); - checked_delete(child); - } - - 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(); - } - - std::size_t size() const { - return children.get<0>().size(); - } - - 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"); - return NULL_VALUE; - } - - void print(std::ostream& out) const; -}; - -inline void node_t::extract() -{ - if (parent_) - parent_->remove_child(this); -} - -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 value_t(text(), true); - } - - void print(std::ostream& out) const; -}; - -} // namespace xml -} // namespace ledger - -#endif // _NODE_H diff --git a/src/data/parser.h b/src/data/parser.h deleted file mode 100644 index ecc73a6f..00000000 --- a/src/data/parser.h +++ /dev/null @@ -1,138 +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 _PARSER_H -#define _PARSER_H - -#include "utils.h" -#include "builder.h" - -namespace ledger { - -class account_t; -class journal_t; - -class parser_t -{ - public: - virtual ~parser_t() {} - - virtual bool test(std::istream& in) const = 0; - - virtual std::size_t parse(std::istream& in, - const path& pathname, - xml::builder_t& builder) = 0; -}; - -DECLARE_EXCEPTION(parse_error); - -/************************************************************************ - * - * General utility parsing functions - */ - -inline char * skip_ws(char * ptr) { - while (*ptr == ' ' || *ptr == '\t' || *ptr == '\n') - ptr++; - return ptr; -} - -inline char * next_element(char * buf, bool variable = false) { - for (char * p = buf; *p; p++) { - if (! (*p == ' ' || *p == '\t')) - continue; - - if (! variable) { - *p = '\0'; - return skip_ws(p + 1); - } - else if (*p == '\t') { - *p = '\0'; - return skip_ws(p + 1); - } - else if (*(p + 1) == ' ') { - *p = '\0'; - return skip_ws(p + 2); - } - } - return NULL; -} - -inline char peek_next_nonws(std::istream& in) { - char c = in.peek(); - while (! in.eof() && std::isspace(c)) { - in.get(c); - c = in.peek(); - } - return c; -} - -#define READ_INTO(str, targ, size, var, cond) { \ - char * _p = targ; \ - var = str.peek(); \ - while (! str.eof() && var != '\n' && (cond) && _p - targ < size) { \ - str.get(var); \ - if (str.eof()) \ - break; \ - if (var == '\\') { \ - str.get(var); \ - if (in.eof()) \ - break; \ - } \ - *_p++ = var; \ - var = str.peek(); \ - } \ - *_p = '\0'; \ -} - -#define READ_INTO_(str, targ, size, var, idx, cond) { \ - char * _p = targ; \ - var = str.peek(); \ - while (! str.eof() && var != '\n' && (cond) && _p - targ < size) { \ - str.get(var); \ - if (str.eof()) \ - break; \ - idx++; \ - if (var == '\\') { \ - str.get(var); \ - if (in.eof()) \ - break; \ - idx++; \ - } \ - *_p++ = var; \ - var = str.peek(); \ - } \ - *_p = '\0'; \ -} - -} // namespace ledger - -#endif // _PARSER_H diff --git a/src/data/textual.cc b/src/data/textual.cc deleted file mode 100644 index 9bee6c39..00000000 --- a/src/data/textual.cc +++ /dev/null @@ -1,480 +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 "textual.h" - -namespace ledger { - -using namespace xml; - -#define MAX_LINE 1024 - -typedef builder_t::position_t position_t; - -void parse_transaction(builder_t& builder, - char * line, - position_t& end_of_line) -{ - // First cut up the input line into its various parts. - - char * state = NULL; - char * account_path = NULL; - char * amount = NULL; - char * note = NULL; - - char * p = line; - - if (*p == '*' || *p == '!') - state = p++; - - account_path = skip_ws(p); - - amount = next_element(account_path, true); - if (amount) { - char * p = amount; - while (*p && *p != ';') - p++; - - if (*p == ';') { - *p++ = '\0'; - note = skip_ws(p); - } - - p = amount + (std::strlen(amount) - 1); - while (p > amount && std::isspace(*p)) - p--; - - if (std::isspace(*(p + 1))) - *++p = '\0'; - } - - // Setup the details for this node - - if (state) { - switch (*state) { - case '*': - builder.push_attr(CLEARED_ATTR, "yes"); - break; - case '!': - builder.push_attr(PENDING_ATTR, "yes"); - break; - } - } - - builder.begin_node(TRANSACTION_NODE); - - // Parse the account name - - char * b = &account_path[0]; - char * e = &account_path[std::strlen(account_path) - 1]; - if ((*b == '[' && *e == ']') || - (*b == '(' && *e == ')')) { - builder.push_attr(VIRTUAL_ATTR, "yes"); - if (*b == '[') - builder.push_attr(BALANCE_ATTR, "yes"); - *account_path++ = '\0'; - *e = '\0'; - } - - builder.begin_node(ACCOUNT_PATH_NODE, true); - builder.append_text(account_path); - builder.end_node(ACCOUNT_PATH_NODE); - - // Parse the optional amount - - if (amount) { - builder.begin_node(AMOUNT_EXPR_NODE, true); - builder.append_text(amount); - builder.end_node(AMOUNT_EXPR_NODE); - } - - // Parse the optional note - - if (note) { - builder.begin_node(NOTE_NODE, true); - builder.append_text(note); - builder.end_node(NOTE_NODE); - } - - builder.end_node(TRANSACTION_NODE, end_of_line); -} - -bool parse_transactions(std::istream& in, builder_t& builder) -{ - TRACE_START(entry_xacts, 1, "Time spent parsing transactions:"); - - bool added = false; - - while (! in.eof() && (in.peek() == ' ' || in.peek() == '\t')) { - static char line[MAX_LINE + 1]; - line[0] = '\0'; - in.getline(line, MAX_LINE); - if (in.eof() || line[0] == '\0') - break; - - position_t end_of_line(builder.position()); - end_of_line.offset += std::strlen(line) + 1; - end_of_line.linenum++; - - char * p = skip_ws(line); - if (! *p || *p == '\r' || *p == '\n') - break; - - parse_transaction(builder, line, end_of_line); - added = true; - } - - TRACE_STOP(entry_xacts, 1); - - return added; -} - -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:"); - - // First cut up the input line into its various parts - - char * date = NULL; - char * date_eff = NULL; - char * statep = NULL; - char * code = NULL; - char * payee = NULL; - - date = line; - - char * p = line; - - while (*p && (std::isdigit(*p) || *p == '/' || *p == '.' || *p == '-')) - p++; - assert(*p); - - if (*p == '=') { - *p++ = '\0'; - date_eff = p; - - while (*p && (std::isdigit(*p) || *p == '/' || *p == '.' || *p == '-')) - p++; - assert(*p); - } else { - *p++ = '\0'; - } - - p = skip_ws(p); - - if (*p == '*' || *p == '!') { - statep = p; - p++; *p++ = '\0'; - - p = skip_ws(p); - } - - if (*p == '(') { - code = ++p; - while (*p && *p != ')') - p++; - assert(*p); - *p++ = '\0'; - - p = skip_ws(p); - } - - payee = p; - - p = payee + (std::strlen(payee) - 1); - while (p > payee && std::isspace(*p)) - p--; - - if (std::isspace(*(p + 1))) - *++p = '\0'; - - TRACE_STOP(entry_text, 1); - - // Setup the details for this node - - TRACE_START(entry_details, 1, "Time spent parsing entry details:"); - - builder.push_attr(DATE_ATTR, date); - - if (date_eff) - builder.push_attr(EFF_DATE_ATTR, date_eff); - - if (statep) { - switch (*statep) { - case '*': - builder.push_attr(CLEARED_ATTR, "yes"); - break; - case '!': - builder.push_attr(PENDING_ATTR, "yes"); - break; - } - } - - if (code) - builder.push_attr(CODE_ATTR, code); - - builder.begin_node(ENTRY_NODE); - - builder.begin_node(PAYEE_NODE, true); - assert(payee); - builder.append_text(*payee != '\0' ? payee : "<Unspecified payee>"); - builder.end_node(PAYEE_NODE, end_of_line); - - TRACE_STOP(entry_details, 1); - - // Parse all the transactions associated with this entry - - if (! parse_transactions(in, builder)) - throw_(parse_error, "Entry has no transactions"); - - builder.end_node(ENTRY_NODE); -} - -bool textual_parser_t::test(std::istream& in) const -{ - char buf[5]; - - in.read(buf, 5); - if (std::strncmp(buf, "<?xml", 5) == 0) - throw_(parse_error, "Ledger file contains XML data, but format was not recognized"); - - in.clear(); - in.seekg(0, std::ios::beg); - assert(in.good()); - return true; -} - -std::size_t textual_parser_t::parse(std::istream& in, - const path& pathname, - builder_t& builder) -{ - TRACE_START(parsing_total, 1, "Total time spent parsing text:"); - - INFO("Parsing file '" << pathname.string() << "'"); - - builder.begin_node(JOURNAL_NODE); - - std::size_t count = 0; - - while (in.good() && ! in.eof()) { - static char line[MAX_LINE + 1]; - in.getline(line, MAX_LINE); - if (in.eof()) - break; - - position_t end_of_line(builder.position()); - end_of_line.offset += std::strlen(line) + 1; - end_of_line.linenum++; - - //PUSH_CONTEXT(); - - switch (line[0]) { - case '\0': - case '\r': - break; - - case ' ': - case '\t': { - char * p = skip_ws(line); - if (*p && *p != '\r') - throw_(parse_error, "Line begins with whitespace"); - break; - } - - case 'i': - case 'I': { - string date(line, 2, 19); - - char * p = skip_ws(line + 22); - char * n = next_element(p, true); - - builder.push_attr(TIME_ATTR, date); - builder.push_attr(ACCOUNT_ATTR, p); - builder.begin_node(CHECKIN_NODE, true); - builder.append_text(n); - builder.end_node(CHECKIN_NODE, end_of_line); - break; - } - - case 'o': - case 'O': { - string date(line, 2, 19); - - char * p = skip_ws(line + 22); - char * n = next_element(p, true); - - builder.push_attr(TIME_ATTR, date); - builder.push_attr(ACCOUNT_ATTR, p); - builder.begin_node(CHECKIN_NODE, true); - builder.append_text(n); - builder.end_node(CHECKIN_NODE, end_of_line); - break; - } - - case 'D': { // specifies default commodity flags - builder.push_attr(TEMPLATE_ATTR, skip_ws(line + 1)); - builder.push_node(COMMODITY_TEMPLATE_NODE, end_of_line); - break; - } - - case 'A': // a default account for unbalanced xacts - builder.push_attr(NAME_ATTR, skip_ws(line + 1)); - builder.push_node(DEFAULT_ACCOUNT_NODE, end_of_line); - break; - - case 'C': // a set of conversions - if (char * p = std::strchr(line + 1, '=')) { - *p++ = '\0'; - builder.push_attr(FROM_ATTR, skip_ws(line + 1)); - builder.push_attr(TO_ATTR, p); - builder.push_node(COMMODITY_CONVERSION_NODE, end_of_line); - } else { - throw_(parse_error, "Conversion entry (code C) must follow the format X=Y"); - } - break; - - case 'P': { // a pricing entry - char * date_field_ptr = skip_ws(line + 1); - char * time_field_ptr = next_element(date_field_ptr); - if (! time_field_ptr) - throw_(parse_error, "Pricing entry (code P) is missing arguments"); - string date_field = date_field_ptr; - - char * symbol_and_price; - moment_t datetime; - - if (std::isdigit(time_field_ptr[0])) { - symbol_and_price = next_element(time_field_ptr); - if (! symbol_and_price) - throw_(parse_error, "Pricing entry (code P) is missing a symbol name"); - } else { - symbol_and_price = time_field_ptr; - } - - builder.push_attr(DATE_ATTR, date_field_ptr); - builder.push_attr(TIME_ATTR, time_field_ptr); - - string symbol; - commodity_t::parse_symbol(symbol_and_price, symbol); - - builder.push_attr(SYMBOL_ATTR, symbol); - builder.push_attr(PRICE_ATTR, skip_ws(symbol_and_price)); - builder.push_node(PRICE_HISTORY_NODE, end_of_line); - break; - } - - case 'N': { // don't download prices - char * p = skip_ws(line + 1); - - string symbol; - commodity_t::parse_symbol(p, symbol); - - builder.push_attr(SYMBOL_ATTR, symbol); - builder.push_node(COMMODITY_NOMARKET_NODE, end_of_line); - break; - } - - case 'Y': // set current year - builder.push_attr(YEAR_ATTR, skip_ws(line + 1)); - builder.push_node(CURRENT_YEAR_NODE, end_of_line); - break; - - case 'h': - case 'b': - case ';': // comment - // jww (2007-05-12): Read in the comment and save it - break; - - case '@': - case '!': { // directive - char * p = next_element(line); - string word(line + 1); - - builder.push_attr(NAME_ATTR, word); - builder.push_attr(ARG_ATTR, p); - builder.push_node(DIRECTIVE_NODE, end_of_line); - break; - } - - case '-': // option setting - throw_(parse_error, "Option settings are not allowed in journal files"); - - case '=': { // automated entry - builder.begin_node(AUTO_ENTRY_NODE); - builder.begin_node(RULE_NODE, true); - builder.append_text(skip_ws(line + 1)); - builder.end_node(RULE_NODE); - - builder.set_position(end_of_line); - - if (! parse_transactions(in, builder)) - throw_(parse_error, "Automated entry has no transactions"); - - builder.end_node(AUTO_ENTRY_NODE); - break; - } - - case '~': // period entry - builder.begin_node(PERIOD_ENTRY_NODE); - builder.begin_node(PERIOD_NODE, true); - builder.append_text(skip_ws(line + 1)); - builder.end_node(PERIOD_NODE); - - builder.set_position(end_of_line); - - if (! parse_transactions(in, builder)) - throw_(parse_error, "Repeating entry has no transactions"); - - builder.end_node(PERIOD_ENTRY_NODE); - break; - - default: - TRACE_START(entries, 1, "Time spent handling entries:"); - parse_entry(in, builder, line, end_of_line); - count++; - TRACE_STOP(entries, 1); - break; - } - - //POP_CONTEXT(builder_context(builder)); - } - - builder.end_node(JOURNAL_NODE); - - TRACE_STOP(parsing_total, 1); - - return count; -} - -} // namespace ledger diff --git a/src/data/textual.h b/src/data/textual.h deleted file mode 100644 index f4d81f19..00000000 --- a/src/data/textual.h +++ /dev/null @@ -1,51 +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 _TEXTUAL_H -#define _TEXTUAL_H - -#include "parser.h" - -namespace ledger { - -class textual_parser_t : public parser_t -{ - public: - virtual bool test(std::istream& in) const; - - virtual std::size_t parse(std::istream& in, - const path& pathname, - xml::builder_t& builder); -}; - -} // namespace ledger - -#endif // _TEXTUAL_H |