1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 
4 #ifndef OPENVDB_IO_ARCHIVE_HAS_BEEN_INCLUDED
5 #define OPENVDB_IO_ARCHIVE_HAS_BEEN_INCLUDED
6 
7 #include <openvdb/version.h>
8 #include "Compression.h" // for COMPRESS_ZIP, etc.
9 #include <openvdb/Grid.h>
10 #include <openvdb/MetaMap.h>
11 #include <openvdb/Platform.h>
12 #include <openvdb/version.h> // for VersionId
13 #include <boost/uuid/uuid.hpp>
14 #include <cstdint>
15 #include <iosfwd>
16 #include <map>
17 #include <memory>
18 #include <string>
19 
20 
21 class TestFile;
22 
23 namespace openvdb {
24 OPENVDB_USE_VERSION_NAMESPACE
25 namespace OPENVDB_VERSION_NAME {
26 namespace io {
27 
28 class GridDescriptor;
29 
30 
31 /// Grid serializer/unserializer
32 class OPENVDB_API Archive
33 {
34 public:
35     using Ptr = SharedPtr<Archive>;
36     using ConstPtr = SharedPtr<const Archive>;
37 
38     static const uint32_t DEFAULT_COMPRESSION_FLAGS;
39 
40     Archive();
41     Archive(const Archive&) = default;
42     Archive& operator=(const Archive&) = default;
43     virtual ~Archive();
44 
45     /// @brief Return a copy of this archive.
46     virtual Ptr copy() const;
47 
48     /// @brief Return the UUID that was most recently written (or read,
49     /// if no UUID has been written yet).
50     std::string getUniqueTag() const;
51     /// @brief Return @c true if the given UUID matches this archive's UUID.
52     bool isIdentical(const std::string& uuidStr) const;
53 
54     /// @brief Return the file format version number of the input stream.
fileVersion()55     uint32_t fileVersion() const { return mFileVersion; }
56     /// @brief Return the (major, minor) version number of the library that was
57     /// used to write the input stream.
libraryVersion()58     VersionId libraryVersion() const { return mLibraryVersion; }
59     /// @brief Return a string of the form "<major>.<minor>/<format>", giving the
60     /// library and file format version numbers associated with the input stream.
61     std::string version() const;
62 
63     /// @brief Return @c true if trees shared by multiple grids are written out
64     /// only once, @c false if they are written out once per grid.
isInstancingEnabled()65     bool isInstancingEnabled() const { return mEnableInstancing; }
66     /// @brief Specify whether trees shared by multiple grids should be
67     /// written out only once (@c true) or once per grid (@c false).
68     /// @note Instancing is enabled by default.
setInstancingEnabled(bool b)69     void setInstancingEnabled(bool b) { mEnableInstancing = b; }
70 
71     /// Return @c true if the OpenVDB library includes support for the Blosc compressor.
72     static bool hasBloscCompression();
73 
74     /// Return @c true if the OpenVDB library includes support for the ZLib compressor.
75     static bool hasZLibCompression();
76 
77     /// Return a bit mask specifying compression options for the data stream.
compression()78     uint32_t compression() const { return mCompression; }
79     /// @brief Specify whether and how the data stream should be compressed.
80     /// @param c bitwise OR (e.g., COMPRESS_ZIP | COMPRESS_ACTIVE_MASK) of
81     ///     compression option flags (see Compression.h for the available flags)
82     /// @note Not all combinations of compression options are supported.
setCompression(uint32_t c)83     void setCompression(uint32_t c) { mCompression = c; }
84 
85     /// @brief Return @c true if grid statistics (active voxel count and
86     /// bounding box, etc.) are computed and written as grid metadata.
isGridStatsMetadataEnabled()87     bool isGridStatsMetadataEnabled() const { return mEnableGridStats; }
88     /// @brief Specify whether grid statistics (active voxel count and
89     /// bounding box, etc.) should be computed and written as grid metadata.
setGridStatsMetadataEnabled(bool b)90     void setGridStatsMetadataEnabled(bool b) { mEnableGridStats = b; }
91 
92     /// @brief Write the grids in the given container to this archive's output stream.
93     virtual void write(const GridCPtrVec&, const MetaMap& = MetaMap()) const {}
94 
95     /// @brief Return @c true if delayed loading is enabled.
96     /// @details If enabled, delayed loading can be disabled for individual files,
97     /// but not vice-versa.
98     /// @note Define the environment variable @c OPENVDB_DISABLE_DELAYED_LOAD
99     /// to disable delayed loading unconditionally.
100     static bool isDelayedLoadingEnabled();
101 
102 protected:
103     /// @brief Return @c true if the input stream contains grid offsets
104     /// that allow for random access or partial reading.
inputHasGridOffsets()105     bool inputHasGridOffsets() const { return mInputHasGridOffsets; }
setInputHasGridOffsets(bool b)106     void setInputHasGridOffsets(bool b) { mInputHasGridOffsets = b; }
107 
108     /// @brief Tag the given input stream with the input file format version number.
109     ///
110     /// The tag can be retrieved with getFormatVersion().
111     /// @sa getFormatVersion()
112     void setFormatVersion(std::istream&);
113 
114     /// @brief Tag the given input stream with the version number of
115     /// the library with which the input stream was created.
116     ///
117     /// The tag can be retrieved with getLibraryVersion().
118     /// @sa getLibraryVersion()
119     void setLibraryVersion(std::istream&);
120 
121     /// @brief Tag the given input stream with flags indicating whether
122     /// the input stream contains compressed data and how it is compressed.
123     void setDataCompression(std::istream&);
124 
125     /// @brief Tag an output stream with flags specifying only those
126     /// compression options that are applicable to the given grid.
127     void setGridCompression(std::ostream&, const GridBase&) const;
128     /// @brief Read in the compression flags for a grid and
129     /// tag the given input stream with those flags.
130     static void readGridCompression(std::istream&);
131 
132     /// Read in and return the number of grids on the input stream.
133     static int32_t readGridCount(std::istream&);
134 
135     /// Populate the given grid from the input stream.
136     static void readGrid(GridBase::Ptr, const GridDescriptor&, std::istream&);
137     /// @brief Populate the given grid from the input stream, but only where it
138     /// intersects the given world-space bounding box.
139     static void readGrid(GridBase::Ptr, const GridDescriptor&, std::istream&, const BBoxd&);
140     /// @brief Populate the given grid from the input stream, but only where it
141     /// intersects the given index-space bounding box.
142     static void readGrid(GridBase::Ptr, const GridDescriptor&, std::istream&, const CoordBBox&);
143 
144     using NamedGridMap = std::map<Name /*uniqueName*/, GridBase::Ptr>;
145 
146     /// @brief If the grid represented by the given grid descriptor
147     /// is an instance, connect it with its instance parent.
148     void connectInstance(const GridDescriptor&, const NamedGridMap&) const;
149 
150     /// Write the given grid descriptor and grid to an output stream
151     /// and update the GridDescriptor offsets.
152     /// @param seekable  if true, the output stream supports seek operations
153     void writeGrid(GridDescriptor&, GridBase::ConstPtr, std::ostream&, bool seekable) const;
154     /// Write the given grid descriptor and grid metadata to an output stream
155     /// and update the GridDescriptor offsets, but don't write the grid's tree,
156     /// since it is shared with another grid.
157     /// @param seekable  if true, the output stream supports seek operations
158     void writeGridInstance(GridDescriptor&, GridBase::ConstPtr,
159         std::ostream&, bool seekable) const;
160 
161     /// @brief Read the magic number, version numbers, UUID, etc. from the given input stream.
162     /// @return @c true if the input UUID differs from the previously-read UUID.
163     bool readHeader(std::istream&);
164     /// @brief Write the magic number, version numbers, UUID, etc. to the given output stream.
165     /// @param seekable  if true, the output stream supports seek operations
166     /// @todo This method should not be const since it actually redefines the UUID!
167     void writeHeader(std::ostream&, bool seekable) const;
168 
169     //@{
170     /// Write the given grids to an output stream.
171     void write(std::ostream&, const GridPtrVec&, bool seekable, const MetaMap& = MetaMap()) const;
172     void write(std::ostream&, const GridCPtrVec&, bool seekable, const MetaMap& = MetaMap()) const;
173     //@}
174 
175 private:
176     friend class ::TestFile;
177 
178     /// The version of the file that was read
179     uint32_t mFileVersion;
180     /// The version of the library that was used to create the file that was read
181     VersionId mLibraryVersion;
182     /// 16-byte (128-bit) UUID
183     mutable boost::uuids::uuid mUuid;// needs to be mutable since writeHeader is const!
184     /// Flag indicating whether the input stream contains grid offsets
185     /// and therefore supports partial reading
186     bool mInputHasGridOffsets;
187     /// Flag indicating whether a tree shared by multiple grids should be
188     /// written out only once (true) or once per grid (false)
189     bool mEnableInstancing;
190     /// Flags indicating whether and how the data stream is compressed
191     uint32_t mCompression;
192     /// Flag indicating whether grid statistics metadata should be written
193     bool mEnableGridStats;
194 }; // class Archive
195 
196 } // namespace io
197 } // namespace OPENVDB_VERSION_NAME
198 } // namespace openvdb
199 
200 #endif // OPENVDB_IO_ARCHIVE_HAS_BEEN_INCLUDED
201