1 /* 2 * Copyright (C) 2005 Frerich Raabe <raabe (at) kde.org> 3 * Copyright (C) 2006, 2009 Apple Inc. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include "config.h" 28 #include "XPathResult.h" 29 30 #if ENABLE(XPATH) 31 32 #include "Document.h" 33 #include "Node.h" 34 #include "ExceptionCode.h" 35 #include "XPathEvaluator.h" 36 #include "XPathException.h" 37 38 namespace WebCore { 39 40 using namespace XPath; 41 42 XPathResult::XPathResult(Document* document, const Value& value) 43 : m_value(value) 44 { 45 switch (m_value.type()) { 46 case Value::BooleanValue: 47 m_resultType = BOOLEAN_TYPE; 48 return; 49 case Value::NumberValue: 50 m_resultType = NUMBER_TYPE; 51 return; 52 case Value::StringValue: 53 m_resultType = STRING_TYPE; 54 return; 55 case Value::NodeSetValue: 56 m_resultType = UNORDERED_NODE_ITERATOR_TYPE; 57 m_nodeSetPosition = 0; 58 m_nodeSet = m_value.toNodeSet(); 59 m_document = document; 60 m_domTreeVersion = document->domTreeVersion(); 61 return; 62 } 63 ASSERT_NOT_REACHED(); 64 } 65 66 XPathResult::~XPathResult() 67 { 68 } 69 70 void XPathResult::convertTo(unsigned short type, ExceptionCode& ec) 71 { 72 switch (type) { 73 case ANY_TYPE: 74 break; 75 case NUMBER_TYPE: 76 m_resultType = type; 77 m_value = m_value.toNumber(); 78 break; 79 case STRING_TYPE: 80 m_resultType = type; 81 m_value = m_value.toString(); 82 break; 83 case BOOLEAN_TYPE: 84 m_resultType = type; 85 m_value = m_value.toBoolean(); 86 break; 87 case UNORDERED_NODE_ITERATOR_TYPE: 88 case UNORDERED_NODE_SNAPSHOT_TYPE: 89 case ANY_UNORDERED_NODE_TYPE: 90 case FIRST_ORDERED_NODE_TYPE: // This is correct - singleNodeValue() will take care of ordering. 91 if (!m_value.isNodeSet()) { 92 ec = XPathException::TYPE_ERR; 93 return; 94 } 95 m_resultType = type; 96 break; 97 case ORDERED_NODE_ITERATOR_TYPE: 98 if (!m_value.isNodeSet()) { 99 ec = XPathException::TYPE_ERR; 100 return; 101 } 102 m_nodeSet.sort(); 103 m_resultType = type; 104 break; 105 case ORDERED_NODE_SNAPSHOT_TYPE: 106 if (!m_value.isNodeSet()) { 107 ec = XPathException::TYPE_ERR; 108 return; 109 } 110 m_value.toNodeSet().sort(); 111 m_resultType = type; 112 break; 113 } 114 } 115 116 unsigned short XPathResult::resultType() const 117 { 118 return m_resultType; 119 } 120 121 double XPathResult::numberValue(ExceptionCode& ec) const 122 { 123 if (resultType() != NUMBER_TYPE) { 124 ec = XPathException::TYPE_ERR; 125 return 0.0; 126 } 127 return m_value.toNumber(); 128 } 129 130 String XPathResult::stringValue(ExceptionCode& ec) const 131 { 132 if (resultType() != STRING_TYPE) { 133 ec = XPathException::TYPE_ERR; 134 return String(); 135 } 136 return m_value.toString(); 137 } 138 139 bool XPathResult::booleanValue(ExceptionCode& ec) const 140 { 141 if (resultType() != BOOLEAN_TYPE) { 142 ec = XPathException::TYPE_ERR; 143 return false; 144 } 145 return m_value.toBoolean(); 146 } 147 148 Node* XPathResult::singleNodeValue(ExceptionCode& ec) const 149 { 150 if (resultType() != ANY_UNORDERED_NODE_TYPE && resultType() != FIRST_ORDERED_NODE_TYPE) { 151 ec = XPathException::TYPE_ERR; 152 return 0; 153 } 154 155 const NodeSet& nodes = m_value.toNodeSet(); 156 if (resultType() == FIRST_ORDERED_NODE_TYPE) 157 return nodes.firstNode(); 158 else 159 return nodes.anyNode(); 160 } 161 162 bool XPathResult::invalidIteratorState() const 163 { 164 if (resultType() != UNORDERED_NODE_ITERATOR_TYPE && resultType() != ORDERED_NODE_ITERATOR_TYPE) 165 return false; 166 167 ASSERT(m_document); 168 return m_document->domTreeVersion() != m_domTreeVersion; 169 } 170 171 unsigned long XPathResult::snapshotLength(ExceptionCode& ec) const 172 { 173 if (resultType() != UNORDERED_NODE_SNAPSHOT_TYPE && resultType() != ORDERED_NODE_SNAPSHOT_TYPE) { 174 ec = XPathException::TYPE_ERR; 175 return 0; 176 } 177 178 return m_value.toNodeSet().size(); 179 } 180 181 Node* XPathResult::iterateNext(ExceptionCode& ec) 182 { 183 if (resultType() != UNORDERED_NODE_ITERATOR_TYPE && resultType() != ORDERED_NODE_ITERATOR_TYPE) { 184 ec = XPathException::TYPE_ERR; 185 return 0; 186 } 187 188 if (invalidIteratorState()) { 189 ec = INVALID_STATE_ERR; 190 return 0; 191 } 192 193 if (m_nodeSetPosition + 1 > m_nodeSet.size()) 194 return 0; 195 196 Node* node = m_nodeSet[m_nodeSetPosition]; 197 198 m_nodeSetPosition++; 199 200 return node; 201 } 202 203 Node* XPathResult::snapshotItem(unsigned long index, ExceptionCode& ec) 204 { 205 if (resultType() != UNORDERED_NODE_SNAPSHOT_TYPE && resultType() != ORDERED_NODE_SNAPSHOT_TYPE) { 206 ec = XPathException::TYPE_ERR; 207 return 0; 208 } 209 210 const NodeSet& nodes = m_value.toNodeSet(); 211 if (index >= nodes.size()) 212 return 0; 213 214 return nodes[index]; 215 } 216 217 } 218 219 #endif // ENABLE(XPATH) 220