diff options
Diffstat (limited to 'src/xmlpatterns/data/qderivedstring_p.h')
-rw-r--r-- | src/xmlpatterns/data/qderivedstring_p.h | 341 |
1 files changed, 341 insertions, 0 deletions
diff --git a/src/xmlpatterns/data/qderivedstring_p.h b/src/xmlpatterns/data/qderivedstring_p.h new file mode 100644 index 0000000..a9d4f16 --- /dev/null +++ b/src/xmlpatterns/data/qderivedstring_p.h @@ -0,0 +1,341 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef Patternist_DerivedString_H +#define Patternist_DerivedString_H + +#include <QRegExp> + +#include "private/qxmlutils_p.h" +#include "qbuiltintypes_p.h" +#include "qpatternistlocale_p.h" +#include "qvalidationerror_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents instances of derived @c xs:string types, such as @c + * xs:normalizedString. + * + * Whitespace is a significant part for creating values from the lexical + * space. Of course the specification is tricky here. Here's some pointers: + * + * - From <a href="4.3.6.1 The whiteSpace Schema Component">XML Schema Part 2: Datatypes + * Second Edition, 4.3.6 whiteSpace</a>: + * "For all atomic datatypes other than string (and types + * derived by restriction from it) the value of whiteSpace is + * collapse and cannot be changed by a schema author; for string the + * value of whiteSpace is preserve; for any type derived by + * restriction from string the value of whiteSpace can be any of the + * three legal values." + * - From <a href="http://www.w3.org/TR/xmlschema-1/#d0e1654">XML Schema Part 1: Structures + * Second Edition, 3.1.4 White Space Normalization during Validation</a>: + * "[Definition:] The normalized value of an element or attribute + * information item is an initial value whose white space, if any, + * has been normalized according to the value of the whiteSpace facet of + * the simple type definition used in its validation." + * + * @author Frans Englich <fenglich@trolltech.com> + * @ingroup Patternist_xdm + * @todo Documentation is missing + */ + template<TypeOfDerivedString DerivedType> + class DerivedString : public AtomicValue + { + private: + static inline ItemType::Ptr itemType() + { + switch(DerivedType) + { + case TypeNormalizedString: return BuiltinTypes::xsNormalizedString; + case TypeToken: return BuiltinTypes::xsToken; + case TypeLanguage: return BuiltinTypes::xsLanguage; + case TypeNMTOKEN: return BuiltinTypes::xsNMTOKEN; + case TypeName: return BuiltinTypes::xsName; + case TypeNCName: return BuiltinTypes::xsNCName; + case TypeID: return BuiltinTypes::xsID; + case TypeIDREF: return BuiltinTypes::xsIDREF; + case TypeENTITY: return BuiltinTypes::xsENTITY; + case TypeString: return BuiltinTypes::xsString; + } + + Q_ASSERT_X(false, Q_FUNC_INFO, "This line is not supposed to be reached."); + return ItemType::Ptr(); + } + + const QString m_value; + + inline DerivedString(const QString &value) : m_value(value) + { + } + + /** + * @short This is an incomplete test for whether @p ch conforms to + * the XML 1.0 NameChar production. + */ + static inline bool isNameChar(const QChar &ch) + { + return ch.isLetter() || + ch.isDigit() || + ch == QLatin1Char('.') || + ch == QLatin1Char('-') || + ch == QLatin1Char('_') || + ch == QLatin1Char(':'); + } + + /** + * @returns @c true if @p input is a valid @c xs:Name. + * @see <a href="http://www.w3.org/TR/REC-xml/#NT-Name">Extensible + * Markup Language (XML) 1.0 (Fourth Edition), [5] Name</a> + */ + static inline bool isValidName(const QString &input) + { + if(input.isEmpty()) + return false; + + const QChar first(input.at(0)); + + if(first.isLetter() || + first == QLatin1Char('_') || + first == QLatin1Char(':')) + { + const int len = input.length(); + + if(len == 1) + return true; + + /* Since we've checked the first character above, we start at + * position 1. */ + for(int i = 1; i < len; ++i) + { + if(!isNameChar(input.at(i))) + return false; + } + + return true; + } + else + return false; + } + + /** + * @returns @c true if @p input conforms to the XML 1.0 @c Nmtoken product. + * + * @see <a + * href="http://www.w3.org/TR/2000/WD-xml-2e-20000814#NT-Nmtoken">Extensible + * Markup Language (XML) 1.0 (Second Edition), [7] Nmtoken</a> + */ + static inline bool isValidNMTOKEN(const QString &input) + { + const int len = input.length(); + + if(len == 0) + return false; + + for(int i = 0; i < len; ++i) + { + if(!isNameChar(input.at(i))) + return false; + } + + return true; + } + + /** + * @short Performs attribute value normalization as if @p input was not + * from a @c CDATA section. + * + * Each whitespace character in @p input that's not a space, such as tab + * or new line character, is replaced with a space. This algorithm + * differs from QString::simplified() in that it doesn't collapse + * subsequent whitespace characters to a single one, or remove trailing + * and leading space. + * + * @see <a href="http://www.w3.org/TR/REC-xml/#AVNormalize">Extensible + * Markup Language (XML) 1.0 (Second Edition), 3.3.3 [E70]Attribute-Value Normalization</a> + */ + static QString attributeNormalize(const QString &input) + { + QString retval(input); + const int len = retval.length(); + const QLatin1Char space(' '); + + for(int i = 0; i < len; ++i) + { + const QChar ati(retval.at(i)); + + if(ati.isSpace() && ati != space) + retval[i] = space; + } + + return retval; + } + + static AtomicValue::Ptr error(const NamePool::Ptr &np, const QString &invalidValue) + { + return ValidationError::createError(QString::fromLatin1("%1 is not a valid value for " + "type %2.").arg(formatData(invalidValue)) + .arg(formatType(np, itemType()))); + } + + public: + + /** + * @note This function doesn't perform any cleanup/normalizaiton of @p + * value. @p value must be a canonical value space of the type. + * + * If you want cleanup to be performed and/or the lexical space + * checked, use fromLexical(). + */ + static AtomicValue::Ptr fromValue(const QString &value) + { + return AtomicValue::Ptr(new DerivedString(value)); + } + + /** + * Constructs an instance from the lexical + * representation @p lexical. + */ + static AtomicValue::Ptr fromLexical(const NamePool::Ptr &np, const QString &lexical) + { + switch(DerivedType) + { + case TypeString: + return AtomicValue::Ptr(new DerivedString(lexical)); + case TypeNormalizedString: + return AtomicValue::Ptr(new DerivedString(attributeNormalize(lexical))); + case TypeToken: + return AtomicValue::Ptr(new DerivedString(lexical.simplified())); + case TypeLanguage: + { + const QString simplified(lexical.trimmed()); + + const QRegExp validate(QLatin1String("[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*")); + Q_ASSERT(validate.isValid()); + + if(validate.exactMatch(simplified)) + return AtomicValue::Ptr(new DerivedString(lexical.simplified())); + else + return error(np, simplified); + } + case TypeNMTOKEN: + { + const QString trimmed(lexical.trimmed()); + + if(isValidNMTOKEN(trimmed)) + return AtomicValue::Ptr(new DerivedString(trimmed)); + else + return error(np, trimmed); + } + case TypeName: + { + const QString simplified(lexical.simplified()); + + if(isValidName(simplified)) + return AtomicValue::Ptr(new DerivedString(simplified)); + else + return error(np, simplified); + } + case TypeID: + /* Fallthrough. */ + case TypeIDREF: + /* Fallthrough. */ + case TypeENTITY: + /* Fallthrough. */ + case TypeNCName: + { + /* We treat xs:ID, xs:ENTITY, xs:IDREF and xs:NCName in the exact same + * way, except for the type annotation. + * + * We use trimmed() instead of simplified() because it's + * faster and whitespace isn't allowed between + * non-whitespace characters anyway, for these types. */ + const QString trimmed(lexical.trimmed()); + + if(QXmlUtils::isNCName(trimmed)) + return AtomicValue::Ptr(new DerivedString(trimmed)); + else + return error(np, trimmed); + } + default: + { + Q_ASSERT_X(false, Q_FUNC_INFO, "This line is not supposed to be reached."); + return AtomicValue::Ptr(); + } + } + } + + virtual QString stringValue() const + { + return m_value; + } + + virtual bool evaluateEBV(const QExplicitlySharedDataPointer<DynamicContext> &) const + { + return m_value.length() > 0; + } + + virtual ItemType::Ptr type() const + { + return itemType(); + } + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif |