1
/* $Id: tif_stream.cxx,v 1.11 2010-12-11 23:12:29 faxguy Exp $ */
4
* Copyright (c) 1988-1996 Sam Leffler
5
* Copyright (c) 1991-1996 Silicon Graphics, Inc.
7
* Permission to use, copy, modify, distribute, and sell this software and
8
* its documentation for any purpose is hereby granted without fee, provided
9
* that (i) the above copyright notices and this permission notice appear in
10
* all copies of the software and related documentation, and (ii) the names of
11
* Sam Leffler and Silicon Graphics may not be used in any advertising or
12
* publicity relating to the software without the specific, prior written
13
* permission of Sam Leffler and Silicon Graphics.
15
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
16
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
17
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
19
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
20
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
21
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
22
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
23
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
28
* TIFF Library UNIX-specific Routines.
39
ISO C++ uses a 'std::streamsize' type to define counts. This makes
40
it similar to, (but perhaps not the same as) size_t.
42
The std::ios::pos_type is used to represent stream positions as used
43
by tellg(), tellp(), seekg(), and seekp(). This makes it similar to
44
(but perhaps not the same as) 'off_t'. The std::ios::streampos type
45
is used for character streams, but is documented to not be an
46
integral type anymore, so it should *not* be assigned to an integral
49
The std::ios::off_type is used to specify relative offsets needed by
50
the variants of seekg() and seekp() which accept a relative offset
53
Useful prototype knowledge:
56
ios::pos_type basic_istream::tellg()
59
basic_istream& basic_istream::seekg(ios::pos_type)
60
basic_istream& basic_istream::seekg(ios::off_type, ios_base::seekdir)
63
basic_istream& istream::read(char *str, streamsize count)
65
Number of characters read in last unformatted read
66
streamsize istream::gcount();
69
ios::pos_type basic_ostream::tellp()
72
basic_ostream& basic_ostream::seekp(ios::pos_type)
73
basic_ostream& basic_ostream::seekp(ios::off_type, ios_base::seekdir)
76
basic_ostream& ostream::write(const char *str, streamsize count)
84
static tmsize_t _tiffosReadProc(thandle_t, void*, tmsize_t);
85
static tmsize_t _tiffisReadProc(thandle_t fd, void* buf, tmsize_t size);
86
static tmsize_t _tiffosWriteProc(thandle_t fd, void* buf, tmsize_t size);
87
static tmsize_t _tiffisWriteProc(thandle_t, void*, tmsize_t);
88
static uint64 _tiffosSeekProc(thandle_t fd, uint64 off, int whence);
89
static uint64 _tiffisSeekProc(thandle_t fd, uint64 off, int whence);
90
static uint64 _tiffosSizeProc(thandle_t fd);
91
static uint64 _tiffisSizeProc(thandle_t fd);
92
static int _tiffosCloseProc(thandle_t fd);
93
static int _tiffisCloseProc(thandle_t fd);
94
static int _tiffDummyMapProc(thandle_t , void** base, toff_t* size );
95
static void _tiffDummyUnmapProc(thandle_t , void* base, toff_t size );
96
static TIFF* _tiffStreamOpen(const char* name, const char* mode, void *fd);
101
ios::pos_type start_pos;
107
ios::pos_type start_pos;
111
_tiffosReadProc(thandle_t, void*, tmsize_t)
117
_tiffisReadProc(thandle_t fd, void* buf, tmsize_t size)
119
tiffis_data *data = reinterpret_cast<tiffis_data *>(fd);
121
// Verify that type does not overflow.
122
streamsize request_size = size;
123
if (static_cast<tmsize_t>(request_size) != size)
124
return static_cast<tmsize_t>(-1);
126
data->stream->read((char *) buf, request_size);
128
return static_cast<tmsize_t>(data->stream->gcount());
132
_tiffosWriteProc(thandle_t fd, void* buf, tmsize_t size)
134
tiffos_data *data = reinterpret_cast<tiffos_data *>(fd);
135
ostream *os = data->stream;
136
ios::pos_type pos = os->tellp();
138
// Verify that type does not overflow.
139
streamsize request_size = size;
140
if (static_cast<tmsize_t>(request_size) != size)
141
return static_cast<tmsize_t>(-1);
143
os->write(reinterpret_cast<const char *>(buf), request_size);
145
return static_cast<tmsize_t>(os->tellp() - pos);
149
_tiffisWriteProc(thandle_t, void*, tmsize_t)
155
_tiffosSeekProc(thandle_t fd, uint64 off, int whence)
157
tiffos_data *data = reinterpret_cast<tiffos_data *>(fd);
158
ostream *os = data->stream;
160
// if the stream has already failed, don't do anything
162
return static_cast<uint64>(-1);
167
// Compute 64-bit offset
168
uint64 new_offset = static_cast<uint64>(data->start_pos) + off;
170
// Verify that value does not overflow
171
ios::off_type offset = static_cast<ios::off_type>(new_offset);
172
if (static_cast<uint64>(offset) != new_offset)
173
return static_cast<uint64>(-1);
175
os->seekp(offset, ios::beg);
180
// Verify that value does not overflow
181
ios::off_type offset = static_cast<ios::off_type>(off);
182
if (static_cast<uint64>(offset) != off)
183
return static_cast<uint64>(-1);
185
os->seekp(offset, ios::cur);
190
// Verify that value does not overflow
191
ios::off_type offset = static_cast<ios::off_type>(off);
192
if (static_cast<uint64>(offset) != off)
193
return static_cast<uint64>(-1);
195
os->seekp(offset, ios::end);
200
// Attempt to workaround problems with seeking past the end of the
201
// stream. ofstream doesn't have a problem with this but
202
// ostrstream/ostringstream does. In that situation, add intermediate
208
ios::iostate old_state;
210
ios::pos_type origin;
212
old_state = os->rdstate();
213
// reset the fail bit or else tellp() won't work below
214
os->clear(os->rdstate() & ~ios::failbit);
218
origin = data->start_pos;
221
origin = os->tellp();
224
os->seekp(0, ios::end);
225
origin = os->tellp();
228
// restore original stream state
229
os->clear(old_state);
231
// only do something if desired seek position is valid
232
if( (static_cast<uint64>(origin) + off) > static_cast<uint64>(data->start_pos) ) {
235
// clear the fail bit
236
os->clear(os->rdstate() & ~ios::failbit);
238
// extend the stream to the expected size
239
os->seekp(0, ios::end);
240
num_fill = (static_cast<uint64>(origin)) + off - os->tellp();
241
for( uint64 i = 0; i < num_fill; i++ )
245
os->seekp(static_cast<ios::off_type>(static_cast<uint64>(origin) + off), ios::beg);
249
return static_cast<uint64>(os->tellp());
253
_tiffisSeekProc(thandle_t fd, uint64 off, int whence)
255
tiffis_data *data = reinterpret_cast<tiffis_data *>(fd);
260
// Compute 64-bit offset
261
uint64 new_offset = static_cast<uint64>(data->start_pos) + off;
263
// Verify that value does not overflow
264
ios::off_type offset = static_cast<ios::off_type>(new_offset);
265
if (static_cast<uint64>(offset) != new_offset)
266
return static_cast<uint64>(-1);
268
data->stream->seekg(offset, ios::beg);
273
// Verify that value does not overflow
274
ios::off_type offset = static_cast<ios::off_type>(off);
275
if (static_cast<uint64>(offset) != off)
276
return static_cast<uint64>(-1);
278
data->stream->seekg(offset, ios::cur);
283
// Verify that value does not overflow
284
ios::off_type offset = static_cast<ios::off_type>(off);
285
if (static_cast<uint64>(offset) != off)
286
return static_cast<uint64>(-1);
288
data->stream->seekg(offset, ios::end);
293
return (uint64) (data->stream->tellg() - data->start_pos);
297
_tiffosSizeProc(thandle_t fd)
299
tiffos_data *data = reinterpret_cast<tiffos_data *>(fd);
300
ostream *os = data->stream;
301
ios::pos_type pos = os->tellp();
304
os->seekp(0, ios::end);
312
_tiffisSizeProc(thandle_t fd)
314
tiffis_data *data = reinterpret_cast<tiffis_data *>(fd);
315
ios::pos_type pos = data->stream->tellg();
318
data->stream->seekg(0, ios::end);
319
len = data->stream->tellg();
320
data->stream->seekg(pos);
326
_tiffosCloseProc(thandle_t fd)
328
// Our stream was not allocated by us, so it shouldn't be closed by us.
329
delete reinterpret_cast<tiffos_data *>(fd);
334
_tiffisCloseProc(thandle_t fd)
336
// Our stream was not allocated by us, so it shouldn't be closed by us.
337
delete reinterpret_cast<tiffis_data *>(fd);
342
_tiffDummyMapProc(thandle_t , void** base, toff_t* size )
348
_tiffDummyUnmapProc(thandle_t , void* base, toff_t size )
353
* Open a TIFF file descriptor for read/writing.
356
_tiffStreamOpen(const char* name, const char* mode, void *fd)
360
if( strchr(mode, 'w') ) {
361
tiffos_data *data = new tiffos_data;
362
data->stream = reinterpret_cast<ostream *>(fd);
363
data->start_pos = data->stream->tellp();
366
tif = TIFFClientOpen(name, mode,
367
reinterpret_cast<thandle_t>(data),
374
_tiffDummyUnmapProc);
376
tiffis_data *data = new tiffis_data;
377
data->stream = reinterpret_cast<istream *>(fd);
378
data->start_pos = data->stream->tellg();
380
tif = TIFFClientOpen(name, mode,
381
reinterpret_cast<thandle_t>(data),
388
_tiffDummyUnmapProc);
397
TIFFStreamOpen(const char* name, ostream *os)
399
// If os is either a ostrstream or ostringstream, and has no data
400
// written to it yet, then tellp() will return -1 which will break us.
401
// We workaround this by writing out a dummy character and
402
// then seek back to the beginning.
403
if( !os->fail() && static_cast<int>(os->tellp()) < 0 ) {
408
// NB: We don't support mapped files with streams so add 'm'
409
return _tiffStreamOpen(name, "wm", os);
413
TIFFStreamOpen(const char* name, istream *is)
415
// NB: We don't support mapped files with streams so add 'm'
416
return _tiffStreamOpen(name, "rm", is);
419
/* vim: set ts=8 sts=8 sw=8 noet: */
423
indent-tabs-mode: true