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

https://bitbucket.org/cabalistic/ogredeps/ · C++ · 295 lines · 197 code · 46 blank · 52 comment · 11 complexity · 5c260b2730c3667af90c839c5a782cbf MD5 · raw file

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