2006-05-09 Steve Falkenburg <sfalken@apple.com>
[WebKit-https.git] / WebCore / xpath / impl / XPathValue.cpp
1 /*
2  * Copyright 2005 Frerich Raabe <raabe@kde.org>
3  * Copyright (C) 2006 Apple Computer, Inc.
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 #include "config.h"
27
28 #if XPATH_SUPPORT
29
30 #include "XPathValue.h"
31 #include "Logging.h"
32
33 #ifdef _MSC_VER // math functions missing from Microsoft Visual Studio standard C library
34 #include <xmath.h>
35 #define isnan(x) _isnan(x)
36 #define isinf(x) !_finite(x)
37 #define signbit(x) (_copysign(1.0, (x)) < 0)
38 #endif
39
40 namespace WebCore {
41 namespace XPath {
42
43 Value::Value()
44 {
45 }
46
47 Value::Value(Node* value)
48     : m_type(NodeVector_)
49 {
50     m_nodevector.append(value);
51 }
52
53 Value::Value(const NodeVector& value)
54     : m_type(NodeVector_)
55     , m_nodevector(value)
56 {
57 }
58
59 Value::Value(bool value)
60     : m_type(Boolean),
61     m_bool(value)
62 {
63 }
64
65 Value::Value(double value)
66     : m_type(Number),
67     m_number(value)
68 {
69 }
70
71 Value::Value(const String& value)
72     : m_type(String_),
73     m_string(value)
74 {
75 }
76
77 Value::Type Value::type() const
78 {
79     return m_type;
80 }
81
82 bool Value::isNodeVector() const
83 {
84     return m_type == NodeVector_;
85 }
86
87 bool Value::isBoolean() const
88 {
89     return m_type == Boolean;
90 }
91
92 bool Value::isNumber() const
93 {
94     return m_type == Number;
95 }
96
97 bool Value::isString() const
98 {
99     return m_type == String_;
100 }
101
102 NodeVector& Value::toNodeVector()
103 {
104     if (m_type != NodeVector_) {
105         LOG(XPath, "Cannot convert anything to a nodevector.");
106     }
107     return m_nodevector;
108 }
109
110 const NodeVector &Value::toNodeVector() const
111 {
112     if (m_type != NodeVector_) {
113         LOG(XPath, "Cannot convert anything to a nodevector.");
114     }
115     
116     return m_nodevector;    
117 }    
118
119 bool Value::toBoolean() const
120 {
121     switch (m_type) {
122         case NodeVector_:
123             return !m_nodevector.isEmpty();
124         case Boolean:
125             return m_bool;
126         case Number:
127             return m_number != 0;
128         case String_:
129             return !m_string.isEmpty();
130     }
131     return false;
132 }
133
134 double Value::toNumber() const
135 {
136     switch (m_type) {
137         case NodeVector_:
138             return Value(toString()).toNumber();
139         case Number:
140             return m_number;
141         case String_: {
142             bool canConvert;
143             DeprecatedString s = m_string.deprecatedString().simplifyWhiteSpace();
144             
145             double value = s.toDouble(&canConvert);
146             if (canConvert)
147                 return value;
148
149             return NAN;
150         }
151         case Boolean:
152             return m_bool;
153     }
154     return 0.0;
155 }
156
157 String Value::toString() const
158 {
159     switch (m_type) {
160         case NodeVector_:
161             if (m_nodevector.isEmpty()) 
162                 return "";
163
164             return stringValue(m_nodevector[0].get());
165         case String_:
166             return m_string;
167         case Number:
168             if (isnan(m_number))
169                 return "NaN";
170             else if (m_number == 0)
171                 return "0";
172             else if (isinf(m_number)) {
173                 if (signbit(m_number) == 0)
174                     return "Infinity";
175                 else
176                     return "-Infinity";
177             }
178             return DeprecatedString::number(m_number);
179         case Boolean:
180             return m_bool ? "true" : "false";
181     }
182     
183     return String();
184 }
185
186
187 }
188 }
189
190 #endif // XPATH_SUPPORT