| 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 |