kdelibs/khtml/xml/dom3_xpathimpl.cpp
Ivailo Monev 39f1e04295 generic: add back khtml and kjs with some changes
Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
2015-11-09 23:23:53 +02:00

255 lines
7.5 KiB
C++

/*
* dom3_xpathimpl.cpp - Copyright 2005 Frerich Raabe <raabe@kde.org>
* Copyright 2010 Maksim Orlovich <maksim@kde.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <dom/dom_exception.h>
#include <dom/dom3_xpath.h>
#include <xml/dom3_xpathimpl.h>
#include <xml/dom_nodeimpl.h>
#include <xml/dom_nodelistimpl.h>
#include "xpath/expression.h"
#include "xpath/util.h"
using namespace DOM;
using namespace khtml;
using namespace khtml::XPath;
using namespace DOM::XPath;
XPathResultImpl::XPathResultImpl()
{
}
XPathResultImpl::XPathResultImpl( const Value &value )
: m_value( value )
{
switch ( m_value.type() ) {
case Value::Boolean:
m_resultType = BOOLEAN_TYPE;
break;
case Value::Number:
m_resultType = NUMBER_TYPE;
break;
case Value::String:
m_resultType = STRING_TYPE;
break;
case Value::Nodeset:
m_resultType = UNORDERED_NODE_ITERATOR_TYPE;
m_nodeIterator = 0;
}
}
void XPathResultImpl::convertTo( unsigned short type, int &exceptioncode )
{
switch ( type ) {
case ANY_TYPE:
break;
case NUMBER_TYPE:
m_resultType = type;
m_value = Value( m_value.toNumber() );
break;
case STRING_TYPE:
m_resultType = type;
m_value = Value( m_value.toString() );
break;
case BOOLEAN_TYPE:
m_resultType = type;
m_value = Value( m_value.toBoolean() );
break;
case UNORDERED_NODE_ITERATOR_TYPE:
case ORDERED_NODE_ITERATOR_TYPE:
case UNORDERED_NODE_SNAPSHOT_TYPE:
case ORDERED_NODE_SNAPSHOT_TYPE:
case ANY_UNORDERED_NODE_TYPE:
case FIRST_ORDERED_NODE_TYPE:
if ( !m_value.isNodeset() ) {
exceptioncode = XPathException::toCode(XPathException::TYPE_ERR);
return;
}
m_resultType = type;
break;
default:
kDebug(6011) << "Cannot convert XPathResultImpl to unknown type" << type;
exceptioncode = XPathException::toCode(XPathException::TYPE_ERR);
}
}
unsigned short XPathResultImpl::resultType() const
{
return m_resultType;
}
double XPathResultImpl::numberValue(int &exceptioncode) const
{
if ( resultType() != NUMBER_TYPE ) {
exceptioncode = XPathException::toCode(XPathException::TYPE_ERR);
return 0.0;
}
return m_value.toNumber();
}
DOM::DOMString XPathResultImpl::stringValue(int &exceptioncode) const
{
if ( resultType() != STRING_TYPE ) {
exceptioncode = XPathException::toCode(XPathException::TYPE_ERR);
return DOMString();
}
return m_value.toString();
}
bool XPathResultImpl::booleanValue(int &exceptioncode) const
{
if ( resultType() != BOOLEAN_TYPE ) {
exceptioncode = XPathException::toCode(XPathException::TYPE_ERR);
return false;
}
return m_value.toBoolean();
}
NodeImpl *XPathResultImpl::singleNodeValue(int &exceptioncode) const
{
if ( resultType() != ANY_UNORDERED_NODE_TYPE &&
resultType() != FIRST_ORDERED_NODE_TYPE ) {
exceptioncode = XPathException::toCode(XPathException::TYPE_ERR);
return 0;
}
DomNodeList nodes = m_value.toNodeset();
if (nodes && nodes->length())
return nodes->item(0);
else
return 0;
}
bool XPathResultImpl::invalidIteratorState() const
{
if ( resultType() != UNORDERED_NODE_ITERATOR_TYPE &&
resultType() != ORDERED_NODE_ITERATOR_TYPE ) {
return false;
}
// XXX How to tell whether the document was changed since this
// result was returned?
return true;
}
unsigned long XPathResultImpl::snapshotLength(int &exceptioncode) const
{
if ( resultType() != UNORDERED_NODE_SNAPSHOT_TYPE &&
resultType() != ORDERED_NODE_SNAPSHOT_TYPE ) {
exceptioncode = XPathException::toCode(XPathException::TYPE_ERR);
return 0;
}
SharedPtr<DOM::StaticNodeListImpl> nodes = m_value.toNodeset();
return nodes ? nodes->length() : 0;
}
NodeImpl *XPathResultImpl::iterateNext(int &exceptioncode)
{
if ( resultType() != UNORDERED_NODE_ITERATOR_TYPE &&
resultType() != ORDERED_NODE_ITERATOR_TYPE ) {
exceptioncode = XPathException::toCode(XPathException::TYPE_ERR);
return 0;
}
// XXX How to tell whether the document was changed since this
// result was returned? We need to throw an INVALID_STATE_ERR if that
// is the case.
SharedPtr<DOM::StaticNodeListImpl> nodes = m_value.toNodeset();
if ( !nodes || m_nodeIterator >= nodes->length() ) {
return 0;
} else {
NodeImpl* n = nodes->item(m_nodeIterator);
++m_nodeIterator;
return n;
}
}
NodeImpl *XPathResultImpl::snapshotItem( unsigned long index, int &exceptioncode )
{
if ( resultType() != UNORDERED_NODE_SNAPSHOT_TYPE &&
resultType() != ORDERED_NODE_SNAPSHOT_TYPE ) {
exceptioncode = XPathException::toCode(XPathException::TYPE_ERR);
return 0;
}
DomNodeList nodes = m_value.toNodeset();
if ( !nodes || index >= nodes->length() ) {
return 0;
}
return nodes->item( index );
}
// ---------------------------------------------------------------------------
DefaultXPathNSResolverImpl::DefaultXPathNSResolverImpl( NodeImpl *node )
: m_node( node )
{
}
DOMString DefaultXPathNSResolverImpl::lookupNamespaceURI( const DOMString& prefix )
{
// Apparently Node::lookupNamespaceURI doesn't do this.
// ### check
if ( prefix.string() == "xml" ) {
return DOMString( "http://www.w3.org/XML/1998/namespace" );
}
return m_node->lookupNamespaceURI( prefix );
}
// ---------------------------------------------------------------------------
XPathExpressionImpl::XPathExpressionImpl( const DOMString& expression, XPathNSResolverImpl *resolver ): m_statement(expression, resolver)
{
}
XPathResultImpl *XPathExpressionImpl::evaluate( NodeImpl *contextNode,
unsigned short type,
XPathResultImpl* /*result_*/,
int &exceptioncode )
{
if ( !isValidContextNode( contextNode ) ) {
exceptioncode = DOMException::NOT_SUPPORTED_ERR;
return 0;
}
// We are permitted, but not required, to re-use result_. We don't.
Value xpathRes = m_statement.evaluate( contextNode, exceptioncode );
XPathResultImpl* result = new XPathResultImpl( exceptioncode ? Value() : xpathRes );
if ( type != ANY_TYPE ) {
result->convertTo( type, exceptioncode );
if( exceptioncode ) {
kDebug(6011) << "couldn't convert XPathResult to" << type << "from" << xpathRes.type();
delete result;
return 0;
}
}
return result;
}
int XPathExpressionImpl::parseExceptionCode()
{
return m_statement.exceptionCode();
}
// kate: indent-width 4; replace-tabs off; tab-width 4; space-indent off;