aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/v8/qjsconverter_impl_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/qml/v8/qjsconverter_impl_p.h')
-rw-r--r--src/qml/qml/v8/qjsconverter_impl_p.h268
1 files changed, 268 insertions, 0 deletions
diff --git a/src/qml/qml/v8/qjsconverter_impl_p.h b/src/qml/qml/v8/qjsconverter_impl_p.h
new file mode 100644
index 0000000000..10b8ab5fae
--- /dev/null
+++ b/src/qml/qml/v8/qjsconverter_impl_p.h
@@ -0,0 +1,268 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qjsconverter_p.h"
+
+#ifndef QJSCONVERTER_IMPL_P_H
+#define QJSCONVERTER_IMPL_P_H
+
+QT_BEGIN_NAMESPACE
+
+extern char *qdtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve, char **digits_str);
+Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax);
+
+
+quint32 QJSConverter::toArrayIndex(const QString& string)
+{
+ // FIXME this function should be exported by JSC C API.
+ bool ok;
+ quint32 idx = string.toUInt(&ok);
+ if (!ok || toString(idx) != string)
+ idx = 0xffffffff;
+
+ return idx;
+}
+
+QString QJSConverter::toString(v8::Handle<v8::String> jsString)
+{
+ if (jsString.IsEmpty())
+ return QString();
+ QString qstr;
+ qstr.resize(jsString->Length());
+ jsString->Write(reinterpret_cast<uint16_t*>(qstr.data()));
+ return qstr;
+}
+
+v8::Local<v8::String> QJSConverter::toString(const QString& string)
+{
+ return v8::String::New(reinterpret_cast<const uint16_t*>(string.data()), string.size());
+}
+
+QString QJSConverter::toString(double value)
+{
+ // FIXME this should be easier. The ideal fix is to create
+ // a new function in V8 API which could cover the functionality.
+
+ if (qIsNaN(value))
+ return QString::fromLatin1("NaN");
+ if (qIsInf(value))
+ return QString::fromLatin1(value < 0 ? "-Infinity" : "Infinity");
+ if (!value)
+ return QString::fromLatin1("0");
+
+ QVarLengthArray<char, 25> buf;
+ int decpt;
+ int sign;
+ char* result = 0;
+ char* endresult;
+ (void)qdtoa(value, 0, 0, &decpt, &sign, &endresult, &result);
+
+ if (!result)
+ return QString();
+
+ int resultLen = endresult - result;
+ if (decpt <= 0 && decpt > -6) {
+ buf.resize(-decpt + 2 + sign);
+ qMemSet(buf.data(), '0', -decpt + 2 + sign);
+ if (sign) // fix the sign.
+ buf[0] = '-';
+ buf[sign + 1] = '.';
+ buf.append(result, resultLen);
+ } else {
+ if (sign)
+ buf.append('-');
+ int length = buf.size() - sign + resultLen;
+ if (decpt <= 21 && decpt > 0) {
+ if (length <= decpt) {
+ const char* zeros = "0000000000000000000000000";
+ buf.append(result, resultLen);
+ buf.append(zeros, decpt - length);
+ } else {
+ buf.append(result, decpt);
+ buf.append('.');
+ buf.append(result + decpt, resultLen - decpt);
+ }
+ } else if (result[0] >= '0' && result[0] <= '9') {
+ if (length > 1) {
+ buf.append(result, 1);
+ buf.append('.');
+ buf.append(result + 1, resultLen - 1);
+ } else
+ buf.append(result, resultLen);
+ buf.append('e');
+ buf.append(decpt >= 0 ? '+' : '-');
+ int e = qAbs(decpt - 1);
+ if (e >= 100)
+ buf.append('0' + e / 100);
+ if (e >= 10)
+ buf.append('0' + (e % 100) / 10);
+ buf.append('0' + e % 10);
+ }
+ }
+ free(result);
+ buf.append(0);
+ return QString::fromLatin1(buf.constData());
+}
+
+// return a mask of v8::PropertyAttribute that may also contains QScriptValue::PropertyGetter or QScriptValue::PropertySetter
+uint QJSConverter::toPropertyAttributes(const QFlags<QJSValuePrivate::PropertyFlag>& flags)
+{
+ uint attr = 0;
+ if (flags.testFlag(QJSValuePrivate::ReadOnly))
+ attr |= v8::ReadOnly;
+ if (flags.testFlag(QJSValuePrivate::Undeletable))
+ attr |= v8::DontDelete;
+ if (flags.testFlag(QJSValuePrivate::SkipInEnumeration))
+ attr |= v8::DontEnum;
+ // if (flags.testFlag(QScriptValue::PropertyGetter))
+ // attr |= QScriptValue::PropertyGetter;
+ // if (flags.testFlag(QScriptValue::PropertySetter))
+ // attr |= QScriptValue::PropertySetter;
+ return attr;
+}
+
+// Converts a JS RegExp to a QRegExp.
+// The conversion is not 100% exact since ECMA regexp and QRegExp
+// have different semantics/flags, but we try to do our best.
+QRegExp QJSConverter::toRegExp(v8::Handle<v8::RegExp> jsRegExp)
+{
+ QString pattern = QJSConverter::toString(jsRegExp->GetSource());
+ Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive;
+ if (jsRegExp->GetFlags() & v8::RegExp::kIgnoreCase)
+ caseSensitivity = Qt::CaseInsensitive;
+ return QRegExp(pattern, caseSensitivity, QRegExp::RegExp2);
+}
+
+// Converts a QRegExp to a JS RegExp.
+// The conversion is not 100% exact since ECMA regexp and QRegExp
+// have different semantics/flags, but we try to do our best.
+v8::Local<v8::RegExp> QJSConverter::toRegExp(const QRegExp &re)
+{
+ // Convert the pattern to a ECMAScript pattern.
+ QString pattern = qt_regexp_toCanonical(re.pattern(), re.patternSyntax());
+ if (re.isMinimal()) {
+ QString ecmaPattern;
+ int len = pattern.length();
+ ecmaPattern.reserve(len);
+ int i = 0;
+ const QChar *wc = pattern.unicode();
+ bool inBracket = false;
+ while (i < len) {
+ QChar c = wc[i++];
+ ecmaPattern += c;
+ switch (c.unicode()) {
+ case '?':
+ case '+':
+ case '*':
+ case '}':
+ if (!inBracket)
+ ecmaPattern += QLatin1Char('?');
+ break;
+ case '\\':
+ if (i < len)
+ ecmaPattern += wc[i++];
+ break;
+ case '[':
+ inBracket = true;
+ break;
+ case ']':
+ inBracket = false;
+ break;
+ default:
+ break;
+ }
+ }
+ pattern = ecmaPattern;
+ }
+
+ int flags = v8::RegExp::kNone;
+ if (re.caseSensitivity() == Qt::CaseInsensitive)
+ flags |= v8::RegExp::kIgnoreCase;
+
+ return v8::RegExp::New(QJSConverter::toString(pattern), static_cast<v8::RegExp::Flags>(flags));
+}
+
+// Converts a QStringList to JS.
+// The result is a new Array object with length equal to the length
+// of the QStringList, and the elements being the QStringList's
+// elements converted to JS Strings.
+v8::Local<v8::Array> QJSConverter::toStringList(const QStringList &lst)
+{
+ v8::Local<v8::Array> result = v8::Array::New(lst.size());
+ for (int i = 0; i < lst.size(); ++i)
+ result->Set(i, toString(lst.at(i)));
+ return result;
+}
+
+// Converts a JS Array object to a QStringList.
+// The result is a QStringList with length equal to the length
+// of the JS Array, and elements being the JS Array's elements
+// converted to QStrings.
+QStringList QJSConverter::toStringList(v8::Handle<v8::Array> jsArray)
+{
+ QStringList result;
+ uint32_t length = jsArray->Length();
+ for (uint32_t i = 0; i < length; ++i)
+ result.append(toString(jsArray->Get(i)->ToString()));
+ return result;
+}
+
+
+// Converts a JS Date to a QDateTime.
+QDateTime QJSConverter::toDateTime(v8::Handle<v8::Date> jsDate)
+{
+ return QDateTime::fromMSecsSinceEpoch(jsDate->NumberValue());
+}
+
+// Converts a QDateTime to a JS Date.
+v8::Local<v8::Value> QJSConverter::toDateTime(const QDateTime &dt)
+{
+ double date;
+ if (!dt.isValid())
+ date = qSNaN();
+ else
+ date = dt.toMSecsSinceEpoch();
+ return v8::Date::New(date);
+}
+
+QT_END_NAMESPACE
+
+#endif // QJSCONVERTER_IMPL_P_H