diff options
author | John Wiegley <johnw@newartisans.com> | 2007-05-15 00:30:05 +0000 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2008-04-13 03:38:51 -0400 |
commit | 9e55655e0c1a56d3059bd8fc485e37fc3333b3bb (patch) | |
tree | 92ff00093779b7c7fb843417c27726508fa9f557 | |
parent | b36d24481d37170195e3f92267b343b9489c6bba (diff) | |
download | fork-ledger-9e55655e0c1a56d3059bd8fc485e37fc3333b3bb.tar.gz fork-ledger-9e55655e0c1a56d3059bd8fc485e37fc3333b3bb.tar.bz2 fork-ledger-9e55655e0c1a56d3059bd8fc485e37fc3333b3bb.zip |
Got the xpath command working again.
-rw-r--r-- | src/main.cc | 10 | ||||
-rw-r--r-- | src/option.cc | 84 | ||||
-rw-r--r-- | src/session.cc | 15 | ||||
-rw-r--r-- | src/session.h | 12 | ||||
-rw-r--r-- | src/value.cc | 19 | ||||
-rw-r--r-- | src/value.h | 38 | ||||
-rw-r--r-- | src/xpath.cc | 51 | ||||
-rw-r--r-- | src/xpath.h | 18 |
8 files changed, 141 insertions, 106 deletions
diff --git a/src/main.cc b/src/main.cc index 3db75442..7aea3c2c 100644 --- a/src/main.cc +++ b/src/main.cc @@ -269,10 +269,12 @@ static int read_and_report(ledger::report_t * report, int argc, char * argv[], xpath.print(*out, xml_document); *out << std::endl; -#if 0 - std::auto_ptr<repitem_t> items(repitem_t::wrap(&session, report, true)); - items->select(path.get()); -#endif + value_t nodelist; + xpath.calc(nodelist, xml_document, report); + + foreach (const value_t& node, nodelist.as_sequence()) + node.as_xml_node()->print(*out); + return 0; } diff --git a/src/option.cc b/src/option.cc index 24ee9bfe..d56eb0ff 100644 --- a/src/option.cc +++ b/src/option.cc @@ -31,17 +31,12 @@ #include "option.h" -#if 0 -#ifdef USE_BOOST_PYTHON -static ledger::option_t * find_option(const string& name); -#endif -#endif - namespace ledger { namespace { - xml::xpath_t::ptr_op_t find_option(xml::xpath_t::scope_t * scope, - const string& name) + typedef tuple<xml::xpath_t::ptr_op_t, bool> op_bool_tuple; + + op_bool_tuple find_option(xml::xpath_t::scope_t * scope, const string& name) { char buf[128]; std::strcpy(buf, "option_"); @@ -54,18 +49,31 @@ namespace { } *p = '\0'; - return scope->lookup(buf); + xml::xpath_t::ptr_op_t op = scope->lookup(buf); + if (op) + return op_bool_tuple(op, false); + + *p++ = '_'; + *p = '\0'; + + return op_bool_tuple(scope->lookup(buf), true); } - xml::xpath_t::ptr_op_t find_option(xml::xpath_t::scope_t * scope, - const char letter) + op_bool_tuple find_option(xml::xpath_t::scope_t * scope, const char letter) { - char buf[9]; + char buf[10]; std::strcpy(buf, "option_"); buf[7] = letter; buf[8] = '\0'; - return scope->lookup(buf); + xml::xpath_t::ptr_op_t op = scope->lookup(buf); + if (op) + return op_bool_tuple(op, false); + + buf[8] = '_'; + buf[9] = '\0'; + + return op_bool_tuple(scope->lookup(buf), true); } void process_option(const xml::xpath_t::function_t& opt, @@ -99,9 +107,9 @@ namespace { bool process_option(const string& name, xml::xpath_t::scope_t * scope, const char * arg) { - xml::xpath_t::ptr_op_t opt(find_option(scope, name)); - if (opt) { - process_option(opt->as_function(), scope, arg); + op_bool_tuple opt(find_option(scope, name)); + if (opt.get<0>()) { + process_option(opt.get<0>()->as_function(), scope, arg); return true; } return false; @@ -132,10 +140,7 @@ void process_environment(const char ** envp, const string& tag, try { #endif if (! process_option(string(buf), scope, q + 1)) -#if 0 - throw new option_error("unknown option") -#endif - ; + ; //throw_(option_error, "unknown option"); #if 0 } catch (error * err) { @@ -178,51 +183,44 @@ void process_arguments(int argc, char ** argv, const bool anywhere, value = p; } - xml::xpath_t::ptr_op_t opt(find_option(scope, name)); - if (! opt) + op_bool_tuple opt(find_option(scope, name)); + if (! opt.get<0>()) throw_(option_error, "illegal option --" << name); - if (/*def->wants_args &&*/ value == NULL) { + if (opt.get<1>() && value == NULL) { value = *++i; if (value == NULL) throw_(option_error, "missing option argument for --" << name); } - process_option(opt->as_function(), scope, value); + process_option(opt.get<0>()->as_function(), scope, value); } else if ((*i)[1] == '\0') { throw_(option_error, "illegal option -"); } else { - std::list<xml::xpath_t::ptr_op_t> option_queue; + typedef tuple<xml::xpath_t::ptr_op_t, bool, char> op_bool_char_tuple; + + std::list<op_bool_char_tuple> option_queue; int x = 1; for (char c = (*i)[x]; c != '\0'; x++, c = (*i)[x]) { - xml::xpath_t::ptr_op_t opt = find_option(scope, c); - if (! opt) + op_bool_tuple opt(find_option(scope, c)); + if (! opt.get<0>()) throw_(option_error, "illegal option -" << c); - option_queue.push_back(opt); + option_queue.push_back + (op_bool_char_tuple(opt.get<0>(), opt.get<1>(), c)); } - foreach (xml::xpath_t::ptr_op_t& o, option_queue) { + foreach (op_bool_char_tuple& o, option_queue) { char * value = NULL; -#if 0 - if (def->wants_args) { -#endif + if (o.get<1>()) { value = *++i; if (value == NULL) - throw_(option_error, "missing option argument for -" << -#if 0 - def->short_opt -#else - '?' -#endif - ); -#if 0 + throw_(option_error, + "missing option argument for -" << o.get<2>()); } -#endif - process_option(o->as_function(), scope, value); - + process_option(o.get<0>()->as_function(), scope, value); } } } diff --git a/src/session.cc b/src/session.cc index 0affd370..65b9ada5 100644 --- a/src/session.cc +++ b/src/session.cc @@ -219,27 +219,26 @@ xml::xpath_t::ptr_op_t session_t::lookup(const string& name) p = p + 7; switch (*p) { case 'd': - if (std::strcmp(p, "debug") == 0) - return MAKE_FUNCTOR(session_t::option_debug); + if (std::strcmp(p, "debug_") == 0) + return MAKE_FUNCTOR(session_t::option_debug_); break; case 'f': - if (! *(p + 1) || std::strcmp(p, "file") == 0) - return MAKE_FUNCTOR(session_t::option_file); + if ((*(p + 1) == '_' && ! *(p + 2)) || + std::strcmp(p, "file_") == 0) + return MAKE_FUNCTOR(session_t::option_file_); break; case 't': - if (std::strcmp(p, "trace") == 0) - return MAKE_FUNCTOR(session_t::option_trace); + if (std::strcmp(p, "trace_") == 0) + return MAKE_FUNCTOR(session_t::option_trace_); break; case 'v': -#if 0 if (! *(p + 1) || std::strcmp(p, "verbose") == 0) return MAKE_FUNCTOR(session_t::option_verbose); else if (std::strcmp(p, "verify") == 0) return MAKE_FUNCTOR(session_t::option_verify); -#endif break; } } diff --git a/src/session.h b/src/session.h index 0fdd2881..7658fc24 100644 --- a/src/session.h +++ b/src/session.h @@ -188,11 +188,11 @@ class session_t : public xml::xpath_t::scope_t // Debug options // - void option_verify(value_t&) {} - void option_trace(value_t&, xml::xpath_t::scope_t * locals) {} - void option_debug(value_t&, xml::xpath_t::scope_t * locals) {} + void option_trace_(value_t&, xml::xpath_t::scope_t * locals) {} + void option_debug_(value_t&, xml::xpath_t::scope_t * locals) {} - void option_verbose(value_t&) { + void option_verify(value_t&, xml::xpath_t::scope_t *) {} + void option_verbose(value_t&, xml::xpath_t::scope_t *) { #if defined(LOGGING_ON) if (_log_level < LOG_INFO) _log_level = LOG_INFO; @@ -203,13 +203,13 @@ class session_t : public xml::xpath_t::scope_t // Option handlers // - void option_file(value_t&, xml::xpath_t::scope_t * locals) { + void option_file_(value_t&, xml::xpath_t::scope_t * locals) { data_file = locals->args.as_string(); } #if 0 #if defined(USE_BOOST_PYTHON) - void option_import(value_t&) { + void option_import_(value_t&) { python_import(optarg); } void option_import_stdin(value_t&) { diff --git a/src/value.cc b/src/value.cc index 12c6379d..40167af3 100644 --- a/src/value.cc +++ b/src/value.cc @@ -727,7 +727,7 @@ bool value_t::operator==(const value_t& val) const case INTEGER: return as_long() == val.as_long(); case AMOUNT: - return val.as_amount() == as_amount(); + return val.as_amount() == to_amount(); case BALANCE: return val.as_balance() == to_amount(); case BALANCE_PAIR: @@ -1569,9 +1569,20 @@ void value_t::print(std::ostream& out, const int first_width, as_xml_node()->print(out); break; - case SEQUENCE: - assert(false); // jww (2006-09-28): write them all out! - throw_(value_error, "Cannot write out a sequence"); + case SEQUENCE: { + out << '('; + bool first = true; + foreach (const value_t& value, as_sequence()) { + if (first) + first = false; + else + out << ", "; + + value.print(out, first_width, latter_width); + } + out << ')'; + break; + } case BALANCE: as_balance().print(out, first_width, latter_width); diff --git a/src/value.h b/src/value.h index f001a4aa..51b5be22 100644 --- a/src/value.h +++ b/src/value.h @@ -187,6 +187,9 @@ class value_t return *this; } + bool is_boolean() const { + return type == BOOLEAN; + } bool& as_boolean() { assert(type == BOOLEAN); return *(bool *) data; @@ -195,6 +198,10 @@ class value_t assert(type == BOOLEAN); return *(bool *) data; } + + bool is_long() const { + return type == INTEGER; + } long& as_long() { assert(type == INTEGER); return *(long *) data; @@ -203,6 +210,10 @@ class value_t assert(type == INTEGER); return *(long *) data; } + + bool is_datetime() const { + return type == DATETIME; + } moment_t& as_datetime() { assert(type == DATETIME); return *(moment_t *) data; @@ -211,6 +222,10 @@ class value_t assert(type == DATETIME); return *(moment_t *) data; } + + bool is_amount() const { + return type == AMOUNT; + } amount_t& as_amount() { assert(type == AMOUNT); return *(amount_t *) data; @@ -219,6 +234,10 @@ class value_t assert(type == AMOUNT); return *(amount_t *) data; } + + bool is_balance() const { + return type == BALANCE; + } balance_t& as_balance() { assert(type == BALANCE); return *(balance_t *) data; @@ -227,6 +246,10 @@ class value_t assert(type == BALANCE); return *(balance_t *) data; } + + bool is_balance_pair() const { + return type == BALANCE_PAIR; + } balance_pair_t& as_balance_pair() { assert(type == BALANCE_PAIR); return *(balance_pair_t *) data; @@ -235,6 +258,10 @@ class value_t assert(type == BALANCE_PAIR); return *(balance_pair_t *) data; } + + bool is_string() const { + return type == STRING; + } string& as_string() { assert(type == STRING); return *(string *) data; @@ -243,6 +270,10 @@ class value_t assert(type == STRING); return *(string *) data; } + + bool is_sequence() const { + return type == SEQUENCE; + } sequence_t& as_sequence() { assert(type == SEQUENCE); return *(sequence_t *) data; @@ -252,6 +283,9 @@ class value_t return *(sequence_t *) data; } + bool is_xml_node() const { + return type == XML_NODE; + } xml::node_t *& as_xml_node() { assert(type == XML_NODE); return *(xml::node_t **) data; @@ -260,6 +294,10 @@ class value_t assert(type == XML_NODE); return *(xml::node_t **) data; } + + bool is_pointer() const { + return type == POINTER; + } void *& as_pointer() { assert(type == POINTER); return *(void **) data; diff --git a/src/xpath.cc b/src/xpath.cc index 932fb84a..702aaeae 100644 --- a/src/xpath.cc +++ b/src/xpath.cc @@ -71,7 +71,7 @@ void xpath_t::token_t::parse_ident(std::istream& in) char buf[256]; READ_INTO_(in, buf, 255, c, length, - std::isalnum(c) || c == '_' || c == '.'); + std::isalnum(c) || c == '_' || c == '.' || c == '-'); switch (buf[0]) { case 'a': @@ -440,20 +440,6 @@ xpath_t::ptr_op_t xpath_t::wrap_value(const value_t& val) return temp; } -xpath_t::ptr_op_t xpath_t::wrap_sequence(const value_t::sequence_t& val) -{ - xpath_t::ptr_op_t temp(new xpath_t::op_t(xpath_t::op_t::VALUE)); - - if (val.size() == 0) - temp->set_value(new value_t(false)); - else if (val.size() == 1) - temp->set_value(new value_t(val.front())); - else - temp->set_value(new value_t(val)); - - return temp; -} - xpath_t::ptr_op_t xpath_t::wrap_functor(const function_t& fobj) { xpath_t::ptr_op_t temp(new xpath_t::op_t(xpath_t::op_t::FUNCTION)); @@ -1073,7 +1059,9 @@ void xpath_t::op_t::find_values(value_t& context, scope_t * scope, { xpath_t expr(compile(context, scope, true)); - if (expr.ptr->kind == VALUE) + if (expr.ptr->is_value() && + (expr.ptr->as_value().is_xml_node() || + expr.ptr->as_value().is_sequence())) append_value(expr.ptr->as_value(), result_seq); if (recursive) { @@ -1191,7 +1179,6 @@ xpath_t::ptr_op_t xpath_t::op_t::compile(value_t& context, scope_t * scope, value_t::sequence_t nodes; foreach (node_t * node, context.as_xml_node()->as_parent_node()) nodes.push_back(node); - return wrap_value(nodes); } @@ -1201,7 +1188,7 @@ xpath_t::ptr_op_t xpath_t::op_t::compile(value_t& context, scope_t * scope, // fall through... case NODE_NAME: - if (context.type == value_t::XML_NODE) { + if (context.is_xml_node()) { node_t * ptr = context.as_xml_node(); if (resolve) { // First, look up the symbol as a node name within the current @@ -1218,14 +1205,12 @@ xpath_t::ptr_op_t xpath_t::op_t::compile(value_t& context, scope_t * scope, } return wrap_value(nodes); } - } else { - assert(ptr); - if (optional<node_t::nameid_t> id = - ptr->document().lookup_name_id(as_string())) { - ptr_op_t node = new_node(NODE_ID); - node->set_name(*id); - return node; - } + } + else if (optional<node_t::nameid_t> id = + ptr->document().lookup_name_id(as_string())) { + ptr_op_t node = new_node(NODE_ID); + node->set_name(*id); + return node; } } return this; @@ -1333,11 +1318,7 @@ xpath_t::ptr_op_t xpath_t::op_t::compile(value_t& context, scope_t * scope, append_value(lexpr.ptr->as_value(), result_seq); append_value(rexpr.ptr->as_value(), result_seq); - if (result_seq.size() == 1) - return wrap_value(result_seq.front()); - else - return wrap_sequence(result_seq); - break; + return wrap_value(result_seq); } case O_ADD: @@ -1627,8 +1608,7 @@ xpath_t::ptr_op_t xpath_t::op_t::compile(value_t& context, scope_t * scope, case O_RFIND: case O_PRED: { xpath_t lexpr(left()->compile(context, scope, resolve)); - xpath_t rexpr(resolve ? right() : - right()->compile(context, scope, false)); + xpath_t rexpr(resolve ? right() : right()->compile(context, scope, false)); if (! lexpr.ptr->is_value() || ! resolve) { if (left() == lexpr.ptr) @@ -1682,10 +1662,7 @@ xpath_t::ptr_op_t xpath_t::op_t::compile(value_t& context, scope_t * scope, "to non-node(s)"); } - if (result_seq.size() == 1) - return wrap_value(result_seq.front()); - else - return wrap_sequence(result_seq); + return wrap_value(result_seq); } case LAST: diff --git a/src/xpath.h b/src/xpath.h index 9b0129ed..ccec7b0a 100644 --- a/src/xpath.h +++ b/src/xpath.h @@ -59,7 +59,6 @@ public: xml::xpath_t::wrap_functor(bind(&x, this, _1, _2)) static ptr_op_t wrap_value(const value_t& val); - static ptr_op_t wrap_sequence(const value_t::sequence_t& val); static ptr_op_t wrap_functor(const function_t& fobj); public: @@ -294,10 +293,9 @@ public: op_t& operator=(const op_t&); - bool is_value() const { - return kind == VALUE; + bool is_long() const { + return data.type() == typeid(unsigned int); } - unsigned int& as_long() { assert(kind == ARG_INDEX || kind == O_ARG); return boost::get<unsigned int>(data); @@ -309,6 +307,9 @@ public: data = val; } + bool is_value() const { + return kind == VALUE; + } value_t& as_value() { assert(kind == VALUE); value_t * val = boost::get<shared_ptr<value_t> >(data).get(); @@ -323,6 +324,9 @@ public: data = shared_ptr<value_t>(val); } + bool is_string() const { + return data.type() == typeid(string); + } string& as_string() { assert(kind == NODE_NAME || kind == ATTR_NAME || kind == FUNC_NAME); return boost::get<string>(data); @@ -334,6 +338,9 @@ public: data = val; } + bool is_function() const { + return kind == FUNCTION; + } function_t& as_function() { assert(kind == FUNCTION); return boost::get<function_t>(data); @@ -345,6 +352,9 @@ public: data = val; } + bool is_name() const { + return data.type() == typeid(node_t::nameid_t); + } node_t::nameid_t& as_name() { assert(kind == NODE_ID || kind == ATTR_ID); return boost::get<node_t::nameid_t>(data); |