Coverage Report

Created: 2026-06-14 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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