1 ///////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
4 // Digital Ltd. LLC
5 //
6 // All rights reserved.
7 //
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions are
10 // met:
11 // *       Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 // *       Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
16 // distribution.
17 // *       Neither the name of Industrial Light & Magic nor the names of
18 // its contributors may be used to endorse or promote products derived
19 // from this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.67
32 //
33 ///////////////////////////////////////////////////////////////////////////
34 
35 
36 //-----------------------------------------------------------------------------
37 //
38 //	Low-level file input and output for OpenEXR
39 //	based on C++ standard iostreams.
40 //
41 //-----------------------------------------------------------------------------
42 
43 #include <ImfStdIO.h>
44 #include "Iex.h"
45 #include <errno.h>
46 
47 using namespace std;
48 #include "ImfNamespace.h"
49 
50 OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
51 
52 namespace {
53 
54 void
clearError()55 clearError ()
56 {
57     errno = 0;
58 }
59 
60 
61 bool
checkError(istream & is,streamsize expected=0)62 checkError (istream &is, streamsize expected = 0)
63 {
64     if (!is)
65     {
66 	if (errno)
67 	    IEX_NAMESPACE::throwErrnoExc();
68 
69 	if (is.gcount() < expected)
70 	{
71 		THROW (IEX_NAMESPACE::InputExc, "Early end of file: read " << is.gcount()
72 			<< " out of " << expected << " requested bytes.");
73 	}
74 	return false;
75     }
76 
77     return true;
78 }
79 
80 
81 void
checkError(ostream & os)82 checkError (ostream &os)
83 {
84     if (!os)
85     {
86 	if (errno)
87 	    IEX_NAMESPACE::throwErrnoExc();
88 
89 	throw IEX_NAMESPACE::ErrnoExc ("File output failed.");
90     }
91 }
92 
93 } // namespace
94 
95 
StdIFStream(const char fileName[])96 StdIFStream::StdIFStream (const char fileName[]):
97     OPENEXR_IMF_INTERNAL_NAMESPACE::IStream (fileName),
98     _is (new ifstream (fileName, ios_base::binary)),
99     _deleteStream (true)
100 {
101     if (!*_is)
102     {
103 	delete _is;
104 	IEX_NAMESPACE::throwErrnoExc();
105     }
106 }
107 
108 
StdIFStream(ifstream & is,const char fileName[])109 StdIFStream::StdIFStream (ifstream &is, const char fileName[]):
110     OPENEXR_IMF_INTERNAL_NAMESPACE::IStream (fileName),
111     _is (&is),
112     _deleteStream (false)
113 {
114     // empty
115 }
116 
117 
~StdIFStream()118 StdIFStream::~StdIFStream ()
119 {
120     if (_deleteStream)
121 	delete _is;
122 }
123 
124 
125 bool
read(char c[],int n)126 StdIFStream::read (char c[/*n*/], int n)
127 {
128     if (!*_is)
129         throw IEX_NAMESPACE::InputExc ("Unexpected end of file.");
130 
131     clearError();
132     _is->read (c, n);
133     return checkError (*_is, n);
134 }
135 
136 
137 Int64
tellg()138 StdIFStream::tellg ()
139 {
140     return std::streamoff (_is->tellg());
141 }
142 
143 
144 void
seekg(Int64 pos)145 StdIFStream::seekg (Int64 pos)
146 {
147     _is->seekg (pos);
148     checkError (*_is);
149 }
150 
151 
152 void
clear()153 StdIFStream::clear ()
154 {
155     _is->clear();
156 }
157 
158 
StdOFStream(const char fileName[])159 StdOFStream::StdOFStream (const char fileName[]):
160     OPENEXR_IMF_INTERNAL_NAMESPACE::OStream (fileName),
161     _os (new ofstream (fileName, ios_base::binary)),
162     _deleteStream (true)
163 {
164     if (!*_os)
165     {
166 	delete _os;
167 	IEX_NAMESPACE::throwErrnoExc();
168     }
169 }
170 
171 
StdOFStream(ofstream & os,const char fileName[])172 StdOFStream::StdOFStream (ofstream &os, const char fileName[]):
173     OPENEXR_IMF_INTERNAL_NAMESPACE::OStream (fileName),
174     _os (&os),
175     _deleteStream (false)
176 {
177     // empty
178 }
179 
180 
~StdOFStream()181 StdOFStream::~StdOFStream ()
182 {
183     if (_deleteStream)
184 	delete _os;
185 }
186 
187 
188 void
write(const char c[],int n)189 StdOFStream::write (const char c[/*n*/], int n)
190 {
191     clearError();
192     _os->write (c, n);
193     checkError (*_os);
194 }
195 
196 
197 Int64
tellp()198 StdOFStream::tellp ()
199 {
200     return std::streamoff (_os->tellp());
201 }
202 
203 
204 void
seekp(Int64 pos)205 StdOFStream::seekp (Int64 pos)
206 {
207     _os->seekp (pos);
208     checkError (*_os);
209 }
210 
211 
StdOSStream()212 StdOSStream::StdOSStream (): OPENEXR_IMF_INTERNAL_NAMESPACE::OStream ("(string)")
213 {
214     // empty
215 }
216 
217 
218 void
write(const char c[],int n)219 StdOSStream::write (const char c[/*n*/], int n)
220 {
221     clearError();
222     _os.write (c, n);
223     checkError (_os);
224 }
225 
226 
227 Int64
tellp()228 StdOSStream::tellp ()
229 {
230     return std::streamoff (_os.tellp());
231 }
232 
233 
234 void
seekp(Int64 pos)235 StdOSStream::seekp (Int64 pos)
236 {
237     _os.seekp (pos);
238     checkError (_os);
239 }
240 
241 
242 OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT
243