OpenVDB 14.0.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#include <memory> // for std::unique_ptr
25
26#include <nanovdb/NanoVDB.h>
28
29namespace nanovdb {
30
31namespace tools {
32
33/// @brief Performs several validation tests on a grid pointer.
34/// @tparam ValueT Build type of the input grid
35/// @param grid const point to the grid that needs validation
36/// @param mode Mode of the validation check (defined in GridChecksum.h)
37/// @param verbose If true information about the first failed test is printed to std::cerr
38/// @return Return true if the specified grid passes several validation tests.
39template <typename ValueT>
40bool isValid(const NanoGrid<ValueT> *grid, CheckMode mode, bool verbose = false);
41
42//================================================================================================
43
44/// @brief validate grid
45template<typename ValueT>
46__hostdev__ char* checkGrid(const NanoGrid<ValueT> *grid, char *error, CheckMode mode = CheckMode::Full)
47{
48 *error = '\0';// reset error string
49 char str[32];// temporary buffer for toStr
50
51 // check Grid
52 if (grid == nullptr) {
53 return util::sprint(error, "Invalid pointer: Grid is NULL");
54 } else if (!isAligned(grid)) {
55 return util::sprint(error, "Invalid pointer: Grid is misaligned");
56 } else if (grid->mMagic != NANOVDB_MAGIC_NUMB && grid->mMagic != NANOVDB_MAGIC_GRID) {
57 return util::sprint(error, "Invalid magic number: ", toStr(str, toMagic(grid->mMagic)));
58 } else if (!grid->mVersion.isCompatible()) {
59 return util::sprint(error, "Incompatible version number: ", toStr(str, grid->mVersion));
60 } else if (grid->mGridCount == 0) {
61 return util::sprint(error, "Zero grid count");
62 } else if (grid->mGridIndex >= grid->mGridCount) {
63 return util::sprint(error, "grid index(", int(grid->mGridIndex), ") >= grid count(", int(grid->mGridCount), ")");
64 } else if (grid->mGridClass >= GridClass::End) {
65 return util::sprint(error, "Invalid GridClass(", toStr(str, grid->mGridClass), ")");
66 } else if (grid->mGridType >= GridType::End) {
67 return util::sprint(error, "Invalid GridType(", toStr(str, grid->mGridType), ")");
68 } else if (grid->mGridType != toGridType<ValueT>()) {
69 return util::sprint(error, "Invalid combination of BuildType(", toStr(str, toGridType<ValueT>()), ") and GridType(", toStr(str+16, grid->mGridType), ")");
70 } else if (!isValid(grid->mGridType, grid->mGridClass)) {
71 return util::sprint(error, "Invalid combination of GridType(", toStr(str, grid->mGridType), ") and GridClass(", toStr(str+16,grid->mGridClass), ")");
72 }
73
74 // check Tree
75 auto &tree = grid->tree();
76 if (auto *p = tree.getRoot()) {
77 if (!isAligned(p)) return util::strcpy(error, "Invalid pointer: Root is misaligned");
78 } else {
79 return util::strcpy(error, "Invalid pointer: Root is NULL");
80 }
81
82 // check Root
83 auto &root = tree.root();
84 auto *rootData = root.data();
85 if (rootData == nullptr) {
86 return util::strcpy(error, "Invalid pointer: Root is NULL");
87 } else if (!isAligned((const void*)rootData)) {
88 return util::strcpy(error, "Invalid pointer: Root is misaligned");
89 } else if ( (const uint8_t*)(rootData) < (const uint8_t*)(&tree+1)) {
90 return util::strcpy(error, "Invalid root pointer (should be located after the Grid and Tree)");
91 } else if ( (const void*)(rootData) > util::PtrAdd(rootData, root.memUsage())) {
92 return util::strcpy(error, "Invalid root pointer (appears to be located after the end of the buffer)");
93 } else {// check root tiles
94 const void *bounds[2] = {rootData + 1, util::PtrAdd(rootData, root.memUsage())};
95 for (uint32_t i = 0; i<rootData->mTableSize; ++i) {
96 const void *tile = rootData->tile(i);
97 if ( tile < bounds[0] ) {
98 return util::strcpy(error, "Invalid root tile pointer (below lower bound");
99 } else if (tile >= bounds[1]) {
100 return util::strcpy(error, "Invalid root tile pointer (above higher bound");
101 }
102 }
103 }
104 if (mode == CheckMode::Half) return error;
105
106 // check nodes
107 const bool test = grid->isBreadthFirst();
108 auto *n0 = tree.template getFirstNode<0>();
109 auto *n1 = tree.template getFirstNode<1>();
110 auto *n2 = tree.template getFirstNode<2>();
111 const void *bounds[3][2] = {{n0, util::PtrAdd(grid, grid->gridSize())}, {n1, n0}, {n2, n1}};
112
113 auto check = [&](const void *ptr, int level) -> bool {
114 if (ptr==nullptr) {
115 util::strcpy(error, "Invalid node pointer: node is NULL");
116 } else if (!isAligned(ptr)) {
117 util::strcpy(error, "Invalid node pointer: node is misaligned");
118 } else if (test && level == 0 && (const void*)(n0++) != ptr) {
119 util::strcpy(error, "Leaf node is not stored breadth-first");
120 } else if (test && level == 1 && (const void*)(n1++) != ptr) {
121 util::strcpy(error, "Lower node is not stored breadth-first");
122 } else if (test && level == 2 && (const void*)(n2++) != ptr) {
123 util::strcpy(error, "Upper node is not stored breadth-first");
124 } else if ( ptr < bounds[level][0] ) {
125 util::strcpy(error, "Invalid node pointer: below lower bound");
126 } else if ( ptr >= bounds[level][1] ) {
127 util::strcpy(error, "Invalid node pointer: above higher bound");
128 }
129 return !util::empty(error);
130 };
131
132 for (auto it2 = root.cbeginChild(); it2; ++it2) {
133 if (check(&*it2, 2)) return error;
134 for (auto it1 = it2->cbeginChild(); it1; ++it1) {
135 if (check(&*it1, 1)) return error;
136 for (auto it0 = it1->cbeginChild(); it0; ++it0) if (check(&*it0, 0)) return error;
137 }// loop over child nodes of the upper internal node
138 }// loop over child nodes of the root node
139
140 return error;
141} // checkGrid
142
143//================================================================================================
144
145template <typename ValueT>
146bool isValid(const NanoGrid<ValueT> *grid, CheckMode mode, bool verbose)
147{
148 std::unique_ptr<char[]> strUP(new char[100]);
149 char *str = strUP.get();
150
151 tools::checkGrid(grid, str, mode);
152
153 if (util::empty(str) && !validateChecksum(grid, mode)) util::strcpy(str, "Mis-matching checksum");
154 if (verbose && !util::empty(str)) std::cerr << "Validation failed: " << str << std::endl;
155
156 return util::empty(str);
157}// isValid
158
159//================================================================================================
160
162 template <typename BuildT>
163 static bool known(const GridData *gridData, CheckMode mode, bool verbose)
164 {
165 return tools::isValid((const NanoGrid<BuildT>*)gridData, mode, verbose);
166 }
167 static bool unknown(const GridData *gridData, CheckMode, bool verbose)
168 {
169 if (verbose) {
170 char str[16];
171 std::cerr << "Unsupported GridType: \"" << toStr(str, gridData->mGridType) << "\"\n" << std::endl;
172 }
173 return false;
174 }
175};// IsNanoGridValid
176
177/// @brief Validate a specific grid in a GridHandle
178/// @tparam GridHandleT Type of GridHandle
179/// @param handle GridHandle containing host grids
180/// @param gridID linear index of the grid to be validated
181/// @param mode node of validation tests
182/// @param verbose if true information is printed if the grid fails a validation test
183/// @return true if grid @c gridID passes all the validation tests
184template <typename GridHandleT>
185bool validateGrid(const GridHandleT &handle, uint32_t gridID, CheckMode mode, bool verbose)
186{
187 if (mode == CheckMode::Disable) {
188 return true;
189 } else if (gridID >= handle.gridCount()) {
190 if (verbose) std::cerr << "grid index " << gridID << " exceeds available grid count " << handle.gridCount() << std::endl;
191 return false;
192 }
193 return callNanoGrid<IsNanoGridValid>(handle.gridData(gridID), mode, verbose);
194}// validateGrid
195
196//================================================================================================
197
198/// @brief Validate all the grids in a GridHandle
199/// @tparam GridHandleT Type of GridHandle
200/// @param handle GridHandle containing host grids (0,1...,N)
201/// @param mode node of validation tests
202/// @param verbose if true information is printed if a grid fails a validation test
203/// @return true if all grids pass alle the validation tests
204template <typename GridHandleT>
205bool validateGrids(const GridHandleT &handle, CheckMode mode, bool verbose)
206{
207 if (mode == CheckMode::Disable) return true;
208 for (uint32_t gridID=0; gridID<handle.gridCount(); ++gridID) {
209 if (!validateGrid(handle, gridID, mode, verbose)) return false;
210 }
211 return true;
212}// validateGrids
213
214}// namespace tools
215
216}// namespace nanovdb
217
218#endif // NANOVDB_TOOLS_GRID_VALIDATOR_H_HAS_BEEN_INCLUDED
Computes a pair of uint32_t checksums, of a Grid, by means of 32 bit Cyclic Redundancy Check (CRC32)
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
#define __hostdev__
Definition SampleFromVoxels.h:29
bool isBreadthFirst() const
Definition NanoVDB.h:2301
uint64_t gridSize() const
Return memory usage in bytes for this class only.
Definition NanoVDB.h:2188
const TreeT & tree() const
Return a const reference to the tree.
Definition NanoVDB.h:2211
bool isCompatible() const
Definition NanoVDB.h:757
Definition CreateNanoGrid.h:106
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:357
bool validateGrid(const GridHandleT &handle, uint32_t gridID, CheckMode mode, bool verbose)
Validate a specific grid in a GridHandle.
Definition GridValidator.h:185
bool validateGrids(const GridHandleT &handle, CheckMode mode, bool verbose)
Validate all the grids in a GridHandle.
Definition GridValidator.h:205
__hostdev__ char * checkGrid(const NanoGrid< ValueT > *grid, char *error, CheckMode mode=CheckMode::Full)
validate grid
Definition GridValidator.h:46
bool isValid(const NanoGrid< ValueT > *grid, CheckMode mode, bool verbose=false)
Performs several validation tests on a grid pointer.
Definition GridValidator.h:146
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:555
char * strcpy(char *dst, const char *src)
Copy characters from src to dst.
Definition Util.h:209
bool empty(const char *str)
tests if a c-string str is empty, that is its first value is '\0'
Definition Util.h:187
char * sprint(char *dst, T var1, Types... var2)
prints a variable number of string and/or numbers to a destination string
Definition Util.h:329
Defines a simple memory pool used to call cub functions that use dynamic temporary storage.
Definition GridHandle.h:34
auto callNanoGrid(GridDataT *gridData, ArgsT &&... args)
Below is an example of the struct used for generic programming with callNanoGrid.
Definition NanoVDB.h:4805
GridType toGridType()
Maps from a templated build type to a GridType enum.
Definition NanoVDB.h:848
Grid< NanoTree< BuildT > > NanoGrid
Definition NanoVDB.h:4699
@ End
Definition NanoVDB.h:303
@ End
Definition NanoVDB.h:250
CheckMode
List of different modes for computing for a checksum.
Definition NanoVDB.h:1831
@ Full
Definition NanoVDB.h:1836
@ Disable
Definition NanoVDB.h:1831
@ Half
Definition NanoVDB.h:1833
MagicType toMagic(uint64_t magic)
maps 64 bits of magic number to enum
Definition NanoVDB.h:370
char * toStr(char *dst, GridType gridType)
Maps a GridType to a c-string.
Definition NanoVDB.h:257
static bool isAligned(const void *p)
return true if the specified pointer is 32 byte aligned
Definition NanoVDB.h:597
Struct with all the member data of the Grid (useful during serialization of an openvdb grid)
Definition NanoVDB.h:1952
Version mVersion
Definition NanoVDB.h:1956
GridType mGridType
Definition NanoVDB.h:1966
uint64_t mMagic
Definition NanoVDB.h:1954
GridClass mGridClass
Definition NanoVDB.h:1965
uint32_t mGridCount
Definition NanoVDB.h:1959
uint32_t mGridIndex
Definition NanoVDB.h:1958
Definition GridValidator.h:161
static bool known(const GridData *gridData, CheckMode mode, bool verbose)
Definition GridValidator.h:163
static bool unknown(const GridData *gridData, CheckMode, bool verbose)
Definition GridValidator.h:167