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