ReactOS 0.4.16-dev-2613-g9533ad7
tif_stream.cxx
Go to the documentation of this file.
1/*
2 * Copyright (c) 1988-1996 Sam Leffler
3 * Copyright (c) 1991-1996 Silicon Graphics, Inc.
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and
6 * its documentation for any purpose is hereby granted without fee, provided
7 * that (i) the above copyright notices and this permission notice appear in
8 * all copies of the software and related documentation, and (ii) the names of
9 * Sam Leffler and Silicon Graphics may not be used in any advertising or
10 * publicity relating to the software without the specific, prior written
11 * permission of Sam Leffler and Silicon Graphics.
12 *
13 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
14 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
15 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
16 *
17 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
18 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
21 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22 * OF THIS SOFTWARE.
23 */
24
25/*
26 * TIFF Library UNIX-specific Routines.
27 */
28#include "tiffiop.h"
29#include <iostream>
30
31using namespace std;
32
33/*
34 ISO C++ uses a 'std::streamsize' type to define counts. This makes
35 it similar to, (but perhaps not the same as) size_t.
36
37 The std::ios::pos_type is used to represent stream positions as used
38 by tellg(), tellp(), seekg(), and seekp(). This makes it similar to
39 (but perhaps not the same as) 'off_t'. The std::ios::streampos type
40 is used for character streams, but is documented to not be an
41 integral type anymore, so it should *not* be assigned to an integral
42 type.
43
44 The std::ios::off_type is used to specify relative offsets needed by
45 the variants of seekg() and seekp() which accept a relative offset
46 argument.
47
48 Useful prototype knowledge:
49
50 Obtain read position
51 ios::pos_type basic_istream::tellg()
52
53 Set read position
54 basic_istream& basic_istream::seekg(ios::pos_type)
55 basic_istream& basic_istream::seekg(ios::off_type, ios_base::seekdir)
56
57 Read data
58 basic_istream& istream::read(char *str, streamsize count)
59
60 Number of characters read in last unformatted read
61 streamsize istream::gcount();
62
63 Obtain write position
64 ios::pos_type basic_ostream::tellp()
65
66 Set write position
67 basic_ostream& basic_ostream::seekp(ios::pos_type)
68 basic_ostream& basic_ostream::seekp(ios::off_type, ios_base::seekdir)
69
70 Write data
71 basic_ostream& ostream::write(const char *str, streamsize count)
72*/
73
74struct tiffis_data;
75struct tiffos_data;
76
77extern "C"
78{
79
84 static uint64_t _tiffosSeekProc(thandle_t fd, uint64_t off, int whence);
85 static uint64_t _tiffisSeekProc(thandle_t fd, uint64_t off, int whence);
88 static int _tiffosCloseProc(thandle_t fd);
89 static int _tiffisCloseProc(thandle_t fd);
90 static int _tiffDummyMapProcCxx(thandle_t, void **base, toff_t *size);
91 static void _tiffDummyUnmapProcCxx(thandle_t, void *base, toff_t size);
92 static TIFF *_tiffStreamOpen(const char *name, const char *mode, void *fd);
93
95 {
98 };
99
101 {
104 };
105
106 static tmsize_t _tiffosReadProc(thandle_t, void *, tmsize_t) { return 0; }
107
109 {
110 tiffis_data *data = reinterpret_cast<tiffis_data *>(fd);
111
112 // Verify that type does not overflow.
113 streamsize request_size = size;
114 if (static_cast<tmsize_t>(request_size) != size)
115 return static_cast<tmsize_t>(-1);
116
117 data->stream->read((char *)buf, request_size);
118
119 return static_cast<tmsize_t>(data->stream->gcount());
120 }
121
123 {
124 tiffos_data *data = reinterpret_cast<tiffos_data *>(fd);
125 ostream *os = data->stream;
126 ios::pos_type pos = os->tellp();
127
128 // Verify that type does not overflow.
129 streamsize request_size = size;
130 if (static_cast<tmsize_t>(request_size) != size)
131 return static_cast<tmsize_t>(-1);
132
133 os->write(reinterpret_cast<const char *>(buf), request_size);
134
135 return static_cast<tmsize_t>(os->tellp() - pos);
136 }
137
138 static tmsize_t _tiffisWriteProc(thandle_t, void *, tmsize_t) { return 0; }
139
141 {
142 tiffos_data *data = reinterpret_cast<tiffos_data *>(fd);
143 ostream *os = data->stream;
144
145 // if the stream has already failed, don't do anything
146 if (os->fail())
147 return static_cast<uint64_t>(-1);
148
149 switch (whence)
150 {
151 case SEEK_SET:
152 {
153 // Compute 64-bit offset
154 uint64_t new_offset =
155 static_cast<uint64_t>(data->start_pos) + off;
156
157 // Verify that value does not overflow
158 ios::off_type offset = static_cast<ios::off_type>(new_offset);
159 if (static_cast<uint64_t>(offset) != new_offset)
160 return static_cast<uint64_t>(-1);
161
162 os->seekp(offset, ios::beg);
163 break;
164 }
165 case SEEK_CUR:
166 {
167 // Verify that value does not overflow
168 ios::off_type offset = static_cast<ios::off_type>(off);
169 if (static_cast<uint64_t>(offset) != off)
170 return static_cast<uint64_t>(-1);
171
172 os->seekp(offset, ios::cur);
173 break;
174 }
175 case SEEK_END:
176 {
177 // Verify that value does not overflow
178 ios::off_type offset = static_cast<ios::off_type>(off);
179 if (static_cast<uint64_t>(offset) != off)
180 return static_cast<uint64_t>(-1);
181
182 os->seekp(offset, ios::end);
183 break;
184 }
185 }
186
187 // Attempt to workaround problems with seeking past the end of the
188 // stream. ofstream doesn't have a problem with this but
189 // ostrstream/ostringstream does. In that situation, add intermediate
190 // '\0' characters.
191 if (os->fail())
192 {
193 ios::iostate old_state;
195
196 old_state = os->rdstate();
197 // reset the fail bit or else tellp() won't work below
198 os->clear(os->rdstate() & ~ios::failbit);
199 switch (whence)
200 {
201 case SEEK_SET:
202 default:
203 origin = data->start_pos;
204 break;
205 case SEEK_CUR:
206 origin = os->tellp();
207 break;
208 case SEEK_END:
209 os->seekp(0, ios::end);
210 origin = os->tellp();
211 break;
212 }
213 // restore original stream state
214 os->clear(old_state);
215
216 // only do something if desired seek position is valid
217 if ((static_cast<uint64_t>(origin) + off) >
218 static_cast<uint64_t>(data->start_pos))
219 {
220 uint64_t num_fill;
221
222 // clear the fail bit
223 os->clear(os->rdstate() & ~ios::failbit);
224
225 // extend the stream to the expected size
226 os->seekp(0, ios::end);
227 num_fill = (static_cast<uint64_t>(origin)) + off - os->tellp();
228 for (uint64_t i = 0; i < num_fill; i++)
229 os->put('\0');
230
231 // retry the seek
232 os->seekp(static_cast<ios::off_type>(
233 static_cast<uint64_t>(origin) + off),
234 ios::beg);
235 }
236 }
237
238 return static_cast<uint64_t>(os->tellp());
239 }
240
242 {
243 tiffis_data *data = reinterpret_cast<tiffis_data *>(fd);
244
245 switch (whence)
246 {
247 case SEEK_SET:
248 {
249 // Compute 64-bit offset
250 uint64_t new_offset =
251 static_cast<uint64_t>(data->start_pos) + off;
252
253 // Verify that value does not overflow
254 ios::off_type offset = static_cast<ios::off_type>(new_offset);
255 if (static_cast<uint64_t>(offset) != new_offset)
256 return static_cast<uint64_t>(-1);
257
258 data->stream->seekg(offset, ios::beg);
259 break;
260 }
261 case SEEK_CUR:
262 {
263 // Verify that value does not overflow
264 ios::off_type offset = static_cast<ios::off_type>(off);
265 if (static_cast<uint64_t>(offset) != off)
266 return static_cast<uint64_t>(-1);
267
268 data->stream->seekg(offset, ios::cur);
269 break;
270 }
271 case SEEK_END:
272 {
273 // Verify that value does not overflow
274 ios::off_type offset = static_cast<ios::off_type>(off);
275 if (static_cast<uint64_t>(offset) != off)
276 return static_cast<uint64_t>(-1);
277
278 data->stream->seekg(offset, ios::end);
279 break;
280 }
281 }
282
283 return (uint64_t)(data->stream->tellg() - data->start_pos);
284 }
285
287 {
288 tiffos_data *data = reinterpret_cast<tiffos_data *>(fd);
289 ostream *os = data->stream;
290 ios::pos_type pos = os->tellp();
292
293 os->seekp(0, ios::end);
294 len = os->tellp();
295 os->seekp(pos);
296
297 return (uint64_t)len;
298 }
299
301 {
302 tiffis_data *data = reinterpret_cast<tiffis_data *>(fd);
303 ios::pos_type pos = data->stream->tellg();
305
306 data->stream->seekg(0, ios::end);
307 len = data->stream->tellg();
308 data->stream->seekg(pos);
309
310 return (uint64_t)len;
311 }
312
314 {
315 // Our stream was not allocated by us, so it shouldn't be closed by us.
316 delete reinterpret_cast<tiffos_data *>(fd);
317 return 0;
318 }
319
321 {
322 // Our stream was not allocated by us, so it shouldn't be closed by us.
323 delete reinterpret_cast<tiffis_data *>(fd);
324 return 0;
325 }
326
328 {
329 (void)base;
330 (void)size;
331 return (0);
332 }
333
335 {
336 (void)base;
337 (void)size;
338 }
339
340 /*
341 * Open a TIFF file descriptor for read/writing.
342 */
343 static TIFF *_tiffStreamOpen(const char *name, const char *mode, void *fd)
344 {
345 TIFF *tif;
346
347 if (strchr(mode, 'w'))
348 {
350 data->stream = reinterpret_cast<ostream *>(fd);
351 data->start_pos = data->stream->tellp();
352
353 // Open for writing.
354 tif = TIFFClientOpen(
355 name, mode, reinterpret_cast<thandle_t>(data), _tiffosReadProc,
358 if (!tif)
359 {
360 delete data;
361 }
362 }
363 else
364 {
366 data->stream = reinterpret_cast<istream *>(fd);
367 data->start_pos = data->stream->tellg();
368 // Open for reading.
369 tif = TIFFClientOpen(
370 name, mode, reinterpret_cast<thandle_t>(data), _tiffisReadProc,
373 if (!tif)
374 {
375 delete data;
376 }
377 }
378
379 return (tif);
380 }
381
382} /* extern "C" */
383
384TIFF *TIFFStreamOpen(const char *name, ostream *os)
385{
386 // If os is either a ostrstream or ostringstream, and has no data
387 // written to it yet, then tellp() will return -1 which will break us.
388 // We workaround this by writing out a dummy character and
389 // then seek back to the beginning.
390 if (!os->fail() && static_cast<int>(os->tellp()) < 0)
391 {
392 *os << '\0';
393 os->seekp(0);
394 }
395
396 // NB: We don't support mapped files with streams so add 'm'
397 return _tiffStreamOpen(name, "wm", os);
398}
399
400TIFF *TIFFStreamOpen(const char *name, istream *is)
401{
402 // NB: We don't support mapped files with streams so add 'm'
403 return _tiffStreamOpen(name, "rm", is);
404}
basic_ostream< char, char_traits< char > > ostream
Definition: _iosfwd.h:121
basic_istream< char, char_traits< char > > istream
Definition: _iosfwd.h:120
#define SEEK_END
Definition: cabinet.c:29
ptrdiff_t streamsize
Definition: char_traits.h:81
_Traits::off_type off_type
Definition: _ios.h:54
void clear(iostate __state=goodbit)
Definition: _ios.h:91
_Traits::pos_type pos_type
Definition: _ios.h:53
pos_type tellg()
Definition: _istream.c:494
_Self & seekp(pos_type __pos)
Definition: _ostream.h:147
pos_type tellp()
Definition: _ostream.h:141
_Self & put(char_type __c)
Definition: _ostream.c:408
_Self & write(const char_type *__s, streamsize __n)
Definition: _ostream.c:430
iostate rdstate() const
Definition: _ios_base.h:170
bool fail() const
Definition: _ios_base.h:174
int iostate
Definition: _ios_base.h:58
UINT64 uint64_t
Definition: types.h:77
#define SEEK_CUR
Definition: stdio.h:44
_ACRTIMP char *__cdecl strchr(const char *, int)
Definition: string.c:3286
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLsizeiptr size
Definition: glext.h:5919
GLintptr offset
Definition: glext.h:5920
GLenum mode
Definition: glext.h:6217
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
voidpf uLong int origin
Definition: ioapi.h:144
#define SEEK_SET
Definition: jmemansi.c:26
Definition: features.h:417
static int fd
Definition: io.c:51
Definition: name.c:39
Definition: tiffiop.h:113
ios::pos_type start_pos
Definition: tif_stream.cxx:97
istream * stream
Definition: tif_stream.cxx:96
ostream * stream
Definition: tif_stream.cxx:102
ios::pos_type start_pos
Definition: tif_stream.cxx:103
TIFF * TIFFClientOpen(const char *name, const char *mode, thandle_t clientdata, TIFFReadWriteProc readproc, TIFFReadWriteProc writeproc, TIFFSeekProc seekproc, TIFFCloseProc closeproc, TIFFSizeProc sizeproc, TIFFMapFileProc mapproc, TIFFUnmapFileProc unmapproc)
Definition: tif_open.c:289
static TIFF * _tiffStreamOpen(const char *name, const char *mode, void *fd)
Definition: tif_stream.cxx:343
static int _tiffDummyMapProcCxx(thandle_t, void **base, toff_t *size)
Definition: tif_stream.cxx:327
static uint64_t _tiffisSeekProc(thandle_t fd, uint64_t off, int whence)
Definition: tif_stream.cxx:241
static int _tiffisCloseProc(thandle_t fd)
Definition: tif_stream.cxx:320
static uint64_t _tiffosSeekProc(thandle_t fd, uint64_t off, int whence)
Definition: tif_stream.cxx:140
static tmsize_t _tiffisWriteProc(thandle_t, void *, tmsize_t)
Definition: tif_stream.cxx:138
static uint64_t _tiffisSizeProc(thandle_t fd)
Definition: tif_stream.cxx:300
static tmsize_t _tiffosWriteProc(thandle_t fd, void *buf, tmsize_t size)
Definition: tif_stream.cxx:122
static tmsize_t _tiffisReadProc(thandle_t fd, void *buf, tmsize_t size)
Definition: tif_stream.cxx:108
static void _tiffDummyUnmapProcCxx(thandle_t, void *base, toff_t size)
Definition: tif_stream.cxx:334
static tmsize_t _tiffosReadProc(thandle_t, void *, tmsize_t)
Definition: tif_stream.cxx:106
TIFF * TIFFStreamOpen(const char *name, ostream *os)
Definition: tif_stream.cxx:384
static int _tiffosCloseProc(thandle_t fd)
Definition: tif_stream.cxx:313
static uint64_t _tiffosSizeProc(thandle_t fd)
Definition: tif_stream.cxx:286
TIFF_SSIZE_T tmsize_t
Definition: tiffio.h:67
uint64_t toff_t
Definition: tiffio.h:70