GCC Code Coverage Report


Directory: ./
File: openvdb/openvdb/io/Stream.cc
Date: 2022-07-25 17:40:05
Exec Total Coverage
Lines: 47 87 54.0%
Functions: 11 14 78.6%
Branches: 31 172 18.0%

Line Branch Exec Source
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3
4 #include "Stream.h"
5
6 #include "File.h" ///< @todo refactor
7 #include "GridDescriptor.h"
8 #include "TempFile.h"
9 #include <openvdb/Exceptions.h>
10 #include <cstdint>
11 #include <boost/iostreams/copy.hpp>
12 #include <cstdio> // for remove()
13 #include <functional> // for std::bind()
14 #include <iostream>
15 #include <vector>
16
17
18 namespace openvdb {
19 OPENVDB_USE_VERSION_NAMESPACE
20 namespace OPENVDB_VERSION_NAME {
21 namespace io {
22
23 struct Stream::Impl
24 {
25
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
10 Impl(): mOutputStream{nullptr} {}
26 2 Impl(const Impl& other) { *this = other; }
27 2 Impl& operator=(const Impl& other)
28 {
29
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (&other != this) {
30 mMeta = other.mMeta; ///< @todo deep copy?
31 mGrids = other.mGrids; ///< @todo deep copy?
32
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 mOutputStream = other.mOutputStream;
33 mFile.reset();
34 }
35 2 return *this;
36 }
37
38 MetaMap::Ptr mMeta;
39 GridPtrVecPtr mGrids;
40 std::ostream* mOutputStream;
41 std::unique_ptr<File> mFile;
42 };
43
44
45 ////////////////////////////////////////
46
47
48 namespace {
49
50 /// @todo Use MappedFile auto-deletion instead.
51 void
52 3 removeTempFile(const std::string expectedFilename, const std::string& filename)
53 {
54
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (filename == expectedFilename) {
55
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (0 != std::remove(filename.c_str())) {
56 std::string mesg = getErrorString();
57 if (!mesg.empty()) mesg = " (" + mesg + ")";
58 OPENVDB_LOG_WARN("failed to remove temporary file " << filename << mesg);
59 }
60 }
61 3 }
62
63 }
64
65
66
1/2
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 Stream::Stream(std::istream& is, bool delayLoad): mImpl(new Impl)
67 {
68
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!is) return;
69
70
3/6
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
3 if (delayLoad && Archive::isDelayedLoadingEnabled()) {
71 // Copy the contents of the stream to a temporary private file
72 // and open the file instead.
73 3 std::unique_ptr<TempFile> tempFile;
74 try {
75
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
3 tempFile.reset(new TempFile);
76 } catch (std::exception& e) {
77 std::string mesg;
78 if (e.what()) mesg = std::string(" (") + e.what() + ")";
79 OPENVDB_LOG_WARN("failed to create a temporary file for delayed loading" << mesg
80 << "; will read directly from the input stream instead");
81 }
82
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (tempFile) {
83
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 boost::iostreams::copy(is, *tempFile);
84
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 const std::string& filename = tempFile->filename();
85
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
3 mImpl->mFile.reset(new File(filename));
86
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 mImpl->mFile->setCopyMaxBytes(0); // don't make a copy of the temporary file
87 /// @todo Need to pass auto-deletion flag to MappedFile.
88
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
6 mImpl->mFile->open(delayLoad,
89
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
3 std::bind(&removeTempFile, filename, std::placeholders::_1));
90 }
91 }
92
93
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!mImpl->mFile) {
94 readHeader(is);
95
96 // Tag the input stream with the library and file format version numbers
97 // and the compression options specified in the header.
98 StreamMetadata::Ptr streamMetadata(new StreamMetadata);
99 io::setStreamMetadataPtr(is, streamMetadata, /*transfer=*/false);
100 io::setVersion(is, libraryVersion(), fileVersion());
101 io::setDataCompression(is, compression());
102
103 // Read in the VDB metadata.
104 mImpl->mMeta.reset(new MetaMap);
105 mImpl->mMeta->readMeta(is);
106
107 // Read in the number of grids.
108 const int32_t gridCount = readGridCount(is);
109
110 // Read in all grids and insert them into mGrids.
111 mImpl->mGrids.reset(new GridPtrVec);
112 std::vector<GridDescriptor> descriptors;
113 descriptors.reserve(gridCount);
114 Archive::NamedGridMap namedGrids;
115 for (int32_t i = 0; i < gridCount; ++i) {
116 GridDescriptor gd;
117 gd.read(is);
118 descriptors.push_back(gd);
119 GridBase::Ptr grid = readGrid(gd, is);
120 mImpl->mGrids->push_back(grid);
121 namedGrids[gd.uniqueName()] = grid;
122 }
123
124 // Connect instances (grids that share trees with other grids).
125 for (size_t i = 0, N = descriptors.size(); i < N; ++i) {
126 Archive::connectInstance(descriptors[i], namedGrids);
127 }
128 }
129 }
130
131
132 Stream::Stream(): mImpl(new Impl)
133 {
134 }
135
136
137
1/2
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
7 Stream::Stream(std::ostream& os): mImpl(new Impl)
138 {
139 7 mImpl->mOutputStream = &os;
140 7 }
141
142
143 28 Stream::~Stream()
144 {
145 28 }
146
147
148
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 Stream::Stream(const Stream& other): Archive(other), mImpl(new Impl(*other.mImpl))
149 {
150 2 }
151
152
153 Stream&
154 Stream::operator=(const Stream& other)
155 {
156 if (&other != this) {
157 mImpl.reset(new Impl(*other.mImpl));
158 }
159 return *this;
160 }
161
162
163 SharedPtr<Archive>
164 2 Stream::copy() const
165 {
166
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 return SharedPtr<Archive>(new Stream(*this));
167 }
168
169
170 ////////////////////////////////////////
171
172
173 GridBase::Ptr
174 Stream::readGrid(const GridDescriptor& gd, std::istream& is) const
175 {
176 GridBase::Ptr grid;
177
178 if (!GridBase::isRegistered(gd.gridType())) {
179 OPENVDB_THROW(TypeError, "can't read grid \""
180 << GridDescriptor::nameAsString(gd.uniqueName()) <<
181 "\" from input stream because grid type " << gd.gridType() << " is unknown");
182 } else {
183 grid = GridBase::createGrid(gd.gridType());
184 if (grid) grid->setSaveFloatAsHalf(gd.saveFloatAsHalf());
185
186 Archive::readGrid(grid, gd, is);
187 }
188 return grid;
189 }
190
191
192 void
193
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 Stream::write(const GridCPtrVec& grids, const MetaMap& metadata) const
194 {
195
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (mImpl->mOutputStream == nullptr) {
196 OPENVDB_THROW(ValueError, "no output stream was specified");
197 }
198 6 this->writeGrids(*mImpl->mOutputStream, grids, metadata);
199 6 }
200
201
202 void
203 6 Stream::writeGrids(std::ostream& os, const GridCPtrVec& grids, const MetaMap& metadata) const
204 {
205 6 Archive::write(os, grids, /*seekable=*/false, metadata);
206 6 }
207
208
209 ////////////////////////////////////////
210
211
212 MetaMap::Ptr
213 2 Stream::getMetadata() const
214 {
215
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 MetaMap::Ptr result;
216
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (mImpl->mFile) {
217
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 result = mImpl->mFile->getMetadata();
218 } else if (mImpl->mMeta) {
219 // Return a deep copy of the file-level metadata
220 // that was read when this object was constructed.
221 result.reset(new MetaMap(*mImpl->mMeta));
222 }
223 2 return result;
224 }
225
226
227 GridPtrVecPtr
228
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 Stream::getGrids()
229 {
230
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (mImpl->mFile) {
231 3 return mImpl->mFile->getGrids();
232 }
233 return mImpl->mGrids;
234 }
235
236 } // namespace io
237 } // namespace OPENVDB_VERSION_NAME
238 } // namespace openvdb
239