Merge remote-tracking branch 'upstream/master' into add-tests-to-c-api-2

This commit is contained in:
Marc-Antoine Lortie
2020-04-13 09:08:45 -04:00
84 changed files with 2323 additions and 1974 deletions

View File

@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -49,13 +47,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_STREAMREADER_H_INCLUDED
#ifdef __GNUC__
# pragma GCC system_header
#pragma GCC system_header
#endif
#include <assimp/IOStream.hpp>
#include <assimp/Defines.h>
#include <assimp/ByteSwapper.h>
#include <assimp/Defines.h>
#include <assimp/Exceptional.h>
#include <assimp/IOStream.hpp>
#include <memory>
@@ -74,10 +72,8 @@ namespace Assimp {
template <bool SwapEndianess = false, bool RuntimeSwitch = false>
class StreamReader {
public:
// FIXME: use these data types throughout the whole library,
// then change them to 64 bit values :-)
using diff = int;
using pos = unsigned int;
using diff = size_t;
using pos = size_t;
// ---------------------------------------------------------------------
/** Construction from a given stream with a well-defined endianness.
@@ -91,40 +87,45 @@ public:
* stream is in little endian byte order. Otherwise the
* endianness information is contained in the @c SwapEndianess
* template parameter and this parameter is meaningless. */
StreamReader(std::shared_ptr<IOStream> stream, bool le = false)
: stream(stream)
, le(le)
{
StreamReader(std::shared_ptr<IOStream> stream, bool le = false) :
mStream(stream),
mBuffer(nullptr),
mCurrent(nullptr),
mEnd(nullptr),
mLimit(nullptr),
mLe(le) {
ai_assert(stream);
InternBegin();
}
// ---------------------------------------------------------------------
StreamReader(IOStream* stream, bool le = false)
: stream(std::shared_ptr<IOStream>(stream))
, le(le)
{
ai_assert(stream);
StreamReader(IOStream *stream, bool le = false) :
mStream(std::shared_ptr<IOStream>(stream)),
mBuffer(nullptr),
mCurrent(nullptr),
mEnd(nullptr),
mLimit(nullptr),
mLe(le) {
ai_assert(nullptr != stream);
InternBegin();
}
// ---------------------------------------------------------------------
~StreamReader() {
delete[] buffer;
delete[] mBuffer;
}
// deprecated, use overloaded operator>> instead
// ---------------------------------------------------------------------
/** Read a float from the stream */
float GetF4()
{
/// Read a float from the stream.
float GetF4() {
return Get<float>();
}
// ---------------------------------------------------------------------
/** Read a double from the stream */
double GetF8() {
/// Read a double from the stream.
double GetF8() {
return Get<double>();
}
@@ -136,7 +137,7 @@ public:
// ---------------------------------------------------------------------
/** Read a signed 8 bit integer from the stream */
int8_t GetI1() {
int8_t GetI1() {
return Get<int8_t>();
}
@@ -154,55 +155,55 @@ public:
// ---------------------------------------------------------------------
/** Read a unsigned 16 bit integer from the stream */
uint16_t GetU2() {
uint16_t GetU2() {
return Get<uint16_t>();
}
// ---------------------------------------------------------------------
/** Read a unsigned 8 bit integer from the stream */
/// Read a unsigned 8 bit integer from the stream
uint8_t GetU1() {
return Get<uint8_t>();
}
// ---------------------------------------------------------------------
/** Read an unsigned 32 bit integer from the stream */
uint32_t GetU4() {
/// Read an unsigned 32 bit integer from the stream
uint32_t GetU4() {
return Get<uint32_t>();
}
// ---------------------------------------------------------------------
/** Read a unsigned 64 bit integer from the stream */
uint64_t GetU8() {
/// Read a unsigned 64 bit integer from the stream
uint64_t GetU8() {
return Get<uint64_t>();
}
// ---------------------------------------------------------------------
/** Get the remaining stream size (to the end of the stream) */
unsigned int GetRemainingSize() const {
return (unsigned int)(end - current);
/// Get the remaining stream size (to the end of the stream)
size_t GetRemainingSize() const {
return (unsigned int)(mEnd - mCurrent);
}
// ---------------------------------------------------------------------
/** Get the remaining stream size (to the current read limit). The
* return value is the remaining size of the stream if no custom
* read limit has been set. */
unsigned int GetRemainingSizeToLimit() const {
return (unsigned int)(limit - current);
size_t GetRemainingSizeToLimit() const {
return (unsigned int)(mLimit - mCurrent);
}
// ---------------------------------------------------------------------
/** Increase the file pointer (relative seeking) */
void IncPtr(intptr_t plus) {
current += plus;
if (current > limit) {
void IncPtr(intptr_t plus) {
mCurrent += plus;
if (mCurrent > mLimit) {
throw DeadlyImportError("End of file or read limit was reached");
}
}
// ---------------------------------------------------------------------
/** Get the current file pointer */
int8_t* GetPtr() const {
return current;
int8_t *GetPtr() const {
return mCurrent;
}
// ---------------------------------------------------------------------
@@ -211,9 +212,9 @@ public:
* large chunks of data at once.
* @param p The new pointer, which is validated against the size
* limit and buffer boundaries. */
void SetPtr(int8_t* p) {
current = p;
if (current > limit || current < buffer) {
void SetPtr(int8_t *p) {
mCurrent = p;
if (mCurrent > mLimit || mCurrent < mBuffer) {
throw DeadlyImportError("End of file or read limit was reached");
}
}
@@ -222,21 +223,20 @@ public:
/** Copy n bytes to an external buffer
* @param out Destination for copying
* @param bytes Number of bytes to copy */
void CopyAndAdvance(void* out, size_t bytes) {
int8_t* ur = GetPtr();
SetPtr(ur+bytes); // fire exception if eof
void CopyAndAdvance(void *out, size_t bytes) {
int8_t *ur = GetPtr();
SetPtr(ur + bytes); // fire exception if eof
::memcpy(out,ur,bytes);
::memcpy(out, ur, bytes);
}
// ---------------------------------------------------------------------
/** Get the current offset from the beginning of the file */
int GetCurrentPos() const {
return (unsigned int)(current - buffer);
/// @brief Get the current offset from the beginning of the file
int GetCurrentPos() const {
return (unsigned int)(mCurrent - mBuffer);
}
void SetCurrentPos(size_t pos) {
SetPtr(buffer + pos);
SetPtr(mBuffer + pos);
}
// ---------------------------------------------------------------------
@@ -246,15 +246,15 @@ public:
* the beginning of the file. Specifying UINT_MAX
* resets the limit to the original end of the stream.
* Returns the previously set limit. */
unsigned int SetReadLimit(unsigned int _limit) {
unsigned int SetReadLimit(unsigned int _limit) {
unsigned int prev = GetReadLimit();
if (UINT_MAX == _limit) {
limit = end;
mLimit = mEnd;
return prev;
}
limit = buffer + _limit;
if (limit > end) {
mLimit = mBuffer + _limit;
if (mLimit > mEnd) {
throw DeadlyImportError("StreamReader: Invalid read limit");
}
return prev;
@@ -263,21 +263,21 @@ public:
// ---------------------------------------------------------------------
/** Get the current read limit in bytes. Reading over this limit
* accidentally raises an exception. */
unsigned int GetReadLimit() const {
return (unsigned int)(limit - buffer);
unsigned int GetReadLimit() const {
return (unsigned int)(mLimit - mBuffer);
}
// ---------------------------------------------------------------------
/** Skip to the read limit in bytes. Reading over this limit
* accidentally raises an exception. */
void SkipToReadLimit() {
current = limit;
void SkipToReadLimit() {
mCurrent = mLimit;
}
// ---------------------------------------------------------------------
/** overload operator>> and allow chaining of >> ops. */
template <typename T>
StreamReader& operator >> (T& f) {
StreamReader &operator>>(T &f) {
f = Get<T>();
return *this;
}
@@ -286,14 +286,14 @@ public:
/** Generic read method. ByteSwap::Swap(T*) *must* be defined */
template <typename T>
T Get() {
if ( current + sizeof(T) > limit) {
if (mCurrent + sizeof(T) > mLimit) {
throw DeadlyImportError("End of file or stream limit was reached");
}
T f;
::memcpy (&f, current, sizeof(T));
Intern::Getter<SwapEndianess,T,RuntimeSwitch>() (&f,le);
current += sizeof(T);
::memcpy(&f, mCurrent, sizeof(T));
Intern::Getter<SwapEndianess, T, RuntimeSwitch>()(&f, mLe);
mCurrent += sizeof(T);
return f;
}
@@ -301,46 +301,44 @@ public:
private:
// ---------------------------------------------------------------------
void InternBegin() {
if (!stream) {
// in case someone wonders: StreamReader is frequently invoked with
// no prior validation whether the input stream is valid. Since
// no one bothers changing the error message, this message here
// is passed down to the caller and 'unable to open file'
// simply describes best what happened.
if (nullptr == mStream) {
throw DeadlyImportError("StreamReader: Unable to open file");
}
const size_t s = stream->FileSize() - stream->Tell();
if (!s) {
const size_t filesize = mStream->FileSize() - mStream->Tell();
if (0 == filesize) {
throw DeadlyImportError("StreamReader: File is empty or EOF is already reached");
}
current = buffer = new int8_t[s];
const size_t read = stream->Read(current,1,s);
mCurrent = mBuffer = new int8_t[filesize];
const size_t read = mStream->Read(mCurrent, 1, filesize);
// (read < s) can only happen if the stream was opened in text mode, in which case FileSize() is not reliable
ai_assert(read <= s);
end = limit = &buffer[read-1] + 1;
ai_assert(read <= filesize);
mEnd = mLimit = &mBuffer[read - 1] + 1;
}
private:
std::shared_ptr<IOStream> stream;
int8_t *buffer, *current, *end, *limit;
bool le;
std::shared_ptr<IOStream> mStream;
int8_t *mBuffer;
int8_t *mCurrent;
int8_t *mEnd;
int8_t *mLimit;
bool mLe;
};
// --------------------------------------------------------------------------------------------
// `static` StreamReaders. Their byte order is fixed and they might be a little bit faster.
#ifdef AI_BUILD_BIG_ENDIAN
typedef StreamReader<true> StreamReaderLE;
typedef StreamReader<false> StreamReaderBE;
typedef StreamReader<true> StreamReaderLE;
typedef StreamReader<false> StreamReaderBE;
#else
typedef StreamReader<true> StreamReaderBE;
typedef StreamReader<false> StreamReaderLE;
typedef StreamReader<true> StreamReaderBE;
typedef StreamReader<false> StreamReaderLE;
#endif
// `dynamic` StreamReader. The byte order of the input data is specified in the
// c'tor. This involves runtime branching and might be a little bit slower.
typedef StreamReader<true,true> StreamReaderAny;
typedef StreamReader<true, true> StreamReaderAny;
} // end namespace Assimp

View File

@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -49,29 +47,29 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_METADATA_H_INC
#ifdef __GNUC__
# pragma GCC system_header
#pragma GCC system_header
#endif
#if defined(_MSC_VER) && (_MSC_VER <= 1500)
# include "Compiler/pstdint.h"
#include "Compiler/pstdint.h"
#else
# include <stdint.h>
#include <stdint.h>
#endif
// -------------------------------------------------------------------------------
/**
* Enum used to distinguish data types
*/
// -------------------------------------------------------------------------------
// -------------------------------------------------------------------------------
typedef enum aiMetadataType {
AI_BOOL = 0,
AI_INT32 = 1,
AI_UINT64 = 2,
AI_FLOAT = 3,
AI_DOUBLE = 4,
AI_AISTRING = 5,
AI_BOOL = 0,
AI_INT32 = 1,
AI_UINT64 = 2,
AI_FLOAT = 3,
AI_DOUBLE = 4,
AI_AISTRING = 5,
AI_AIVECTOR3D = 6,
AI_META_MAX = 7,
AI_META_MAX = 7,
#ifndef SWIG
FORCE_32BIT = INT_MAX
@@ -84,10 +82,10 @@ typedef enum aiMetadataType {
*
* The type field uniquely identifies the underlying type of the data field
*/
// -------------------------------------------------------------------------------
// -------------------------------------------------------------------------------
struct aiMetadataEntry {
aiMetadataType mType;
void* mData;
void *mData;
};
#ifdef __cplusplus
@@ -98,15 +96,29 @@ struct aiMetadataEntry {
/**
* Helper functions to get the aiType enum entry for a type
*/
// -------------------------------------------------------------------------------
// -------------------------------------------------------------------------------
inline aiMetadataType GetAiType( bool ) { return AI_BOOL; }
inline aiMetadataType GetAiType( int32_t ) { return AI_INT32; }
inline aiMetadataType GetAiType( uint64_t ) { return AI_UINT64; }
inline aiMetadataType GetAiType( float ) { return AI_FLOAT; }
inline aiMetadataType GetAiType( double ) { return AI_DOUBLE; }
inline aiMetadataType GetAiType( const aiString & ) { return AI_AISTRING; }
inline aiMetadataType GetAiType( const aiVector3D & ) { return AI_AIVECTOR3D; }
inline aiMetadataType GetAiType(bool) {
return AI_BOOL;
}
inline aiMetadataType GetAiType(int32_t) {
return AI_INT32;
}
inline aiMetadataType GetAiType(uint64_t) {
return AI_UINT64;
}
inline aiMetadataType GetAiType(float) {
return AI_FLOAT;
}
inline aiMetadataType GetAiType(double) {
return AI_DOUBLE;
}
inline aiMetadataType GetAiType(const aiString &) {
return AI_AISTRING;
}
inline aiMetadataType GetAiType(const aiVector3D &) {
return AI_AIVECTOR3D;
}
#endif // __cplusplus
@@ -116,17 +128,17 @@ inline aiMetadataType GetAiType( const aiVector3D & ) { return AI_AIVECTOR3D; }
*
* Metadata is a key-value store using string keys and values.
*/
// -------------------------------------------------------------------------------
// -------------------------------------------------------------------------------
struct aiMetadata {
/** Length of the mKeys and mValues arrays, respectively */
unsigned int mNumProperties;
/** Arrays of keys, may not be NULL. Entries in this array may not be NULL as well. */
C_STRUCT aiString* mKeys;
C_STRUCT aiString *mKeys;
/** Arrays of values, may not be NULL. Entries in this array may be NULL if the
* corresponding property key has no assigned value. */
C_STRUCT aiMetadataEntry* mValues;
C_STRUCT aiMetadataEntry *mValues;
#ifdef __cplusplus
@@ -134,71 +146,62 @@ struct aiMetadata {
* @brief The default constructor, set all members to zero by default.
*/
aiMetadata() AI_NO_EXCEPT
: mNumProperties(0)
, mKeys(nullptr)
, mValues(nullptr) {
: mNumProperties(0),
mKeys(nullptr),
mValues(nullptr) {
// empty
}
aiMetadata( const aiMetadata &rhs )
: mNumProperties( rhs.mNumProperties )
, mKeys( nullptr )
, mValues( nullptr ) {
mKeys = new aiString[ mNumProperties ];
for ( size_t i = 0; i < static_cast<size_t>( mNumProperties ); ++i ) {
mKeys[ i ] = rhs.mKeys[ i ];
aiMetadata(const aiMetadata &rhs) :
mNumProperties(rhs.mNumProperties), mKeys(nullptr), mValues(nullptr) {
mKeys = new aiString[mNumProperties];
for (size_t i = 0; i < static_cast<size_t>(mNumProperties); ++i) {
mKeys[i] = rhs.mKeys[i];
}
mValues = new aiMetadataEntry[ mNumProperties ];
for ( size_t i = 0; i < static_cast<size_t>(mNumProperties); ++i ) {
mValues[ i ].mType = rhs.mValues[ i ].mType;
switch ( rhs.mValues[ i ].mType ) {
mValues = new aiMetadataEntry[mNumProperties];
for (size_t i = 0; i < static_cast<size_t>(mNumProperties); ++i) {
mValues[i].mType = rhs.mValues[i].mType;
switch (rhs.mValues[i].mType) {
case AI_BOOL:
mValues[ i ].mData = new bool;
::memcpy( mValues[ i ].mData, rhs.mValues[ i ].mData, sizeof(bool) );
mValues[i].mData = new bool;
::memcpy(mValues[i].mData, rhs.mValues[i].mData, sizeof(bool));
break;
case AI_INT32: {
int32_t v;
::memcpy( &v, rhs.mValues[ i ].mData, sizeof( int32_t ) );
mValues[ i ].mData = new int32_t( v );
}
break;
::memcpy(&v, rhs.mValues[i].mData, sizeof(int32_t));
mValues[i].mData = new int32_t(v);
} break;
case AI_UINT64: {
uint64_t v;
::memcpy( &v, rhs.mValues[ i ].mData, sizeof( uint64_t ) );
mValues[ i ].mData = new uint64_t( v );
}
break;
uint64_t v;
::memcpy(&v, rhs.mValues[i].mData, sizeof(uint64_t));
mValues[i].mData = new uint64_t(v);
} break;
case AI_FLOAT: {
float v;
::memcpy( &v, rhs.mValues[ i ].mData, sizeof( float ) );
mValues[ i ].mData = new float( v );
}
break;
float v;
::memcpy(&v, rhs.mValues[i].mData, sizeof(float));
mValues[i].mData = new float(v);
} break;
case AI_DOUBLE: {
double v;
::memcpy( &v, rhs.mValues[ i ].mData, sizeof( double ) );
mValues[ i ].mData = new double( v );
}
break;
double v;
::memcpy(&v, rhs.mValues[i].mData, sizeof(double));
mValues[i].mData = new double(v);
} break;
case AI_AISTRING: {
aiString v;
rhs.Get<aiString>( mKeys[ i ], v );
mValues[ i ].mData = new aiString( v );
}
break;
aiString v;
rhs.Get<aiString>(mKeys[i], v);
mValues[i].mData = new aiString(v);
} break;
case AI_AIVECTOR3D: {
aiVector3D v;
rhs.Get<aiVector3D>( mKeys[ i ], v );
mValues[ i ].mData = new aiVector3D( v );
}
break;
aiVector3D v;
rhs.Get<aiVector3D>(mKeys[i], v);
mValues[i].mData = new aiVector3D(v);
} break;
#ifndef SWIG
case FORCE_32BIT:
#endif
default:
break;
}
}
}
@@ -206,33 +209,33 @@ struct aiMetadata {
* @brief The destructor.
*/
~aiMetadata() {
delete [] mKeys;
delete[] mKeys;
mKeys = nullptr;
if (mValues) {
// Delete each metadata entry
for (unsigned i=0; i<mNumProperties; ++i) {
void* data = mValues[i].mData;
for (unsigned i = 0; i < mNumProperties; ++i) {
void *data = mValues[i].mData;
switch (mValues[i].mType) {
case AI_BOOL:
delete static_cast< bool* >( data );
delete static_cast<bool *>(data);
break;
case AI_INT32:
delete static_cast< int32_t* >( data );
delete static_cast<int32_t *>(data);
break;
case AI_UINT64:
delete static_cast< uint64_t* >( data );
delete static_cast<uint64_t *>(data);
break;
case AI_FLOAT:
delete static_cast< float* >( data );
delete static_cast<float *>(data);
break;
case AI_DOUBLE:
delete static_cast< double* >( data );
delete static_cast<double *>(data);
break;
case AI_AISTRING:
delete static_cast< aiString* >( data );
delete static_cast<aiString *>(data);
break;
case AI_AIVECTOR3D:
delete static_cast< aiVector3D* >( data );
delete static_cast<aiVector3D *>(data);
break;
#ifndef SWIG
case FORCE_32BIT:
@@ -243,7 +246,7 @@ struct aiMetadata {
}
// Delete the metadata array
delete [] mValues;
delete[] mValues;
mValues = nullptr;
}
}
@@ -252,16 +255,15 @@ struct aiMetadata {
* @brief Allocates property fields + keys.
* @param numProperties Number of requested properties.
*/
static inline
aiMetadata *Alloc( unsigned int numProperties ) {
if ( 0 == numProperties ) {
static inline aiMetadata *Alloc(unsigned int numProperties) {
if (0 == numProperties) {
return nullptr;
}
aiMetadata *data = new aiMetadata;
data->mNumProperties = numProperties;
data->mKeys = new aiString[ data->mNumProperties ]();
data->mValues = new aiMetadataEntry[ data->mNumProperties ]();
data->mKeys = new aiString[data->mNumProperties]();
data->mValues = new aiMetadataEntry[data->mNumProperties]();
return data;
}
@@ -269,44 +271,40 @@ struct aiMetadata {
/**
* @brief Deallocates property fields + keys.
*/
static inline
void Dealloc( aiMetadata *metadata ) {
static inline void Dealloc(aiMetadata *metadata) {
delete metadata;
}
template<typename T>
inline
void Add(const std::string& key, const T& value) {
aiString* new_keys = new aiString[mNumProperties + 1];
aiMetadataEntry* new_values = new aiMetadataEntry[mNumProperties + 1];
template <typename T>
inline void Add(const std::string &key, const T &value) {
aiString *new_keys = new aiString[mNumProperties + 1];
aiMetadataEntry *new_values = new aiMetadataEntry[mNumProperties + 1];
for(unsigned int i = 0; i < mNumProperties; ++i)
{
new_keys[i] = mKeys[i];
new_values[i] = mValues[i];
}
for (unsigned int i = 0; i < mNumProperties; ++i) {
new_keys[i] = mKeys[i];
new_values[i] = mValues[i];
}
delete[] mKeys;
delete[] mValues;
delete[] mKeys;
delete[] mValues;
mKeys = new_keys;
mValues = new_values;
mKeys = new_keys;
mValues = new_values;
mNumProperties++;
mNumProperties++;
Set(mNumProperties - 1, key, value);
}
Set(mNumProperties - 1, key, value);
}
template<typename T>
inline
bool Set( unsigned index, const std::string& key, const T& value ) {
template <typename T>
inline bool Set(unsigned index, const std::string &key, const T &value) {
// In range assertion
if ( index >= mNumProperties ) {
if (index >= mNumProperties) {
return false;
}
// Ensure that we have a valid key.
if ( key.empty() ) {
if (key.empty()) {
return false;
}
@@ -321,73 +319,86 @@ struct aiMetadata {
return true;
}
template<typename T>
inline
bool Get( unsigned index, T& value ) const {
template <typename T>
inline bool Set( const std::string &key, const T &value ) {
if (key.empty()) {
return false;
}
bool result = false;
for (unsigned int i = 0; i < mNumProperties; ++i) {
if (key == mKeys[i].C_Str()) {
Set(i, key, value);
result = true;
break;
}
}
return result;
}
template <typename T>
inline bool Get(unsigned index, T &value) const {
// In range assertion
if ( index >= mNumProperties ) {
if (index >= mNumProperties) {
return false;
}
// Return false if the output data type does
// not match the found value's data type
if ( GetAiType( value ) != mValues[ index ].mType ) {
if (GetAiType(value) != mValues[index].mType) {
return false;
}
// Otherwise, output the found value and
// return true
value = *static_cast<T*>(mValues[index].mData);
value = *static_cast<T *>(mValues[index].mData);
return true;
}
template<typename T>
inline
bool Get( const aiString& key, T& value ) const {
template <typename T>
inline bool Get(const aiString &key, T &value) const {
// Search for the given key
for ( unsigned int i = 0; i < mNumProperties; ++i ) {
if ( mKeys[ i ] == key ) {
return Get( i, value );
for (unsigned int i = 0; i < mNumProperties; ++i) {
if (mKeys[i] == key) {
return Get(i, value);
}
}
return false;
}
template<typename T>
inline
bool Get( const std::string& key, T& value ) const {
template <typename T>
inline bool Get(const std::string &key, T &value) const {
return Get(aiString(key), value);
}
/// Return metadata entry for analyzing it by user.
/// \param [in] pIndex - index of the entry.
/// \param [out] pKey - pointer to the key value.
/// \param [out] pEntry - pointer to the entry: type and value.
/// \return false - if pIndex is out of range, else - true.
inline
bool Get(size_t index, const aiString*& key, const aiMetadataEntry*& entry) const {
if ( index >= mNumProperties ) {
/// Return metadata entry for analyzing it by user.
/// \param [in] pIndex - index of the entry.
/// \param [out] pKey - pointer to the key value.
/// \param [out] pEntry - pointer to the entry: type and value.
/// \return false - if pIndex is out of range, else - true.
inline bool Get(size_t index, const aiString *&key, const aiMetadataEntry *&entry) const {
if (index >= mNumProperties) {
return false;
}
key = &mKeys[index];
entry = &mValues[index];
key = &mKeys[index];
entry = &mValues[index];
return true;
}
return true;
}
/// Check whether there is a metadata entry for the given key.
/// \param [in] Key - the key value value to check for.
inline
bool HasKey(const char* key) {
if ( nullptr == key ) {
inline bool HasKey(const char *key) {
if (nullptr == key) {
return false;
}
// Search for the given key
for (unsigned int i = 0; i < mNumProperties; ++i) {
if ( 0 == strncmp(mKeys[i].C_Str(), key, mKeys[i].length ) ) {
if (0 == strncmp(mKeys[i].C_Str(), key, mKeys[i].length)) {
return true;
}
}
@@ -395,7 +406,6 @@ struct aiMetadata {
}
#endif // __cplusplus
};
#endif // AI_METADATA_H_INC