1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtXmlPatterns module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include <QtGlobal>
41
42#include "qbase64binary_p.h"
43#include "qbuiltintypes_p.h"
44#include "qpatternistlocale_p.h"
45#include "qvalidationerror_p.h"
46
47#include "qhexbinary_p.h"
48
49QT_BEGIN_NAMESPACE
50
51using namespace QPatternist;
52
53HexBinary::HexBinary(const QByteArray &val) : Base64Binary(val)
54{
55}
56
57qint8 HexBinary::fromHex(const QChar &c)
58{
59 if(c.unicode() > 'f')
60 return -1;
61
62 const char *const range = "0123456789ABCDEFabcdef";
63
64 const char *const in = strchr(s: range, c: c.unicode());
65
66 if(!in)
67 return -1;
68
69 /* Pointer arithmetic. */
70 int digit = in - range;
71
72 if(digit > 15)
73 digit -= 6;
74
75 return digit;
76}
77
78AtomicValue::Ptr HexBinary::fromLexical(const NamePool::Ptr &np, const QString &str)
79{
80 const QString lexical(str.trimmed());
81 const int len = lexical.length();
82
83 if(len == 0)
84 return AtomicValue::Ptr(new HexBinary(QByteArray()));
85
86 if((len & 1) != 0)
87 {
88 /* Catch a common case. */
89 return ValidationError::createError(description: QtXmlPatterns::tr(
90 sourceText: "A value of type %1 must contain an even number of "
91 "digits. The value %2 does not.")
92 .arg(args: formatType(np, type: BuiltinTypes::xsHexBinary),
93 args: formatData(data: QString::number(len))));
94 }
95
96 QByteArray val;
97 val.resize(size: len / 2);
98
99 for(int i = 0; i < len / 2; ++i)
100 {
101 qint8 p1 = fromHex(c: lexical[i * 2]);
102 qint8 p2 = fromHex(c: lexical[i * 2 + 1]);
103
104 if(p1 == -1 || p2 == -1)
105 {
106 const QString hex(QString::fromLatin1(str: "%1%2").arg(args: lexical[i * 2], args: lexical[i * 2 + 1]));
107
108 return ValidationError::createError(description: QtXmlPatterns::tr(
109 sourceText: "%1 is not valid as a value of type %2.")
110 .arg(args: formatData(data: hex),
111 args: formatType(np, type: BuiltinTypes::xsHexBinary)));
112 }
113
114 val[i] = static_cast<char>(p1 * 16 + p2);
115 }
116 Q_ASSERT(!val.isEmpty());
117
118 return AtomicValue::Ptr(new HexBinary(val));
119}
120
121HexBinary::Ptr HexBinary::fromValue(const QByteArray &data)
122{
123 return HexBinary::Ptr(new HexBinary(data));
124}
125
126QString HexBinary::stringValue() const
127{
128 static const char s_toHex[] = "0123456789ABCDEF";
129 const int len = m_value.count();
130 QString result;
131 result.reserve(asize: len * 2);
132
133 for(int i = 0; i < len; ++i)
134 {
135 // This cast is significant.
136 const unsigned char val = static_cast<unsigned char>(m_value.at(i));
137 result += QLatin1Char(s_toHex[val >> 4]);
138 result += QLatin1Char(s_toHex[val & 0x0F]);
139 }
140
141 return result;
142}
143
144ItemType::Ptr HexBinary::type() const
145{
146 return BuiltinTypes::xsHexBinary;
147}
148
149QT_END_NAMESPACE
150

source code of qtxmlpatterns/src/xmlpatterns/data/qhexbinary.cpp