//------------------------------------------------------------------------------
// emFileStream.h
//
// Copyright (C) 2025 Oliver Hamann.
//
// Homepage: http://eaglemode.sourceforge.net/
//
// This program is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public License version 3 as published by the
// Free Software Foundation.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License version 3 for
// more details.
//
// You should have received a copy of the GNU General Public License version 3
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------
#ifndef emFileStream_h
#define emFileStream_h
#ifndef emOwnPtr_h
#include <emCore/emOwnPtr.h>
#endif
#ifndef emStd2_h
#include <emCore/emStd2.h>
#endif
//==============================================================================
//================================ emFileStream ================================
//==============================================================================
class emFileStream {
public:
// Class for a FILE* with an additional buffer. That buffer makes
// reading and writing of many small blocks faster.
emFileStream(FILE * file=NULL, size_t bufSize=8192);
~emFileStream();
void TryOpen(const char * filePath, const char * mode);
void TryClose();
void Close();
bool IsOpen() const;
emInt64 TryTell();
void TrySeek(emInt64 pos);
void TrySeekEnd(emInt64 posFromEnd=0);
void TrySkip(emInt64 offset);
void TryRead(void * buf, size_t len);
size_t TryReadAtMost(void * buf, size_t maxLen);
emString TryReadLine(bool removeLineBreak=false);
int TryReadCharOrEOF();
emInt8 TryReadInt8();
emUInt8 TryReadUInt8();
emInt16 TryReadInt16LE();
emInt16 TryReadInt16BE();
emUInt16 TryReadUInt16LE();
emUInt16 TryReadUInt16BE();
emInt32 TryReadInt32LE();
emInt32 TryReadInt32BE();
emUInt32 TryReadUInt32LE();
emUInt32 TryReadUInt32BE();
emInt64 TryReadInt64LE();
emInt64 TryReadInt64BE();
emUInt64 TryReadUInt64LE();
emUInt64 TryReadUInt64BE();
void TryWrite(const void * buf, size_t len);
void TryWrite(const char * str);
void TryWriteChar(int value);
void TryWriteInt8(emInt8 value);
void TryWriteUInt8(emUInt8 value);
void TryWriteInt16LE(emInt16 value);
void TryWriteInt16BE(emInt16 value);
void TryWriteUInt16LE(emUInt16 value);
void TryWriteUInt16BE(emUInt16 value);
void TryWriteInt32LE(emInt32 value);
void TryWriteInt32BE(emInt32 value);
void TryWriteUInt32LE(emUInt32 value);
void TryWriteUInt32BE(emUInt32 value);
void TryWriteInt64LE(emInt64 value);
void TryWriteInt64BE(emInt64 value);
void TryWriteUInt64LE(emUInt64 value);
void TryWriteUInt64BE(emUInt64 value);
void TryFlush();
FILE * TryGetFile();
private:
void TryFlushAndResetBuffer();
void TryFlushBuffer();
const emByte * TryReadBuffered(size_t size);
emByte * TryWriteBuffered(size_t size);
emByte * TryFillBufferForReading(size_t minSize);
emByte * TryPrepareBufferForWriting(size_t minSize);
FILE * File;
emInt64 FilePos;
emOwnArrayPtr<emByte> Buf;
size_t BufSize;
emByte * BufPos;
emByte * BufReadEnd;
emByte * BufWriteEnd;
};
inline bool emFileStream::IsOpen() const
{
return File!=NULL;
}
inline int emFileStream::TryReadCharOrEOF()
{
emByte * p=BufPos;
if (p>=BufReadEnd) {
p=TryFillBufferForReading(0);
if (p>=BufReadEnd) return -1;
}
BufPos=p+1;
return p[0];
}
inline emInt8 emFileStream::TryReadInt8()
{
return *TryReadBuffered(1);
}
inline emUInt8 emFileStream::TryReadUInt8()
{
return *TryReadBuffered(1);
}
inline emInt16 emFileStream::TryReadInt16LE()
{
return TryReadUInt16LE();
}
inline emInt16 emFileStream::TryReadInt16BE()
{
return TryReadUInt16BE();
}
inline emUInt16 emFileStream::TryReadUInt16LE()
{
const emByte * p=TryReadBuffered(2);
return ((emUInt16)p[0]) | (((emUInt16)p[1])<<8);
}
inline emUInt16 emFileStream::TryReadUInt16BE()
{
const emByte * p=TryReadBuffered(2);
return (((emUInt16)p[0])<<8) | ((emUInt16)p[1]);
}
inline emInt32 emFileStream::TryReadInt32LE()
{
return TryReadUInt32LE();
}
inline emInt32 emFileStream::TryReadInt32BE()
{
return TryReadUInt32BE();
}
inline emInt64 emFileStream::TryReadInt64LE()
{
return TryReadUInt64LE();
}
inline emInt64 emFileStream::TryReadInt64BE()
{
return TryReadUInt64BE();
}
inline void emFileStream::TryWrite(const char * str)
{
TryWrite(str,strlen(str));
}
inline void emFileStream::TryWriteChar(int value)
{
*TryWriteBuffered(1)=(emByte)value;
}
inline void emFileStream::TryWriteInt8(emInt8 value)
{
*TryWriteBuffered(1)=value;
}
inline void emFileStream::TryWriteUInt8(emUInt8 value)
{
*TryWriteBuffered(1)=value;
}
inline void emFileStream::TryWriteInt16LE(emInt16 value)
{
TryWriteUInt16LE(value);
}
inline void emFileStream::TryWriteInt16BE(emInt16 value)
{
TryWriteUInt16BE(value);
}
inline void emFileStream::TryWriteUInt16LE(emUInt16 value)
{
emByte * p=TryWriteBuffered(2);
p[0]=(emByte)value;
p[1]=(emByte)(value>>8);
}
inline void emFileStream::TryWriteUInt16BE(emUInt16 value)
{
emByte * p=TryWriteBuffered(2);
p[0]=(emByte)(value>>8);
p[1]=(emByte)value;
}
inline void emFileStream::TryWriteInt32LE(emInt32 value)
{
TryWriteUInt32LE(value);
}
inline void emFileStream::TryWriteInt32BE(emInt32 value)
{
TryWriteUInt32BE(value);
}
inline void emFileStream::TryWriteInt64LE(emInt64 value)
{
TryWriteUInt64LE(value);
}
inline void emFileStream::TryWriteInt64BE(emInt64 value)
{
TryWriteUInt64BE(value);
}
inline const emByte * emFileStream::TryReadBuffered(size_t size)
{
emByte * p=BufPos;
if (p+size>BufReadEnd) p=TryFillBufferForReading(size);
BufPos=p+size;
return p;
}
inline emByte * emFileStream::TryWriteBuffered(size_t size)
{
emByte * p=BufPos;
if (p+size>BufWriteEnd) p=TryPrepareBufferForWriting(size);
BufPos=p+size;
return p;
}
#endif