[WebIDL] Properly model buffer source / typed arrays as their own IDL types
[WebKit-https.git] / Source / WebCore / xml / XPathResult.cpp
1 /*
2  * Copyright (C) 2005 Frerich Raabe <raabe@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 #include "Document.h"
31 #include "ExceptionCode.h"
32 #include "XPathEvaluator.h"
33 #include "XPathException.h"
34
35 namespace WebCore {
36
37 using namespace XPath;
38
39 XPathResult::XPathResult(Document& document, const Value& value)
40     : m_value(value)
41 {
42     switch (m_value.type()) {
43         case Value::BooleanValue:
44             m_resultType = BOOLEAN_TYPE;
45             return;
46         case Value::NumberValue:
47             m_resultType = NUMBER_TYPE;
48             return;
49         case Value::StringValue:
50             m_resultType = STRING_TYPE;
51             return;
52         case Value::NodeSetValue:
53             m_resultType = UNORDERED_NODE_ITERATOR_TYPE;
54             m_nodeSetPosition = 0;
55             m_nodeSet = m_value.toNodeSet();
56             m_document = &document;
57             m_domTreeVersion = document.domTreeVersion();
58             return;
59     }
60     ASSERT_NOT_REACHED();
61 }
62
63 XPathResult::~XPathResult()
64 {
65 }
66
67 ExceptionOr<void> XPathResult::convertTo(unsigned short type)
68 {
69     switch (type) {
70     case ANY_TYPE:
71         break;
72     case NUMBER_TYPE:
73         m_resultType = type;
74         m_value = m_value.toNumber();
75         break;
76     case STRING_TYPE:
77         m_resultType = type;
78         m_value = m_value.toString();
79         break;
80     case BOOLEAN_TYPE:
81         m_resultType = type;
82         m_value = m_value.toBoolean();
83         break;
84     case UNORDERED_NODE_ITERATOR_TYPE:
85     case UNORDERED_NODE_SNAPSHOT_TYPE:
86     case ANY_UNORDERED_NODE_TYPE:
87     case FIRST_ORDERED_NODE_TYPE: // This is correct - singleNodeValue() will take care of ordering.
88         if (!m_value.isNodeSet())
89             return Exception { XPathException::TYPE_ERR };
90         m_resultType = type;
91         break;
92     case ORDERED_NODE_ITERATOR_TYPE:
93         if (!m_value.isNodeSet())
94             return Exception { XPathException::TYPE_ERR };
95         m_nodeSet.sort();
96         m_resultType = type;
97         break;
98     case ORDERED_NODE_SNAPSHOT_TYPE:
99         if (!m_value.isNodeSet())
100             return Exception { XPathException::TYPE_ERR };
101         m_value.toNodeSet().sort();
102         m_resultType = type;
103         break;
104     }
105     return { };
106 }
107
108 unsigned short XPathResult::resultType() const
109 {
110     return m_resultType;
111 }
112
113 ExceptionOr<double> XPathResult::numberValue() const
114 {
115     if (resultType() != NUMBER_TYPE)
116         return Exception { XPathException::TYPE_ERR };
117     return m_value.toNumber();
118 }
119
120 ExceptionOr<String> XPathResult::stringValue() const
121 {
122     if (resultType() != STRING_TYPE)
123         return Exception { XPathException::TYPE_ERR };
124     return m_value.toString();
125 }
126
127 ExceptionOr<bool> XPathResult::booleanValue() const
128 {
129     if (resultType() != BOOLEAN_TYPE)
130         return Exception { XPathException::TYPE_ERR };
131     return m_value.toBoolean();
132 }
133
134 ExceptionOr<Node*> XPathResult::singleNodeValue() const
135 {
136     if (resultType() != ANY_UNORDERED_NODE_TYPE && resultType() != FIRST_ORDERED_NODE_TYPE)
137         return Exception { XPathException::TYPE_ERR };
138
139     auto& nodes = m_value.toNodeSet();
140     if (resultType() == FIRST_ORDERED_NODE_TYPE)
141         return nodes.firstNode();
142     else
143         return nodes.anyNode();
144 }
145
146 bool XPathResult::invalidIteratorState() const
147 {
148     if (resultType() != UNORDERED_NODE_ITERATOR_TYPE && resultType() != ORDERED_NODE_ITERATOR_TYPE)
149         return false;
150
151     ASSERT(m_document);
152     return m_document->domTreeVersion() != m_domTreeVersion;
153 }
154
155 ExceptionOr<unsigned> XPathResult::snapshotLength() const
156 {
157     if (resultType() != UNORDERED_NODE_SNAPSHOT_TYPE && resultType() != ORDERED_NODE_SNAPSHOT_TYPE)
158         return Exception { XPathException::TYPE_ERR };
159
160     return m_value.toNodeSet().size();
161 }
162
163 ExceptionOr<Node*> XPathResult::iterateNext()
164 {
165     if (resultType() != UNORDERED_NODE_ITERATOR_TYPE && resultType() != ORDERED_NODE_ITERATOR_TYPE)
166         return Exception { XPathException::TYPE_ERR };
167
168     if (invalidIteratorState())
169         return Exception { INVALID_STATE_ERR };
170
171     if (m_nodeSetPosition >= m_nodeSet.size())
172         return nullptr;
173
174     return m_nodeSet[m_nodeSetPosition++];
175 }
176
177 ExceptionOr<Node*> XPathResult::snapshotItem(unsigned index)
178 {
179     if (resultType() != UNORDERED_NODE_SNAPSHOT_TYPE && resultType() != ORDERED_NODE_SNAPSHOT_TYPE)
180         return Exception { XPathException::TYPE_ERR };
181
182     auto& nodes = m_value.toNodeSet();
183     if (index >= nodes.size())
184         return nullptr;
185
186     return nodes[index];
187 }
188
189 }