]> git.saurik.com Git - wxWidgets.git/blob - src/tiff/libtiff/tif_stream.cxx
cleanup
[wxWidgets.git] / src / tiff / libtiff / tif_stream.cxx
1 /* $Id: tif_stream.cxx,v 1.5 2005/07/26 08:11:13 dron 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 using namespace std;
34
35 class tiffis_data
36 {
37 public:
38
39 istream *myIS;
40 long myStreamStartPos;
41 };
42
43 class tiffos_data
44 {
45 public:
46
47 ostream *myOS;
48 long myStreamStartPos;
49 };
50
51 static tsize_t
52 _tiffosReadProc(thandle_t, tdata_t, tsize_t)
53 {
54 return 0;
55 }
56
57 static tsize_t
58 _tiffisReadProc(thandle_t fd, tdata_t buf, tsize_t size)
59 {
60 tiffis_data *data = (tiffis_data *)fd;
61
62 data->myIS->read((char *)buf, (int)size);
63
64 return data->myIS->gcount();
65 }
66
67 static tsize_t
68 _tiffosWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
69 {
70 tiffos_data *data = (tiffos_data *)fd;
71 ostream *os = data->myOS;
72 int pos = os->tellp();
73
74 os->write((const char *)buf, size);
75
76 return ((int)os->tellp()) - pos;
77 }
78
79 static tsize_t
80 _tiffisWriteProc(thandle_t, tdata_t, tsize_t)
81 {
82 return 0;
83 }
84
85 static toff_t
86 _tiffosSeekProc(thandle_t fd, toff_t off, int whence)
87 {
88 tiffos_data *data = (tiffos_data *)fd;
89 ostream *os = data->myOS;
90
91 // if the stream has already failed, don't do anything
92 if( os->fail() )
93 return os->tellp();
94
95 switch(whence) {
96 case SEEK_SET:
97 os->seekp(data->myStreamStartPos + off, ios::beg);
98 break;
99 case SEEK_CUR:
100 os->seekp(off, ios::cur);
101 break;
102 case SEEK_END:
103 os->seekp(off, ios::end);
104 break;
105 }
106
107 // Attempt to workaround problems with seeking past the end of the
108 // stream. ofstream doesn't have a problem with this but
109 // ostrstream/ostringstream does. In that situation, add intermediate
110 // '\0' characters.
111 if( os->fail() ) {
112 ios::iostate old_state;
113 toff_t origin;
114
115 old_state = os->rdstate();
116 // reset the fail bit or else tellp() won't work below
117 os->clear(os->rdstate() & ~ios::failbit);
118 switch( whence ) {
119 case SEEK_SET:
120 origin = data->myStreamStartPos;
121 break;
122 case SEEK_CUR:
123 origin = os->tellp();
124 break;
125 case SEEK_END:
126 os->seekp(0, ios::end);
127 origin = os->tellp();
128 break;
129 }
130 // restore original stream state
131 os->clear(old_state);
132
133 // only do something if desired seek position is valid
134 if( origin + off > data->myStreamStartPos ) {
135 toff_t num_fill;
136
137 // clear the fail bit
138 os->clear(os->rdstate() & ~ios::failbit);
139
140 // extend the stream to the expected size
141 os->seekp(0, ios::end);
142 num_fill = origin + off - (toff_t)os->tellp();
143 for( toff_t i = 0; i < num_fill; i++ )
144 os->put('\0');
145
146 // retry the seek
147 os->seekp(origin + off, ios::beg);
148 }
149 }
150
151 return os->tellp();
152 }
153
154 static toff_t
155 _tiffisSeekProc(thandle_t fd, toff_t off, int whence)
156 {
157 tiffis_data *data = (tiffis_data *)fd;
158
159 switch(whence) {
160 case SEEK_SET:
161 data->myIS->seekg(data->myStreamStartPos + off, ios::beg);
162 break;
163 case SEEK_CUR:
164 data->myIS->seekg(off, ios::cur);
165 break;
166 case SEEK_END:
167 data->myIS->seekg(off, ios::end);
168 break;
169 }
170
171 return ((long)data->myIS->tellg()) - data->myStreamStartPos;
172 }
173
174 static toff_t
175 _tiffosSizeProc(thandle_t fd)
176 {
177 tiffos_data *data = (tiffos_data *)fd;
178 ostream *os = data->myOS;
179 toff_t pos = os->tellp();
180 toff_t len;
181
182 os->seekp(0, ios::end);
183 len = os->tellp();
184 os->seekp(pos);
185
186 return len;
187 }
188
189 static toff_t
190 _tiffisSizeProc(thandle_t fd)
191 {
192 tiffis_data *data = (tiffis_data *)fd;
193 int pos = data->myIS->tellg();
194 int len;
195
196 data->myIS->seekg(0, ios::end);
197 len = data->myIS->tellg();
198 data->myIS->seekg(pos);
199
200 return len;
201 }
202
203 static int
204 _tiffosCloseProc(thandle_t fd)
205 {
206 // Our stream was not allocated by us, so it shouldn't be closed by us.
207 delete (tiffos_data *)fd;
208 return 0;
209 }
210
211 static int
212 _tiffisCloseProc(thandle_t fd)
213 {
214 // Our stream was not allocated by us, so it shouldn't be closed by us.
215 delete (tiffis_data *)fd;
216 return 0;
217 }
218
219 static int
220 _tiffDummyMapProc(thandle_t , tdata_t* , toff_t* )
221 {
222 return (0);
223 }
224
225 static void
226 _tiffDummyUnmapProc(thandle_t , tdata_t , toff_t )
227 {
228 }
229
230 /*
231 * Open a TIFF file descriptor for read/writing.
232 */
233 static TIFF*
234 _tiffStreamOpen(const char* name, const char* mode, void *fd)
235 {
236 TIFF* tif;
237
238 if( strchr(mode, 'w') ) {
239 tiffos_data *data = new tiffos_data;
240 data->myOS = (ostream *)fd;
241 data->myStreamStartPos = data->myOS->tellp();
242
243 // Open for writing.
244 tif = TIFFClientOpen(name, mode,
245 (thandle_t) data,
246 _tiffosReadProc, _tiffosWriteProc,
247 _tiffosSeekProc, _tiffosCloseProc,
248 _tiffosSizeProc,
249 _tiffDummyMapProc, _tiffDummyUnmapProc);
250 } else {
251 tiffis_data *data = new tiffis_data;
252 data->myIS = (istream *)fd;
253 data->myStreamStartPos = data->myIS->tellg();
254 // Open for reading.
255 tif = TIFFClientOpen(name, mode,
256 (thandle_t) data,
257 _tiffisReadProc, _tiffisWriteProc,
258 _tiffisSeekProc, _tiffisCloseProc,
259 _tiffisSizeProc,
260 _tiffDummyMapProc, _tiffDummyUnmapProc);
261 }
262
263 return (tif);
264 }
265
266 TIFF*
267 TIFFStreamOpen(const char* name, ostream *os)
268 {
269 // If os is either a ostrstream or ostringstream, and has no data
270 // written to it yet, then tellp() will return -1 which will break us.
271 // We workaround this by writing out a dummy character and
272 // then seek back to the beginning.
273 if( !os->fail() && (int)os->tellp() < 0 ) {
274 *os << '\0';
275 os->seekp(0);
276 }
277
278 // NB: We don't support mapped files with streams so add 'm'
279 return _tiffStreamOpen(name, "wm", os);
280 }
281
282 TIFF*
283 TIFFStreamOpen(const char* name, istream *is)
284 {
285 // NB: We don't support mapped files with streams so add 'm'
286 return _tiffStreamOpen(name, "rm", is);
287 }
288
289 /* vim: set ts=8 sts=8 sw=8 noet: */