159 lines
3.3 KiB
C++
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
|