~chris.gagnon/+junk/qtpim-coverage

« back to all changes in this revision

Viewing changes to src/versit/qversitreader_p.h

  • Committer: chris.gagnon
  • Date: 2013-12-10 23:09:37 UTC
  • Revision ID: chris.gagnon@canonical.com-20131210230937-2akf1ft1edcttk87
first post

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
 
4
** Contact: http://www.qt-project.org/legal
 
5
**
 
6
** This file is part of the QtVersit 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 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.
 
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 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.
 
24
**
 
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.
 
28
**
 
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.
 
36
**
 
37
**
 
38
** $QT_END_LICENSE$
 
39
**
 
40
****************************************************************************/
 
41
 
 
42
 
 
43
#ifndef QVERSITREADER_P_H
 
44
#define QVERSITREADER_P_H
 
45
 
 
46
//
 
47
//  W A R N I N G
 
48
//  -------------
 
49
//
 
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.
 
53
//
 
54
// We mean it.
 
55
//
 
56
 
 
57
#include <qversitreader.h>
 
58
#include <qversitdocument.h>
 
59
#include <qversitproperty.h>
 
60
#include "qversitutils_p.h"
 
61
 
 
62
#include <QObject>
 
63
#include <QThread>
 
64
#include <QByteArray>
 
65
#include <QIODevice>
 
66
#include <QList>
 
67
#include <QStack>
 
68
#include <QPointer>
 
69
#include <QScopedPointer>
 
70
#include <QByteArray>
 
71
#include <QMutex>
 
72
#include <QWaitCondition>
 
73
#include <QPair>
 
74
#include <QHash>
 
75
 
 
76
QT_BEGIN_NAMESPACE
 
77
class QBuffer;
 
78
QT_END_NAMESPACE
 
79
 
 
80
QT_BEGIN_NAMESPACE_VERSIT
 
81
 
 
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;
 
85
 
 
86
/*
 
87
 * An LByteArray has a subset of QByteArray's interface, plus an efficient chopLeft function
 
88
 * 
 
89
 * It stores a QByteArray internally, plus a marker of where it starts and where it ends.
 
90
 */
 
91
class LByteArray
 
92
{
 
93
public:
 
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;
 
99
    }
 
100
    char at(int i) const {
 
101
        return mData.at(mStart + i);
 
102
    }
 
103
    QByteArray toByteArray() const {
 
104
        return mData.mid(mStart, mEnd-mStart);
 
105
    }
 
106
    /* Removes \a n bytes from the start of the QByteArray. */ 
 
107
    void chopLeft(int n) {
 
108
        Q_ASSERT(size() >= n && n >= 0);
 
109
        mStart += n;
 
110
    }
 
111
    QByteArray left(int n) {
 
112
        Q_ASSERT(size() >= n && n >= 0);
 
113
        return mData.mid(mStart, n);
 
114
    }
 
115
    int indexOf(const QByteArray& needle) {
 
116
        int index = mData.indexOf(needle, mStart) - mStart;
 
117
        if (index < size())
 
118
            return index;
 
119
        return -1;
 
120
    }
 
121
    int size() const {
 
122
        return mEnd - mStart;
 
123
    }
 
124
    const char* constData() const {
 
125
        return mData.constData() + mStart;
 
126
    }
 
127
    bool contains(const QByteArray& ba) const {
 
128
        int i = mData.indexOf(ba, mStart);
 
129
        return i > 0 && i <= mEnd - ba.length();
 
130
    }
 
131
    bool endsWith(const QByteArray& ba) const {
 
132
        // Loop backwards from ba and from mData (starting from index mEnd)
 
133
        if (ba.size() > size())
 
134
            return false;
 
135
        return memcmp(mData.constData()+mEnd-ba.size(), ba.constData(), ba.size()) == 0;
 
136
    }
 
137
    LByteArray& operator=(const QByteArray& ba) {
 
138
        mData = ba;
 
139
        mStart = 0;
 
140
        mEnd = mData.size();
 
141
        return *this;
 
142
    }
 
143
    bool operator==(const QByteArray& ba) {
 
144
        return toByteArray() == ba;
 
145
    }
 
146
    bool operator!=(const QByteArray& ba) {
 
147
        return toByteArray() != ba;
 
148
    }
 
149
 
 
150
private:
 
151
    /* Clears the memory of bytes before the start marker */
 
152
    void dropOldData() {
 
153
        if (mStart > MAX_OLD_BYTES_TO_KEEP && mEnd >= mStart) {
 
154
            mData.remove(0, mStart);
 
155
            mEnd -= mStart;
 
156
            mStart = 0;
 
157
        }
 
158
    }
 
