ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
quaziodevice.cpp
Go to the documentation of this file.
1 /*
2 Copyright (C) 2005-2014 Sergey A. Tachenov
3 
4 This file is part of QuaZIP.
5 
6 QuaZIP is free software: you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation, either version 2.1 of the License, or
9 (at your option) any later version.
10 
11 QuaZIP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Lesser General Public License for more details.
15 
16 You should have received a copy of the GNU Lesser General Public License
17 along with QuaZIP. If not, see <http://www.gnu.org/licenses/>.
18 
19 See COPYING file for the full LGPL text.
20 
21 Original ZIP package is copyrighted by Gilles Vollant and contributors,
22 see quazip/(un)zip.h files for details. Basically it's the zlib license.
23 */
24 
25 #include "quaziodevice.h"
26 
27 #pragma warning(disable : 4996)
28 
29 #define QUAZIO_INBUFSIZE 4096
30 #define QUAZIO_OUTBUFSIZE 4096
31 
33 class QuaZIODevicePrivate {
34  friend class QuaZIODevice;
35  QuaZIODevicePrivate(QIODevice *io);
36  ~QuaZIODevicePrivate();
37  QIODevice *io;
38  z_stream zins;
39  z_stream zouts;
40  char *inBuf;
41  int inBufPos;
42  int inBufSize;
43  char *outBuf;
44  int outBufPos;
45  int outBufSize;
46  bool zBufError;
47  bool atEnd;
48  int doFlush(QString &error);
49 };
50 
51 QuaZIODevicePrivate::QuaZIODevicePrivate(QIODevice *io)
52  : io(io),
53  inBuf(NULL),
54  inBufPos(0),
55  inBufSize(0),
56  outBuf(NULL),
57  outBufPos(0),
58  outBufSize(0),
59  zBufError(false),
60  atEnd(false) {
61  zins.zalloc = (alloc_func)NULL;
62  zins.zfree = (free_func)NULL;
63  zins.opaque = NULL;
64  zouts.zalloc = (alloc_func)NULL;
65  zouts.zfree = (free_func)NULL;
66  zouts.opaque = NULL;
67  inBuf = new char[QUAZIO_INBUFSIZE];
68  outBuf = new char[QUAZIO_OUTBUFSIZE];
69 #ifdef QUAZIP_ZIODEVICE_DEBUG_OUTPUT
70  debug.setFileName("debug.out");
71  debug.open(QIODevice::WriteOnly);
72 #endif
73 #ifdef QUAZIP_ZIODEVICE_DEBUG_INPUT
74  indebug.setFileName("debug.in");
75  indebug.open(QIODevice::WriteOnly);
76 #endif
77 }
78 
79 QuaZIODevicePrivate::~QuaZIODevicePrivate() {
80 #ifdef QUAZIP_ZIODEVICE_DEBUG_OUTPUT
81  debug.close();
82 #endif
83 #ifdef QUAZIP_ZIODEVICE_DEBUG_INPUT
84  indebug.close();
85 #endif
86  if (inBuf != NULL) delete[] inBuf;
87  if (outBuf != NULL) delete[] outBuf;
88 }
89 
90 int QuaZIODevicePrivate::doFlush(QString &error) {
91  int flushed = 0;
92  while (outBufPos < outBufSize) {
93  int more = io->write(outBuf + outBufPos, outBufSize - outBufPos);
94  if (more == -1) {
95  error = io->errorString();
96  return -1;
97  }
98  if (more == 0) break;
99  outBufPos += more;
100  flushed += more;
101  }
102  if (outBufPos == outBufSize) {
103  outBufPos = outBufSize = 0;
104  }
105  return flushed;
106 }
107 
109 
110 // #define QUAZIP_ZIODEVICE_DEBUG_OUTPUT
111 // #define QUAZIP_ZIODEVICE_DEBUG_INPUT
112 #ifdef QUAZIP_ZIODEVICE_DEBUG_OUTPUT
113 #include <QFile>
114 static QFile debug;
115 #endif
116 #ifdef QUAZIP_ZIODEVICE_DEBUG_INPUT
117 #include <QFile>
118 static QFile indebug;
119 #endif
120 
121 QuaZIODevice::QuaZIODevice(QIODevice *io, QObject *parent)
122  : QIODevice(parent), d(new QuaZIODevicePrivate(io)) {
123  connect(io, SIGNAL(readyRead()), SIGNAL(readyRead()));
124 }
125 
127  if (isOpen()) close();
128  delete d;
129 }
130 
131 QIODevice *QuaZIODevice::getIoDevice() const { return d->io; }
132 
133 bool QuaZIODevice::open(QIODevice::OpenMode mode) {
134  if ((mode & QIODevice::Append) != 0) {
135  setErrorString(
136 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
137  tr("QIODevice::Append is not supported for"
138  " QuaZIODevice"));
139 #else
140  trUtf8("QIODevice::Append is not supported for"
141  " QuaZIODevice"));
142 #endif
143  return false;
144  }
145  if ((mode & QIODevice::ReadWrite) == QIODevice::ReadWrite) {
146  setErrorString(
147 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
148  tr("QIODevice::ReadWrite is not supported for"
149  " QuaZIODevice"));
150 #else
151  trUtf8("QIODevice::ReadWrite is not supported for"
152  " QuaZIODevice"));
153 #endif
154  return false;
155  }
156  if ((mode & QIODevice::ReadOnly) != 0) {
157  if (inflateInit(&d->zins) != Z_OK) {
158  setErrorString(d->zins.msg);
159  return false;
160  }
161  }
162  if ((mode & QIODevice::WriteOnly) != 0) {
163  if (deflateInit(&d->zouts, Z_DEFAULT_COMPRESSION) != Z_OK) {
164  setErrorString(d->zouts.msg);
165  return false;
166  }
167  }
168  return QIODevice::open(mode);
169 }
170 
172  if ((openMode() & QIODevice::ReadOnly) != 0) {
173  if (inflateEnd(&d->zins) != Z_OK) {
174  setErrorString(d->zins.msg);
175  }
176  }
177  if ((openMode() & QIODevice::WriteOnly) != 0) {
178  flush();
179  if (deflateEnd(&d->zouts) != Z_OK) {
180  setErrorString(d->zouts.msg);
181  }
182  }
183  QIODevice::close();
184 }
185 
186 qint64 QuaZIODevice::readData(char *data, qint64 maxSize) {
187  int read = 0;
188  while (read < maxSize) {
189  if (d->inBufPos == d->inBufSize) {
190  d->inBufPos = 0;
191  d->inBufSize = d->io->read(d->inBuf, QUAZIO_INBUFSIZE);
192  if (d->inBufSize == -1) {
193  d->inBufSize = 0;
194  setErrorString(d->io->errorString());
195  return -1;
196  }
197  if (d->inBufSize == 0) break;
198  }
199  while (read < maxSize && d->inBufPos < d->inBufSize) {
200  d->zins.next_in = (Bytef *)(d->inBuf + d->inBufPos);
201  d->zins.avail_in = d->inBufSize - d->inBufPos;
202  d->zins.next_out = (Bytef *)(data + read);
203  d->zins.avail_out =
204  (uInt)(maxSize - read); // hope it's less than 2GB
205  int more = 0;
206  switch (inflate(&d->zins, Z_SYNC_FLUSH)) {
207  case Z_OK:
208  read = (char *)d->zins.next_out - data;
209  d->inBufPos = (char *)d->zins.next_in - d->inBuf;
210  break;
211  case Z_STREAM_END:
212  read = (char *)d->zins.next_out - data;
213  d->inBufPos = (char *)d->zins.next_in - d->inBuf;
214  d->atEnd = true;
215  return read;
216  case Z_BUF_ERROR: // this should never happen, but just in case
217  if (!d->zBufError) {
218  qWarning(
219  "Z_BUF_ERROR detected with %d/%d in/out, weird",
220  d->zins.avail_in, d->zins.avail_out);
221  d->zBufError = true;
222  }
223  memmove(d->inBuf, d->inBuf + d->inBufPos,
224  d->inBufSize - d->inBufPos);
225  d->inBufSize -= d->inBufPos;
226  d->inBufPos = 0;
227  more = d->io->read(d->inBuf + d->inBufSize,
228  QUAZIO_INBUFSIZE - d->inBufSize);
229  if (more == -1) {
230  setErrorString(d->io->errorString());
231  return -1;
232  }
233  if (more == 0) return read;
234  d->inBufSize += more;
235  break;
236  default:
237  setErrorString(QString::fromLocal8Bit(d->zins.msg));
238  return -1;
239  }
240  }
241  }
242 #ifdef QUAZIP_ZIODEVICE_DEBUG_INPUT
243  indebug.write(data, read);
244 #endif
245  return read;
246 }
247 
248 qint64 QuaZIODevice::writeData(const char *data, qint64 maxSize) {
249  int written = 0;
250  QString error;
251  if (d->doFlush(error) == -1) {
252  setErrorString(error);
253  return -1;
254  }
255  while (written < maxSize) {
256  // there is some data waiting in the output buffer
257  if (d->outBufPos < d->outBufSize) return written;
258  d->zouts.next_in = (Bytef *)(data + written);
259  d->zouts.avail_in =
260  (uInt)(maxSize - written); // hope it's less than 2GB
261  d->zouts.next_out = (Bytef *)d->outBuf;
262  d->zouts.avail_out = QUAZIO_OUTBUFSIZE;
263  switch (deflate(&d->zouts, Z_NO_FLUSH)) {
264  case Z_OK:
265  written = (char *)d->zouts.next_in - data;
266  d->outBufSize = (char *)d->zouts.next_out - d->outBuf;
267  break;
268  default:
269  setErrorString(QString::fromLocal8Bit(d->zouts.msg));
270  return -1;
271  }
272  if (d->doFlush(error) == -1) {
273  setErrorString(error);
274  return -1;
275  }
276  }
277 #ifdef QUAZIP_ZIODEVICE_DEBUG_OUTPUT
278  debug.write(data, written);
279 #endif
280  return written;
281 }
282 
284  QString error;
285  if (d->doFlush(error) < 0) {
286  setErrorString(error);
287  return false;
288  }
289  // can't flush buffer, some data is still waiting
290  if (d->outBufPos < d->outBufSize) return true;
291  Bytef c = 0;
292  d->zouts.next_in = &c; // fake input buffer
293  d->zouts.avail_in = 0; // of zero size
294  do {
295  d->zouts.next_out = (Bytef *)d->outBuf;
296  d->zouts.avail_out = QUAZIO_OUTBUFSIZE;
297  switch (deflate(&d->zouts, Z_SYNC_FLUSH)) {
298  case Z_OK:
299  d->outBufSize = (char *)d->zouts.next_out - d->outBuf;
300  if (d->doFlush(error) < 0) {
301  setErrorString(error);
302  return false;
303  }
304  if (d->outBufPos < d->outBufSize) return true;
305  break;
306  case Z_BUF_ERROR: // nothing to write?
307  return true;
308  default:
309  setErrorString(QString::fromLocal8Bit(d->zouts.msg));
310  return false;
311  }
312  } while (d->zouts.avail_out == 0);
313  return true;
314 }
315 
316 bool QuaZIODevice::isSequential() const { return true; }
317 
318 bool QuaZIODevice::atEnd() const {
319  // Here we MUST check QIODevice::bytesAvailable() because WE
320  // might have reached the end, but QIODevice didn't--
321  // it could have simply pre-buffered all remaining data.
322  return (openMode() == NotOpen) ||
323  (QIODevice::bytesAvailable() == 0 && d->atEnd);
324 }
325 
327  // If we haven't recevied Z_STREAM_END, it means that
328  // we have at least one more input byte available.
329  // Plus whatever QIODevice has buffered.
330  return (d->atEnd ? 0 : 1) + QIODevice::bytesAvailable();
331 }
#define NULL
A class to compress/decompress QIODevice.
Definition: quaziodevice.h:42
virtual bool open(QIODevice::OpenMode mode)
Opens the device.
virtual bool flush()
Flushes data waiting to be written.
virtual bool atEnd() const
Returns true iff the end of the compressed stream is reached.
QuaZIODevice(QIODevice *io, QObject *parent=NULL)
Constructor.
virtual qint64 readData(char *data, qint64 maxSize)
Implementation of QIODevice::readData().
virtual qint64 writeData(const char *data, qint64 maxSize)
Implementation of QIODevice::writeData().
~QuaZIODevice()
Destructor.
virtual qint64 bytesAvailable() const
Returns the number of the bytes buffered.
virtual void close()
Closes this device, but not the underlying one.
QIODevice * getIoDevice() const
Returns the underlying device.
virtual bool isSequential() const
Returns true.
static void error(char *msg)
Definition: lsd.c:159
Tensor Append(const Tensor &self, const Tensor &other, const utility::optional< int64_t > &axis)
Appends the two tensors, along the given axis into a new tensor. Both the tensors must have same data...
#define QUAZIO_INBUFSIZE
#define QUAZIO_OUTBUFSIZE
#define isOpen(pFd)
Definition: sqlite3.c:52420