Space-Project/dependencies/physx-4.1/source/filebuf/include/PsMemoryBuffer.h
2021-01-16 17:11:39 +01:00

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