diff options
Diffstat (limited to 'tools/linguist/shared/proitems.cpp')
-rw-r--r-- | tools/linguist/shared/proitems.cpp | 485 |
1 files changed, 246 insertions, 239 deletions
diff --git a/tools/linguist/shared/proitems.cpp b/tools/linguist/shared/proitems.cpp index 5c88686..0b65126 100644 --- a/tools/linguist/shared/proitems.cpp +++ b/tools/linguist/shared/proitems.cpp @@ -1,358 +1,365 @@ -/**************************************************************************** +/************************************************************************** ** -** 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 Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (info@qt.nokia.com) ** -** This file is part of the Qt Linguist 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: +** 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. ** +** If you have questions regarding the use of this file, please contact +** Nokia at info@qt.nokia.com. ** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +**************************************************************************/ #include "proitems.h" -#include "abstractproitemvisitor.h" #include <QtCore/QFileInfo> +#include <QtCore/QSet> QT_BEGIN_NAMESPACE -// --------------- ProItem ------------ -void ProItem::setComment(const QString &comment) -{ - m_comment = comment; -} - -QString ProItem::comment() const -{ - return m_comment; -} - -// --------------- ProBlock ---------------- - -ProBlock::ProBlock(ProBlock *parent) -{ - m_blockKind = 0; - m_parent = parent; - m_refCount = 1; -} - -ProBlock::~ProBlock() -{ - foreach (ProItem *itm, m_proitems) - if (itm->kind() == BlockKind) - static_cast<ProBlock *>(itm)->deref(); - else - delete itm; -} - -void ProBlock::appendItem(ProItem *proitem) -{ - m_proitems << proitem; -} - -void ProBlock::setItems(const QList<ProItem *> &proitems) -{ - m_proitems = proitems; -} - -QList<ProItem *> ProBlock::items() const -{ - return m_proitems; -} - -void ProBlock::setBlockKind(int blockKind) -{ - m_blockKind = blockKind; -} +using namespace ProStringConstants; -int ProBlock::blockKind() const +// from qhash.cpp +uint ProString::hash(const QChar *p, int n) { - return m_blockKind; -} + uint h = 0; -void ProBlock::setParent(ProBlock *parent) -{ - m_parent = parent; + while (n--) { + h = (h << 4) + (*p++).unicode(); + h ^= (h & 0xf0000000) >> 23; + h &= 0x0fffffff; + } + return h; } -ProBlock *ProBlock::parent() const +ProString::ProString() : + m_offset(0), m_length(0), m_file(0), m_hash(0x80000000) { - return m_parent; } -ProItem::ProItemKind ProBlock::kind() const +ProString::ProString(const ProString &other) : + m_string(other.m_string), m_offset(other.m_offset), m_length(other.m_length), m_file(other.m_file), m_hash(other.m_hash) { - return ProItem::BlockKind; } -ProItem::ProItemReturn ProBlock::Accept(AbstractProItemVisitor *visitor) +ProString::ProString(const ProString &other, OmitPreHashing) : + m_string(other.m_string), m_offset(other.m_offset), m_length(other.m_length), m_file(other.m_file), m_hash(0x80000000) { - if (visitor->visitBeginProBlock(this) == ReturnSkip) - return ReturnTrue; - ProItemReturn rt = ReturnTrue; - for (int i = 0; i < m_proitems.count(); ++i) { - rt = m_proitems.at(i)->Accept(visitor); - if (rt != ReturnTrue && rt != ReturnFalse) { - if (rt == ReturnLoop) { - rt = ReturnTrue; - while (visitor->visitProLoopIteration()) - for (int j = i; ++j < m_proitems.count(); ) { - rt = m_proitems.at(j)->Accept(visitor); - if (rt != ReturnTrue && rt != ReturnFalse) { - if (rt == ReturnNext) { - rt = ReturnTrue; - break; - } - if (rt == ReturnBreak) - rt = ReturnTrue; - goto do_break; - } - } - do_break: - visitor->visitProLoopCleanup(); - } - break; - } - } - visitor->visitEndProBlock(this); - return rt; } -// --------------- ProVariable ---------------- -ProVariable::ProVariable(const QString &name, ProBlock *parent) - : ProBlock(parent) +ProString::ProString(const QString &str) : + m_string(str), m_offset(0), m_length(str.length()), m_file(0) { - setBlockKind(ProBlock::VariableKind); - m_variable = name; - m_variableKind = SetOperator; + updatedHash(); } -void ProVariable::setVariableOperator(VariableOperator variableKind) +ProString::ProString(const QString &str, OmitPreHashing) : + m_string(str), m_offset(0), m_length(str.length()), m_file(0), m_hash(0x80000000) { - m_variableKind = variableKind; } -ProVariable::VariableOperator ProVariable::variableOperator() const +ProString::ProString(const char *str) : + m_string(QString::fromLatin1(str)), m_offset(0), m_length(qstrlen(str)), m_file(0) { - return m_variableKind; + updatedHash(); } -void ProVariable::setVariable(const QString &name) +ProString::ProString(const char *str, OmitPreHashing) : + m_string(QString::fromLatin1(str)), m_offset(0), m_length(qstrlen(str)), m_file(0), m_hash(0x80000000) { - m_variable = name; } -QString ProVariable::variable() const +ProString::ProString(const QString &str, int offset, int length) : + m_string(str), m_offset(offset), m_length(length), m_file(0) { - return m_variable; + updatedHash(); } -ProItem::ProItemReturn ProVariable::Accept(AbstractProItemVisitor *visitor) +ProString::ProString(const QString &str, int offset, int length, uint hash) : + m_string(str), m_offset(offset), m_length(length), m_file(0), m_hash(hash) { - visitor->visitBeginProVariable(this); - foreach (ProItem *item, m_proitems) - item->Accept(visitor); // cannot fail - visitor->visitEndProVariable(this); - return ReturnTrue; } -// --------------- ProValue ---------------- -ProValue::ProValue(const QString &value, ProVariable *variable) +ProString::ProString(const QString &str, int offset, int length, ProStringConstants::OmitPreHashing) : + m_string(str), m_offset(offset), m_length(length), m_file(0), m_hash(0x80000000) { - m_variable = variable; - m_value = value; } -void ProValue::setValue(const QString &value) +void ProString::setValue(const QString &str) { - m_value = value; + m_string = str, m_offset = 0, m_length = str.length(); + updatedHash(); } -QString ProValue::value() const +void ProString::setValue(const QString &str, OmitPreHashing) { - return m_value; + m_string = str, m_offset = 0, m_length = str.length(), m_hash = 0x80000000; } -void ProValue::setVariable(ProVariable *variable) +uint ProString::updatedHash() const { - m_variable = variable; + return (m_hash = hash(m_string.constData() + m_offset, m_length)); } -ProVariable *ProValue::variable() const +uint qHash(const ProString &str) { - return m_variable; + if (!(str.m_hash & 0x80000000)) + return str.m_hash; + return str.updatedHash(); } -ProItem::ProItemKind ProValue::kind() const +QString ProString::toQString() const { - return ProItem::ValueKind; + return m_string.mid(m_offset, m_length); } -ProItem::ProItemReturn ProValue::Accept(AbstractProItemVisitor *visitor) +QString &ProString::toQString(QString &tmp) const { - visitor->visitProValue(this); - return ReturnTrue; + return tmp.setRawData(m_string.constData() + m_offset, m_length); } -// --------------- ProFunction ---------------- -ProFunction::ProFunction(const QString &text) +bool ProString::operator==(const ProString &other) const { - m_text = text; + if (m_length != other.m_length) + return false; + return !memcmp(m_string.constData() + m_offset, + other.m_string.constData() + other.m_offset, m_length * 2); } -void ProFunction::setText(const QString &text) +bool ProString::operator==(const QString &other) const { - m_text = text; + if (m_length != other.length()) + return false; + return !memcmp(m_string.constData() + m_offset, other.constData(), m_length * 2); } -QString ProFunction::text() const +bool ProString::operator==(const QLatin1String &other) const { - return m_text; -} + const ushort *uc = (ushort *)m_string.constData() + m_offset; + const ushort *e = uc + m_length; + const uchar *c = (uchar *)other.latin1(); -ProItem::ProItemKind ProFunction::kind() const -{ - return ProItem::FunctionKind; -} + if (!c) + return isEmpty(); -ProItem::ProItemReturn ProFunction::Accept(AbstractProItemVisitor *visitor) -{ - return visitor->visitProFunction(this); + while (*c) { + if (uc == e || *uc != *c) + return false; + ++uc; + ++c; + } + return (uc == e); +} + +QChar *ProString::prepareAppend(int extraLen) +{ + if (m_string.isDetached() && m_length + extraLen <= m_string.capacity()) { + m_string.reserve(0); // Prevent the resize() below from reallocating + QChar *ptr = (QChar *)m_string.constData(); + if (m_offset) + memmove(ptr, ptr + m_offset, m_length * 2); + ptr += m_length; + m_offset = 0; + m_length += extraLen; + m_string.resize(m_length); + m_hash = 0x80000000; + return ptr; + } else { + QString neu(m_length + extraLen, Qt::Uninitialized); + QChar *ptr = (QChar *)neu.constData(); + memcpy(ptr, m_string.constData() + m_offset, m_length * 2); + ptr += m_length; + *this = ProString(neu, NoHash); + return ptr; + } } -// --------------- ProCondition ---------------- -ProCondition::ProCondition(const QString &text) +// If pending != 0, prefix with space if appending to non-empty non-pending +ProString &ProString::append(const ProString &other, bool *pending) { - m_text = text; + if (other.m_length) { + if (!m_length) { + *this = other; + } else { + QChar *ptr; + if (pending && !*pending) { + ptr = prepareAppend(1 + other.m_length); + *ptr++ = 32; + } else { + ptr = prepareAppend(other.m_length); + } + memcpy(ptr, other.m_string.constData() + other.m_offset, other.m_length * 2); + if (other.m_file) + m_file = other.m_file; + } + if (pending) + *pending = true; + } + return *this; } -void ProCondition::setText(const QString &text) +ProString &ProString::append(const ProStringList &other, bool *pending, bool skipEmpty1st) { - m_text = text; + if (const int sz = other.size()) { + int startIdx = 0; + if (pending && !*pending && skipEmpty1st && other.at(0).isEmpty()) { + if (sz == 1) + return *this; + startIdx = 1; + } + if (!m_length && sz == startIdx + 1) { + *this = other.at(startIdx); + } else { + int totalLength = sz - startIdx; + for (int i = startIdx; i < sz; ++i) + totalLength += other.at(i).size(); + bool putSpace = false; + if (pending && !*pending && m_length) + putSpace = true; + else + totalLength--; + + QChar *ptr = prepareAppend(totalLength); + for (int i = startIdx; i < sz; ++i) { + if (putSpace) + *ptr++ = 32; + else + putSpace = true; + const ProString &str = other.at(i); + memcpy(ptr, str.m_string.constData() + str.m_offset, str.m_length * 2); + ptr += str.m_length; + } + if (other.last().m_file) + m_file = other.last().m_file; + } + if (pending) + *pending = true; + } + return *this; } -QString ProCondition::text() const +QString operator+(const ProString &one, const ProString &two) { - return m_text; + if (two.m_length) { + if (!one.m_length) { + return two.toQString(); + } else { + QString neu(one.m_length + two.m_length, Qt::Uninitialized); + ushort *ptr = (ushort *)neu.constData(); + memcpy(ptr, one.m_string.constData() + one.m_offset, one.m_length * 2); + memcpy(ptr + one.m_length, two.m_string.constData() + two.m_offset, two.m_length * 2); + return neu; + } + } + return one.toQString(); } -ProItem::ProItemKind ProCondition::kind() const -{ - return ProItem::ConditionKind; -} -ProItem::ProItemReturn ProCondition::Accept(AbstractProItemVisitor *visitor) +ProString ProString::mid(int off, int len) const { - visitor->visitProCondition(this); - return ReturnTrue; + ProString ret(*this, NoHash); + if (off > m_length) + off = m_length; + ret.m_offset += off; + ret.m_length -= off; + if (ret.m_length > len) + ret.m_length = len; + return ret; } -// --------------- ProOperator ---------------- -ProOperator::ProOperator(OperatorKind operatorKind) +ProString ProString::trimmed() const { - m_operatorKind = operatorKind; + ProString ret(*this, NoHash); + int cur = m_offset; + int end = cur + m_length; + const QChar *data = m_string.constData(); + for (; cur < end; cur++) + if (!data[cur].isSpace()) { + // No underrun check - we know there is at least one non-whitespace + while (data[end - 1].isSpace()) + end--; + break; + } + ret.m_offset = cur; + ret.m_length = end - cur; + return ret; } -void ProOperator::setOperatorKind(OperatorKind operatorKind) +QString ProStringList::join(const QString &sep) const { - m_operatorKind = operatorKind; -} + int totalLength = 0; + const int sz = size(); -ProOperator::OperatorKind ProOperator::operatorKind() const -{ - return m_operatorKind; -} + for (int i = 0; i < sz; ++i) + totalLength += at(i).size(); -ProItem::ProItemKind ProOperator::kind() const -{ - return ProItem::OperatorKind; -} + if (sz) + totalLength += sep.size() * (sz - 1); -ProItem::ProItemReturn ProOperator::Accept(AbstractProItemVisitor *visitor) -{ - visitor->visitProOperator(this); - return ReturnTrue; + QString res(totalLength, Qt::Uninitialized); + QChar *ptr = (QChar *)res.constData(); + for (int i = 0; i < sz; ++i) { + if (i) { + memcpy(ptr, sep.constData(), sep.size() * 2); + ptr += sep.size(); + } + memcpy(ptr, at(i).constData(), at(i).size() * 2); + ptr += at(i).size(); + } + return res; +} + +void ProStringList::removeDuplicates() +{ + int n = size(); + int j = 0; + QSet<ProString> seen; + seen.reserve(n); + for (int i = 0; i < n; ++i) { + const ProString &s = at(i); + if (seen.contains(s)) + continue; + seen.insert(s); + if (j != i) + (*this)[j] = s; + ++j; + } + if (n != j) + erase(begin() + j, end()); } -// --------------- ProFile ---------------- ProFile::ProFile(const QString &fileName) - : ProBlock(0) + : m_refCount(1), + m_fileName(fileName), + m_ok(true) { - m_modified = false; - setBlockKind(ProBlock::ProFileKind); - m_fileName = fileName; - - QFileInfo fi(fileName); - m_displayFileName = fi.fileName(); - m_directoryName = fi.absolutePath(); + if (!fileName.startsWith(QLatin1Char('('))) + m_directoryName = QFileInfo( // qmake sickness: canonicalize only the directory! + fileName.left(fileName.lastIndexOf(QLatin1Char('/')))).canonicalFilePath(); } ProFile::~ProFile() { } -QString ProFile::displayFileName() const -{ - return m_displayFileName; -} - -QString ProFile::fileName() const -{ - return m_fileName; -} - -QString ProFile::directoryName() const -{ - return m_directoryName; -} - -void ProFile::setModified(bool modified) -{ - m_modified = modified; -} - -bool ProFile::isModified() const -{ - return m_modified; -} - -ProItem::ProItemReturn ProFile::Accept(AbstractProItemVisitor *visitor) -{ - ProItemReturn rt; - if ((rt = visitor->visitBeginProFile(this)) != ReturnTrue) - return rt; - ProBlock::Accept(visitor); // cannot fail - return visitor->visitEndProFile(this); -} - QT_END_NAMESPACE |