Blame libtiff/tif_stream.cxx

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: */