include/filebuf/PxFileBuf.h

File members: include/filebuf/PxFileBuf.h

// 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-2024 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 PSFILEBUFFER_PXFILEBUF_H
#define PSFILEBUFFER_PXFILEBUF_H

#include "foundation/PxSimpleTypes.h"
#include "foundation/PxAllocator.h"

#if !PX_DOXYGEN
namespace physx
{

namespace general_PxIOStream2
{
#endif

PX_PUSH_PACK_DEFAULT

class PxFileBuf
{
public:

    enum EndianMode
    {
        ENDIAN_NONE     = 0, // do no conversion for endian mode
        ENDIAN_BIG      = 1, // always read/write data as natively big endian (Power PC, etc.)
        ENDIAN_LITTLE   = 2 // always read/write data as natively little endian (Intel, etc.) Default Behavior!
    };

    PxFileBuf(EndianMode mode=ENDIAN_LITTLE)
    {
        setEndianMode(mode);
    }

    virtual ~PxFileBuf(void)
    {

    }

    static const uint32_t STREAM_SEEK_END=0xFFFFFFFF;

    enum OpenMode
    {
        OPEN_FILE_NOT_FOUND,
        OPEN_READ_ONLY,                 // open file buffer stream for read only access
        OPEN_WRITE_ONLY,                // open file buffer stream for write only access
        OPEN_READ_WRITE_NEW,            // open a new file for both read/write access
        OPEN_READ_WRITE_EXISTING        // open an existing file for both read/write access
    };

    virtual OpenMode    getOpenMode(void) const  = 0;

    bool isOpen(void) const
    {
        return getOpenMode()!=OPEN_FILE_NOT_FOUND;
    }

    enum SeekType
    {
        SEEKABLE_NO         = 0,
        SEEKABLE_READ       = 0x1,
        SEEKABLE_WRITE      = 0x2,
        SEEKABLE_READWRITE  = 0x3
    };

    virtual SeekType isSeekable(void) const = 0;

    void    setEndianMode(EndianMode e)
    {
        mEndianMode = e;
        if ( (e==ENDIAN_BIG && !isBigEndian() ) ||
             (e==ENDIAN_LITTLE && isBigEndian() ) )
        {
            mEndianSwap = true;
        }
        else
        {
            mEndianSwap = false;
        }
    }

    EndianMode  getEndianMode(void) const
    {
        return mEndianMode;
    }

    virtual uint32_t getFileLength(void) const = 0;

    virtual uint32_t    seekRead(uint32_t loc) = 0;

    virtual uint32_t    seekWrite(uint32_t loc) = 0;

    virtual uint32_t    read(void *mem,uint32_t len) = 0;

    virtual uint32_t    peek(void *mem,uint32_t len) = 0;

    virtual uint32_t    write(const void *mem,uint32_t len) = 0;

    virtual uint32_t    tellRead(void) const = 0;

    virtual uint32_t    tellWrite(void) const = 0;

    virtual void    flush(void) = 0;

    virtual void close(void) {}

    void release(void)
    {
        PX_DELETE_THIS;
    }

    static PX_INLINE bool isBigEndian()
     {
       int32_t i = 1;
        return *(reinterpret_cast<char*>(&i))==0;
    }

    PX_INLINE void swap2Bytes(void* _data) const
    {
        char *data = static_cast<char *>(_data);
        char one_byte;
        one_byte = data[0]; data[0] = data[1]; data[1] = one_byte;
    }

    PX_INLINE void swap4Bytes(void* _data) const
    {
        char *data = static_cast<char *>(_data);
        char one_byte;
        one_byte = data[0]; data[0] = data[3]; data[3] = one_byte;
        one_byte = data[1]; data[1] = data[2]; data[2] = one_byte;
    }

    PX_INLINE void swap8Bytes(void *_data) const
    {
        char *data = static_cast<char *>(_data);
        char one_byte;
        one_byte = data[0]; data[0] = data[7]; data[7] = one_byte;
        one_byte = data[1]; data[1] = data[6]; data[6] = one_byte;
        one_byte = data[2]; data[2] = data[5]; data[5] = one_byte;
        one_byte = data[3]; data[3] = data[4]; data[4] = one_byte;
    }

    PX_INLINE void storeDword(uint32_t v)
    {
        if ( mEndianSwap )
            swap4Bytes(&v);

        write(&v,sizeof(v));
    }

    PX_INLINE void storeFloat(float v)
    {
        if ( mEndianSwap )
            swap4Bytes(&v);
        write(&v,sizeof(v));
    }

    PX_INLINE void storeDouble(double v)
    {
        if ( mEndianSwap )
            swap8Bytes(&v);
        write(&v,sizeof(v));
    }

    PX_INLINE  void storeByte(uint8_t b)
    {
        write(&b,sizeof(b));
    }

    PX_INLINE void storeWord(uint16_t w)
    {
        if ( mEndianSwap )
            swap2Bytes(&w);
        write(&w,sizeof(w));
    }

    uint8_t readByte(void)
    {
        uint8_t v=0;
        read(&v,sizeof(v));
        return v;
    }

    uint16_t readWord(void)
    {
        uint16_t v=0;
        read(&v,sizeof(v));
        if ( mEndianSwap )
            swap2Bytes(&v);
        return v;
    }

    uint32_t readDword(void)
    {
        uint32_t v=0;
        read(&v,sizeof(v));
        if ( mEndianSwap )
            swap4Bytes(&v);
        return v;
    }

    float readFloat(void)
    {
        float v=0;
        read(&v,sizeof(v));
        if ( mEndianSwap )
            swap4Bytes(&v);
        return v;
    }

    double readDouble(void)
    {
        double v=0;
        read(&v,sizeof(v));
        if ( mEndianSwap )
            swap8Bytes(&v);
        return v;
    }

private:
    bool        mEndianSwap;    // whether or not the endian should be swapped on the current platform
    EndianMode  mEndianMode;    // the current endian mode behavior for the stream
};

PX_POP_PACK

#if !PX_DOXYGEN
} // end of namespace

using namespace general_PxIOStream2;

namespace general_PxIOStream = general_PxIOStream2;

} // end of namespace
#endif

#endif // PSFILEBUFFER_PXFILEBUF_H