// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // * Neither the name of NVIDIA CORPORATION nor the names of its // contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. // Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. // Copyright (c) 2001-2004 NovodeX AG. All rights reserved. #ifndef PXPVDSDK_PXPROFILEDATAPARSING_H #define PXPVDSDK_PXPROFILEDATAPARSING_H #include "foundation/Px.h" namespace physx { namespace profile { //Converts datatypes without using type punning. struct BlockParserDataConverter { union { uint8_t mU8[8]; uint16_t mU16[4]; uint32_t mU32[2]; uint64_t mU64[1]; int8_t mI8[8]; int16_t mI16[4]; int32_t mI32[2]; int64_t mI64[1]; float mF32[2]; double mF64[1]; }; template inline TDataType convert() { PX_ASSERT( false ); return TDataType(); } template inline void convert( const TDataType& ) {} }; template<> inline uint8_t BlockParserDataConverter::convert() { return mU8[0]; } template<> inline uint16_t BlockParserDataConverter::convert() { return mU16[0]; } template<> inline uint32_t BlockParserDataConverter::convert() { return mU32[0]; } template<> inline uint64_t BlockParserDataConverter::convert() { return mU64[0]; } template<> inline int8_t BlockParserDataConverter::convert() { return mI8[0]; } template<> inline int16_t BlockParserDataConverter::convert() { return mI16[0]; } template<> inline int32_t BlockParserDataConverter::convert() { return mI32[0]; } template<> inline int64_t BlockParserDataConverter::convert() { return mI64[0]; } template<> inline float BlockParserDataConverter::convert() { return mF32[0]; } template<> inline double BlockParserDataConverter::convert() { return mF64[0]; } template<> inline void BlockParserDataConverter::convert( const uint8_t& inData ) { mU8[0] = inData; } template<> inline void BlockParserDataConverter::convert( const uint16_t& inData ) { mU16[0] = inData; } template<> inline void BlockParserDataConverter::convert( const uint32_t& inData ) { mU32[0] = inData; } template<> inline void BlockParserDataConverter::convert( const uint64_t& inData ) { mU64[0] = inData; } template<> inline void BlockParserDataConverter::convert( const int8_t& inData ) { mI8[0] = inData; } template<> inline void BlockParserDataConverter::convert( const int16_t& inData ) { mI16[0] = inData; } template<> inline void BlockParserDataConverter::convert( const int32_t& inData ) { mI32[0] = inData; } template<> inline void BlockParserDataConverter::convert( const int64_t& inData ) { mI64[0] = inData; } template<> inline void BlockParserDataConverter::convert( const float& inData ) { mF32[0] = inData; } template<> inline void BlockParserDataConverter::convert( const double& inData ) { mF64[0] = inData; } //Handles various details around parsing blocks of uint8_t data. struct BlockParseFunctions { template static inline void swapBytes( uint8_t* inData ) { for ( uint32_t idx = 0; idx < ByteCount/2; ++idx ) { uint32_t endIdx = ByteCount-idx-1; uint8_t theTemp = inData[idx]; inData[idx] = inData[endIdx]; inData[endIdx] = theTemp; } } static inline bool checkLength( const uint8_t* inStart, const uint8_t* inStop, uint32_t inLength ) { return static_cast(inStop - inStart) >= inLength; } //warning work-around template static inline T val(T v) {return v;} template static inline bool parse( const uint8_t*& inStart, const uint8_t* inStop, TDataType& outData ) { if ( checkLength( inStart, inStop, sizeof( TDataType ) ) ) { BlockParserDataConverter theConverter; for ( uint32_t idx =0; idx < sizeof( TDataType ); ++idx ) theConverter.mU8[idx] = inStart[idx]; if ( val(DoSwapBytes)) swapBytes( theConverter.mU8 ); outData = theConverter.convert(); inStart += sizeof( TDataType ); return true; } return false; } template static inline bool parseBlock( const uint8_t*& inStart, const uint8_t* inStop, TDataType* outData, uint32_t inNumItems ) { uint32_t desired = sizeof(TDataType)*inNumItems; if ( checkLength( inStart, inStop, desired ) ) { if ( val(DoSwapBytes) ) { for ( uint32_t item = 0; item < inNumItems; ++item ) { BlockParserDataConverter theConverter; for ( uint32_t idx =0; idx < sizeof( TDataType ); ++idx ) theConverter.mU8[idx] = inStart[idx]; swapBytes( theConverter.mU8 ); outData[item] = theConverter.convert(); inStart += sizeof(TDataType); } } else { uint8_t* target = reinterpret_cast(outData); memmove( target, inStart, desired ); inStart += desired; } return true; } return false; } //In-place byte swapping block template static inline bool parseBlock( uint8_t*& inStart, const uint8_t* inStop, uint32_t inNumItems ) { uint32_t desired = sizeof(TDataType)*inNumItems; if ( checkLength( inStart, inStop, desired ) ) { if ( val(DoSwapBytes) ) { for ( uint32_t item = 0; item < inNumItems; ++item, inStart += sizeof( TDataType ) ) swapBytes( inStart ); //In-place swap. } else inStart += sizeof( TDataType ) * inNumItems; return true; } return false; } }; //Wraps the begin/end keeping track of them. template struct BlockParser { const uint8_t* mBegin; const uint8_t* mEnd; BlockParser( const uint8_t* inBegin=NULL, const uint8_t* inEnd=NULL ) : mBegin( inBegin ) , mEnd( inEnd ) { } inline bool hasMoreData() const { return mBegin != mEnd; } inline bool checkLength( uint32_t inLength ) { return BlockParseFunctions::checkLength( mBegin, mEnd, inLength ); } template inline bool read( TDataType& outDatatype ) { return BlockParseFunctions::parse( mBegin, mEnd, outDatatype ); } template inline bool readBlock( TDataType* outDataPtr, uint32_t inNumItems ) { return BlockParseFunctions::parseBlock( mBegin, mEnd, outDataPtr, inNumItems ); } template inline bool readBlock( uint32_t inNumItems ) { uint8_t* theTempPtr = const_cast(mBegin); bool retval = BlockParseFunctions::parseBlock( theTempPtr, mEnd, inNumItems ); mBegin = theTempPtr; return retval; } uint32_t amountLeft() const { return static_cast( mEnd - mBegin ); } }; //Reads the data without checking for error conditions template inline TDataType blockParserRead( TBlockParserType& inType ) { TDataType retval; inType.read( retval ); return retval; } }} #endif // PXPVDSDK_PXPROFILEDATAPARSING_H