source: trunk/src/script/qscriptecmanumber.cpp@ 203

Last change on this file since 203 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 9.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtScript module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qscriptecmanumber_p.h"
43
44#ifndef QT_NO_SCRIPT
45
46#include "qscriptengine_p.h"
47#include "qscriptvalueimpl_p.h"
48#include "qscriptcontext_p.h"
49#include "qscriptmember_p.h"
50#include "qscriptobject_p.h"
51
52#include <QtCore/QtDebug>
53#include <QtCore/qnumeric.h>
54#include <math.h>
55
56QT_BEGIN_NAMESPACE
57
58namespace QScript { namespace Ecma {
59
60Number::Number(QScriptEnginePrivate *eng):
61 Core(eng, QLatin1String("Number"), QScriptClassInfo::NumberType)
62{
63 newNumber(&publicPrototype, 0);
64
65 eng->newConstructor(&ctor, this, publicPrototype);
66
67 addPrototypeFunction(QLatin1String("toString"), method_toString, 0);
68 addPrototypeFunction(QLatin1String("toLocaleString"), method_toLocaleString, 0);
69 addPrototypeFunction(QLatin1String("valueOf"), method_valueOf, 0);
70 addPrototypeFunction(QLatin1String("toFixed"), method_toFixed, 1);
71 addPrototypeFunction(QLatin1String("toExponential"), method_toExponential, 1);
72 addPrototypeFunction(QLatin1String("toPrecision"), method_toPrecision, 1);
73
74 QScriptValue::PropertyFlags flags = QScriptValue::Undeletable
75 | QScriptValue::ReadOnly
76 | QScriptValue::SkipInEnumeration;
77 ctor.setProperty(QLatin1String("NaN"),
78 QScriptValueImpl(qSNaN()), flags);
79 ctor.setProperty(QLatin1String("NEGATIVE_INFINITY"),
80 QScriptValueImpl(-qInf()), flags);
81 ctor.setProperty(QLatin1String("POSITIVE_INFINITY"),
82 QScriptValueImpl(qInf()), flags);
83 ctor.setProperty(QLatin1String("MAX_VALUE"),
84 QScriptValueImpl(1.7976931348623158e+308), flags);
85#ifdef __INTEL_COMPILER
86# pragma warning( push )
87# pragma warning(disable: 239)
88#endif
89 ctor.setProperty(QLatin1String("MIN_VALUE"),
90 QScriptValueImpl(5e-324), flags);
91#ifdef __INTEL_COMPILER
92# pragma warning( pop )
93#endif
94}
95
96Number::~Number()
97{
98}
99
100void Number::execute(QScriptContextPrivate *context)
101{
102#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
103 engine()->notifyFunctionEntry(context);
104#endif
105 qsreal value;
106 if (context->argumentCount() > 0)
107 value = context->argument(0).toNumber();
108 else
109 value = 0;
110
111 QScriptValueImpl num(value);
112 if (!context->isCalledAsConstructor()) {
113 context->setReturnValue(num);
114 } else {
115 QScriptValueImpl &obj = context->m_thisObject;
116 obj.setClassInfo(classInfo());
117 obj.setInternalValue(num);
118 obj.setPrototype(publicPrototype);
119 context->setReturnValue(obj);
120 }
121#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
122 engine()->notifyFunctionExit(context);
123#endif
124}
125
126void Number::newNumber(QScriptValueImpl *result, qsreal value)
127{
128 engine()->newObject(result, publicPrototype, classInfo());
129 result->setInternalValue(QScriptValueImpl(value));
130}
131
132QScriptValueImpl Number::method_toString(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo)
133{
134 QScriptValueImpl self = context->thisObject();
135 if (self.classInfo() != classInfo) {
136 return throwThisObjectTypeError(
137 context, QLatin1String("Number.prototype.toString"));
138 }
139 QScriptValueImpl arg = context->argument(0);
140 if (!arg.isUndefined()) {
141 int radix = arg.toInt32();
142 if (radix < 2 || radix > 36)
143 return context->throwError(QString::fromLatin1("Number.prototype.toString: %0 is not a valid radix")
144 .arg(radix));
145 if (radix != 10) {
146 QString str;
147 qsreal num = self.internalValue().toNumber();
148 if (qIsNaN(num))
149 return QScriptValueImpl(eng, QLatin1String("NaN"));
150 else if (qIsInf(num))
151 return QScriptValueImpl(eng, QLatin1String(num < 0 ? "-Infinity" : "Infinity"));
152 bool negative = false;
153 if (num < 0) {
154 negative = true;
155 num = -num;
156 }
157 qsreal frac = num - ::floor(num);
158 num = QScriptEnginePrivate::toInteger(num);
159 do {
160 char c = (char)::fmod(num, radix);
161 c = (c < 10) ? (c + '0') : (c - 10 + 'a');
162 str.prepend(QLatin1Char(c));
163 num = ::floor(num / radix);
164 } while (num != 0);
165 if (frac != 0) {
166 str.append(QLatin1Char('.'));
167 do {
168 frac = frac * radix;
169 char c = (char)::floor(frac);
170 c = (c < 10) ? (c + '0') : (c - 10 + 'a');
171 str.append(QLatin1Char(c));
172 frac = frac - ::floor(frac);
173 } while (frac != 0);
174 }
175 if (negative)
176 str.prepend(QLatin1Char('-'));
177 return QScriptValueImpl(eng, str);
178 }
179 }
180 QString str = self.internalValue().toString();
181 return (QScriptValueImpl(eng, str));
182}
183
184QScriptValueImpl Number::method_toLocaleString(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo)
185{
186 QScriptValueImpl self = context->thisObject();
187 if (self.classInfo() != classInfo) {
188 return throwThisObjectTypeError(
189 context, QLatin1String("Number.prototype.toLocaleString"));
190 }
191 QString str = self.internalValue().toString();
192 return (QScriptValueImpl(eng, str));
193}
194
195QScriptValueImpl Number::method_valueOf(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo)
196{
197 QScriptValueImpl self = context->thisObject();
198 if (self.classInfo() != classInfo) {
199 return throwThisObjectTypeError(
200 context, QLatin1String("Number.prototype.valueOf"));
201 }
202 return (self.internalValue());
203}
204
205QScriptValueImpl Number::method_toFixed(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo)
206{
207 QScriptValueImpl self = context->thisObject();
208 if (self.classInfo() != classInfo) {
209 return throwThisObjectTypeError(
210 context, QLatin1String("Number.prototype.toFixed"));
211 }
212 qsreal fdigits = 0;
213
214 if (context->argumentCount() > 0)
215 fdigits = context->argument(0).toInteger();
216
217 if (qIsNaN(fdigits))
218 fdigits = 0;
219
220 qsreal v = self.internalValue().toNumber();
221 QString str;
222 if (qIsNaN(v))
223 str = QString::fromLatin1("NaN");
224 else if (qIsInf(v))
225 str = QString::fromLatin1(v < 0 ? "-Infinity" : "Infinity");
226 else
227 str = QString::number(v, 'f', int (fdigits));
228 return (QScriptValueImpl(eng, str));
229}
230
231QScriptValueImpl Number::method_toExponential(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo)
232{
233 QScriptValueImpl self = context->thisObject();
234 if (self.classInfo() != classInfo) {
235 return throwThisObjectTypeError(
236 context, QLatin1String("Number.prototype.toExponential"));
237 }
238 qsreal fdigits = 0;
239
240 if (context->argumentCount() > 0)
241 fdigits = context->argument(0).toInteger();
242
243 qsreal v = self.internalValue().toNumber();
244 QString z = QString::number(v, 'e', int (fdigits));
245 return (QScriptValueImpl(eng, z));
246}
247
248QScriptValueImpl Number::method_toPrecision(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo)
249{
250 QScriptValueImpl self = context->thisObject();
251 if (self.classInfo() != classInfo) {
252 return throwThisObjectTypeError(
253 context, QLatin1String("Number.prototype.toPrecision"));
254 }
255 qsreal fdigits = 0;
256
257 if (context->argumentCount() > 0)
258 fdigits = context->argument(0).toInteger();
259
260 qsreal v = self.internalValue().toNumber();
261 return (QScriptValueImpl(eng, QString::number(v, 'g', int (fdigits))));
262}
263
264} } // namespace QScript::Ecma
265
266QT_END_NAMESPACE
267
268#endif // QT_NO_SCRIPT
Note: See TracBrowser for help on using the repository browser.