1/****************************************************************************
2**
3** Copyright (C) 2015 The Qt Company Ltd.
4** Contact: http://www.qt.io/licensing/
5**
6** This file is part of the QtVersit module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL21$
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 http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://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 2.1 or version 3 as published by the Free
20** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22** following information to ensure the GNU Lesser General Public License
23** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25**
26** As a special exception, The Qt Company gives you certain additional
27** rights. These rights are described in The Qt Company LGPL Exception
28** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29**
30** $QT_END_LICENSE$
31**
32****************************************************************************/
33
34#include "qversitreader.h"
35#include "qversitreader_p.h"
36
37#include <QtCore/qbuffer.h>
38#include <QtCore/qtextcodec.h>
39
40QT_BEGIN_NAMESPACE_VERSIT
41
42/*!
43 \class QVersitReader
44 \brief The QVersitReader class provides an interface for reading versit
45 documents such as vCards from a Stream.
46 \ingroup versit
47 \inmodule QtVersit
48
49 QVersitReader concatenation of Versit documents such as vCards
50 from a text stream and returns a list of QVersitDocument instances.
51 QVersitReader supports reading from an abstract I/O device
52 which can be, for example, a file or a memory buffer.
53 The reading can be done asynchronously, and the
54 waitForFinished() function can be used to make a blocking
55 read.
56
57 \sa QVersitDocument
58 */
59
60/*!
61 * \enum QVersitReader::Error
62 * This enum specifies an error that occurred during the most recent operation:
63 * \value NoError The most recent operation was successful
64 * \value UnspecifiedError The most recent operation failed for an undocumented reason
65 * \value IOError The most recent operation failed because of a problem with the device
66 * \value OutOfMemoryError The most recent operation failed due to running out of memory
67 * \value NotReadyError The most recent operation failed because there is an operation in progress
68 * \value ParseError The most recent operation failed because the input was malformed
69 */
70
71/*!
72 * \enum QVersitReader::State
73 * Enumerates the various states that a reader may be in at any given time
74 * \value InactiveState Read operation not yet started
75 * \value ActiveState Read operation started, not yet finished
76 * \value CanceledState Read operation is finished due to cancellation
77 * \value FinishedState Read operation successfully completed
78 */
79
80/*!
81 * \fn QVersitReader::stateChanged(QVersitReader::State state)
82 * The signal is emitted by the reader when its state has changed (eg. when it has finished
83 * reading from the device).
84 * \a state is the new state of the reader.
85 */
86
87/*!
88 * \fn QVersitReader::resultsAvailable()
89 * The signal is emitted by the reader as it reads from the device when it has made more Versit
90 * documents available.
91 */
92
93/*! Constructs a new reader. */
94QVersitReader::QVersitReader() : d(new QVersitReaderPrivate)
95{
96 d->init(reader: this);
97}
98
99/*! Constructs a new reader that reads from \a inputDevice. */
100QVersitReader::QVersitReader(QIODevice *inputDevice) : d(new QVersitReaderPrivate)
101{
102 d->init(reader: this);
103 d->mIoDevice = inputDevice;
104}
105
106/*! Constructs a new reader that reads from \a inputData. */
107QVersitReader::QVersitReader(const QByteArray &inputData) : d(new QVersitReaderPrivate)
108{
109 d->init(reader: this);
110 d->mInputBytes.reset(other: new QBuffer);
111 d->mInputBytes->setData(inputData);
112 d->mInputBytes->open(openMode: QIODevice::ReadOnly);
113 d->mIoDevice = d->mInputBytes.data();
114}
115
116/*!
117 * Frees the memory used by the reader.
118 * Waits until a pending asynchronous reading has been completed.
119 */
120QVersitReader::~QVersitReader()
121{
122 d->wait();
123 delete d;
124}
125
126/*!
127 * Sets the device used for reading the input to be the given \a device.
128 * Does not take ownership of the device. This overrides any byte array input source set with
129 * setData().
130 *
131 * The caller must ensure that \a device remains valid for the lifetime of
132 * this QVersitReader object.
133 */
134void QVersitReader::setDevice(QIODevice* device)
135{
136 d->mInputBytes.reset(other: 0);
137 d->mIoDevice = device;
138}
139
140/*!
141 * Returns the device used for reading input, or 0 if no device has been set (or if the input source
142 * was set with setData().
143 */
144QIODevice* QVersitReader::device() const
145{
146 if (d->mInputBytes.isNull())
147 return d->mIoDevice;
148 else
149 return 0;
150}
151
152/*!
153 * Sets the data to read from to the byte array input source, \a inputData.
154 * This overrides any device set with setDevice().
155 */
156void QVersitReader::setData(const QByteArray &inputData)
157{
158 if (d->mInputBytes.isNull()) {
159 d->mInputBytes.reset(other: new QBuffer);
160 } else if (d->mInputBytes->isOpen()) {
161 d->mInputBytes->close();
162 }
163 d->mInputBytes->setData(inputData);
164 d->mInputBytes->open(openMode: QIODevice::ReadOnly);
165 d->mIoDevice = d->mInputBytes.data();
166}
167
168/*!
169 * Sets \a codec as the codec for the reader to use when parsing the input stream to.
170 * This codec is not used for values where the CHARSET Versit parameter occurs.
171 * If the codec is null, this denotes that the reader will try to detect the codec
172 * from the input. The codec autodetection algorithm can detect UTF-8, UTF-16 or
173 * UTF-32. If the input is in some 8-bit codec, it will fall back to using the system
174 * locale's codec.
175 */
176void QVersitReader::setDefaultCodec(QTextCodec *codec)
177{
178 d->mDefaultCodec = codec;
179}
180
181/*!
182 * Returns the codec the reader uses when parsing the input stream. If the codec is
183 * null, this denotes that the reader will try to detect the codec from the input.
184 */
185QTextCodec* QVersitReader::defaultCodec() const
186{
187 return d->mDefaultCodec;
188}
189
190/*!
191 * Returns the state of the reader.
192 */
193QVersitReader::State QVersitReader::state() const
194{
195 return d->state();
196}
197
198/*!
199 * Returns the error encountered by the last operation.
200 */
201QVersitReader::Error QVersitReader::error() const
202{
203 return d->error();
204}
205
206/*!
207 * Starts reading the input asynchronously.
208 * Returns false if the input device has not been set or opened or
209 * if there is another asynchronous read operation already pending.
210 * Signal \l stateChanged() is emitted with parameter FinishedState
211 * when the reading has finished.
212 *
213 * The device must be already open. The client is responsible for
214 * closing it when finished.
215 */
216bool QVersitReader::startReading()
217{
218 if (d->state() == ActiveState || d->isRunning()) {
219 d->setError(QVersitReader::NotReadyError);
220 return false;
221 } else if (!d->mIoDevice || !d->mIoDevice->isReadable()) {
222 d->setError(QVersitReader::IOError);
223 return false;
224 } else {
225 d->setState(ActiveState);
226 d->setError(NoError);
227 d->setCanceling(false);
228 d->start();
229 return true;
230 }
231}
232
233/*!
234 * Attempts to asynchronously cancel the read request.
235 */
236void QVersitReader::cancel()
237{
238 d->setCanceling(true);
239}
240
241/*!
242 * If the state is ActiveState, blocks until the reader has finished reading or \a msec milliseconds
243 * has elapsed, returning true if it successfully finishes or is cancelled by the user.
244 * If \a msec is negative or zero, the function blocks until the writer has finished, regardless of
245 * how long it takes.
246 * If the state is FinishedState, returns true immediately.
247 * Otherwise, returns false immediately.
248 */
249bool QVersitReader::waitForFinished(int msec)
250{
251 State state = d->state();
252 if (state != InactiveState) {
253 if (msec <= 0)
254 return d->wait(ULONG_MAX);
255 else
256 return d->wait(time: msec);
257 } else {
258 return false;
259 }
260}
261
262/*!
263 * Returns the reading result. Even if there was an error or reading has not completed, a partial
264 * list of results may be returned.
265 */
266QList<QVersitDocument> QVersitReader::results() const
267{
268 QMutexLocker locker(&d->mMutex);
269 return d->mVersitDocuments;
270}
271
272#include "moc_qversitreader.cpp"
273
274QT_END_NAMESPACE_VERSIT
275

source code of qtpim/src/versit/qversitreader.cpp