|
Packit |
994f1a |
/* $Id: tif_stream.cxx,v 1.6.2.1 2009-01-01 00:10:43 bfriesen Exp $ */
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
/*
|
|
Packit |
994f1a |
* Copyright (c) 1988-1996 Sam Leffler
|
|
Packit |
994f1a |
* Copyright (c) 1991-1996 Silicon Graphics, Inc.
|
|
Packit |
994f1a |
*
|
|
Packit |
994f1a |
* Permission to use, copy, modify, distribute, and sell this software and
|
|
Packit |
994f1a |
* its documentation for any purpose is hereby granted without fee, provided
|
|
Packit |
994f1a |
* that (i) the above copyright notices and this permission notice appear in
|
|
Packit |
994f1a |
* all copies of the software and related documentation, and (ii) the names of
|
|
Packit |
994f1a |
* Sam Leffler and Silicon Graphics may not be used in any advertising or
|
|
Packit |
994f1a |
* publicity relating to the software without the specific, prior written
|
|
Packit |
994f1a |
* permission of Sam Leffler and Silicon Graphics.
|
|
Packit |
994f1a |
*
|
|
Packit |
994f1a |
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
|
Packit |
994f1a |
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
|
Packit |
994f1a |
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
|
Packit |
994f1a |
*
|
|
Packit |
994f1a |
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
|
|
Packit |
994f1a |
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
|
Packit |
994f1a |
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
|
Packit |
994f1a |
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
|
Packit |
994f1a |
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
|
Packit |
994f1a |
* OF THIS SOFTWARE.
|
|
Packit |
994f1a |
*/
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
/*
|
|
Packit |
994f1a |
* TIFF Library UNIX-specific Routines.
|
|
Packit |
994f1a |
*/
|
|
Packit |
994f1a |
#include "tiffiop.h"
|
|
Packit |
994f1a |
#include <iostream>
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
#ifndef __VMS
|
|
Packit |
994f1a |
using namespace std;
|
|
Packit |
994f1a |
#endif
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
class tiffis_data
|
|
Packit |
994f1a |
{
|
|
Packit |
994f1a |
public:
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
istream *myIS;
|
|
Packit |
994f1a |
long myStreamStartPos;
|
|
Packit |
994f1a |
};
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
class tiffos_data
|
|
Packit |
994f1a |
{
|
|
Packit |
994f1a |
public:
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
ostream *myOS;
|
|
Packit |
994f1a |
long myStreamStartPos;
|
|
Packit |
994f1a |
};
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
static tsize_t
|
|
Packit |
994f1a |
_tiffosReadProc(thandle_t, tdata_t, tsize_t)
|
|
Packit |
994f1a |
{
|
|
Packit |
994f1a |
return 0;
|
|
Packit |
994f1a |
}
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
static tsize_t
|
|
Packit |
994f1a |
_tiffisReadProc(thandle_t fd, tdata_t buf, tsize_t size)
|
|
Packit |
994f1a |
{
|
|
Packit |
994f1a |
tiffis_data *data = (tiffis_data *)fd;
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
data->myIS->read((char *)buf, (int)size);
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
return data->myIS->gcount();
|
|
Packit |
994f1a |
}
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
static tsize_t
|
|
Packit |
994f1a |
_tiffosWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
|
|
Packit |
994f1a |
{
|
|
Packit |
994f1a |
tiffos_data *data = (tiffos_data *)fd;
|
|
Packit |
994f1a |
ostream *os = data->myOS;
|
|
Packit |
994f1a |
int pos = os->tellp();
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
os->write((const char *)buf, size);
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
return ((int)os->tellp()) - pos;
|
|
Packit |
994f1a |
}
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
static tsize_t
|
|
Packit |
994f1a |
_tiffisWriteProc(thandle_t, tdata_t, tsize_t)
|
|
Packit |
994f1a |
{
|
|
Packit |
994f1a |
return 0;
|
|
Packit |
994f1a |
}
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
static toff_t
|
|
Packit |
994f1a |
_tiffosSeekProc(thandle_t fd, toff_t off, int whence)
|
|
Packit |
994f1a |
{
|
|
Packit |
994f1a |
tiffos_data *data = (tiffos_data *)fd;
|
|
Packit |
994f1a |
ostream *os = data->myOS;
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
// if the stream has already failed, don't do anything
|
|
Packit |
994f1a |
if( os->fail() )
|
|
Packit |
994f1a |
return os->tellp();
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
switch(whence) {
|
|
Packit |
994f1a |
case SEEK_SET:
|
|
Packit |
994f1a |
os->seekp(data->myStreamStartPos + off, ios::beg);
|
|
Packit |
994f1a |
break;
|
|
Packit |
994f1a |
case SEEK_CUR:
|
|
Packit |
994f1a |
os->seekp(off, ios::cur);
|
|
Packit |
994f1a |
break;
|
|
Packit |
994f1a |
case SEEK_END:
|
|
Packit |
994f1a |
os->seekp(off, ios::end);
|
|
Packit |
994f1a |
break;
|
|
Packit |
994f1a |
}
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
// Attempt to workaround problems with seeking past the end of the
|
|
Packit |
994f1a |
// stream. ofstream doesn't have a problem with this but
|
|
Packit |
994f1a |
// ostrstream/ostringstream does. In that situation, add intermediate
|
|
Packit |
994f1a |
// '\0' characters.
|
|
Packit |
994f1a |
if( os->fail() ) {
|
|
Packit |
994f1a |
#ifdef __VMS
|
|
Packit |
994f1a |
int old_state;
|
|
Packit |
994f1a |
#else
|
|
Packit |
994f1a |
ios::iostate old_state;
|
|
Packit |
994f1a |
#endif
|
|
Packit |
994f1a |
toff_t origin=0;
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
old_state = os->rdstate();
|
|
Packit |
994f1a |
// reset the fail bit or else tellp() won't work below
|
|
Packit |
994f1a |
os->clear(os->rdstate() & ~ios::failbit);
|
|
Packit |
994f1a |
switch( whence ) {
|
|
Packit |
994f1a |
case SEEK_SET:
|
|
Packit |
994f1a |
origin = data->myStreamStartPos;
|
|
Packit |
994f1a |
break;
|
|
Packit |
994f1a |
case SEEK_CUR:
|
|
Packit |
994f1a |
origin = os->tellp();
|
|
Packit |
994f1a |
break;
|
|
Packit |
994f1a |
case SEEK_END:
|
|
Packit |
994f1a |
os->seekp(0, ios::end);
|
|
Packit |
994f1a |
origin = os->tellp();
|
|
Packit |
994f1a |
break;
|
|
Packit |
994f1a |
}
|
|
Packit |
994f1a |
// restore original stream state
|
|
Packit |
994f1a |
os->clear(old_state);
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
// only do something if desired seek position is valid
|
|
Packit |
994f1a |
if( origin + off > data->myStreamStartPos ) {
|
|
Packit |
994f1a |
toff_t num_fill;
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
// clear the fail bit
|
|
Packit |
994f1a |
os->clear(os->rdstate() & ~ios::failbit);
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
// extend the stream to the expected size
|
|
Packit |
994f1a |
os->seekp(0, ios::end);
|
|
Packit |
994f1a |
num_fill = origin + off - (toff_t)os->tellp();
|
|
Packit |
994f1a |
for( toff_t i = 0; i < num_fill; i++ )
|
|
Packit |
994f1a |
os->put('\0');
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
// retry the seek
|
|
Packit |
994f1a |
os->seekp(origin + off, ios::beg);
|
|
Packit |
994f1a |
}
|
|
Packit |
994f1a |
}
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
return os->tellp();
|
|
Packit |
994f1a |
}
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
static toff_t
|
|
Packit |
994f1a |
_tiffisSeekProc(thandle_t fd, toff_t off, int whence)
|
|
Packit |
994f1a |
{
|
|
Packit |
994f1a |
tiffis_data *data = (tiffis_data *)fd;
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
switch(whence) {
|
|
Packit |
994f1a |
case SEEK_SET:
|
|
Packit |
994f1a |
data->myIS->seekg(data->myStreamStartPos + off, ios::beg);
|
|
Packit |
994f1a |
break;
|
|
Packit |
994f1a |
case SEEK_CUR:
|
|
Packit |
994f1a |
data->myIS->seekg(off, ios::cur);
|
|
Packit |
994f1a |
break;
|
|
Packit |
994f1a |
case SEEK_END:
|
|
Packit |
994f1a |
data->myIS->seekg(off, ios::end);
|
|
Packit |
994f1a |
break;
|
|
Packit |
994f1a |
}
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
return ((long)data->myIS->tellg()) - data->myStreamStartPos;
|
|
Packit |
994f1a |
}
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
static toff_t
|
|
Packit |
994f1a |
_tiffosSizeProc(thandle_t fd)
|
|
Packit |
994f1a |
{
|
|
Packit |
994f1a |
tiffos_data *data = (tiffos_data *)fd;
|
|
Packit |
994f1a |
ostream *os = data->myOS;
|
|
Packit |
994f1a |
toff_t pos = os->tellp();
|
|
Packit |
994f1a |
toff_t len;
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
os->seekp(0, ios::end);
|
|
Packit |
994f1a |
len = os->tellp();
|
|
Packit |
994f1a |
os->seekp(pos);
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
return len;
|
|
Packit |
994f1a |
}
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
static toff_t
|
|
Packit |
994f1a |
_tiffisSizeProc(thandle_t fd)
|
|
Packit |
994f1a |
{
|
|
Packit |
994f1a |
tiffis_data *data = (tiffis_data *)fd;
|
|
Packit |
994f1a |
int pos = data->myIS->tellg();
|
|
Packit |
994f1a |
int len;
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
data->myIS->seekg(0, ios::end);
|
|
Packit |
994f1a |
len = data->myIS->tellg();
|
|
Packit |
994f1a |
data->myIS->seekg(pos);
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
return len;
|
|
Packit |
994f1a |
}
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
static int
|
|
Packit |
994f1a |
_tiffosCloseProc(thandle_t fd)
|
|
Packit |
994f1a |
{
|
|
Packit |
994f1a |
// Our stream was not allocated by us, so it shouldn't be closed by us.
|
|
Packit |
994f1a |
delete (tiffos_data *)fd;
|
|
Packit |
994f1a |
return 0;
|
|
Packit |
994f1a |
}
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
static int
|
|
Packit |
994f1a |
_tiffisCloseProc(thandle_t fd)
|
|
Packit |
994f1a |
{
|
|
Packit |
994f1a |
// Our stream was not allocated by us, so it shouldn't be closed by us.
|
|
Packit |
994f1a |
delete (tiffis_data *)fd;
|
|
Packit |
994f1a |
return 0;
|
|
Packit |
994f1a |
}
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
static int
|
|
Packit |
994f1a |
_tiffDummyMapProc(thandle_t , tdata_t* , toff_t* )
|
|
Packit |
994f1a |
{
|
|
Packit |
994f1a |
return (0);
|
|
Packit |
994f1a |
}
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
static void
|
|
Packit |
994f1a |
_tiffDummyUnmapProc(thandle_t , tdata_t , toff_t )
|
|
Packit |
994f1a |
{
|
|
Packit |
994f1a |
}
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
/*
|
|
Packit |
994f1a |
* Open a TIFF file descriptor for read/writing.
|
|
Packit |
994f1a |
*/
|
|
Packit |
994f1a |
static TIFF*
|
|
Packit |
994f1a |
_tiffStreamOpen(const char* name, const char* mode, void *fd)
|
|
Packit |
994f1a |
{
|
|
Packit |
994f1a |
TIFF* tif;
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
if( strchr(mode, 'w') ) {
|
|
Packit |
994f1a |
tiffos_data *data = new tiffos_data;
|
|
Packit |
994f1a |
data->myOS = (ostream *)fd;
|
|
Packit |
994f1a |
data->myStreamStartPos = data->myOS->tellp();
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
// Open for writing.
|
|
Packit |
994f1a |
tif = TIFFClientOpen(name, mode,
|
|
Packit |
994f1a |
(thandle_t) data,
|
|
Packit |
994f1a |
_tiffosReadProc, _tiffosWriteProc,
|
|
Packit |
994f1a |
_tiffosSeekProc, _tiffosCloseProc,
|
|
Packit |
994f1a |
_tiffosSizeProc,
|
|
Packit |
994f1a |
_tiffDummyMapProc, _tiffDummyUnmapProc);
|
|
Packit |
994f1a |
} else {
|
|
Packit |
994f1a |
tiffis_data *data = new tiffis_data;
|
|
Packit |
994f1a |
data->myIS = (istream *)fd;
|
|
Packit |
994f1a |
data->myStreamStartPos = data->myIS->tellg();
|
|
Packit |
994f1a |
// Open for reading.
|
|
Packit |
994f1a |
tif = TIFFClientOpen(name, mode,
|
|
Packit |
994f1a |
(thandle_t) data,
|
|
Packit |
994f1a |
_tiffisReadProc, _tiffisWriteProc,
|
|
Packit |
994f1a |
_tiffisSeekProc, _tiffisCloseProc,
|
|
Packit |
994f1a |
_tiffisSizeProc,
|
|
Packit |
994f1a |
_tiffDummyMapProc, _tiffDummyUnmapProc);
|
|
Packit |
994f1a |
}
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
return (tif);
|
|
Packit |
994f1a |
}
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
TIFF*
|
|
Packit |
994f1a |
TIFFStreamOpen(const char* name, ostream *os)
|
|
Packit |
994f1a |
{
|
|
Packit |
994f1a |
// If os is either a ostrstream or ostringstream, and has no data
|
|
Packit |
994f1a |
// written to it yet, then tellp() will return -1 which will break us.
|
|
Packit |
994f1a |
// We workaround this by writing out a dummy character and
|
|
Packit |
994f1a |
// then seek back to the beginning.
|
|
Packit |
994f1a |
if( !os->fail() && (int)os->tellp() < 0 ) {
|
|
Packit |
994f1a |
*os << '\0';
|
|
Packit |
994f1a |
os->seekp(0);
|
|
Packit |
994f1a |
}
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
// NB: We don't support mapped files with streams so add 'm'
|
|
Packit |
994f1a |
return _tiffStreamOpen(name, "wm", os);
|
|
Packit |
994f1a |
}
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
TIFF*
|
|
Packit |
994f1a |
TIFFStreamOpen(const char* name, istream *is)
|
|
Packit |
994f1a |
{
|
|
Packit |
994f1a |
// NB: We don't support mapped files with streams so add 'm'
|
|
Packit |
994f1a |
return _tiffStreamOpen(name, "rm", is);
|
|
Packit |
994f1a |
}
|
|
Packit |
994f1a |
|
|
Packit |
994f1a |
/* vim: set ts=8 sts=8 sw=8 noet: */
|