/src/openexr/src/lib/OpenEXR/ImfStdIO.cpp
Line | Count | Source |
1 | | // |
2 | | // SPDX-License-Identifier: BSD-3-Clause |
3 | | // Copyright (c) Contributors to the OpenEXR Project. |
4 | | // |
5 | | |
6 | | //----------------------------------------------------------------------------- |
7 | | // |
8 | | // Low-level file input and output for OpenEXR |
9 | | // based on C++ standard iostreams. |
10 | | // |
11 | | //----------------------------------------------------------------------------- |
12 | | |
13 | | #include "Iex.h" |
14 | | #include <ImfMisc.h> |
15 | | #include <ImfStdIO.h> |
16 | | #include <errno.h> |
17 | | #include <filesystem> |
18 | | #if __cplusplus >= 202002L |
19 | | # include <ranges> |
20 | | # include <span> |
21 | | #endif |
22 | | |
23 | | using namespace std; |
24 | | #include "ImfNamespace.h" |
25 | | |
26 | | OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER |
27 | | |
28 | | namespace |
29 | | { |
30 | | |
31 | | inline ifstream* |
32 | | make_ifstream (const char* filename) |
33 | 0 | { |
34 | | #if __cplusplus >= 202002L |
35 | | auto u8view = ranges::views::transform (span{filename, strlen(filename)}, |
36 | | [](char c) -> char8_t { return c; }); |
37 | | return new ifstream (filesystem::path (u8view.begin (), u8view.end ()), |
38 | | ios_base::in | ios_base::binary); |
39 | | #else |
40 | 0 | return new ifstream (filesystem::u8path (filename), |
41 | 0 | ios_base::in | ios_base::binary); |
42 | 0 | #endif |
43 | 0 | } |
44 | | |
45 | | inline ofstream* |
46 | | make_ofstream (const char* filename) |
47 | 0 | { |
48 | | #if __cplusplus >= 202002L |
49 | | auto u8view = ranges::views::transform (span{filename, strlen(filename)}, |
50 | | [](char c) -> char8_t { return c; }); |
51 | | return new ofstream (filesystem::path (u8view.begin (), u8view.end ()), |
52 | | ios_base::out | ios_base::binary); |
53 | | #else |
54 | 0 | return new ofstream (filesystem::u8path (filename), |
55 | 0 | ios_base::out | ios_base::binary); |
56 | 0 | #endif |
57 | 0 | } |
58 | | |
59 | | void |
60 | | clearError () |
61 | 0 | { |
62 | 0 | errno = 0; |
63 | 0 | } |
64 | | |
65 | | bool |
66 | | checkError (istream& is, streamsize expected = 0) |
67 | 0 | { |
68 | 0 | if (!is) |
69 | 0 | { |
70 | 0 | if (errno) IEX_NAMESPACE::throwErrnoExc (); |
71 | |
|
72 | 0 | if (is.gcount () < expected) |
73 | 0 | { |
74 | 0 | THROW ( |
75 | 0 | IEX_NAMESPACE::InputExc, |
76 | 0 | "Early end of file: read " << is.gcount () << " out of " |
77 | 0 | << expected << " requested bytes."); |
78 | 0 | } |
79 | 0 | return false; |
80 | 0 | } |
81 | | |
82 | 0 | return true; |
83 | 0 | } |
84 | | |
85 | | void |
86 | | checkError (ostream& os) |
87 | 0 | { |
88 | 0 | if (!os) |
89 | 0 | { |
90 | 0 | if (errno) IEX_NAMESPACE::throwErrnoExc (); |
91 | |
|
92 | 0 | throw IEX_NAMESPACE::ErrnoExc ("File output failed."); |
93 | 0 | } |
94 | 0 | } |
95 | | |
96 | | } // namespace |
97 | | |
98 | | StdIFStream::StdIFStream (const char fileName[]) |
99 | 0 | : OPENEXR_IMF_INTERNAL_NAMESPACE::IStream (fileName) |
100 | 0 | , _is (make_ifstream (fileName)) |
101 | 0 | , _deleteStream (true) |
102 | 0 | { |
103 | 0 | if (!*_is) |
104 | 0 | { |
105 | 0 | delete _is; |
106 | 0 | IEX_NAMESPACE::throwErrnoExc (); |
107 | 0 | } |
108 | 0 | } |
109 | | |
110 | | StdIFStream::StdIFStream (ifstream& is, const char fileName[]) |
111 | 0 | : OPENEXR_IMF_INTERNAL_NAMESPACE::IStream (fileName) |
112 | 0 | , _is (&is) |
113 | 0 | , _deleteStream (false) |
114 | 0 | { |
115 | | // empty |
116 | 0 | } |
117 | | |
118 | | StdIFStream::~StdIFStream () |
119 | 0 | { |
120 | 0 | if (_deleteStream) delete _is; |
121 | 0 | } |
122 | | |
123 | | bool |
124 | | StdIFStream::read (char c[/*n*/], int n) |
125 | 0 | { |
126 | 0 | if (!*_is) throw IEX_NAMESPACE::InputExc ("Unexpected end of file."); |
127 | | |
128 | 0 | clearError (); |
129 | 0 | _is->read (c, n); |
130 | 0 | return checkError (*_is, n); |
131 | 0 | } |
132 | | |
133 | | uint64_t |
134 | | StdIFStream::tellg () |
135 | 0 | { |
136 | 0 | return std::streamoff (_is->tellg ()); |
137 | 0 | } |
138 | | |
139 | | void |
140 | | StdIFStream::seekg (uint64_t pos) |
141 | 0 | { |
142 | 0 | _is->seekg (pos); |
143 | 0 | checkError (*_is); |
144 | 0 | } |
145 | | |
146 | | void |
147 | | StdIFStream::clear () |
148 | 0 | { |
149 | 0 | _is->clear (); |
150 | 0 | } |
151 | | |
152 | | StdISStream::StdISStream () |
153 | 0 | : OPENEXR_IMF_INTERNAL_NAMESPACE::IStream ("(string)") |
154 | 0 | { |
155 | | // empty |
156 | 0 | } |
157 | | |
158 | | StdISStream::~StdISStream () |
159 | 0 | {} |
160 | | |
161 | | bool |
162 | | StdISStream::read (char c[/*n*/], int n) |
163 | 0 | { |
164 | 0 | if (!_is) throw IEX_NAMESPACE::InputExc ("Unexpected end of file."); |
165 | | |
166 | 0 | clearError (); |
167 | 0 | _is.read (c, n); |
168 | 0 | return checkError (_is, n); |
169 | 0 | } |
170 | | |
171 | | uint64_t |
172 | | StdISStream::tellg () |
173 | 0 | { |
174 | 0 | return std::streamoff (_is.tellg ()); |
175 | 0 | } |
176 | | |
177 | | void |
178 | | StdISStream::seekg (uint64_t pos) |
179 | 0 | { |
180 | 0 | _is.seekg (pos); |
181 | 0 | checkError (_is); |
182 | 0 | } |
183 | | |
184 | | void |
185 | | StdISStream::clear () |
186 | 0 | { |
187 | 0 | _is.clear (); |
188 | 0 | } |
189 | | |
190 | | std::string |
191 | | StdISStream::str () const |
192 | 0 | { |
193 | 0 | return _is.str (); |
194 | 0 | } |
195 | | |
196 | | void |
197 | | StdISStream::str (const std::string& s) |
198 | 0 | { |
199 | 0 | _is.str (s); |
200 | 0 | } |
201 | | |
202 | | StdOFStream::StdOFStream (const char fileName[]) |
203 | 0 | : OPENEXR_IMF_INTERNAL_NAMESPACE::OStream (fileName) |
204 | 0 | , _os (make_ofstream (fileName)) |
205 | 0 | , _deleteStream (true) |
206 | 0 | { |
207 | 0 | if (!*_os) |
208 | 0 | { |
209 | 0 | delete _os; |
210 | 0 | IEX_NAMESPACE::throwErrnoExc (); |
211 | 0 | } |
212 | 0 | } |
213 | | |
214 | | StdOFStream::StdOFStream (ofstream& os, const char fileName[]) |
215 | 0 | : OPENEXR_IMF_INTERNAL_NAMESPACE::OStream (fileName) |
216 | 0 | , _os (&os) |
217 | 0 | , _deleteStream (false) |
218 | 0 | { |
219 | | // empty |
220 | 0 | } |
221 | | |
222 | | StdOFStream::~StdOFStream () |
223 | 0 | { |
224 | 0 | if (_deleteStream) delete _os; |
225 | 0 | } |
226 | | |
227 | | void |
228 | | StdOFStream::write (const char c[/*n*/], int n) |
229 | 0 | { |
230 | 0 | clearError (); |
231 | 0 | _os->write (c, n); |
232 | 0 | checkError (*_os); |
233 | 0 | } |
234 | | |
235 | | uint64_t |
236 | | StdOFStream::tellp () |
237 | 0 | { |
238 | 0 | return std::streamoff (_os->tellp ()); |
239 | 0 | } |
240 | | |
241 | | void |
242 | | StdOFStream::seekp (uint64_t pos) |
243 | 0 | { |
244 | 0 | _os->seekp (pos); |
245 | 0 | checkError (*_os); |
246 | 0 | } |
247 | | |
248 | | StdOSStream::StdOSStream () |
249 | 0 | : OPENEXR_IMF_INTERNAL_NAMESPACE::OStream ("(string)") |
250 | 0 | { |
251 | | // empty |
252 | 0 | } |
253 | | |
254 | | StdOSStream::~StdOSStream () |
255 | 0 | {} |
256 | | |
257 | | void |
258 | | StdOSStream::write (const char c[/*n*/], int n) |
259 | 0 | { |
260 | 0 | clearError (); |
261 | 0 | _os.write (c, n); |
262 | 0 | checkError (_os); |
263 | 0 | } |
264 | | |
265 | | uint64_t |
266 | | StdOSStream::tellp () |
267 | 0 | { |
268 | 0 | return std::streamoff (_os.tellp ()); |
269 | 0 | } |
270 | | |
271 | | void |
272 | | StdOSStream::seekp (uint64_t pos) |
273 | 0 | { |
274 | 0 | _os.seekp (pos); |
275 | 0 | checkError (_os); |
276 | 0 | } |
277 | | |
278 | | std::string |
279 | | StdOSStream::str () const |
280 | 0 | { |
281 | 0 | return _os.str (); |
282 | 0 | } |
283 | | |
284 | | OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT |