This commit is contained in:
2025-11-27 04:27:26 +05:30
parent 131ad3120c
commit 4033cfb710
10 changed files with 113 additions and 107 deletions

View File

@ -5,8 +5,8 @@ set(SRC_FILES
"imp/cpp/AsyncOps.cpp" "imp/cpp/AsyncOps.cpp"
"imp/cpp/SocketOps.cpp" "imp/cpp/SocketOps.cpp"
"imp/cpp/ProcessOps.cpp" "imp/cpp/ProcessOps.cpp"
"imp/cpp/BinaryStreamReader.cpp" "imp/cpp/StreamReader.cpp"
"imp/cpp/BinaryStreamWriter.cpp" "imp/cpp/StreamWriter.cpp"
) )
add_library(IACore STATIC ${SRC_FILES}) add_library(IACore STATIC ${SRC_FILES})

View File

@ -18,76 +18,26 @@
namespace IACore namespace IACore
{ {
UnorderedMap<PCUINT8, PVOID> FileOps::s_mappedFiles; UnorderedMap<PCUINT8, Tuple<PVOID, PVOID, PVOID>> FileOps::s_mappedFiles;
VOID FileOps::UnmapFile(IN PCUINT8 mappedPtr) VOID FileOps::UnmapFile(IN PCUINT8 mappedPtr)
{ {
if (!s_mappedFiles.contains(mappedPtr)) if (!s_mappedFiles.contains(mappedPtr))
return; return;
const auto handle = s_mappedFiles.extract(mappedPtr)->second; const auto handles = s_mappedFiles.extract(mappedPtr)->second;
#if IA_PLATFORM_WINDOWS #if IA_PLATFORM_WINDOWS
::UnmapViewOfFile(std::get<1>(handles));
::CloseHandle(std::get<2>(handles));
::CloseHandle(std::get<0>(handles));
#elif IA_PLATFORM_UNIX #elif IA_PLATFORM_UNIX
::munmap(std::get<1>(handles), (SIZE_T) std::get<2>(handles));
::close((INT32) ((UINT64) std::get<0>(handles)));
#else #else
# error "IACore FileOps does not support this platform" # error "IACore FileOps does not support this platform"
#endif #endif
} }
Expected<PUINT8, String> FileOps::MapFile(IN CONST FilePath &path) Expected<PCUINT8, String> FileOps::MapFile(IN CONST FilePath &path, OUT SIZE_T &size)
{
#if IA_PLATFORM_WINDOWS
const auto handle = CreateFileW(path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (handle == INVALID_HANDLE_VALUE)
return MakeUnexpected(std::format("Failed to open {} for memory mapping", path.c_str()));
auto hmap = CreateFileMappingW(handle, NULL, PAGE_READWRITE, 0, 0, NULL);
if (hmap == NULL)
{
CloseHandle(handle);
return MakeUnexpected(std::format("Failed to memory map {}", path.c_str()));
}
const auto result = static_cast<PUINT8>(MapViewOfFile(hmap, FILE_MAP_ALL_ACCESS, 0, 0, 0));
if (result == NULL)
{
CloseHandle(handle);
CloseHandle(hmap);
return MakeUnexpected(std::format("Failed to memory map {}", path.c_str()));
}
s_mappedFiles[result] = (PVOID) handle;
return result;
#elif IA_PLATFORM_UNIX
const auto handle = open(path.c_str(), O_RDONLY);
if (handle == -1)
return MakeUnexpected(std::format("Failed to open {} for memory mapping", path.c_str()));
void *addr = mmap(nullptr, 0, PROT_WRITE | PROT_READ, MAP_PRIVATE, handle, 0);
if (addr == MAP_FAILED)
{
close(handle);
return MakeUnexpected(std::format("Failed to memory map {}", path.c_str()));
}
const auto result = static_cast<PUINT8>(addr);
s_mappedFiles[result] = (PVOID) ((UINT64) handle);
return result;
#else
# error "IACore FileOps does not support this platform"
#endif
}
Expected<PCUINT8, String> FileOps::MapReadonlyFile(IN CONST FilePath &path)
{
SIZE_T size;
return MapReadonlyFile(path, size);
}
Expected<PCUINT8, String> FileOps::MapReadonlyFile(IN CONST FilePath &path, OUT SIZE_T &size)
{ {
#if IA_PLATFORM_WINDOWS #if IA_PLATFORM_WINDOWS
@ -124,7 +74,7 @@ namespace IACore
CloseHandle(hmap); CloseHandle(hmap);
return MakeUnexpected(std::format("Failed to memory map {}", path.c_str())); return MakeUnexpected(std::format("Failed to memory map {}", path.c_str()));
} }
s_mappedFiles[result] = (PVOID) handle; s_mappedFiles[result] = std::make_tuple((PVOID) handle, (PVOID) result, (PVOID) hmap);
return result; return result;
#elif IA_PLATFORM_UNIX #elif IA_PLATFORM_UNIX
@ -152,7 +102,7 @@ namespace IACore
} }
const auto result = static_cast<PCUINT8>(addr); const auto result = static_cast<PCUINT8>(addr);
madvise(addr, size, MADV_SEQUENTIAL); madvise(addr, size, MADV_SEQUENTIAL);
s_mappedFiles[result] = (PVOID) ((UINT64) handle); s_mappedFiles[result] = std::make_tuple((PVOID) ((UINT64) handle), (PVOID) addr, (PVOID) size);
return result; return result;
#else #else
@ -160,27 +110,74 @@ namespace IACore
#endif #endif
} }
Expected<StreamWriter, String> FileOps::StreamToFile(IN CONST FilePath &path) Expected<StreamWriter, String> FileOps::StreamToFile(IN CONST FilePath &path, IN BOOL overwrite)
{ {
if (!overwrite && FileSystem::exists(path))
return MakeUnexpected(std::format("File aready exists: {}", path.c_str()));
return StreamWriter(path);
} }
Expected<StreamReader, String> FileOps::StreamFromFile(IN CONST FilePath &path) Expected<StreamReader, String> FileOps::StreamFromFile(IN CONST FilePath &path)
{ {
if (!FileSystem::exists(path))
return MakeUnexpected(std::format("File does not exist: {}", path.c_str()));
return StreamReader(path);
} }
Expected<String, String> FileOps::ReadTextFile(IN CONST FilePath &path) Expected<String, String> FileOps::ReadTextFile(IN CONST FilePath &path)
{ {
const auto f = fopen(path.c_str(), "rb");
if (!f)
return MakeUnexpected(std::format("Failed to open file: {}", path.c_str()));
String result;
fseek(f, 0, SEEK_END);
result.resize(ftell(f) + 1);
fseek(f, 0, SEEK_SET);
fread(result.data(), 1, result.size() - 1, f);
fclose(f);
result.back() = '\0';
return result;
} }
Expected<Vector<UINT8>, String> FileOps::ReadBinaryFile(IN CONST FilePath &path) Expected<Vector<UINT8>, String> FileOps::ReadBinaryFile(IN CONST FilePath &path)
{ {
const auto f = fopen(path.c_str(), "rb");
if (!f)
return MakeUnexpected(std::format("Failed to open file: {}", path.c_str()));
Vector<UINT8> result;
fseek(f, 0, SEEK_END);
result.resize(ftell(f));
fseek(f, 0, SEEK_SET);
fread(result.data(), 1, result.size(), f);
fclose(f);
return result;
} }
Expected<SIZE_T, String> FileOps::WriteTextFile(IN CONST FilePath &path, IN CONST String &contents) Expected<SIZE_T, String> FileOps::WriteTextFile(IN CONST FilePath &path, IN CONST String &contents,
IN BOOL overwrite)
{ {
if (!overwrite && FileSystem::exists(path))
return MakeUnexpected(std::format("File aready exists: {}", path.c_str()));
const auto f = fopen(path.c_str(), "wb");
if (!f)
return MakeUnexpected(std::format("Failed to write to file: {}", path.c_str()));
const auto result = fwrite(contents.data(), 1, contents.size(), f);
fputc(0, f);
fclose(f);
return result;
} }
Expected<SIZE_T, String> FileOps::WriteBinaryFile(IN CONST FilePath &path, IN Span<UINT8> contents) Expected<SIZE_T, String> FileOps::WriteBinaryFile(IN CONST FilePath &path, IN Span<UINT8> contents,
IN BOOL overwrite)
{ {
if (!overwrite && FileSystem::exists(path))
return MakeUnexpected(std::format("File aready exists: {}", path.c_str()));
const auto f = fopen(path.c_str(), "wb");
if (!f)
return MakeUnexpected(std::format("Failed to write to file: {}", path.c_str()));
const auto result = fwrite(contents.data(), 1, contents.size(), f);
fclose(f);
return result;
} }
} // namespace IACore } // namespace IACore

