From aa9bdc19bac61ad4d22d6791581735c27e992edb Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C4=99drzej=20Nowacki?= Date: Thu, 8 Sep 2011 09:45:55 +0200 Subject: [PATCH] Split qjsconverter_p header. Change-Id: I7495cfe5932cdd226e6e8c550fff421e3705184a Reviewed-on: http://codereview.qt-project.org/4411 Reviewed-by: Qt Sanity Bot Reviewed-by: Kent Hansen --- src/declarative/qml/v8/qjsconverter_impl_p.h | 268 +++++++++++++++++++++++++++ src/declarative/qml/v8/qjsconverter_p.h | 202 ++------------------ src/declarative/qml/v8/qscript_impl_p.h | 1 + src/declarative/qml/v8/qv8stringwrapper.cpp | 1 + src/declarative/qml/v8/script.pri | 1 + 5 files changed, 282 insertions(+), 191 deletions(-) create mode 100644 src/declarative/qml/v8/qjsconverter_impl_p.h diff --git a/src/declarative/qml/v8/qjsconverter_impl_p.h b/src/declarative/qml/v8/qjsconverter_impl_p.h new file mode 100644 index 0000000..2272721 --- /dev/null +++ b/src/declarative/qml/v8/qjsconverter_impl_p.h @@ -0,0 +1,268 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative 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 jsString) +{ + if (jsString.IsEmpty()) + return QString(); + QString qstr; + qstr.resize(jsString->Length()); + jsString->Write(reinterpret_cast(qstr.data())); + return qstr; +} + +v8::Local QJSConverter::toString(const QString& string) +{ + return v8::String::New(reinterpret_cast(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 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& flags) +{ + uint attr = 0; + if (flags.testFlag(QJSValue::ReadOnly)) + attr |= v8::ReadOnly; + if (flags.testFlag(QJSValue::Undeletable)) + attr |= v8::DontDelete; + if (flags.testFlag(QJSValue::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 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::Handle 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(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::Handle QJSConverter::toStringList(const QStringList &lst) +{ + v8::Handle 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 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 jsDate) +{ + return QDateTime::fromMSecsSinceEpoch(jsDate->NumberValue()); +} + +// Converts a QDateTime to a JS Date. +v8::Handle 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 diff --git a/src/declarative/qml/v8/qjsconverter_p.h b/src/declarative/qml/v8/qjsconverter_p.h index c42381b..9ec7aaf 100644 --- a/src/declarative/qml/v8/qjsconverter_p.h +++ b/src/declarative/qml/v8/qjsconverter_p.h @@ -37,9 +37,6 @@ 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); - /* \internal \class QJSConverter @@ -50,222 +47,45 @@ Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyn */ class QJSConverter { public: - static quint32 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; - } - - static QString toString(v8::Handle jsString) - { - if (jsString.IsEmpty()) - return QString(); - QString qstr; - qstr.resize(jsString->Length()); - jsString->Write(reinterpret_cast(qstr.data())); - return qstr; - } - - static v8::Local toString(const QString& string) - { - return v8::String::New(reinterpret_cast(string.data()), string.size()); - } - - static QString 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"); + static inline quint32 toArrayIndex(const QString& string); - QVarLengthArray 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()); - } + static inline QString toString(v8::Handle jsString); + static inline v8::Local toString(const QString& string); + static inline QString toString(double value); enum { PropertyAttributeMask = v8::ReadOnly | v8::DontDelete | v8::DontEnum, }; - // return a mask of v8::PropertyAttribute that may also contains QScriptValue::PropertyGetter or QScriptValue::PropertySetter - static uint toPropertyAttributes(const QFlags& flags) - { - uint attr = 0; - if (flags.testFlag(QJSValue::ReadOnly)) - attr |= v8::ReadOnly; - if (flags.testFlag(QJSValue::Undeletable)) - attr |= v8::DontDelete; - if (flags.testFlag(QJSValue::SkipInEnumeration)) - attr |= v8::DontEnum; -// if (flags.testFlag(QScriptValue::PropertyGetter)) -// attr |= QScriptValue::PropertyGetter; -// if (flags.testFlag(QScriptValue::PropertySetter)) -// attr |= QScriptValue::PropertySetter; - return attr; - } + static inline uint toPropertyAttributes(const QFlags& flags); // 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. - static QRegExp toRegExp(v8::Handle 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); - } + static inline QRegExp toRegExp(v8::Handle jsRegExp); // 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. - static v8::Handle 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(flags)); - } + static inline v8::Handle toRegExp(const QRegExp &re); // 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. - static v8::Handle toStringList(const QStringList &lst) - { - v8::Handle result = v8::Array::New(lst.size()); - for (int i = 0; i < lst.size(); ++i) - result->Set(i, toString(lst.at(i))); - return result; - } + static inline v8::Handle toStringList(const QStringList &lst); // 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. - static QStringList toStringList(v8::Handle 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; - } - + static inline QStringList toStringList(v8::Handle jsArray); // Converts a JS Date to a QDateTime. - static QDateTime toDateTime(v8::Handle jsDate) - { - return QDateTime::fromMSecsSinceEpoch(jsDate->NumberValue()); - } + static inline QDateTime toDateTime(v8::Handle jsDate); // Converts a QDateTime to a JS Date. - static v8::Handle toDateTime(const QDateTime &dt) - { - double date; - if (!dt.isValid()) - date = qSNaN(); - else - date = dt.toMSecsSinceEpoch(); - return v8::Date::New(date); - } + static inline v8::Handle toDateTime(const QDateTime &dt); }; QT_END_NAMESPACE diff --git a/src/declarative/qml/v8/qscript_impl_p.h b/src/declarative/qml/v8/qscript_impl_p.h index d197d9f..035a784 100644 --- a/src/declarative/qml/v8/qscript_impl_p.h +++ b/src/declarative/qml/v8/qscript_impl_p.h @@ -38,5 +38,6 @@ #include "qv8engine_impl_p.h" #include "qjsvalue_impl_p.h" #include "qjsvalueiterator_impl_p.h" +#include "qjsconverter_impl_p.h" #endif //QSCRIPT_IMPL_P_H diff --git a/src/declarative/qml/v8/qv8stringwrapper.cpp b/src/declarative/qml/v8/qv8stringwrapper.cpp index a1db580..d70a9d9 100644 --- a/src/declarative/qml/v8/qv8stringwrapper.cpp +++ b/src/declarative/qml/v8/qv8stringwrapper.cpp @@ -41,6 +41,7 @@ #include "qv8stringwrapper_p.h" #include "qjsconverter_p.h" +#include "qjsconverter_impl_p.h" QT_BEGIN_NAMESPACE diff --git a/src/declarative/qml/v8/script.pri b/src/declarative/qml/v8/script.pri index 7454d20..68a8c64 100644 --- a/src/declarative/qml/v8/script.pri +++ b/src/declarative/qml/v8/script.pri @@ -13,6 +13,7 @@ HEADERS += \ $$PWD/qjsvalueiterator.h \ $$PWD/qjsvalue_impl_p.h \ $$PWD/qjsconverter_p.h \ + $$PWD/qjsconverter_impl_p.h \ $$PWD/qscriptisolate_p.h \ $$PWD/qscriptshareddata_p.h \ $$PWD/qscripttools_p.h \ -- 2.7.4