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