1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
7 ** This file is part of the QtXmlPatterns module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
46 // This file is not part of the Qt API. It exists purely as an
47 // implementation detail. This header file may change from version to
48 // version without notice, or even be removed.
52 #ifndef Patternist_NamePool_H
53 #define Patternist_NamePool_H
56 #include <QReadLocker>
57 #include <QReadWriteLock>
58 #include <QSharedData>
63 #include <QtXmlPatterns/private/qprimitives_p.h>
72 * @short Store names such as namespace bindings and QNames and allows them to
73 * be referenced in efficient ways.
75 * Once a string have been inserted it stays there and cannot be removed. The
76 * only way to deallocate any string in the NamePool is to deallocate the
77 * NamePool itself, as a whole.
79 * This class is not only reentrant, it is thread-safe in all sense of the
80 * word. All functions of this class can be called concurrently. This is
81 * achieved by internal locking.
83 * @author Frans Englich <frans.englich@nokia.com>
84 * @todo Use QSubStrings, we can save very many heap allocations by that.
87 class Q_AUTOTEST_EXPORT NamePool : public QSharedData
90 typedef QExplicitlySharedDataPointer<NamePool> Ptr;
93 friend class StandardNamespaces;
99 * This must be identical to the amount of members in
100 * StandardNamespaces.
102 StandardNamespaceCount = 11,
103 StandardPrefixCount = 9,
104 StandardLocalNameCount = 141
107 QVector<QString> m_prefixes;
108 QVector<QString> m_namespaces;
109 QVector<QString> m_localNames;
112 * This hash contains no essential data, but speeds up
113 * finding a prefix in m_prefixes by mapping a prefix(the key) to
114 * the index into m_prefixes(which the value is).
116 * In other words, one can skip this variable at the cost of having
117 * to linearly loop over prefixes, in order to find the entry.
119 QHash<QString, QXmlName::PrefixCode> m_prefixMapping;
122 * Same as m_prefixMapping but applies for URIs, and hence m_namespaces instead
125 QHash<QString, QXmlName::NamespaceCode> m_namespaceMapping;
127 QHash<QString, QXmlName::LocalNameCode> m_localNameMapping;
129 enum DefaultCapacities
131 DefaultPrefixCapacity = 10,
132 DefaultURICapacity = DefaultPrefixCapacity,
134 * It looks like it's quite common with 40-60 different local names per XML
135 * vocabulary. For background, see:
137 * - http://englich.wordpress.com/2007/01/11/representing-xml/
138 * - http://englich.wordpress.com/2007/01/09/xmlstat/
140 DefaultLocalNameCapacity = 60
147 * @short Allocates a namespace binding for @p prefix and @p uri.
149 * In the returned QXmlName, the local name is
150 * StandardLocalNames::empty, and QXmlName::prefix() and
151 * QXmlName::namespaceUri() returns @p prefix and @p uri, respectively.
153 * In older versions of this code, the class NamespaceBinding existed,
154 * but as part of having the public class QXmlName, it was dropped and
155 * a special interpretation/convention involving use of QXmlName was
158 QXmlName allocateBinding(const QString &prefix, const QString &uri);
160 QXmlName allocateQName(const QString &uri, const QString &localName, const QString &prefix = QString());
162 inline QXmlName allocateQName(const QXmlName::NamespaceCode uri, const QString &ln)
164 /* We don't lock here, but we do in allocateLocalName(). */
165 return QXmlName(uri, allocateLocalName(ln));
168 inline const QString &stringForLocalName(const QXmlName::LocalNameCode code) const
170 const QReadLocker l(&lock);
171 return m_localNames.at(code);
174 inline const QString &stringForPrefix(const QXmlName::PrefixCode code) const
176 const QReadLocker l(&lock);
177 return m_prefixes.at(code);
180 inline const QString &stringForNamespace(const QXmlName::NamespaceCode code) const
182 const QReadLocker l(&lock);
183 return m_namespaces.at(code);
186 QString displayName(const QXmlName qName) const;
188 inline QString toLexical(const QXmlName qName) const
190 const QReadLocker l(&lock);
191 Q_ASSERT_X(!qName.isNull(), "", "It makes no sense to call toLexical() on a null name.");
193 if(qName.hasPrefix())
195 const QString &p = m_prefixes.at(qName.prefix());
196 return p + QLatin1Char(':') + m_localNames.at(qName.localName());
199 return m_localNames.at(qName.localName());
202 inline QXmlName::NamespaceCode allocateNamespace(const QString &uri)
204 const QWriteLocker l(&lock);
205 return unlockedAllocateNamespace(uri);
208 inline QXmlName::LocalNameCode allocateLocalName(const QString &ln)
210 const QWriteLocker l(&lock);
211 return unlockedAllocateLocalName(ln);
214 inline QXmlName::PrefixCode allocatePrefix(const QString &prefix)
216 const QWriteLocker l(&lock);
217 return unlockedAllocatePrefix(prefix);
220 QString toClarkName(const QXmlName &name) const;
221 QXmlName fromClarkName(const QString &clarkName);
225 * @note This function can not be called concurrently.
227 QXmlName::NamespaceCode unlockedAllocateNamespace(const QString &uri);
230 * @note This function can not be called concurrently.
232 QXmlName::LocalNameCode unlockedAllocateLocalName(const QString &ln);
235 * It's assumed that @p prefix is a valid @c NCName.
237 * @note This function can not be called concurrently.
239 QXmlName::PrefixCode unlockedAllocatePrefix(const QString &prefix);
241 Q_DISABLE_COPY(NamePool)
244 * @note This function can not be called concurrently.
246 const QString &displayPrefix(const QXmlName::NamespaceCode nc) const;
248 mutable QReadWriteLock lock;
252 * @short Formats QName.
256 static inline QString formatKeyword(const NamePool::Ptr &np, const QXmlName name)
258 return QLatin1String("<span class='XQuery-keyword'>") +
259 escape(np->displayName(name)) +
260 QLatin1String("</span>");
264 * @see NamespaceResolver::Constants
266 class StandardNamespaces
272 * This does not mean empty in the sense of "empty", but
273 * in the sense of an empty string, "".
275 * Its value, zero, is significant.
286 * @short A special value that when passed as the namespace part
287 * to NamespaceResolver::addBinding(), undeclares the prefix.
289 * This is used by the namespace prolog declaration.
291 * A dummy value is added to the name pool.
296 * Signals that a node shouldn't inherit namespaces from its parent. Must be used
297 * with StandardPrefixes::StopNamespaceInheritance.
299 StopNamespaceInheritance,
302 * A namespace used to identify for instance @c \#all template
309 // const QString * a = &*qset.insert("foo");
310 class StandardLocalNames
316 adjust_dateTime_to_timezone,
317 adjust_date_to_timezone,
318 adjust_time_to_timezone,
327 codepoints_to_string,
379 local_name_from_QName,
384 minutes_from_dateTime,
385 minutes_from_duration,
389 months_from_duration,
392 namespace_uri_for_prefix,
393 namespace_uri_from_QName,
415 seconds_from_dateTime,
416 seconds_from_duration,
424 string_to_codepoints,
430 supports_backwards_compatibility,
431 supports_serialization,
434 timezone_from_dateTime,
442 unparsed_entity_public_id,
445 unparsed_text_available,
459 class StandardPrefixes
465 * This does not mean empty in the sense of "empty", but
466 * in the sense of an empty string, "".
468 * Its value, zero, is significant.
478 StopNamespaceInheritance
483 inline QXmlName::LocalNameCode QXmlName::localName() const
485 return (m_qNameCode & LocalNameMask) >> LocalNameOffset;
488 inline QXmlName::PrefixCode QXmlName::prefix() const
490 return (m_qNameCode & PrefixMask) >> PrefixOffset;
493 inline bool QXmlName::hasPrefix() const
495 return prefix() != 0;
498 inline bool QXmlName::hasNamespace() const
500 return namespaceURI() != 0;
503 inline QXmlName::NamespaceCode QXmlName::namespaceURI() const
505 return (m_qNameCode & NamespaceMask) >> NamespaceOffset;
508 inline bool QXmlName::isLexicallyEqual(const QXmlName &other) const
510 return (m_qNameCode & LexicalQNameMask) == (other.m_qNameCode & LexicalQNameMask);
513 inline void QXmlName::setPrefix(const PrefixCode c)
515 m_qNameCode |= (c << PrefixOffset);
518 inline void QXmlName::setNamespaceURI(const NamespaceCode c)
520 m_qNameCode |= (c << NamespaceOffset);
523 inline void QXmlName::setLocalName(const LocalNameCode c)
525 m_qNameCode |= (c << LocalNameOffset);
528 inline QXmlName::Code QXmlName::code() const
533 inline QXmlName::QXmlName(const NamespaceCode uri,
534 const LocalNameCode ln,
535 const PrefixCode p) : m_qNameCode((uri << NamespaceOffset) +
536 (ln << LocalNameOffset) +
539 /* We can't use members like prefix() here because if one of the
540 * values are to large, they would overflow into the others. */
541 Q_ASSERT_X(p <= MaximumPrefixes, "",
542 qPrintable(QString::fromLatin1("NamePool prefix limits: max is %1, therefore %2 exceeds.").arg(MaximumPrefixes).arg(p)));
543 Q_ASSERT_X(ln <= MaximumLocalNames, "",
544 qPrintable(QString::fromLatin1("NamePool local name limits: max is %1, therefore %2 exceeds.").arg(MaximumLocalNames).arg(ln)));
545 Q_ASSERT_X(uri <= MaximumNamespaces, "",
546 qPrintable(QString::fromLatin1("NamePool namespace limits: max is %1, therefore %2 exceeds.").arg(MaximumNamespaces).arg(uri)));
550 Q_DECLARE_TYPEINFO(QPatternist::NamePool::Ptr, Q_MOVABLE_TYPE);