Changed xpath to use intrusive_ptr; got the xml command working

This commit is contained in:
John Wiegley 2007-05-14 11:09:54 +00:00
parent 65af168838
commit f83705b847
21 changed files with 920 additions and 1386 deletions

View file

@ -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 \

View file

@ -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.

View file

@ -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;

View file

@ -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

View file

@ -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()));

View file

@ -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

View file

@ -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);
}
}
}

View file

@ -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);

View file

@ -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() <<*/ "'");
}
}

View file

@ -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 {

View file

@ -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;
}
}

View file

@ -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,

View file

@ -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;
}
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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);
}
};