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