159
    void setBounds(int start, int end) {
 
160
        mStart = start;
 
161
        mEnd = end;
 
162
    }
 
163
    QByteArray mData;
 
164
    int mStart;
 
165
    int mEnd;
 
166
    friend class LineReader;
 
167
};
 
168
 
 
169
class Q_VERSIT_EXPORT LineReader
 
170
{
 
171
public:
 
172
    LineReader(QIODevice* device, QTextCodec* codec);
 
173
    LineReader(QIODevice* device);
 
174
    LineReader(QIODevice* device, QTextCodec* codec, int chunkSize);
 
175
    void init();
 
176
    void pushLine(const QByteArray& line);
 
177
    int odometer() const;
 
178
    bool atEnd() const;
 
179
    QTextCodec* codec() const;
 
180
    bool isCodecCertain() const;
 
181
    bool isCodecUtf8Compatible() const;
 
182
    void setCodecUtf8Incompatible();
 
183
    LByteArray readLine();
 
184
 
 
185
private:
 
186
    void readOneLine(LByteArray* cursor);
 
187
    bool tryReadLine(LByteArray* cursor, bool atEnd);
 
188
 
 
189
    QIODevice* const mDevice;
 
190
    QTextCodec* mCodec;
 
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
 
196
    LByteArray mBuffer;
 
197
    int mOdometer;
 
198
    int mSearchFrom;
 
199
};
 
200
 
 
201
class Q_VERSIT_EXPORT QVersitReaderPrivate : public QThread
 
202
{
 
203
    Q_OBJECT
 
204
 
 
205
public: // Constructors and destructor
 
206
    QVersitReaderPrivate();
 
207
    ~QVersitReaderPrivate();
 
208
 
 
209
    static QHash<QPair<QVersitDocument::VersitType,QString>, QVersitProperty::ValueType>*
 
210
        valueTypeMap();
 
211
    void init(QVersitReader* reader);
 
212
 
 
213
signals:
 
214
    void stateChanged(QVersitReader::State state);
 
215
    void resultsAvailable();
 
216
 
 
217
protected: // From QThread
 
218
     void run();
 
219
 
 
220
public: // New functions
 
221
    void read();
 
222
 
 
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);
 
229
    bool isCanceling();
 
230
 
 
231
    bool parseVersitDocument(LineReader* lineReader, QVersitDocument* document);
 
232
    bool parseVersitDocumentBody(LineReader* lineReader, QVersitDocument* document);
 
233
 
 
234
    QVersitProperty parseNextVersitProperty(
 
235
        QVersitDocument::VersitType versitType,
 
236
        LineReader* lineReader);
 
237
 
 
238
    void parseVCard21Property(
 
239
        LByteArray* text,
 
240
        QVersitProperty* property,
 
241
        LineReader* lineReader);
 
242
 
 
243
    void parseVCard30Property(
 
244
        QVersitDocument::VersitType versitType,
 
245
        LByteArray* text,
 
246
        QVersitProperty* property,
 
247
        LineReader* lineReader);
 
248
 
 
249
    bool setVersionFromProperty(
 
250
        QVersitDocument* document,
 
251
        const QVersitProperty& property) const;
 
252
 
 
253
    bool unencode(
 
254
        QByteArray* value,
 
255
        QVersitProperty* property,
 
256
        LineReader* lineReader) const;
 
257
 
 
258
    QString decodeCharset(
 
259
        const QByteArray& value,
 
260
        QVersitProperty* property,
 
261
        LineReader* lineReader,
 
262
        QTextCodec** codec) const;
 
263
 
 
264
    void decodeQuotedPrintable(QByteArray* text) const;
 
265
 
 
266
 
 
267
    /* These functions operate on a cursor describing a single line */
 
268
    QPair<QStringList,QString> extractPropertyGroupsAndName(LByteArray* line, QTextCodec* codec)
 
269
            const;
 
270
    QMultiHash<QString,QString> extractVCard21PropertyParams(LByteArray* line, QTextCodec* codec)
 
271
            const;
 
272
    QMultiHash<QString,QString> extractVCard30PropertyParams(LByteArray* line, QTextCodec* codec)
 
273
            const;
 
274
 
 
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,
 
286
                                  const QChar& sep,
 
287
                                  QString::SplitBehavior behaviour,
 
288
                                  bool hasEscapedBackslashes);
 
289
    static void removeBackSlashEscaping(QString* text);
 
290
 
 
291
// Data
 
292
public:
 
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;
 
300
    bool mIsCanceling;
 
301
    mutable QMutex mMutex;
 
302
 
 
303
private:
 
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;
 
307
};
 
308
 
 
309
QT_END_NAMESPACE_VERSIT
 
310
 
 
311
#endif // QVERSITREADER_P_H