]>
git.saurik.com Git - wxWidgets.git/blob - src/tiff/libtiff/tif_stream.cxx
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.
38 ISO C++ uses a 'std::streamsize' type to define counts. This makes
39 it similar to, (but perhaps not the same as) size_t.
41 The std::ios::pos_type is used to represent stream positions as used
42 by tellg(), tellp(), seekg(), and seekp(). This makes it similar to
43 (but perhaps not the same as) 'off_t'. The std::ios::streampos type
44 is used for character streams, but is documented to not be an
45 integral type anymore, so it should *not* be assigned to an integral
48 The std::ios::off_type is used to specify relative offsets needed by
49 the variants of seekg() and seekp() which accept a relative offset
52 Useful prototype knowledge:
55 ios::pos_type basic_istream::tellg()
58 basic_istream& basic_istream::seekg(ios::pos_type)
59 basic_istream& basic_istream::seekg(ios::off_type, ios_base::seekdir)
62 basic_istream& istream::read(char *str, streamsize count)
64 Number of characters read in last unformatted read
65 streamsize istream::gcount();
68 ios::pos_type basic_ostream::tellp()
71 basic_ostream& basic_ostream::seekp(ios::pos_type)
72 basic_ostream& basic_ostream::seekp(ios::off_type, ios_base::seekdir)
75 basic_ostream& ostream::write(const char *str, streamsize count)
83 static tmsize_t
_tiffosReadProc(thandle_t
, void*, tmsize_t
);
84 static tmsize_t
_tiffisReadProc(thandle_t fd
, void* buf
, tmsize_t size
);
85 static tmsize_t
_tiffosWriteProc(thandle_t fd
, void* buf
, tmsize_t size
);
86 static tmsize_t
_tiffisWriteProc(thandle_t
, void*, tmsize_t
);
87 static uint64
_tiffosSeekProc(thandle_t fd
, uint64 off
, int whence
);
88 static uint64
_tiffisSeekProc(thandle_t fd
, uint64 off
, int whence
);
89 static uint64
_tiffosSizeProc(thandle_t fd
);
90 static uint64
_tiffisSizeProc(thandle_t fd
);
91 static int _tiffosCloseProc(thandle_t fd
);
92 static int _tiffisCloseProc(thandle_t fd
);
93 static int _tiffDummyMapProc(thandle_t
, void** base
, toff_t
* size
);
94 static void _tiffDummyUnmapProc(thandle_t
, void* base
, toff_t size
);
95 static TIFF
* _tiffStreamOpen(const char* name
, const char* mode
, void *fd
);
100 ios::pos_type start_pos
;
106 ios::pos_type start_pos
;
110 _tiffosReadProc(thandle_t
, void*, tmsize_t
)
116 _tiffisReadProc(thandle_t fd
, void* buf
, tmsize_t size
)
118 tiffis_data
*data
= reinterpret_cast<tiffis_data
*>(fd
);
120 // Verify that type does not overflow.
121 streamsize request_size
= size
;
122 if (static_cast<tmsize_t
>(request_size
) != size
)
123 return static_cast<tmsize_t
>(-1);
125 data
->stream
->read((char *) buf
, request_size
);
127 return static_cast<tmsize_t
>(data
->stream
->gcount());
131 _tiffosWriteProc(thandle_t fd
, void* buf
, tmsize_t size
)
133 tiffos_data
*data
= reinterpret_cast<tiffos_data
*>(fd
);
134 ostream
*os
= data
->stream
;
135 ios::pos_type pos
= os
->tellp();
137 // Verify that type does not overflow.
138 streamsize request_size
= size
;
139 if (static_cast<tmsize_t
>(request_size
) != size
)
140 return static_cast<tmsize_t
>(-1);
142 os
->write(reinterpret_cast<const char *>(buf
), request_size
);
144 return static_cast<tmsize_t
>(os
->tellp() - pos
);
148 _tiffisWriteProc(thandle_t
, void*, tmsize_t
)
154 _tiffosSeekProc(thandle_t fd
, uint64 off
, int whence
)
156 tiffos_data
*data
= reinterpret_cast<tiffos_data
*>(fd
);
157 ostream
*os
= data
->stream
;
159 // if the stream has already failed, don't do anything
161 return static_cast<uint64
>(-1);
166 // Compute 64-bit offset
167 uint64 new_offset
= static_cast<uint64
>(data
->start_pos
) + off
;
169 // Verify that value does not overflow
170 ios::off_type offset
= static_cast<ios::off_type
>(new_offset
);
171 if (static_cast<uint64
>(offset
) != new_offset
)
172 return static_cast<uint64
>(-1);
174 os
->seekp(offset
, ios::beg
);
179 // Verify that value does not overflow
180 ios::off_type offset
= static_cast<ios::off_type
>(off
);
181 if (static_cast<uint64
>(offset
) != off
)
182 return static_cast<uint64
>(-1);
184 os
->seekp(offset
, ios::cur
);
189 // Verify that value does not overflow
190 ios::off_type offset
= static_cast<ios::off_type
>(off
);
191 if (static_cast<uint64
>(offset
) != off
)
192 return static_cast<uint64
>(-1);
194 os
->seekp(offset
, ios::end
);
199 // Attempt to workaround problems with seeking past the end of the
200 // stream. ofstream doesn't have a problem with this but
201 // ostrstream/ostringstream does. In that situation, add intermediate
207 ios::iostate old_state
;
209 ios::pos_type origin
;
211 old_state
= os
->rdstate();
212 // reset the fail bit or else tellp() won't work below
213 os
->clear(os
->rdstate() & ~ios::failbit
);
217 origin
= data
->start_pos
;
220 origin
= os
->tellp();
223 os
->seekp(0, ios::end
);
224 origin
= os
->tellp();
227 // restore original stream state
228 os
->clear(old_state
);
230 // only do something if desired seek position is valid
231 if( (static_cast<uint64
>(origin
) + off
) > static_cast<uint64
>(data
->start_pos
) ) {
234 // clear the fail bit
235 os
->clear(os
->rdstate() & ~ios::failbit
);
237 // extend the stream to the expected size
238 os
->seekp(0, ios::end
);
239 num_fill
= (static_cast<uint64
>(origin
)) + off
- os
->tellp();
240 for( uint64 i
= 0; i
< num_fill
; i
++ )
244 os
->seekp(static_cast<ios::off_type
>(static_cast<uint64
>(origin
) + off
), ios::beg
);
248 return static_cast<uint64
>(os
->tellp());
252 _tiffisSeekProc(thandle_t fd
, uint64 off
, int whence
)
254 tiffis_data
*data
= reinterpret_cast<tiffis_data
*>(fd
);
259 // Compute 64-bit offset
260 uint64 new_offset
= static_cast<uint64
>(data
->start_pos
) + off
;
262 // Verify that value does not overflow
263 ios::off_type offset
= static_cast<ios::off_type
>(new_offset
);
264 if (static_cast<uint64
>(offset
) != new_offset
)
265 return static_cast<uint64
>(-1);
267 data
->stream
->seekg(offset
, ios::beg
);
272 // Verify that value does not overflow
273 ios::off_type offset
= static_cast<ios::off_type
>(off
);
274 if (static_cast<uint64
>(offset
) != off
)
275 return static_cast<uint64
>(-1);
277 data
->stream
->seekg(offset
, ios::cur
);
282 // Verify that value does not overflow
283 ios::off_type offset
= static_cast<ios::off_type
>(off
);
284 if (static_cast<uint64
>(offset
) != off
)
285 return static_cast<uint64
>(-1);
287 data
->stream
->seekg(offset
, ios::end
);
292 return (uint64
) (data
->stream
->tellg() - data
->start_pos
);
296 _tiffosSizeProc(thandle_t fd
)
298 tiffos_data
*data
= reinterpret_cast<tiffos_data
*>(fd
);
299 ostream
*os
= data
->stream
;
300 ios::pos_type pos
= os
->tellp();
303 os
->seekp(0, ios::end
);
311 _tiffisSizeProc(thandle_t fd
)
313 tiffis_data
*data
= reinterpret_cast<tiffis_data
*>(fd
);
314 ios::pos_type pos
= data
->stream
->tellg();
317 data
->stream
->seekg(0, ios::end
);
318 len
= data
->stream
->tellg();
319 data
->stream
->seekg(pos
);
325 _tiffosCloseProc(thandle_t fd
)
327 // Our stream was not allocated by us, so it shouldn't be closed by us.
328 delete reinterpret_cast<tiffos_data
*>(fd
);
333 _tiffisCloseProc(thandle_t fd
)
335 // Our stream was not allocated by us, so it shouldn't be closed by us.
336 delete reinterpret_cast<tiffis_data
*>(fd
);
341 _tiffDummyMapProc(thandle_t
, void** base
, toff_t
* size
)
347 _tiffDummyUnmapProc(thandle_t
, void* base
, toff_t size
)
352 * Open a TIFF file descriptor for read/writing.
355 _tiffStreamOpen(const char* name
, const char* mode
, void *fd
)
359 if( strchr(mode
, 'w') ) {
360 tiffos_data
*data
= new tiffos_data
;
361 data
->stream
= reinterpret_cast<ostream
*>(fd
);
362 data
->start_pos
= data
->stream
->tellp();
365 tif
= TIFFClientOpen(name
, mode
,
366 reinterpret_cast<thandle_t
>(data
),
373 _tiffDummyUnmapProc
);
375 tiffis_data
*data
= new tiffis_data
;
376 data
->stream
= reinterpret_cast<istream
*>(fd
);
377 data
->start_pos
= data
->stream
->tellg();
379 tif
= TIFFClientOpen(name
, mode
,
380 reinterpret_cast<thandle_t
>(data
),
387 _tiffDummyUnmapProc
);
396 TIFFStreamOpen(const char* name
, ostream
*os
)
398 // If os is either a ostrstream or ostringstream, and has no data
399 // written to it yet, then tellp() will return -1 which will break us.
400 // We workaround this by writing out a dummy character and
401 // then seek back to the beginning.
402 if( !os
->fail() && static_cast<int>(os
->tellp()) < 0 ) {
407 // NB: We don't support mapped files with streams so add 'm'
408 return _tiffStreamOpen(name
, "wm", os
);
412 TIFFStreamOpen(const char* name
, istream
*is
)
414 // NB: We don't support mapped files with streams so add 'm'
415 return _tiffStreamOpen(name
, "rm", is
);
418 /* vim: set ts=8 sts=8 sw=8 noet: */
422 indent-tabs-mode: true