1
/****************************************************************************
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4
** Contact: http://www.qt-project.org/legal
6
** This file is part of the QtVersit module of the Qt Toolkit.
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 Digia. For licensing terms and
14
** conditions see http://qt.digia.com/licensing. For further information
15
** use the contact form at http://qt.digia.com/contact-us.
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 2.1 as published by the Free Software
20
** Foundation and appearing in the file LICENSE.LGPL included in the
21
** packaging of this file. Please review the following information to
22
** ensure the GNU Lesser General Public License version 2.1 requirements
23
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25
** In addition, as a special exception, Digia gives you certain additional
26
** rights. These rights are described in the Digia Qt LGPL Exception
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29
** GNU General Public License Usage
30
** Alternatively, this file may be used under the terms of the GNU
31
** General Public License version 3.0 as published by the Free Software
32
** Foundation and appearing in the file LICENSE.GPL included in the
33
** packaging of this file. Please review the following information to
34
** ensure the GNU General Public License version 3.0 requirements will be
35
** met: http://www.gnu.org/copyleft/gpl.html.
40
****************************************************************************/
43
#ifndef QVERSITREADER_P_H
44
#define QVERSITREADER_P_H
50
// This file is not part of the Qt API. It exists purely as an
51
// implementation detail. This header file may change from version to
52
// version without notice, or even be removed.
57
#include <qversitreader.h>
58
#include <qversitdocument.h>
59
#include <qversitproperty.h>
60
#include "qversitutils_p.h"
69
#include <QScopedPointer>
72
#include <QWaitCondition>
80
QT_BEGIN_NAMESPACE_VERSIT
82
// The maximum number of bytes allowed to stay in memory after being read. The smaller this is,
83
// the more time spent moving bytes around. The larger it is, the more memory is wasted.
84
static const int MAX_OLD_BYTES_TO_KEEP = 8192;
87
* An LByteArray has a subset of QByteArray's interface, plus an efficient chopLeft function
89
* It stores a QByteArray internally, plus a marker of where it starts and where it ends.
94
LByteArray() : mStart(0), mEnd(0) {}
95
explicit LByteArray(const QByteArray& d) :mData(d), mStart(0), mEnd(d.size()) {}
96
LByteArray(const QByteArray& d, int start, int end) :mData(d), mStart(start), mEnd(end) {}
97
bool isEmpty() const {
98
return mEnd <= mStart;
100
char at(int i) const {
101
return mData.at(mStart + i);
103
QByteArray toByteArray() const {
104
return mData.mid(mStart, mEnd-mStart);
106
/* Removes \a n bytes from the start of the QByteArray. */
107
void chopLeft(int n) {
108
Q_ASSERT(size() >= n && n >= 0);
111
QByteArray left(int n) {
112
Q_ASSERT(size() >= n && n >= 0);
113
return mData.mid(mStart, n);
115
int indexOf(const QByteArray& needle) {
116
int index = mData.indexOf(needle, mStart) - mStart;
122
return mEnd - mStart;
124
const char* constData() const {
125
return mData.constData() + mStart;
127
bool contains(const QByteArray& ba) const {
128
int i = mData.indexOf(ba, mStart);
129
return i > 0 && i <= mEnd - ba.length();
131
bool endsWith(const QByteArray& ba) const {
132
// Loop backwards from ba and from mData (starting from index mEnd)
133
if (ba.size() > size())
135
return memcmp(mData.constData()+mEnd-ba.size(), ba.constData(), ba.size()) == 0;
137
LByteArray& operator=(const QByteArray& ba) {
143
bool operator==(const QByteArray& ba) {
144
return toByteArray() == ba;
146
bool operator!=(const QByteArray& ba) {
147
return toByteArray() != ba;
151
/* Clears the memory of bytes before the start marker */
153
if (mStart > MAX_OLD_BYTES_TO_KEEP && mEnd >= mStart) {
154
mData.remove(0, mStart);
159
void setBounds(int start, int end) {
166
friend class LineReader;
169
class Q_VERSIT_EXPORT LineReader
172
LineReader(QIODevice* device, QTextCodec* codec);
173
LineReader(QIODevice* device);
174
LineReader(QIODevice* device, QTextCodec* codec, int chunkSize);
176
void pushLine(const QByteArray& line);
177
int odometer() const;
179
QTextCodec* codec() const;
180
bool isCodecCertain() const;
181
bool isCodecUtf8Compatible() const;
182
void setCodecUtf8Incompatible();
183
LByteArray readLine();
186
void readOneLine(LByteArray* cursor);
187
bool tryReadLine(LByteArray* cursor, bool atEnd);
189
QIODevice* const mDevice;
191
bool mIsCodecCertain;
192
bool mIsCodecUtf8Compatible;
193
int mChunkSize; // How many bytes to read in one go.
194
QList<QByteArrayMatcher> mCrlfList;
195
QStack<QByteArray> mPushedLines; // Stores a lines that has been "pushed" in front by pushLine
201
class Q_VERSIT_EXPORT QVersitReaderPrivate : public QThread
205
public: // Constructors and destructor
206
QVersitReaderPrivate();
207
~QVersitReaderPrivate();
209
static QHash<QPair<QVersitDocument::VersitType,QString>, QVersitProperty::ValueType>*
211
void init(QVersitReader* reader);
214
void stateChanged(QVersitReader::State state);
215
void resultsAvailable();
217
protected: // From QThread
220
public: // New functions
223
// mutexed getters and setters.
224
void setState(QVersitReader::State);
225
QVersitReader::State state() const;
226
void setError(QVersitReader::Error);
227
QVersitReader::Error error() const;
228
void setCanceling(bool cancelling);
231
bool parseVersitDocument(LineReader* lineReader, QVersitDocument* document);
232
bool parseVersitDocumentBody(LineReader* lineReader, QVersitDocument* document);
234
QVersitProperty parseNextVersitProperty(
235
QVersitDocument::VersitType versitType,
236
LineReader* lineReader);
238
void parseVCard21Property(
240
QVersitProperty* property,
241
LineReader* lineReader);
243
void parseVCard30Property(
244
QVersitDocument::VersitType versitType,
246
QVersitProperty* property,
247
LineReader* lineReader);
249
bool setVersionFromProperty(
250
QVersitDocument* document,
251
const QVersitProperty& property) const;
255
QVersitProperty* property,
256
LineReader* lineReader) const;
258
QString decodeCharset(
259
const QByteArray& value,
260
QVersitProperty* property,
261
LineReader* lineReader,
262
QTextCodec** codec) const;
264
void decodeQuotedPrintable(QByteArray* text) const;
267
/* These functions operate on a cursor describing a single line */
268
QPair<QStringList,QString> extractPropertyGroupsAndName(LByteArray* line, QTextCodec* codec)
270
QMultiHash<QString,QString> extractVCard21PropertyParams(LByteArray* line, QTextCodec* codec)
272
QMultiHash<QString,QString> extractVCard30PropertyParams(LByteArray* line, QTextCodec* codec)
275
// "Private" functions
276
QList<QByteArray> extractParams(LByteArray* line, QTextCodec *codec) const;
277
QList<QByteArray> extractParts(const QByteArray& text, const QByteArray& separator,
278
QTextCodec *codec) const;
279
QByteArray extractPart(const QByteArray& text, int startPosition, int length=-1) const;
280
QString paramName(const QByteArray& parameter, QTextCodec* codec) const;
281
QString paramValue(const QByteArray& parameter, QTextCodec* codec) const;
282
template <class T> static bool containsAt(const T& text, const QByteArray& ba, int index);
283
bool splitStructuredValue(QVersitProperty* property,
284
bool hasEscapedBackslashes) const;
285
static QStringList splitValue(const QString& string,
287
QString::SplitBehavior behaviour,
288
bool hasEscapedBackslashes);
289
static void removeBackSlashEscaping(QString* text);
293
QPointer<QIODevice> mIoDevice;
294
QScopedPointer<QBuffer> mInputBytes; // Holds the data set by setData()
295
QList<QVersitDocument> mVersitDocuments;
296
int mDocumentNestingLevel; // Depth in parsing nested Versit documents
297
QTextCodec* mDefaultCodec;
298
QVersitReader::State mState;
299
QVersitReader::Error mError;
301
mutable QMutex mMutex;
304
/* key is the document type and property name, value is the type of property it is.
305
If there is no entry, assume it is a PlainType */
306
static QHash<QPair<QVersitDocument::VersitType,QString>, QVersitProperty::ValueType>* mValueTypeMap;
309
QT_END_NAMESPACE_VERSIT
311
#endif // QVERSITREADER_P_H