#pragma once #include #include #include "lc_math.h" #define LC_FOURCC(ch0, ch1, ch2, ch3) (quint32)((quint32)(quint8)(ch0) | ((quint32)(quint8)(ch1) << 8) | \ ((quint32)(quint8)(ch2) << 16) | ((quint32)(quint8)(ch3) << 24 )) class lcFile { public: lcFile() { } virtual ~lcFile() { } lcFile(const lcFile&) = delete; lcFile(lcFile&&) = delete; lcFile& operator=(const lcFile&) = delete; lcFile& operator=(lcFile&&) = delete; virtual long GetPosition() const = 0; virtual void Seek(qint64 Offset, int From) = 0; virtual size_t GetLength() const = 0; virtual void Close() = 0; virtual char* ReadLine(char* Buffer, size_t BufferSize) = 0; void WriteLine(const char* Buffer) { WriteBuffer(Buffer, strlen(Buffer)); } virtual size_t ReadBuffer(void* Buffer, size_t Bytes) = 0; virtual size_t WriteBuffer(const void* Buffer, size_t Bytes) = 0; quint8 ReadU8() { quint8 Value; Read8(&Value, 1); return Value; } size_t ReadU8(quint8* Buffer, size_t Count) { return Read8(Buffer, Count); } qint8 ReadS8() { qint8 Value; Read8(&Value, 1); return Value; } size_t ReadS8(qint8* Buffer, size_t Count) { return Read8(Buffer, Count); } quint16 ReadU16() { quint16 Value; Read16(&Value, 1); return Value; } size_t ReadU16(quint16* Buffer, size_t Count) { return Read16(Buffer, Count); } qint16 ReadS16() { qint16 Value; Read16(&Value, 1); return Value; } size_t ReadS16(qint16* Buffer, size_t Count) { return Read16(Buffer, Count); } quint32 ReadU32() { quint32 Value; Read32(&Value, 1); return Value; } size_t ReadU32(quint32* Buffer, size_t Count) { return Read32(Buffer, Count); } qint32 ReadS32() { qint32 Value; Read32(&Value, 1); return Value; } size_t ReadS32(qint32* Buffer, size_t Count) { return Read32(Buffer, Count); } quint64 ReadU64() { quint64 Value; Read64(&Value, 1); return Value; } size_t ReadU64(quint64* Buffer, size_t Count) { return Read64(Buffer, Count); } qint64 ReadS64() { qint64 Value; Read64(&Value, 1); return Value; } size_t ReadS64(qint64* Buffer, size_t Count) { return Read64(Buffer, Count); } float ReadFloat() { float Value; Read32(&Value, 1); return Value; } size_t ReadFloats(float* Buffer, size_t Count) { return Read32(Buffer, Count); } double ReadDouble() { double Value; Read64(&Value, 1); return Value; } lcVector3 ReadVector3() { lcVector3 Vector; ReadFloats(Vector, 3); return Vector; } size_t ReadDoubles(double* Buffer, size_t Count) { return Read64(Buffer, Count); } QString ReadQString() { const quint32 Size = ReadU32(); char* Buffer = new char[Size]; ReadBuffer(Buffer, Size); QString String = QString::fromUtf8(Buffer, Size); delete[] Buffer; return String; } void WriteU8(const quint8& Value) { Write8(&Value, 1); } size_t WriteU8(const quint8* Buffer, size_t Count) { return Write8(Buffer, Count); } void WriteS8(const qint8& Value) { Write8(&Value, 1); } size_t WriteS8(const qint8* Buffer, size_t Count) { return Write8(Buffer, Count); } void WriteU16(const quint16& Value) { Write16(&Value, 1); } size_t WriteU16(const quint16* Buffer, size_t Count) { return Write16(Buffer, Count); } void WriteS16(const qint16& Value) { Write16(&Value, 1); } size_t WriteS16(const qint16* Buffer, size_t Count) { return Write16(Buffer, Count); } void WriteU32(const quint32& Value) { Write32(&Value, 1); } size_t WriteU32(const quint32* Buffer, size_t Count) { return Write32(Buffer, Count); } void WriteS32(const qint32& Value) { Write32(&Value, 1); } size_t WriteS32(const qint32* Buffer, size_t Count) { return Write32(Buffer, Count); } void WriteU64(const quint64& Value) { Write64(&Value, 1); } size_t WriteU64(const quint64* Buffer, size_t Count) { return Write64(Buffer, Count); } void WriteS64(const qint64& Value) { Write64(&Value, 1); } size_t WriteS64(const qint64* Buffer, size_t Count) { return Write64(Buffer, Count); } void WriteFloat(const float& Value) { Write32(&Value, 1); } size_t WriteFloats(const float* Buffer, size_t Count) { return Write32(Buffer, Count); } void WriteDouble(const double& Value) { Write64(&Value, 1); } size_t WriteDoubles(const double* Buffer, size_t Count) { return Write64(Buffer, Count); } void WriteVector3(const lcVector3& Vector) { WriteFloats(Vector, 3); } void WriteQString(const QString& String) { QByteArray Data = String.toUtf8(); WriteU32(Data.size()); WriteBuffer(Data, Data.size()); } protected: size_t Read8(void* Buffer, size_t Count) { return ReadBuffer(Buffer, Count); } size_t Read16(void* Buffer, size_t Count) { size_t NumRead; NumRead = ReadBuffer(Buffer, Count * 2) / 2; #if Q_BYTE_ORDER == Q_BIG_ENDIAN quint8 Temp[2]; quint8* Bytes = (quint8*)Buffer; for (size_t Idx = 0; Idx < NumRead; Idx++) { Temp[0] = Bytes[0]; Temp[1] = Bytes[1]; *Bytes++ = Temp[1]; *Bytes++ = Temp[0]; } #endif return NumRead; } size_t Read32(void* Buffer, size_t Count) { size_t NumRead; NumRead = ReadBuffer(Buffer, Count * 4) / 4; #if Q_BYTE_ORDER == Q_BIG_ENDIAN quint8 Temp[4]; quint8* Bytes = (quint8*)Buffer; for (size_t Idx = 0; Idx < NumRead; Idx++) { Temp[0] = Bytes[0]; Temp[1] = Bytes[1]; Temp[2] = Bytes[2]; Temp[3] = Bytes[3]; *Bytes++ = Temp[3]; *Bytes++ = Temp[2]; *Bytes++ = Temp[1]; *Bytes++ = Temp[0]; } #endif return NumRead; } size_t Read64(void* Buffer, size_t Count) { size_t NumRead; NumRead = ReadBuffer(Buffer, Count * 8) / 8; #if Q_BYTE_ORDER == Q_BIG_ENDIAN quint8 Temp[8]; quint8* Bytes = (quint8*)Buffer; for (size_t Idx = 0; Idx < NumRead; Idx++) { Temp[0] = Bytes[0]; Temp[1] = Bytes[1]; Temp[2] = Bytes[2]; Temp[3] = Bytes[3]; Temp[4] = Bytes[4]; Temp[5] = Bytes[5]; Temp[6] = Bytes[6]; Temp[7] = Bytes[7]; *Bytes++ = Temp[7]; *Bytes++ = Temp[6]; *Bytes++ = Temp[5]; *Bytes++ = Temp[4]; *Bytes++ = Temp[3]; *Bytes++ = Temp[2]; *Bytes++ = Temp[1]; *Bytes++ = Temp[0]; } #endif return NumRead; } size_t Write8(const void* Buffer, size_t Count) { return WriteBuffer(Buffer, Count); } size_t Write16(const void* Buffer, size_t Count) { #if Q_BYTE_ORDER == Q_BIG_ENDIAN size_t BytesWritten = 0; quint8 Temp[2]; quint8* Bytes = (quint8*)Buffer; for (size_t Idx = 0; Idx < Count; Idx++) { Temp[1] = *Bytes++; Temp[0] = *Bytes++; BytesWritten += WriteBuffer(Temp, 2); } return BytesWritten / 2; #else return WriteBuffer(Buffer, Count * 2) / 2; #endif } size_t Write32(const void* Buffer, size_t Count) { #if Q_BYTE_ORDER == Q_BIG_ENDIAN size_t BytesWritten = 0; quint8 Temp[4]; quint8* Bytes = (quint8*)Buffer; for (size_t Idx = 0; Idx < Count; Idx++) { Temp[3] = *Bytes++; Temp[2] = *Bytes++; Temp[1] = *Bytes++; Temp[0] = *Bytes++; BytesWritten += WriteBuffer(Temp, 4); } return BytesWritten / 4; #else return WriteBuffer(Buffer, Count * 4); #endif } size_t Write64(const void* Buffer, size_t Count) { #if Q_BYTE_ORDER == Q_BIG_ENDIAN size_t BytesWritten = 0; quint8 Temp[8]; quint8* Bytes = (quint8*)Buffer; for (size_t Idx = 0; Idx < Count; Idx++) { Temp[7] = *Bytes++; Temp[6] = *Bytes++; Temp[5] = *Bytes++; Temp[4] = *Bytes++; Temp[3] = *Bytes++; Temp[2] = *Bytes++; Temp[1] = *Bytes++; Temp[0] = *Bytes++; BytesWritten += WriteBuffer(Temp, 8); } return BytesWritten / 8; #else return WriteBuffer(Buffer, Count * 8); #endif } }; class lcMemFile : public lcFile { public: lcMemFile(); ~lcMemFile(); lcMemFile(const lcMemFile&) = delete; lcMemFile(lcMemFile&&) = delete; lcMemFile& operator=(const lcMemFile&) = delete; lcMemFile& operator=(lcMemFile&&) = delete; long GetPosition() const override; void Seek(qint64 Offset, int From) override; void SetLength(size_t NewLength); size_t GetLength() const override; void Close() override; char* ReadLine(char* Buffer, size_t BufferSize) override; size_t ReadBuffer(void* Buffer, size_t Bytes) override; size_t WriteBuffer(const void* Buffer, size_t Bytes) override; void GrowFile(size_t NewLength); size_t mGrowBytes; size_t mPosition; size_t mBufferSize; size_t mFileSize; unsigned char* mBuffer; }; class lcDiskFile : public lcFile { public: lcDiskFile() { } lcDiskFile(const QString& FileName) : mFile(FileName) { } ~lcDiskFile() { Close(); } lcDiskFile(const lcDiskFile&) = delete; lcDiskFile(lcDiskFile&&) = delete; lcDiskFile& operator=(const lcDiskFile&) = delete; lcDiskFile& operator=(lcDiskFile&&) = delete; void SetFileName(const QString& FileName) { mFile.setFileName(FileName); } long GetPosition() const override { return mFile.pos(); } void Seek(qint64 Offset, int From) override { switch (From) { case SEEK_CUR: Offset += mFile.pos(); break; case SEEK_END: Offset += mFile.size(); break; } mFile.seek(Offset); } size_t GetLength() const override { return mFile.size(); } void Close() override { mFile.close(); } char* ReadLine(char* Buffer, size_t BufferSize) override { const qint64 LineLength = mFile.readLine(Buffer, BufferSize); return LineLength != -1 ? Buffer : nullptr; } size_t ReadBuffer(void* Buffer, size_t Bytes) override { return mFile.read((char*)Buffer, Bytes); } size_t WriteBuffer(const void* Buffer, size_t Bytes) override { return mFile.write((const char*)Buffer, Bytes); } bool Open(QIODevice::OpenMode Flags) { return mFile.open(Flags); } protected: QFile mFile; };