arabica/include/XSLT/impl/xslt_execution_context.hpp

280 lines
11 KiB
C++
Raw Normal View History

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;
2012-11-08 18:13:33 +01:00
template<class string_type, class string_adaptor> class ExecutionContext;
2012-11-08 18:19:10 +01:00
template<class string_type, class string_adaptor> class StackFrame;
template<class string_type, class string_adaptor> class ChainStackFrame;
2007-07-19 19:01:42 +02:00
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;
2012-11-21 12:12:35 +01:00
virtual Arabica::XPath::XPathValue<string_type, string_adaptor> value(const DOM::Node<string_type, string_adaptor>& node,
2012-11-08 18:13:33 +01:00
ExecutionContext<string_type, string_adaptor>& context,
2012-11-06 21:25:10 +01:00
DOMSink<string_type, string_adaptor>& sink) const = 0;
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
2012-11-08 18:13:33 +01:00
template<class string_type, class string_adaptor>
2007-07-19 19:01:42 +02:00
class ExecutionContext
{
public:
2012-11-08 18:13:33 +01:00
ExecutionContext(const CompiledStylesheet<string_type, string_adaptor>& stylesheet,
Sink<string_type, string_adaptor>& output,
std::basic_ostream<typename string_adaptor::value_type>& error_output) :
2007-07-19 19:01:42 +02:00
stylesheet_(stylesheet),
sink_(output.asOutput()),
2007-07-19 19:01:42 +02:00
message_sink_(error_output),
to_msg_(0)
2007-07-19 19:01:42 +02:00
{
xpathContext_.setVariableResolver(stack_);
sink_.set_warning_sink(message_sink_.asOutput());
message_sink_.asOutput().set_warning_sink(message_sink_.asOutput());
2007-07-19 19:01:42 +02:00
} // ExecutionContext
2012-11-08 18:13:33 +01:00
ExecutionContext(Sink<string_type, string_adaptor>& output,
ExecutionContext<string_type, string_adaptor>& rhs) :
2007-07-19 19:01:42 +02:00
stylesheet_(rhs.stylesheet_),
stack_(rhs.stack_),
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-08 18:13:33 +01:00
const CompiledStylesheet<string_type, string_adaptor>& stylesheet() const { return stylesheet_; }
2007-07-19 19:01:42 +02:00
2012-11-08 18:13:33 +01:00
Output<string_type, string_adaptor>& sink()
2007-07-19 19:01:42 +02:00
{
return !to_msg_ ? sink_ : message_sink_.asOutput();
2007-07-19 19:01:42 +02:00
} // sink
void redirectToMessageSink() { ++to_msg_; }
void revertFromMessageSink() { --to_msg_; }
2007-07-19 19:01:42 +02:00
2012-11-08 18:13:33 +01:00
const Arabica::XPath::ExecutionContext<string_type, string_adaptor>& xpathContext() const { return xpathContext_; }
2007-07-19 19:01:42 +02:00
2012-11-08 18:13:33 +01:00
void topLevelParam(const DOM::Node<string_type, string_adaptor>& node, const Variable_declaration<string_type, string_adaptor>& param);
string_type passParam(const DOM::Node<string_type, string_adaptor>& node, const Variable_declaration<string_type, string_adaptor>& param);
void unpassParam(const string_type& name);
void declareParam(const DOM::Node<string_type, string_adaptor>& node, const Variable_declaration<string_type, string_adaptor>& param);
void declareVariable(const DOM::Node<string_type, string_adaptor>& node, const Variable_declaration<string_type, string_adaptor>& variable);
2007-07-19 19:01:42 +02:00
void freezeTopLevel();
2012-11-08 18:13:33 +01:00
void injectGlobalScope(const typename ScopeType<string_type, string_adaptor>::Scope& scope);
2007-07-19 19:01:42 +02:00
2012-11-08 18:13:33 +01:00
void setPosition(const DOM::Node<string_type, string_adaptor>& current, size_t pos) { setPosition(current, static_cast<int>(pos)); }
void setPosition(const DOM::Node<string_type, string_adaptor>& current, int pos)
2007-07-19 19:01:42 +02:00
{
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(); }
void chainStackFrame() { stack_.chainScope(); }
2007-07-19 19:01:42 +02:00
void popStackFrame() { stack_.popScope(); }
private:
2012-11-08 18:13:33 +01:00
const CompiledStylesheet<string_type, string_adaptor>& stylesheet_;
VariableStack<string_type, string_adaptor> stack_;
Arabica::XPath::ExecutionContext<string_type, string_adaptor> xpathContext_;
Output<string_type, string_adaptor>& sink_;
StreamSink<string_type, string_adaptor> message_sink_;
int to_msg_;
2007-07-19 19:01:42 +02:00
2012-11-08 18:19:10 +01:00
friend class StackFrame<string_type, string_adaptor> ;
friend class ChainStackFrame<string_type, string_adaptor> ;
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-08 18:13:33 +01:00
class VariableClosure : public Variable_instance<string_type, string_adaptor>
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-08 18:21:57 +01:00
typedef typename ScopeType<string_type, string_adaptor>::Scope Scope;
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,
2012-11-08 18:13:33 +01:00
ExecutionContext<string_type, string_adaptor>& context)
2007-07-19 19:01:42 +02:00
{
return Variable_instance_ptr(new VariableClosure(var, node, context));
} // create
2012-11-08 18:13:33 +01:00
virtual const string_type& name() const { return var_.name(); }
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_)
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,
2012-11-08 18:13:33 +01:00
ExecutionContext<string_type, string_adaptor>& context) :
2007-07-19 19:01:42 +02:00
var_(var),
sink_(),
2007-07-19 19:01:42 +02:00
node_(node),
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_;
2012-11-08 18:13:33 +01:00
mutable ExecutionContext<string_type, string_adaptor> 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-08 18:13:33 +01:00
template<class string_type, class string_adaptor>
void ExecutionContext<string_type, string_adaptor>::topLevelParam(const DOM::Node<string_type, string_adaptor>& node, const Variable_declaration<string_type, string_adaptor>& param)
2007-07-19 19:01:42 +02:00
{
2012-11-08 18:13:33 +01:00
stack_.topLevelParam(VariableClosure<string_type, string_adaptor>::create(param, node, *this));
} // topLevelParam
2007-07-19 19:01:42 +02:00
2012-11-08 18:13:33 +01:00
template<class string_type, class string_adaptor>
string_type ExecutionContext<string_type, string_adaptor>::passParam(const DOM::Node<string_type, string_adaptor>& node, const Variable_declaration<string_type, string_adaptor>& param)
2007-07-19 19:01:42 +02:00
{
2012-11-08 18:13:33 +01:00
return stack_.passParam(VariableClosure<string_type, string_adaptor>::create(param, node, *this));
2007-07-19 19:01:42 +02:00
} // passParam
2012-11-08 18:13:33 +01:00
template<class string_type, class string_adaptor>
void ExecutionContext<string_type, string_adaptor>::unpassParam(const string_type& name)
{
stack_.unpassParam(name);
} // unpassParam
2012-11-08 18:13:33 +01:00
template<class string_type, class string_adaptor>
void ExecutionContext<string_type, string_adaptor>::declareParam(const DOM::Node<string_type, string_adaptor>& node, const Variable_declaration<string_type, string_adaptor>& param)
2007-07-19 19:01:42 +02:00
{
if(!stack_.findPassedParam(param.name()))
2012-11-08 18:13:33 +01:00
stack_.declareParam(VariableClosure<string_type, string_adaptor>::create(param, node, *this));
2007-07-19 19:01:42 +02:00
} // declareParam
2012-11-08 18:13:33 +01:00
template<class string_type, class string_adaptor>
void ExecutionContext<string_type, string_adaptor>::declareVariable(const DOM::Node<string_type, string_adaptor>& node, const Variable_declaration<string_type, string_adaptor>& variable)
2007-07-19 19:01:42 +02:00
{
2012-11-08 18:13:33 +01:00
stack_.declareVariable(VariableClosure<string_type, string_adaptor>::create(variable, node, *this));
2007-07-19 19:01:42 +02:00
} // declareVariable
2012-11-08 18:13:33 +01:00
template<class string_type, class string_adaptor>
void ExecutionContext<string_type, string_adaptor>::freezeTopLevel()
2007-07-19 19:01:42 +02:00
{
stack_.freezeTopLevel();
} // freezeTopLevel
2012-11-08 18:13:33 +01:00
template<class string_type, class string_adaptor>
void ExecutionContext<string_type, string_adaptor>::injectGlobalScope(const typename ScopeType<string_type, string_adaptor>::Scope& scope)
2007-07-19 19:01:42 +02:00
{
stack_.injectGlobalScope(scope);
} // injectGlobalScope
///////////////////////////
2012-11-08 18:13:33 +01:00
template<class string_type, class string_adaptor>
2007-07-19 19:01:42 +02:00
class StackFrame
{
public:
2012-11-08 18:13:33 +01:00
StackFrame(ExecutionContext<string_type, string_adaptor>& context) : context_(context) { context_.pushStackFrame(); }
2007-07-19 19:01:42 +02:00
~StackFrame() { context_.popStackFrame(); }
private:
2012-11-08 18:13:33 +01:00
ExecutionContext<string_type, string_adaptor>& context_;
2007-07-19 19:01:42 +02:00
StackFrame(const StackFrame&);
StackFrame& operator=(const StackFrame&);
bool operator==(const StackFrame&) const;
}; // class StackFrame
2012-11-08 18:13:33 +01:00
template<class string_type, class string_adaptor>
class ChainStackFrame
{
public:
2012-11-08 18:13:33 +01:00
ChainStackFrame(ExecutionContext<string_type, string_adaptor>& context) : context_(context) { context_.chainStackFrame(); }
~ChainStackFrame() { context_.popStackFrame(); }
private:
2012-11-08 18:13:33 +01:00
ExecutionContext<string_type, string_adaptor>& context_;
ChainStackFrame(const ChainStackFrame&);
ChainStackFrame& operator=(const ChainStackFrame&);
bool operator==(const ChainStackFrame&) const;
}; // class ChainStackFrame
2007-07-19 19:01:42 +02:00
///////////////////////////
2012-11-08 18:13:33 +01:00
template<class string_type, class string_adaptor>
2007-07-19 19:01:42 +02:00
class LastFrame
{
public:
2012-11-08 18:13:33 +01:00
LastFrame(ExecutionContext<string_type, string_adaptor>& context, int last) : context_(context)
2007-07-19 19:01:42 +02:00
{
oldLast_ = context_.setLast(last);
} // LastFrame
2012-11-08 18:13:33 +01:00
LastFrame(ExecutionContext<string_type, string_adaptor>& context, size_t last) : context_(context)
2007-07-19 19:01:42 +02:00
{
oldLast_ = context_.setLast(static_cast<int>(last));
} // LastFrame
~LastFrame()
{
context_.setLast(oldLast_);
} // ~LastFrame
private:
2012-11-08 18:13:33 +01:00
ExecutionContext<string_type, string_adaptor>& context_;
2007-07-19 19:01:42 +02:00
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