Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright Contributors to the OpenVDB Project | ||
2 | // SPDX-License-Identifier: MPL-2.0 | ||
3 | |||
4 | /// @file io/File.cc | ||
5 | |||
6 | #include "File.h" | ||
7 | |||
8 | #include "TempFile.h" | ||
9 | #include <openvdb/Exceptions.h> | ||
10 | #include <openvdb/util/logging.h> | ||
11 | #include <cstdint> | ||
12 | #include <boost/iostreams/copy.hpp> | ||
13 | #ifndef _WIN32 | ||
14 | #include <sys/types.h> | ||
15 | #include <sys/stat.h> | ||
16 | #include <unistd.h> | ||
17 | #endif | ||
18 | #include <cassert> | ||
19 | #include <cstdlib> // for getenv(), strtoul() | ||
20 | #include <cstring> // for strerror_r() | ||
21 | #include <fstream> | ||
22 | #include <iostream> | ||
23 | #include <limits> | ||
24 | #include <sstream> | ||
25 | |||
26 | |||
27 | namespace openvdb { | ||
28 | OPENVDB_USE_VERSION_NAMESPACE | ||
29 | namespace OPENVDB_VERSION_NAME { | ||
30 | namespace io { | ||
31 | |||
32 | // Implementation details of the File class | ||
33 | struct File::Impl | ||
34 | { | ||
35 | enum { DEFAULT_COPY_MAX_BYTES = 500000000 }; // 500 MB | ||
36 | |||
37 | struct NoBBox {}; | ||
38 | |||
39 | // Common implementation of the various File::readGrid() overloads, | ||
40 | // with and without bounding box clipping | ||
41 | template<typename BoxType> | ||
42 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 106 times.
|
212 | static GridBase::Ptr readGrid(const File& file, const GridDescriptor& gd, const BoxType& bbox) |
43 | { | ||
44 | // This method should not be called for files that don't contain grid offsets. | ||
45 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 106 times.
|
212 | assert(file.inputHasGridOffsets()); |
46 | |||
47 | 212 | GridBase::Ptr grid = file.createGrid(gd); | |
48 |
2/4✓ Branch 1 taken 106 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 106 times.
✗ Branch 5 not taken.
|
212 | gd.seekToGrid(file.inputStream()); |
49 |
1/2✓ Branch 1 taken 106 times.
✗ Branch 2 not taken.
|
212 | unarchive(file, grid, gd, bbox); |
50 | 212 | return grid; | |
51 | } | ||
52 | |||
53 | 102 | static void unarchive(const File& file, GridBase::Ptr& grid, | |
54 | const GridDescriptor& gd, NoBBox) | ||
55 | { | ||
56 |
1/2✓ Branch 2 taken 102 times.
✗ Branch 3 not taken.
|
204 | file.Archive::readGrid(grid, gd, file.inputStream()); |
57 | 102 | } | |
58 | |||
59 | ✗ | static void unarchive(const File& file, GridBase::Ptr& grid, | |
60 | const GridDescriptor& gd, const CoordBBox& indexBBox) | ||
61 | { | ||
62 | ✗ | file.Archive::readGrid(grid, gd, file.inputStream(), indexBBox); | |
63 | } | ||
64 | |||
65 | 4 | static void unarchive(const File& file, GridBase::Ptr& grid, | |
66 | const GridDescriptor& gd, const BBoxd& worldBBox) | ||
67 | { | ||
68 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
8 | file.Archive::readGrid(grid, gd, file.inputStream(), worldBBox); |
69 | 4 | } | |
70 | |||
71 | 119 | static Index64 getDefaultCopyMaxBytes() | |
72 | { | ||
73 | Index64 result = DEFAULT_COPY_MAX_BYTES; | ||
74 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 119 times.
|
119 | if (const char* s = std::getenv("OPENVDB_DELAYED_LOAD_COPY_MAX_BYTES")) { |
75 | ✗ | char* endptr = nullptr; | |
76 | ✗ | result = std::strtoul(s, &endptr, /*base=*/10); | |
77 | } | ||
78 | 119 | return result; | |
79 | } | ||
80 | |||
81 | std::string mFilename; | ||
82 | // The file-level metadata | ||
83 | MetaMap::Ptr mMeta; | ||
84 | // The memory-mapped file | ||
85 | MappedFile::Ptr mFileMapping; | ||
86 | // The buffer for the input stream, if it is a memory-mapped file | ||
87 | SharedPtr<std::streambuf> mStreamBuf; | ||
88 | // The file stream that is open for reading | ||
89 | std::unique_ptr<std::istream> mInStream; | ||
90 | // File-level stream metadata (file format, compression, etc.) | ||
91 | StreamMetadata::Ptr mStreamMetadata; | ||
92 | // Flag indicating if we have read in the global information (header, | ||
93 | // metadata, and grid descriptors) for this VDB file | ||
94 | bool mIsOpen; | ||
95 | // File size limit for copying during delayed loading | ||
96 | Index64 mCopyMaxBytes; | ||
97 | // Grid descriptors for all grids stored in the file, indexed by grid name | ||
98 | NameMap mGridDescriptors; | ||
99 | // All grids, indexed by unique name (used only when mHasGridOffsets is false) | ||
100 | Archive::NamedGridMap mNamedGrids; | ||
101 | // All grids stored in the file (used only when mHasGridOffsets is false) | ||
102 | GridPtrVecPtr mGrids; | ||
103 | }; // class File::Impl | ||
104 | |||
105 | |||
106 | //////////////////////////////////////// | ||
107 | |||
108 | |||
109 |
1/2✓ Branch 2 taken 119 times.
✗ Branch 3 not taken.
|
119 | File::File(const std::string& filename): mImpl(new Impl) |
110 | { | ||
111 |
1/2✓ Branch 1 taken 119 times.
✗ Branch 2 not taken.
|
119 | mImpl->mFilename = filename; |
112 | 119 | mImpl->mIsOpen = false; | |
113 | 119 | mImpl->mCopyMaxBytes = Impl::getDefaultCopyMaxBytes(); | |
114 | setInputHasGridOffsets(true); | ||
115 | 119 | } | |
116 | |||
117 | |||
118 | 316 | File::~File() | |
119 | { | ||
120 | 316 | } | |
121 | |||
122 | |||
123 | 18 | File::File(const File& other) | |
124 | : Archive(other) | ||
125 |
1/2✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
18 | , mImpl(new Impl) |
126 | { | ||
127 |
1/2✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
18 | *this = other; |
128 | 18 | } | |
129 | |||
130 | |||
131 | File& | ||
132 | 18 | File::operator=(const File& other) | |
133 | { | ||
134 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | if (&other != this) { |
135 | Archive::operator=(other); | ||
136 | const Impl& otherImpl = *other.mImpl; | ||
137 | 18 | mImpl->mFilename = otherImpl.mFilename; | |
138 | mImpl->mMeta = otherImpl.mMeta; | ||
139 | 18 | mImpl->mIsOpen = false; // don't want two file objects reading from the same stream | |
140 | 18 | mImpl->mCopyMaxBytes = otherImpl.mCopyMaxBytes; | |
141 | mImpl->mGridDescriptors = otherImpl.mGridDescriptors; | ||
142 | mImpl->mNamedGrids = otherImpl.mNamedGrids; | ||
143 | mImpl->mGrids = otherImpl.mGrids; | ||
144 | } | ||
145 | 18 | return *this; | |
146 | } | ||
147 | |||
148 | |||
149 | SharedPtr<Archive> | ||
150 | 18 | File::copy() const | |
151 | { | ||
152 |
1/2✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
|
36 | return SharedPtr<Archive>{new File{*this}}; |
153 | } | ||
154 | |||
155 | |||
156 | //////////////////////////////////////// | ||
157 | |||
158 | |||
159 | const std::string& | ||
160 | 315 | File::filename() const | |
161 | { | ||
162 | 315 | return mImpl->mFilename; | |
163 | } | ||
164 | |||
165 | |||
166 | MetaMap::Ptr | ||
167 | 1 | File::fileMetadata() | |
168 | { | ||
169 | 1 | return mImpl->mMeta; | |
170 | } | ||
171 | |||
172 | MetaMap::ConstPtr | ||
173 | ✗ | File::fileMetadata() const | |
174 | { | ||
175 | ✗ | return mImpl->mMeta; | |
176 | } | ||
177 | |||
178 | |||
179 | const File::NameMap& | ||
180 | 312 | File::gridDescriptors() const | |
181 | { | ||
182 | 312 | return mImpl->mGridDescriptors; | |
183 | } | ||
184 | |||
185 | File::NameMap& | ||
186 | 252 | File::gridDescriptors() | |
187 | { | ||
188 | 252 | return mImpl->mGridDescriptors; | |
189 | } | ||
190 | |||
191 | |||
192 | std::istream& | ||
193 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 639 times.
|
642 | File::inputStream() const |
194 | { | ||
195 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 639 times.
|
642 | if (!mImpl->mInStream) { |
196 |
3/8✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
|
15 | OPENVDB_THROW(IoError, filename() << " is not open for reading"); |
197 | } | ||
198 | 639 | return *mImpl->mInStream; | |
199 | } | ||
200 | |||
201 | |||
202 | //////////////////////////////////////// | ||
203 | |||
204 | |||
205 | Index64 | ||
206 | 58 | File::getSize() const | |
207 | { | ||
208 | /// @internal boost::filesystem::file_size() would be a more portable alternative, | ||
209 | /// but as of 9/2014, Houdini ships without the Boost.Filesystem library, | ||
210 | /// which makes it much less convenient to use that library. | ||
211 | |||
212 | Index64 result = std::numeric_limits<Index64>::max(); | ||
213 | |||
214 | 58 | std::string mesg = "could not get size of file " + filename(); | |
215 | |||
216 | #ifdef _WIN32 | ||
217 | // Get the file size by seeking to the end of the file. | ||
218 | std::ifstream fstrm(filename()); | ||
219 | if (fstrm) { | ||
220 | fstrm.seekg(0, fstrm.end); | ||
221 | result = static_cast<Index64>(fstrm.tellg()); | ||
222 | } else { | ||
223 | OPENVDB_THROW(IoError, mesg); | ||
224 | } | ||
225 | #else | ||
226 | // Get the file size using the stat() system call. | ||
227 | struct stat info; | ||
228 |
3/4✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 57 times.
|
116 | if (0 != ::stat(filename().c_str(), &info)) { |
229 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | std::string s = getErrorString(); |
230 |
3/6✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
|
3 | if (!s.empty()) mesg += " (" + s + ")"; |
231 |
1/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
4 | OPENVDB_THROW(IoError, mesg); |
232 | } | ||
233 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
|
57 | if (!S_ISREG(info.st_mode)) { |
234 | ✗ | mesg += " (not a regular file)"; | |
235 | ✗ | OPENVDB_THROW(IoError, mesg); | |
236 | } | ||
237 | 57 | result = static_cast<Index64>(info.st_size); | |
238 | #endif | ||
239 | |||
240 | 57 | return result; | |
241 | } | ||
242 | |||
243 | |||
244 | Index64 | ||
245 | 57 | File::copyMaxBytes() const | |
246 | { | ||
247 | 57 | return mImpl->mCopyMaxBytes; | |
248 | } | ||
249 | |||
250 | |||
251 | void | ||
252 | 3 | File::setCopyMaxBytes(Index64 bytes) | |
253 | { | ||
254 | 3 | mImpl->mCopyMaxBytes = bytes; | |
255 | 3 | } | |
256 | |||
257 | |||
258 | //////////////////////////////////////// | ||
259 | |||
260 | |||
261 | bool | ||
262 | 265 | File::isOpen() const | |
263 | { | ||
264 | 265 | return mImpl->mIsOpen; | |
265 | } | ||
266 | |||
267 | |||
268 | bool | ||
269 | 59 | File::open(bool delayLoad, const MappedFile::Notifier& notifier) | |
270 | { | ||
271 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 58 times.
|
59 | if (isOpen()) { |
272 |
3/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
|
5 | OPENVDB_THROW(IoError, filename() << " is already open"); |
273 | } | ||
274 | mImpl->mInStream.reset(); | ||
275 | |||
276 | // Open the file. | ||
277 | 58 | std::unique_ptr<std::istream> newStream; | |
278 | 58 | SharedPtr<std::streambuf> newStreamBuf; | |
279 | 58 | MappedFile::Ptr newFileMapping; | |
280 |
3/6✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 58 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 58 times.
|
58 | if (!delayLoad || !Archive::isDelayedLoadingEnabled()) { |
281 | newStream.reset(new std::ifstream( | ||
282 | ✗ | filename().c_str(), std::ios_base::in | std::ios_base::binary)); | |
283 | } else { | ||
284 | bool isTempFile = false; | ||
285 |
2/4✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 58 times.
✗ Branch 5 not taken.
|
58 | std::string fname = filename(); |
286 |
5/6✓ Branch 1 taken 57 times.
✓ Branch 2 taken 1 times.
✓ Branch 4 taken 57 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 54 times.
✓ Branch 7 taken 3 times.
|
58 | if (getSize() < copyMaxBytes()) { |
287 | // If the file is not too large, make a temporary private copy of it | ||
288 | // and open the copy instead. The original file can then be modified | ||
289 | // or removed without affecting delayed load. | ||
290 | try { | ||
291 |
1/2✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
|
108 | TempFile tempFile; |
292 |
1/2✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
|
54 | std::ifstream fstrm(filename().c_str(), |
293 |
1/2✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
|
108 | std::ios_base::in | std::ios_base::binary); |
294 |
1/2✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
|
54 | boost::iostreams::copy(fstrm, tempFile); |
295 |
1/2✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
|
54 | fname = tempFile.filename(); |
296 | isTempFile = true; | ||
297 | ✗ | } catch (std::exception& e) { | |
298 | std::string mesg; | ||
299 | ✗ | if (e.what()) mesg = std::string(" (") + e.what() + ")"; | |
300 | ✗ | OPENVDB_LOG_WARN("failed to create a temporary copy of " << filename() | |
301 | << " for delayed loading" << mesg | ||
302 | << "; will read directly from " << filename() << " instead"); | ||
303 | } | ||
304 | } | ||
305 | |||
306 | // While the file is open, its mapping, stream buffer and stream | ||
307 | // must all be maintained. Once the file is closed, the buffer and | ||
308 | // the stream can be discarded, but the mapping needs to persist | ||
309 | // if any grids were lazily loaded. | ||
310 | try { | ||
311 |
3/6✓ Branch 1 taken 57 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 57 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 57 times.
✗ Branch 8 not taken.
|
57 | newFileMapping.reset(new MappedFile(fname, /*autoDelete=*/isTempFile)); |
312 |
2/4✓ Branch 1 taken 57 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 57 times.
✗ Branch 5 not taken.
|
114 | newStreamBuf = newFileMapping->createBuffer(); |
313 |
2/4✓ Branch 1 taken 57 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 57 times.
✗ Branch 5 not taken.
|
57 | newStream.reset(new std::istream(newStreamBuf.get())); |
314 | ✗ | } catch (std::exception& e) { | |
315 | ✗ | std::ostringstream ostr; | |
316 | ✗ | ostr << "could not open file " << filename(); | |
317 | ✗ | if (e.what() != nullptr) ostr << " (" << e.what() << ")"; | |
318 | ✗ | OPENVDB_THROW(IoError, ostr.str()); | |
319 | } | ||
320 | } | ||
321 | |||
322 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
|
57 | if (newStream->fail()) { |
323 | ✗ | OPENVDB_THROW(IoError, "could not open file " << filename()); | |
324 | } | ||
325 | |||
326 | // Read in the file header. | ||
327 | bool newFile = false; | ||
328 | try { | ||
329 |
2/2✓ Branch 1 taken 56 times.
✓ Branch 2 taken 1 times.
|
57 | newFile = Archive::readHeader(*newStream); |
330 | 1 | } catch (IoError& e) { | |
331 |
5/10✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
|
5 | if (e.what() && std::string("not a VDB file") == e.what()) { |
332 | // Rethrow, adding the filename. | ||
333 | ✗ | OPENVDB_THROW(IoError, filename() << " is not a VDB file"); | |
334 | } | ||
335 | 1 | throw; | |
336 | } | ||
337 | |||
338 | mImpl->mFileMapping = newFileMapping; | ||
339 |
2/4✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 56 times.
✗ Branch 4 not taken.
|
56 | if (mImpl->mFileMapping) mImpl->mFileMapping->setNotifier(notifier); |
340 | mImpl->mStreamBuf = newStreamBuf; | ||
341 | mImpl->mInStream.swap(newStream); | ||
342 | |||
343 | // Tag the input stream with the file format and library version numbers | ||
344 | // and other metadata. | ||
345 |
3/6✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 56 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 56 times.
✗ Branch 8 not taken.
|
56 | mImpl->mStreamMetadata.reset(new StreamMetadata); |
346 |
1/2✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
|
56 | mImpl->mStreamMetadata->setSeekable(true); |
347 |
2/4✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 56 times.
✗ Branch 5 not taken.
|
56 | io::setStreamMetadataPtr(inputStream(), mImpl->mStreamMetadata, /*transfer=*/false); |
348 |
2/4✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 56 times.
✗ Branch 5 not taken.
|
56 | Archive::setFormatVersion(inputStream()); |
349 |
2/4✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 56 times.
✗ Branch 5 not taken.
|
56 | Archive::setLibraryVersion(inputStream()); |
350 |
2/4✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 56 times.
✗ Branch 5 not taken.
|
56 | Archive::setDataCompression(inputStream()); |
351 |
2/4✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 56 times.
✗ Branch 5 not taken.
|
56 | io::setMappedFilePtr(inputStream(), mImpl->mFileMapping); |
352 | |||
353 | // Read in the VDB metadata. | ||
354 |
2/4✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 56 times.
✗ Branch 5 not taken.
|
112 | mImpl->mMeta = MetaMap::Ptr(new MetaMap); |
355 |
2/4✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 56 times.
✗ Branch 5 not taken.
|
56 | mImpl->mMeta->readMeta(inputStream()); |
356 | |||
357 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 51 times.
|
56 | if (!inputHasGridOffsets()) { |
358 | OPENVDB_LOG_DEBUG_RUNTIME("file " << filename() << " does not support partial reading"); | ||
359 | |||
360 |
2/4✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
|
5 | mImpl->mGrids.reset(new GridPtrVec); |
361 | mImpl->mNamedGrids.clear(); | ||
362 | |||
363 | // Stream in the entire contents of the file and append all grids to mGrids. | ||
364 |
2/4✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
|
5 | const int32_t gridCount = readGridCount(inputStream()); |
365 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 5 times.
|
17 | for (int32_t i = 0; i < gridCount; ++i) { |
366 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
24 | GridDescriptor gd; |
367 |
2/4✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
|
12 | gd.read(inputStream()); |
368 | |||
369 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
12 | GridBase::Ptr grid = createGrid(gd); |
370 |
2/4✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
|
24 | Archive::readGrid(grid, gd, inputStream()); |
371 | |||
372 |
2/6✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 12 times.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
24 | gridDescriptors().insert(std::make_pair(gd.gridName(), gd)); |
373 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
12 | mImpl->mGrids->push_back(grid); |
374 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
12 | mImpl->mNamedGrids[gd.uniqueName()] = grid; |
375 | } | ||
376 | // Connect instances (grids that share trees with other grids). | ||
377 |
4/6✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12 times.
✓ Branch 7 taken 5 times.
|
22 | for (NameMapCIter it = gridDescriptors().begin(); it != gridDescriptors().end(); ++it) { |
378 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
12 | Archive::connectInstance(it->second, mImpl->mNamedGrids); |
379 | } | ||
380 | } else { | ||
381 | // Read in just the grid descriptors. | ||
382 |
2/4✓ Branch 1 taken 51 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 51 times.
✗ Branch 5 not taken.
|
51 | readGridDescriptors(inputStream()); |
383 | } | ||
384 | |||
385 |
1/2✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
|
56 | mImpl->mIsOpen = true; |
386 | 56 | return newFile; // true if file is not identical to opened file | |
387 | } | ||
388 | |||
389 | |||
390 | void | ||
391 |
2/2✓ Branch 0 taken 34 times.
✓ Branch 1 taken 11 times.
|
45 | File::close() |
392 | { | ||
393 | // Reset all data. | ||
394 | mImpl->mMeta.reset(); | ||
395 | mImpl->mGridDescriptors.clear(); | ||
396 | mImpl->mGrids.reset(); | ||
397 | mImpl->mNamedGrids.clear(); | ||
398 | mImpl->mInStream.reset(); | ||
399 | mImpl->mStreamBuf.reset(); | ||
400 | mImpl->mStreamMetadata.reset(); | ||
401 | mImpl->mFileMapping.reset(); | ||
402 | |||
403 | 45 | mImpl->mIsOpen = false; | |
404 | setInputHasGridOffsets(true); | ||
405 | 45 | } | |
406 | |||
407 | |||
408 | //////////////////////////////////////// | ||
409 | |||
410 | |||
411 | bool | ||
412 | 19 | File::hasGrid(const Name& name) const | |
413 | { | ||
414 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 18 times.
|
19 | if (!isOpen()) { |
415 |
3/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
|
5 | OPENVDB_THROW(IoError, filename() << " is not open for reading"); |
416 | } | ||
417 | 18 | return (findDescriptor(name) != gridDescriptors().end()); | |
418 | } | ||
419 | |||
420 | |||
421 | MetaMap::Ptr | ||
422 | 16 | File::getMetadata() const | |
423 | { | ||
424 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 15 times.
|
16 | if (!isOpen()) { |
425 |
3/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
|
5 | OPENVDB_THROW(IoError, filename() << " is not open for reading"); |
426 | } | ||
427 | // Return a deep copy of the file-level metadata, which was read | ||
428 | // when the file was opened. | ||
429 |
1/2✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
|
30 | return MetaMap::Ptr(new MetaMap(*mImpl->mMeta)); |
430 | } | ||
431 | |||
432 | |||
433 | GridPtrVecPtr | ||
434 | 35 | File::getGrids() const | |
435 | { | ||
436 |
2/2✓ Branch 1 taken 7 times.
✓ Branch 2 taken 28 times.
|
35 | if (!isOpen()) { |
437 |
3/8✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 7 times.
✗ Branch 8 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
|
35 | OPENVDB_THROW(IoError, filename() << " is not open for reading"); |
438 | } | ||
439 | |||
440 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 25 times.
|
28 | GridPtrVecPtr ret; |
441 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 25 times.
|
28 | if (!inputHasGridOffsets()) { |
442 | // If the input file doesn't have grid offsets, then all of the grids | ||
443 | // have already been streamed in and stored in mGrids. | ||
444 | ret = mImpl->mGrids; | ||
445 | } else { | ||
446 |
2/4✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 25 times.
✗ Branch 5 not taken.
|
25 | ret.reset(new GridPtrVec); |
447 | |||
448 | Archive::NamedGridMap namedGrids; | ||
449 | |||
450 | // Read all grids represented by the GridDescriptors. | ||
451 |
4/6✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 25 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 58 times.
✓ Branch 7 taken 25 times.
|
108 | for (NameMapCIter i = gridDescriptors().begin(), e = gridDescriptors().end(); i != e; ++i) { |
452 | 58 | const GridDescriptor& gd = i->second; | |
453 |
1/2✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
|
58 | GridBase::Ptr grid = readGrid(gd); |
454 |
1/2✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
|
58 | ret->push_back(grid); |
455 |
1/2✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
|
58 | namedGrids[gd.uniqueName()] = grid; |
456 | } | ||
457 | |||
458 | // Connect instances (grids that share trees with other grids). | ||
459 |
4/6✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 25 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 58 times.
✓ Branch 7 taken 25 times.
|
108 | for (NameMapCIter i = gridDescriptors().begin(), e = gridDescriptors().end(); i != e; ++i) { |
460 |
1/2✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
|
58 | Archive::connectInstance(i->second, namedGrids); |
461 | } | ||
462 | } | ||
463 | 28 | return ret; | |
464 | } | ||
465 | |||
466 | |||
467 | GridBase::Ptr | ||
468 |
2/2✓ Branch 0 taken 41 times.
✓ Branch 1 taken 6 times.
|
47 | File::retrieveCachedGrid(const Name& name) const |
469 | { | ||
470 | // If the file has grid offsets, grids are read on demand | ||
471 | // and not cached in mNamedGrids. | ||
472 |
2/2✓ Branch 0 taken 41 times.
✓ Branch 1 taken 6 times.
|
47 | if (inputHasGridOffsets()) return GridBase::Ptr(); |
473 | |||
474 | // If the file does not have grid offsets, mNamedGrids should already | ||
475 | // contain the entire contents of the file. | ||
476 | |||
477 | // Search by unique name. | ||
478 | Archive::NamedGridMap::const_iterator it = | ||
479 |
2/2✓ Branch 2 taken 1 times.
✓ Branch 3 taken 5 times.
|
12 | mImpl->mNamedGrids.find(GridDescriptor::stringAsUniqueName(name)); |
480 | // If not found, search by grid name. | ||
481 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
|
7 | if (it == mImpl->mNamedGrids.end()) it = mImpl->mNamedGrids.find(name); |
482 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
|
6 | if (it == mImpl->mNamedGrids.end()) { |
483 |
3/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
|
5 | OPENVDB_THROW(KeyError, filename() << " has no grid named \"" << name << "\""); |
484 | } | ||
485 | return it->second; | ||
486 | } | ||
487 | |||
488 | |||
489 | //////////////////////////////////////// | ||
490 | |||
491 | |||
492 | GridPtrVecPtr | ||
493 | 4 | File::readAllGridMetadata() | |
494 | { | ||
495 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
|
4 | if (!isOpen()) { |
496 |
3/8✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
|
10 | OPENVDB_THROW(IoError, filename() << " is not open for reading"); |
497 | } | ||
498 | |||
499 | 2 | GridPtrVecPtr ret(new GridPtrVec); | |
500 | |||
501 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | if (!inputHasGridOffsets()) { |
502 | // If the input file doesn't have grid offsets, then all of the grids | ||
503 | // have already been streamed in and stored in mGrids. | ||
504 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | for (size_t i = 0, N = mImpl->mGrids->size(); i < N; ++i) { |
505 | // Return copies of the grids, but with empty trees. | ||
506 |
1/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
4 | ret->push_back((*mImpl->mGrids)[i]->copyGridWithNewTree()); |
507 | } | ||
508 | } else { | ||
509 | // Read just the metadata and transforms for all grids. | ||
510 |
4/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 1 times.
|
4 | for (NameMapCIter i = gridDescriptors().begin(), e = gridDescriptors().end(); i != e; ++i) { |
511 | 2 | const GridDescriptor& gd = i->second; | |
512 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | GridBase::ConstPtr grid = readGridPartial(gd, /*readTopology=*/false); |
513 | // Return copies of the grids, but with empty trees. | ||
514 | // (As of 0.98.0, at least, it would suffice to just const cast | ||
515 | // the grid pointers returned by readGridPartial(), but shallow | ||
516 | // copying the grids helps to ensure future compatibility.) | ||
517 |
2/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
4 | ret->push_back(grid->copyGridWithNewTree()); |
518 | } | ||
519 | } | ||
520 | 2 | return ret; | |
521 | } | ||
522 | |||
523 | |||
524 | GridBase::Ptr | ||
525 | 10 | File::readGridMetadata(const Name& name) | |
526 | { | ||
527 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 6 times.
|
10 | if (!isOpen()) { |
528 |
3/8✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
|
20 | OPENVDB_THROW(IoError, filename() << " is not open for reading."); |
529 | } | ||
530 | |||
531 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | GridBase::ConstPtr ret; |
532 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | if (!inputHasGridOffsets()) { |
533 | // Retrieve the grid from mGrids, which should already contain | ||
534 | // the entire contents of the file. | ||
535 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
|
3 | ret = readGrid(name); |
536 | } else { | ||
537 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | NameMapCIter it = findDescriptor(name); |
538 |
3/4✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 2 times.
|
3 | if (it == gridDescriptors().end()) { |
539 |
3/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
|
5 | OPENVDB_THROW(KeyError, filename() << " has no grid named \"" << name << "\""); |
540 | } | ||
541 | |||
542 | // Seek to and read in the grid from the file. | ||
543 | 2 | const GridDescriptor& gd = it->second; | |
544 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | ret = readGridPartial(gd, /*readTopology=*/false); |
545 | } | ||
546 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
8 | return ret->copyGridWithNewTree(); |
547 | } | ||
548 | |||
549 | |||
550 | //////////////////////////////////////// | ||
551 | |||
552 | |||
553 | GridBase::Ptr | ||
554 | 40 | File::readGrid(const Name& name) | |
555 | { | ||
556 | 40 | return readGridByName(name, BBoxd()); | |
557 | } | ||
558 | |||
559 | |||
560 | GridBase::Ptr | ||
561 | 7 | File::readGrid(const Name& name, const BBoxd& bbox) | |
562 | { | ||
563 | 7 | return readGridByName(name, bbox); | |
564 | } | ||
565 | |||
566 | |||
567 | GridBase::Ptr | ||
568 | 47 | File::readGridByName(const Name& name, const BBoxd& bbox) | |
569 | { | ||
570 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 47 times.
|
47 | if (!isOpen()) { |
571 | ✗ | OPENVDB_THROW(IoError, filename() << " is not open for reading."); | |
572 | } | ||
573 | |||
574 | const bool clip = bbox.isSorted(); | ||
575 | |||
576 | // If a grid with the given name was already read and cached | ||
577 | // (along with the entire contents of the file, because the file | ||
578 | // doesn't support random access), retrieve and return it. | ||
579 | 47 | GridBase::Ptr grid = retrieveCachedGrid(name); | |
580 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 41 times.
|
46 | if (grid) { |
581 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
|
5 | if (clip) { |
582 |
2/4✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
6 | grid = grid->deepCopyGrid(); |
583 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | grid->clipGrid(bbox); |
584 | } | ||
585 | return grid; | ||
586 | } | ||
587 | |||
588 |
1/2✓ Branch 1 taken 41 times.
✗ Branch 2 not taken.
|
41 | NameMapCIter it = findDescriptor(name); |
589 |
3/4✓ Branch 1 taken 41 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 40 times.
|
41 | if (it == gridDescriptors().end()) { |
590 |
3/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
|
5 | OPENVDB_THROW(KeyError, filename() << " has no grid named \"" << name << "\""); |
591 | } | ||
592 | |||
593 | // Seek to and read in the grid from the file. | ||
594 | 40 | const GridDescriptor& gd = it->second; | |
595 |
6/8✓ Branch 0 taken 4 times.
✓ Branch 1 taken 36 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 36 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 8 times.
✓ Branch 9 taken 32 times.
|
80 | grid = (clip ? readGrid(gd, bbox) : readGrid(gd)); |
596 | |||
597 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 32 times.
|
40 | if (gd.isInstance()) { |
598 | /// @todo Refactor to share code with Archive::connectInstance()? | ||
599 | NameMapCIter parentIt = | ||
600 |
3/6✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
|
9 | findDescriptor(GridDescriptor::nameAsString(gd.instanceParentName())); |
601 |
2/4✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
|
8 | if (parentIt == gridDescriptors().end()) { |
602 | ✗ | OPENVDB_THROW(KeyError, "missing instance parent \"" | |
603 | << GridDescriptor::nameAsString(gd.instanceParentName()) | ||
604 | << "\" for grid " << GridDescriptor::nameAsString(gd.uniqueName()) | ||
605 | << " in file " << filename()); | ||
606 | } | ||
607 | |||
608 | 8 | GridBase::Ptr parent; | |
609 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (clip) { |
610 | ✗ | const CoordBBox indexBBox = grid->constTransform().worldToIndexNodeCentered(bbox); | |
611 | ✗ | parent = readGrid(parentIt->second, indexBBox); | |
612 | } else { | ||
613 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | parent = readGrid(parentIt->second); |
614 | } | ||
615 |
3/8✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
16 | if (parent) grid->setTree(parent->baseTreePtr()); |
616 | } | ||
617 | return grid; | ||
618 | } | ||
619 | |||
620 | |||
621 | //////////////////////////////////////// | ||
622 | |||
623 | |||
624 | void | ||
625 | 60 | File::writeGrids(const GridCPtrVec& grids, const MetaMap& meta) const | |
626 | { | ||
627 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 59 times.
|
60 | if (isOpen()) { |
628 |
3/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
|
5 | OPENVDB_THROW(IoError, |
629 | filename() << " cannot be written because it is open for reading"); | ||
630 | } | ||
631 | |||
632 | // Create a file stream and write it out. | ||
633 | 118 | std::ofstream file; | |
634 |
2/4✓ Branch 1 taken 59 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 59 times.
✗ Branch 5 not taken.
|
59 | file.open(filename().c_str(), |
635 | std::ios_base::out | std::ios_base::binary | std::ios_base::trunc); | ||
636 | |||
637 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
|
59 | if (file.fail()) { |
638 | ✗ | OPENVDB_THROW(IoError, "could not open " << filename() << " for writing"); | |
639 | } | ||
640 | |||
641 | // Write out the vdb. | ||
642 |
1/2✓ Branch 1 taken 59 times.
✗ Branch 2 not taken.
|
59 | Archive::write(file, grids, /*seekable=*/true, meta); |
643 | |||
644 |
1/2✓ Branch 1 taken 59 times.
✗ Branch 2 not taken.
|
59 | file.close(); |
645 | 59 | } | |
646 | |||
647 | |||
648 | //////////////////////////////////////// | ||
649 | |||
650 | |||
651 | void | ||
652 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
|
53 | File::readGridDescriptors(std::istream& is) |
653 | { | ||
654 | // This method should not be called for files that don't contain grid offsets. | ||
655 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
|
53 | assert(inputHasGridOffsets()); |
656 | |||
657 | 53 | gridDescriptors().clear(); | |
658 | |||
659 |
2/2✓ Branch 1 taken 102 times.
✓ Branch 2 taken 53 times.
|
155 | for (int32_t i = 0, N = readGridCount(is); i < N; ++i) { |
660 | // Read the grid descriptor. | ||
661 | 204 | GridDescriptor gd; | |
662 |
1/2✓ Branch 1 taken 102 times.
✗ Branch 2 not taken.
|
102 | gd.read(is); |
663 | |||
664 | // Add the descriptor to the dictionary. | ||
665 |
1/2✓ Branch 1 taken 102 times.
✗ Branch 2 not taken.
|
204 | gridDescriptors().insert(std::make_pair(gd.gridName(), gd)); |
666 | |||
667 | // Skip forward to the next descriptor. | ||
668 |
1/2✓ Branch 1 taken 102 times.
✗ Branch 2 not taken.
|
102 | gd.seekToEnd(is); |
669 | } | ||
670 | 53 | } | |
671 | |||
672 | |||
673 | //////////////////////////////////////// | ||
674 | |||
675 | |||
676 | File::NameMapCIter | ||
677 | 76 | File::findDescriptor(const Name& name) const | |
678 | { | ||
679 | 76 | const Name uniqueName = GridDescriptor::stringAsUniqueName(name); | |
680 | |||
681 | // Find all descriptors with the given grid name. | ||
682 |
3/4✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 30 times.
✓ Branch 4 taken 46 times.
|
152 | std::pair<NameMapCIter, NameMapCIter> range = gridDescriptors().equal_range(name); |
683 | |||
684 |
2/2✓ Branch 0 taken 30 times.
✓ Branch 1 taken 46 times.
|
76 | if (range.first == range.second) { |
685 | // If no descriptors were found with the given grid name, the name might have | ||
686 | // a suffix ("name[N]"). In that case, remove the "[N]" suffix and search again. | ||
687 |
2/4✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
|
60 | range = gridDescriptors().equal_range(GridDescriptor::stripSuffix(uniqueName)); |
688 | } | ||
689 | |||
690 | 76 | const size_t count = size_t(std::distance(range.first, range.second)); | |
691 |
4/4✓ Branch 0 taken 31 times.
✓ Branch 1 taken 45 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 27 times.
|
76 | if (count > 1 && name == uniqueName) { |
692 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | OPENVDB_LOG_WARN(filename() << " has more than one grid named \"" << name << "\""); |
693 | } | ||
694 | |||
695 |
1/2✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
|
76 | NameMapCIter ret = gridDescriptors().end(); |
696 | |||
697 |
2/2✓ Branch 0 taken 73 times.
✓ Branch 1 taken 3 times.
|
76 | if (count > 0) { |
698 |
2/2✓ Branch 0 taken 43 times.
✓ Branch 1 taken 30 times.
|
73 | if (name == uniqueName) { |
699 | // If the given grid name is unique or if no "[N]" index was given, | ||
700 | // use the first matching descriptor. | ||
701 | 43 | ret = range.first; | |
702 | } else { | ||
703 | // If the given grid name has a "[N]" index, find the descriptor | ||
704 | // with a matching unique name. | ||
705 |
2/2✓ Branch 0 taken 52 times.
✓ Branch 1 taken 1 times.
|
53 | for (NameMapCIter it = range.first; it != range.second; ++it) { |
706 |
1/2✓ Branch 1 taken 52 times.
✗ Branch 2 not taken.
|
52 | const Name candidateName = it->second.uniqueName(); |
707 |
4/4✓ Branch 0 taken 26 times.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 3 times.
|
52 | if (candidateName == uniqueName || candidateName == name) { |
708 | 29 | ret = it; | |
709 | break; | ||
710 | } | ||
711 | } | ||
712 | } | ||
713 | } | ||
714 | 76 | return ret; | |
715 | } | ||
716 | |||
717 | |||
718 | //////////////////////////////////////// | ||
719 | |||
720 | |||
721 | GridBase::Ptr | ||
722 | 122 | File::createGrid(const GridDescriptor& gd) const | |
723 | { | ||
724 | // Create the grid. | ||
725 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 122 times.
|
122 | if (!GridBase::isRegistered(gd.gridType())) { |
726 | ✗ | OPENVDB_THROW(KeyError, "Cannot read grid " | |
727 | << GridDescriptor::nameAsString(gd.uniqueName()) | ||
728 | << " from " << filename() << ": grid type " | ||
729 | << gd.gridType() << " is not registered"); | ||
730 | } | ||
731 | |||
732 | 122 | GridBase::Ptr grid = GridBase::createGrid(gd.gridType()); | |
733 |
2/4✓ Branch 0 taken 122 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 122 times.
✗ Branch 4 not taken.
|
122 | if (grid) grid->setSaveFloatAsHalf(gd.saveFloatAsHalf()); |
734 | |||
735 | 122 | return grid; | |
736 | } | ||
737 | |||
738 | |||
739 | GridBase::ConstPtr | ||
740 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | File::readGridPartial(const GridDescriptor& gd, bool readTopology) const |
741 | { | ||
742 | // This method should not be called for files that don't contain grid offsets. | ||
743 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | assert(inputHasGridOffsets()); |
744 | |||
745 | 4 | GridBase::Ptr grid = createGrid(gd); | |
746 | |||
747 | // Seek to grid. | ||
748 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | gd.seekToGrid(inputStream()); |
749 | |||
750 | // Read the grid partially. | ||
751 |
2/6✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
|
12 | readGridPartial(grid, inputStream(), gd.isInstance(), readTopology); |
752 | |||
753 | // Promote to a const grid. | ||
754 | GridBase::ConstPtr constGrid = grid; | ||
755 | |||
756 | 4 | return constGrid; | |
757 | } | ||
758 | |||
759 | |||
760 | GridBase::Ptr | ||
761 | 102 | File::readGrid(const GridDescriptor& gd) const | |
762 | { | ||
763 | 102 | return Impl::readGrid(*this, gd, Impl::NoBBox()); | |
764 | } | ||
765 | |||
766 | |||
767 | GridBase::Ptr | ||
768 | 4 | File::readGrid(const GridDescriptor& gd, const BBoxd& bbox) const | |
769 | { | ||
770 | 4 | return Impl::readGrid(*this, gd, bbox); | |
771 | } | ||
772 | |||
773 | |||
774 | GridBase::Ptr | ||
775 | ✗ | File::readGrid(const GridDescriptor& gd, const CoordBBox& bbox) const | |
776 | { | ||
777 | ✗ | return Impl::readGrid(*this, gd, bbox); | |
778 | } | ||
779 | |||
780 | |||
781 | void | ||
782 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | File::readGridPartial(GridBase::Ptr grid, std::istream& is, |
783 | bool isInstance, bool readTopology) const | ||
784 | { | ||
785 | // This method should not be called for files that don't contain grid offsets. | ||
786 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | assert(inputHasGridOffsets()); |
787 | |||
788 | // This code needs to stay in sync with io::Archive::readGrid(), in terms of | ||
789 | // the order of operations. | ||
790 | 4 | readGridCompression(is); | |
791 | 4 | grid->readMeta(is); | |
792 | |||
793 | // drop DelayedLoadMetadata from the grid as it is only useful for IO | ||
794 |
1/2✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
|
8 | if ((*grid)[GridBase::META_FILE_DELAYED_LOAD]) { |
795 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
8 | grid->removeMeta(GridBase::META_FILE_DELAYED_LOAD); |
796 | } | ||
797 | |||
798 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | if (getFormatVersion(is) >= OPENVDB_FILE_VERSION_GRID_INSTANCING) { |
799 | grid->readTransform(is); | ||
800 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (!isInstance && readTopology) { |
801 | ✗ | grid->readTopology(is); | |
802 | } | ||
803 | } else { | ||
804 | ✗ | if (readTopology) { | |
805 | ✗ | grid->readTopology(is); | |
806 | grid->readTransform(is); | ||
807 | } | ||
808 | } | ||
809 | 4 | } | |
810 | |||
811 | |||
812 | //////////////////////////////////////// | ||
813 | |||
814 | |||
815 | File::NameIterator | ||
816 | 4 | File::beginName() const | |
817 | { | ||
818 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
|
4 | if (!isOpen()) { |
819 |
3/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
|
5 | OPENVDB_THROW(IoError, filename() << " is not open for reading"); |
820 | } | ||
821 | 3 | return File::NameIterator(gridDescriptors().begin()); | |
822 | } | ||
823 | |||
824 | |||
825 | File::NameIterator | ||
826 | 9 | File::endName() const | |
827 | { | ||
828 | 9 | return File::NameIterator(gridDescriptors().end()); | |
829 | } | ||
830 | |||
831 | } // namespace io | ||
832 | } // namespace OPENVDB_VERSION_NAME | ||
833 | } // namespace openvdb | ||
834 |