From: Martin Jones Date: Thu, 21 Jul 2011 09:05:45 +0000 (+1000) Subject: Some lexer improvement, mostly by avoiding QChar::isWhatever() X-Git-Tag: qt-v5.0.0-alpha1~1833 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e17010ea327415cb5b67b1a70bc583bb31892294;p=profile%2Fivi%2Fqtdeclarative.git Some lexer improvement, mostly by avoiding QChar::isWhatever() Change-Id: I330a45a2f611a594d9b0e9bb24ebef028654a8d8 Reviewed-on: http://codereview.qt.nokia.com/3756 Reviewed-by: Roberto Raggi Reviewed-by: Qt Sanity Bot --- diff --git a/src/declarative/qml/ftw/ftw.pri b/src/declarative/qml/ftw/ftw.pri index 000c81b..190296a 100644 --- a/src/declarative/qml/ftw/ftw.pri +++ b/src/declarative/qml/ftw/ftw.pri @@ -9,6 +9,7 @@ HEADERS += \ $$PWD/qdeclarativerefcount_p.h \ $$PWD/qdeclarativepool_p.h \ $$PWD/qfieldlist_p.h \ + $$PWD/qdeclarativeutils_p.h SOURCES += \ $$PWD/qintrusivelist.cpp \ @@ -16,4 +17,3 @@ SOURCES += \ $$PWD/qhashedstring.cpp \ $$PWD/qdeclarativerefcount.cpp \ $$PWD/qdeclarativepool.cpp \ - diff --git a/src/declarative/qml/ftw/qdeclarativeutils_p.h b/src/declarative/qml/ftw/qdeclarativeutils_p.h new file mode 100644 index 0000000..63e9001 --- /dev/null +++ b/src/declarative/qml/ftw/qdeclarativeutils_p.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEUTIL_P_H +#define QDECLARATIVEUTIL_P_H + +#include + +QT_BEGIN_NAMESPACE + +namespace QDeclarativeUtils { + +inline bool isUpper(const QChar &qc) +{ + ushort c = qc.unicode(); + return ((c >= 'A' && c <= 'Z') || (c > 127 && QChar::category(c) == QChar::Letter_Uppercase)); +} + +inline bool isLower(const QChar &qc) +{ + ushort c = qc.unicode(); + return ((c >= 'a' && c <= 'z') || (c > 127 && QChar::category(c) == QChar::Letter_Lowercase)); +} + +inline bool isLetter(const QChar &qc) +{ + ushort c = qc.unicode(); + return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c > 127 && qc.isLetter())); +} + +inline bool isDigit(const QChar &qc) +{ + ushort c = qc.unicode(); + return ((c >= '0' && c <= '9') || (c > 127 && qc.isDigit())); +} + +inline bool isLetterOrNumber(const QChar &qc) +{ + ushort c = qc.unicode(); + return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || (c > 127 && qc.isLetterOrNumber())); +} + +inline bool isSpace(const QChar &qc) +{ + ushort c = qc.unicode(); + return (c == 0x20 || (c >= 0x09 && c <= 0x0D) || c == 0x85 || (c > 127 && qc.isSpace())); +} + +} // namespace QDeclarative + +QT_END_NAMESPACE + +#endif // QDECLARATIVEUTIL_P_H diff --git a/src/declarative/qml/parser/qdeclarativejslexer.cpp b/src/declarative/qml/parser/qdeclarativejslexer.cpp index 980c15c..570548c 100644 --- a/src/declarative/qml/parser/qdeclarativejslexer.cpp +++ b/src/declarative/qml/parser/qdeclarativejslexer.cpp @@ -42,7 +42,9 @@ #include "qdeclarativejslexer_p.h" #include "qdeclarativejsengine_p.h" #include "qdeclarativejsnodepool_p.h" +#include #include +#include #include QT_BEGIN_NAMESPACE @@ -126,6 +128,7 @@ void Lexer::setCode(const QString &code, int lineno) _code = code; _tokenText.clear(); + _tokenText.reserve(1024); _errorMessage.clear(); _tokenSpell = QStringRef(); @@ -275,7 +278,7 @@ again: _validTokenText = false; _tokenLinePtr = _lastLinePtr; - while (_char.isSpace()) { + while (QDeclarativeUtils::isSpace(_char)) { if (_char == QLatin1Char('\n')) { _tokenLinePtr = _codePtr; @@ -404,43 +407,44 @@ again: return T_DIVIDE_; case '.': - if (_char.isDigit()) { - QByteArray chars; - chars.reserve(32); + if (QDeclarativeUtils::isDigit(_char)) { + QVarLengthArray chars; - chars += ch.unicode(); // append the `.' + chars.append(ch.unicode()); // append the `.' - while (_char.isDigit()) { - chars += _char.unicode(); + while (QDeclarativeUtils::isDigit(_char)) { + chars.append(_char.unicode()); scanChar(); } - if (_char.toLower() == QLatin1Char('e')) { - if (_codePtr[0].isDigit() || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) && - _codePtr[1].isDigit())) { + if (_char == QLatin1Char('e') || _char == QLatin1Char('E')) { + if (QDeclarativeUtils::isDigit(_codePtr[0]) || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) && + QDeclarativeUtils::isDigit(_codePtr[1]))) { - chars += _char.unicode(); + chars.append(_char.unicode()); scanChar(); // consume `e' if (_char == QLatin1Char('+') || _char == QLatin1Char('-')) { - chars += _char.unicode(); + chars.append(_char.unicode()); scanChar(); // consume the sign } - while (_char.isDigit()) { - chars += _char.unicode(); + while (QDeclarativeUtils::isDigit(_char)) { + chars.append(_char.unicode()); scanChar(); } } } + chars.append('\0'); + const char *begin = chars.constData(); const char *end = 0; bool ok = false; _tokenValue = qstrtod(begin, &end, &ok); - if (end != chars.end()) { + if (end - begin != chars.size() - 1) { _errorCode = IllegalExponentIndicator; _errorMessage = QCoreApplication::translate("QDeclarativeParser", "Illegal syntax for exponential number"); return T_ERROR; @@ -525,7 +529,7 @@ again: case '\'': case '"': { const QChar quote = ch; - _tokenText.clear(); + _tokenText.resize(0); _validTokenText = true; bool multilineStringLiteral = false; @@ -632,11 +636,11 @@ again: } default: - if (ch.isLetter() || ch == QLatin1Char('$') || ch == QLatin1Char('_') || (ch == QLatin1Char('\\') && _char == QLatin1Char('u'))) { + if (QDeclarativeUtils::isLetter(ch) || ch == QLatin1Char('$') || ch == QLatin1Char('_') || (ch == QLatin1Char('\\') && _char == QLatin1Char('u'))) { bool identifierWithEscapeChars = false; if (ch == QLatin1Char('\\')) { identifierWithEscapeChars = true; - _tokenText.clear(); + _tokenText.resize(0); bool ok = false; _tokenText += decodeUnicodeEscapeCharacter(&ok); _validTokenText = true; @@ -647,7 +651,7 @@ again: } } while (true) { - if (_char.isLetterOrNumber() || _char == QLatin1Char('$') || _char == QLatin1Char('_')) { + if (QDeclarativeUtils::isLetterOrNumber(_char) || _char == QLatin1Char('$') || _char == QLatin1Char('_')) { if (identifierWithEscapeChars) _tokenText += _char; @@ -655,7 +659,8 @@ again: } else if (_char == QLatin1Char('\\') && _codePtr[0] == QLatin1Char('u')) { if (! identifierWithEscapeChars) { identifierWithEscapeChars = true; - _tokenText = QString(_tokenStartPtr, _codePtr - _tokenStartPtr - 1); + _tokenText.resize(0); + _tokenText.insert(0, _tokenStartPtr, _codePtr - _tokenStartPtr - 1); _validTokenText = true; } @@ -685,19 +690,18 @@ again: return kind; } } - } else if (ch.isDigit()) { - QByteArray chars; - chars.reserve(32); - chars += ch.unicode(); + } else if (QDeclarativeUtils::isDigit(ch)) { + QVarLengthArray chars; + chars.append(ch.unicode()); if (ch == QLatin1Char('0') && (_char == 'x' || _char == 'X')) { // parse hex integer literal - chars += _char.unicode(); + chars.append(_char.unicode()); scanChar(); // consume `x' while (isHexDigit(_char)) { - chars += _char.unicode(); + chars.append(_char.unicode()); scanChar(); } @@ -706,64 +710,66 @@ again: } // decimal integer literal - while (_char.isDigit()) { - chars += _char.unicode(); + while (QDeclarativeUtils::isDigit(_char)) { + chars.append(_char.unicode()); scanChar(); // consume the digit } if (_char == QLatin1Char('.')) { - chars += _char.unicode(); + chars.append(_char.unicode()); scanChar(); // consume `.' - while (_char.isDigit()) { - chars += _char.unicode(); + while (QDeclarativeUtils::isDigit(_char)) { + chars.append(_char.unicode()); scanChar(); } - if (_char.toLower() == QLatin1Char('e')) { - if (_codePtr[0].isDigit() || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) && - _codePtr[1].isDigit())) { + if (_char == QLatin1Char('e') || _char == QLatin1Char('E')) { + if (QDeclarativeUtils::isDigit(_codePtr[0]) || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) && + QDeclarativeUtils::isDigit(_codePtr[1]))) { - chars += _char.unicode(); + chars.append(_char.unicode()); scanChar(); // consume `e' if (_char == QLatin1Char('+') || _char == QLatin1Char('-')) { - chars += _char.unicode(); + chars.append(_char.unicode()); scanChar(); // consume the sign } - while (_char.isDigit()) { - chars += _char.unicode(); + while (QDeclarativeUtils::isDigit(_char)) { + chars.append(_char.unicode()); scanChar(); } } } - } else if (_char.toLower() == QLatin1Char('e')) { - if (_codePtr[0].isDigit() || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) && - _codePtr[1].isDigit())) { + } else if (_char == QLatin1Char('e') || _char == QLatin1Char('E')) { + if (QDeclarativeUtils::isDigit(_codePtr[0]) || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) && + QDeclarativeUtils::isDigit(_codePtr[1]))) { - chars += _char.unicode(); + chars.append(_char.unicode()); scanChar(); // consume `e' if (_char == QLatin1Char('+') || _char == QLatin1Char('-')) { - chars += _char.unicode(); + chars.append(_char.unicode()); scanChar(); // consume the sign } - while (_char.isDigit()) { - chars += _char.unicode(); + while (QDeclarativeUtils::isDigit(_char)) { + chars.append(_char.unicode()); scanChar(); } } } + chars.append('\0'); + const char *begin = chars.constData(); const char *end = 0; bool ok = false; _tokenValue = qstrtod(begin, &end, &ok); - if (end != chars.end()) { + if (end - begin != chars.size() - 1) { _errorCode = IllegalExponentIndicator; _errorMessage = QCoreApplication::translate("QDeclarativeParser", "Illegal syntax for exponential number"); return T_ERROR; @@ -780,7 +786,7 @@ again: bool Lexer::scanRegExp(RegExpBodyPrefix prefix) { - _tokenText.clear(); + _tokenText.resize(0); _validTokenText = true; _patternFlags = 0; diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index c75570d..984e2c8 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -64,6 +64,7 @@ #include "private/qdeclarativescriptparser_p.h" #include "private/qdeclarativebinding_p.h" #include "private/qdeclarativev4compiler_p.h" +#include "private/qdeclarativeutils_p.h" #include #include @@ -128,7 +129,7 @@ bool QDeclarativeCompiler::isAttachedPropertyName(const QString &name) bool QDeclarativeCompiler::isAttachedPropertyName(const QStringRef &name) { - return !name.isEmpty() && name.at(0) >= 'A' && name.at(0) <= 'Z'; + return !name.isEmpty() && QDeclarativeUtils::isUpper(name.at(0)); } /*! @@ -153,9 +154,9 @@ bool QDeclarativeCompiler::isSignalPropertyName(const QStringRef &name) if (!name.startsWith(on_string)) return false; int ns = name.size(); for (int i = 2; i < ns; ++i) { - QChar curr = name.at(i); - if (curr == QLatin1Char('_')) continue; - if (curr >= QLatin1Char('A') && curr <= QLatin1Char('Z')) return true; + const QChar curr = name.at(i); + if (curr.unicode() == '_') continue; + if (QDeclarativeUtils::isUpper(curr)) return true; return false; } return false; // consists solely of underscores - invalid. @@ -1418,7 +1419,7 @@ bool QDeclarativeCompiler::buildSignal(QDeclarativeParser::Property *prop, QDecl // Note that the property name could start with any alpha or '_' or '$' character, // so we need to do the lower-casing of the first alpha character. for (int firstAlphaIndex = 0; firstAlphaIndex < name.size(); ++firstAlphaIndex) { - if (name.at(firstAlphaIndex) >= QLatin1Char('A') && name.at(firstAlphaIndex) <= QLatin1Char('Z')) { + if (QDeclarativeUtils::isUpper(name.at(firstAlphaIndex))) { name[firstAlphaIndex] = name.at(firstAlphaIndex).toLower(); break; } @@ -2274,7 +2275,7 @@ bool QDeclarativeCompiler::testQualifiedEnumAssignment(const QMetaProperty &prop COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop.name()))); QString string = v->value.asString(); - if (!string.at(0).isUpper()) + if (!QDeclarativeUtils::isUpper(string.at(0))) return true; QStringList parts = string.split(QLatin1Char('.')); @@ -2399,7 +2400,7 @@ bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj) COMPILE_EXCEPTION(&prop, tr("Duplicate property name")); QString propName = QString::fromUtf8(prop.name); - if (propName.at(0).isUpper()) + if (QDeclarativeUtils::isUpper(propName.at(0))) COMPILE_EXCEPTION(&prop, tr("Property names cannot begin with an upper case letter")); if (enginePrivate->v8engine()->illegalNames().contains(propName)) @@ -2408,29 +2409,43 @@ bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj) propNames.insert(prop.name); } - for (int ii = 0; ii < obj->dynamicSignals.count(); ++ii) { - const QDeclarativeParser::Object::DynamicSignal &currSig = obj->dynamicSignals.at(ii); - QByteArray name = currSig.name; - if (methodNames.contains(name)) - COMPILE_EXCEPTION(&currSig, tr("Duplicate signal name")); - QString nameStr = QString::fromUtf8(name); - if (nameStr.at(0).isUpper()) + for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) { + const QDeclarativeScript::Object::DynamicSignal &currSig = *s; + + if (methodNames.testAndSet(currSig.name.hash())) { + for (Object::DynamicSignal *s2 = obj->dynamicSignals.first(); s2 != s; + s2 = obj->dynamicSignals.next(s2)) { + if (s2->name == currSig.name) + COMPILE_EXCEPTION(&currSig, tr("Duplicate signal name")); + } + } + + if (currSig.name.at(0).isUpper()) COMPILE_EXCEPTION(&currSig, tr("Signal names cannot begin with an upper case letter")); - if (enginePrivate->v8engine()->illegalNames().contains(nameStr)) + if (enginePrivate->v8engine()->illegalNames().contains(currSig.name)) COMPILE_EXCEPTION(&currSig, tr("Illegal signal name")); - methodNames.insert(name); } - for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) { - const QDeclarativeParser::Object::DynamicSlot &currSlot = obj->dynamicSlots.at(ii); - QByteArray name = currSlot.name; - if (methodNames.contains(name)) - COMPILE_EXCEPTION(&currSlot, tr("Duplicate method name")); - QString nameStr = QString::fromUtf8(name); - if (nameStr.at(0).isUpper()) + + for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) { + const QDeclarativeScript::Object::DynamicSlot &currSlot = *s; + + if (methodNames.testAndSet(currSlot.name.hash())) { + for (Object::DynamicSignal *s2 = obj->dynamicSignals.first(); s2; + s2 = obj->dynamicSignals.next(s2)) { + if (s2->name == currSlot.name) + COMPILE_EXCEPTION(&currSlot, tr("Duplicate method name")); + } + for (Object::DynamicSlot *s2 = obj->dynamicSlots.first(); s2 != s; + s2 = obj->dynamicSlots.next(s2)) { + if (s2->name == currSlot.name) + COMPILE_EXCEPTION(&currSlot, tr("Duplicate method name")); + } + } + + if (currSlot.name.at(0).isUpper()) COMPILE_EXCEPTION(&currSlot, tr("Method names cannot begin with an upper case letter")); - if (enginePrivate->v8engine()->illegalNames().contains(nameStr)) + if (enginePrivate->v8engine()->illegalNames().contains(currSlot.name)) COMPILE_EXCEPTION(&currSlot, tr("Illegal method name")); - methodNames.insert(name); } return true; @@ -2485,7 +2500,7 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, Dyn int lastSlash = path.lastIndexOf(QLatin1Char('/')); if (lastSlash > -1) { QString nameBase = path.mid(lastSlash + 1, path.length()-lastSlash-5); - if (!nameBase.isEmpty() && nameBase.at(0).isUpper()) + if (!nameBase.isEmpty() && QDeclarativeUtils::isUpper(nameBase.at(0))) newClassName = nameBase.toUtf8() + "_QMLTYPE_" + QByteArray::number(idx); } } @@ -2704,18 +2719,18 @@ bool QDeclarativeCompiler::checkValidId(QDeclarativeParser::Value *v, const QStr if (val.isEmpty()) COMPILE_EXCEPTION(v, tr( "Invalid empty ID")); - if (val.at(0).isLetter() && !val.at(0).isLower()) + QChar ch = val.at(0); + if (QDeclarativeUtils::isLetter(ch) && !QDeclarativeUtils::isLower(ch)) COMPILE_EXCEPTION(v, tr( "IDs cannot start with an uppercase letter")); QChar u(QLatin1Char('_')); - for (int ii = 0; ii < val.count(); ++ii) { + if (!QDeclarativeUtils::isLetter(ch) && ch != u) + COMPILE_EXCEPTION(v, tr( "IDs must start with a letter or underscore")); - if (ii == 0 && !val.at(ii).isLetter() && val.at(ii) != u) { - COMPILE_EXCEPTION(v, tr( "IDs must start with a letter or underscore")); - } else if (ii != 0 && !val.at(ii).isLetterOrNumber() && val.at(ii) != u) { + for (int ii = 1; ii < val.count(); ++ii) { + ch = val.at(ii); + if (!QDeclarativeUtils::isLetterOrNumber(ch) && ch != u) COMPILE_EXCEPTION(v, tr( "IDs must contain only letters, numbers, and underscores")); - } - } if (enginePrivate->v8engine()->illegalNames().contains(val)) diff --git a/src/declarative/qml/qdeclarativedirparser.cpp b/src/declarative/qml/qdeclarativedirparser.cpp index 6798870..1008d39 100644 --- a/src/declarative/qml/qdeclarativedirparser.cpp +++ b/src/declarative/qml/qdeclarativedirparser.cpp @@ -42,6 +42,7 @@ #include "private/qdeclarativedirparser_p.h" #include "qdeclarativeerror.h" #include +#include #include #include @@ -140,9 +141,9 @@ bool QDeclarativeDirParser::parse() while (index != length) { const QChar ch = line.at(index); - if (ch.isSpace()) { + if (QDeclarativeUtils::isSpace(ch)) { do { ++index; } - while (index != length && line.at(index).isSpace()); + while (index != length && QDeclarativeUtils::isSpace(line.at(index))); } else if (ch == QLatin1Char('#')) { // recognized a comment @@ -152,7 +153,7 @@ bool QDeclarativeDirParser::parse() const int start = index; do { ++index; } - while (index != length && !line.at(index).isSpace()); + while (index != length && !QDeclarativeUtils::isSpace(line.at(index))); const QString lexeme = line.mid(start, index - start); diff --git a/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp b/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp index 9e66ff4..1b8abba 100644 --- a/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp +++ b/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp @@ -44,6 +44,7 @@ #include // For AnchorLine #include +#include DEFINE_BOOL_CONFIG_OPTION(qmlVerboseCompiler, QML_VERBOSE_COMPILER) @@ -587,7 +588,7 @@ bool QDeclarativeV4IRBuilder::visit(AST::FieldMemberExpression *ast) break; case IR::Name::AttachType: - if (name.at(0).isUpper()) { + if (QDeclarativeUtils::isUpper(name.at(0))) { QByteArray utf8Name = name.toUtf8(); const char *enumName = utf8Name.constData();