Removed the libs directory containing win32 compiled versions of libpng, libtiff...
[openjpeg.git] / thirdparty / libtiff / tif_stream.cxx
1 /* $Id: tif_stream.cxx,v 1.6.2.1 2009-01-01 00:10:43 bfriesen Exp $ */
2
3 /*
4  * Copyright (c) 1988-1996 Sam Leffler
5  * Copyright (c) 1991-1996 Silicon Graphics, Inc.
6  *
7  * Permission to use, copy, modify, distribute, and sell this software and 
8  * its documentation for any purpose is hereby granted without fee, provided
9  * that (i) the above copyright notices and this permission notice appear in
10  * all copies of the software and related documentation, and (ii) the names of
11  * Sam Leffler and Silicon Graphics may not be used in any advertising or
12  * publicity relating to the software without the specific, prior written
13  * permission of Sam Leffler and Silicon Graphics.
14  * 
15  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
16  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
17  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
18  * 
19  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
20  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
21  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
22  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
23  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
24  * OF THIS SOFTWARE.
25  */
26
27 /*
28  * TIFF Library UNIX-specific Routines.
29  */
30 #include "tiffiop.h"
31 #include <iostream>
32
33 #ifndef __VMS
34 using namespace std;
35 #endif
36
37 class tiffis_data
38 {
39   public:
40
41         istream *myIS;
42         long    myStreamStartPos;
43 };
44
45 class tiffos_data
46 {
47   public:
48
49         ostream *myOS;
50         long    myStreamStartPos;
51 };
52
53 static tsize_t
54 _tiffosReadProc(thandle_t, tdata_t, tsize_t)
55 {
56         return 0;
57 }
58
59 static tsize_t
60 _tiffisReadProc(thandle_t fd, tdata_t buf, tsize_t size)
61 {
62         tiffis_data     *data = (tiffis_data *)fd;
63
64         data->myIS->read((char *)buf, (int)size);
65
66         return data->myIS->gcount();
67 }
68
69 static tsize_t
70 _tiffosWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
71 {
72         tiffos_data     *data = (tiffos_data *)fd;
73         ostream         *os = data->myOS;
74         int             pos = os->tellp();
75
76         os->write((const char *)buf, size);
77
78         return ((int)os->tellp()) - pos;
79 }
80
81 static tsize_t
82 _tiffisWriteProc(thandle_t, tdata_t, tsize_t)
83 {
84         return 0;
85 }
86
87 static toff_t
88 _tiffosSeekProc(thandle_t fd, toff_t off, int whence)
89 {
90         tiffos_data     *data = (tiffos_data *)fd;
91         ostream *os = data->myOS;
92
93         // if the stream has already failed, don't do anything
94         if( os->fail() )
95                 return os->tellp();
96
97         switch(whence) {
98         case SEEK_SET:
99             os->seekp(data->myStreamStartPos + off, ios::beg);
100                 break;
101         case SEEK_CUR:
102                 os->seekp(off, ios::cur);
103                 break;
104         case SEEK_END:
105                 os->seekp(off, ios::end);
106                 break;
107         }
108
109         // Attempt to workaround problems with seeking past the end of the
110         // stream.  ofstream doesn't have a problem with this but
111         // ostrstream/ostringstream does. In that situation, add intermediate
112         // '\0' characters.
113         if( os->fail() ) {
114 #ifdef __VMS
115                 int             old_state;
116 #else
117                 ios::iostate    old_state;
118 #endif
119                 toff_t          origin=0;
120
121                 old_state = os->rdstate();
122                 // reset the fail bit or else tellp() won't work below
123                 os->clear(os->rdstate() & ~ios::failbit);
124                 switch( whence ) {
125                         case SEEK_SET:
126                                 origin = data->myStreamStartPos;
127                                 break;
128                         case SEEK_CUR:
129                                 origin = os->tellp();
130                                 break;
131                         case SEEK_END:
132                                 os->seekp(0, ios::end);
133                                 origin = os->tellp();
134                                 break;
135                 }
136                 // restore original stream state
137                 os->clear(old_state);   
138
139                 // only do something if desired seek position is valid
140                 if( origin + off > data->myStreamStartPos ) {
141                         toff_t  num_fill;
142
143                         // clear the fail bit 
144                         os->clear(os->rdstate() & ~ios::failbit);
145
146                         // extend the stream to the expected size
147                         os->seekp(0, ios::end);
148                         num_fill = origin + off - (toff_t)os->tellp();
149                         for( toff_t i = 0; i < num_fill; i++ )
150                                 os->put('\0');
151
152                         // retry the seek
153                         os->seekp(origin + off, ios::beg);
154                 }
155         }
156
157         return os->tellp();
158 }
159
160 static toff_t
161 _tiffisSeekProc(thandle_t fd, toff_t off, int whence)
162 {
163         tiffis_data     *data = (tiffis_data *)fd;
164
165         switch(whence) {
166         case SEEK_SET:
167                 data->myIS->seekg(data->myStreamStartPos + off, ios::beg);
168                 break;
169         case SEEK_CUR:
170                 data->myIS->seekg(off, ios::cur);
171                 break;
172         case SEEK_END:
173                 data->myIS->seekg(off, ios::end);
174                 break;
175         }
176
177         return ((long)data->myIS->tellg()) - data->myStreamStartPos;
178 }
179
180 static toff_t
181 _tiffosSizeProc(thandle_t fd)
182 {
183         tiffos_data     *data = (tiffos_data *)fd;
184         ostream         *os = data->myOS;
185         toff_t          pos = os->tellp();
186         toff_t          len;
187
188         os->seekp(0, ios::end);
189         len = os->tellp();
190         os->seekp(pos);
191
192         return len;
193 }
194
195 static toff_t
196 _tiffisSizeProc(thandle_t fd)
197 {
198         tiffis_data     *data = (tiffis_data *)fd;
199         int             pos = data->myIS->tellg();
200         int             len;
201
202         data->myIS->seekg(0, ios::end);
203         len = data->myIS->tellg();
204         data->myIS->seekg(pos);
205
206         return len;
207 }
208
209 static int
210 _tiffosCloseProc(thandle_t fd)
211 {
212         // Our stream was not allocated by us, so it shouldn't be closed by us.
213         delete (tiffos_data *)fd;
214         return 0;
215 }
216
217 static int
218 _tiffisCloseProc(thandle_t fd)
219 {
220         // Our stream was not allocated by us, so it shouldn't be closed by us.
221         delete (tiffis_data *)fd;
222         return 0;
223 }
224
225 static int
226 _tiffDummyMapProc(thandle_t , tdata_t* , toff_t* )
227 {
228         return (0);
229 }
230
231 static void
232 _tiffDummyUnmapProc(thandle_t , tdata_t , toff_t )
233 {
234 }
235
236 /*
237  * Open a TIFF file descriptor for read/writing.
238  */
239 static TIFF*
240 _tiffStreamOpen(const char* name, const char* mode, void *fd)
241 {
242         TIFF*   tif;
243
244         if( strchr(mode, 'w') ) {
245                 tiffos_data     *data = new tiffos_data;
246                 data->myOS = (ostream *)fd;
247                 data->myStreamStartPos = data->myOS->tellp();
248
249                 // Open for writing.
250                 tif = TIFFClientOpen(name, mode,
251                                 (thandle_t) data,
252                                 _tiffosReadProc, _tiffosWriteProc,
253                                 _tiffosSeekProc, _tiffosCloseProc,
254                                 _tiffosSizeProc,
255                                 _tiffDummyMapProc, _tiffDummyUnmapProc);
256         } else {
257                 tiffis_data     *data = new tiffis_data;
258                 data->myIS = (istream *)fd;
259                 data->myStreamStartPos = data->myIS->tellg();
260                 // Open for reading.
261                 tif = TIFFClientOpen(name, mode,
262                                 (thandle_t) data,
263                                 _tiffisReadProc, _tiffisWriteProc,
264                                 _tiffisSeekProc, _tiffisCloseProc,
265                                 _tiffisSizeProc,
266                                 _tiffDummyMapProc, _tiffDummyUnmapProc);
267         }
268
269         return (tif);
270 }
271
272 TIFF*
273 TIFFStreamOpen(const char* name, ostream *os)
274 {
275         // If os is either a ostrstream or ostringstream, and has no data
276         // written to it yet, then tellp() will return -1 which will break us.
277         // We workaround this by writing out a dummy character and
278         // then seek back to the beginning.
279         if( !os->fail() && (int)os->tellp() < 0 ) {
280                 *os << '\0';
281                 os->seekp(0);
282         }
283
284         // NB: We don't support mapped files with streams so add 'm'
285         return _tiffStreamOpen(name, "wm", os);
286 }
287
288 TIFF*
289 TIFFStreamOpen(const char* name, istream *is)
290 {
291         // NB: We don't support mapped files with streams so add 'm'
292         return _tiffStreamOpen(name, "rm", is);
293 }
294
295 /* vim: set ts=8 sts=8 sw=8 noet: */