Update to 2.0.0 tree from current Fremantle build
[opencv] / 3rdparty / libtiff / tif_stream.cxx
diff --git a/3rdparty/libtiff/tif_stream.cxx b/3rdparty/libtiff/tif_stream.cxx
new file mode 100644 (file)
index 0000000..5e75218
--- /dev/null
@@ -0,0 +1,290 @@
+/* $Id: tif_stream.cxx,v 1.1 2005-06-17 13:54:52 vp153 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 <iostream>
+#include <cstring>
+#include "tiffiop.h"
+
+using namespace std;
+
+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() ) {
+               ios::iostate    old_state;
+               toff_t          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;
+                               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: */