ReactOS  0.4.15-dev-341-g17c5fb8
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
32 using 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 
76 struct tiffis_data;
77 struct tiffos_data;
78 
79 extern "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 
107 static tmsize_t
109 {
110  return 0;
111 }
112 
113 static 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 
128 static 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 
145 static tmsize_t
147 {
148  return 0;
149 }
150 
151 static 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 
249 static 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 
293 static 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 
308 static 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 
322 static 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 
330 static 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 
338 static int
340 {
341  (void) base;
342  (void) size;
343  return (0);
344 }
345 
346 static void
348 {
349  (void) base;
350  (void) size;
351 }
352 
353 /*
354  * Open a TIFF file descriptor for read/writing.
355  */
356 static 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 
403 TIFF*
404 TIFFStreamOpen(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 
419 TIFF*
420 TIFFStreamOpen(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 
unsigned long long uint64
Definition: platform.h:18
#define SEEK_CUR
Definition: util.h:63
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
basic_ostream< char, char_traits< char > > ostream
Definition: _iosfwd.h:121
static uint64 _tiffisSizeProc(thandle_t fd)
Definition: tif_stream.cxx:309
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLintptr offset
Definition: glext.h:5920
uint64 toff_t
Definition: tiffio.h:66
istream * stream
Definition: tif_stream.cxx:97
voidpf uLong int origin
Definition: ioapi.h:142
static int fd
Definition: io.c:51
GLuint GLuint end
Definition: gl.h:1545
Definition: features.h:417
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
Definition: tiffiop.h:115
char_traits< char > ::off_type off_type
Definition: _ios.h:54
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
TIFF_SSIZE_T tmsize_t
Definition: tiffio.h:65
static int _tiffisCloseProc(thandle_t fd)
Definition: tif_stream.cxx:331
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 int _tiffDummyMapProc(thandle_t, void **base, toff_t *size)
Definition: tif_stream.cxx:339
basic_ios< char, char_traits< char > > ios
Definition: _iosfwd.h:76
#define SEEK_SET
Definition: jmemansi.c:26
GLsizeiptr size
Definition: glext.h:5919
TIFF * TIFFStreamOpen(const char *name, ostream *os)
Definition: tif_stream.cxx:404
basic_istream< char, char_traits< char > > istream
Definition: _iosfwd.h:120
static tmsize_t _tiffosReadProc(thandle_t, void *, tmsize_t)
Definition: tif_stream.cxx:108
static int _tiffosCloseProc(thandle_t fd)
Definition: tif_stream.cxx:323
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
int iostate
Definition: _ios_base.h:58
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
GLenum GLsizei len
Definition: glext.h:6722
GLenum mode
Definition: glext.h:6217
ostream * stream
Definition: tif_stream.cxx:103
static tmsize_t _tiffisReadProc(thandle_t fd, void *buf, tmsize_t size)
Definition: tif_stream.cxx:114
static uint64 _tiffisSeekProc(thandle_t fd, uint64 off, int whence)
Definition: tif_stream.cxx:250
char * strchr(const char *String, int ch)
Definition: utclib.c:501
Definition: name.c:38
ios::pos_type start_pos
Definition: tif_stream.cxx:98
ptrdiff_t streamsize
Definition: char_traits.h:81
#define SEEK_END
Definition: cabinet.c:27
ios::pos_type start_pos
Definition: tif_stream.cxx:104
static uint64 _tiffosSizeProc(thandle_t fd)
Definition: tif_stream.cxx:294
static tmsize_t _tiffisWriteProc(thandle_t, void *, tmsize_t)
Definition: tif_stream.cxx:146
char_traits< char > ::pos_type pos_type
Definition: _ios.h:53
off
Definition: i386-dis.c:3909