ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
qioapi.cpp
Go to the documentation of this file.
1 /* ioapi.c -- IO base function header for compress/uncompress .zip
2  files using zlib + zip or unzip API
3 
4  Version 1.01e, February 12th, 2005
5 
6  Copyright (C) 1998-2005 Gilles Vollant
7 
8  Modified by Sergey A. Tachenov to integrate with Qt.
9 */
10 
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 
15 #include <QIODevice>
16 
17 #include "ioapi.h"
18 #include "quazip_global.h"
19 #include "zlib.h"
20 #if (QT_VERSION >= 0x050100)
21 #define QUAZIP_QSAVEFILE_BUG_WORKAROUND
22 #endif
23 #ifdef QUAZIP_QSAVEFILE_BUG_WORKAROUND
24 #include <QSaveFile>
25 #endif
26 
27 /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
28 
29 #ifndef SEEK_CUR
30 #define SEEK_CUR 1
31 #endif
32 
33 #ifndef SEEK_END
34 #define SEEK_END 2
35 #endif
36 
37 #ifndef SEEK_SET
38 #define SEEK_SET 0
39 #endif
40 
41 voidpf call_zopen64(const zlib_filefunc64_32_def *pfilefunc,
42  voidpf file,
43  int mode) {
44  if (pfilefunc->zfile_func64.zopen64_file != NULL)
45  return (*(pfilefunc->zfile_func64.zopen64_file))(
46  pfilefunc->zfile_func64.opaque, file, mode);
47  else {
48  return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,
49  file, mode);
50  }
51 }
52 
53 int call_zseek64(const zlib_filefunc64_32_def *pfilefunc,
54  voidpf filestream,
56  int origin) {
57  if (pfilefunc->zfile_func64.zseek64_file != NULL)
58  return (*(pfilefunc->zfile_func64.zseek64_file))(
59  pfilefunc->zfile_func64.opaque, filestream, offset, origin);
60  else {
61  uLong offsetTruncated = (uLong)offset;
62  if (offsetTruncated != offset)
63  return -1;
64  else
65  return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,
66  filestream, offsetTruncated,
67  origin);
68  }
69 }
70 
72  voidpf filestream) {
73  if (pfilefunc->zfile_func64.zseek64_file != NULL)
74  return (*(pfilefunc->zfile_func64.ztell64_file))(
75  pfilefunc->zfile_func64.opaque, filestream);
76  else {
77  uLong tell_uLong = (*(pfilefunc->ztell32_file))(
78  pfilefunc->zfile_func64.opaque, filestream);
79  if ((tell_uLong) == ((uLong)-1))
80  return (ZPOS64_T)-1;
81  else
82  return tell_uLong;
83  }
84 }
85 
87 struct QIODevice_descriptor {
88  // Position only used for writing to sequential devices.
89  qint64 pos;
90  inline QIODevice_descriptor() : pos(0) {}
91 };
93 
94 voidpf ZCALLBACK qiodevice_open_file_func(voidpf opaque,
95  voidpf file,
96  int mode) {
97  QIODevice_descriptor *d = reinterpret_cast<QIODevice_descriptor *>(opaque);
98  QIODevice *iodevice = reinterpret_cast<QIODevice *>(file);
99  QIODevice::OpenMode desiredMode;
101  desiredMode = QIODevice::ReadOnly;
102  else if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
103  desiredMode = QIODevice::ReadWrite;
104  else if (mode & ZLIB_FILEFUNC_MODE_CREATE)
105  desiredMode = QIODevice::WriteOnly;
106  if (iodevice->isOpen()) {
107  if ((iodevice->openMode() & desiredMode) == desiredMode) {
108  if (desiredMode != QIODevice::WriteOnly &&
109  iodevice->isSequential()) {
110  // We can use sequential devices only for writing.
111  delete d;
112  return NULL;
113  } else {
114  if ((desiredMode & QIODevice::WriteOnly) != 0) {
115  // open for writing, need to seek existing device
116  if (!iodevice->isSequential()) {
117  iodevice->seek(0);
118  } else {
119  d->pos = iodevice->pos();
120  }
121  }
122  }
123  return iodevice;
124  } else {
125  delete d;
126  return NULL;
127  }
128  }
129  iodevice->open(desiredMode);
130  if (iodevice->isOpen()) {
131  if (desiredMode != QIODevice::WriteOnly && iodevice->isSequential()) {
132  // We can use sequential devices only for writing.
133  iodevice->close();
134  delete d;
135  return NULL;
136  } else {
137  return iodevice;
138  }
139  } else {
140  delete d;
141  return NULL;
142  }
143 }
144 
146  voidpf stream,
147  void *buf,
148  uLong size) {
149  QIODevice_descriptor *d = reinterpret_cast<QIODevice_descriptor *>(opaque);
150  QIODevice *iodevice = reinterpret_cast<QIODevice *>(stream);
151  qint64 ret64 = iodevice->read((char *)buf, size);
152  uLong ret;
153  ret = (uLong)ret64;
154  if (ret64 != -1) {
155  d->pos += ret64;
156  }
157  return ret;
158 }
159 
161  voidpf stream,
162  const void *buf,
163  uLong size) {
164  QIODevice_descriptor *d = reinterpret_cast<QIODevice_descriptor *>(opaque);
165  QIODevice *iodevice = reinterpret_cast<QIODevice *>(stream);
166  uLong ret;
167  qint64 ret64 = iodevice->write((char *)buf, size);
168  if (ret64 != -1) {
169  d->pos += ret64;
170  }
171  ret = (uLong)ret64;
172  return ret;
173 }
174 
175 uLong ZCALLBACK qiodevice_tell_file_func(voidpf opaque, voidpf stream) {
176  QIODevice_descriptor *d = reinterpret_cast<QIODevice_descriptor *>(opaque);
177  QIODevice *iodevice = reinterpret_cast<QIODevice *>(stream);
178  uLong ret;
179  qint64 ret64;
180  if (iodevice->isSequential()) {
181  ret64 = d->pos;
182  } else {
183  ret64 = iodevice->pos();
184  }
185  ret = static_cast<uLong>(ret64);
186  return ret;
187 }
188 
189 ZPOS64_T ZCALLBACK qiodevice64_tell_file_func(voidpf opaque, voidpf stream) {
190  QIODevice_descriptor *d = reinterpret_cast<QIODevice_descriptor *>(opaque);
191  QIODevice *iodevice = reinterpret_cast<QIODevice *>(stream);
192  qint64 ret;
193  if (iodevice->isSequential()) {
194  ret = d->pos;
195  } else {
196  ret = iodevice->pos();
197  }
198  return static_cast<ZPOS64_T>(ret);
199 }
200 
201 int ZCALLBACK qiodevice_seek_file_func(voidpf /*opaque UNUSED*/,
202  voidpf stream,
203  uLong offset,
204  int origin) {
205  QIODevice *iodevice = reinterpret_cast<QIODevice *>(stream);
206  if (iodevice->isSequential()) {
207  if (origin == ZLIB_FILEFUNC_SEEK_END && offset == 0) {
208  // sequential devices are always at end (needed in mdAppend)
209  return 0;
210  } else {
211  qWarning("qiodevice_seek_file_func() called for sequential device");
212  return -1;
213  }
214  }
215  uLong qiodevice_seek_result = 0;
216  int ret;
217  switch (origin) {
219  qiodevice_seek_result = ((QIODevice *)stream)->pos() + offset;
220  break;
222  qiodevice_seek_result = ((QIODevice *)stream)->size() - offset;
223  break;
225  qiodevice_seek_result = offset;
226  break;
227  default:
228  return -1;
229  }
230  ret = !iodevice->seek(qiodevice_seek_result);
231  return ret;
232 }
233 
234 int ZCALLBACK qiodevice64_seek_file_func(voidpf /*opaque UNUSED*/,
235  voidpf stream,
237  int origin) {
238  QIODevice *iodevice = reinterpret_cast<QIODevice *>(stream);
239  if (iodevice->isSequential()) {
240  if (origin == ZLIB_FILEFUNC_SEEK_END && offset == 0) {
241  // sequential devices are always at end (needed in mdAppend)
242  return 0;
243  } else {
244  qWarning("qiodevice_seek_file_func() called for sequential device");
245  return -1;
246  }
247  }
248  qint64 qiodevice_seek_result = 0;
249  int ret;
250  switch (origin) {
252  qiodevice_seek_result = ((QIODevice *)stream)->pos() + offset;
253  break;
255  qiodevice_seek_result = ((QIODevice *)stream)->size() - offset;
256  break;
258  qiodevice_seek_result = offset;
259  break;
260  default:
261  return -1;
262  }
263  ret = !iodevice->seek(qiodevice_seek_result);
264  return ret;
265 }
266 
267 int ZCALLBACK qiodevice_close_file_func(voidpf opaque, voidpf stream) {
268  QIODevice_descriptor *d = reinterpret_cast<QIODevice_descriptor *>(opaque);
269  delete d;
270  QIODevice *device = reinterpret_cast<QIODevice *>(stream);
271 #ifdef QUAZIP_QSAVEFILE_BUG_WORKAROUND
272  // QSaveFile terribly breaks the is-a idiom:
273  // it IS a QIODevice, but it is NOT compatible with it: close() is private
274  QSaveFile *file = qobject_cast<QSaveFile *>(device);
275  if (file != NULL) {
276  // We have to call the ugly commit() instead:
277  return file->commit() ? 0 : -1;
278  }
279 #endif
280  device->close();
281  return 0;
282 }
283 
284 int ZCALLBACK qiodevice_fakeclose_file_func(voidpf opaque, voidpf /*stream*/) {
285  QIODevice_descriptor *d = reinterpret_cast<QIODevice_descriptor *>(opaque);
286  delete d;
287  return 0;
288 }
289 
290 int ZCALLBACK qiodevice_error_file_func(voidpf /*opaque UNUSED*/,
291  voidpf /*stream UNUSED*/) {
292  // can't check for error due to the QIODevice API limitation
293  return 0;
294 }
295 
296 void fill_qiodevice_filefunc(zlib_filefunc_def *pzlib_filefunc_def) {
297  pzlib_filefunc_def->zopen_file = qiodevice_open_file_func;
298  pzlib_filefunc_def->zread_file = qiodevice_read_file_func;
299  pzlib_filefunc_def->zwrite_file = qiodevice_write_file_func;
300  pzlib_filefunc_def->ztell_file = qiodevice_tell_file_func;
301  pzlib_filefunc_def->zseek_file = qiodevice_seek_file_func;
302  pzlib_filefunc_def->zclose_file = qiodevice_close_file_func;
303  pzlib_filefunc_def->zerror_file = qiodevice_error_file_func;
304  pzlib_filefunc_def->opaque = new QIODevice_descriptor;
305 }
306 
308  // Open functions are the same for Qt.
309  pzlib_filefunc_def->zopen64_file = qiodevice_open_file_func;
310  pzlib_filefunc_def->zread_file = qiodevice_read_file_func;
311  pzlib_filefunc_def->zwrite_file = qiodevice_write_file_func;
312  pzlib_filefunc_def->ztell64_file = qiodevice64_tell_file_func;
313  pzlib_filefunc_def->zseek64_file = qiodevice64_seek_file_func;
314  pzlib_filefunc_def->zclose_file = qiodevice_close_file_func;
315  pzlib_filefunc_def->zerror_file = qiodevice_error_file_func;
316  pzlib_filefunc_def->opaque = new QIODevice_descriptor;
317  pzlib_filefunc_def->zfakeclose_file = qiodevice_fakeclose_file_func;
318 }
319 
321  zlib_filefunc64_32_def *p_filefunc64_32,
322  const zlib_filefunc_def *p_filefunc32) {
323  p_filefunc64_32->zfile_func64.zopen64_file = NULL;
324  p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file;
325  p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
326  p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file;
327  p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file;
328  p_filefunc64_32->zfile_func64.ztell64_file = NULL;
329  p_filefunc64_32->zfile_func64.zseek64_file = NULL;
330  p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file;
331  p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
332  p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque;
333  p_filefunc64_32->zfile_func64.zfakeclose_file = NULL;
334  p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file;
335  p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file;
336 }
int size
int offset
#define NULL
#define ZLIB_FILEFUNC_MODE_READWRITEFILTER
Definition: ioapi.h:116
#define ZLIB_FILEFUNC_MODE_EXISTING
Definition: ioapi.h:118
#define ZLIB_FILEFUNC_SEEK_CUR
Definition: ioapi.h:110
#define ZLIB_FILEFUNC_SEEK_SET
Definition: ioapi.h:112
#define ZCALLBACK
Definition: ioapi.h:127
#define ZLIB_FILEFUNC_MODE_CREATE
Definition: ioapi.h:119
#define ZLIB_FILEFUNC_SEEK_END
Definition: ioapi.h:111
#define ZLIB_FILEFUNC_MODE_READ
Definition: ioapi.h:114
unsigned long long int ZPOS64_T
Definition: ioapi.h:97
int qiodevice_seek_file_func(voidpf, voidpf stream, uLong offset, int origin)
Definition: qioapi.cpp:201
void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def *p_filefunc64_32, const zlib_filefunc_def *p_filefunc32)
Definition: qioapi.cpp:320
voidpf call_zopen64(const zlib_filefunc64_32_def *pfilefunc, voidpf file, int mode)
Definition: qioapi.cpp:41
voidpf qiodevice_open_file_func(voidpf opaque, voidpf file, int mode)
Definition: qioapi.cpp:94
int qiodevice_close_file_func(voidpf opaque, voidpf stream)
Definition: qioapi.cpp:267
void fill_qiodevice64_filefunc(zlib_filefunc64_def *pzlib_filefunc_def)
Definition: qioapi.cpp:307
uLong qiodevice_tell_file_func(voidpf opaque, voidpf stream)
Definition: qioapi.cpp:175
int qiodevice_error_file_func(voidpf, voidpf)
Definition: qioapi.cpp:290
uLong qiodevice_write_file_func(voidpf opaque, voidpf stream, const void *buf, uLong size)
Definition: qioapi.cpp:160
ZPOS64_T qiodevice64_tell_file_func(voidpf opaque, voidpf stream)
Definition: qioapi.cpp:189
int qiodevice64_seek_file_func(voidpf, voidpf stream, ZPOS64_T offset, int origin)
Definition: qioapi.cpp:234
ZPOS64_T call_ztell64(const zlib_filefunc64_32_def *pfilefunc, voidpf filestream)
Definition: qioapi.cpp:71
void fill_qiodevice_filefunc(zlib_filefunc_def *pzlib_filefunc_def)
Definition: qioapi.cpp:296
int call_zseek64(const zlib_filefunc64_32_def *pfilefunc, voidpf filestream, ZPOS64_T offset, int origin)
Definition: qioapi.cpp:53
uLong qiodevice_read_file_func(voidpf opaque, voidpf stream, void *buf, uLong size)
Definition: qioapi.cpp:145
int qiodevice_fakeclose_file_func(voidpf opaque, voidpf)
Definition: qioapi.cpp:284
seek_file_func zseek32_file
Definition: ioapi.h:183
zlib_filefunc64_def zfile_func64
Definition: ioapi.h:180
open_file_func zopen32_file
Definition: ioapi.h:181
tell_file_func ztell32_file
Definition: ioapi.h:182
write_file_func zwrite_file
Definition: ioapi.h:166
open64_file_func zopen64_file
Definition: ioapi.h:164
close_file_func zfakeclose_file
Definition: ioapi.h:172
read_file_func zread_file
Definition: ioapi.h:165
tell64_file_func ztell64_file
Definition: ioapi.h:167
close_file_func zclose_file
Definition: ioapi.h:169
seek64_file_func zseek64_file
Definition: ioapi.h:168
testerror_file_func zerror_file
Definition: ioapi.h:170
seek_file_func zseek_file
Definition: ioapi.h:150
open_file_func zopen_file
Definition: ioapi.h:146
testerror_file_func zerror_file
Definition: ioapi.h:152
write_file_func zwrite_file
Definition: ioapi.h:148
read_file_func zread_file
Definition: ioapi.h:147
close_file_func zclose_file
Definition: ioapi.h:151
tell_file_func ztell_file
Definition: ioapi.h:149