#pragma once #include "Types.h" #include "BaseObj.h" #include "Util.h" #include "Array.h" #include "Vector.h" #include "Str.h" #include "Version.h" #include "Vec2.h" #include "Vec3.h" #include "Color3.h" #include "Vec4.h" #include "Rect.h" #include "Color4.h" #include "Quat.h" #include "Mat2.h" #include "Mat3.h" #include "Mat4.h" namespace ehs { template class Serializer : public BaseObj { private: Endianness endianness; Byte* data; N size; N offset; public: ~Serializer() override { delete[] data; } Serializer() : endianness(Endianness::BE), data(nullptr), size(0), offset(0) { AddType("Serializer"); } Serializer(const Endianness endianness) : endianness(endianness), data(nullptr), size(0), offset(0) { AddType("Serializer"); } Serializer(const Endianness endianness, const N size) : endianness(endianness), data(new Byte[size]), size(size), offset(0) { AddType("Serializer"); } Serializer(const Endianness endianness, const Byte* const data, const N size, const N offset = 0) : endianness(endianness), data(new Byte[size]), size(size), offset(offset) { AddType("Serializer"); for (N i = 0; i < size; ++i) this->data[i] = data[i]; } Serializer(Serializer&& serializer) noexcept : BaseObj((BaseObj&&)serializer), endianness(serializer.endianness), data(serializer.data), size(serializer.size), offset(serializer.offset) { serializer.data = nullptr; serializer.size = 0; serializer.offset = 0; } Serializer(const Serializer& serializer) : BaseObj(serializer), endianness(serializer.endianness), data(new Byte[serializer.size]), size(serializer.size), offset(serializer.offset) { for (N i = 0; i < serializer.size; ++i) data[i] = serializer.data[i]; } Serializer& operator=(Serializer&& serializer) noexcept { if (this == &serializer) return *this; BaseObj::operator=((Serializer&&)serializer); endianness = serializer.endianness; delete[] data; data = serializer.data; size = serializer.size; offset = serializer.offset; serializer.data = nullptr; serializer.size = 0; serializer.offset = 0; return *this; } Serializer& operator=(const Serializer& serializer) { if (this == &serializer) return *this; BaseObj::operator=(serializer); endianness = serializer.endianness; delete[] data; data = new Byte[serializer.size]; for (N i = 0; i < serializer.size; ++i) data[i] = serializer.data[i]; size = serializer.size; offset = serializer.offset; return *this; } bool operator==(const Serializer& in) const { if (size != in.size) return false; return Util::Compare(data, in.data, size); } bool operator!=(const Serializer& in) const { if (size != in.size) return true; return !Util::Compare(data, in.data, size); } Serializer& operator+=(const N size) { offset += size; return *this; } Serializer& operator-=(const N size) { offset -= size; return *this; } Serializer& operator*=(const N size) { offset *= size; return *this; } Serializer& operator/=(const N size) { offset /= size; return *this; } Serializer& operator%=(const N size) { offset %= size; return *this; } operator const Byte* () const { return data; } operator Byte* () { return data; } void SetEndianness(const Endianness newEndianness) { endianness = newEndianness; } Endianness GetEndianness() const { return endianness; } template void WriteArray(const T* const value, const O size) { if (sizeof(N) + size * sizeof(T) > this->size - offset) { N remainder = sizeof(N) + size * sizeof(T) - (this->size - offset); Byte* r = new Byte[this->size + remainder]; Util::Copy(r, data, size); delete[] data; data = r; this->size += remainder; } if (CPU::GetEndianness() == Endianness::LE) { if (endianness == Endianness::LE) { *(N*)&data[offset] = (N)size; offset += sizeof(N); for (N i = 0; i < size; ++i) *(T*)&data[offset + i * sizeof(T)] = value[i]; } else { N tmp = (N)size; for (N i = 0; i < sizeof(N); ++i) data[offset + i] = ((Byte*)&tmp)[sizeof(N) - i - 1]; offset += sizeof(N); for (N i = 0; i < size; ++i) for (N b = 0; b < sizeof(T); ++b) data[offset + i * sizeof(T) + b] = ((Byte*)&value[i])[sizeof(T) - i - 1]; } } else { if (endianness == Endianness::LE) { N tmp = (N)size; for (N i = 0; i < sizeof(N); ++i) data[offset + i] = ((Byte*)&tmp)[sizeof(N) - i - 1]; offset += sizeof(N); for (N i = 0; i < size; ++i) for (N b = 0; b < sizeof(T); ++b) data[offset + i * sizeof(T) + b] = ((Byte*)&value[i])[sizeof(T) - i - 1]; } else { *(N*)&data[offset] = (N)size; offset += sizeof(N); for (N i = 0; i < size; ++i) *(T*)&data[offset + i * sizeof(T)] = value[i]; } } offset += sizeof(T) * size; } template void WriteArray(const Array& value) { if (sizeof(N) + value.Size() * sizeof(T) > size - offset) { N remainder = sizeof(N) + value.Size() * sizeof(T) - (size - offset); Byte* r = new Byte[size + remainder]; Util::Copy(r, data, size); delete[] data; data = r; size += remainder; } if (CPU::GetEndianness() == Endianness::LE) { if (endianness == Endianness::LE) { *(N*)&data[offset] = (N)value.Size(); offset += sizeof(N); for (N i = 0; i < value.Size(); ++i) *(T*)&data[offset + i * sizeof(T)] = value[i]; } else { N tmpSize = (N)value.Size(); for (N i = 0; i < sizeof(N); ++i) data[offset + i] = ((Byte*)&tmpSize)[sizeof(N) - i - 1]; offset += sizeof(N); for (N i = 0; i < value.Size(); ++i) for (N b = 0; b < sizeof(T); ++b) data[offset + i * sizeof(T) + b] = ((Byte*)&value[i])[sizeof(T) - i - 1]; } } else { if (endianness == Endianness::LE) { N tmpSize = (N)value.Size(); for (N i = 0; i < sizeof(N); ++i) data[offset + i] = ((Byte*)&tmpSize)[sizeof(N) - i - 1]; offset += sizeof(N); for (N i = 0; i < value.Size(); ++i) for (N b = 0; b < sizeof(T); ++b) data[offset + i * sizeof(T) + b] = ((Byte*)&value[i])[sizeof(T) - i - 1]; } else { *(N*)&data[offset] = (N)value.Size(); offset += sizeof(N); for (N i = 0; i < value.Size(); ++i) *(T*)&data[offset + i * sizeof(T)] = value[i]; } } offset += sizeof(T) * value.Size(); } template void WriteVector(const Vector& value) { if (sizeof(N) + value.Size() * sizeof(T) > size - offset) { N remainder = sizeof(N) + value.Size() * sizeof(T) - (size - offset); Byte* r = new Byte[size + remainder]; Util::Copy(r, data, size); delete[] data; data = r; size += remainder; } if (CPU::GetEndianness() == Endianness::LE) { if (endianness == Endianness::LE) { *(N*)&data[offset] = (N)value.Size(); offset += sizeof(N); for (N i = 0; i < value.Size(); ++i) *(T*)&data[offset + i * sizeof(T)] = value[i]; } else { N tmpSize = (N)value.Size(); for (N i = 0; i < sizeof(N); ++i) data[offset + i] = ((Byte*)&tmpSize)[sizeof(N) - i - 1]; offset += sizeof(N); for (N i = 0; i < value.Size(); ++i) for (N b = 0; b < sizeof(T); ++b) data[offset + i * sizeof(T) + b] = ((Byte*)&value[i])[sizeof(T) - i - 1]; } } else { if (endianness == Endianness::LE) { N tmpSize = (N)value.Size(); for (N i = 0; i < sizeof(N); ++i) data[offset + i] = ((Byte*)&tmpSize)[sizeof(N) - i - 1]; offset += sizeof(N); for (N i = 0; i < value.Size(); ++i) for (N b = 0; b < sizeof(T); ++b) data[offset + i * sizeof(T) + b] = ((Byte*)&value[i])[sizeof(T) - i - 1]; } else { *(N*)&data[offset] = (N)value.Size(); offset += sizeof(N); for (N i = 0; i < value.Size(); ++i) *(T*)&data[offset + i * sizeof(T)] = value[i]; } } offset += sizeof(T) * value.Size(); } template void WriteStr(const T* str, const bool sizeKnown, N inSize = 0) { if (!inSize) while (str[inSize]) inSize++; N bSize = sizeof(T) * inSize; N bSizeN = sizeof(T) * (inSize + 1); if (bSizeN > size - offset) { N remainder = bSizeN - (size - offset); Byte* r = new Byte[size + remainder]; Util::Copy(r, data, size); delete[] data; data = r; size += remainder; } if (CPU::GetEndianness() == Endianness::LE) { if (endianness == Endianness::LE) { Util::Copy(&data[offset], &str[0], bSize); if (!sizeKnown) *(T*)&data[offset + inSize] = 0; } else { for (N i = 0; i < inSize; ++i) for (N b = 0; b < sizeof(T); ++b) data[offset + sizeof(T) * i + b] = ((Byte*)&str[i])[sizeof(T) - i - 1]; if (!sizeKnown) *(T*)&data[offset + bSize] = 0; } } else { if (endianness == Endianness::LE) { for (N i = 0; i < inSize; ++i) for (N b = 0; b < sizeof(T); ++b) data[offset + sizeof(T) * i + b] = ((Byte*)&str[i])[sizeof(T) - i - 1]; if (!sizeKnown) *(T*)&data[offset + bSize] = 0; } else { Util::Copy(&data[offset], &str[0], bSize); if (!sizeKnown) *(T*)&data[offset + bSize] = 0; } } offset += bSizeN; } template void WriteStr(const Str& str) { N inSize = sizeof(T) * (str.Size() + 1); if (inSize > size - offset) { N remainder = inSize - (size - offset); Byte* r = new Byte[size + remainder]; Util::Copy(r, data, size); delete[] data; data = r; size += remainder; } if (CPU::GetEndianness() == Endianness::LE) { if (endianness == Endianness::LE) { Util::Copy(&data[offset], &str[0], str.Size(true)); *(T*)&data[offset + str.Size(true)] = 0; } else { for (N i = 0; i < str.Size(); ++i) for (N b = 0; b < sizeof(T); ++b) data[offset + sizeof(T) * i + b] = ((Byte*)&str[i])[sizeof(T) - i - 1]; *(T*)&data[offset + str.Size(true)] = 0; } } else { if (endianness == Endianness::LE) { for (N i = 0; i < str.Size(); ++i) for (N b = 0; b < sizeof(T); ++b) data[offset + sizeof(T) * i + b] = ((Byte*)&str[i])[sizeof(T) - i - 1]; *(T*)&data[offset + str.Size(true)] = 0; } else { Util::Copy(&data[offset], &str[0], str.Size(true)); *(T*)&data[offset + str.Size(true)] = 0; } } offset += inSize; } void WriteVersion(const Version& value) { if (sizeof(unsigned int) * 3 > size - offset) { N remainder = sizeof(unsigned int) * 3 - (size - offset); Byte* r = new Byte[size + remainder]; Util::Copy(r, data, size); delete[] data; data = r; size += remainder; } if (CPU::GetEndianness() == Endianness::LE) { if (endianness == Endianness::LE) for (N i = 0; i < 3; ++i) *(unsigned int*)&data[offset + i * sizeof(unsigned int)] = value[i]; else for (N i = 0; i < 3; ++i) for (N b = 0; b < sizeof(unsigned int); ++b) data[offset + i * sizeof(unsigned int) + b] = value[sizeof(unsigned int) - i - 1]; } else { if (endianness == Endianness::LE) for (N i = 0; i < 3; ++i) for (N b = 0; b < sizeof(unsigned int); ++b) data[offset + i * sizeof(unsigned int) + b] = value[sizeof(unsigned int) - i - 1]; else for (N i = 0; i < 3; ++i) *(unsigned int*)&data[offset + i * sizeof(unsigned int)] = value[i]; } offset += sizeof(unsigned int) * 3; } template void WriteVec2(const Vec2& value) { if (sizeof(T) * 2 > size - offset) { N remainder = sizeof(T) * 2 - (size - offset); Byte* r = new Byte[size + remainder]; Util::Copy(r, data, size); delete[] data; data = r; size += remainder; } if (CPU::GetEndianness() == Endianness::LE) { if (endianness == Endianness::LE) for (N i = 0; i < 2; ++i) *(T*)&data[offset + i * sizeof(T)] = value[i]; else for (N i = 0; i < 2; ++i) for (N b = 0; b < sizeof(T); ++b) data[offset + i * sizeof(T) + b] = value[sizeof(T) - i - 1]; } else { if (endianness == Endianness::LE) for (N i = 0; i < 2; ++i) for (N b = 0; b < sizeof(T); ++b) data[offset + i * sizeof(T) + b] = value[sizeof(T) - i - 1]; else for (N i = 0; i < 2; ++i) *(T*)&data[offset + i * sizeof(T)] = value[i]; } offset += sizeof(T) * 2; } template void WriteVec3(const Vec3& value) { if (sizeof(T) * 3 > size - offset) { N remainder = sizeof(T) * 3 - (size - offset); Byte* r = new Byte[size + remainder]; Util::Copy(r, data, size); delete[] data; data = r; size += remainder; } if (CPU::GetEndianness() == Endianness::LE) { if (endianness == Endianness::LE) for (N i = 0; i < 3; ++i) *(T*)&data[offset + i * sizeof(T)] = value[i]; else for (N i = 0; i < 3; ++i) for (N b = 0; b < sizeof(T); ++b) data[offset + i * sizeof(T) + b] = value[sizeof(T) - i - 1]; } else { if (endianness == Endianness::LE) for (N i = 0; i < 3; ++i) for (N b = 0; b < sizeof(T); ++b) data[offset + i * sizeof(T) + b] = value[sizeof(T) - i - 1]; else for (N i = 0; i < 3; ++i) *(T*)&data[offset + i * sizeof(T)] = value[i]; } offset += sizeof(T) * 3; } void WriteColor3(const Color3& value) { if (sizeof(float) * 3 > size - offset) { N remainder = sizeof(float) * 3 - (size - offset); Byte* r = new Byte[size + remainder]; Util::Copy(r, data, size); delete[] data; data = r; size += remainder; } if (CPU::GetEndianness() == Endianness::LE) { if (endianness == Endianness::LE) for (N i = 0; i < 3; ++i) *(float*)&data[offset + i * sizeof(float)] = value[i]; else for (N i = 0; i < 3; ++i) for (N b = 0; b < sizeof(float); ++b) data[offset + i * sizeof(float) + b] = value[sizeof(float) - i - 1]; } else { if (endianness == Endianness::LE) for (N i = 0; i < 3; ++i) for (N b = 0; b < sizeof(float); ++b) data[offset + i * sizeof(float) + b] = value[sizeof(float) - i - 1]; else for (N i = 0; i < 3; ++i) *(float*)&data[offset + i * sizeof(float)] = value[i]; } offset += sizeof(float) * 3; } template void WriteVec4(const Vec4& value) { if (sizeof(T) * 4 > size - offset) { N remainder = sizeof(T) * 4 - (size - offset); Byte* r = new Byte[size + remainder]; Util::Copy(r, data, size); delete[] data; data = r; size += remainder; } if (CPU::GetEndianness() == Endianness::LE) { if (endianness == Endianness::LE) for (N i = 0; i < 4; ++i) *(T*)&data[offset + i * sizeof(T)] = value[i]; else for (N i = 0; i < 4; ++i) for (N b = 0; b < sizeof(T); ++b) data[offset + i * sizeof(T) + b] = value[sizeof(T) - i - 1]; } else { if (endianness == Endianness::LE) for (N i = 0; i < 4; ++i) for (N b = 0; b < sizeof(T); ++b) data[offset + i * sizeof(T) + b] = value[sizeof(T) - i - 1]; else for (N i = 0; i < 4; ++i) *(T*)&data[offset + i * sizeof(T)] = value[i]; } offset += sizeof(T) * 4; } template void WriteRect(const Rect& value) { if (sizeof(T) * 4 > size - offset) { N remainder = sizeof(T) * 4 - (size - offset); Byte* r = new Byte[size + remainder]; Util::Copy(r, data, size); delete[] data; data = r; size += remainder; } if (CPU::GetEndianness() == Endianness::LE) { if (endianness == Endianness::LE) for (N i = 0; i < 4; ++i) *(T*)&data[offset + i * sizeof(T)] = value[i]; else for (N i = 0; i < 4; ++i) for (N b = 0; b < sizeof(T); ++b) data[offset + i * sizeof(T) + b] = value[sizeof(T) - i - 1]; } else { if (endianness == Endianness::LE) for (N i = 0; i < 4; ++i) for (N b = 0; b < sizeof(T); ++b) data[offset + i * sizeof(T) + b] = value[sizeof(T) - i - 1]; else for (N i = 0; i < 4; ++i) *(T*)&data[offset + i * sizeof(T)] = value[i]; } offset += sizeof(T) * 4; } void WriteColor4(const Color4& value) { if (sizeof(float) * 4 > size - offset) { N remainder = sizeof(float) * 4 - (size - offset); Byte* r = new Byte[size + remainder]; Util::Copy(r, data, size); delete[] data; data = r; size += remainder; } if (CPU::GetEndianness() == Endianness::LE) { if (endianness == Endianness::LE) for (N i = 0; i < 4; ++i) *(float*)&data[offset + i * sizeof(float)] = value[i]; else for (N i = 0; i < 4; ++i) for (N b = 0; b < sizeof(float); ++b) data[offset + i * sizeof(float) + b] = value[sizeof(float) - i - 1]; } else { if (endianness == Endianness::LE) for (N i = 0; i < 4; ++i) for (N b = 0; b < sizeof(float); ++b) data[offset + i * sizeof(float) + b] = value[sizeof(float) - i - 1]; else for (N i = 0; i < 4; ++i) *(float*)&data[offset + i * sizeof(float)] = value[i]; } offset += sizeof(float) * 4; } template void WriteQuat(const Quat& value) { if (sizeof(T) * 4 > size - offset) { N remainder = sizeof(T) * 4 - (size - offset); Byte* r = new Byte[size + remainder]; Util::Copy(r, data, size); delete[] data; data = r; size += remainder; } if (CPU::GetEndianness() == Endianness::LE) { if (endianness == Endianness::LE) for (N i = 0; i < 4; ++i) *(T*)&data[offset + i * sizeof(T)] = value[i]; else for (N i = 0; i < 4; ++i) for (N b = 0; b < sizeof(T); ++b) data[offset + i * sizeof(T) + b] = value[sizeof(T) - i - 1]; } else { if (endianness == Endianness::LE) for (N i = 0; i < 4; ++i) for (N b = 0; b < sizeof(T); ++b) data[offset + i * sizeof(T) + b] = value[sizeof(T) - i - 1]; else for (N i = 0; i < 4; ++i) *(T*)&data[offset + i * sizeof(T)] = value[i]; } offset += sizeof(T) * 4; } template void WriteMat2(const Mat2& value) { if (sizeof(T) * 4 > size - offset) { N remainder = sizeof(T) * 4 - (size - offset); Byte* r = new Byte[size + remainder]; Util::Copy(r, data, size); delete[] data; data = r; size += remainder; } if (CPU::GetEndianness() == Endianness::LE) { if (endianness == Endianness::LE) for (N i = 0; i < 4; ++i) *(T*)&data[offset + i * sizeof(T)] = value[i]; else for (N i = 0; i < 4; ++i) for (N b = 0; b < sizeof(T); ++b) data[offset + i * sizeof(T) + b] = ((Byte*)&value[i])[sizeof(T) - b - 1]; } else { if (endianness == Endianness::LE) for (N i = 0; i < 4; ++i) for (N b = 0; b < sizeof(T); ++b) data[offset + i * sizeof(T) + b] = ((Byte*)&value[i])[sizeof(T) - b - 1]; else for (N i = 0; i < 4; ++i) *(T*)&data[offset + i * sizeof(T)] = value[i]; } offset += sizeof(T) * 4; } template void WriteMat3(const Mat3& value) { if (sizeof(T) * 9 > size - offset) { N remainder = sizeof(T) * 9 - (size - offset); Byte* r = new Byte[size + remainder]; Util::Copy(r, data, size); delete[] data; data = r; size += remainder; } if (CPU::GetEndianness() == Endianness::LE) { if (endianness == Endianness::LE) for (N i = 0; i < 9; ++i) *(T*)&data[offset + i * sizeof(T)] = value[i]; else for (N i = 0; i < 9; ++i) for (N b = 0; b < sizeof(T); ++b) data[offset + i * sizeof(T) + b] = ((Byte*)&value[i])[sizeof(T) - b - 1]; } else { if (endianness == Endianness::LE) for (N i = 0; i < 9; ++i) for (N b = 0; b < sizeof(T); ++b) data[offset + i * sizeof(T) + b] = ((Byte*)&value[i])[sizeof(T) - b - 1]; else for (N i = 0; i < 9; ++i) *(T*)&data[offset + i * sizeof(T)] = value[i]; } offset += sizeof(T) * 9; } template void WriteMat4(const Mat4& value) { if (sizeof(T) * 16 > size - offset) { N remainder = sizeof(T) * 16 - (size - offset); Byte* r = new Byte[size + remainder]; Util::Copy(r, data, size); delete[] data; data = r; size += remainder; } if (CPU::GetEndianness() == Endianness::LE) { if (endianness == Endianness::LE) for (N y = 0; y < 4; ++y) for (N x = 0; x < 4; ++x) *(T*)&data[offset + y * sizeof(T) * 4 + x * sizeof(T)] = value[y][x]; else for (N y = 0; y < 4; ++y) for (N x = 0; x < 4; ++x) for (N i = 0; i < sizeof(T); ++i) data[offset + y * sizeof(T) * 4 + x * sizeof(T) + i] = ((Byte*)&value[y][x])[sizeof(T) - i - 1]; } else { if (endianness == Endianness::LE) for (N y = 0; y < 4; ++y) for (N x = 0; x < 4; ++x) for (N i = 0; i < sizeof(T); ++i) data[offset + y * sizeof(T) * 4 + x * sizeof(T) + i] = ((Byte*)&value[y][x])[sizeof(T) - i - 1]; else for (N y = 0; y < 4; ++y) for (N x = 0; x < 4; ++x) *(T*)&data[offset + y * sizeof(T) * 4 + x * sizeof(T)] = value[y][x]; } offset += sizeof(T) * 16; } void WriteSer(const Serializer& ser) { if (ser.endianness != endianness) return; if (ser.Size() > size - offset) { N remainder = ser.Size() - (size - offset); Byte* result = new Byte[size + remainder]; Util::Copy(result, data, size); delete[] data; data = result; size += remainder; } Util::Copy(&data[offset], &ser[0], ser.Size()); offset += ser.Size(); } void WritePadding(const N size) { if (size > this->size - offset) { N remainder = size - (this->size - offset); Byte* r = new Byte[this->size + remainder]; Util::Copy(r, data, this->size); delete[] data; data = r; this->size += remainder; } Util::Zero(&data[offset], size); offset += size; } template void Write(const T value) { if (sizeof(T) > size - offset) { N remainder = sizeof(T) - (size - offset); Byte* r = new Byte[size + remainder]; Util::Copy(r, data, size); delete[] data; data = r; size += remainder; } if (CPU::GetEndianness() == Endianness::LE) { if (endianness == Endianness::LE) *(T*)&data[offset] = value; else for (N i = 0; i < sizeof(T); ++i) data[offset + i] = ((Byte*)&value)[sizeof(T) - i - 1]; } else { if (endianness == Endianness::LE) for (N i = 0; i < sizeof(T); ++i) data[offset + i] = ((Byte*)&value)[sizeof(T) - i - 1]; else *(T*)&data[offset] = value; } offset += sizeof(T); } template void ReadArray(T* const value, O* const size) { if (!*size) *size = (O)Read(); for (N i = 0; i < *size; ++i) value[i] = Read(); } template Array ReadArray(const O size = 0) { Array result(size ? size : (O)Read()); for (O i = 0; i < result.Size(); ++i) result[i] = Read(); return result; } template Vector ReadVector(const O size = 0) { Vector result(size ? size : (O)Read()); for (O i = 0; i < result.Size(); ++i) result[i] = Read(); return result; } template Str ReadStr(O size = 0) { if (!size) while (&data[offset + sizeof(T) * size]) size++; Str result(size); if (CPU::GetEndianness() == Endianness::LE) { if (endianness == Endianness::LE) Util::Copy(&result[0], &data[offset], result.Size(true)); else for (N i = 0; i < size; ++i) for (N b = 0; b < sizeof(T); ++b) ((Byte*)&result[i])[sizeof(T) - i - 1] = data[offset + sizeof(T) * i + b]; } else { if (endianness == Endianness::LE) for (N i = 0; i < size; ++i) for (N b = 0; b < sizeof(T); ++b) ((Byte*)&result[i])[sizeof(T) - i - 1] = data[offset + sizeof(T) * i + b]; else Util::Copy(&result[0], &data[offset], result.Size(true)); } offset += result.Size(true) + 1; return result; } Version ReadVersion() { return {Read(), Read(), Read()}; } template Vec2 ReadVec2() { return {Read(), Read()}; } template Vec3 ReadVec3() { return {Read(), Read(), Read()}; } Color3 ReadColor3() { return {Read(), Read(), Read()}; } template Vec4 ReadVec4() { return {Read(), Read(), Read(), Read()}; } template Rect ReadRect() { return {Read(), Read(), Read(), Read()}; } Color4 ReadColor4() { return {Read(), Read(), Read(), Read()}; } template Quat ReadQuat() { return {Read(), Read(), Read(), Read()}; } template Mat2 ReadMat2() { Mat2 result; for (N i = 0; i < 4; ++i) result[i] = Read(); return result; } template Mat3 ReadMat3() { Mat3 result; for (N i = 0; i < 9; ++i) result[i] = Read(); return result; } template Mat4 ReadMat4() { Mat4 result; for (N i = 0; i < 16; ++i) result[i] = Read(); return result; } template T Read() { T value = (T)0; if (CPU::GetEndianness() == Endianness::LE) { if (endianness == Endianness::LE) value = *(T*)&data[offset]; else for (N i = 0; i < sizeof(T); ++i) ((Byte*)&value)[sizeof(T) - i - 1] = data[offset + i]; } else { if (endianness == Endianness::LE) for (N i = 0; i < sizeof(T); ++i) ((Byte*)&value)[sizeof(T) - i - 1] = data[offset + i]; else value = *(T*)&data[offset]; } offset += sizeof(T); return value; } void SetOffset(const N offset) { this->offset = offset; } N GetOffset() const { return offset; } void Resize(const N newSize) { Byte* result = new Byte[newSize]; Util::Copy(result, data, size); delete[] data; data = result; size = newSize; } N Size() const { return size; } }; }