Files
core_misc/tjp/core/file/File.cpp
Timothy Prepscius fa54be052a flatten 20260225
2026-02-25 12:39:24 -05:00

159 lines
3.3 KiB
C++

// TJP COPYRIGHT HEADER
#include "File.h"
#include <iostream>
#include <fstream>
#include <sys/stat.h>
#include <sys/types.h>
#include <utime.h>
#include <tjp/core/exception/Exception.hpp>
#include <tjp/core/string/to_string.hpp>
#include <tjp/core/string/StringView+concat.hpp>
namespace tjp::core::file {
TJP_CORE_HEADER_ONLY_INLINE
Optional<size_t> size(const StringView& path)
{
std::ifstream file(String(path), std::ios::ate | std::ios::binary);
bool exists = (bool)file;
if (!exists || !file.is_open())
return {};
size_t fileSize = (size_t)file.tellg();
return fileSize;
}
TJP_CORE_HEADER_ONLY_INLINE
Optional<Contents> readRange(const StringView& path, s64 offset, size_t length)
{
std::ifstream file(String(path), std::ios::ate | std::ios::binary);
bool exists = (bool)file;
if (!exists || !file.is_open())
return {};
size_t fileSize = (size_t)file.tellg();
if (offset < 0)
offset += s64(fileSize);
if (offset < 0)
return {};
if (fileSize < offset + length)
return {};
Contents buffer(length);
file.seekg(offset);
file.read(buffer.data(), buffer.size());
file.close();
return buffer;
};
TJP_CORE_HEADER_ONLY_INLINE
bool pathExists (const StringView &file)
{
struct stat status;
return (stat (file.data(), &status)==0);
}
TJP_CORE_HEADER_ONLY_INLINE
bool ensurePath (const StringView &base_, const StringView &path)
{
char delimiter = '/';
// find the end of the last portion of the path we need to create
auto finalPos = path.rfind(delimiter);
if (finalPos == path.npos)
return true;
auto base = String(base_);
if (!base.empty() && base.back() != delimiter)
base += delimiter;
decltype(finalPos) pos = 0;
auto colonpos = path.find(':');
auto firstdelimiterpos = path.find(delimiter);
if (colonpos > 0 && firstdelimiterpos > 0 && colonpos < firstdelimiterpos)
{
// Skip the first one if there's a colon ('c:/blah/whaterver')
pos = path.find (delimiter, pos+1);
}
while (pos<finalPos)
{
// find the next part of the path to create
pos = path.find (delimiter, pos+1);
// does it already exist
#ifdef WIN32
// pull it out as a separate string
std::wstring directory_ = toLongPath(path.substr (0, pos));
std::wstring directory = base + directory_;
WIN32_FILE_ATTRIBUTE_DATA data;
bool exists = GetFileAttributesExW (base + directory.c_str(), GetFileExInfoStandard, &data) > 0;
if (exists)
{
// if it does exist, but is not a directory, ensurePath fails
if (!(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
return false;
}
else
{
// if it does not exist create it, if this fails ensurePath fails
if (_wmkdir (directory.c_str())!=0)
return false;
}
#else
auto directory_ = path.substr (0, pos);
auto directory = base + directory_;
struct stat status;
int exists = (stat (directory.c_str(), &status)==0);
if (exists)
{
// if it does exist, but is not a directory, ensurePath fails
if (!(status.st_mode & S_IFDIR))
return false;
}
else
{
// if it does not exist create it, if this fails ensurePath fails
auto result = mkdir (directory.c_str(), (S_IRWXU | S_IRWXG | S_IRWXO));
if (result)
return false;
}
#endif
}
return true;
}
TJP_CORE_HEADER_ONLY_INLINE
bool ensurePath (const StringView &path)
{
return ensurePath("", path);
}
} // namespace