// Copyright 2009 Carl Ollivier-Gooch
// This file is part of the iMesh Reference Implementation (RefImpl).
// The iMesh Reference Implementation is free software: you can
// redistribute it and/or modify it under the terms of the GNU Lesser
// General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
// The iMesh Reference Implementation is distributed in the hope that it
// will be useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
// the GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with the iMesh Reference Implementation. If not, see
// .
#ifndef iMesh_RefImpl_misc_hh
#define iMesh_RefImpl_misc_hh
#include "stdlib.h"
#include "iBase.h"
#include "RI_config.h"
#include
// The do-while(0) business below is so that these macros can be used as
// statements, even in un-{}'ed if clauses or loops.
/// Make sure ITAPS arrays have the right size, or die trying.
template
void vEnsureArraySize(T** array, int* alloc_size,
const int req_size)
throw(iBase_ErrorType)
{
if (*alloc_size == 0) {
if (req_size > 0) {
*array = reinterpret_cast(calloc(req_size, sizeof(T)));
*alloc_size = req_size;
}
}
else if (*alloc_size < req_size) {
throw(iBase_BAD_ARRAY_SIZE);
}
}
// Some of the internal RefImpl functions throw exceptions; this macro
// converts those exceptions into iMesh error return values.
#define TRY(a) \
do { \
try { \
a; \
} catch (iBase_ErrorType iET_) { \
*err = iET_; \
return; \
} \
} while (0)
// This is a variant on the TRY macro, specialized for the array size
// check above.
#define TRY_ARRAY_SIZE(array_, alloc_size_, req_size_, type_) \
do { \
try { \
vEnsureArraySize(array_, alloc_size_, req_size_); \
} catch (iBase_ErrorType ET_) { \
*err = ET_; \
return; \
} \
} while (0)
#define RI_rootSet (reinterpret_cast(INT_MIN + 1))
// #ifdef NDEBUG
// // For production code, there are a bunch of checks that get compiled
// // out; a decent optimizer will make this all go away.
// #define CHECK_FOR_MESH_DATA(pMG_, err_) do {} while (0)
// #define CHECK_ENTITY(pMG_, entity_, err_) do {} while (0)
// #define CHECK_ENTITY_SET(pMG_, entity_set_, err_) do {} while (0)
// #define CHECK_TAG(pMG_, ptbTheTag_, err_) do {} while (0)
// #define CHECK_ENT_ITER(pMG_, pEI_, err_) do {} while (0)
// #define CHECK_ENTARR_ITER(pMG_, pWs_, err_) do {} while (0)
// #define CHECK_CYCLIC(pESB_parent_, pESB_child_, err_) do {} while (0)
// #define CHECK_FOR_NULL_TERMINATION(string_, len_, err_) do {} while (0)
// #else
// Make sure that mesh data exists, because most iMesh functions require it.
#define CHECK_FOR_MESH_DATA(pMG_, err_) \
do { \
if (pMG_->pGB == NULL || \
pMG_->pGB->pMesh() == NULL || \
pMG_->pGB->pMesh()->iNumVerts() == 0) { \
*err_ = iBase_NO_MESH_DATA; \
return; \
} \
} while (0)
// Check whether an entity really does exist in this iMesh database.
#define CHECK_ENTITY(pMG_, entity_, err_) \
do { \
if ( entity_ == NULL || !pMG_->pGB->pMesh()->qIsValidEnt(entity_) ) { \
*err_ = iBase_INVALID_ENTITY_HANDLE; \
return; \
} \
} while (0)
// Check whether an entity set really does exist in this iMesh database.
#define CHECK_ENTITY_SET(pMG_, entity_set_, err_) \
do { \
void *pvSet = reinterpret_cast(entity_set_); \
if ( (pvSet != RI_rootSet) && \
!pMG_->pGB->qHasSet \
(dynamic_cast(entity_set_))) { \
*err_ = iBase_INVALID_ENTITYSET_HANDLE; \
return; \
} \
} while (0)
// Check whether a tag really does exist in this iMesh database.
#define CHECK_TAG(pMG_, ptbTheTag_, err_) \
do { \
if ( !pMG_->pGB->isTag(ptbTheTag_) ) { \
*err_ = iBase_INVALID_TAG_HANDLE; \
return; \
} \
} while (0)
// Check whether an iterator really does exist in this iMesh database.
#define CHECK_ENT_ITER(pMG_, pEI_, err_) \
do { \
if ( !pMG_->pGB->qHasIter(pEI_)) { \
*err_ = iBase_INVALID_ITERATOR_HANDLE; \
return; \
} \
} while (0)
// Check whether an array iterator really does exist in this iMesh database.
#define CHECK_ENTARR_ITER(pMG_, pWs_, err_) \
do { \
if ( !pMG_->pGB->qHasWorkset(pWs_)) { \
*err_ = iBase_INVALID_ITERATOR_HANDLE; \
return; \
} \
} while (0)
// Check whether a string is null terminated, as the C spec requires.
#define CHECK_FOR_NULL_TERMINATION(string_, len_, err_) \
do { \
if (string_[len_] != (char)(0)) { \
*err_ = iBase_FAILURE; \
return; \
} \
} while (0)
// #endif
// Confirm that the provided mesh type and topology are compatible.
#define CHECK_TYPE_AND_TOPO(type_, topo_, err_) \
do { \
if ( type_ < iBase_VERTEX || type_ > iBase_ALL_TYPES ) { \
*err_ = iBase_INVALID_ENTITY_TYPE; \
return; \
} \
else if ( topo_ < iMesh_POINT || topo_ > iMesh_ALL_TOPOLOGIES ) { \
*err_ = iBase_INVALID_ENTITY_TOPOLOGY; \
return; \
} \
else { \
switch (type_) { \
case iBase_VERTEX: \
if (topo_ != iMesh_POINT && topo_ != iMesh_ALL_TOPOLOGIES) { \
*err_ = iBase_BAD_TYPE_AND_TOPO; \
return; \
} \
break; \
case iBase_EDGE: \
if (topo_ != iMesh_LINE_SEGMENT && \
topo_ != iMesh_ALL_TOPOLOGIES) { \
*err_ = iBase_BAD_TYPE_AND_TOPO; \
return; \
} \
break; \
case iBase_FACE: \
if (topo_ != iMesh_TRIANGLE && \
topo_ != iMesh_QUADRILATERAL && \
topo_ != iMesh_POLYGON && \
topo_ != iMesh_ALL_TOPOLOGIES) { \
*err_ = iBase_BAD_TYPE_AND_TOPO; \
return; \
} \
break; \
case iBase_REGION: \
if (topo_ != iMesh_TETRAHEDRON && \
topo_ != iMesh_PYRAMID && \
topo_ != iMesh_PRISM && \
topo_ != iMesh_HEXAHEDRON && \
topo_ != iMesh_SEPTAHEDRON && \
topo_ != iMesh_POLYHEDRON && \
topo_ != iMesh_ALL_TOPOLOGIES) { \
*err_ = iBase_BAD_TYPE_AND_TOPO; \
return; \
} \
break; \
case iBase_ALL_TYPES: \
break; \
} \
} \
} while (0)
// Ensure that a string will be null terminated, even if it wasn't before.
#define NULL_TERMINATE(a_in_, len_, a_) \
do { \
snprintf(a_, 1023, "%s", a_in_); \
a_[len_] = 0; \
} while(false);
// Find the location of data in the array [start, end); it is an error
// for data -not- to be present.
template
int findArrayIndex(const T& data, const T* const start, const T* const end)
{
T const *loc = std::find(start, end, data);
int index = loc - start;
assert(index >= 0 && index < end - start);
return index;
}
#endif