PageRenderTime 69ms CodeModel.GetById 17ms app.highlight 47ms RepoModel.GetById 1ms app.codeStats 0ms

/src/FreeImage/Source/LibTIFF/tif_stream.cxx

https://bitbucket.org/cabalistic/ogredeps/
C++ | 295 lines | 197 code | 46 blank | 52 comment | 8 complexity | 5c260b2730c3667af90c839c5a782cbf MD5 | raw file
  1/* $Id: tif_stream.cxx,v 1.32 2011/04/10 17:14:09 drolon 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
 34using namespace std;
 35#endif
 36
 37class tiffis_data
 38{
 39  public:
 40
 41	istream	*myIS;
 42        long	myStreamStartPos;
 43};
 44
 45class tiffos_data
 46{
 47  public:
 48
 49	ostream	*myOS;
 50	long	myStreamStartPos;
 51};
 52
 53static tsize_t
 54_tiffosReadProc(thandle_t, tdata_t, tsize_t)
 55{
 56        return 0;
 57}
 58
 59static 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
 69static 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
 81static tsize_t
 82_tiffisWriteProc(thandle_t, tdata_t, tsize_t)
 83{
 84	return 0;
 85}
 86
 87static 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
160static 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
180static 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
195static 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
209static 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
217static 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
225static int
226_tiffDummyMapProc(thandle_t , tdata_t* , toff_t* )
227{
228	return (0);
229}
230
231static void
232_tiffDummyUnmapProc(thandle_t , tdata_t , toff_t )
233{
234}
235
236/*
237 * Open a TIFF file descriptor for read/writing.
238 */
239static 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
272TIFF*
273TIFFStreamOpen(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
288TIFF*
289TIFFStreamOpen(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: */