#include "tiffiop.h"
#include <iostream>
+#ifndef __VMS
using namespace std;
+#endif
-class tiffis_data
+/*
+ ISO C++ uses a 'std::streamsize' type to define counts. This makes
+ it similar to, (but perhaps not the same as) size_t.
+
+ The std::ios::pos_type is used to represent stream positions as used
+ by tellg(), tellp(), seekg(), and seekp(). This makes it similar to
+ (but perhaps not the same as) 'off_t'. The std::ios::streampos type
+ is used for character streams, but is documented to not be an
+ integral type anymore, so it should *not* be assigned to an integral
+ type.
+
+ The std::ios::off_type is used to specify relative offsets needed by
+ the variants of seekg() and seekp() which accept a relative offset
+ argument.
+
+ Useful prototype knowledge:
+
+ Obtain read position
+ ios::pos_type basic_istream::tellg()
+
+ Set read position
+ basic_istream& basic_istream::seekg(ios::pos_type)
+ basic_istream& basic_istream::seekg(ios::off_type, ios_base::seekdir)
+
+ Read data
+ basic_istream& istream::read(char *str, streamsize count)
+
+ Number of characters read in last unformatted read
+ streamsize istream::gcount();
+
+ Obtain write position
+ ios::pos_type basic_ostream::tellp()
+
+ Set write position
+ basic_ostream& basic_ostream::seekp(ios::pos_type)
+ basic_ostream& basic_ostream::seekp(ios::off_type, ios_base::seekdir)
+
+ Write data
+ basic_ostream& ostream::write(const char *str, streamsize count)
+*/
+
+struct tiffis_data;
+struct tiffos_data;
+
+extern "C" {
+
+ static tmsize_t _tiffosReadProc(thandle_t, void*, tmsize_t);
+ static tmsize_t _tiffisReadProc(thandle_t fd, void* buf, tmsize_t size);
+ static tmsize_t _tiffosWriteProc(thandle_t fd, void* buf, tmsize_t size);
+ static tmsize_t _tiffisWriteProc(thandle_t, void*, tmsize_t);
+ static uint64 _tiffosSeekProc(thandle_t fd, uint64 off, int whence);
+ static uint64 _tiffisSeekProc(thandle_t fd, uint64 off, int whence);
+ static uint64 _tiffosSizeProc(thandle_t fd);
+ static uint64 _tiffisSizeProc(thandle_t fd);
+ static int _tiffosCloseProc(thandle_t fd);
+ static int _tiffisCloseProc(thandle_t fd);
+ static int _tiffDummyMapProc(thandle_t , void** base, toff_t* size );
+ static void _tiffDummyUnmapProc(thandle_t , void* base, toff_t size );
+ static TIFF* _tiffStreamOpen(const char* name, const char* mode, void *fd);
+
+struct tiffis_data
{
- public:
-
- istream *myIS;
- long myStreamStartPos;
+ istream *stream;
+ ios::pos_type start_pos;
};
-class tiffos_data
+struct tiffos_data
{
- public:
-
- ostream *myOS;
- long myStreamStartPos;
+ ostream *stream;
+ ios::pos_type start_pos;
};
-static tsize_t
-_tiffosReadProc(thandle_t, tdata_t, tsize_t)
+static tmsize_t
+_tiffosReadProc(thandle_t, void*, tmsize_t)
{
return 0;
}
-static tsize_t
-_tiffisReadProc(thandle_t fd, tdata_t buf, tsize_t size)
+static tmsize_t
+_tiffisReadProc(thandle_t fd, void* buf, tmsize_t size)
{
- tiffis_data *data = (tiffis_data *)fd;
+ tiffis_data *data = reinterpret_cast<tiffis_data *>(fd);
- data->myIS->read((char *)buf, (int)size);
+ // Verify that type does not overflow.
+ streamsize request_size = size;
+ if (static_cast<tmsize_t>(request_size) != size)
+ return static_cast<tmsize_t>(-1);
- return data->myIS->gcount();
+ data->stream->read((char *) buf, request_size);
+
+ return static_cast<tmsize_t>(data->stream->gcount());
}
-static tsize_t
-_tiffosWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
+static tmsize_t
+_tiffosWriteProc(thandle_t fd, void* buf, tmsize_t size)
{
- tiffos_data *data = (tiffos_data *)fd;
- ostream *os = data->myOS;
- int pos = os->tellp();
+ tiffos_data *data = reinterpret_cast<tiffos_data *>(fd);
+ ostream *os = data->stream;
+ ios::pos_type pos = os->tellp();
+
+ // Verify that type does not overflow.
+ streamsize request_size = size;
+ if (static_cast<tmsize_t>(request_size) != size)
+ return static_cast<tmsize_t>(-1);
- os->write((const char *)buf, size);
+ os->write(reinterpret_cast<const char *>(buf), request_size);
- return ((int)os->tellp()) - pos;
+ return static_cast<tmsize_t>(os->tellp() - pos);
}
-static tsize_t
-_tiffisWriteProc(thandle_t, tdata_t, tsize_t)
+static tmsize_t
+_tiffisWriteProc(thandle_t, void*, tmsize_t)
{
return 0;
}
-static toff_t
-_tiffosSeekProc(thandle_t fd, toff_t off, int whence)
+static uint64
+_tiffosSeekProc(thandle_t fd, uint64 off, int whence)
{
- tiffos_data *data = (tiffos_data *)fd;
- ostream *os = data->myOS;
+ tiffos_data *data = reinterpret_cast<tiffos_data *>(fd);
+ ostream *os = data->stream;
// if the stream has already failed, don't do anything
if( os->fail() )
- return os->tellp();
+ return static_cast<uint64>(-1);
switch(whence) {
case SEEK_SET:
- os->seekp(data->myStreamStartPos + off, ios::beg);
+ {
+ // Compute 64-bit offset
+ uint64 new_offset = static_cast<uint64>(data->start_pos) + off;
+
+ // Verify that value does not overflow
+ ios::off_type offset = static_cast<ios::off_type>(new_offset);
+ if (static_cast<uint64>(offset) != new_offset)
+ return static_cast<uint64>(-1);
+
+ os->seekp(offset, ios::beg);
break;
+ }
case SEEK_CUR:
- os->seekp(off, ios::cur);
- break;
+ {
+ // Verify that value does not overflow
+ ios::off_type offset = static_cast<ios::off_type>(off);
+ if (static_cast<uint64>(offset) != off)
+ return static_cast<uint64>(-1);
+
+ os->seekp(offset, ios::cur);
+ break;
+ }
case SEEK_END:
- os->seekp(off, ios::end);
- break;
+ {
+ // Verify that value does not overflow
+ ios::off_type offset = static_cast<ios::off_type>(off);
+ if (static_cast<uint64>(offset) != off)
+ return static_cast<uint64>(-1);
+
+ os->seekp(offset, ios::end);
+ break;
+ }
}
// Attempt to workaround problems with seeking past the end of the
// ostrstream/ostringstream does. In that situation, add intermediate
// '\0' characters.
if( os->fail() ) {
+#ifdef __VMS
+ int old_state;
+#else
ios::iostate old_state;
- toff_t origin;
+#endif
+ ios::pos_type origin;
old_state = os->rdstate();
// reset the fail bit or else tellp() won't work below
os->clear(os->rdstate() & ~ios::failbit);
switch( whence ) {
case SEEK_SET:
- origin = data->myStreamStartPos;
+ default:
+ origin = data->start_pos;
break;
case SEEK_CUR:
origin = os->tellp();
os->clear(old_state);
// only do something if desired seek position is valid
- if( origin + off > data->myStreamStartPos ) {
- toff_t num_fill;
+ if( (static_cast<uint64>(origin) + off) > static_cast<uint64>(data->start_pos) ) {
+ uint64 num_fill;
// clear the fail bit
os->clear(os->rdstate() & ~ios::failbit);
// extend the stream to the expected size
os->seekp(0, ios::end);
- num_fill = origin + off - (toff_t)os->tellp();
- for( toff_t i = 0; i < num_fill; i++ )
+ num_fill = (static_cast<uint64>(origin)) + off - os->tellp();
+ for( uint64 i = 0; i < num_fill; i++ )
os->put('\0');
// retry the seek
- os->seekp(origin + off, ios::beg);
+ os->seekp(static_cast<ios::off_type>(static_cast<uint64>(origin) + off), ios::beg);
}
}
- return os->tellp();
+ return static_cast<uint64>(os->tellp());
}
-static toff_t
-_tiffisSeekProc(thandle_t fd, toff_t off, int whence)
+static uint64
+_tiffisSeekProc(thandle_t fd, uint64 off, int whence)
{
- tiffis_data *data = (tiffis_data *)fd;
+ tiffis_data *data = reinterpret_cast<tiffis_data *>(fd);
switch(whence) {
case SEEK_SET:
- data->myIS->seekg(data->myStreamStartPos + off, ios::beg);
- break;
+ {
+ // Compute 64-bit offset
+ uint64 new_offset = static_cast<uint64>(data->start_pos) + off;
+
+ // Verify that value does not overflow
+ ios::off_type offset = static_cast<ios::off_type>(new_offset);
+ if (static_cast<uint64>(offset) != new_offset)
+ return static_cast<uint64>(-1);
+
+ data->stream->seekg(offset, ios::beg);
+ break;
+ }
case SEEK_CUR:
- data->myIS->seekg(off, ios::cur);
- break;
+ {
+ // Verify that value does not overflow
+ ios::off_type offset = static_cast<ios::off_type>(off);
+ if (static_cast<uint64>(offset) != off)
+ return static_cast<uint64>(-1);
+
+ data->stream->seekg(offset, ios::cur);
+ break;
+ }
case SEEK_END:
- data->myIS->seekg(off, ios::end);
- break;
+ {
+ // Verify that value does not overflow
+ ios::off_type offset = static_cast<ios::off_type>(off);
+ if (static_cast<uint64>(offset) != off)
+ return static_cast<uint64>(-1);
+
+ data->stream->seekg(offset, ios::end);
+ break;
+ }
}
- return ((long)data->myIS->tellg()) - data->myStreamStartPos;
+ return (uint64) (data->stream->tellg() - data->start_pos);
}
-static toff_t
+static uint64
_tiffosSizeProc(thandle_t fd)
{
- tiffos_data *data = (tiffos_data *)fd;
- ostream *os = data->myOS;
- toff_t pos = os->tellp();
- toff_t len;
+ tiffos_data *data = reinterpret_cast<tiffos_data *>(fd);
+ ostream *os = data->stream;
+ ios::pos_type pos = os->tellp();
+ ios::pos_type len;
os->seekp(0, ios::end);
len = os->tellp();
os->seekp(pos);
- return len;
+ return (uint64) len;
}
-static toff_t
+static uint64
_tiffisSizeProc(thandle_t fd)
{
- tiffis_data *data = (tiffis_data *)fd;
- int pos = data->myIS->tellg();
- int len;
+ tiffis_data *data = reinterpret_cast<tiffis_data *>(fd);
+ ios::pos_type pos = data->stream->tellg();
+ ios::pos_type len;
- data->myIS->seekg(0, ios::end);
- len = data->myIS->tellg();
- data->myIS->seekg(pos);
+ data->stream->seekg(0, ios::end);
+ len = data->stream->tellg();
+ data->stream->seekg(pos);
- return len;
+ return (uint64) len;
}
static int
_tiffosCloseProc(thandle_t fd)
{
// Our stream was not allocated by us, so it shouldn't be closed by us.
- delete (tiffos_data *)fd;
+ delete reinterpret_cast<tiffos_data *>(fd);
return 0;
}
_tiffisCloseProc(thandle_t fd)
{
// Our stream was not allocated by us, so it shouldn't be closed by us.
- delete (tiffis_data *)fd;
+ delete reinterpret_cast<tiffis_data *>(fd);
return 0;
}
static int
-_tiffDummyMapProc(thandle_t , tdata_t* , toff_t* )
+_tiffDummyMapProc(thandle_t , void** base, toff_t* size )
{
return (0);
}
static void
-_tiffDummyUnmapProc(thandle_t , tdata_t , toff_t )
+_tiffDummyUnmapProc(thandle_t , void* base, toff_t size )
{
}
if( strchr(mode, 'w') ) {
tiffos_data *data = new tiffos_data;
- data->myOS = (ostream *)fd;
- data->myStreamStartPos = data->myOS->tellp();
+ data->stream = reinterpret_cast<ostream *>(fd);
+ data->start_pos = data->stream->tellp();
// Open for writing.
tif = TIFFClientOpen(name, mode,
- (thandle_t) data,
- _tiffosReadProc, _tiffosWriteProc,
- _tiffosSeekProc, _tiffosCloseProc,
+ reinterpret_cast<thandle_t>(data),
+ _tiffosReadProc,
+ _tiffosWriteProc,
+ _tiffosSeekProc,
+ _tiffosCloseProc,
_tiffosSizeProc,
- _tiffDummyMapProc, _tiffDummyUnmapProc);
+ _tiffDummyMapProc,
+ _tiffDummyUnmapProc);
} else {
tiffis_data *data = new tiffis_data;
- data->myIS = (istream *)fd;
- data->myStreamStartPos = data->myIS->tellg();
+ data->stream = reinterpret_cast<istream *>(fd);
+ data->start_pos = data->stream->tellg();
// Open for reading.
tif = TIFFClientOpen(name, mode,
- (thandle_t) data,
- _tiffisReadProc, _tiffisWriteProc,
- _tiffisSeekProc, _tiffisCloseProc,
+ reinterpret_cast<thandle_t>(data),
+ _tiffisReadProc,
+ _tiffisWriteProc,
+ _tiffisSeekProc,
+ _tiffisCloseProc,
_tiffisSizeProc,
- _tiffDummyMapProc, _tiffDummyUnmapProc);
+ _tiffDummyMapProc,
+ _tiffDummyUnmapProc);
}
return (tif);
}
+} /* extern "C" */
+
TIFF*
TIFFStreamOpen(const char* name, ostream *os)
{
// written to it yet, then tellp() will return -1 which will break us.
// We workaround this by writing out a dummy character and
// then seek back to the beginning.
- if( !os->fail() && (int)os->tellp() < 0 ) {
+ if( !os->fail() && static_cast<int>(os->tellp()) < 0 ) {
*os << '\0';
os->seekp(0);
}
}
/* vim: set ts=8 sts=8 sw=8 noet: */
+/*
+ Local Variables:
+ mode: c
+ indent-tabs-mode: true
+ c-basic-offset: 8
+ End:
+*/