View File

@ -21,7 +21,7 @@ namespace IACore
{ {
Logger::ELogLevel Logger::s_logLevel{Logger::ELogLevel::WARN}; Logger::ELogLevel Logger::s_logLevel{Logger::ELogLevel::WARN};
HRTimePoint Logger::s_startTime{}; HRTimePoint Logger::s_startTime{};
IACore::File *Logger::s_logFile{}; std::ofstream Logger::s_logFile{};
VOID Logger::Initialize() VOID Logger::Initialize()
{ {
@ -30,19 +30,19 @@ namespace IACore
VOID Logger::Terminate() VOID Logger::Terminate()
{ {
if (s_logFile) if (s_logFile.is_open())
{ {
s_logFile->Close(); s_logFile.flush();
delete s_logFile; s_logFile.close();
} }
} }
BOOL Logger::EnableLoggingToDisk(IN PCCHAR filePath) BOOL Logger::EnableLoggingToDisk(IN PCCHAR filePath)
{ {
if (s_logFile) if (s_logFile.is_open())
return true; return true;
s_logFile = new IACore::File(filePath, IACore::File::EOpenFlags::Write); s_logFile.open(filePath);
return s_logFile->IsOpen(); return s_logFile.is_open();
} }
VOID Logger::SetLogLevel(IN ELogLevel logLevel) VOID Logger::SetLogLevel(IN ELogLevel logLevel)
@ -58,8 +58,8 @@ namespace IACore
std::cout << prefix << outLine << "\033[39m\n"; std::cout << prefix << outLine << "\033[39m\n";
if (s_logFile) if (s_logFile)
{ {
s_logFile->GetStreamHandle()->write(outLine.data(), outLine.size()); s_logFile.write(outLine.data(), outLine.size());
s_logFile->GetStreamHandle()->put('\n'); s_logFile.put('\n');
} }
} }
} // namespace IACore } // namespace IACore

View File

@ -22,7 +22,7 @@ namespace IACore
{ {
StreamReader::StreamReader(IN CONST FilePath &path) : m_storageType(EStorageType::OWNING_MMAP) StreamReader::StreamReader(IN CONST FilePath &path) : m_storageType(EStorageType::OWNING_MMAP)
{ {
const auto t = FileOps::MapReadonlyFile(path, m_dataSize); const auto t = FileOps::MapFile(path, m_dataSize);
if (!t) if (!t)
{ {
Logger::Error("Failed to memory map file {}", path.string()); Logger::Error("Failed to memory map file {}", path.string());

View File

@ -15,7 +15,6 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <IACore/StreamWriter.hpp> #include <IACore/StreamWriter.hpp>
#include <IACore/FileOps.hpp>
#include <IACore/Logger.hpp> #include <IACore/Logger.hpp>
namespace IACore namespace IACore
@ -31,25 +30,38 @@ namespace IACore
{ {
} }
StreamWriter::StreamWriter(IN CONST FilePath &path) : m_storageType(EStorageType::OWNING_MMAP) StreamWriter::StreamWriter(IN CONST FilePath &path) : m_filePath(path), m_storageType(EStorageType::OWNING_FILE)
{ {
const auto t = FileOps::MapFile(path); IA_RELEASE_ASSERT(!path.empty());
if (!t) const auto f = fopen(m_filePath.c_str(), "wb");
if (!f)
{ {
Logger::Error("Failed to memory map file {}", path.string()); Logger::Error("Failed to open file for writing {}", m_filePath.c_str());
return; return;
} }
m_buffer = *t; fputc(0, f);
m_capacity = SIZE_MAX; fclose(f);
m_owningVector.resize(m_capacity = 256);
m_buffer = m_owningVector.data();
} }
StreamWriter::~StreamWriter() StreamWriter::~StreamWriter()
{ {
switch (m_storageType) switch (m_storageType)
{ {
case EStorageType::OWNING_MMAP: case EStorageType::OWNING_FILE: {
FileOps::UnmapFile(m_buffer); IA_RELEASE_ASSERT(!m_filePath.empty());
break; const auto f = fopen(m_filePath.c_str(), "wb");
if (!f)
{
Logger::Error("Failed to open file for writing {}", m_filePath.c_str());
return;
}
fwrite(m_owningVector.data(), 1, m_owningVector.size(), f);
fclose(f);
}
break;
case EStorageType::OWNING_VECTOR: case EStorageType::OWNING_VECTOR:
case EStorageType::NON_OWNING: case EStorageType::NON_OWNING:
@ -60,14 +72,11 @@ namespace IACore
#define HANDLE_OUT_OF_CAPACITY(_size) \ #define HANDLE_OUT_OF_CAPACITY(_size) \
if B_UNLIKELY ((m_cursor + _size) > m_capacity) \ if B_UNLIKELY ((m_cursor + _size) > m_capacity) \
{ \ { \
if (m_storageType == EStorageType::OWNING_VECTOR) \ if (m_storageType == EStorageType::NON_OWNING) \
{ \
m_owningVector.resize(m_capacity + (_size << 1)); \
m_capacity = m_owningVector.size(); \
m_buffer = m_owningVector.data(); \
} \
else \
return false; \ return false; \
m_owningVector.resize(m_capacity + (_size << 1)); \
m_capacity = m_owningVector.size(); \
m_buffer = m_owningVector.data(); \
} }
BOOL StreamWriter::Write(IN UINT8 byte, IN SIZE_T count) BOOL StreamWriter::Write(IN UINT8 byte, IN SIZE_T count)

View File

@ -25,19 +25,17 @@ namespace IACore
{ {
public: public:
STATIC VOID UnmapFile(IN PCUINT8 mappedPtr); STATIC VOID UnmapFile(IN PCUINT8 mappedPtr);
STATIC Expected<PUINT8, String> MapFile(IN CONST FilePath &path); STATIC Expected<PCUINT8, String> MapFile(IN CONST FilePath &path, OUT SIZE_T &size);
STATIC Expected<PCUINT8, String> MapReadonlyFile(IN CONST FilePath &path);
STATIC Expected<PCUINT8, String> MapReadonlyFile(IN CONST FilePath &path, OUT SIZE_T &size);
STATIC Expected<StreamWriter, String> StreamToFile(IN CONST FilePath &path);
STATIC Expected<StreamReader, String> StreamFromFile(IN CONST FilePath &path); STATIC Expected<StreamReader, String> StreamFromFile(IN CONST FilePath &path);
STATIC Expected<StreamWriter, String> StreamToFile(IN CONST FilePath &path, IN BOOL overwrite = false);
STATIC Expected<String, String> ReadTextFile(IN CONST FilePath &path); STATIC Expected<String, String> ReadTextFile(IN CONST FilePath &path);
STATIC Expected<Vector<UINT8>, String> ReadBinaryFile(IN CONST FilePath &path); STATIC Expected<Vector<UINT8>, String> ReadBinaryFile(IN CONST FilePath &path);
STATIC Expected<SIZE_T, String> WriteTextFile(IN CONST FilePath &path, IN CONST String &contents); STATIC Expected<SIZE_T, String> WriteTextFile(IN CONST FilePath &path, IN CONST String &contents, IN BOOL overwrite = false);
STATIC Expected<SIZE_T, String> WriteBinaryFile(IN CONST FilePath &path, IN Span<UINT8> contents); STATIC Expected<SIZE_T, String> WriteBinaryFile(IN CONST FilePath &path, IN Span<UINT8> contents, IN BOOL overwrite = false);
private: private:
STATIC UnorderedMap<PCUINT8, PVOID> s_mappedFiles; STATIC UnorderedMap<PCUINT8, Tuple<PVOID, PVOID, PVOID>> s_mappedFiles;
}; };
} // namespace IACore } // namespace IACore

View File

@ -20,8 +20,6 @@
namespace IACore namespace IACore
{ {
class File;
class Logger class Logger
{ {
public: public:
@ -112,6 +110,6 @@ namespace IACore
private: private:
STATIC ELogLevel s_logLevel; STATIC ELogLevel s_logLevel;
STATIC HRTimePoint s_startTime; STATIC HRTimePoint s_startTime;
STATIC IACore::File *s_logFile; STATIC std::ofstream s_logFile;
}; };
} }

View File

@ -41,6 +41,7 @@
# include <type_traits> # include <type_traits>
# include <initializer_list> # include <initializer_list>
# include <tuple>
# include <array> # include <array>
# include <string> # include <string>
# include <vector> # include <vector>
@ -531,6 +532,8 @@ using UnorderedMap = ankerl::unordered_dense::map<_key_type, _value_type>;
template<typename _value_type> using Atomic = std::atomic<_value_type>; template<typename _value_type> using Atomic = std::atomic<_value_type>;
template<typename _value_type> using SharedPtr = std::shared_ptr<_value_type>; template<typename _value_type> using SharedPtr = std::shared_ptr<_value_type>;
template<typename _value_type> using UniquePtr = std::unique_ptr<_value_type>; template<typename _value_type> using UniquePtr = std::unique_ptr<_value_type>;
template<typename _type_a, typename _type_b> using Pair = std::pair<_type_a, _type_b>;
template<typename... types> using Tuple = std::tuple<types...>;
template<typename _expected_type, typename _unexpected_type> template<typename _expected_type, typename _unexpected_type>
using Expected = tl::expected<_expected_type, _unexpected_type>; using Expected = tl::expected<_expected_type, _unexpected_type>;

View File

@ -25,7 +25,7 @@ namespace IACore
enum class EStorageType enum class EStorageType
{ {
NON_OWNING, NON_OWNING,
OWNING_MMAP, OWNING_FILE,
OWNING_VECTOR, OWNING_VECTOR,
}; };
@ -54,6 +54,7 @@ namespace IACore
PUINT8 m_buffer{}; PUINT8 m_buffer{};
SIZE_T m_cursor{}; SIZE_T m_cursor{};
SIZE_T m_capacity{}; SIZE_T m_capacity{};
FilePath m_filePath{};
Vector<UINT8> m_owningVector; Vector<UINT8> m_owningVector;
CONST EStorageType m_storageType; CONST EStorageType m_storageType;
}; };

View File

@ -40,10 +40,10 @@ set_target_properties(${TEST_NAME_PREFIX}Environment PROPERTIES USE_EXCEPTIONS O
# ------------------------------------------------ # ------------------------------------------------
# Unit: FileOps # Unit: FileOps
# ------------------------------------------------ # ------------------------------------------------
add_executable(${TEST_NAME_PREFIX}FileOps "FileOps.cpp") #add_executable(${TEST_NAME_PREFIX}FileOps "FileOps.cpp")
target_link_libraries(${TEST_NAME_PREFIX}FileOps PRIVATE IACore) #target_link_libraries(${TEST_NAME_PREFIX}FileOps PRIVATE IACore)
target_compile_options(${TEST_NAME_PREFIX}FileOps PRIVATE -fexceptions) #target_compile_options(${TEST_NAME_PREFIX}FileOps PRIVATE -fexceptions)
set_target_properties(${TEST_NAME_PREFIX}FileOps PROPERTIES USE_EXCEPTIONS ON) #set_target_properties(${TEST_NAME_PREFIX}FileOps PROPERTIES USE_EXCEPTIONS ON)
# ------------------------------------------------ # ------------------------------------------------
# Unit: ProcessOps # Unit: ProcessOps