Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright Contributors to the OpenVDB Project | ||
2 | // SPDX-License-Identifier: MPL-2.0 | ||
3 | |||
4 | #include "GridDescriptor.h" | ||
5 | |||
6 | #include <openvdb/Exceptions.h> | ||
7 | #include <boost/algorithm/string/predicate.hpp> // for boost::ends_with() | ||
8 | #include <boost/algorithm/string/erase.hpp> // for boost::erase_last() | ||
9 | #include <sstream> | ||
10 | |||
11 | |||
12 | namespace openvdb { | ||
13 | OPENVDB_USE_VERSION_NAMESPACE | ||
14 | namespace OPENVDB_VERSION_NAME { | ||
15 | namespace io { | ||
16 | |||
17 | namespace { | ||
18 | |||
19 | // In order not to break backward compatibility with existing VDB files, | ||
20 | // grids stored using 16-bit half floats are flagged by adding the following | ||
21 | // suffix to the grid's type name on output. The suffix is removed on input | ||
22 | // and the grid's "save float as half" flag set accordingly. | ||
23 | const char* HALF_FLOAT_TYPENAME_SUFFIX = "_HalfFloat"; | ||
24 | |||
25 | const char* SEP = "\x1e"; // ASCII "record separator" | ||
26 | |||
27 | } | ||
28 | |||
29 | |||
30 | 265 | GridDescriptor::GridDescriptor(): | |
31 | mSaveFloatAsHalf(false), | ||
32 | mGridPos(0), | ||
33 | mBlockPos(0), | ||
34 | 265 | mEndPos(0) | |
35 | { | ||
36 | 265 | } | |
37 | |||
38 | 168 | GridDescriptor::GridDescriptor(const Name &name, const Name &type, bool half): | |
39 | mGridName(stripSuffix(name)), | ||
40 | mUniqueName(name), | ||
41 | mGridType(type), | ||
42 | mSaveFloatAsHalf(half), | ||
43 | mGridPos(0), | ||
44 | mBlockPos(0), | ||
45 |
2/4✓ Branch 2 taken 168 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 168 times.
✗ Branch 6 not taken.
|
168 | mEndPos(0) |
46 | { | ||
47 | 168 | } | |
48 | |||
49 | 664 | GridDescriptor::~GridDescriptor() | |
50 | { | ||
51 | 664 | } | |
52 | |||
53 | void | ||
54 | 164 | GridDescriptor::writeHeader(std::ostream &os) const | |
55 | { | ||
56 | 164 | writeString(os, mUniqueName); | |
57 | |||
58 | 164 | Name gridType = mGridType; | |
59 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 163 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
164 | if (mSaveFloatAsHalf) gridType += HALF_FLOAT_TYPENAME_SUFFIX; |
60 |
1/2✓ Branch 1 taken 164 times.
✗ Branch 2 not taken.
|
164 | writeString(os, gridType); |
61 | |||
62 |
1/2✓ Branch 1 taken 164 times.
✗ Branch 2 not taken.
|
164 | writeString(os, mInstanceParentName); |
63 | 164 | } | |
64 | |||
65 | void | ||
66 | 312 | GridDescriptor::writeStreamPos(std::ostream &os) const | |
67 | { | ||
68 | 312 | os.write(reinterpret_cast<const char*>(&mGridPos), sizeof(int64_t)); | |
69 | 312 | os.write(reinterpret_cast<const char*>(&mBlockPos), sizeof(int64_t)); | |
70 | 312 | os.write(reinterpret_cast<const char*>(&mEndPos), sizeof(int64_t)); | |
71 | 312 | } | |
72 | |||
73 | GridBase::Ptr | ||
74 | 127 | GridDescriptor::read(std::istream &is) | |
75 | { | ||
76 | // Read in the name. | ||
77 | 127 | mUniqueName = readString(is); | |
78 | 127 | mGridName = stripSuffix(mUniqueName); | |
79 | |||
80 | // Read in the grid type. | ||
81 | 254 | mGridType = readString(is); | |
82 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 126 times.
|
127 | if (boost::ends_with(mGridType, HALF_FLOAT_TYPENAME_SUFFIX)) { |
83 | 1 | mSaveFloatAsHalf = true; | |
84 | 1 | boost::erase_last(mGridType, HALF_FLOAT_TYPENAME_SUFFIX); | |
85 | } | ||
86 | |||
87 |
1/2✓ Branch 1 taken 127 times.
✗ Branch 2 not taken.
|
127 | if (getFormatVersion(is) >= OPENVDB_FILE_VERSION_GRID_INSTANCING) { |
88 | 254 | mInstanceParentName = readString(is); | |
89 | } | ||
90 | |||
91 | // Create the grid of the type if it has been registered. | ||
92 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 125 times.
|
127 | if (!GridBase::isRegistered(mGridType)) { |
93 |
2/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
10 | OPENVDB_THROW(LookupError, "Cannot read grid." << |
94 | " Grid type " << mGridType << " is not registered."); | ||
95 | } | ||
96 | // else | ||
97 | 125 | GridBase::Ptr grid = GridBase::createGrid(mGridType); | |
98 |
2/4✓ Branch 0 taken 125 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 125 times.
✗ Branch 4 not taken.
|
125 | if (grid) grid->setSaveFloatAsHalf(mSaveFloatAsHalf); |
99 | |||
100 | // Read in the offsets. | ||
101 |
1/2✓ Branch 1 taken 125 times.
✗ Branch 2 not taken.
|
125 | is.read(reinterpret_cast<char*>(&mGridPos), sizeof(int64_t)); |
102 |
1/2✓ Branch 1 taken 125 times.
✗ Branch 2 not taken.
|
125 | is.read(reinterpret_cast<char*>(&mBlockPos), sizeof(int64_t)); |
103 |
1/2✓ Branch 1 taken 125 times.
✗ Branch 2 not taken.
|
125 | is.read(reinterpret_cast<char*>(&mEndPos), sizeof(int64_t)); |
104 | |||
105 | 125 | return grid; | |
106 | } | ||
107 | |||
108 | void | ||
109 | 122 | GridDescriptor::seekToGrid(std::istream &is) const | |
110 | { | ||
111 | 122 | is.seekg(mGridPos, std::ios_base::beg); | |
112 | 122 | } | |
113 | |||
114 | void | ||
115 | 3 | GridDescriptor::seekToBlocks(std::istream &is) const | |
116 | { | ||
117 | 3 | is.seekg(mBlockPos, std::ios_base::beg); | |
118 | 3 | } | |
119 | |||
120 | void | ||
121 | 103 | GridDescriptor::seekToEnd(std::istream &is) const | |
122 | { | ||
123 | 103 | is.seekg(mEndPos, std::ios_base::beg); | |
124 | 103 | } | |
125 | |||
126 | |||
127 | void | ||
128 | ✗ | GridDescriptor::seekToGrid(std::ostream &os) const | |
129 | { | ||
130 | ✗ | os.seekp(mGridPos, std::ios_base::beg); | |
131 | } | ||
132 | |||
133 | void | ||
134 | ✗ | GridDescriptor::seekToBlocks(std::ostream &os) const | |
135 | { | ||
136 | ✗ | os.seekp(mBlockPos, std::ios_base::beg); | |
137 | } | ||
138 | |||
139 | void | ||
140 | 148 | GridDescriptor::seekToEnd(std::ostream &os) const | |
141 | { | ||
142 | 148 | os.seekp(mEndPos, std::ios_base::beg); | |
143 | 148 | } | |
144 | |||
145 | |||
146 | //////////////////////////////////////// | ||
147 | |||
148 | |||
149 | // static | ||
150 | Name | ||
151 | 198 | GridDescriptor::addSuffix(const Name& name, int n) | |
152 | { | ||
153 | 396 | std::ostringstream ostr; | |
154 |
2/4✓ Branch 1 taken 198 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 198 times.
✗ Branch 5 not taken.
|
198 | ostr << name << SEP << n; |
155 | 198 | return ostr.str(); | |
156 | } | ||
157 | |||
158 | |||
159 | // static | ||
160 | Name | ||
161 | 329 | GridDescriptor::stripSuffix(const Name& name) | |
162 | { | ||
163 | 329 | return name.substr(0, name.find(SEP)); | |
164 | } | ||
165 | |||
166 | |||
167 | // static | ||
168 | std::string | ||
169 | 41 | GridDescriptor::nameAsString(const Name& name) | |
170 | { | ||
171 | 41 | std::string::size_type pos = name.find(SEP); | |
172 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 28 times.
|
41 | if (pos == std::string::npos) return name; |
173 | |||
174 |
4/8✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 28 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
|
56 | return name.substr(0, pos) + "[" + name.substr(pos + 1) + "]"; |
175 | } | ||
176 | |||
177 | |||
178 | //static | ||
179 | Name | ||
180 | 82 | GridDescriptor::stringAsUniqueName(const std::string& s) | |
181 | { | ||
182 | 82 | Name ret = s; | |
183 |
4/6✓ Branch 0 taken 82 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 82 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 30 times.
✓ Branch 6 taken 52 times.
|
82 | if (!ret.empty() && *ret.rbegin() == ']') { // found trailing ']' |
184 | std::string::size_type pos = ret.find("["); | ||
185 | // Replace "[N]" with SEP "N". | ||
186 |
1/2✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
|
30 | if (pos != std::string::npos) { |
187 |
1/2✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
|
30 | ret.resize(ret.size() - 1); // drop trailing ']' |
188 |
1/2✓ Branch 2 taken 30 times.
✗ Branch 3 not taken.
|
30 | ret.replace(ret.find("["), 1, SEP); |
189 | } | ||
190 | } | ||
191 | 82 | return ret; | |
192 | } | ||
193 | |||
194 | } // namespace io | ||
195 | } // namespace OPENVDB_VERSION_NAME | ||
196 | } // namespace openvdb | ||
197 |