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/SocketOps.cpp"
"imp/cpp/ProcessOps.cpp"
"imp/cpp/BinaryStreamReader.cpp"
"imp/cpp/BinaryStreamWriter.cpp"
"imp/cpp/StreamReader.cpp"
"imp/cpp/StreamWriter.cpp"
)
add_library(IACore STATIC ${SRC_FILES})

View File

@ -18,76 +18,26 @@
namespace IACore
{
UnorderedMap<PCUINT8, PVOID> FileOps::s_mappedFiles;
UnorderedMap<PCUINT8, Tuple<PVOID, PVOID, PVOID>> FileOps::s_mappedFiles;
VOID FileOps::UnmapFile(IN PCUINT8 mappedPtr)
{
if (!s_mappedFiles.contains(mappedPtr))
return;
const auto handle = s_mappedFiles.extract(mappedPtr)->second;
const auto handles = s_mappedFiles.extract(mappedPtr)->second;
#if IA_PLATFORM_WINDOWS
::UnmapViewOfFile(std::get<1>(handles));
::CloseHandle(std::get<2>(handles));
::CloseHandle(std::get<0>(handles));
#elif IA_PLATFORM_UNIX
::munmap(std::get<1>(handles), (SIZE_T) std::get<2>(handles));
::close((INT32) ((UINT64) std::get<0>(handles)));
#else
# error "IACore FileOps does not support this platform"
#endif
}
Expected<PUINT8, String> FileOps::MapFile(IN CONST FilePath &path)
{
#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)
Expected<PCUINT8, String> FileOps::MapFile(IN CONST FilePath &path, OUT SIZE_T &size)
{
#if IA_PLATFORM_WINDOWS
@ -124,7 +74,7 @@ namespace IACore
CloseHandle(hmap);
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;
#elif IA_PLATFORM_UNIX
@ -152,7 +102,7 @@ namespace IACore
}
const auto result = static_cast<PCUINT8>(addr);
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;
#else
@ -160,27 +110,74 @@ namespace IACore
#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)
{
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)
{
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)
{
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

View File

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

View File

@ -22,7 +22,7 @@ namespace IACore
{
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)
{
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/>.
#include <IACore/StreamWriter.hpp>
#include <IACore/FileOps.hpp>
#include <IACore/Logger.hpp>
namespace IACore
@ -31,24 +30,37 @@ 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);
if (!t)
IA_RELEASE_ASSERT(!path.empty());
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;
}
m_buffer = *t;
m_capacity = SIZE_MAX;
fputc(0, f);
fclose(f);
m_owningVector.resize(m_capacity = 256);
m_buffer = m_owningVector.data();
}
StreamWriter::~StreamWriter()
{
switch (m_storageType)
{
case EStorageType::OWNING_MMAP:
FileOps::UnmapFile(m_buffer);
case EStorageType::OWNING_FILE: {
IA_RELEASE_ASSERT(!m_filePath.empty());
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:
@ -60,14 +72,11 @@ namespace IACore
#define HANDLE_OUT_OF_CAPACITY(_size) \
if B_UNLIKELY ((m_cursor + _size) > m_capacity) \
{ \
if (m_storageType == EStorageType::OWNING_VECTOR) \
{ \
if (m_storageType == EStorageType::NON_OWNING) \
return false; \
m_owningVector.resize(m_capacity + (_size << 1)); \
m_capacity = m_owningVector.size(); \
m_buffer = m_owningVector.data(); \
} \
else \
return false; \
}
BOOL StreamWriter::Write(IN UINT8 byte, IN SIZE_T count)

View File

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

View File

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

View File

@ -41,6 +41,7 @@
# include <type_traits>
# include <initializer_list>
# include <tuple>
# include <array>
# include <string>
# 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 SharedPtr = std::shared_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>
using Expected = tl::expected<_expected_type, _unexpected_type>;

View File

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

View File

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