- Changes in Cat functions
- Using gmtime_s and gmtime_r as a thread-safe functions
- ZFill() that is used for padding
- Option for ZipWriter to pad LocalFileHeaders(it is used to properly run tests)
- ZipWriter::IsOpen()
- Moved material creation away from WriteObjContents
- Using MemMappedFile instead of ReadFile
- Scoping files and adding them to archive
- UsdEncoder refactoring
This commit is contained in:
Vladyslav Baranovskyi
2024-11-27 20:21:14 +02:00
parent ba8574f537
commit 34bfebbdd3
5 changed files with 85 additions and 70 deletions

View File

@@ -106,54 +106,64 @@ namespace
static_assert(sizeof(EndOfCentralDirectoryHeader) == 22, "Well packed struct");
static_assert(sizeof(NtfsExtraField) == 36, "Well packed struct");
uint32_t Cat(std::vector<uint8_t>& dest, size_t size, uint8_t* thing)
uint32_t Cat(std::vector<uint8_t>& dest, size_t size, const uint8_t* thing)
{
uint32_t startOffset = dest.size();
dest.insert(dest.end(), (uint8_t*)thing, (uint8_t*)(thing + size));
dest.insert(dest.end(), thing, thing + size);
return startOffset;
}
template<typename T>
uint32_t Cat(std::vector<uint8_t>& dest, T* thing)
uint32_t Cat(std::vector<uint8_t>& dest, const T* thing)
{
return Cat(dest, sizeof(T), reinterpret_cast<uint8_t*>(thing));
return Cat(dest, sizeof(T), reinterpret_cast<const uint8_t*>(thing));
}
uint32_t Cat(std::vector<uint8_t>& dest, const std::vector<uint8_t>& thing)
{
return Cat(dest, thing.size(), const_cast<uint8_t*>(thing.data()));
return Cat(dest, thing.size(), thing.data());
}
std::pair<uint16_t, uint16_t> ConvertToDosTimeDate(time_t time)
std::pair<uint16_t, uint16_t> ConvertToDosTimeDate(const time_t time)
{
std::tm* tm = std::gmtime(&time);
if (tm)
{
uint16_t dosTime = 0;
dosTime |= (tm->tm_sec / 2) & 0x1F; // Seconds divided by 2 (Bits 00-04)
dosTime |= (tm->tm_min & 0x3F) << 5; // Minutes (Bits 05-10)
dosTime |= (tm->tm_hour & 0x1F) << 11; // Hours (Bits 11-15)
std::tm tm;
#if _MSC_VER >= 1400
if (gmtime_s(&tm, &time) != 0) [[unlikely]]
throw std::runtime_error("gmtime_s() failed");
#else
if (gmtime_r(&time, &tm) == nullptr) [[unlikely]]
throw std::runtime_error("gmtime_r() failed");
#endif
uint16_t dosTime = 0;
dosTime |= (tm.tm_sec / 2) & 0x1F; // Seconds divided by 2 (Bits 00-04)
dosTime |= (tm.tm_min & 0x3F) << 5; // Minutes (Bits 05-10)
dosTime |= (tm.tm_hour & 0x1F) << 11; // Hours (Bits 11-15)
uint16_t dosDate = 0;
dosDate |= (tm->tm_mday & 0x1F); // Day (Bits 00-04)
dosDate |= ((tm->tm_mon + 1) & 0x0F) << 5; // Month (Bits 05-08)
dosDate |= ((tm->tm_year - 80) & 0x7F) << 9; // Year from 1980 (Bits 09-15)
return { dosTime, dosDate };
}
uint16_t dosDate = 0;
dosDate |= (tm.tm_mday & 0x1F); // Day (Bits 00-04)
dosDate |= ((tm.tm_mon + 1) & 0x0F) << 5; // Month (Bits 05-08)
dosDate |= ((tm.tm_year - 80) & 0x7F) << 9; // Year from 1980 (Bits 09-15)
return { dosTime, dosDate };
}
return {};
template<int MAX_PADDING_SIZE = 64>
void ZFill(FILE *handle, size_t num)
{
uint8_t zeros[MAX_PADDING_SIZE] = {};
fwrite(&zeros, num, 1, handle);
}
}
namespace OpenVulkano
{
ZipWriter::ZipWriter(const std::filesystem::path& filePath)
ZipWriter::ZipWriter(const std::filesystem::path& filePath, bool alignHeadersby64)
{
m_file = fopen(filePath.string().c_str(), "wb");
if (!m_file)
{
throw std::runtime_error("Unable to open file for writing: " + filePath.string());
}
m_pad = alignHeadersby64;
}
void ZipWriter::AddFile(const FileDescription& description, const void* buffer)
@@ -169,6 +179,13 @@ namespace OpenVulkano
time_t accessTime = modTime; // FileDescription doesn't have this field
auto [dosTime, dosDate] = ConvertToDosTimeDate(modTime);
if (m_pad)
{
size_t headerSize = sizeof(LocalFileHeader) + fileNameLength;
size_t padding = 64 - ((ftell(m_file) + headerSize) & 63);
ZFill<64>(m_file, padding);
}
LocalFileHeader lfh;
lfh.fileLastModTime = dosTime;
lfh.fileLastModDate = dosDate;
@@ -209,7 +226,7 @@ namespace OpenVulkano
ZipWriter::~ZipWriter()
{
if (m_file)
if (IsOpen())
{
int centralDirsOffset = 0;
if (m_numFiles)

View File

@@ -17,12 +17,15 @@ namespace OpenVulkano
{
std::vector<uint8_t> m_centralDirs;
int m_numFiles = 0;
bool m_pad = false;
FILE* m_file;
public:
ZipWriter(const std::filesystem::path& filePath);
ZipWriter(const std::filesystem::path& filePath, bool alignHeadersby64 = false);
~ZipWriter();
bool IsOpen() const { return m_file != nullptr; }
void AddFile(const FileDescription& description, const void* buffer);
void AddFile(const std::filesystem::path& fileName, const char* inArchiveName);
};