2007-07-19 19:01:42 +02:00
|
|
|
#ifndef ARABICA_XSLT_EXECUTION_CONTEXT_HPP
|
|
|
|
#define ARABICA_XSLT_EXECUTION_CONTEXT_HPP
|
|
|
|
|
|
|
|
#include <ostream>
|
|
|
|
#include "xslt_sink.hpp"
|
|
|
|
#include "xslt_variable_stack.hpp"
|
|
|
|
|
|
|
|
namespace Arabica
|
|
|
|
{
|
|
|
|
namespace XSLT
|
|
|
|
{
|
|
|
|
|
2012-11-06 21:03:15 +01:00
|
|
|
template<class string_type, class string_adaptor> class CompiledStylesheet;
|
2007-07-19 19:01:42 +02:00
|
|
|
class ExecutionContext;
|
|
|
|
|
2012-11-06 21:25:10 +01:00
|
|
|
template<class string_type, class string_adaptor>
|
2007-07-19 19:01:42 +02:00
|
|
|
class Variable_declaration
|
|
|
|
{
|
|
|
|
protected:
|
|
|
|
Variable_declaration() { }
|
|
|
|
|
|
|
|
public:
|
2012-11-06 21:25:10 +01:00
|
|
|
virtual const string_type& name() const = 0;
|
|
|
|
virtual Arabica::XPath::XPathValue<string_type> value(const DOM::Node<string_type, string_adaptor>& node,
|
2009-12-15 00:55:56 +01:00
|
|
|
ExecutionContext& context,
|
2012-11-06 21:25:10 +01:00
|
|
|
DOMSink<string_type, string_adaptor>& sink) const = 0;
|
2008-11-19 18:26:07 +01:00
|
|
|
virtual const Precedence& precedence() const = 0;
|
2007-07-19 19:01:42 +02:00
|
|
|
|
|
|
|
private:
|
|
|
|
Variable_declaration(const Variable_declaration&);
|
|
|
|
Variable_declaration& operator=(const Variable_declaration&);
|
|
|
|
bool operator==(const Variable_declaration&) const;
|
|
|
|
}; // class Variable_declaration
|
|
|
|
|
|
|
|
class ExecutionContext
|
|
|
|
{
|
|
|
|
public:
|
2012-11-06 21:03:15 +01:00
|
|
|
ExecutionContext(const CompiledStylesheet<std::string, Arabica::default_string_adaptor<std::string> >& stylesheet,
|
2012-11-06 20:29:22 +01:00
|
|
|
Sink<std::string>& output,
|
2007-07-19 19:01:42 +02:00
|
|
|
std::ostream& error_output) :
|
|
|
|
stylesheet_(stylesheet),
|
2009-12-15 00:55:56 +01:00
|
|
|
sink_(output.asOutput()),
|
2007-07-19 19:01:42 +02:00
|
|
|
message_sink_(error_output),
|
2007-11-11 22:31:10 +01:00
|
|
|
to_msg_(0)
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
|
|
|
xpathContext_.setVariableResolver(stack_);
|
2009-12-15 00:55:56 +01:00
|
|
|
sink_.set_warning_sink(message_sink_.asOutput());
|
2008-10-21 23:53:00 +02:00
|
|
|
message_sink_.asOutput().set_warning_sink(message_sink_.asOutput());
|
2007-07-19 19:01:42 +02:00
|
|
|
} // ExecutionContext
|
|
|
|
|
2012-11-06 20:29:22 +01:00
|
|
|
ExecutionContext(Sink<std::string>& output,
|
2009-12-15 00:55:56 +01:00
|
|
|
ExecutionContext& rhs) :
|
2007-07-19 19:01:42 +02:00
|
|
|
stylesheet_(rhs.stylesheet_),
|
|
|
|
stack_(rhs.stack_),
|
2009-12-15 00:55:56 +01:00
|
|
|
sink_(output.asOutput()),
|
2007-07-19 19:01:42 +02:00
|
|
|
message_sink_(rhs.message_sink_),
|
|
|
|
to_msg_(false)
|
|
|
|
{
|
|
|
|
xpathContext_.setVariableResolver(stack_);
|
|
|
|
xpathContext_.setCurrentNode(rhs.xpathContext().currentNode());
|
|
|
|
xpathContext_.setPosition(rhs.xpathContext().position());
|
|
|
|
xpathContext_.setLast(rhs.xpathContext().last());
|
|
|
|
} // ExecutionContext
|
|
|
|
|
2012-11-06 21:03:15 +01:00
|
|
|
const CompiledStylesheet<std::string, Arabica::default_string_adaptor<std::string> >& stylesheet() const { return stylesheet_; }
|
2007-07-19 19:01:42 +02:00
|
|
|
|
2012-11-06 20:29:22 +01:00
|
|
|
Output<std::string, Arabica::default_string_adaptor<std::string> >& sink()
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
2009-12-15 00:55:56 +01:00
|
|
|
return !to_msg_ ? sink_ : message_sink_.asOutput();
|
2007-07-19 19:01:42 +02:00
|
|
|
} // sink
|
2007-11-11 22:31:10 +01:00
|
|
|
void redirectToMessageSink() { ++to_msg_; }
|
|
|
|
void revertFromMessageSink() { --to_msg_; }
|
2007-07-19 19:01:42 +02:00
|
|
|
|
|
|
|
const Arabica::XPath::ExecutionContext<std::string>& xpathContext() const { return xpathContext_; }
|
|
|
|
|
2012-11-06 21:25:10 +01:00
|
|
|
void topLevelParam(const DOM::Node<std::string>& node, const Variable_declaration<std::string, Arabica::default_string_adaptor<std::string> >& param);
|
|
|
|
std::string passParam(const DOM::Node<std::string>& node, const Variable_declaration<std::string, Arabica::default_string_adaptor<std::string> >& param);
|
2007-10-27 01:21:21 +02:00
|
|
|
void unpassParam(const std::string& name);
|
2012-11-06 21:25:10 +01:00
|
|
|
void declareParam(const DOM::Node<std::string>& node, const Variable_declaration<std::string, Arabica::default_string_adaptor<std::string> >& param);
|
|
|
|
void declareVariable(const DOM::Node<std::string>& node, const Variable_declaration<std::string, Arabica::default_string_adaptor<std::string> >& variable);
|
2007-07-19 19:01:42 +02:00
|
|
|
void freezeTopLevel();
|
2012-11-06 21:44:52 +01:00
|
|
|
void injectGlobalScope(const ScopeType<std::string, Arabica::default_string_adaptor<std::string> >::Scope& scope);
|
2007-07-19 19:01:42 +02:00
|
|
|
|
|
|
|
void setPosition(const DOM::Node<std::string>& current, size_t pos) { setPosition(current, static_cast<int>(pos)); }
|
|
|
|
void setPosition(const DOM::Node<std::string>& current, int pos)
|
|
|
|
{
|
|
|
|
xpathContext_.setCurrentNode(current);
|
|
|
|
xpathContext_.setPosition(pos);
|
|
|
|
} // setPosition
|
|
|
|
|
|
|
|
int setLast(int last)
|
|
|
|
{
|
|
|
|
int old = xpathContext_.last();
|
|
|
|
xpathContext_.setLast(last);
|
|
|
|
return old;
|
|
|
|
} // setLast
|
|
|
|
|
|
|
|
private:
|
|
|
|
void pushStackFrame() { stack_.pushScope(); }
|
2007-11-01 23:28:20 +01:00
|
|
|
void chainStackFrame() { stack_.chainScope(); }
|
2007-07-19 19:01:42 +02:00
|
|
|
void popStackFrame() { stack_.popScope(); }
|
|
|
|
|
|
|
|
private:
|
2012-11-06 21:03:15 +01:00
|
|
|
const CompiledStylesheet<std::string, Arabica::default_string_adaptor<std::string> >& stylesheet_;
|
2012-11-06 21:44:52 +01:00
|
|
|
VariableStack<std::string, Arabica::default_string_adaptor<std::string> > stack_;
|
2007-07-19 19:01:42 +02:00
|
|
|
Arabica::XPath::ExecutionContext<std::string> xpathContext_;
|
2012-11-06 20:29:22 +01:00
|
|
|
Output<std::string, Arabica::default_string_adaptor<std::string> >& sink_;
|
|
|
|
StreamSink<std::string> message_sink_;
|
2007-11-11 22:31:10 +01:00
|
|
|
int to_msg_;
|
2007-07-19 19:01:42 +02:00
|
|
|
|
|
|
|
friend class StackFrame;
|
2007-11-01 23:28:20 +01:00
|
|
|
friend class ChainStackFrame;
|
2007-07-19 19:01:42 +02:00
|
|
|
}; // class ExecutionContext
|
|
|
|
|
|
|
|
///////////////////////////
|
2012-11-06 21:49:14 +01:00
|
|
|
template<class string_type, class string_adaptor>
|
2012-11-06 21:44:52 +01:00
|
|
|
class VariableClosure : public Variable_instance<std::string, Arabica::default_string_adaptor<std::string> >
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
|
|
|
public:
|
2012-11-06 21:49:14 +01:00
|
|
|
typedef typename ScopeType<string_type, string_adaptor>::Variable_instance_ptr Variable_instance_ptr;
|
2012-11-06 21:44:52 +01:00
|
|
|
|
2012-11-06 21:49:14 +01:00
|
|
|
static Variable_instance_ptr create(const Variable_declaration<string_type, string_adaptor>& var,
|
|
|
|
const DOM::Node<string_type, string_adaptor>& node,
|
2008-08-05 19:29:18 +02:00
|
|
|
ExecutionContext& context)
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
|
|
|
return Variable_instance_ptr(new VariableClosure(var, node, context));
|
|
|
|
} // create
|
|
|
|
|
|
|
|
virtual const std::string& name() const { return var_.name(); }
|
2008-11-19 18:26:07 +01:00
|
|
|
virtual const Precedence& precedence() const { return var_.precedence(); }
|
2007-07-19 19:01:42 +02:00
|
|
|
|
2012-11-06 21:49:14 +01:00
|
|
|
virtual Arabica::XPath::XPathValue<string_type, string_adaptor> value() const
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
|
|
|
if(!value_)
|
2009-12-15 00:55:56 +01:00
|
|
|
value_ = var_.value(node_, context_, sink_);
|
2007-07-19 19:01:42 +02:00
|
|
|
return value_;
|
|
|
|
} // value
|
|
|
|
|
|
|
|
virtual void injectGlobalScope(const Scope& scope) const
|
|
|
|
{
|
|
|
|
context_.injectGlobalScope(scope);
|
|
|
|
} // globalScope
|
|
|
|
|
|
|
|
private:
|
2012-11-06 21:49:14 +01:00
|
|
|
VariableClosure(const Variable_declaration<string_type, string_adaptor>& var,
|
|
|
|
const DOM::Node<string_type, string_adaptor>& node,
|
2007-07-19 19:01:42 +02:00
|
|
|
ExecutionContext& context) :
|
|
|
|
var_(var),
|
2009-12-15 00:55:56 +01:00
|
|
|
sink_(),
|
2007-07-19 19:01:42 +02:00
|
|
|
node_(node),
|
2009-12-15 00:55:56 +01:00
|
|
|
context_(sink_, context)
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
|
|
|
} // VariableClosure
|
|
|
|
|
2012-11-06 21:49:14 +01:00
|
|
|
const Variable_declaration<string_type, string_adaptor>& var_;
|
|
|
|
mutable DOMSink<string_type, string_adaptor> sink_;
|
|
|
|
const DOM::Node<string_type, string_adaptor> node_;
|
2007-07-19 19:01:42 +02:00
|
|
|
mutable ExecutionContext context_;
|
2012-11-06 21:49:14 +01:00
|
|
|
mutable Arabica::XPath::XPathValue<string_type, string_adaptor> value_;
|
2007-07-19 19:01:42 +02:00
|
|
|
|
|
|
|
VariableClosure();
|
|
|
|
VariableClosure(const VariableClosure&);
|
|
|
|
VariableClosure& operator=(const VariableClosure&);
|
|
|
|
const VariableClosure& operator==(const VariableClosure&) const;
|
|
|
|
}; // class VariableClosure
|
|
|
|
|
|
|
|
///////////////////////////
|
2012-11-06 21:25:10 +01:00
|
|
|
void ExecutionContext::topLevelParam(const DOM::Node<std::string>& node, const Variable_declaration<std::string, Arabica::default_string_adaptor<std::string> >& param)
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
2012-11-06 21:49:14 +01:00
|
|
|
stack_.topLevelParam(VariableClosure<std::string, Arabica::default_string_adaptor<std::string> >::create(param, node, *this));
|
2007-10-27 01:21:21 +02:00
|
|
|
} // topLevelParam
|
2007-07-19 19:01:42 +02:00
|
|
|
|
2012-11-06 21:25:10 +01:00
|
|
|
std::string ExecutionContext::passParam(const DOM::Node<std::string>& node, const Variable_declaration<std::string, Arabica::default_string_adaptor<std::string> >& param)
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
2012-11-06 21:49:14 +01:00
|
|
|
return stack_.passParam(VariableClosure<std::string, Arabica::default_string_adaptor<std::string> >::create(param, node, *this));
|
2007-07-19 19:01:42 +02:00
|
|
|
} // passParam
|
|
|
|
|
2007-10-27 01:21:21 +02:00
|
|
|
void ExecutionContext::unpassParam(const std::string& name)
|
|
|
|
{
|
|
|
|
stack_.unpassParam(name);
|
|
|
|
} // unpassParam
|
|
|
|
|
2012-11-06 21:25:10 +01:00
|
|
|
void ExecutionContext::declareParam(const DOM::Node<std::string>& node, const Variable_declaration<std::string, Arabica::default_string_adaptor<std::string> >& param)
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
2009-08-18 22:16:12 +02:00
|
|
|
if(!stack_.findPassedParam(param.name()))
|
2012-11-06 21:49:14 +01:00
|
|
|
stack_.declareParam(VariableClosure<std::string, Arabica::default_string_adaptor<std::string> >::create(param, node, *this));
|
2007-07-19 19:01:42 +02:00
|
|
|
} // declareParam
|
|
|
|
|
2012-11-06 21:25:10 +01:00
|
|
|
void ExecutionContext::declareVariable(const DOM::Node<std::string>& node, const Variable_declaration<std::string, Arabica::default_string_adaptor<std::string> >& variable)
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
2012-11-06 21:49:14 +01:00
|
|
|
stack_.declareVariable(VariableClosure<std::string, Arabica::default_string_adaptor<std::string> >::create(variable, node, *this));
|
2007-07-19 19:01:42 +02:00
|
|
|
} // declareVariable
|
|
|
|
|
|
|
|
void ExecutionContext::freezeTopLevel()
|
|
|
|
{
|
|
|
|
stack_.freezeTopLevel();
|
|
|
|
} // freezeTopLevel
|
|
|
|
|
2012-11-06 21:44:52 +01:00
|
|
|
void ExecutionContext::injectGlobalScope(const ScopeType<std::string, Arabica::default_string_adaptor<std::string> >::Scope& scope)
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
|
|
|
stack_.injectGlobalScope(scope);
|
|
|
|
} // injectGlobalScope
|
|
|
|
|
|
|
|
///////////////////////////
|
|
|
|
class StackFrame
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
StackFrame(ExecutionContext& context) : context_(context) { context_.pushStackFrame(); }
|
|
|
|
~StackFrame() { context_.popStackFrame(); }
|
|
|
|
|
|
|
|
private:
|
|
|
|
ExecutionContext& context_;
|
|
|
|
|
|
|
|
StackFrame(const StackFrame&);
|
|
|
|
StackFrame& operator=(const StackFrame&);
|
|
|
|
bool operator==(const StackFrame&) const;
|
|
|
|
}; // class StackFrame
|
|
|
|
|
2007-11-01 23:28:20 +01:00
|
|
|
class ChainStackFrame
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ChainStackFrame(ExecutionContext& context) : context_(context) { context_.chainStackFrame(); }
|
|
|
|
~ChainStackFrame() { context_.popStackFrame(); }
|
|
|
|
|
|
|
|
private:
|
|
|
|
ExecutionContext& context_;
|
|
|
|
|
|
|
|
ChainStackFrame(const ChainStackFrame&);
|
|
|
|
ChainStackFrame& operator=(const ChainStackFrame&);
|
|
|
|
bool operator==(const ChainStackFrame&) const;
|
|
|
|
}; // class ChainStackFrame
|
|
|
|
|
2007-07-19 19:01:42 +02:00
|
|
|
///////////////////////////
|
|
|
|
class LastFrame
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
LastFrame(ExecutionContext& context, int last) : context_(context)
|
|
|
|
{
|
|
|
|
oldLast_ = context_.setLast(last);
|
|
|
|
} // LastFrame
|
|
|
|
|
|
|
|
LastFrame(ExecutionContext& context, size_t last) : context_(context)
|
|
|
|
{
|
|
|
|
oldLast_ = context_.setLast(static_cast<int>(last));
|
|
|
|
} // LastFrame
|
|
|
|
|
|
|
|
~LastFrame()
|
|
|
|
{
|
|
|
|
context_.setLast(oldLast_);
|
|
|
|
} // ~LastFrame
|
|
|
|
|
|
|
|
private:
|
|
|
|
ExecutionContext& context_;
|
|
|
|
int oldLast_;
|
|
|
|
|
|
|
|
LastFrame(const LastFrame&);
|
|
|
|
LastFrame& operator=(const LastFrame&);
|
|
|
|
bool operator==(const LastFrame&) const;
|
|
|
|
}; // class LastFrame
|
|
|
|
|
|
|
|
} // namespace XSLT
|
|
|
|
} // namespace Arabica
|
|
|
|
|
|
|
|
#endif // ARABICA_XSLT_EXECUTION_CONTEXT_HPP
|
|
|
|
|