• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2     Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
3 
4     This library is free software; you can redistribute it and/or
5     modify it under the terms of the GNU Library General Public
6     License as published by the Free Software Foundation; either
7     version 2 of the License, or (at your option) any later version.
8 
9     This library is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12     Library General Public License for more details.
13 
14     You should have received a copy of the GNU Library General Public License
15     along with this library; see the file COPYING.LIB.  If not, write to
16     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17     Boston, MA 02110-1301, USA.
18 */
19 
20 #ifndef qscriptconverter_p_h
21 #define qscriptconverter_p_h
22 
23 #include "qscriptvalue.h"
24 #include <JavaScriptCore/JavaScript.h>
25 #include <QtCore/qglobal.h>
26 #include <QtCore/qnumeric.h>
27 #include <QtCore/qstring.h>
28 #include <QtCore/qvarlengtharray.h>
29 
30 extern char *qdtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve, char **digits_str);
31 
32 /*
33   \internal
34   \class QScriptConverter
35   QScriptValue and QScriptEngine helper class. This class's responsibility is to convert values
36   between JS values and Qt/C++ values.
37 
38   This is a nice way to inline these functions in both QScriptValue and QScriptEngine.
39 */
40 class QScriptConverter {
41 public:
toArrayIndex(const JSStringRef jsstring)42     static quint32 toArrayIndex(const JSStringRef jsstring)
43     {
44         // FIXME this function should be exported by JSC C API.
45         QString qstring = toString(jsstring);
46 
47         bool ok;
48         quint32 idx = qstring.toUInt(&ok);
49         if (!ok || toString(idx) != qstring)
50             idx = 0xffffffff;
51 
52         return idx;
53     }
54 
toString(const JSStringRef str)55     static QString toString(const JSStringRef str)
56     {
57         return QString(reinterpret_cast<const QChar*>(JSStringGetCharactersPtr(str)), JSStringGetLength(str));
58     }
toString(const QString & str)59     static JSStringRef toString(const QString& str)
60     {
61         return JSStringCreateWithUTF8CString(str.toUtf8().constData());
62     }
toString(const char * str)63     static JSStringRef toString(const char* str)
64     {
65         return JSStringCreateWithUTF8CString(str);
66     }
toString(double value)67     static QString toString(double value)
68     {
69         // FIXME this should be easier. The ideal fix is to create
70         // a new function in JSC C API which could cover the functionality.
71 
72         if (qIsNaN(value))
73             return QString::fromLatin1("NaN");
74         if (qIsInf(value))
75             return QString::fromLatin1(value < 0 ? "-Infinity" : "Infinity");
76         if (!value)
77             return QString::fromLatin1("0");
78 
79         QVarLengthArray<char, 25> buf;
80         int decpt;
81         int sign;
82         char* result = 0;
83         char* endresult;
84         (void)qdtoa(value, 0, 0, &decpt, &sign, &endresult, &result);
85 
86         if (!result)
87             return QString();
88 
89         int resultLen = endresult - result;
90         if (decpt <= 0 && decpt > -6) {
91             buf.resize(-decpt + 2 + sign);
92             qMemSet(buf.data(), '0', -decpt + 2 + sign);
93             if (sign) // fix the sign.
94                 buf[0] = '-';
95             buf[sign + 1] = '.';
96             buf.append(result, resultLen);
97         } else {
98             if (sign)
99                 buf.append('-');
100             int length = buf.size() - sign + resultLen;
101             if (decpt <= 21 && decpt > 0) {
102                 if (length <= decpt) {
103                     const char* zeros = "0000000000000000000000000";
104                     buf.append(result, resultLen);
105                     buf.append(zeros, decpt - length);
106                 } else {
107                     buf.append(result, decpt);
108                     buf.append('.');
109                     buf.append(result + decpt, resultLen - decpt);
110                 }
111             } else if (result[0] >= '0' && result[0] <= '9') {
112                 if (length > 1) {
113                     buf.append(result, 1);
114                     buf.append('.');
115                     buf.append(result + 1, resultLen - 1);
116                 } else
117                     buf.append(result, resultLen);
118                 buf.append('e');
119                 buf.append(decpt >= 0 ? '+' : '-');
120                 int e = qAbs(decpt - 1);
121                 if (e >= 100)
122                     buf.append('0' + e / 100);
123                 if (e >= 10)
124                     buf.append('0' + (e % 100) / 10);
125                 buf.append('0' + e % 10);
126             }
127         }
128         free(result);
129         buf.append(0);
130         return QString::fromLatin1(buf.constData());
131     }
132 
toPropertyFlags(const QFlags<QScriptValue::PropertyFlag> & flags)133     static JSPropertyAttributes toPropertyFlags(const QFlags<QScriptValue::PropertyFlag>& flags)
134     {
135         JSPropertyAttributes attr = 0;
136         if (flags.testFlag(QScriptValue::ReadOnly))
137             attr |= kJSPropertyAttributeReadOnly;
138         if (flags.testFlag(QScriptValue::Undeletable))
139             attr |= kJSPropertyAttributeDontDelete;
140         if (flags.testFlag(QScriptValue::SkipInEnumeration))
141             attr |= kJSPropertyAttributeDontEnum;
142         return attr;
143     }
144 };
145 
146 #endif // qscriptconverter_p_h
147