source: trunk/src/xmlpatterns/utils/qnamepool_p.h

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 16.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtXmlPatterns module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42//
43// W A R N I N G
44// -------------
45//
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.
49//
50// We mean it.
51
52#ifndef Patternist_NamePool_H
53#define Patternist_NamePool_H
54
55#include <QHash>
56#include <QReadLocker>
57#include <QReadWriteLock>
58#include <QSharedData>
59#include <QString>
60#include <QVector>
61#include <QXmlName>
62
63#include <QtXmlPatterns/private/qprimitives_p.h>
64
65QT_BEGIN_HEADER
66
67QT_BEGIN_NAMESPACE
68
69namespace QPatternist
70{
71 /**
72 * @short Store names such as namespace bindings and QNames and allows them to
73 * be referenced in efficient ways.
74 *
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.
78 *
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.
82 *
83 * @author Frans Englich <[email protected]>
84 * @todo Use QSubStrings, we can save very many heap allocations by that.
85 * @todo Check limits
86 */
87 class Q_AUTOTEST_EXPORT NamePool : public QSharedData
88 {
89 public:
90 typedef QExplicitlySharedDataPointer<NamePool> Ptr;
91
92 private:
93 friend class StandardNamespaces;
94
95 enum
96 {
97 NoSuchValue = -1,
98 /**
99 * This must be identical to the amount of members in
100 * StandardNamespaces.
101 */
102 StandardNamespaceCount = 11,
103 StandardPrefixCount = 9,
104 StandardLocalNameCount = 141
105 };
106
107 QVector<QString> m_prefixes;
108 QVector<QString> m_namespaces;
109 QVector<QString> m_localNames;
110
111 /**
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).
115 *
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.
118 */
119 QHash<QString, QXmlName::PrefixCode> m_prefixMapping;
120
121 /**
122 * Same as m_prefixMapping but applies for URIs, and hence m_namespaces instead
123 * of m_prefixes.
124 */
125 QHash<QString, QXmlName::NamespaceCode> m_namespaceMapping;
126
127 QHash<QString, QXmlName::LocalNameCode> m_localNameMapping;
128
129 enum DefaultCapacities
130 {
131 DefaultPrefixCapacity = 10,
132 DefaultURICapacity = DefaultPrefixCapacity,
133 /**
134 * It looks like it's quite common with 40-60 different local names per XML
135 * vocabulary. For background, see:
136 *
137 * - http://englich.wordpress.com/2007/01/11/representing-xml/
138 * - http://englich.wordpress.com/2007/01/09/xmlstat/
139 */
140 DefaultLocalNameCapacity = 60
141 };
142
143 public:
144 NamePool();
145
146 /**
147 * @short Allocates a namespace binding for @p prefix and @p uri.
148 *
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.
152 *
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
156 * adopted.
157 */
158 QXmlName allocateBinding(const QString &prefix, const QString &uri);
159
160 QXmlName allocateQName(const QString &uri, const QString &localName, const QString &prefix = QString());
161
162 inline QXmlName allocateQName(const QXmlName::NamespaceCode uri, const QString &ln)
163 {
164 /* We don't lock here, but we do in allocateLocalName(). */
165 return QXmlName(uri, allocateLocalName(ln));
166 }
167
168 inline const QString &stringForLocalName(const QXmlName::LocalNameCode code) const
169 {
170 const QReadLocker l(&lock);
171 return m_localNames.at(code);
172 }
173
174 inline const QString &stringForPrefix(const QXmlName::PrefixCode code) const
175 {
176 const QReadLocker l(&lock);
177 return m_prefixes.at(code);
178 }
179
180 inline const QString &stringForNamespace(const QXmlName::NamespaceCode code) const
181 {
182 const QReadLocker l(&lock);
183 return m_namespaces.at(code);
184 }
185
186 QString displayName(const QXmlName qName) const;
187
188 inline QString toLexical(const QXmlName qName) const
189 {
190 const QReadLocker l(&lock);
191 Q_ASSERT_X(!qName.isNull(), "", "It makes no sense to call toLexical() on a null name.");
192
193 if(qName.hasPrefix())
194 {
195 const QString &p = m_prefixes.at(qName.prefix());
196 return p + QLatin1Char(':') + m_localNames.at(qName.localName());
197 }
198 else
199 return m_localNames.at(qName.localName());
200 }
201
202 inline QXmlName::NamespaceCode allocateNamespace(const QString &uri)
203 {
204 const QWriteLocker l(&lock);
205 return unlockedAllocateNamespace(uri);
206 }
207
208 inline QXmlName::LocalNameCode allocateLocalName(const QString &ln)
209 {
210 const QWriteLocker l(&lock);
211 return unlockedAllocateLocalName(ln);
212 }
213
214 inline QXmlName::PrefixCode allocatePrefix(const QString &prefix)
215 {
216 const QWriteLocker l(&lock);
217 return unlockedAllocatePrefix(prefix);
218 }
219
220 QString toClarkName(const QXmlName &name) const;
221 QXmlName fromClarkName(const QString &clarkName);
222
223 private:
224 /**
225 * @note This function can not be called concurrently.
226 */
227 QXmlName::NamespaceCode unlockedAllocateNamespace(const QString &uri);
228
229 /**
230 * @note This function can not be called concurrently.
231 */
232 QXmlName::LocalNameCode unlockedAllocateLocalName(const QString &ln);
233
234 /**
235 * It's assumed that @p prefix is a valid @c NCName.
236 *
237 * @note This function can not be called concurrently.
238 */
239 QXmlName::PrefixCode unlockedAllocatePrefix(const QString &prefix);
240
241 Q_DISABLE_COPY(NamePool)
242
243 /**
244 * @note This function can not be called concurrently.
245 */
246 const QString &displayPrefix(const QXmlName::NamespaceCode nc) const;
247
248 mutable QReadWriteLock lock;
249 };
250
251 /**
252 * @short Formats QName.
253 *
254 * @relates QXmlName
255 */
256 static inline QString formatKeyword(const NamePool::Ptr &np, const QXmlName name)
257 {
258 return QLatin1String("<span class='XQuery-keyword'>") +
259 escape(np->displayName(name)) +
260 QLatin1String("</span>");
261 }
262
263 /**
264 * @see NamespaceResolver::Constants
265 */
266 class StandardNamespaces
267 {
268 public:
269 enum ID
270 {
271 /**
272 * This does not mean empty in the sense of "empty", but
273 * in the sense of an empty string, "".
274 *
275 * Its value, zero, is significant.
276 */
277 empty = 0,
278 fn,
279 local,
280 xml,
281 xmlns,
282 xs,
283 xsi,
284 xslt,
285 /**
286 * @short A special value that when passed as the namespace part
287 * to NamespaceResolver::addBinding(), undeclares the prefix.
288 *
289 * This is used by the namespace prolog declaration.
290 *
291 * A dummy value is added to the name pool.
292 */
293 UndeclarePrefix,
294
295 /**
296 * Signals that a node shouldn't inherit namespaces from its parent. Must be used
297 * with StandardPrefixes::StopNamespaceInheritance.
298 */
299 StopNamespaceInheritance,
300
301 /**
302 * A namespace used to identify for instance @c \#all template
303 * mode in XSL-T.
304 */
305 InternalXSLT
306 };
307 };
308
309 // const QString * a = &*qset.insert("foo");
310 class StandardLocalNames
311 {
312 public:
313 enum
314 {
315 abs,
316 adjust_dateTime_to_timezone,
317 adjust_date_to_timezone,
318 adjust_time_to_timezone,
319 all,
320 arity,
321 avg,
322 base,
323 base_uri,
324 boolean,
325 ceiling,
326 codepoint_equal,
327 codepoints_to_string,
328 collection,
329 compare,
330 concat,
331 contains,
332 count,
333 current,
334 current_date,
335 current_dateTime,
336 current_time,
337 data,
338 dateTime,
339 day_from_date,
340 day_from_dateTime,
341 days_from_duration,
342 deep_equal,
343 Default,
344 default_collation,
345 distinct_values,
346 doc,
347 doc_available,
348 document,
349 document_uri,
350 element_available,
351 empty,
352 encode_for_uri,
353 ends_with,
354 error,
355 escape_html_uri,
356 exactly_one,
357 exists,
358 False,
359 floor,
360 function_available,
361 function_name,
362 generate_id,
363 generic_string_join,
364 hours_from_dateTime,
365 hours_from_duration,
366 hours_from_time,
367 id,
368 idref,
369 implicit_timezone,
370 index_of,
371 in_scope_prefixes,
372 insert_before,
373 iri_to_uri,
374 is_schema_aware,
375 key,
376 lang,
377 last,
378 local_name,
379 local_name_from_QName,
380 lower_case,
381 matches,
382 max,
383 min,
384 minutes_from_dateTime,
385 minutes_from_duration,
386 minutes_from_time,
387 month_from_date,
388 month_from_dateTime,
389 months_from_duration,
390 name,
391 namespace_uri,
392 namespace_uri_for_prefix,
393 namespace_uri_from_QName,
394 nilled,
395 node_name,
396 normalize_space,
397 normalize_unicode,
398 Not,
399 number,
400 one_or_more,
401 position,
402 prefix_from_QName,
403 product_name,
404 product_version,
405 property_name,
406 QName,
407 remove,
408 replace,
409 resolve_QName,
410 resolve_uri,
411 reverse,
412 root,
413 round,
414 round_half_to_even,
415 seconds_from_dateTime,
416 seconds_from_duration,
417 seconds_from_time,
418 sourceValue,
419 starts_with,
420 static_base_uri,
421 string,
422 string_join,
423 string_length,
424 string_to_codepoints,
425 subsequence,
426 substring,
427 substring_after,
428 substring_before,
429 sum,
430 supports_backwards_compatibility,
431 supports_serialization,
432 system_property,
433 timezone_from_date,
434 timezone_from_dateTime,
435 timezone_from_time,
436 tokenize,
437 trace,
438 translate,
439 True,
440 type_available,
441 unordered,
442 unparsed_entity_public_id,
443 unparsed_entity_uri,
444 unparsed_text,
445 unparsed_text_available,
446 upper_case,
447 vendor,
448 vendor_url,
449 version,
450 xml,
451 xmlns,
452 year_from_date,
453 year_from_dateTime,
454 years_from_duration,
455 zero_or_one
456 };
457 };
458
459 class StandardPrefixes
460 {
461 public:
462 enum
463 {
464 /**
465 * This does not mean empty in the sense of "empty", but
466 * in the sense of an empty string, "".
467 *
468 * Its value, zero, is significant.
469 */
470 empty = 0,
471 fn,
472 local,
473 xml,
474 xmlns,
475 xs,
476 xsi,
477 ns0,
478 StopNamespaceInheritance
479 };
480 };
481}
482
483inline QXmlName::LocalNameCode QXmlName::localName() const
484{
485 return (m_qNameCode & LocalNameMask) >> LocalNameOffset;
486}
487
488inline QXmlName::PrefixCode QXmlName::prefix() const
489{
490 return (m_qNameCode & PrefixMask) >> PrefixOffset;
491}
492
493inline bool QXmlName::hasPrefix() const
494{
495 return prefix() != 0;
496}
497
498inline bool QXmlName::hasNamespace() const
499{
500 return namespaceURI() != 0;
501}
502
503inline QXmlName::NamespaceCode QXmlName::namespaceURI() const
504{
505 return (m_qNameCode & NamespaceMask) >> NamespaceOffset;
506}
507
508inline bool QXmlName::isLexicallyEqual(const QXmlName &other) const
509{
510 return (m_qNameCode & LexicalQNameMask) == (other.m_qNameCode & LexicalQNameMask);
511}
512
513inline void QXmlName::setPrefix(const PrefixCode c)
514{
515 m_qNameCode |= (c << PrefixOffset);
516}
517
518inline void QXmlName::setNamespaceURI(const NamespaceCode c)
519{
520 m_qNameCode |= (c << NamespaceOffset);
521}
522
523inline void QXmlName::setLocalName(const LocalNameCode c)
524{
525 m_qNameCode |= (c << LocalNameOffset);
526}
527
528inline QXmlName::Code QXmlName::code() const
529{
530 return m_qNameCode;
531}
532
533inline QXmlName::QXmlName(const NamespaceCode uri,
534 const LocalNameCode ln,
535 const PrefixCode p) : m_qNameCode((uri << NamespaceOffset) +
536 (ln << LocalNameOffset) +
537 (p << PrefixOffset))
538{
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)));
547}
548
549
550Q_DECLARE_TYPEINFO(QPatternist::NamePool::Ptr, Q_MOVABLE_TYPE);
551
552QT_END_NAMESPACE
553
554QT_END_HEADER
555
556#endif
Note: See TracBrowser for help on using the repository browser.