Add CFile wrapper
This commit is contained in:
131
openVulkanoCpp/IO/CFile.hpp
Normal file
131
openVulkanoCpp/IO/CFile.hpp
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstdio>
|
||||
#include <filesystem>
|
||||
|
||||
namespace OpenVulkano
|
||||
{
|
||||
class CFile
|
||||
{
|
||||
static constexpr std::array<char[4], 12> MODE_STRINGS = { "r", "rb", "w", "wb", "a", "ab", "r+", "rb+", "w+", "wb+", "a+", "ab+" };
|
||||
static constexpr std::array<wchar_t[4], 12> MODE_STRINGS_W = { L"r", L"rb", L"w", L"wb", L"a", L"ab", L"r+", L"rb+", L"w+", L"wb+", L"a+", L"ab+" };
|
||||
|
||||
public:
|
||||
enum Mode
|
||||
{
|
||||
READ = 0,
|
||||
READ_BINARY,
|
||||
WRITE,
|
||||
WRITE_BINARY,
|
||||
APPEND,
|
||||
APPEND_BINARY,
|
||||
READ_WRITE, // Null if file does not exist
|
||||
READ_WRITE_BINARY, // Null if file does not exist
|
||||
WRITE_READ, // Creates file if not exists
|
||||
WRITE_READ_BINARY, // Creates file if not exists
|
||||
APPEND_READ,
|
||||
APPEND_READ_BINARY,
|
||||
};
|
||||
|
||||
FILE* f = nullptr;
|
||||
|
||||
CFile() = default;
|
||||
|
||||
CFile(const std::filesystem::path& path, const Mode mode) : CFile(path.c_str(), mode)
|
||||
{}
|
||||
|
||||
template<typename T>
|
||||
CFile(const T* path, Mode mode) requires std::is_same_v<T, char> || std::is_same_v<T, wchar_t> : f(FOpen(path, mode))
|
||||
{}
|
||||
|
||||
CFile(const CFile&) = delete;
|
||||
CFile& operator=(const CFile&) = delete;
|
||||
|
||||
CFile(CFile&& other) noexcept : f(other.f)
|
||||
{
|
||||
other.f = nullptr;
|
||||
}
|
||||
|
||||
CFile& operator=(CFile&& other) noexcept
|
||||
{
|
||||
Close();
|
||||
f = other.f;
|
||||
other.f = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~CFile()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
if (f)
|
||||
{
|
||||
fclose(f);
|
||||
f = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Open(const std::filesystem::path& path, const Mode mode)
|
||||
{
|
||||
Close(); // Close current
|
||||
f = FOpen(path.c_str(), mode);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Open(const T* path, const Mode mode) requires std::is_same_v<T, char> || std::is_same_v<T, wchar_t>
|
||||
{
|
||||
f = FOpen(path, mode);
|
||||
}
|
||||
|
||||
size_t Read(void* data, const size_t elementSize, const size_t elementCount = 1) const
|
||||
{
|
||||
return fread(data, elementSize, elementCount, f);
|
||||
}
|
||||
|
||||
size_t Write(const void* data, const size_t elementSize, const size_t elementCount = 1) const
|
||||
{
|
||||
return fwrite(data, elementSize, elementCount, f);
|
||||
}
|
||||
|
||||
int Put(const char c) const
|
||||
{
|
||||
return fputc(c, f);
|
||||
}
|
||||
|
||||
void Seek(const long position, const int mode = SEEK_SET) const
|
||||
{
|
||||
fseek(f, position, mode);
|
||||
}
|
||||
|
||||
[[nodiscard]] long Tell() const
|
||||
{
|
||||
return ftell(f);
|
||||
}
|
||||
|
||||
FILE* FilePtr() const { return f; }
|
||||
|
||||
[[nodiscard]] operator bool() const noexcept { return f != nullptr; }
|
||||
|
||||
[[nodiscard]] operator FILE*() const noexcept { return f; }
|
||||
|
||||
// Helper function, might be used outside off class
|
||||
template<typename T>
|
||||
[[nodiscard]] static FILE* FOpen(const T* path, const Mode mode) requires std::is_same_v<T, char> || std::is_same_v<T, wchar_t>
|
||||
{
|
||||
if constexpr (std::is_same_v<T, char>)
|
||||
return fopen(path, MODE_STRINGS[mode]);
|
||||
else
|
||||
return _wfopen(path, MODE_STRINGS_W[mode]);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -6,8 +6,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IO/CFile.hpp"
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include <span>
|
||||
#include <string_view>
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace OpenVulkano
|
||||
{
|
||||
class JpegWithTagsWriter final
|
||||
{
|
||||
FILE* file;
|
||||
CFile file;
|
||||
|
||||
template<typename T> static T EndianSwap(T value)
|
||||
{
|
||||
@@ -30,7 +30,7 @@ namespace OpenVulkano
|
||||
|
||||
void Check() const
|
||||
{
|
||||
if (file == nullptr) throw std::runtime_error("Can't append to jpeg file, it has already been completed.");
|
||||
if (!file) throw std::runtime_error("Can't append to jpeg file, it has already been closed.");
|
||||
}
|
||||
|
||||
// ReSharper disable once CppDFAConstantParameter
|
||||
@@ -39,36 +39,26 @@ namespace OpenVulkano
|
||||
Check();
|
||||
// ReSharper disable once CppDFAConstantConditions
|
||||
if (app > 0xF) [[unlikely]] throw std::runtime_error("App marker is out of range.");
|
||||
fputc(0xFF, file);
|
||||
fputc(0xE0 + app, file);
|
||||
file.Put(0xFF);
|
||||
file.Put(0xE0 + app);
|
||||
}
|
||||
|
||||
void Write16(uint16_t value) const
|
||||
{
|
||||
value = EndianSwap(value);
|
||||
fwrite(&value, sizeof(value), 1, file);
|
||||
file.Write(&value, sizeof(value));
|
||||
}
|
||||
|
||||
void Write32(uint32_t value) const
|
||||
{
|
||||
value = EndianSwap(value);
|
||||
fwrite(&value, sizeof(value), 1, file);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static FILE* FOpen(const T* path)
|
||||
{
|
||||
if constexpr (std::is_same_v<T, char>)
|
||||
return fopen(path, "wb");
|
||||
else
|
||||
return _wfopen(path, L"wb");
|
||||
file.Write(&value, sizeof(value));
|
||||
}
|
||||
|
||||
public:
|
||||
JpegWithTagsWriter(const std::filesystem::path& filePath)
|
||||
JpegWithTagsWriter(const std::filesystem::path& filePath) : file(filePath, CFile::WRITE_BINARY)
|
||||
{
|
||||
file = FOpen(filePath.c_str());
|
||||
if (file == nullptr) throw std::runtime_error("Can't open file.");
|
||||
if (!file) throw std::runtime_error("Can't open file.");
|
||||
// Write soi marker
|
||||
fputc(0xFF, file);
|
||||
fputc(0xD8, file);
|
||||
@@ -81,16 +71,14 @@ namespace OpenVulkano
|
||||
|
||||
void Close()
|
||||
{
|
||||
if (!file) throw std::runtime_error("Jpeg file alreay closed!");
|
||||
fclose(file);
|
||||
file = nullptr;
|
||||
file.Close();
|
||||
}
|
||||
|
||||
void WriteExifTag(const std::span<const uint8_t>& exifTag) const
|
||||
{
|
||||
WriteAppMarker();
|
||||
Write16(exifTag.size() + 2); // 2 byte extra for the size value itself
|
||||
fwrite(exifTag.data(), sizeof(uint8_t), exifTag.size(), file);
|
||||
file.Write(exifTag.data(), sizeof(uint8_t), exifTag.size());
|
||||
}
|
||||
|
||||
void WriteXmpTag(const std::string& xmpTag) const
|
||||
@@ -98,9 +86,9 @@ namespace OpenVulkano
|
||||
constexpr std::string_view XMP_MARKER = "http://ns.adobe.com/xap/1.0/";
|
||||
WriteAppMarker(1);
|
||||
Write16(xmpTag.size() + XMP_MARKER.size() + 3); // 1 byte extra for null termination, 2 byte extra for the size value itself
|
||||
fwrite(XMP_MARKER.data(), XMP_MARKER.size(), 1, file);
|
||||
file.Write(XMP_MARKER.data(), XMP_MARKER.size());
|
||||
fputc(0, file); // Null terminate string
|
||||
fwrite(xmpTag.c_str(), 1, xmpTag.size(), file);
|
||||
file.Write(xmpTag.c_str(), 1, xmpTag.size());
|
||||
}
|
||||
|
||||
// Must be called as last function, as this will finalize the image writing and will close the file
|
||||
@@ -112,9 +100,9 @@ namespace OpenVulkano
|
||||
if (close) Close();
|
||||
}
|
||||
|
||||
operator bool() const { return file != nullptr; }
|
||||
operator bool() const { return file; }
|
||||
|
||||
[[nodiscard]] bool IsOpen() const { return file != nullptr; }
|
||||
[[nodiscard]] bool IsOpen() const { return file; }
|
||||
|
||||
[[nodiscard]] FILE* GetFilePtr() const { return file; }
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user