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
|
#pragma once
|
||||||
|
|
||||||
|
#include "IO/CFile.hpp"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <filesystem>
|
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ namespace OpenVulkano
|
|||||||
{
|
{
|
||||||
class JpegWithTagsWriter final
|
class JpegWithTagsWriter final
|
||||||
{
|
{
|
||||||
FILE* file;
|
CFile file;
|
||||||
|
|
||||||
template<typename T> static T EndianSwap(T value)
|
template<typename T> static T EndianSwap(T value)
|
||||||
{
|
{
|
||||||
@@ -30,7 +30,7 @@ namespace OpenVulkano
|
|||||||
|
|
||||||
void Check() const
|
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
|
// ReSharper disable once CppDFAConstantParameter
|
||||||
@@ -39,36 +39,26 @@ namespace OpenVulkano
|
|||||||
Check();
|
Check();
|
||||||
// ReSharper disable once CppDFAConstantConditions
|
// ReSharper disable once CppDFAConstantConditions
|
||||||
if (app > 0xF) [[unlikely]] throw std::runtime_error("App marker is out of range.");
|
if (app > 0xF) [[unlikely]] throw std::runtime_error("App marker is out of range.");
|
||||||
fputc(0xFF, file);
|
file.Put(0xFF);
|
||||||
fputc(0xE0 + app, file);
|
file.Put(0xE0 + app);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write16(uint16_t value) const
|
void Write16(uint16_t value) const
|
||||||
{
|
{
|
||||||
value = EndianSwap(value);
|
value = EndianSwap(value);
|
||||||
fwrite(&value, sizeof(value), 1, file);
|
file.Write(&value, sizeof(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write32(uint32_t value) const
|
void Write32(uint32_t value) const
|
||||||
{
|
{
|
||||||
value = EndianSwap(value);
|
value = EndianSwap(value);
|
||||||
fwrite(&value, sizeof(value), 1, file);
|
file.Write(&value, sizeof(value));
|
||||||
}
|
|
||||||
|
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
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) throw std::runtime_error("Can't open file.");
|
||||||
if (file == nullptr) throw std::runtime_error("Can't open file.");
|
|
||||||
// Write soi marker
|
// Write soi marker
|
||||||
fputc(0xFF, file);
|
fputc(0xFF, file);
|
||||||
fputc(0xD8, file);
|
fputc(0xD8, file);
|
||||||
@@ -81,16 +71,14 @@ namespace OpenVulkano
|
|||||||
|
|
||||||
void Close()
|
void Close()
|
||||||
{
|
{
|
||||||
if (!file) throw std::runtime_error("Jpeg file alreay closed!");
|
file.Close();
|
||||||
fclose(file);
|
|
||||||
file = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteExifTag(const std::span<const uint8_t>& exifTag) const
|
void WriteExifTag(const std::span<const uint8_t>& exifTag) const
|
||||||
{
|
{
|
||||||
WriteAppMarker();
|
WriteAppMarker();
|
||||||
Write16(exifTag.size() + 2); // 2 byte extra for the size value itself
|
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
|
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/";
|
constexpr std::string_view XMP_MARKER = "http://ns.adobe.com/xap/1.0/";
|
||||||
WriteAppMarker(1);
|
WriteAppMarker(1);
|
||||||
Write16(xmpTag.size() + XMP_MARKER.size() + 3); // 1 byte extra for null termination, 2 byte extra for the size value itself
|
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
|
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
|
// 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();
|
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; }
|
[[nodiscard]] FILE* GetFilePtr() const { return file; }
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user