| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576 |
- /*
- * Copyright 2010-2016 Branimir Karadzic. All rights reserved.
- * License: https://github.com/bkaradzic/bx#license-bsd-2-clause
- */
- #ifndef BX_READERWRITER_H_HEADER_GUARD
- #define BX_READERWRITER_H_HEADER_GUARD
- #include <alloca.h>
- #include <stdarg.h> // va_list
- #include <stdio.h>
- #include <string.h>
- #include "bx.h"
- #include "allocator.h"
- #include "error.h"
- #include "uint32_t.h"
- #if BX_CRT_MSVC
- # define fseeko64 _fseeki64
- # define ftello64 _ftelli64
- #elif BX_PLATFORM_ANDROID || BX_PLATFORM_BSD || BX_PLATFORM_IOS || BX_PLATFORM_OSX || BX_PLATFORM_QNX
- # define fseeko64 fseeko
- # define ftello64 ftello
- #endif // BX_
- BX_ERROR_RESULT(BX_ERROR_READERWRITER_OPEN, BX_MAKEFOURCC('R', 'W', 0, 1) );
- BX_ERROR_RESULT(BX_ERROR_READERWRITER_READ, BX_MAKEFOURCC('R', 'W', 0, 2) );
- BX_ERROR_RESULT(BX_ERROR_READERWRITER_WRITE, BX_MAKEFOURCC('R', 'W', 0, 3) );
- namespace bx
- {
- struct Whence
- {
- enum Enum
- {
- Begin,
- Current,
- End,
- };
- };
- struct BX_NO_VTABLE ReaderI
- {
- virtual ~ReaderI() = 0;
- virtual int32_t read(void* _data, int32_t _size, Error* _err) = 0;
- };
- inline ReaderI::~ReaderI()
- {
- }
- struct BX_NO_VTABLE WriterI
- {
- virtual ~WriterI() = 0;
- virtual int32_t write(const void* _data, int32_t _size, Error* _err) = 0;
- };
- inline WriterI::~WriterI()
- {
- }
- struct BX_NO_VTABLE SeekerI
- {
- virtual ~SeekerI() = 0;
- virtual int64_t seek(int64_t _offset = 0, Whence::Enum _whence = Whence::Current) = 0;
- };
- inline SeekerI::~SeekerI()
- {
- }
- /// Read data.
- inline int32_t read(ReaderI* _reader, void* _data, int32_t _size, Error* _err = NULL)
- {
- BX_ERROR_SCOPE(_err);
- return _reader->read(_data, _size, _err);
- }
- /// Read value.
- template<typename Ty>
- inline int32_t read(ReaderI* _reader, Ty& _value, Error* _err = NULL)
- {
- BX_ERROR_SCOPE(_err);
- BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) );
- return _reader->read(&_value, sizeof(Ty), _err);
- }
- /// Read value and converts it to host endianess. _fromLittleEndian specifies
- /// underlying stream endianess.
- template<typename Ty>
- inline int32_t readHE(ReaderI* _reader, Ty& _value, bool _fromLittleEndian, Error* _err = NULL)
- {
- BX_ERROR_SCOPE(_err);
- BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) );
- Ty value;
- int32_t result = _reader->read(&value, sizeof(Ty), _err);
- _value = toHostEndian(value, _fromLittleEndian);
- return result;
- }
- /// Write data.
- inline int32_t write(WriterI* _writer, const void* _data, int32_t _size, Error* _err = NULL)
- {
- BX_ERROR_SCOPE(_err);
- return _writer->write(_data, _size, _err);
- }
- /// Write repeat the same value.
- inline int32_t writeRep(WriterI* _writer, uint8_t _byte, int32_t _size, Error* _err = NULL)
- {
- BX_ERROR_SCOPE(_err);
- const uint32_t tmp0 = uint32_sels(64 - _size, 64, _size);
- const uint32_t tmp1 = uint32_sels(256 - _size, 256, tmp0);
- const uint32_t blockSize = uint32_sels(1024 - _size, 1024, tmp1);
- uint8_t* temp = (uint8_t*)alloca(blockSize);
- memset(temp, _byte, blockSize);
- int32_t size = 0;
- while (0 < _size)
- {
- int32_t bytes = write(_writer, temp, uint32_min(blockSize, _size), _err);
- size += bytes;
- _size -= bytes;
- }
- return size;
- }
- /// Write value.
- template<typename Ty>
- inline int32_t write(WriterI* _writer, const Ty& _value, Error* _err = NULL)
- {
- BX_ERROR_SCOPE(_err);
- BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) );
- return _writer->write(&_value, sizeof(Ty), _err);
- }
- /// Write value as little endian.
- template<typename Ty>
- inline int32_t writeLE(WriterI* _writer, const Ty& _value, Error* _err = NULL)
- {
- BX_ERROR_SCOPE(_err);
- BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) );
- Ty value = toLittleEndian(_value);
- int32_t result = _writer->write(&value, sizeof(Ty), _err);
- return result;
- }
- /// Write value as big endian.
- template<typename Ty>
- inline int32_t writeBE(WriterI* _writer, const Ty& _value, Error* _err = NULL)
- {
- BX_ERROR_SCOPE(_err);
- BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) );
- Ty value = toBigEndian(_value);
- int32_t result = _writer->write(&value, sizeof(Ty), _err);
- return result;
- }
- /// Write formated string.
- inline int32_t writePrintf(WriterI* _writer, const char* _format, ...)
- {
- va_list argList;
- va_start(argList, _format);
- char temp[2048];
- char* out = temp;
- int32_t max = sizeof(temp);
- int32_t len = vsnprintf(out, max, _format, argList);
- if (len > max)
- {
- out = (char*)alloca(len);
- len = vsnprintf(out, len, _format, argList);
- }
- int32_t size = write(_writer, out, len);
- va_end(argList);
- return size;
- }
- /// Skip _offset bytes forward.
- inline int64_t skip(SeekerI* _seeker, int64_t _offset)
- {
- return _seeker->seek(_offset, Whence::Current);
- }
- /// Seek to any position in file.
- inline int64_t seek(SeekerI* _seeker, int64_t _offset = 0, Whence::Enum _whence = Whence::Current)
- {
- return _seeker->seek(_offset, _whence);
- }
- /// Returns size of file.
- inline int64_t getSize(SeekerI* _seeker)
- {
- int64_t offset = _seeker->seek();
- int64_t size = _seeker->seek(0, Whence::End);
- _seeker->seek(offset, Whence::Begin);
- return size;
- }
- struct BX_NO_VTABLE ReaderSeekerI : public ReaderI, public SeekerI
- {
- };
- /// Peek data.
- inline int32_t peek(ReaderSeekerI* _reader, void* _data, int32_t _size, Error* _err = NULL)
- {
- BX_ERROR_SCOPE(_err);
- int64_t offset = bx::seek(_reader);
- int32_t size = _reader->read(_data, _size, _err);
- bx::seek(_reader, offset, bx::Whence::Begin);
- return size;
- }
- /// Peek value.
- template<typename Ty>
- inline int32_t peek(ReaderSeekerI* _reader, Ty& _value, Error* _err = NULL)
- {
- BX_ERROR_SCOPE(_err);
- BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) );
- return peek(_reader, &_value, sizeof(Ty), _err);
- }
- struct BX_NO_VTABLE WriterSeekerI : public WriterI, public SeekerI
- {
- };
- struct BX_NO_VTABLE ReaderOpenI
- {
- virtual ~ReaderOpenI() = 0;
- virtual bool open(const char* _filePath, Error* _err) = 0;
- };
- inline ReaderOpenI::~ReaderOpenI()
- {
- }
- struct BX_NO_VTABLE WriterOpenI
- {
- virtual ~WriterOpenI() = 0;
- virtual bool open(const char* _filePath, bool _append, Error* _err) = 0;
- };
- inline WriterOpenI::~WriterOpenI()
- {
- }
- struct BX_NO_VTABLE CloserI
- {
- virtual ~CloserI() = 0;
- virtual void close() = 0;
- };
- inline CloserI::~CloserI()
- {
- }
- struct BX_NO_VTABLE FileReaderI : public ReaderOpenI, public CloserI, public ReaderSeekerI
- {
- };
- struct BX_NO_VTABLE FileWriterI : public WriterOpenI, public CloserI, public WriterSeekerI
- {
- };
- inline bool open(ReaderOpenI* _reader, const char* _filePath, Error* _err = NULL)
- {
- BX_ERROR_USE_TEMP_WHEN_NULL(_err);
- return _reader->open(_filePath, _err);
- }
- inline bool open(WriterOpenI* _writer, const char* _filePath, bool _append = false, Error* _err = NULL)
- {
- BX_ERROR_USE_TEMP_WHEN_NULL(_err);
- return _writer->open(_filePath, _append, _err);
- }
- inline void close(CloserI* _reader)
- {
- _reader->close();
- }
- struct BX_NO_VTABLE MemoryBlockI
- {
- virtual void* more(uint32_t _size = 0) = 0;
- virtual uint32_t getSize() = 0;
- };
- class StaticMemoryBlock : public MemoryBlockI
- {
- public:
- StaticMemoryBlock(void* _data, uint32_t _size)
- : m_data(_data)
- , m_size(_size)
- {
- }
- virtual ~StaticMemoryBlock()
- {
- }
- virtual void* more(uint32_t /*_size*/ = 0) BX_OVERRIDE
- {
- return m_data;
- }
- virtual uint32_t getSize() BX_OVERRIDE
- {
- return m_size;
- }
- private:
- void* m_data;
- uint32_t m_size;
- };
- class MemoryBlock : public MemoryBlockI
- {
- public:
- MemoryBlock(AllocatorI* _allocator)
- : m_allocator(_allocator)
- , m_data(NULL)
- , m_size(0)
- {
- }
- virtual ~MemoryBlock()
- {
- BX_FREE(m_allocator, m_data);
- }
- virtual void* more(uint32_t _size = 0) BX_OVERRIDE
- {
- if (0 < _size)
- {
- m_size += _size;
- m_data = BX_REALLOC(m_allocator, m_data, m_size);
- }
- return m_data;
- }
- virtual uint32_t getSize() BX_OVERRIDE
- {
- return m_size;
- }
- private:
- AllocatorI* m_allocator;
- void* m_data;
- uint32_t m_size;
- };
- class SizerWriter : public WriterSeekerI
- {
- public:
- SizerWriter()
- : m_pos(0)
- , m_top(0)
- {
- }
- virtual ~SizerWriter()
- {
- }
- virtual int64_t seek(int64_t _offset = 0, Whence::Enum _whence = Whence::Current) BX_OVERRIDE
- {
- switch (_whence)
- {
- case Whence::Begin:
- m_pos = int64_clamp(_offset, 0, m_top);
- break;
- case Whence::Current:
- m_pos = int64_clamp(m_pos + _offset, 0, m_top);
- break;
- case Whence::End:
- m_pos = int64_clamp(m_top - _offset, 0, m_top);
- break;
- }
- return m_pos;
- }
- virtual int32_t write(const void* /*_data*/, int32_t _size, Error* _err) BX_OVERRIDE
- {
- BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors.");
- int32_t morecore = int32_t(m_pos - m_top) + _size;
- if (0 < morecore)
- {
- m_top += morecore;
- }
- int64_t remainder = m_top-m_pos;
- int32_t size = uint32_min(_size, uint32_t(int64_min(remainder, INT32_MAX) ) );
- m_pos += size;
- if (size != _size)
- {
- BX_ERROR_SET(_err, BX_ERROR_READERWRITER_WRITE, "SizerWriter: write truncated.");
- }
- return size;
- }
- private:
- int64_t m_pos;
- int64_t m_top;
- };
- class MemoryReader : public ReaderSeekerI
- {
- public:
- MemoryReader(const void* _data, uint32_t _size)
- : m_data( (const uint8_t*)_data)
- , m_pos(0)
- , m_top(_size)
- {
- }
- virtual ~MemoryReader()
- {
- }
- virtual int64_t seek(int64_t _offset, Whence::Enum _whence) BX_OVERRIDE
- {
- switch (_whence)
- {
- case Whence::Begin:
- m_pos = int64_clamp(_offset, 0, m_top);
- break;
- case Whence::Current:
- m_pos = int64_clamp(m_pos + _offset, 0, m_top);
- break;
- case Whence::End:
- m_pos = int64_clamp(m_top - _offset, 0, m_top);
- break;
- }
- return m_pos;
- }
- virtual int32_t read(void* _data, int32_t _size, Error* _err) BX_OVERRIDE
- {
- BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors.");
- int64_t remainder = m_top-m_pos;
- int32_t size = uint32_min(_size, uint32_t(int64_min(remainder, INT32_MAX) ) );
- memcpy(_data, &m_data[m_pos], size);
- m_pos += size;
- if (size != _size)
- {
- BX_ERROR_SET(_err, BX_ERROR_READERWRITER_READ, "MemoryReader: read truncated.");
- }
- return size;
- }
- const uint8_t* getDataPtr() const
- {
- return &m_data[m_pos];
- }
- int64_t getPos() const
- {
- return m_pos;
- }
- int64_t remaining() const
- {
- return m_top-m_pos;
- }
- private:
- const uint8_t* m_data;
- int64_t m_pos;
- int64_t m_top;
- };
- class MemoryWriter : public WriterSeekerI
- {
- public:
- MemoryWriter(MemoryBlockI* _memBlock)
- : m_memBlock(_memBlock)
- , m_data(NULL)
- , m_pos(0)
- , m_top(0)
- , m_size(0)
- {
- }
- virtual ~MemoryWriter()
- {
- }
- virtual int64_t seek(int64_t _offset = 0, Whence::Enum _whence = Whence::Current) BX_OVERRIDE
- {
- switch (_whence)
- {
- case Whence::Begin:
- m_pos = int64_clamp(_offset, 0, m_top);
- break;
- case Whence::Current:
- m_pos = int64_clamp(m_pos + _offset, 0, m_top);
- break;
- case Whence::End:
- m_pos = int64_clamp(m_top - _offset, 0, m_top);
- break;
- }
- return m_pos;
- }
- virtual int32_t write(const void* _data, int32_t _size, Error* _err) BX_OVERRIDE
- {
- BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors.");
- int32_t morecore = int32_t(m_pos - m_size) + _size;
- if (0 < morecore)
- {
- morecore = BX_ALIGN_MASK(morecore, 0xfff);
- m_data = (uint8_t*)m_memBlock->more(morecore);
- m_size = m_memBlock->getSize();
- }
- int64_t remainder = m_size-m_pos;
- int32_t size = uint32_min(_size, uint32_t(int64_min(remainder, INT32_MAX) ) );
- memcpy(&m_data[m_pos], _data, size);
- m_pos += size;
- m_top = int64_max(m_top, m_pos);
- if (size != _size)
- {
- BX_ERROR_SET(_err, BX_ERROR_READERWRITER_WRITE, "MemoryWriter: write truncated.");
- }
- return size;
- }
- private:
- MemoryBlockI* m_memBlock;
- uint8_t* m_data;
- int64_t m_pos;
- int64_t m_top;
- int64_t m_size;
- };
- class StaticMemoryBlockWriter : public MemoryWriter
- {
- public:
- StaticMemoryBlockWriter(void* _data, uint32_t _size)
- : MemoryWriter(&m_smb)
- , m_smb(_data, _size)
- {
- }
- ~StaticMemoryBlockWriter()
- {
- }
- private:
- StaticMemoryBlock m_smb;
- };
- } // namespace bx
- #endif // BX_READERWRITER_H_HEADER_GUARD
|