OpenVDB 13.1.0
Loading...
Searching...
No Matches
GridValidator.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: Apache-2.0
3
4/*!
5 \file nanovdb/tools/GridValidator.h
6
7 \author Ken Museth
8
9 \date August 30, 2020
10
11 \brief Checks the validity of an existing NanoVDB grid.
12
13 \note before v32.6.0: checksum[0] = Grid+Tree+Root, checksum[1] = nodes
14 after v32.6.0: checksum[0] = Grid+Tree, checksum[1] = nodes + blind data in 4K blocks
15
16 When serialized:
17 [Grid,Tree][Root][ROOT TILES...][Node<5>...][Node<4>...][Leaf<3>...][BlindMeta...][BlindData...]
18*/
19
20#ifndef NANOVDB_TOOLS_GRID_VALIDATOR_H_HAS_BEEN_INCLUDED
21#define NANOVDB_TOOLS_GRID_VALIDATOR_H_HAS_BEEN_INCLUDED
22
23#include <iostream> // for std::cerr
24
25#include <nanovdb/NanoVDB.h>
27
28namespace nanovdb {
29
30namespace tools {
31
32/// @brief Performs several validation tests on a grid pointer.
33/// @tparam ValueT Build type of the input grid
34/// @param grid const point to the grid that needs validation
35/// @param mode Mode of the validation check (defined in GridChecksum.h)
36/// @param verbose If true information about the first failed test is printed to std::cerr
37/// @return Return true if the specified grid passes several validation tests.
38template <typename ValueT>
39bool isValid(const NanoGrid<ValueT> *grid, CheckMode mode, bool verbose = false);
40
41/// @brief Return true if the specified grid passes several validation tests.
42/// @tparam ValueT Build type of the input grid
43/// @param grid Grid to validate
44/// @param detailed If true the validation test is detailed and relatively slow.
45/// @param verbose If true information about the first failed test is printed to std::cerr
46/// @note This method has been deprecated by the one defined above
47template <typename ValueT>
48[[deprecated("Use isValue(const NanoGrid<ValueT>*, CheckMode, bool) instead.")]]
49bool isValid(const NanoGrid<ValueT> &grid, bool detailed = true, bool verbose = false)
50{
51 return isValid(&grid, detailed ? CheckMode::Full : CheckMode::Half, verbose);
52}
53
54//================================================================================================
55
56/// @brief validate grid
57template<typename ValueT>
58__hostdev__ char* checkGrid(const NanoGrid<ValueT> *grid, char *error, CheckMode mode = CheckMode::Full)
59{
60 *error = '\0';// reset error string
61 char str[32];// temporary buffer for toStr
62
63 // check Grid
64 if (grid == nullptr) {
65 return util::sprint(error, "Invalid pointer: Grid is NULL");
66 } else if (!isAligned(grid)) {
67 return util::sprint(error, "Invalid pointer: Grid is misaligned");
68 } else if (grid->mMagic != NANOVDB_MAGIC_NUMB && grid->mMagic != NANOVDB_MAGIC_GRID) {
69 return util::sprint(error, "Invalid magic number: ", toStr(str, toMagic(grid->mMagic)));
70 } else if (!grid->mVersion.isCompatible()) {
71 return util::sprint(error, "Incompatible version number: ", toStr(str, grid->mVersion));
72 } else if (grid->mGridCount == 0) {
73 return util::sprint(error, "Zero grid count");
74 } else if (grid->mGridIndex >= grid->mGridCount) {
75 return util::sprint(error, "grid index(", int(grid->mGridIndex), ") >= grid count(", int(grid->mGridCount), ")");
76 } else if (grid->mGridClass >= GridClass::End) {
77 return util::sprint(error, "Invalid GridClass(", toStr(str, grid->mGridClass), ")");
78 } else if (grid->mGridType >= GridType::End) {
79 return util::sprint(error, "Invalid GridType(", toStr(str, grid->mGridType), ")");
80 } else if (grid->mGridType != toGridType<ValueT>()) {
81 return util::sprint(error, "Invalid combination of BuildType(", toStr(str, toGridType<ValueT>()), ") and GridType(", toStr(str+16, grid->mGridType), ")");
82 } else if (!isValid(grid->mGridType, grid->mGridClass)) {
83 return util::sprint(error, "Invalid combination of GridType(", toStr(str, grid->mGridType), ") and GridClass(", toStr(str+16,grid->mGridClass), ")");
84 }
85
86 // check Tree
87 auto &tree = grid->tree();
88 if (auto *p = tree.getRoot()) {
89 if (!isAligned(p)) return util::strcpy(error, "Invalid pointer: Root is misaligned");
90 } else {
91 return util::strcpy(error, "Invalid pointer: Root is NULL");
92 }
93
94 // check Root
95 auto &root = tree.root();
96 auto *rootData = root.data();
97 if (rootData == nullptr) {
98 return util::strcpy(error, "Invalid pointer: Root is NULL");
99 } else if (!isAligned((const void*)rootData)) {
100 return util::strcpy(error, "Invalid pointer: Root is misaligned");
101 } else if ( (const uint8_t*)(rootData) < (const uint8_t*)(&tree+1)) {
102 return util::strcpy(error, "Invalid root pointer (should be located after the Grid and Tree)");
103 } else if ( (const void*)(rootData) > util::PtrAdd(rootData, root.memUsage())) {
104 return util::strcpy(error, "Invalid root pointer (appears to be located after the end of the buffer)");
105 } else {// check root tiles
106 const void *bounds[2] = {rootData + 1, util::PtrAdd(rootData, root.memUsage())};
107 for (uint32_t i = 0; i<rootData->mTableSize; ++i) {
108 const void *tile = rootData->tile(i);
109 if ( tile < bounds[0] ) {
110 return util::strcpy(error, "Invalid root tile pointer (below lower bound");
111 } else if (tile >= bounds[1]) {
112 return util::strcpy(error, "Invalid root tile pointer (above higher bound");
113 }
114 }
115 }
116 if (mode == CheckMode::Half) return error;
117
118 // check nodes
119 const bool test = grid->isBreadthFirst();
120 auto *n0 = tree.template getFirstNode<0>();
121 auto *n1 = tree.template getFirstNode<1>();
122 auto *n2 = tree.template getFirstNode<2>();
123 const void *bounds[3][2] = {{n0, util::PtrAdd(n0, grid->gridSize())}, {n1, n0}, {n2, n1}};
124
125 auto check = [&](const void *ptr, int level) -> bool {
126 if (ptr==nullptr) {
127 util::strcpy(error, "Invalid node pointer: node is NULL");
128 } else if (!isAligned(ptr)) {
129 util::strcpy(error, "Invalid node pointer: node is misaligned");
130 } else if (test && level == 0 && (const void*)(n0++) != ptr) {
131 util::strcpy(error, "Leaf node is not stored breadth-first");
132 } else if (test && level == 1 && (const void*)(n1++) != ptr) {
133 util::strcpy(error, "Lower node is not stored breadth-first");
134 } else if (test && level == 2 && (const void*)(n2++) != ptr) {
135 util::strcpy(error, "Upper node is not stored breadth-first");
136 } else if ( ptr < bounds[level][0] ) {
137 util::strcpy(error, "Invalid node pointer: below lower bound");
138 } else if ( ptr >= bounds[level][1] ) {
139 util::strcpy(error, "Invalid node pointer: above higher bound");
140 }
141 return !util::empty(error);
142 };
143
144 for (auto it2 = root.cbeginChild(); it2; ++it2) {
145 if (check(&*it2, 2)) return error;
146 for (auto it1 = it2->cbeginChild(); it1; ++it1) {
147 if (check(&*it1, 1)) return error;
148 for (auto it0 = it1->cbeginChild(); it0; ++it0) if (check(&*it0, 0)) return error;
149 }// loop over child nodes of the upper internal node
150 }// loop over child nodes of the root node
151
152 return error;
153} // checkGrid
154
155//================================================================================================
156
157template <typename ValueT>
158bool isValid(const NanoGrid<ValueT> *grid, CheckMode mode, bool verbose)
159{
160 std::unique_ptr<char[]> strUP(new char[100]);
161 char *str = strUP.get();
162
163 tools::checkGrid(grid, str, mode);
164
165 if (util::empty(str) && !validateChecksum(grid, mode)) util::strcpy(str, "Mis-matching checksum");
166 if (verbose && !util::empty(str)) std::cerr << "Validation failed: " << str << std::endl;
167
168 return util::empty(str);
169}// isValid
170
171//================================================================================================
172
174 template <typename BuildT>
175 static bool known(const GridData *gridData, CheckMode mode, bool verbose)
176 {
177 return tools::isValid((const NanoGrid<BuildT>*)gridData, mode, verbose);
178 }
179 static bool unknown(const GridData *gridData, CheckMode, bool verbose)
180 {
181 if (verbose) {
182 char str[16];
183 std::cerr << "Unsupported GridType: \"" << toStr(str, gridData->mGridType) << "\"\n" << std::endl;
184 }
185 return false;
186 }
187};// IsNanoGridValid
188
189/// @brief Validate a specific grid in a GridHandle
190/// @tparam GridHandleT Type of GridHandle
191/// @param handle GridHandle containing host grids
192/// @param gridID linear index of the grid to be validated
193/// @param mode node of validation tests
194/// @param verbose if true information is printed if the grid fails a validation test
195/// @return true if grid @c gridID passes all the validation tests
196template <typename GridHandleT>
197bool validateGrid(const GridHandleT &handle, uint32_t gridID, CheckMode mode, bool verbose)
198{
199 if (mode == CheckMode::Disable) {
200 return true;
201 } else if (gridID >= handle.gridCount()) {
202 if (verbose) std::cerr << "grid index " << gridID << " exceeds available grid count " << handle.gridCount() << std::endl;
203 return false;
204 }
205 return callNanoGrid<IsNanoGridValid>(handle.gridData(gridID), mode, verbose);
206}// validateGrid
207
208//================================================================================================
209
210/// @brief Validate all the grids in a GridHandle
211/// @tparam GridHandleT Type of GridHandle
212/// @param handle GridHandle containing host grids (0,1...,N)
213/// @param mode node of validation tests
214/// @param verbose if true information is printed if a grid fails a validation test
215/// @return true if all grids pass alle the validation tests
216template <typename GridHandleT>
217bool validateGrids(const GridHandleT &handle, CheckMode mode, bool verbose)
218{
219 if (mode == CheckMode::Disable) return true;
220 for (uint32_t gridID=0; gridID<handle.gridCount(); ++gridID) {
221 if (!validateGrid(handle, gridID, mode, verbose)) return false;
222 }
223 return true;
224}// validateGrids
225
226}// namespace tools
227
228template<typename ValueT>
229[[deprecated("Use nanovdb:tools::checkGrid instead.")]]
230__hostdev__ char* checkGrid(const NanoGrid<ValueT> *grid, char *error, CheckMode mode = CheckMode::Full)
231{
232 return tools::checkGrid<ValueT>(grid, error, mode);
233}
234
235template <typename ValueT>
236[[deprecated("Use nanovdb:tools::isValid instead.")]]
237bool isValid(const NanoGrid<ValueT> *grid, CheckMode mode, bool verbose = false)
238{
239 return tools::isValid<ValueT>(grid, mode, verbose);
240}
241
242}// namespace nanovdb
243
244#endif // NANOVDB_TOOLS_GRID_VALIDATOR_H_HAS_BEEN_INCLUDED
Implements a light-weight self-contained VDB data-structure in a single file! In other words,...
#define NANOVDB_MAGIC_GRID
Definition NanoVDB.h:140
#define NANOVDB_MAGIC_NUMB
Definition NanoVDB.h:139
bool isBreadthFirst() const
Definition NanoVDB.h:2326
uint64_t gridSize() const
Return memory usage in bytes for this class only.
Definition NanoVDB.h:2213
const TreeT & tree() const
Return a const reference to the tree.
Definition NanoVDB.h:2236
bool isCompatible() const
Definition NanoVDB.h:760
#define __hostdev__
Definition SampleFromVoxels.h:29
Definition CreateNanoGrid.h:104
bool validateChecksum(const GridData *gridData, CheckMode mode=CheckMode::Default)
Return true if the checksum of gridData matches the expected value already encoded into the grid's me...
Definition GridChecksum.h:368
bool validateGrid(const GridHandleT &handle, uint32_t gridID, CheckMode mode, bool verbose)
Validate a specific grid in a GridHandle.
Definition GridValidator.h:197
bool validateGrids(const GridHandleT &handle, CheckMode mode, bool verbose)
Validate all the grids in a GridHandle.
Definition GridValidator.h:217
__hostdev__ char * checkGrid(const NanoGrid< ValueT > *grid, char *error, CheckMode mode=CheckMode::Full)
validate grid
Definition GridValidator.h:58
bool isValid(const NanoGrid< ValueT > *grid, CheckMode mode, bool verbose=false)
Performs several validation tests on a grid pointer.
Definition GridValidator.h:158
static DstT * PtrAdd(void *p, int64_t offset)
Adds a byte offset to a non-const pointer to produce another non-const pointer.
Definition Util.h:524
char * strcpy(char *dst, const char *src)
Copy characters from src to dst.
Definition Util.h:178
bool empty(const char *str)
tests if a c-string str is empty, that is its first value is '\0'
Definition Util.h:156
char * sprint(char *dst, T var1, Types... var2)
prints a variable number of string and/or numbers to a destination string
Definition Util.h:298
Defines a simple memory pool used to call cub functions that use dynamic temporary storage.
Definition GridHandle.h:31
auto callNanoGrid(GridDataT *gridData, ArgsT &&... args)
Below is an example of the struct used for generic programming with callNanoGrid.
Definition NanoVDB.h:4846
GridType toGridType()
Maps from a templated build type to a GridType enum.
Definition NanoVDB.h:851
Grid< NanoTree< BuildT > > NanoGrid
Definition NanoVDB.h:4742
@ End
Definition NanoVDB.h:299
@ End
Definition NanoVDB.h:246
CheckMode
List of different modes for computing for a checksum.
Definition NanoVDB.h:1846
@ Full
Definition NanoVDB.h:1851
@ Disable
Definition NanoVDB.h:1846
@ Half
Definition NanoVDB.h:1848
MagicType toMagic(uint64_t magic)
maps 64 bits of magic number to enum
Definition NanoVDB.h:366
char * toStr(char *dst, GridType gridType)
Maps a GridType to a c-string.
Definition NanoVDB.h:253
__hostdev__ char * checkGrid(const NanoGrid< ValueT > *grid, char *error, CheckMode mode=CheckMode::Full)
Definition GridValidator.h:230
static bool isAligned(const void *p)
return true if the specified pointer is 32 byte aligned
Definition NanoVDB.h:600
bool isValid(GridType gridType, GridClass gridClass)
return true if the combination of GridType and GridClass is valid.
Definition NanoVDB.h:664
Struct with all the member data of the Grid (useful during serialization of an openvdb grid)
Definition NanoVDB.h:1977
Version mVersion
Definition NanoVDB.h:1981
GridType mGridType
Definition NanoVDB.h:1991
uint64_t mMagic
Definition NanoVDB.h:1979
GridClass mGridClass
Definition NanoVDB.h:1990
uint32_t mGridCount
Definition NanoVDB.h:1984
uint32_t mGridIndex
Definition NanoVDB.h:1983
Definition GridValidator.h:173
static bool known(const GridData *gridData, CheckMode mode, bool verbose)
Definition GridValidator.h:175
static bool unknown(const GridData *gridData, CheckMode, bool verbose)
Definition GridValidator.h:179
Computes a pair of uint32_t checksums, of a Grid, by means of 32 bit Cyclic Redundancy Check (CRC32)