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