]>
git.saurik.com Git - wxWidgets.git/blob - src/tiff/libtiff/tif_stream.cxx
3 * Copyright (c) 1988-1996 Sam Leffler
4 * Copyright (c) 1991-1996 Silicon Graphics, Inc.
6 * Permission to use, copy, modify, distribute, and sell this software and
7 * its documentation for any purpose is hereby granted without fee, provided
8 * that (i) the above copyright notices and this permission notice appear in
9 * all copies of the software and related documentation, and (ii) the names of
10 * Sam Leffler and Silicon Graphics may not be used in any advertising or
11 * publicity relating to the software without the specific, prior written
12 * permission of Sam Leffler and Silicon Graphics.
14 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
15 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
16 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
18 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
19 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
20 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
21 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
22 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
27 * TIFF Library UNIX-specific Routines.
37 ISO C++ uses a 'std::streamsize' type to define counts. This makes
38 it similar to, (but perhaps not the same as) size_t.
40 The std::ios::pos_type is used to represent stream positions as used
41 by tellg(), tellp(), seekg(), and seekp(). This makes it similar to
42 (but perhaps not the same as) 'off_t'. The std::ios::streampos type
43 is used for character streams, but is documented to not be an
44 integral type anymore, so it should *not* be assigned to an integral
47 The std::ios::off_type is used to specify relative offsets needed by
48 the variants of seekg() and seekp() which accept a relative offset
51 Useful prototype knowledge:
54 ios::pos_type basic_istream::tellg()
57 basic_istream& basic_istream::seekg(ios::pos_type)
58 basic_istream& basic_istream::seekg(ios::off_type, ios_base::seekdir)
61 basic_istream& istream::read(char *str, streamsize count)
63 Number of characters read in last unformatted read
64 streamsize istream::gcount();
67 ios::pos_type basic_ostream::tellp()
70 basic_ostream& basic_ostream::seekp(ios::pos_type)
71 basic_ostream& basic_ostream::seekp(ios::off_type, ios_base::seekdir)
74 basic_ostream& ostream::write(const char *str, streamsize count)
82 static tmsize_t
_tiffosReadProc(thandle_t
, void*, tmsize_t
);
83 static tmsize_t
_tiffisReadProc(thandle_t fd
, void* buf
, tmsize_t size
);
84 static tmsize_t
_tiffosWriteProc(thandle_t fd
, void* buf
, tmsize_t size
);
85 static tmsize_t
_tiffisWriteProc(thandle_t
, void*, tmsize_t
);
86 static uint64
_tiffosSeekProc(thandle_t fd
, uint64 off
, int whence
);
87 static uint64
_tiffisSeekProc(thandle_t fd
, uint64 off
, int whence
);
88 static uint64
_tiffosSizeProc(thandle_t fd
);
89 static uint64
_tiffisSizeProc(thandle_t fd
);
90 static int _tiffosCloseProc(thandle_t fd
);
91 static int _tiffisCloseProc(thandle_t fd
);
92 static int _tiffDummyMapProc(thandle_t
, void** base
, toff_t
* size
);
93 static void _tiffDummyUnmapProc(thandle_t
, void* base
, toff_t size
);
94 static TIFF
* _tiffStreamOpen(const char* name
, const char* mode
, void *fd
);
99 ios::pos_type start_pos
;
105 ios::pos_type start_pos
;
109 _tiffosReadProc(thandle_t
, void*, tmsize_t
)
115 _tiffisReadProc(thandle_t fd
, void* buf
, tmsize_t size
)
117 tiffis_data
*data
= reinterpret_cast<tiffis_data
*>(fd
);
119 // Verify that type does not overflow.
120 streamsize request_size
= size
;
121 if (static_cast<tmsize_t
>(request_size
) != size
)
122 return static_cast<tmsize_t
>(-1);
124 data
->stream
->read((char *) buf
, request_size
);
126 return static_cast<tmsize_t
>(data
->stream
->gcount());
130 _tiffosWriteProc(thandle_t fd
, void* buf
, tmsize_t size
)
132 tiffos_data
*data
= reinterpret_cast<tiffos_data
*>(fd
);
133 ostream
*os
= data
->stream
;
134 ios::pos_type pos
= os
->tellp();
136 // Verify that type does not overflow.
137 streamsize request_size
= size
;
138 if (static_cast<tmsize_t
>(request_size
) != size
)
139 return static_cast<tmsize_t
>(-1);
141 os
->write(reinterpret_cast<const char *>(buf
), request_size
);
143 return static_cast<tmsize_t
>(os
->tellp() - pos
);
147 _tiffisWriteProc(thandle_t
, void*, tmsize_t
)
153 _tiffosSeekProc(thandle_t fd
, uint64 off
, int whence
)
155 tiffos_data
*data
= reinterpret_cast<tiffos_data
*>(fd
);
156 ostream
*os
= data
->stream
;
158 // if the stream has already failed, don't do anything
160 return static_cast<uint64
>(-1);
165 // Compute 64-bit offset
166 uint64 new_offset
= static_cast<uint64
>(data
->start_pos
) + off
;
168 // Verify that value does not overflow
169 ios::off_type offset
= static_cast<ios::off_type
>(new_offset
);
170 if (static_cast<uint64
>(offset
) != new_offset
)
171 return static_cast<uint64
>(-1);
173 os
->seekp(offset
, ios::beg
);
178 // Verify that value does not overflow
179 ios::off_type offset
= static_cast<ios::off_type
>(off
);
180 if (static_cast<uint64
>(offset
) != off
)
181 return static_cast<uint64
>(-1);
183 os
->seekp(offset
, ios::cur
);
188 // Verify that value does not overflow
189 ios::off_type offset
= static_cast<ios::off_type
>(off
);
190 if (static_cast<uint64
>(offset
) != off
)
191 return static_cast<uint64
>(-1);
193 os
->seekp(offset
, ios::end
);
198 // Attempt to workaround problems with seeking past the end of the
199 // stream. ofstream doesn't have a problem with this but
200 // ostrstream/ostringstream does. In that situation, add intermediate
206 ios::iostate old_state
;
208 ios::pos_type origin
;
210 old_state
= os
->rdstate();
211 // reset the fail bit or else tellp() won't work below
212 os
->clear(os
->rdstate() & ~ios::failbit
);
216 origin
= data
->start_pos
;
219 origin
= os
->tellp();
222 os
->seekp(0, ios::end
);
223 origin
= os
->tellp();
226 // restore original stream state
227 os
->clear(old_state
);
229 // only do something if desired seek position is valid
230 if( (static_cast<uint64
>(origin
) + off
) > static_cast<uint64
>(data
->start_pos
) ) {
233 // clear the fail bit
234 os
->clear(os
->rdstate() & ~ios::failbit
);
236 // extend the stream to the expected size
237 os
->seekp(0, ios::end
);
238 num_fill
= (static_cast<uint64
>(origin
)) + off
- os
->tellp();
239 for( uint64 i
= 0; i
< num_fill
; i
++ )
243 os
->seekp(static_cast<ios::off_type
>(static_cast<uint64
>(origin
) + off
), ios::beg
);
247 return static_cast<uint64
>(os
->tellp());
251 _tiffisSeekProc(thandle_t fd
, uint64 off
, int whence
)
253 tiffis_data
*data
= reinterpret_cast<tiffis_data
*>(fd
);
258 // Compute 64-bit offset
259 uint64 new_offset
= static_cast<uint64
>(data
->start_pos
) + off
;
261 // Verify that value does not overflow
262 ios::off_type offset
= static_cast<ios::off_type
>(new_offset
);
263 if (static_cast<uint64
>(offset
) != new_offset
)
264 return static_cast<uint64
>(-1);
266 data
->stream
->seekg(offset
, ios::beg
);
271 // Verify that value does not overflow
272 ios::off_type offset
= static_cast<ios::off_type
>(off
);
273 if (static_cast<uint64
>(offset
) != off
)
274 return static_cast<uint64
>(-1);
276 data
->stream
->seekg(offset
, ios::cur
);
281 // Verify that value does not overflow
282 ios::off_type offset
= static_cast<ios::off_type
>(off
);
283 if (static_cast<uint64
>(offset
) != off
)
284 return static_cast<uint64
>(-1);
286 data
->stream
->seekg(offset
, ios::end
);
291 return (uint64
) (data
->stream
->tellg() - data
->start_pos
);
295 _tiffosSizeProc(thandle_t fd
)
297 tiffos_data
*data
= reinterpret_cast<tiffos_data
*>(fd
);
298 ostream
*os
= data
->stream
;
299 ios::pos_type pos
= os
->tellp();
302 os
->seekp(0, ios::end
);
310 _tiffisSizeProc(thandle_t fd
)
312 tiffis_data
*data
= reinterpret_cast<tiffis_data
*>(fd
);
313 ios::pos_type pos
= data
->stream
->tellg();
316 data
->stream
->seekg(0, ios::end
);
317 len
= data
->stream
->tellg();
318 data
->stream
->seekg(pos
);
324 _tiffosCloseProc(thandle_t fd
)
326 // Our stream was not allocated by us, so it shouldn't be closed by us.
327 delete reinterpret_cast<tiffos_data
*>(fd
);
332 _tiffisCloseProc(thandle_t fd
)
334 // Our stream was not allocated by us, so it shouldn't be closed by us.
335 delete reinterpret_cast<tiffis_data
*>(fd
);
340 _tiffDummyMapProc(thandle_t
, void** base
, toff_t
* size
)
346 _tiffDummyUnmapProc(thandle_t
, void* base
, toff_t size
)
351 * Open a TIFF file descriptor for read/writing.
354 _tiffStreamOpen(const char* name
, const char* mode
, void *fd
)
358 if( strchr(mode
, 'w') ) {
359 tiffos_data
*data
= new tiffos_data
;
360 data
->stream
= reinterpret_cast<ostream
*>(fd
);
361 data
->start_pos
= data
->stream
->tellp();
364 tif
= TIFFClientOpen(name
, mode
,
365 reinterpret_cast<thandle_t
>(data
),
372 _tiffDummyUnmapProc
);
374 tiffis_data
*data
= new tiffis_data
;
375 data
->stream
= reinterpret_cast<istream
*>(fd
);
376 data
->start_pos
= data
->stream
->tellg();
378 tif
= TIFFClientOpen(name
, mode
,
379 reinterpret_cast<thandle_t
>(data
),
386 _tiffDummyUnmapProc
);
395 TIFFStreamOpen(const char* name
, ostream
*os
)
397 // If os is either a ostrstream or ostringstream, and has no data
398 // written to it yet, then tellp() will return -1 which will break us.
399 // We workaround this by writing out a dummy character and
400 // then seek back to the beginning.
401 if( !os
->fail() && static_cast<int>(os
->tellp()) < 0 ) {
406 // NB: We don't support mapped files with streams so add 'm'
407 return _tiffStreamOpen(name
, "wm", os
);
411 TIFFStreamOpen(const char* name
, istream
*is
)
413 // NB: We don't support mapped files with streams so add 'm'
414 return _tiffStreamOpen(name
, "rm", is
);
417 /* vim: set ts=8 sts=8 sw=8 noet: */
421 indent-tabs-mode: true