summaryrefslogtreecommitdiff
path: root/src/xml.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/xml.cc')
-rw-r--r--src/xml.cc584
1 files changed, 0 insertions, 584 deletions
diff --git a/src/xml.cc b/src/xml.cc
deleted file mode 100644
index 9b14f97c..00000000
--- a/src/xml.cc
+++ /dev/null
@@ -1,584 +0,0 @@
-/*
- * Copyright (c) 2003-2007, John Wiegley. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of New Artisans LLC nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "xml.h"
-#include "journal.h"
-
-namespace ledger {
-namespace xml {
-
-const std::size_t document_t::ledger_builtins_size = 12;
-const char * document_t::ledger_builtins[] = {
- "account",
- "account-path",
- "amount",
- "code",
- "commodity",
- "entries",
- "entry",
- "journal",
- "name",
- "note",
- "payee",
- "transaction"
-};
-
-document_t::~document_t()
-{
- TRACE_DTOR(xml::document_t);
- if (top && top != &stub)
- checked_delete(top);
-}
-
-void document_t::set_top(node_t * _top)
-{
- if (top && top != &stub)
- checked_delete(top);
- top = _top;
-}
-
-int document_t::register_name(const string& name)
-{
- int index = lookup_name_id(name);
- if (index != -1)
- return index;
-
- names.push_back(name);
- index = names.size() - 1;
-
- DEBUG("xml.lookup", this << " Inserting name: " << names.back());
-
- std::pair<names_map::iterator, bool> result =
- names_index.insert(names_map::value_type(names.back(), index));
- assert(result.second);
-
- return index + 1000;
-}
-
-int document_t::lookup_name_id(const string& name) const
-{
- int id;
- if ((id = lookup_builtin_id(name)) != -1)
- return id;
-
- DEBUG("xml.lookup", this << " Finding name: " << name);
-
- names_map::const_iterator i = names_index.find(name);
- if (i != names_index.end())
- return (*i).second + 1000;
-
- return -1;
-}
-
-int document_t::lookup_builtin_id(const string& name)
-{
- int first = 0;
- int last = (int)ledger_builtins_size;
-
- while (first <= last) {
- int mid = (first + last) / 2; // compute mid point.
-
- int result;
- if ((result = (int)name[0] - (int)ledger_builtins[mid][0]) == 0)
- result = std::strcmp(name.c_str(), ledger_builtins[mid]);
-
- if (result > 0)
- first = mid + 1; // repeat search in top half.
- else if (result < 0)
- last = mid - 1; // repeat search in bottom half.
- else
- return mid + 10;
- }
-
- return -1;
-}
-
-const char * document_t::lookup_name(int id) const
-{
- if (id < 1000) {
- switch (id) {
- case CURRENT:
- return "CURRENT";
- case PARENT:
- return "PARENT";
- case ROOT:
- return "ROOT";
- case ALL:
- return "ALL";
- default:
- assert(id >= 10);
- return ledger_builtins[id - 10];
- }
- } else {
- return names[id - 1000].c_str();
- }
-}
-
-void document_t::print(std::ostream& out) const
-{
- if (top) {
- out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
- top->print(out);
- }
-}
-
-#ifndef THREADSAFE
-document_t * node_t::document = NULL;
-#endif
-
-node_t::node_t(document_t * _document, parent_node_t * _parent, flags_t _flags)
- : supports_flags<>(_flags), name_id(0), parent(_parent),
- next(NULL), prev(NULL), attrs(NULL)
-{
- TRACE_CTOR(node_t, "document_t *, node_t *");
- document = _document;
- if (document && ! document->top)
- document->set_top(this);
- if (parent)
- parent->add_child(this);
-}
-
-void node_t::extract()
-{
- if (prev)
- prev->next = next;
-
- if (parent) {
- if (parent->_children == this)
- parent->_children = next;
-
- if (parent->_last_child == this)
- parent->_last_child = prev;
-
- parent = NULL;
- }
-
- if (next)
- next->prev = prev;
-
- next = NULL;
- prev = NULL;
-}
-
-const char * node_t::name() const
-{
- return document->lookup_name(name_id);
-}
-
-int node_t::set_name(const char * _name)
-{
- name_id = document->register_name(_name);
- return name_id;
-}
-
-node_t * node_t::lookup_child(const char * _name) const
-{
- int id = document->lookup_name_id(_name);
- return lookup_child(id);
-}
-
-node_t * node_t::lookup_child(const string& _name) const
-{
- int id = document->lookup_name_id(_name);
- return lookup_child(id);
-}
-
-void parent_node_t::clear()
-{
- node_t * child = _children;
- while (child) {
- node_t * tnext = child->next;
- checked_delete(child);
- child = tnext;
- }
-}
-
-void parent_node_t::add_child(node_t * node)
-{
- // It is important that this node is not called before children(),
- // otherwise, this node will not get auto-populated.
- if (_children == NULL) {
- assert(_last_child == NULL);
- _children = node;
- node->prev = NULL;
- } else {
- assert(_last_child != NULL);
- _last_child->next = node;
- node->prev = _last_child;
- }
-
- node->parent = this;
-
- while (node->next) {
- node_t * next_node = node->next;
- assert(next_node->prev == node);
- next_node->parent = this;
- node = next_node;
- }
-
- _last_child = node;
-}
-
-void parent_node_t::print(std::ostream& out, int depth) const
-{
- for (int i = 0; i < depth; i++) out << " ";
- out << '<' << name() << ">\n";
-
- for (node_t * child = children(); child; child = child->next)
- child->print(out, depth + 1);
-
- for (int i = 0; i < depth; i++) out << " ";
- out << "</" << name() << ">\n";
-}
-
-void terminal_node_t::print(std::ostream& out, int depth) const
-{
- for (int i = 0; i < depth; i++) out << " ";
-
- if (data.empty()) {
- out << '<' << name() << " />\n";
- } else {
- out << '<' << name() << ">"
- << text()
- << "</" << name() << ">\n";
- }
-}
-
-#if defined(HAVE_EXPAT) || defined(HAVE_XMLPARSE)
-
-template <typename T>
-inline T * create_node(document_t::parser_t * parser)
-{
- T * node = new T(parser->document, parser->node_stack.empty() ?
- NULL : parser->node_stack.front());
-
- node->set_name(parser->pending);
- node->attrs = parser->pending_attrs;
-
- parser->pending = NULL;
- parser->pending_attrs = NULL;
-
- return node;
-}
-
-static void startElement(void *userData, const char *name, const char **attrs)
-{
- document_t::parser_t * parser = static_cast<document_t::parser_t *>(userData);
-
- DEBUG("xml.parse", "startElement(" << name << ")");
-
- if (parser->pending) {
- parent_node_t * node = create_node<parent_node_t>(parser);
- if (parser->node_stack.empty())
- parser->document->top = node;
- parser->node_stack.push_front(node);
- }
-
- parser->pending = name;
-
- if (attrs) {
- for (const char ** p = attrs; *p; p += 2) {
- if (! parser->pending_attrs)
- parser->pending_attrs = new node_t::attrs_map;
-
- std::pair<node_t::attrs_map::iterator, bool> result
- = parser->pending_attrs->insert
- (node_t::attrs_map::value_type(*p, *(p + 1)));
- assert(result.second);
- }
- }
-}
-
-static void endElement(void *userData, const char *name)
-{
- document_t::parser_t * parser = static_cast<document_t::parser_t *>(userData);
-
- DEBUG("xml.parse", "endElement(" << name << ")");
-
- if (parser->pending) {
- terminal_node_t * node = create_node<terminal_node_t>(parser);
- if (parser->node_stack.empty()) {
- parser->document->top = node;
- return;
- }
- }
- else if (! parser->handled_data) {
- assert(! parser->node_stack.empty());
- parser->node_stack.pop_front();
- }
- else {
- parser->handled_data = false;
- }
-}
-
-static void dataHandler(void *userData, const char *s, int len)
-{
- document_t::parser_t * parser = static_cast<document_t::parser_t *>(userData);
-
- DEBUG("xml.parse", "dataHandler(" << string(s, len) << ")");
-
- bool all_whitespace = true;
- for (int i = 0; i < len; i++) {
- if (! std::isspace(s[i])) {
- all_whitespace = false;
- break;
- }
- }
-
- // jww (2006-09-28): I currently do not support text nodes within a
- // node that has children.
-
- if (! all_whitespace) {
- terminal_node_t * node = create_node<terminal_node_t>(parser);
-
- node->set_text(string(s, len));
- parser->handled_data = true;
-
- if (parser->node_stack.empty()) {
- parser->document->top = node;
- return;
- }
- }
-}
-
-bool document_t::parser_t::test(std::istream& in) const
-{
- char buf[80];
-
- in.getline(buf, 79);
- if (std::strncmp(buf, "<?xml", 5) != 0) {
- in.clear();
- in.seekg(0, std::ios::beg);
- return false;
- }
-
- in.clear();
- in.seekg(0, std::ios::beg);
- return true;
-}
-
-document_t * document_t::parser_t::parse(std::istream& in)
-{
- std::auto_ptr<document_t> doc(new document_t);
-
- document = doc.get();
-
- parser = XML_ParserCreate(NULL);
-
- XML_SetElementHandler(parser, startElement, endElement);
- XML_SetCharacterDataHandler(parser, dataHandler);
- XML_SetUserData(parser, this);
-
- char buf[BUFSIZ];
- while (! in.eof()) {
- in.getline(buf, BUFSIZ - 1);
- std::strcat(buf, "\n");
- bool result;
- try {
- result = XML_Parse(parser, buf, std::strlen(buf), in.eof());
- }
- catch (const std::exception& err) {
- //unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
- XML_ParserFree(parser);
- throw_(parse_error, err.what());
- }
-
- if (! have_error.empty()) {
- //unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
-#if 0
- // jww (2007-04-26): What is this doing??
- parse_error err(have_error);
- std::cerr << "Error: " << err.what() << std::endl;
-#endif
- have_error = "";
- }
-
- if (! result) {
- //unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
- const char * err = XML_ErrorString(XML_GetErrorCode(parser));
- XML_ParserFree(parser);
- throw_(parse_error, err);
- }
- }
-
- XML_ParserFree(parser);
-
- document = NULL;
- return doc.release();
-}
-
-#endif // HAVE_EXPAT || HAVE_XMLPARSE
-
-node_t * commodity_node_t::children() const
-{
- // jww (2007-04-19): Need to report the commodity and its details
- return NULL;
-}
-
-node_t * amount_node_t::children() const
-{
- // jww (2007-04-19): Need to report the quantity and commodity
- return NULL;
-}
-
-node_t * transaction_node_t::children() const
-{
- return parent_node_t::children();
-}
-
-node_t * transaction_node_t::lookup_child(int _name_id) const
-{
- switch (_name_id) {
- case document_t::PAYEE:
- payee_virtual_node = new terminal_node_t(document);
- payee_virtual_node->set_text(transaction->entry->payee);
- return payee_virtual_node;
-
- case document_t::ACCOUNT:
- return new account_node_t(document, transaction->account,
- const_cast<transaction_node_t *>(this));
- }
- return NULL;
-}
-
-value_t transaction_node_t::to_value() const
-{
- if (transaction->amount)
- return *transaction->amount;
- else
- return value_t();
-}
-
-node_t * entry_node_t::children() const
-{
- if (! _children)
- for (transactions_list::iterator i = entry->transactions.begin();
- i != entry->transactions.end();
- i++)
- new transaction_node_t(document, *i, const_cast<entry_node_t *>(this));
-
- return parent_node_t::children();
-}
-
-node_t * entry_node_t::lookup_child(int _name_id) const
-{
- switch (_name_id) {
- case document_t::CODE: {
- if (! entry->code)
- break;
-
- // jww (2007-04-20): I have to save this and then delete it later
- terminal_node_t * code_node =
- new terminal_node_t(document, const_cast<entry_node_t *>(this));
- code_node->set_name(document_t::CODE);
- code_node->set_text(*entry->code);
- return code_node;
- }
-
- case document_t::PAYEE: {
- // jww (2007-04-20): I have to save this and then delete it later
- terminal_node_t * payee_node =
- new terminal_node_t(document, const_cast<entry_node_t *>(this));
- payee_node->set_name(document_t::PAYEE);
- payee_node->set_text(entry->payee);
- return payee_node;
- }
- }
- return NULL;
-}
-
-node_t * account_node_t::children() const
-{
- if (! _children) {
- if (! account->name.empty()) {
- terminal_node_t * name_node =
- new terminal_node_t(document, const_cast<account_node_t *>(this));
- name_node->set_name(document_t::NAME);
- name_node->set_text(account->name);
- }
-
- if (account->note) {
- terminal_node_t * note_node =
- new terminal_node_t(document, const_cast<account_node_t *>(this));
- note_node->set_name(document_t::NOTE);
- note_node->set_text(*account->note);
- }
-
- for (accounts_map::iterator i = account->accounts.begin();
- i != account->accounts.end();
- i++)
- new account_node_t(document, (*i).second, const_cast<account_node_t *>(this));
- }
- return parent_node_t::children();
-}
-
-node_t * journal_node_t::children() const
-{
- if (! _children) {
-#if 0
- account_node_t * master_account =
- new account_node_t(document, journal->master, const_cast<journal_node_t *>(this));
-#endif
-
- parent_node_t * entries =
- new parent_node_t(document, const_cast<journal_node_t *>(this));
- entries->set_name(document_t::ENTRIES);
-
- for (entries_list::iterator i = journal->entries.begin();
- i != journal->entries.end();
- i++)
- new entry_node_t(document, *i, const_cast<journal_node_t *>(this));
- }
- return parent_node_t::children();
-}
-
-void output_xml_string(std::ostream& out, const string& str)
-{
- for (const char * s = str.c_str(); *s; s++) {
- switch (*s) {
- case '<':
- out << "&lt;";
- break;
- case '>':
- out << "&gt;";
- break;
- case '&':
- out << "&amp;";
- break;
- default:
- out << *s;
- break;
- }
- }
-}
-
-} // namespace xml
-} // namespace ledger