1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtXmlPatterns module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
44 #include "qcompressedwhitespace_p.h"
48 using namespace QPatternist;
50 CompressedWhitespace::CharIdentifier CompressedWhitespace::toIdentifier(const QChar ch)
64 Q_ASSERT_X(false, Q_FUNC_INFO,
65 "The caller must guarantee only whitespace is passed.");
71 bool CompressedWhitespace::isEven(const int number)
73 Q_ASSERT(number >= 0);
74 return number % 2 == 0;
77 quint8 CompressedWhitespace::toCompressedChar(const QChar ch, const int len)
80 Q_ASSERT(len <= MaxCharCount);
82 return len + toIdentifier(ch);
85 QChar CompressedWhitespace::toChar(const CharIdentifier id)
89 case Space: return QLatin1Char(' ');
90 case CR: return QLatin1Char('\r');
91 case LF: return QLatin1Char('\n');
92 case Tab: return QLatin1Char('\t');
95 Q_ASSERT_X(false, Q_FUNC_INFO, "Unexpected input");
101 QString CompressedWhitespace::compress(const QStringRef &input)
103 Q_ASSERT(!isEven(1) && isEven(0) && isEven(2));
104 Q_ASSERT(!input.isEmpty());
107 const int len = input.length();
109 /* The amount of compressed characters. For instance, if input is
110 * four spaces followed by one tab, compressedChars will be 2, and the resulting
111 * QString will have a length of 1, two compressedChars stored in one QChar. */
112 int compressedChars = 0;
114 for(int i = 0; i < len; ++i)
116 const QChar c(input.at(i));
122 if(i + 1 == input.length() || input.at(i + 1) != c)
128 /* The length of subsequent whitespace characters in the input. */
129 int wsLen = (i - start) + 1;
131 /* We might get a sequence of whitespace that is so long, that we can't
132 * store it in one unit/byte. In that case we chop it into as many subsequent
133 * ones that is needed. */
136 const int unitLength = qMin(wsLen, int(MaxCharCount));
139 ushort resultCP = toCompressedChar(c, unitLength);
141 if(isEven(compressedChars))
142 result += QChar(resultCP);
145 resultCP = resultCP << 8;
146 resultCP |= result.at(result.size() - 1).unicode();
147 result[result.size() - 1] = resultCP;
160 QString CompressedWhitespace::decompress(const QString &input)
162 Q_ASSERT(!input.isEmpty());
163 const int len = input.length() * 2;
166 for(int i = 0; i < len; ++i)
168 ushort cp = input.at(i / 2).unicode();
180 const quint8 wsLen = cp & Lower6Bits;
181 const quint8 id = cp & UpperTwoBits;
183 /* Resize retval, and fill in on the top. */
184 const int oldSize = retval.size();
185 const int newSize = retval.size() + wsLen;
186 retval.resize(newSize);
187 const QChar ch(toChar(CharIdentifier(id)));
189 for(int f = oldSize; f < newSize; ++f)