Changed xpath to use intrusive_ptr; got the xml command working
This commit is contained in:
parent
65af168838
commit
f83705b847
21 changed files with 920 additions and 1386 deletions
|
|
@ -37,6 +37,7 @@ libledger_la_SOURCES = \
|
|||
src/utils.cc \
|
||||
src/times.cc \
|
||||
src/mask.cc \
|
||||
src/abbrev.cc \
|
||||
src/commodity.cc \
|
||||
src/amount.cc \
|
||||
src/balance.cc \
|
||||
|
|
@ -49,7 +50,6 @@ libledger_la_SOURCES = \
|
|||
src/textual.cc \
|
||||
src/binary.cc \
|
||||
src/transform.cc \
|
||||
src/register.cc \
|
||||
src/report.cc \
|
||||
src/session.cc
|
||||
|
||||
|
|
@ -94,6 +94,7 @@ libpyledger_la_SOURCES = \
|
|||
|
||||
|
||||
pkginclude_HEADERS = \
|
||||
src/abbrev.h \
|
||||
src/amount.h \
|
||||
src/balance.h \
|
||||
src/balpair.h \
|
||||
|
|
@ -113,7 +114,6 @@ pkginclude_HEADERS = \
|
|||
src/pyinterp.h \
|
||||
src/pyledger.h \
|
||||
src/pyutils.h \
|
||||
src/register.h \
|
||||
src/report.h \
|
||||
src/scoped_execute.h \
|
||||
src/session.h \
|
||||
|
|
|
|||
|
|
@ -293,7 +293,7 @@ bool entry_base_t::finalize()
|
|||
|
||||
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), data(NULL)
|
||||
code(e.code), payee(e.payee)
|
||||
{
|
||||
TRACE_CTOR(entry_t, "copy");
|
||||
for (transactions_list::const_iterator i = transactions.begin();
|
||||
|
|
@ -538,9 +538,6 @@ journal_t::~journal_t()
|
|||
assert(master);
|
||||
checked_delete(master);
|
||||
|
||||
if (document)
|
||||
checked_delete(document);
|
||||
|
||||
// Don't bother unhooking each entry's transactions from the
|
||||
// accounts they refer to, because all accounts are about to
|
||||
// be deleted.
|
||||
|
|
|
|||
|
|
@ -33,19 +33,10 @@
|
|||
#define _JOURNAL_H
|
||||
|
||||
#include "amount.h"
|
||||
#include "xpath.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
namespace xml {
|
||||
class document_t;
|
||||
class xpath_t;
|
||||
|
||||
class transaction_node_t;
|
||||
class entry_node_t;
|
||||
class account_node_t;
|
||||
class journal_node_t;
|
||||
}
|
||||
|
||||
// These flags persist with the object
|
||||
#define TRANSACTION_NORMAL 0x0000
|
||||
#define TRANSACTION_VIRTUAL 0x0001
|
||||
|
|
@ -72,43 +63,20 @@ class transaction_t : public supports_flags<>
|
|||
optional<amount_t> cost;
|
||||
optional<string> cost_expr;
|
||||
optional<string> note;
|
||||
unsigned long beg_pos;
|
||||
unsigned long beg_line;
|
||||
unsigned long end_pos;
|
||||
unsigned long end_line;
|
||||
|
||||
typedef xml::transaction_node_t node_type;
|
||||
mutable node_type * data;
|
||||
|
||||
static bool use_effective_date;
|
||||
|
||||
explicit transaction_t(account_t * _account = NULL)
|
||||
: supports_flags<>(TRANSACTION_NORMAL),
|
||||
entry(NULL),
|
||||
state(UNCLEARED),
|
||||
account(_account),
|
||||
beg_pos(0),
|
||||
beg_line(0),
|
||||
end_pos(0),
|
||||
end_line(0),
|
||||
data(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),
|
||||
beg_pos(0),
|
||||
beg_line(0),
|
||||
end_pos(0),
|
||||
end_line(0),
|
||||
data(NULL) {
|
||||
: 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&");
|
||||
}
|
||||
|
|
@ -123,12 +91,7 @@ class transaction_t : public supports_flags<>
|
|||
amount_expr(xact.amount_expr),
|
||||
cost(xact.cost),
|
||||
cost_expr(xact.cost_expr),
|
||||
note(xact.note),
|
||||
beg_pos(xact.beg_pos),
|
||||
beg_line(xact.beg_line),
|
||||
end_pos(xact.end_pos),
|
||||
end_line(xact.end_line),
|
||||
data(xact.data) {
|
||||
note(xact.note) {
|
||||
TRACE_CTOR(transaction_t, "copy");
|
||||
}
|
||||
~transaction_t();
|
||||
|
|
@ -164,19 +127,12 @@ class entry_base_t
|
|||
{
|
||||
public:
|
||||
journal_t * journal;
|
||||
unsigned long src_idx;
|
||||
unsigned long beg_pos;
|
||||
unsigned long beg_line;
|
||||
unsigned long end_pos;
|
||||
unsigned long end_line;
|
||||
transactions_list transactions;
|
||||
|
||||
entry_base_t() : journal(NULL),
|
||||
beg_pos(0), beg_line(0), end_pos(0), end_line(0) {
|
||||
entry_base_t() : journal(NULL) {
|
||||
TRACE_CTOR(entry_base_t, "");
|
||||
}
|
||||
entry_base_t(const entry_base_t& e) : journal(NULL),
|
||||
beg_pos(0), beg_line(0), end_pos(0), end_line(0)
|
||||
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();
|
||||
|
|
@ -217,10 +173,7 @@ public:
|
|||
optional<string> code;
|
||||
string payee;
|
||||
|
||||
typedef xml::entry_node_t node_type;
|
||||
mutable node_type * data;
|
||||
|
||||
entry_t() : data(NULL) {
|
||||
entry_t() {
|
||||
TRACE_CTOR(entry_t, "");
|
||||
}
|
||||
entry_t(const entry_t& e);
|
||||
|
|
@ -337,9 +290,6 @@ class account_t
|
|||
unsigned short depth;
|
||||
accounts_map accounts;
|
||||
|
||||
typedef xml::account_node_t node_type;
|
||||
mutable node_type * data;
|
||||
|
||||
mutable ident_t ident;
|
||||
mutable string _fullname;
|
||||
|
||||
|
|
@ -347,7 +297,7 @@ class account_t
|
|||
const string& _name = "",
|
||||
const optional<string> _note = none)
|
||||
: parent(_parent), name(_name), note(_note),
|
||||
depth(parent ? parent->depth + 1 : 0), data(NULL), ident(0) {
|
||||
depth(parent ? parent->depth + 1 : 0), ident(0) {
|
||||
TRACE_CTOR(account_t, "account_t *, const string&, const string&");
|
||||
}
|
||||
~account_t();
|
||||
|
|
@ -432,16 +382,6 @@ class journal_t
|
|||
char * item_pool;
|
||||
char * item_pool_end;
|
||||
|
||||
// This is used for dynamically representing the journal data as an
|
||||
// XML tree, to facilitate transformations without modifying any of
|
||||
// the underlying structures (the transformers modify the XML tree
|
||||
// -- perhaps even adding, changing or deleting nodes -- but they do
|
||||
// not affect the basic data parsed from the journal file).
|
||||
mutable xml::document_t * document;
|
||||
|
||||
typedef xml::journal_node_t node_type;
|
||||
mutable node_type * data;
|
||||
|
||||
auto_entries_list auto_entries;
|
||||
period_entries_list period_entries;
|
||||
mutable accounts_map accounts_cache;
|
||||
|
|
@ -450,7 +390,7 @@ class journal_t
|
|||
|
||||
journal_t(session_t * _session)
|
||||
: session(_session), basket(NULL),
|
||||
item_pool(NULL), item_pool_end(NULL), document(NULL) {
|
||||
item_pool(NULL), item_pool_end(NULL) {
|
||||
TRACE_CTOR(journal_t, "");
|
||||
master = new account_t(NULL, "");
|
||||
master->journal = this;
|
||||
|
|
|
|||
12
src/ledger.h
12
src/ledger.h
|
|
@ -46,24 +46,12 @@
|
|||
#include <value.h>
|
||||
#include <xpath.h>
|
||||
#include <format.h>
|
||||
//#include <quotes.h>
|
||||
|
||||
#include <session.h>
|
||||
#include <journal.h>
|
||||
#include <parser.h>
|
||||
#include <textual.h>
|
||||
#include <binary.h>
|
||||
|
||||
#include <report.h>
|
||||
#include <transform.h>
|
||||
|
||||
#include <register.h>
|
||||
|
||||
#if 0
|
||||
#include <emacs.h>
|
||||
#include <csv.h>
|
||||
#include <derive.h>
|
||||
#include <reconcile.h>
|
||||
#endif
|
||||
|
||||
#endif // _LEDGER_H
|
||||
|
|
|
|||
57
src/main.cc
57
src/main.cc
|
|
@ -116,18 +116,17 @@ static int read_and_report(report_t * report, int argc, char * argv[],
|
|||
|
||||
string verb = *arg++;
|
||||
|
||||
std::auto_ptr<xml::xpath_t::functor_t> command;
|
||||
xml::xpath_t::function_t command;
|
||||
|
||||
#if 0
|
||||
if (verb == "register" || verb == "reg" || verb == "r") {
|
||||
#if 1
|
||||
command.reset(new register_command);
|
||||
#else
|
||||
command = register_command();
|
||||
#if 0
|
||||
command = new format_command
|
||||
("register", either_or(report->format_string,
|
||||
report->session->register_format));
|
||||
#endif
|
||||
}
|
||||
#if 0
|
||||
else if (verb == "balance" || verb == "bal" || verb == "b") {
|
||||
if (! report->raw_mode) {
|
||||
report->transforms.push_back(new accounts_transform);
|
||||
|
|
@ -166,9 +165,10 @@ static int read_and_report(report_t * report, int argc, char * argv[],
|
|||
command = new csv_command;
|
||||
else if (verb == "emacs" || verb == "lisp")
|
||||
command = new emacs_command;
|
||||
else
|
||||
#endif
|
||||
else if (verb == "xml")
|
||||
command.reset(new xml_command);
|
||||
if (verb == "xml")
|
||||
command = xml_command();
|
||||
else if (verb == "expr")
|
||||
;
|
||||
else if (verb == "xpath")
|
||||
|
|
@ -198,10 +198,10 @@ static int read_and_report(report_t * report, int argc, char * argv[],
|
|||
|
||||
// jww (2007-04-19): This is an error, since command is an
|
||||
// auto_ptr!
|
||||
if (xml::xpath_t::op_t * def = report->lookup(buf))
|
||||
command.reset(def->functor_obj());
|
||||
if (xml::xpath_t::ptr_op_t def = report->lookup(buf))
|
||||
command = def->as_function();
|
||||
|
||||
if (! command.get())
|
||||
if (! command)
|
||||
throw_(std::logic_error, string("Unrecognized command '") + verb + "'");
|
||||
}
|
||||
|
||||
|
|
@ -211,23 +211,15 @@ static int read_and_report(report_t * report, int argc, char * argv[],
|
|||
session.read_init();
|
||||
|
||||
INFO_START(journal, "Read journal file");
|
||||
journal_t * journal = session.read_data(report->account);
|
||||
{
|
||||
textual_parser_t text_parser;
|
||||
ifstream input(session.data_file);
|
||||
|
||||
#if 1
|
||||
xml::document_t temp(xml::LEDGER_NODE);
|
||||
xml::document_builder_t builder(temp);
|
||||
text_parser.parse(input, session.data_file, builder);
|
||||
temp.print(std::cout);
|
||||
#else
|
||||
xml::xml_writer_t writer(std::cout);
|
||||
text_parser.parse(input, session.data_file, writer);
|
||||
#endif
|
||||
}
|
||||
xml::document_t xml_document(xml::LEDGER_NODE);
|
||||
xml::document_builder_t builder(xml_document);
|
||||
journal_t * journal = session.create_journal();
|
||||
if (! session.read_data(builder, journal, report->account))
|
||||
throw_(parse_error, "Failed to locate any journal entries; "
|
||||
"did you specify a valid file with -f?");
|
||||
|
||||
INFO_FINISH(journal);
|
||||
return 0;
|
||||
|
||||
TRACE_FINISH(entry_text, 1);
|
||||
TRACE_FINISH(entry_date, 1);
|
||||
|
|
@ -300,8 +292,7 @@ static int read_and_report(report_t * report, int argc, char * argv[],
|
|||
*out << "Result of calculation: ";
|
||||
}
|
||||
|
||||
xml::document_t temp(xml::LEDGER_NODE);
|
||||
*out << expr.calc(temp, report).strip_annotations() << std::endl;
|
||||
*out << expr.calc(xml_document, report).strip_annotations() << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -322,13 +313,14 @@ static int read_and_report(report_t * report, int argc, char * argv[],
|
|||
// Create the an argument scope containing the report command's
|
||||
// arguments, and then invoke the command.
|
||||
|
||||
std::auto_ptr<xml::xpath_t::scope_t> locals
|
||||
scoped_ptr<xml::xpath_t::scope_t> locals
|
||||
(new xml::xpath_t::scope_t(report, xml::xpath_t::scope_t::ARGUMENT));
|
||||
|
||||
locals->args = value_t::sequence_t();
|
||||
locals->args.push_back(out);
|
||||
locals->args.push_back(journal->document);
|
||||
locals->args.push_back(&xml_document);
|
||||
|
||||
#if 0
|
||||
if (command->wants_args) {
|
||||
for (strings_list::iterator i = args.begin();
|
||||
i != args.end();
|
||||
|
|
@ -381,14 +373,15 @@ static int read_and_report(report_t * report, int argc, char * argv[],
|
|||
(string("//xact[account =~ /(") + regexps[0] + ")/]"));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
INFO_START(transforms, "Applied transforms");
|
||||
report->apply_transforms(journal->document);
|
||||
report->apply_transforms(xml_document);
|
||||
INFO_FINISH(transforms);
|
||||
|
||||
INFO_START(command, "Did user command '" << verb << "'");
|
||||
value_t temp;
|
||||
(*command)(temp, locals.get());
|
||||
command(temp, locals.get());
|
||||
INFO_FINISH(command);
|
||||
|
||||
// Write out the binary cache, if need be
|
||||
|
|
@ -483,8 +476,8 @@ int main(int argc, char * argv[], char * envp[])
|
|||
session->register_parser(new ofx_parser_t);
|
||||
#endif
|
||||
session->register_parser(new qif_parser_t);
|
||||
session->register_parser(new textual_parser_t);
|
||||
#endif
|
||||
session->register_parser(new textual_parser_t);
|
||||
|
||||
std::auto_ptr<ledger::report_t> report(new ledger::report_t(session.get()));
|
||||
|
||||
|
|
|
|||
|
|
@ -32,17 +32,10 @@
|
|||
#ifndef _NODE_H
|
||||
#define _NODE_H
|
||||
|
||||
#include "journal.h"
|
||||
#include "value.h"
|
||||
//#include "parser.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
class transaction_t;
|
||||
class entry_t;
|
||||
class account_t;
|
||||
class journal_t;
|
||||
|
||||
namespace xml {
|
||||
|
||||
#define XML_NODE_IS_PARENT 0x1
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@ static ledger::option_t * find_option(const string& name);
|
|||
namespace ledger {
|
||||
|
||||
namespace {
|
||||
xml::xpath_t::op_t * find_option(xml::xpath_t::scope_t * scope,
|
||||
const string& name)
|
||||
xml::xpath_t::ptr_op_t find_option(xml::xpath_t::scope_t * scope,
|
||||
const string& name)
|
||||
{
|
||||
char buf[128];
|
||||
std::strcpy(buf, "option_");
|
||||
|
|
@ -57,7 +57,7 @@ namespace {
|
|||
return scope->lookup(buf);
|
||||
}
|
||||
|
||||
xml::xpath_t::op_t * find_option(xml::xpath_t::scope_t * scope,
|
||||
xml::xpath_t::ptr_op_t find_option(xml::xpath_t::scope_t * scope,
|
||||
const char letter)
|
||||
{
|
||||
char buf[9];
|
||||
|
|
@ -68,20 +68,20 @@ namespace {
|
|||
return scope->lookup(buf);
|
||||
}
|
||||
|
||||
void process_option(xml::xpath_t::functor_t * opt, xml::xpath_t::scope_t * scope,
|
||||
const char * arg)
|
||||
void process_option(const xml::xpath_t::function_t& opt,
|
||||
xml::xpath_t::scope_t * scope, const char * arg)
|
||||
{
|
||||
#if 0
|
||||
try {
|
||||
#endif
|
||||
std::auto_ptr<xml::xpath_t::scope_t> args;
|
||||
scoped_ptr<xml::xpath_t::scope_t> args;
|
||||
if (arg) {
|
||||
args.reset(new xml::xpath_t::scope_t(scope, xml::xpath_t::scope_t::ARGUMENT));
|
||||
args->args.set_string(arg);
|
||||
}
|
||||
|
||||
value_t temp;
|
||||
(*opt)(temp, args.get());
|
||||
opt(temp, args.get());
|
||||
#if 0
|
||||
}
|
||||
catch (error * err) {
|
||||
|
|
@ -99,13 +99,10 @@ namespace {
|
|||
bool process_option(const string& name, xml::xpath_t::scope_t * scope,
|
||||
const char * arg)
|
||||
{
|
||||
std::auto_ptr<xml::xpath_t::op_t> opt(find_option(scope, name));
|
||||
if (opt.get()) {
|
||||
xml::xpath_t::functor_t * def = opt->functor_obj();
|
||||
if (def) {
|
||||
process_option(def, scope, arg);
|
||||
return true;
|
||||
}
|
||||
xml::xpath_t::ptr_op_t opt(find_option(scope, name));
|
||||
if (opt) {
|
||||
process_option(opt->as_function(), scope, arg);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -134,7 +131,7 @@ void process_environment(const char ** envp, const string& tag,
|
|||
#if 0
|
||||
try {
|
||||
#endif
|
||||
if (! process_option(buf, scope, q + 1))
|
||||
if (! process_option(string(buf), scope, q + 1))
|
||||
#if 0
|
||||
throw new option_error("unknown option")
|
||||
#endif
|
||||
|
|
@ -181,50 +178,37 @@ void process_arguments(int argc, char ** argv, const bool anywhere,
|
|||
value = p;
|
||||
}
|
||||
|
||||
std::auto_ptr<xml::xpath_t::op_t> opt(find_option(scope, name));
|
||||
if (! opt.get())
|
||||
xml::xpath_t::ptr_op_t opt(find_option(scope, name));
|
||||
if (! opt)
|
||||
throw_(option_error, "illegal option --" << name);
|
||||
|
||||
xml::xpath_t::functor_t * def = opt->functor_obj();
|
||||
if (! def)
|
||||
throw_(option_error, "illegal option --" << name);
|
||||
|
||||
if (def->wants_args && value == NULL) {
|
||||
if (/*def->wants_args &&*/ value == NULL) {
|
||||
value = *++i;
|
||||
if (value == NULL)
|
||||
throw_(option_error, "missing option argument for --" << name);
|
||||
}
|
||||
process_option(def, scope, value);
|
||||
process_option(opt->as_function(), scope, value);
|
||||
}
|
||||
else if ((*i)[1] == '\0') {
|
||||
throw_(option_error, "illegal option -");
|
||||
}
|
||||
else {
|
||||
std::list<xml::xpath_t::op_t *> option_queue;
|
||||
std::list<xml::xpath_t::ptr_op_t> option_queue;
|
||||
|
||||
int x = 1;
|
||||
for (char c = (*i)[x]; c != '\0'; x++, c = (*i)[x]) {
|
||||
xml::xpath_t::op_t * opt = find_option(scope, c);
|
||||
xml::xpath_t::ptr_op_t opt = find_option(scope, c);
|
||||
if (! opt)
|
||||
throw_(option_error, "illegal option -" << c);
|
||||
|
||||
xml::xpath_t::functor_t * def = opt->functor_obj();
|
||||
if (! def)
|
||||
throw_(option_error, "illegal option -" << c);
|
||||
|
||||
option_queue.push_back(opt);
|
||||
}
|
||||
|
||||
for (std::list<xml::xpath_t::op_t *>::iterator
|
||||
o = option_queue.begin();
|
||||
o != option_queue.end();
|
||||
o++) {
|
||||
foreach (xml::xpath_t::ptr_op_t& o, option_queue) {
|
||||
char * value = NULL;
|
||||
|
||||
xml::xpath_t::functor_t * def = (*o)->functor_obj();
|
||||
assert(def);
|
||||
|
||||
#if 0
|
||||
if (def->wants_args) {
|
||||
#endif
|
||||
value = *++i;
|
||||
if (value == NULL)
|
||||
throw_(option_error, "missing option argument for -" <<
|
||||
|
|
@ -234,10 +218,11 @@ void process_arguments(int argc, char ** argv, const bool anywhere,
|
|||
'?'
|
||||
#endif
|
||||
);
|
||||
#if 0
|
||||
}
|
||||
process_option(def, scope, value);
|
||||
#endif
|
||||
process_option(o->as_function(), scope, value);
|
||||
|
||||
checked_delete(*o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,9 +47,9 @@ class parser_t
|
|||
|
||||
virtual bool test(std::istream& in) const = 0;
|
||||
|
||||
virtual void parse(std::istream& in,
|
||||
const path& pathname,
|
||||
xml::builder_t& builder) = 0;
|
||||
virtual std::size_t parse(std::istream& in,
|
||||
const path& pathname,
|
||||
xml::builder_t& builder) = 0;
|
||||
};
|
||||
|
||||
DECLARE_EXCEPTION(parse_error);
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ void python_interpreter_t::functor_t::operator()(value_t& result,
|
|||
else if (PyObject * err = PyErr_Occurred()) {
|
||||
PyErr_Print();
|
||||
throw_(xml::xpath_t::calc_error,
|
||||
"While calling Python function '" << name() << "'");
|
||||
"While calling Python function '" /*<< name() <<*/ "'");
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
|
|
@ -210,7 +210,7 @@ void python_interpreter_t::functor_t::operator()(value_t& result,
|
|||
catch (const error_already_set&) {
|
||||
PyErr_Print();
|
||||
throw_(xml::xpath_t::calc_error,
|
||||
"While calling Python function '" << name() << "'");
|
||||
"While calling Python function '" /*<< name() <<*/ "'");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,26 +70,24 @@ class python_interpreter_t : public xml::xpath_t::scope_t
|
|||
return eval(str, mode);
|
||||
}
|
||||
|
||||
class functor_t : public xml::xpath_t::functor_t {
|
||||
class functor_t {
|
||||
protected:
|
||||
boost::python::object func;
|
||||
public:
|
||||
functor_t(const string& name, boost::python::object _func)
|
||||
: xml::xpath_t::functor_t(name), func(_func) {}
|
||||
|
||||
functor_t(const string& name, boost::python::object _func) : func(_func) {}
|
||||
virtual void operator()(value_t& result, xml::xpath_t::scope_t * locals);
|
||||
};
|
||||
|
||||
virtual void define(const string& name, xml::xpath_t::op_t * def) {
|
||||
virtual void define(const string& name, xml::xpath_t::ptr_op_t def) {
|
||||
// Pass any definitions up to our parent
|
||||
parent->define(name, def);
|
||||
}
|
||||
|
||||
virtual xml::xpath_t::op_t * lookup(const string& name) {
|
||||
boost::python::object func = eval(name);
|
||||
if (! func)
|
||||
virtual xml::xpath_t::ptr_op_t lookup(const string& name) {
|
||||
if (boost::python::object func = eval(name))
|
||||
return xml::xpath_t::wrap_functor(functor_t(name, func));
|
||||
else
|
||||
return parent ? parent->lookup(name) : NULL;
|
||||
return xml::xpath_t::wrap_functor(new functor_t(name, func));
|
||||
}
|
||||
|
||||
class lambda_t : public functor_t {
|
||||
|
|
|
|||
|
|
@ -38,12 +38,10 @@ report_t::~report_t()
|
|||
TRACE_DTOR(report_t);
|
||||
}
|
||||
|
||||
void report_t::apply_transforms(xml::document_t * document)
|
||||
void report_t::apply_transforms(xml::document_t& document)
|
||||
{
|
||||
for (ptr_list<transform_t>::iterator i = transforms.begin();
|
||||
i != transforms.end();
|
||||
i++)
|
||||
i->execute(document);
|
||||
foreach (transform_t& transform, transforms)
|
||||
transform.execute(document);
|
||||
}
|
||||
|
||||
void report_t::abbrev(value_t& result, xml::xpath_t::scope_t * locals)
|
||||
|
|
@ -107,7 +105,7 @@ bool report_t::resolve(const string& name, value_t& result,
|
|||
return xml::xpath_t::scope_t::resolve(name, result, locals);
|
||||
}
|
||||
|
||||
xml::xpath_t::op_t * report_t::lookup(const string& name)
|
||||
xml::xpath_t::ptr_op_t report_t::lookup(const string& name)
|
||||
{
|
||||
const char * p = name.c_str();
|
||||
switch (*p) {
|
||||
|
|
@ -122,88 +120,91 @@ xml::xpath_t::op_t * report_t::lookup(const string& name)
|
|||
else
|
||||
#endif
|
||||
if (std::strcmp(p, "amount") == 0)
|
||||
return MAKE_FUNCTOR(report_t, option_amount);
|
||||
return MAKE_FUNCTOR(report_t::option_amount);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
if (std::strcmp(p, "bar") == 0)
|
||||
return MAKE_FUNCTOR(report_t, option_bar);
|
||||
return MAKE_FUNCTOR(report_t::option_bar);
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case 'c':
|
||||
if (std::strcmp(p, "clean") == 0)
|
||||
return MAKE_FUNCTOR(report_t, option_clean);
|
||||
return MAKE_FUNCTOR(report_t::option_clean);
|
||||
else if (std::strcmp(p, "compact") == 0)
|
||||
return MAKE_FUNCTOR(report_t, option_compact);
|
||||
return MAKE_FUNCTOR(report_t::option_compact);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 'e':
|
||||
#if 0
|
||||
if (std::strcmp(p, "entries") == 0)
|
||||
return MAKE_FUNCTOR(report_t, option_entries);
|
||||
return MAKE_FUNCTOR(report_t::option_entries);
|
||||
else if (std::strcmp(p, "eval") == 0)
|
||||
return MAKE_FUNCTOR(report_t, option_eval);
|
||||
return MAKE_FUNCTOR(report_t::option_eval);
|
||||
else if (std::strcmp(p, "exclude") == 0)
|
||||
return MAKE_FUNCTOR(report_t, option_remove);
|
||||
return MAKE_FUNCTOR(report_t::option_remove);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
#if 0
|
||||
if (std::strcmp(p, "foo") == 0)
|
||||
return MAKE_FUNCTOR(report_t, option_foo);
|
||||
else if (std::strcmp(p, "format") == 0)
|
||||
return MAKE_FUNCTOR(report_t, option_format);
|
||||
return MAKE_FUNCTOR(report_t::option_foo);
|
||||
else
|
||||
#endif
|
||||
if (std::strcmp(p, "format") == 0)
|
||||
return MAKE_FUNCTOR(report_t::option_format);
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
#if 0
|
||||
if (std::strcmp(p, "include") == 0)
|
||||
return MAKE_FUNCTOR(report_t, option_select);
|
||||
return MAKE_FUNCTOR(report_t::option_select);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
#if 0
|
||||
if (! *(p + 1) || std::strcmp(p, "limit") == 0)
|
||||
return MAKE_FUNCTOR(report_t, option_limit);
|
||||
return MAKE_FUNCTOR(report_t::option_limit);
|
||||
#endif
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case 'm':
|
||||
if (std::strcmp(p, "merge") == 0)
|
||||
return MAKE_FUNCTOR(report_t, option_merge);
|
||||
return MAKE_FUNCTOR(report_t::option_merge);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 'r':
|
||||
#if 0
|
||||
if (std::strcmp(p, "remove") == 0)
|
||||
return MAKE_FUNCTOR(report_t, option_remove);
|
||||
return MAKE_FUNCTOR(report_t::option_remove);
|
||||
#endif
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case 's':
|
||||
if (std::strcmp(p, "select") == 0)
|
||||
return MAKE_FUNCTOR(report_t, option_select);
|
||||
return MAKE_FUNCTOR(report_t::option_select);
|
||||
else if (std::strcmp(p, "split") == 0)
|
||||
return MAKE_FUNCTOR(report_t, option_split);
|
||||
return MAKE_FUNCTOR(report_t::option_split);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 't':
|
||||
if (! *(p + 1))
|
||||
return MAKE_FUNCTOR(report_t, option_amount);
|
||||
return MAKE_FUNCTOR(report_t::option_amount);
|
||||
else if (std::strcmp(p, "total") == 0)
|
||||
return MAKE_FUNCTOR(report_t, option_total);
|
||||
return MAKE_FUNCTOR(report_t::option_total);
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
if (! *(p + 1))
|
||||
return MAKE_FUNCTOR(report_t, option_total);
|
||||
return MAKE_FUNCTOR(report_t::option_total);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ class report_t : public xml::xpath_t::scope_t
|
|||
|
||||
virtual ~report_t();
|
||||
|
||||
void apply_transforms(xml::document_t * document);
|
||||
void apply_transforms(xml::document_t& document);
|
||||
|
||||
//
|
||||
// Utility functions for value expressions
|
||||
|
|
@ -163,7 +163,7 @@ class report_t : public xml::xpath_t::scope_t
|
|||
|
||||
virtual bool resolve(const string& name, value_t& result,
|
||||
xml::xpath_t::scope_t * locals);
|
||||
virtual xml::xpath_t::op_t * lookup(const string& name);
|
||||
virtual xml::xpath_t::ptr_op_t lookup(const string& name);
|
||||
};
|
||||
|
||||
string abbrev(const string& str, unsigned int width,
|
||||
|
|
|
|||
|
|
@ -68,24 +68,24 @@ void release_session_context()
|
|||
#endif
|
||||
}
|
||||
|
||||
void session_t::read_journal(std::istream& in,
|
||||
const path& pathname,
|
||||
xml::builder_t& builder)
|
||||
std::size_t session_t::read_journal(std::istream& in,
|
||||
const path& pathname,
|
||||
xml::builder_t& builder)
|
||||
{
|
||||
#if 0
|
||||
if (! master)
|
||||
master = journal->master;
|
||||
#endif
|
||||
|
||||
for (ptr_list<parser_t>::iterator i = parsers.begin();
|
||||
i != parsers.end();
|
||||
i++)
|
||||
if (i->test(in))
|
||||
i->parse(in, pathname, builder);
|
||||
foreach (parser_t& parser, parsers)
|
||||
if (parser.test(in))
|
||||
return parser.parse(in, pathname, builder);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void session_t::read_journal(const path& pathname,
|
||||
xml::builder_t& builder)
|
||||
std::size_t session_t::read_journal(const path& pathname,
|
||||
xml::builder_t& builder)
|
||||
{
|
||||
#if 0
|
||||
journal->sources.push_back(pathname);
|
||||
|
|
@ -95,7 +95,7 @@ void session_t::read_journal(const path& pathname,
|
|||
throw_(std::logic_error, "Cannot read file" << pathname);
|
||||
|
||||
ifstream stream(pathname);
|
||||
read_journal(stream, pathname, builder);
|
||||
return read_journal(stream, pathname, builder);
|
||||
}
|
||||
|
||||
void session_t::read_init()
|
||||
|
|
@ -111,21 +111,16 @@ void session_t::read_init()
|
|||
// jww (2006-09-15): Read initialization options here!
|
||||
}
|
||||
|
||||
journal_t * session_t::read_data(const string& master_account)
|
||||
std::size_t session_t::read_data(xml::builder_t& builder,
|
||||
journal_t * journal,
|
||||
const string& master_account)
|
||||
{
|
||||
#if 1
|
||||
return NULL;
|
||||
#else
|
||||
if (data_file.empty())
|
||||
throw_(parse_error, "No journal file was specified (please use -f)");
|
||||
|
||||
TRACE_START(parser, 1, "Parsing journal file");
|
||||
|
||||
journal_t * journal = new_journal();
|
||||
journal->document = new xml::document_t;
|
||||
journal->document->set_top(xml::wrap_node(journal->document, journal));
|
||||
|
||||
unsigned int entry_count = 0;
|
||||
std::size_t entry_count = 0;
|
||||
|
||||
DEBUG("ledger.cache", "3. use_cache = " << use_cache);
|
||||
|
||||
|
|
@ -136,8 +131,7 @@ journal_t * session_t::read_data(const string& master_account)
|
|||
scoped_variable<optional<path> >
|
||||
save_price_db(journal->price_db, price_db);
|
||||
|
||||
ifstream stream(*cache_file);
|
||||
entry_count += read_journal(stream, journal, NULL, data_file);
|
||||
entry_count += read_journal(*cache_file, builder);
|
||||
if (entry_count > 0)
|
||||
cache_dirty = false;
|
||||
}
|
||||
|
|
@ -150,7 +144,7 @@ journal_t * session_t::read_data(const string& master_account)
|
|||
|
||||
journal->price_db = price_db;
|
||||
if (journal->price_db && exists(*journal->price_db)) {
|
||||
if (read_journal(*journal->price_db, journal)) {
|
||||
if (read_journal(*journal->price_db, builder)) {
|
||||
throw_(parse_error, "Entries not allowed in price history file");
|
||||
} else {
|
||||
DEBUG("ledger.cache",
|
||||
|
|
@ -163,10 +157,10 @@ journal_t * session_t::read_data(const string& master_account)
|
|||
if (data_file == "-") {
|
||||
use_cache = false;
|
||||
journal->sources.push_back("<stdin>");
|
||||
entry_count += read_journal(std::cin, journal, acct);
|
||||
entry_count += read_journal(std::cin, "<stdin>", builder);
|
||||
}
|
||||
else if (exists(data_file)) {
|
||||
entry_count += read_journal(data_file, journal, acct);
|
||||
entry_count += read_journal(data_file, builder);
|
||||
if (journal->price_db)
|
||||
journal->sources.push_back(*journal->price_db);
|
||||
}
|
||||
|
|
@ -174,14 +168,9 @@ journal_t * session_t::read_data(const string& master_account)
|
|||
|
||||
VERIFY(journal->valid());
|
||||
|
||||
if (entry_count == 0)
|
||||
throw_(parse_error, "Failed to locate any journal entries; "
|
||||
"did you specify a valid file with -f?");
|
||||
|
||||
TRACE_STOP(parser, 1);
|
||||
|
||||
return journal;
|
||||
#endif
|
||||
return entry_count;
|
||||
}
|
||||
|
||||
bool session_t::resolve(const string& name, value_t& result,
|
||||
|
|
@ -221,7 +210,7 @@ bool session_t::resolve(const string& name, value_t& result,
|
|||
return xml::xpath_t::scope_t::resolve(name, result, locals);
|
||||
}
|
||||
|
||||
xml::xpath_t::op_t * session_t::lookup(const string& name)
|
||||
xml::xpath_t::ptr_op_t session_t::lookup(const string& name)
|
||||
{
|
||||
const char * p = name.c_str();
|
||||
switch (*p) {
|
||||
|
|
@ -231,24 +220,26 @@ xml::xpath_t::op_t * session_t::lookup(const string& name)
|
|||
switch (*p) {
|
||||
case 'd':
|
||||
if (std::strcmp(p, "debug") == 0)
|
||||
return MAKE_FUNCTOR(session_t, option_debug);
|
||||
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);
|
||||
return MAKE_FUNCTOR(session_t::option_file);
|
||||
break;
|
||||
|
||||
case 't':
|
||||
if (std::strcmp(p, "trace") == 0)
|
||||
return MAKE_FUNCTOR(session_t, option_trace);
|
||||
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);
|
||||
return MAKE_FUNCTOR(session_t::option_verbose);
|
||||
else if (std::strcmp(p, "verify") == 0)
|
||||
return MAKE_FUNCTOR(session_t, option_verify);
|
||||
return MAKE_FUNCTOR(session_t::option_verify);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,9 +32,10 @@
|
|||
#ifndef _SESSION_H
|
||||
#define _SESSION_H
|
||||
|
||||
#include "xpath.h"
|
||||
#include "journal.h"
|
||||
#include "parser.h"
|
||||
#include "register.h"
|
||||
#include "abbrev.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
|
|
@ -131,7 +132,7 @@ class session_t : public xml::xpath_t::scope_t
|
|||
TRACE_DTOR(session_t);
|
||||
}
|
||||
|
||||
journal_t * new_journal() {
|
||||
journal_t * create_journal() {
|
||||
journal_t * journal = new journal_t(this);
|
||||
journals.push_back(journal);
|
||||
return journal;
|
||||
|
|
@ -148,15 +149,17 @@ class session_t : public xml::xpath_t::scope_t
|
|||
checked_delete(journal);
|
||||
}
|
||||
|
||||
void read_journal(std::istream& in,
|
||||
const path& pathname,
|
||||
xml::builder_t& builder);
|
||||
void read_journal(const path& pathname,
|
||||
xml::builder_t& builder);
|
||||
std::size_t read_journal(std::istream& in,
|
||||
const path& pathname,
|
||||
xml::builder_t& builder);
|
||||
std::size_t read_journal(const path& pathname,
|
||||
xml::builder_t& builder);
|
||||
|
||||
void read_init();
|
||||
|
||||
journal_t * read_data(const string& master_account = "");
|
||||
std::size_t read_data(xml::builder_t& builder,
|
||||
journal_t * journal,
|
||||
const string& master_account = "");
|
||||
|
||||
void register_parser(parser_t * parser) {
|
||||
parsers.push_back(parser);
|
||||
|
|
@ -179,7 +182,7 @@ class session_t : public xml::xpath_t::scope_t
|
|||
|
||||
virtual bool resolve(const string& name, value_t& result,
|
||||
xml::xpath_t::scope_t * locals = NULL);
|
||||
virtual xml::xpath_t::op_t * lookup(const string& name);
|
||||
virtual xml::xpath_t::ptr_op_t lookup(const string& name);
|
||||
|
||||
//
|
||||
// Debug options
|
||||
|
|
|
|||
|
|
@ -140,6 +140,7 @@ extern "C" {
|
|||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
#include <boost/lambda/bind.hpp>
|
||||
#include <boost/lambda/lambda.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
|
@ -154,5 +155,6 @@ extern "C" {
|
|||
#include <boost/ptr_container/ptr_list.hpp>
|
||||
#include <boost/ptr_container/ptr_vector.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
#endif // _SYSTEM_HH
|
||||
|
|
|
|||
|
|
@ -275,9 +275,9 @@ bool textual_parser_t::test(std::istream& in) const
|
|||
return true;
|
||||
}
|
||||
|
||||
void textual_parser_t::parse(std::istream& in,
|
||||
const path& pathname,
|
||||
builder_t& builder)
|
||||
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:");
|
||||
|
||||
|
|
@ -285,6 +285,8 @@ void textual_parser_t::parse(std::istream& in,
|
|||
|
||||
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);
|
||||
|
|
@ -460,6 +462,7 @@ void textual_parser_t::parse(std::istream& in,
|
|||
default:
|
||||
TRACE_START(entries, 1, "Time spent handling entries:");
|
||||
parse_entry(in, builder, line, end_of_line);
|
||||
count++;
|
||||
TRACE_STOP(entries, 1);
|
||||
break;
|
||||
}
|
||||
|
|
@ -470,6 +473,8 @@ void textual_parser_t::parse(std::istream& in,
|
|||
builder.end_node(JOURNAL_NODE);
|
||||
|
||||
TRACE_STOP(parsing_total, 1);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
} // namespace ledger
|
||||
|
|
|
|||
|
|
@ -41,9 +41,9 @@ class textual_parser_t : public parser_t
|
|||
public:
|
||||
virtual bool test(std::istream& in) const;
|
||||
|
||||
virtual void parse(std::istream& in,
|
||||
const path& pathname,
|
||||
xml::builder_t& builder);
|
||||
virtual std::size_t parse(std::istream& in,
|
||||
const path& pathname,
|
||||
xml::builder_t& builder);
|
||||
};
|
||||
|
||||
} // namespace ledger
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
namespace ledger {
|
||||
|
||||
#if 0
|
||||
void populate_account(account_t& acct, xml::document_t * document)
|
||||
void populate_account(account_t& acct, xml::document_t& document)
|
||||
{
|
||||
if (! acct.parent)
|
||||
return;
|
||||
|
|
@ -61,7 +61,7 @@ void populate_account(account_t& acct, xml::document_t * document)
|
|||
}
|
||||
|
||||
class populate_accounts : public repitem_t::select_callback_t {
|
||||
virtual void operator()(xml::document_t * document) {
|
||||
virtual void operator()(xml::document_t& document) {
|
||||
if (item->kind == repitem_t::TRANSACTION) {
|
||||
item->extract();
|
||||
populate_account(*static_cast<xact_repitem_t *>(item)->account(), item);
|
||||
|
|
@ -70,13 +70,13 @@ class populate_accounts : public repitem_t::select_callback_t {
|
|||
};
|
||||
|
||||
class clear_account_data : public repitem_t::select_callback_t {
|
||||
virtual void operator()(xml::document_t * document) {
|
||||
virtual void operator()(xml::document_t& document) {
|
||||
if (item->kind == repitem_t::ACCOUNT)
|
||||
static_cast<account_repitem_t *>(item)->account->data = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
void accounts_transform::execute(xml::document_t * document)
|
||||
void accounts_transform::execute(xml::document_t& document)
|
||||
{
|
||||
populate_accounts cb1;
|
||||
items->select_all(cb1);
|
||||
|
|
@ -99,7 +99,7 @@ void accounts_transform::execute(xml::document_t * document)
|
|||
items->select_all(cb2);
|
||||
}
|
||||
|
||||
void compact_transform::execute(xml::document_t * document)
|
||||
void compact_transform::execute(xml::document_t& document)
|
||||
{
|
||||
for (repitem_t * i = items; i; i = i->next) {
|
||||
if (i->kind == repitem_t::ACCOUNT) {
|
||||
|
|
@ -138,7 +138,7 @@ void compact_transform::execute(xml::document_t * document)
|
|||
}
|
||||
}
|
||||
|
||||
void clean_transform::execute(xml::document_t * document)
|
||||
void clean_transform::execute(xml::document_t& document)
|
||||
{
|
||||
repitem_t * i = items;
|
||||
while (i) {
|
||||
|
|
@ -169,11 +169,11 @@ void clean_transform::execute(xml::document_t * document)
|
|||
}
|
||||
}
|
||||
|
||||
void entries_transform::execute(xml::document_t * document)
|
||||
void entries_transform::execute(xml::document_t& document)
|
||||
{
|
||||
}
|
||||
|
||||
void optimize_transform::execute(xml::document_t * document)
|
||||
void optimize_transform::execute(xml::document_t& document)
|
||||
{
|
||||
for (repitem_t * i = items; i; i = i->next) {
|
||||
if (i->kind == repitem_t::ENTRY) {
|
||||
|
|
@ -194,7 +194,7 @@ void optimize_transform::execute(xml::document_t * document)
|
|||
}
|
||||
}
|
||||
|
||||
void split_transform::execute(xml::document_t * document)
|
||||
void split_transform::execute(xml::document_t& document)
|
||||
{
|
||||
for (repitem_t * i = items; i; i = i->next) {
|
||||
if (i->contents && i->contents->next) {
|
||||
|
|
@ -236,7 +236,7 @@ void split_transform::execute(xml::document_t * document)
|
|||
}
|
||||
}
|
||||
|
||||
void merge_transform::execute(xml::document_t * document)
|
||||
void merge_transform::execute(xml::document_t& document)
|
||||
{
|
||||
for (repitem_t * i = items; i; i = i->next) {
|
||||
if (i->next) {
|
||||
|
|
@ -290,13 +290,13 @@ namespace {
|
|||
#define REPITEM_FLAGGED 0x1
|
||||
|
||||
class mark_selected : public repitem_t::select_callback_t {
|
||||
virtual void operator()(xml::document_t * document) {
|
||||
virtual void operator()(xml::document_t& document) {
|
||||
item->flags |= REPITEM_FLAGGED;
|
||||
}
|
||||
};
|
||||
|
||||
class mark_selected_and_ancestors : public repitem_t::select_callback_t {
|
||||
virtual void operator()(xml::document_t * document) {
|
||||
virtual void operator()(xml::document_t& document) {
|
||||
while (item->parent) {
|
||||
item->flags |= REPITEM_FLAGGED;
|
||||
item = item->parent;
|
||||
|
|
@ -305,27 +305,27 @@ namespace {
|
|||
};
|
||||
|
||||
class delete_unmarked : public repitem_t::select_callback_t {
|
||||
virtual void operator()(xml::document_t * document) {
|
||||
virtual void operator()(xml::document_t& document) {
|
||||
if (item->parent && ! (item->flags & REPITEM_FLAGGED))
|
||||
checked_delete(item);
|
||||
}
|
||||
};
|
||||
|
||||
class delete_marked : public repitem_t::select_callback_t {
|
||||
virtual void operator()(xml::document_t * document) {
|
||||
virtual void operator()(xml::document_t& document) {
|
||||
if (item->flags & REPITEM_FLAGGED)
|
||||
checked_delete(item);
|
||||
}
|
||||
};
|
||||
|
||||
class clear_flags : public repitem_t::select_callback_t {
|
||||
virtual void operator()(xml::document_t * document) {
|
||||
virtual void operator()(xml::document_t& document) {
|
||||
item->flags = 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void select_transform::execute(xml::document_t * document)
|
||||
void select_transform::execute(xml::document_t& document)
|
||||
{
|
||||
if (! path) {
|
||||
items->clear();
|
||||
|
|
@ -340,7 +340,7 @@ void select_transform::execute(xml::document_t * document)
|
|||
items->select_all(cb3);
|
||||
}
|
||||
|
||||
void remove_transform::execute(xml::document_t * document)
|
||||
void remove_transform::execute(xml::document_t& document)
|
||||
{
|
||||
if (! path)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -39,38 +39,38 @@ namespace ledger {
|
|||
class transform_t {
|
||||
public:
|
||||
virtual ~transform_t() {}
|
||||
virtual void execute(xml::document_t * document) = 0;
|
||||
virtual void execute(xml::document_t& document) = 0;
|
||||
};
|
||||
|
||||
class check_transform : public transform_t {
|
||||
// --check checks the validity of the item list.
|
||||
public:
|
||||
virtual void execute(xml::document_t * document);
|
||||
virtual void execute(xml::document_t& document);
|
||||
};
|
||||
|
||||
class accounts_transform : public transform_t {
|
||||
// --accounts transforms the report tree into an account-wise view.
|
||||
public:
|
||||
virtual void execute(xml::document_t * document);
|
||||
virtual void execute(xml::document_t& document);
|
||||
};
|
||||
|
||||
class compact_transform : public transform_t {
|
||||
// --compact compacts an account tree to remove accounts with only
|
||||
// one child account.
|
||||
public:
|
||||
virtual void execute(xml::document_t * document);
|
||||
virtual void execute(xml::document_t& document);
|
||||
};
|
||||
|
||||
class clean_transform : public transform_t {
|
||||
// --clean clears out entries and accounts that have no contents.
|
||||
public:
|
||||
virtual void execute(xml::document_t * document);
|
||||
virtual void execute(xml::document_t& document);
|
||||
};
|
||||
|
||||
class entries_transform : public transform_t {
|
||||
// --entries transforms the report tree into an entries-wise view.
|
||||
public:
|
||||
virtual void execute(xml::document_t * document);
|
||||
virtual void execute(xml::document_t& document);
|
||||
};
|
||||
|
||||
class optimize_transform : public transform_t {
|
||||
|
|
@ -79,7 +79,7 @@ class optimize_transform : public transform_t {
|
|||
// commodity (one the negative of the other), the amount of the
|
||||
// second transaction will be nulled out.
|
||||
public:
|
||||
virtual void execute(xml::document_t * document);
|
||||
virtual void execute(xml::document_t& document);
|
||||
};
|
||||
|
||||
class split_transform : public transform_t {
|
||||
|
|
@ -89,7 +89,7 @@ class split_transform : public transform_t {
|
|||
// useful before sorting, for exampel, in order to sort by
|
||||
// transaction instead of by entry.
|
||||
public:
|
||||
virtual void execute(xml::document_t * document);
|
||||
virtual void execute(xml::document_t& document);
|
||||
};
|
||||
|
||||
class merge_transform : public transform_t {
|
||||
|
|
@ -97,7 +97,7 @@ class merge_transform : public transform_t {
|
|||
// which share the same entry will be merged into a group of
|
||||
// transactions under one reported entry.
|
||||
public:
|
||||
virtual void execute(xml::document_t * document);
|
||||
virtual void execute(xml::document_t& document);
|
||||
};
|
||||
|
||||
class combine_transform : public transform_t {
|
||||
|
|
@ -107,14 +107,14 @@ class combine_transform : public transform_t {
|
|||
// will show the terminating date or a label that is characteristic
|
||||
// of the set).
|
||||
public:
|
||||
virtual void execute(xml::document_t * document);
|
||||
virtual void execute(xml::document_t& document);
|
||||
};
|
||||
|
||||
class group_transform : public transform_t {
|
||||
// --group groups all transactions that affect the same account
|
||||
// within an entry, so that they appear as a single transaction.
|
||||
public:
|
||||
virtual void execute(xml::document_t * document);
|
||||
virtual void execute(xml::document_t& document);
|
||||
};
|
||||
|
||||
class collapse_transform : public transform_t {
|
||||
|
|
@ -123,7 +123,7 @@ class collapse_transform : public transform_t {
|
|||
// fictitous account "<total>" is used to represent the final sum,
|
||||
// if multiple accounts are involved.
|
||||
public:
|
||||
virtual void execute(xml::document_t * document);
|
||||
virtual void execute(xml::document_t& document);
|
||||
};
|
||||
|
||||
class subtotal_transform : public transform_t {
|
||||
|
|
@ -131,7 +131,7 @@ class subtotal_transform : public transform_t {
|
|||
// one giant entry. When used in conjunction with --group, the
|
||||
// affect is very similar to a regular balance report.
|
||||
public:
|
||||
virtual void execute(xml::document_t * document);
|
||||
virtual void execute(xml::document_t& document);
|
||||
};
|
||||
|
||||
#if 0
|
||||
|
|
@ -146,7 +146,7 @@ class select_transform : public transform_t
|
|||
}
|
||||
virtual ~select_transform() {}
|
||||
|
||||
virtual void execute(xml::document_t * document);
|
||||
virtual void execute(xml::document_t& document);
|
||||
};
|
||||
|
||||
class remove_transform : public select_transform
|
||||
|
|
@ -155,7 +155,7 @@ class remove_transform : public select_transform
|
|||
remove_transform(const string& selection_path)
|
||||
: select_transform(selection_path) {}
|
||||
|
||||
virtual void execute(xml::document_t * document);
|
||||
virtual void execute(xml::document_t& document);
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
|||
1308
src/xpath.cc
1308
src/xpath.cc
File diff suppressed because it is too large
Load diff
518
src/xpath.h
518
src/xpath.h
|
|
@ -41,6 +41,7 @@ class xpath_t
|
|||
{
|
||||
public:
|
||||
struct op_t;
|
||||
typedef intrusive_ptr<op_t> ptr_op_t;
|
||||
|
||||
static void initialize();
|
||||
static void shutdown();
|
||||
|
|
@ -49,145 +50,24 @@ public:
|
|||
DECLARE_EXCEPTION(compile_error);
|
||||
DECLARE_EXCEPTION(calc_error);
|
||||
|
||||
#if 0
|
||||
class context : public error_context {
|
||||
public:
|
||||
const xpath_t& xpath;
|
||||
const op_t * err_node;
|
||||
|
||||
context(const xpath_t& _xpath,
|
||||
const op_t * _err_node,
|
||||
const string& desc = "") throw();
|
||||
virtual ~context() throw();
|
||||
|
||||
virtual void describe(std::ostream& out) const throw();
|
||||
};
|
||||
#endif
|
||||
|
||||
public:
|
||||
class scope_t;
|
||||
|
||||
class functor_t {
|
||||
protected:
|
||||
string fname;
|
||||
public:
|
||||
bool wants_args;
|
||||
typedef function<void (value_t&, scope_t *)> function_t;
|
||||
|
||||
functor_t(const string& _fname, bool _wants_args = false)
|
||||
: fname(_fname), wants_args(_wants_args) {}
|
||||
virtual ~functor_t() {}
|
||||
#define MAKE_FUNCTOR(x) \
|
||||
xml::xpath_t::wrap_functor(bind(&x, this, _1, _2))
|
||||
|
||||
virtual void operator()(value_t& result, scope_t * locals) = 0;
|
||||
virtual string name() const { return fname; }
|
||||
};
|
||||
|
||||
template <typename T, typename U>
|
||||
class member_functor_t : public functor_t {
|
||||
public:
|
||||
T * ptr;
|
||||
U T::*dptr;
|
||||
|
||||
member_functor_t(const string& _name, T * _ptr, U T::*_dptr)
|
||||
: functor_t(_name, false), ptr(_ptr), dptr(_dptr) {}
|
||||
|
||||
virtual void operator()(value_t& result, scope_t * locals) {
|
||||
assert(ptr);
|
||||
assert(dptr);
|
||||
result = ptr->*dptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class member_functor_t<T, string> : public functor_t {
|
||||
public:
|
||||
T * ptr;
|
||||
string T::*dptr;
|
||||
|
||||
member_functor_t(const string& _name, T * _ptr, string T::*_dptr)
|
||||
: functor_t(_name, false), ptr(_ptr), dptr(_dptr) {}
|
||||
|
||||
virtual void operator()(value_t& result, scope_t * locals) {
|
||||
assert(ptr);
|
||||
assert(dptr);
|
||||
result.set_string(ptr->*dptr);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class memfun_functor_t : public functor_t {
|
||||
public:
|
||||
T * ptr;
|
||||
void (T::*mptr)(value_t& result);
|
||||
|
||||
memfun_functor_t(const string& _name, T * _ptr,
|
||||
void (T::*_mptr)(value_t& result))
|
||||
: functor_t(_name, false), ptr(_ptr), mptr(_mptr) {}
|
||||
|
||||
virtual void operator()(value_t& result, scope_t * locals = NULL) {
|
||||
assert(ptr);
|
||||
assert(mptr);
|
||||
assert(locals || locals == NULL);
|
||||
(ptr->*mptr)(result);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class memfun_args_functor_t : public functor_t {
|
||||
public:
|
||||
T * ptr;
|
||||
void (T::*mptr)(value_t& result, scope_t * locals);
|
||||
|
||||
memfun_args_functor_t(const string& _name, T * _ptr,
|
||||
void (T::*_mptr)(value_t& result, scope_t * locals))
|
||||
: functor_t(_name, true), ptr(_ptr), mptr(_mptr) {}
|
||||
|
||||
virtual void operator()(value_t& result, scope_t * locals) {
|
||||
assert(ptr);
|
||||
assert(mptr);
|
||||
(ptr->*mptr)(result, locals);
|
||||
}
|
||||
};
|
||||
|
||||
static op_t * wrap_value(const value_t& val);
|
||||
static op_t * wrap_sequence(const value_t::sequence_t& val);
|
||||
static op_t * wrap_functor(functor_t * fobj);
|
||||
#if 0
|
||||
static op_t * wrap_mask(const string& pattern);
|
||||
#endif
|
||||
|
||||
template <typename T, typename U>
|
||||
static op_t *
|
||||
make_functor(const string& name, T * ptr, U T::*mptr) {
|
||||
return wrap_functor(new member_functor_t<T, U>(name, ptr, mptr));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static op_t *
|
||||
make_functor(const string& fname, T * ptr,
|
||||
void (T::*mptr)(value_t& result)) {
|
||||
return wrap_functor(new memfun_functor_t<T>(fname, ptr, mptr));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static op_t *
|
||||
make_functor(const string& fname, T * ptr,
|
||||
void (T::*mptr)(value_t& result, scope_t * locals)) {
|
||||
return wrap_functor(new memfun_args_functor_t<T>(fname, ptr, mptr));
|
||||
}
|
||||
|
||||
#define MAKE_FUNCTOR(cls, name) \
|
||||
xml::xpath_t::make_functor(#name, this, &cls::name)
|
||||
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:
|
||||
class scope_t
|
||||
class scope_t : public noncopyable
|
||||
{
|
||||
typedef std::map<const string, op_t *> symbol_map;
|
||||
|
||||
typedef std::map<const string, ptr_op_t> symbol_map;
|
||||
symbol_map symbols;
|
||||
|
||||
scope_t(const scope_t&);
|
||||
scope_t& operator=(const scope_t&);
|
||||
|
||||
public:
|
||||
scope_t * parent;
|
||||
value_t args;
|
||||
|
|
@ -201,23 +81,19 @@ public:
|
|||
|
||||
virtual ~scope_t() {
|
||||
TRACE_DTOR(xpath_t::scope_t);
|
||||
for (symbol_map::iterator i = symbols.begin();
|
||||
i != symbols.end();
|
||||
i++)
|
||||
(*i).second->release();
|
||||
}
|
||||
|
||||
public:
|
||||
virtual void define(const string& name, op_t * def);
|
||||
virtual void define(const string& name, ptr_op_t def);
|
||||
virtual bool resolve(const string& name, value_t& result,
|
||||
scope_t * locals = NULL) {
|
||||
if (parent)
|
||||
return parent->resolve(name, result, locals);
|
||||
return false;
|
||||
}
|
||||
virtual op_t * lookup(const string& name);
|
||||
virtual ptr_op_t lookup(const string& name);
|
||||
|
||||
void define(const string& name, functor_t * def);
|
||||
void define(const string& name, const function_t& def);
|
||||
|
||||
friend struct op_t;
|
||||
};
|
||||
|
|
@ -225,15 +101,17 @@ public:
|
|||
class function_scope_t : public scope_t
|
||||
{
|
||||
value_t::sequence_t sequence;
|
||||
value_t * value;
|
||||
value_t value;
|
||||
int index;
|
||||
|
||||
public:
|
||||
function_scope_t(const value_t::sequence_t& _sequence,
|
||||
value_t * _value, int _index, scope_t * _parent = NULL)
|
||||
value_t * _value, int _index,
|
||||
scope_t * _parent = NULL)
|
||||
: scope_t(_parent, STATIC),
|
||||
sequence(_sequence), value(_value), index(_index) {}
|
||||
function_scope_t(value_t * _value, int _index, scope_t * _parent = NULL)
|
||||
function_scope_t(const value_t& _value, int _index,
|
||||
scope_t * _parent = NULL)
|
||||
: scope_t(_parent, STATIC), value(_value), index(_index) {}
|
||||
|
||||
virtual bool resolve(const string& name, value_t& result,
|
||||
|
|
@ -245,10 +123,9 @@ public:
|
|||
#define XPATH_PARSE_RELAXED 0x02
|
||||
#define XPATH_PARSE_NO_MIGRATE 0x04
|
||||
#define XPATH_PARSE_NO_REDUCE 0x08
|
||||
#if 0
|
||||
#define XPATH_PARSE_REGEXP 0x10
|
||||
#endif
|
||||
#define XPATH_PARSE_ALLOW_DATE 0x20
|
||||
#define XPATH_PARSE_ALLOW_DATE 0x10
|
||||
|
||||
typedef uint_least8_t flags_t;
|
||||
|
||||
private:
|
||||
struct token_t
|
||||
|
|
@ -256,10 +133,6 @@ private:
|
|||
enum kind_t {
|
||||
IDENT, // [A-Za-z_][-A-Za-z0-9_:]*
|
||||
VALUE, // any kind of literal value
|
||||
#if 0
|
||||
REGEXP, // /regexp/ jww (2006-09-24): deprecate
|
||||
// in favor of a "match" function
|
||||
#endif
|
||||
AT_SYM, // @
|
||||
DOLLAR, // $
|
||||
DOT, // .
|
||||
|
|
@ -286,11 +159,6 @@ private:
|
|||
QUESTION, // ?
|
||||
COLON, // :
|
||||
COMMA, // ,
|
||||
#if 0
|
||||
MATCH, // =~
|
||||
NMATCH, // !~
|
||||
PERCENT, // %
|
||||
#endif
|
||||
KW_AND,
|
||||
KW_OR,
|
||||
KW_DIV,
|
||||
|
|
@ -336,34 +204,33 @@ private:
|
|||
}
|
||||
|
||||
void parse_ident(std::istream& in);
|
||||
void next(std::istream& in, unsigned short flags);
|
||||
void rewind(std::istream& in);
|
||||
void unexpected();
|
||||
|
||||
void next(std::istream& in, flags_t flags);
|
||||
void rewind(std::istream& in);
|
||||
|
||||
void unexpected();
|
||||
static void unexpected(char c, char wanted = '\0');
|
||||
};
|
||||
|
||||
public:
|
||||
struct op_t
|
||||
struct op_t : public noncopyable
|
||||
{
|
||||
enum kind_t {
|
||||
VOID,
|
||||
VALUE,
|
||||
|
||||
NODE_NAME,
|
||||
NODE_ID,
|
||||
FUNC_NAME,
|
||||
NODE_NAME,
|
||||
ATTR_ID,
|
||||
ATTR_NAME,
|
||||
FUNC_NAME,
|
||||
VAR_NAME,
|
||||
|
||||
ARG_INDEX,
|
||||
|
||||
CONSTANTS, // constants end here
|
||||
|
||||
FUNCTOR,
|
||||
#if 0
|
||||
MASK,
|
||||
#endif
|
||||
FUNCTION,
|
||||
|
||||
TERMINALS, // terminals end here
|
||||
|
||||
|
|
@ -392,19 +259,10 @@ public:
|
|||
|
||||
O_COMMA,
|
||||
|
||||
#if 0
|
||||
O_MATCH,
|
||||
O_NMATCH,
|
||||
#endif
|
||||
|
||||
O_DEFINE,
|
||||
O_EVAL,
|
||||
O_ARG,
|
||||
|
||||
#if 0
|
||||
O_PERC,
|
||||
#endif
|
||||
|
||||
O_FIND,
|
||||
O_RFIND,
|
||||
O_PRED,
|
||||
|
|
@ -414,53 +272,96 @@ public:
|
|||
|
||||
kind_t kind;
|
||||
mutable short refc;
|
||||
op_t * left;
|
||||
ptr_op_t left_;
|
||||
|
||||
#if 0
|
||||
optional<variant<value_t,
|
||||
string,
|
||||
unsigned int,
|
||||
functor_t,
|
||||
mask_t,
|
||||
op_t> > data;
|
||||
#else
|
||||
union {
|
||||
value_t * valuep; // used by constant VALUE
|
||||
string * name; // used by constant SYMBOL
|
||||
unsigned int arg_index; // used by ARG_INDEX and O_ARG
|
||||
functor_t * functor; // used by terminal FUNCTOR
|
||||
node_t::nameid_t name_id; // used by NODE_NAME and ATTR_NAME
|
||||
#if 0
|
||||
mask_t * mask; // used by terminal MASK
|
||||
#endif
|
||||
op_t * right; // used by all operators
|
||||
};
|
||||
#endif
|
||||
variant<unsigned int, // used by ARG_INDEX and O_ARG
|
||||
shared_ptr<value_t>, // used by constant VALUE
|
||||
string, // used by constant SYMBOL
|
||||
function_t, // used by terminal FUNCTION
|
||||
node_t::nameid_t, // used by NODE_NAME and ATTR_NAME
|
||||
ptr_op_t> // used by all binary operators
|
||||
data;
|
||||
|
||||
op_t(const kind_t _kind)
|
||||
: kind(_kind), refc(0), left(NULL), right(NULL) {
|
||||
op_t(const kind_t _kind) : kind(_kind), refc(0){
|
||||
TRACE_CTOR(xpath_t::op_t, "const kind_t");
|
||||
}
|
||||
op_t(const op_t&);
|
||||
~op_t();
|
||||
~op_t() {
|
||||
TRACE_DTOR(xpath_t::op_t);
|
||||
|
||||
DEBUG("ledger.xpath.memory", "Destroying " << this);
|
||||
assert(refc == 0);
|
||||
}
|
||||
|
||||
op_t& operator=(const op_t&);
|
||||
|
||||
bool constant() const {
|
||||
bool is_value() const {
|
||||
return kind == VALUE;
|
||||
}
|
||||
void get_value(value_t& result) const;
|
||||
value_t value() const {
|
||||
value_t temp;
|
||||
get_value(temp);
|
||||
return temp;
|
||||
|
||||
unsigned int& as_long() {
|
||||
assert(kind == ARG_INDEX || kind == O_ARG);
|
||||
return boost::get<unsigned int>(data);
|
||||
}
|
||||
const unsigned int& as_long() const {
|
||||
return const_cast<op_t *>(this)->as_long();
|
||||
}
|
||||
void set_long(unsigned int val) {
|
||||
data = val;
|
||||
}
|
||||
|
||||
functor_t * functor_obj() const {
|
||||
if (kind == FUNCTOR)
|
||||
return functor;
|
||||
else
|
||||
return NULL;
|
||||
value_t& as_value() {
|
||||
assert(kind == VALUE);
|
||||
value_t * val = boost::get<scoped_ptr<value_t> >(data).get();
|
||||
assert(val);
|
||||
return *val;
|
||||
}
|
||||
const value_t& as_value() const {
|
||||
return const_cast<op_t *>(this)->as_value();
|
||||
}
|
||||
void set_value(value_t * val) {
|
||||
// jww (2007-05-14): Ugh, fix this
|
||||
data = shared_ptr<value_t>(val);
|
||||
}
|
||||
|
||||
string& as_string() {
|
||||
assert(kind == NODE_NAME || kind == ATTR_NAME || kind == FUNC_NAME);
|
||||
return boost::get<string>(data);
|
||||
}
|
||||
const string& as_string() const {
|
||||
return const_cast<op_t *>(this)->as_string();
|
||||
}
|
||||
void set_string(const string& val) {
|
||||
data = val;
|
||||
}
|
||||
|
||||
function_t& as_function() {
|
||||
assert(kind == FUNCTION);
|
||||
return boost::get<function_t>(data);
|
||||
}
|
||||
const function_t& as_function() const {
|
||||
return const_cast<op_t *>(this)->as_function();
|
||||
}
|
||||
void set_function(const function_t& val) {
|
||||
data = val;
|
||||
}
|
||||
|
||||
node_t::nameid_t& as_name() {
|
||||
assert(kind == NODE_ID || kind == ATTR_ID);
|
||||
return boost::get<node_t::nameid_t>(data);
|
||||
}
|
||||
const node_t::nameid_t& as_name() const {
|
||||
return const_cast<op_t *>(this)->as_name();
|
||||
}
|
||||
void set_name(const node_t::nameid_t& val) {
|
||||
data = val;
|
||||
}
|
||||
|
||||
ptr_op_t& as_op() {
|
||||
assert(kind > TERMINALS);
|
||||
return boost::get<ptr_op_t>(data);
|
||||
}
|
||||
const ptr_op_t& as_op() const {
|
||||
return const_cast<op_t *>(this)->as_op();
|
||||
}
|
||||
|
||||
void release() const {
|
||||
|
|
@ -470,54 +371,55 @@ public:
|
|||
if (--refc == 0)
|
||||
checked_delete(this);
|
||||
}
|
||||
op_t * acquire() {
|
||||
void acquire() {
|
||||
DEBUG("ledger.xpath.memory",
|
||||
"Acquiring " << this << ", refc now " << refc + 1);
|
||||
assert(refc >= 0);
|
||||
refc++;
|
||||
return this;
|
||||
}
|
||||
const op_t * acquire() const {
|
||||
DEBUG("ledger.xpath.memory",
|
||||
"Acquiring " << this << ", refc now " << refc + 1);
|
||||
assert(refc >= 0);
|
||||
refc++;
|
||||
return this;
|
||||
}
|
||||
|
||||
void set_left(op_t * expr) {
|
||||
ptr_op_t& left() {
|
||||
return left_;
|
||||
}
|
||||
const ptr_op_t& left() const {
|
||||
assert(kind > TERMINALS);
|
||||
if (left)
|
||||
left->release();
|
||||
left = expr ? expr->acquire() : NULL;
|
||||
return left_;
|
||||
}
|
||||
|
||||
void set_right(op_t * expr) {
|
||||
void set_left(const ptr_op_t& expr) {
|
||||
assert(kind > TERMINALS);
|
||||
if (right)
|
||||
right->release();
|
||||
right = expr ? expr->acquire() : NULL;
|
||||
left_ = expr;
|
||||
}
|
||||
|
||||
static op_t * new_node(kind_t kind, op_t * left = NULL,
|
||||
op_t * right = NULL);
|
||||
ptr_op_t& right() {
|
||||
assert(kind > TERMINALS);
|
||||
return as_op();
|
||||
}
|
||||
const ptr_op_t& right() const {
|
||||
assert(kind > TERMINALS);
|
||||
return as_op();
|
||||
}
|
||||
void set_right(const ptr_op_t& expr) {
|
||||
assert(kind > TERMINALS);
|
||||
data = expr;
|
||||
}
|
||||
|
||||
op_t * copy(op_t * left = NULL,
|
||||
op_t * right = NULL) const;
|
||||
op_t * compile(value_t * context, scope_t * scope,
|
||||
bool resolve = false);
|
||||
static ptr_op_t new_node(kind_t kind, ptr_op_t left = NULL,
|
||||
ptr_op_t right = NULL);
|
||||
|
||||
void find_values(value_t * context, scope_t * scope,
|
||||
ptr_op_t copy(ptr_op_t left = NULL, ptr_op_t right = NULL) const;
|
||||
ptr_op_t compile(value_t& context, scope_t * scope, bool resolve = false);
|
||||
|
||||
void find_values(value_t& context, scope_t * scope,
|
||||
value_t::sequence_t& result_seq, bool recursive);
|
||||
bool test_value(value_t * context, scope_t * scope, int index = 0);
|
||||
bool test_value(value_t& context, scope_t * scope, int index = 0);
|
||||
|
||||
void append_value(value_t& value, value_t::sequence_t& result_seq);
|
||||
|
||||
static op_t * defer_sequence(value_t::sequence_t& result_seq);
|
||||
static ptr_op_t defer_sequence(value_t::sequence_t& result_seq);
|
||||
|
||||
bool print(std::ostream& out,
|
||||
const bool relaxed = true,
|
||||
const op_t * op_to_find = NULL,
|
||||
const ptr_op_t& op_to_find = NULL,
|
||||
unsigned long * start_pos = NULL,
|
||||
unsigned long * end_pos = NULL) const;
|
||||
|
||||
|
|
@ -525,44 +427,14 @@ public:
|
|||
};
|
||||
|
||||
public:
|
||||
op_t * ptr;
|
||||
ptr_op_t ptr;
|
||||
|
||||
xpath_t& operator=(op_t * _expr) {
|
||||
xpath_t& operator=(ptr_op_t _expr) {
|
||||
expr = "";
|
||||
reset(_expr);
|
||||
ptr = _expr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
op_t& operator*() throw() {
|
||||
return *ptr;
|
||||
}
|
||||
const op_t& operator*() const throw() {
|
||||
return *ptr;
|
||||
}
|
||||
op_t * operator->() throw() {
|
||||
return ptr;
|
||||
}
|
||||
const op_t * operator->() const throw() {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
op_t * get() throw() { return ptr; }
|
||||
const op_t * get() const throw() { return ptr; }
|
||||
|
||||
op_t * release() throw() {
|
||||
op_t * tmp = ptr;
|
||||
ptr = 0;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void reset(op_t * p = 0) throw() {
|
||||
if (p != ptr) {
|
||||
if (ptr)
|
||||
ptr->release();
|
||||
ptr = p;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef THREADSAFE
|
||||
mutable token_t lookahead;
|
||||
#else
|
||||
|
|
@ -570,7 +442,7 @@ public:
|
|||
#endif
|
||||
mutable bool use_lookahead;
|
||||
|
||||
token_t& next_token(std::istream& in, unsigned short tflags) const {
|
||||
token_t& next_token(std::istream& in, flags_t tflags) const {
|
||||
if (use_lookahead)
|
||||
use_lookahead = false;
|
||||
else
|
||||
|
|
@ -597,24 +469,24 @@ public:
|
|||
use_lookahead = true;
|
||||
}
|
||||
|
||||
op_t * parse_value_term(std::istream& in, unsigned short flags) const;
|
||||
op_t * parse_predicate_expr(std::istream& in, unsigned short flags) const;
|
||||
op_t * parse_path_expr(std::istream& in, unsigned short flags) const;
|
||||
op_t * parse_unary_expr(std::istream& in, unsigned short flags) const;
|
||||
op_t * parse_union_expr(std::istream& in, unsigned short flags) const;
|
||||
op_t * parse_mul_expr(std::istream& in, unsigned short flags) const;
|
||||
op_t * parse_add_expr(std::istream& in, unsigned short flags) const;
|
||||
op_t * parse_logic_expr(std::istream& in, unsigned short flags) const;
|
||||
op_t * parse_and_expr(std::istream& in, unsigned short flags) const;
|
||||
op_t * parse_or_expr(std::istream& in, unsigned short flags) const;
|
||||
op_t * parse_querycolon_expr(std::istream& in, unsigned short flags) const;
|
||||
op_t * parse_value_expr(std::istream& in, unsigned short flags) const;
|
||||
ptr_op_t parse_value_term(std::istream& in, flags_t flags) const;
|
||||
ptr_op_t parse_predicate_expr(std::istream& in, flags_t flags) const;
|
||||
ptr_op_t parse_path_expr(std::istream& in, flags_t flags) const;
|
||||
ptr_op_t parse_unary_expr(std::istream& in, flags_t flags) const;
|
||||
ptr_op_t parse_union_expr(std::istream& in, flags_t flags) const;
|
||||
ptr_op_t parse_mul_expr(std::istream& in, flags_t flags) const;
|
||||
ptr_op_t parse_add_expr(std::istream& in, flags_t flags) const;
|
||||
ptr_op_t parse_logic_expr(std::istream& in, flags_t flags) const;
|
||||
ptr_op_t parse_and_expr(std::istream& in, flags_t flags) const;
|
||||
ptr_op_t parse_or_expr(std::istream& in, flags_t flags) const;
|
||||
ptr_op_t parse_querycolon_expr(std::istream& in, flags_t flags) const;
|
||||
ptr_op_t parse_value_expr(std::istream& in, flags_t flags) const;
|
||||
|
||||
op_t * parse_expr(std::istream& in,
|
||||
unsigned short flags = XPATH_PARSE_RELAXED) const;
|
||||
ptr_op_t parse_expr(std::istream& in,
|
||||
flags_t flags = XPATH_PARSE_RELAXED) const;
|
||||
|
||||
op_t * parse_expr(const string& str,
|
||||
unsigned short tflags = XPATH_PARSE_RELAXED) const
|
||||
ptr_op_t parse_expr(const string& str,
|
||||
flags_t tflags = XPATH_PARSE_RELAXED) const
|
||||
{
|
||||
std::istringstream stream(str);
|
||||
#if 0
|
||||
|
|
@ -632,14 +504,14 @@ public:
|
|||
#endif
|
||||
}
|
||||
|
||||
op_t * parse_expr(const char * p,
|
||||
unsigned short tflags = XPATH_PARSE_RELAXED) const {
|
||||
ptr_op_t parse_expr(const char * p,
|
||||
flags_t tflags = XPATH_PARSE_RELAXED) const {
|
||||
return parse_expr(string(p), tflags);
|
||||
}
|
||||
|
||||
bool print(std::ostream& out,
|
||||
const bool relaxed,
|
||||
const op_t * op_to_find,
|
||||
const ptr_op_t op_to_find,
|
||||
unsigned long * start_pos,
|
||||
unsigned long * end_pos) const {
|
||||
if (ptr)
|
||||
|
|
@ -648,36 +520,34 @@ public:
|
|||
}
|
||||
|
||||
public:
|
||||
string expr;
|
||||
unsigned short flags; // flags used to parse `expr'
|
||||
string expr;
|
||||
flags_t flags; // flags used to parse `expr'
|
||||
|
||||
xpath_t() : ptr(NULL), use_lookahead(false), flags(0) {
|
||||
TRACE_CTOR(xpath_t, "");
|
||||
}
|
||||
xpath_t(op_t * _ptr) : ptr(_ptr), use_lookahead(false) {
|
||||
TRACE_CTOR(xpath_t, "op_t *");
|
||||
xpath_t(ptr_op_t _ptr) : ptr(_ptr), use_lookahead(false) {
|
||||
TRACE_CTOR(xpath_t, "ptr_op_t");
|
||||
}
|
||||
|
||||
xpath_t(const string& _expr,
|
||||
unsigned short _flags = XPATH_PARSE_RELAXED)
|
||||
xpath_t(const string& _expr, flags_t _flags = XPATH_PARSE_RELAXED)
|
||||
: ptr(NULL), use_lookahead(false), flags(0) {
|
||||
TRACE_CTOR(xpath_t, "const string&, unsigned short");
|
||||
TRACE_CTOR(xpath_t, "const string&, flags_t");
|
||||
if (! _expr.empty())
|
||||
parse(_expr, _flags);
|
||||
}
|
||||
xpath_t(std::istream& in, unsigned short _flags = XPATH_PARSE_RELAXED)
|
||||
xpath_t(std::istream& in, flags_t _flags = XPATH_PARSE_RELAXED)
|
||||
: ptr(NULL), use_lookahead(false), flags(0) {
|
||||
TRACE_CTOR(xpath_t, "std::istream&, unsigned short");
|
||||
TRACE_CTOR(xpath_t, "std::istream&, flags_t");
|
||||
parse(in, _flags);
|
||||
}
|
||||
xpath_t(const xpath_t& other)
|
||||
: ptr(other.ptr ? other.ptr->acquire() : NULL),
|
||||
use_lookahead(false), expr(other.expr), flags(other.flags) {
|
||||
: ptr(other.ptr), use_lookahead(false),
|
||||
expr(other.expr), flags(other.flags) {
|
||||
TRACE_CTOR(xpath_t, "copy");
|
||||
}
|
||||
virtual ~xpath_t() {
|
||||
TRACE_DTOR(xpath_t);
|
||||
reset(NULL);
|
||||
}
|
||||
|
||||
xpath_t& operator=(const string& _expr) {
|
||||
|
|
@ -686,14 +556,14 @@ public:
|
|||
}
|
||||
xpath_t& operator=(const xpath_t& _expr);
|
||||
xpath_t& operator=(xpath_t& _xpath) {
|
||||
ptr = _xpath.ptr->acquire();
|
||||
ptr = _xpath.ptr;
|
||||
expr = _xpath.expr;
|
||||
flags = _xpath.flags;
|
||||
use_lookahead = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator op_t *() throw() {
|
||||
operator ptr_op_t() throw() {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
|
@ -704,29 +574,21 @@ public:
|
|||
return expr;
|
||||
}
|
||||
|
||||
void parse(const string& _expr, unsigned short _flags = XPATH_PARSE_RELAXED) {
|
||||
void parse(const string& _expr, flags_t _flags = XPATH_PARSE_RELAXED) {
|
||||
expr = _expr;
|
||||
flags = _flags;
|
||||
op_t * tmp = parse_expr(_expr, _flags);
|
||||
assert(tmp);
|
||||
reset(tmp ? tmp->acquire() : NULL);
|
||||
ptr = parse_expr(_expr, _flags);
|
||||
}
|
||||
void parse(std::istream& in, unsigned short _flags = XPATH_PARSE_RELAXED) {
|
||||
void parse(std::istream& in, flags_t _flags = XPATH_PARSE_RELAXED) {
|
||||
expr = "";
|
||||
flags = _flags;
|
||||
op_t * tmp = parse_expr(in, _flags);
|
||||
assert(tmp);
|
||||
reset(tmp ? tmp->acquire() : NULL);
|
||||
ptr = parse_expr(in, _flags);
|
||||
}
|
||||
|
||||
void compile(node_t& top_node, scope_t * scope = NULL) {
|
||||
if (ptr) {
|
||||
if (ptr.get()) {
|
||||
value_t noderef(&top_node);
|
||||
op_t * compiled = ptr->compile(&noderef, scope);
|
||||
if (compiled == ptr)
|
||||
compiled->release();
|
||||
else
|
||||
reset(compiled);
|
||||
ptr = ptr->compile(noderef, scope);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -767,6 +629,13 @@ inline std::ostream& operator<<(std::ostream& out, const xpath_t::op_t& op) {
|
|||
return out;
|
||||
}
|
||||
|
||||
inline void intrusive_ptr_add_ref(xpath_t::op_t * op) {
|
||||
op->acquire();
|
||||
}
|
||||
inline void intrusive_ptr_release(xpath_t::op_t * op) {
|
||||
op->release();
|
||||
}
|
||||
|
||||
} // namespace xml
|
||||
|
||||
template <typename T>
|
||||
|
|
@ -777,15 +646,20 @@ inline T * get_ptr(xml::xpath_t::scope_t * locals, unsigned int idx) {
|
|||
return ptr;
|
||||
}
|
||||
|
||||
class xml_command : public xml::xpath_t::functor_t
|
||||
template <typename T>
|
||||
inline T * get_node_ptr(xml::xpath_t::scope_t * locals, unsigned int idx) {
|
||||
assert(locals->args.size() > idx);
|
||||
T * ptr = polymorphic_downcast<T *>(locals->args[idx].as_xml_node());
|
||||
assert(ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
class xml_command
|
||||
{
|
||||
public:
|
||||
xml_command() : xml::xpath_t::functor_t("xml") {}
|
||||
|
||||
virtual void operator()(value_t&, xml::xpath_t::scope_t * locals) {
|
||||
void operator()(value_t&, xml::xpath_t::scope_t * locals) {
|
||||
std::ostream * out = get_ptr<std::ostream>(locals, 0);
|
||||
xml::document_t * doc = get_ptr<xml::document_t>(locals, 1);
|
||||
|
||||
xml::document_t * doc = get_node_ptr<xml::document_t>(locals, 1);
|
||||
doc->print(*out);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue