450 lines
11 KiB
C++
450 lines
11 KiB
C++
//
|
|
// 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.
|
|
|
|
#ifndef PSFILEBUFFER_PSMEMORYBUFFER_H
|
|
#define PSFILEBUFFER_PSMEMORYBUFFER_H
|
|
|
|
#include "Ps.h"
|
|
#include "PsUserAllocated.h"
|
|
#include "PsAlignedMalloc.h"
|
|
#include "filebuf/PxFileBuf.h"
|
|
#include "foundation/PxAssert.h"
|
|
|
|
namespace physx
|
|
{
|
|
namespace general_PxIOStream2
|
|
{
|
|
using namespace shdfnd;
|
|
|
|
const uint32_t BUFFER_SIZE_DEFAULT = 4096;
|
|
|
|
//Use this class if you want to use your own allocator
|
|
template<class Allocator>
|
|
class PxMemoryBufferBase : public PxFileBuf, public Allocator
|
|
{
|
|
PX_NOCOPY(PxMemoryBufferBase)
|
|
void init(const void *readMem, uint32_t readLen)
|
|
{
|
|
mAllocator = this;
|
|
|
|
mReadBuffer = mReadLoc = static_cast<const uint8_t *>(readMem);
|
|
mReadStop = &mReadLoc[readLen];
|
|
|
|
mWriteBuffer = mWriteLoc = mWriteStop = NULL;
|
|
mWriteBufferSize = 0;
|
|
mDefaultWriteBufferSize = BUFFER_SIZE_DEFAULT;
|
|
|
|
mOpenMode = OPEN_READ_ONLY;
|
|
mSeekType = SEEKABLE_READ;
|
|
}
|
|
|
|
void init(uint32_t defaultWriteBufferSize)
|
|
{
|
|
mAllocator = this;
|
|
|
|
mReadBuffer = mReadLoc = mReadStop = NULL;
|
|
|
|
mWriteBuffer = mWriteLoc = mWriteStop = NULL;
|
|
mWriteBufferSize = 0;
|
|
mDefaultWriteBufferSize = defaultWriteBufferSize;
|
|
|
|
mOpenMode = OPEN_READ_WRITE_NEW;
|
|
mSeekType = SEEKABLE_READWRITE;
|
|
}
|
|
|
|
public:
|
|
PxMemoryBufferBase(const void *readMem,uint32_t readLen)
|
|
{
|
|
init(readMem, readLen);
|
|
}
|
|
|
|
PxMemoryBufferBase(const void *readMem,uint32_t readLen, const Allocator &alloc): Allocator(alloc)
|
|
{
|
|
init(readMem, readLen);
|
|
}
|
|
|
|
PxMemoryBufferBase(uint32_t defaultWriteBufferSize = BUFFER_SIZE_DEFAULT)
|
|
{
|
|
init(defaultWriteBufferSize);
|
|
}
|
|
|
|
PxMemoryBufferBase(uint32_t defaultWriteBufferSize, const Allocator &alloc): Allocator(alloc)
|
|
{
|
|
init(defaultWriteBufferSize);
|
|
}
|
|
|
|
virtual ~PxMemoryBufferBase(void)
|
|
{
|
|
reset();
|
|
}
|
|
|
|
void setAllocator(Allocator *allocator)
|
|
{
|
|
mAllocator = allocator;
|
|
}
|
|
|
|
void initWriteBuffer(uint32_t size)
|
|
{
|
|
if ( mWriteBuffer == NULL )
|
|
{
|
|
if ( size < mDefaultWriteBufferSize ) size = mDefaultWriteBufferSize;
|
|
mWriteBuffer = static_cast<uint8_t *>(mAllocator->allocate(size));
|
|
PX_ASSERT( mWriteBuffer );
|
|
mWriteLoc = mWriteBuffer;
|
|
mWriteStop = &mWriteBuffer[size];
|
|
mWriteBufferSize = size;
|
|
mReadBuffer = mWriteBuffer;
|
|
mReadStop = &mWriteBuffer[size];
|
|
mReadLoc = mWriteBuffer;
|
|
}
|
|
}
|
|
|
|
void reset(void)
|
|
{
|
|
mAllocator->deallocate(mWriteBuffer);
|
|
mWriteBuffer = NULL;
|
|
mWriteBufferSize = 0;
|
|
mWriteLoc = NULL;
|
|
mWriteStop = NULL;
|
|
mReadBuffer = NULL;
|
|
mReadStop = NULL;
|
|
mReadLoc = NULL;
|
|
}
|
|
|
|
virtual OpenMode getOpenMode(void) const
|
|
{
|
|
return mOpenMode;
|
|
}
|
|
|
|
|
|
SeekType isSeekable(void) const
|
|
{
|
|
return mSeekType;
|
|
}
|
|
|
|
virtual uint32_t read(void* buffer, uint32_t size)
|
|
{
|
|
if ( (mReadLoc+size) > mReadStop )
|
|
{
|
|
size = uint32_t(mReadStop - mReadLoc);
|
|
}
|
|
if ( size != 0 )
|
|
{
|
|
memmove(buffer,mReadLoc,size);
|
|
mReadLoc+=size;
|
|
}
|
|
return size;
|
|
}
|
|
|
|
virtual uint32_t peek(void* buffer, uint32_t size)
|
|
{
|
|
if ( (mReadLoc+size) > mReadStop )
|
|
{
|
|
size = uint32_t(mReadStop - mReadLoc);
|
|
}
|
|
if ( size != 0 )
|
|
{
|
|
memmove(buffer,mReadLoc,size);
|
|
}
|
|
return size;
|
|
}
|
|
|
|
virtual uint32_t write(const void* buffer, uint32_t size)
|
|
{
|
|
PX_ASSERT( mOpenMode == OPEN_READ_WRITE_NEW );
|
|
if ( mOpenMode == OPEN_READ_WRITE_NEW )
|
|
{
|
|
if ( (mWriteLoc+size) > mWriteStop )
|
|
growWriteBuffer(size);
|
|
memmove(mWriteLoc,buffer,size);
|
|
mWriteLoc+=size;
|
|
mReadStop = mWriteLoc;
|
|
}
|
|
else
|
|
{
|
|
size = 0;
|
|
}
|
|
return size;
|
|
}
|
|
|
|
PX_INLINE const uint8_t * getReadLoc(void) const { return mReadLoc; }
|
|
PX_INLINE void advanceReadLoc(uint32_t len)
|
|
{
|
|
PX_ASSERT(mReadBuffer);
|
|
if ( mReadBuffer )
|
|
{
|
|
mReadLoc+=len;
|
|
if ( mReadLoc >= mReadStop )
|
|
{
|
|
mReadLoc = mReadStop;
|
|
}
|
|
}
|
|
}
|
|
|
|
virtual uint32_t tellRead(void) const
|
|
{
|
|
uint32_t ret=0;
|
|
|
|
if ( mReadBuffer )
|
|
{
|
|
ret = uint32_t(mReadLoc-mReadBuffer);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
virtual uint32_t tellWrite(void) const
|
|
{
|
|
return uint32_t(mWriteLoc-mWriteBuffer);
|
|
}
|
|
|
|
virtual uint32_t seekRead(uint32_t loc)
|
|
{
|
|
uint32_t ret = 0;
|
|
PX_ASSERT(mReadBuffer);
|
|
if ( mReadBuffer )
|
|
{
|
|
mReadLoc = &mReadBuffer[loc];
|
|
if ( mReadLoc >= mReadStop )
|
|
{
|
|
mReadLoc = mReadStop;
|
|
}
|
|
ret = uint32_t(mReadLoc-mReadBuffer);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
virtual uint32_t seekWrite(uint32_t loc)
|
|
{
|
|
uint32_t ret = 0;
|
|
PX_ASSERT( mOpenMode == OPEN_READ_WRITE_NEW );
|
|
if ( mWriteBuffer )
|
|
{
|
|
if ( loc > mWriteBufferSize )
|
|
{
|
|
mWriteLoc = mWriteStop;
|
|
growWriteBuffer(loc - mWriteBufferSize);
|
|
}
|
|
mWriteLoc = &mWriteBuffer[loc];
|
|
ret = uint32_t(mWriteLoc-mWriteBuffer);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
virtual void flush(void)
|
|
{
|
|
|
|
}
|
|
|
|
virtual uint32_t getFileLength(void) const
|
|
{
|
|
uint32_t ret = 0;
|
|
if ( mReadBuffer )
|
|
{
|
|
ret = uint32_t(mReadStop-mReadBuffer);
|
|
}
|
|
else if ( mWriteBuffer )
|
|
{
|
|
ret = uint32_t(mWriteLoc-mWriteBuffer);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
uint32_t getWriteBufferSize(void) const
|
|
{
|
|
return uint32_t(mWriteLoc-mWriteBuffer);
|
|
}
|
|
|
|
void setWriteLoc(uint8_t *writeLoc)
|
|
{
|
|
PX_ASSERT(writeLoc >= mWriteBuffer && writeLoc < mWriteStop );
|
|
mWriteLoc = writeLoc;
|
|
mReadStop = mWriteLoc;
|
|
}
|
|
|
|
const uint8_t * getWriteBuffer(void) const
|
|
{
|
|
return mWriteBuffer;
|
|
}
|
|
|
|
/**
|
|
* Attention: if you use aligned allocator you cannot free memory with PX_FREE macros instead use deallocate method from base
|
|
*/
|
|
uint8_t * getWriteBufferOwnership(uint32_t &dataLen) // return the write buffer, and zero it out, the caller is taking ownership of the memory
|
|
{
|
|
uint8_t *ret = mWriteBuffer;
|
|
dataLen = uint32_t(mWriteLoc-mWriteBuffer);
|
|
mWriteBuffer = NULL;
|
|
mWriteLoc = NULL;
|
|
mWriteStop = NULL;
|
|
mWriteBufferSize = 0;
|
|
return ret;
|
|
}
|
|
|
|
|
|
void alignRead(uint32_t a)
|
|
{
|
|
uint32_t loc = tellRead();
|
|
uint32_t aloc = ((loc+(a-1))/a)*a;
|
|
if ( aloc != loc )
|
|
{
|
|
seekRead(aloc);
|
|
}
|
|
}
|
|
|
|
void alignWrite(uint32_t a)
|
|
{
|
|
uint32_t loc = tellWrite();
|
|
uint32_t aloc = ((loc+(a-1))/a)*a;
|
|
if ( aloc != loc )
|
|
{
|
|
seekWrite(aloc);
|
|
}
|
|
}
|
|
|
|
private:
|
|
|
|
|
|
// double the size of the write buffer or at least as large as the 'size' value passed in.
|
|
void growWriteBuffer(uint32_t size)
|
|
{
|
|
if ( mWriteBuffer == NULL )
|
|
{
|
|
if ( size < mDefaultWriteBufferSize ) size = mDefaultWriteBufferSize;
|
|
initWriteBuffer(size);
|
|
}
|
|
else
|
|
{
|
|
uint32_t oldWriteIndex = uint32_t(mWriteLoc - mWriteBuffer);
|
|
uint32_t newSize = mWriteBufferSize*2;
|
|
uint32_t avail = newSize-oldWriteIndex;
|
|
if ( size >= avail ) newSize = newSize+size;
|
|
uint8_t *writeBuffer = static_cast<uint8_t *>(mAllocator->allocate(newSize));
|
|
PX_ASSERT( writeBuffer );
|
|
memmove(writeBuffer,mWriteBuffer,mWriteBufferSize);
|
|
mAllocator->deallocate(mWriteBuffer);
|
|
mWriteBuffer = writeBuffer;
|
|
mWriteBufferSize = newSize;
|
|
mWriteLoc = &mWriteBuffer[oldWriteIndex];
|
|
mWriteStop = &mWriteBuffer[mWriteBufferSize];
|
|
uint32_t oldReadLoc = uint32_t(mReadLoc-mReadBuffer);
|
|
mReadBuffer = mWriteBuffer;
|
|
mReadStop = mWriteLoc;
|
|
mReadLoc = &mReadBuffer[oldReadLoc];
|
|
}
|
|
}
|
|
|
|
const uint8_t *mReadBuffer;
|
|
const uint8_t *mReadLoc;
|
|
const uint8_t *mReadStop;
|
|
|
|
uint8_t *mWriteBuffer;
|
|
uint8_t *mWriteLoc;
|
|
uint8_t *mWriteStop;
|
|
|
|
uint32_t mWriteBufferSize;
|
|
uint32_t mDefaultWriteBufferSize;
|
|
Allocator *mAllocator;
|
|
OpenMode mOpenMode;
|
|
SeekType mSeekType;
|
|
|
|
};
|
|
|
|
class PxMemoryBufferAllocator
|
|
{
|
|
public:
|
|
PxMemoryBufferAllocator(uint32_t a = 0) : alignment(a) {}
|
|
|
|
virtual void * allocate(uint32_t size)
|
|
{
|
|
switch(alignment)
|
|
{
|
|
case 0:
|
|
return PX_ALLOC(size, PX_DEBUG_EXP("PxMemoryBufferAllocator"));
|
|
case 16 :
|
|
return physx::AlignedAllocator<16>().allocate(size, __FILE__, __LINE__);
|
|
case 32 :
|
|
return physx::AlignedAllocator<32>().allocate(size, __FILE__, __LINE__);
|
|
case 64 :
|
|
return physx::AlignedAllocator<64>().allocate(size, __FILE__, __LINE__);
|
|
case 128 :
|
|
return physx::AlignedAllocator<128>().allocate(size, __FILE__, __LINE__);
|
|
default :
|
|
PX_ASSERT(0);
|
|
}
|
|
return NULL;
|
|
}
|
|
virtual void deallocate(void *mem)
|
|
{
|
|
switch(alignment)
|
|
{
|
|
case 0:
|
|
PX_FREE(mem);
|
|
break;
|
|
case 16 :
|
|
physx::AlignedAllocator<16>().deallocate(mem);
|
|
break;
|
|
case 32 :
|
|
physx::AlignedAllocator<32>().deallocate(mem);
|
|
break;
|
|
case 64 :
|
|
physx::AlignedAllocator<64>().deallocate(mem);
|
|
break;
|
|
case 128 :
|
|
physx::AlignedAllocator<128>().deallocate(mem);
|
|
break;
|
|
default :
|
|
PX_ASSERT(0);
|
|
}
|
|
}
|
|
virtual ~PxMemoryBufferAllocator(void) {}
|
|
private:
|
|
PxMemoryBufferAllocator& operator=(const PxMemoryBufferAllocator&);
|
|
|
|
const uint32_t alignment;
|
|
};
|
|
|
|
//Use this class if you want to use PhysX memory allocator
|
|
class PsMemoryBuffer: public PxMemoryBufferBase<PxMemoryBufferAllocator>, public UserAllocated
|
|
{
|
|
PX_NOCOPY(PsMemoryBuffer)
|
|
typedef PxMemoryBufferBase<PxMemoryBufferAllocator> BaseClass;
|
|
|
|
public:
|
|
PsMemoryBuffer(const void *readMem,uint32_t readLen): BaseClass(readMem, readLen) {}
|
|
PsMemoryBuffer(const void *readMem,uint32_t readLen, uint32_t alignment): BaseClass(readMem, readLen, PxMemoryBufferAllocator(alignment)) {}
|
|
|
|
PsMemoryBuffer(uint32_t defaultWriteBufferSize=BUFFER_SIZE_DEFAULT): BaseClass(defaultWriteBufferSize) {}
|
|
PsMemoryBuffer(uint32_t defaultWriteBufferSize,uint32_t alignment): BaseClass(defaultWriteBufferSize, PxMemoryBufferAllocator(alignment)) {}
|
|
};
|
|
|
|
}
|
|
using namespace general_PxIOStream2;
|
|
}
|
|
|
|
#endif // PSFILEBUFFER_PSMEMORYBUFFER_H
|
|
|