ReactOS 0.4.15-dev-7924-g5949c20
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
31#ifndef __VMS
32using namespace std;
33#endif
34
35/*
36 ISO C++ uses a 'std::streamsize' type to define counts. This makes
37 it similar to, (but perhaps not the same as) size_t.
38
39 The std::ios::pos_type is used to represent stream positions as used
40 by tellg(), tellp(), seekg(), and seekp(). This makes it similar to
41 (but perhaps not the same as) 'off_t'. The std::ios::streampos type
42 is used for character streams, but is documented to not be an
43 integral type anymore, so it should *not* be assigned to an integral
44 type.
45
46 The std::ios::off_type is used to specify relative offsets needed by
47 the variants of seekg() and seekp() which accept a relative offset
48 argument.
49
50 Useful prototype knowledge:
51
52 Obtain read position
53 ios::pos_type basic_istream::tellg()
54
55 Set read position
56 basic_istream& basic_istream::seekg(ios::pos_type)
57 basic_istream& basic_istream::seekg(ios::off_type, ios_base::seekdir)
58
59 Read data
60 basic_istream& istream::read(char *str, streamsize count)
61
62 Number of characters read in last unformatted read
63 streamsize istream::gcount();
64
65 Obtain write position
66 ios::pos_type basic_ostream::tellp()
67
68 Set write position
69 basic_ostream& basic_ostream::seekp(ios::pos_type)
70 basic_ostream& basic_ostream::seekp(ios::off_type, ios_base::seekdir)
71
72 Write data
73 basic_ostream& ostream::write(const char *str, streamsize count)
74*/
75
76struct tiffis_data;
77struct tiffos_data;
78
79extern "C" {
80
85 static uint64 _tiffosSeekProc(thandle_t fd, uint64 off, int whence);
86 static uint64 _tiffisSeekProc(thandle_t fd, uint64 off, int whence);
89 static int _tiffosCloseProc(thandle_t fd);
90 static int _tiffisCloseProc(thandle_t fd);
91 static int _tiffDummyMapProc(thandle_t , void** base, toff_t* size );
92 static void _tiffDummyUnmapProc(thandle_t , void* base, toff_t size );
93 static TIFF* _tiffStreamOpen(const char* name, const char* mode, void *fd);
94
96{
99};
100
102{
105};
106
107static tmsize_t
109{
110 return 0;
111}
112
113static tmsize_t
115{
116 tiffis_data *data = reinterpret_cast<tiffis_data *>(fd);
117
118 // Verify that type does not overflow.
119 streamsize request_size = size;
120 if (static_cast<tmsize_t>(request_size) != size)
121 return static_cast<tmsize_t>(-1);
122
123 data->stream->read((char *) buf, request_size);
124
125 return static_cast<tmsize_t>(data->stream->gcount());
126}
127
128static tmsize_t
130{
131 tiffos_data *data = reinterpret_cast<tiffos_data *>(fd);
132 ostream *os = data->stream;
133 ios::pos_type pos = os->tellp();
134
135 // Verify that type does not overflow.
136 streamsize request_size = size;
137 if (static_cast<tmsize_t>(request_size) != size)
138 return static_cast<tmsize_t>(-1);
139
140 os->write(reinterpret_cast<const char *>(buf), request_size);
141
142 return static_cast<tmsize_t>(os->tellp() - pos);
143}
144
145static tmsize_t
147{
148 return 0;
149}
150
151static uint64
153{
154 tiffos_data *data = reinterpret_cast<tiffos_data *>(fd);
155 ostream *os = data->stream;
156
157 // if the stream has already failed, don't do anything
158 if( os->fail() )
159 return static_cast<uint64>(-1);
160
161 switch(whence) {
162 case SEEK_SET:
163 {
164 // Compute 64-bit offset
165 uint64 new_offset = static_cast<uint64>(data->start_pos) + off;
166
167 // Verify that value does not overflow
168 ios::off_type offset = static_cast<ios::off_type>(new_offset);
169 if (static_cast<uint64>(offset) != new_offset)
170 return static_cast<uint64>(-1);
171
172 os->seekp(offset, ios::beg);
173 break;
174 }
175 case SEEK_CUR:
176 {
177 // Verify that value does not overflow
178 ios::off_type offset = static_cast<ios::off_type>(off);
179 if (static_cast<uint64>(offset) != off)
180 return static_cast<uint64>(-1);
181
182 os->seekp(offset, ios::cur);
183 break;
184 }
185 case SEEK_END:
186 {
187 // Verify that value does not overflow
188 ios::off_type offset = static_cast<ios::off_type>(off);
189 if (static_cast<uint64>(offset) != off)
190 return static_cast<uint64>(-1);
191
192 os->seekp(offset, ios::end);
193 break;
194 }
195 }
196
197 // Attempt to workaround problems with seeking past the end of the
198 // stream. ofstream doesn't have a problem with this but
199 // ostrstream/ostringstream does. In that situation, add intermediate
200 // '\0' characters.
201 if( os->fail() ) {
202#ifdef __VMS
203 int old_state;
204#else
205 ios::iostate old_state;
206#endif
208
209 old_state = os->rdstate();
210 // reset the fail bit or else tellp() won't work below
211 os->clear(os->rdstate() & ~ios::failbit);
212 switch( whence ) {
213 case SEEK_SET:
214 default:
215 origin = data->start_pos;
216 break;
217 case SEEK_CUR:
218 origin = os->tellp();
219 break;
220 case SEEK_END:
221 os->seekp(0, ios::end);
222 origin = os->tellp();
223 break;
224 }
225 // restore original stream state
226 os->clear(old_state);
227
228 // only do something if desired seek position is valid
229 if( (static_cast<uint64>(origin) + off) > static_cast<uint64>(data->start_pos) ) {
230 uint64 num_fill;
231
232 // clear the fail bit
233 os->clear(os->rdstate() & ~ios::failbit);
234
235 // extend the stream to the expected size
236 os->seekp(0, ios::end);
237 num_fill = (static_cast<uint64>(origin)) + off - os->tellp();
238 for( uint64 i = 0; i < num_fill; i++ )
239 os->put('\0');
240
241 // retry the seek
242 os->seekp(static_cast<ios::off_type>(static_cast<uint64>(origin) + off), ios::beg);
243 }
244 }
245
246 return static_cast<uint64>(os->tellp());
247}
248
249static uint64
251{
252 tiffis_data *data = reinterpret_cast<tiffis_data *>(fd);
253
254 switch(whence) {
255 case SEEK_SET:
256 {
257 // Compute 64-bit offset
258 uint64 new_offset = static_cast<uint64>(data->start_pos) + off;
259
260 // Verify that value does not overflow
261 ios::off_type offset = static_cast<ios::off_type>(new_offset);
262 if (static_cast<uint64>(offset) != new_offset)
263 return static_cast<uint64>(-1);
264
265 data->stream->seekg(offset, ios::beg);
266 break;
267 }
268 case SEEK_CUR:
269 {
270 // Verify that value does not overflow
271 ios::off_type offset = static_cast<ios::off_type>(off);
272 if (static_cast<uint64>(offset) != off)
273 return static_cast<uint64>(-1);
274
275 data->stream->seekg(offset, ios::cur);
276 break;
277 }
278 case SEEK_END:
279 {
280 // Verify that value does not overflow
281 ios::off_type offset = static_cast<ios::off_type>(off);
282 if (static_cast<uint64>(offset) != off)
283 return static_cast<uint64>(-1);
284
285 data->stream->seekg(offset, ios::end);
286 break;
287 }
288 }
289
290 return (uint64) (data->stream->tellg() - data->start_pos);
291}
292
293static uint64
295{
296 tiffos_data *data = reinterpret_cast<tiffos_data *>(fd);
297 ostream *os = data->stream;
298 ios::pos_type pos = os->tellp();
300
301 os->seekp(0, ios::end);
302 len = os->tellp();
303 os->seekp(pos);
304
305 return (uint64) len;
306}
307
308static uint64
310{
311 tiffis_data *data = reinterpret_cast<tiffis_data *>(fd);
312 ios::pos_type pos = data->stream->tellg();
314
315 data->stream->seekg(0, ios::end);
316 len = data->stream->tellg();
317 data->stream->seekg(pos);
318
319 return (uint64) len;
320}
321
322static int
324{
325 // Our stream was not allocated by us, so it shouldn't be closed by us.
326 delete reinterpret_cast<tiffos_data *>(fd);
327 return 0;
328}
329
330static int
332{
333 // Our stream was not allocated by us, so it shouldn't be closed by us.
334 delete reinterpret_cast<tiffis_data *>(fd);
335 return 0;
336}
337
338static int
340{
341 (void) base;
342 (void) size;
343 return (0);
344}
345
346static void
348{
349 (void) base;
350 (void) size;
351}
352
353/*
354 * Open a TIFF file descriptor for read/writing.
355 */
356static TIFF*
357_tiffStreamOpen(const char* name, const char* mode, void *fd)
358{
359 TIFF* tif;
360
361 if( strchr(mode, 'w') ) {
363 data->stream = reinterpret_cast<ostream *>(fd);
364 data->start_pos = data->stream->tellp();
365
366 // Open for writing.
367 tif = TIFFClientOpen(name, mode,
368 reinterpret_cast<thandle_t>(data),
376 if (!tif) {
377 delete data;
378 }
379 } else {
381 data->stream = reinterpret_cast<istream *>(fd);
382 data->start_pos = data->stream->tellg();
383 // Open for reading.
384 tif = TIFFClientOpen(name, mode,
385 reinterpret_cast<thandle_t>(data),
393 if (!tif) {
394 delete data;
395 }
396 }
397
398 return (tif);
399}
400
401} /* extern "C" */
402
403TIFF*
404TIFFStreamOpen(const char* name, ostream *os)
405{
406 // If os is either a ostrstream or ostringstream, and has no data
407 // written to it yet, then tellp() will return -1 which will break us.
408 // We workaround this by writing out a dummy character and
409 // then seek back to the beginning.
410 if( !os->fail() && static_cast<int>(os->tellp()) < 0 ) {
411 *os << '\0';
412 os->seekp(0);
413 }
414
415 // NB: We don't support mapped files with streams so add 'm'
416 return _tiffStreamOpen(name, "wm", os);
417}
418
419TIFF*
420TIFFStreamOpen(const char* name, istream *is)
421{
422 // NB: We don't support mapped files with streams so add 'm'
423 return _tiffStreamOpen(name, "rm", is);
424}
425
426/* vim: set ts=8 sts=8 sw=8 noet: */
427/*
428 * Local Variables:
429 * mode: c
430 * c-basic-offset: 8
431 * fill-column: 78
432 * End:
433 */
434
basic_ostream< char, char_traits< char > > ostream
Definition: _iosfwd.h:121
basic_istream< char, char_traits< char > > istream
Definition: _iosfwd.h:120
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#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
unsigned long long uint64
Definition: platform.h:18
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLsizeiptr size
Definition: glext.h:5919
GLenum mode
Definition: glext.h:6217
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLenum GLsizei len
Definition: glext.h:6722
GLintptr offset
Definition: glext.h:5920
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
#define SEEK_CUR
Definition: util.h:63
Definition: features.h:417
static int fd
Definition: io.c:51
Definition: name.c:39
Definition: tiffiop.h:115
ios::pos_type start_pos
Definition: tif_stream.cxx:98
istream * stream
Definition: tif_stream.cxx:97
ostream * stream
Definition: tif_stream.cxx:103
ios::pos_type start_pos
Definition: tif_stream.cxx:104
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:71
static uint64 _tiffisSeekProc(thandle_t fd, uint64 off, int whence)
Definition: tif_stream.cxx:250
static TIFF * _tiffStreamOpen(const char *name, const char *mode, void *fd)
Definition: tif_stream.cxx:357
static uint64 _tiffosSeekProc(thandle_t fd, uint64 off, int whence)
Definition: tif_stream.cxx:152
static uint64 _tiffosSizeProc(thandle_t fd)
Definition: tif_stream.cxx:294
static int _tiffisCloseProc(thandle_t fd)
Definition: tif_stream.cxx:331
static tmsize_t _tiffisWriteProc(thandle_t, void *, tmsize_t)
Definition: tif_stream.cxx:146
static void _tiffDummyUnmapProc(thandle_t, void *base, toff_t size)
Definition: tif_stream.cxx:347
static tmsize_t _tiffosWriteProc(thandle_t fd, void *buf, tmsize_t size)
Definition: tif_stream.cxx:129
static tmsize_t _tiffisReadProc(thandle_t fd, void *buf, tmsize_t size)
Definition: tif_stream.cxx:114
static uint64 _tiffisSizeProc(thandle_t fd)
Definition: tif_stream.cxx:309
static int _tiffDummyMapProc(thandle_t, void **base, toff_t *size)
Definition: tif_stream.cxx:339
static tmsize_t _tiffosReadProc(thandle_t, void *, tmsize_t)
Definition: tif_stream.cxx:108
TIFF * TIFFStreamOpen(const char *name, ostream *os)
Definition: tif_stream.cxx:404
static int _tiffosCloseProc(thandle_t fd)
Definition: tif_stream.cxx:323
uint64 toff_t
Definition: tiffio.h:66
TIFF_SSIZE_T tmsize_t
Definition: tiffio.h:65