17 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
21 #elif defined(_WIN32) || defined(_WIN64)
34 explicit Impl(
const Path* path) :
_path(path), _read(false), _read_index(0), _read_size(0), _read_buffer(), _write(false), _write_index(0), _write_size(0), _write_buffer()
36 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
38 #elif defined(_WIN32) || defined(_WIN64)
39 _file = INVALID_HANDLE_VALUE;
50 catch (
const FileSystemException& ex)
52 fatality(FileSystemException(ex.string()).Attach(path()));
56 const Path& path()
const {
return *
_path; }
62 throwex FileSystemException(
"File is not opened!").Attach(path());
63 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
64 off_t result = lseek(_file, 0, SEEK_CUR);
65 if (result == (off_t)-1)
66 throwex FileSystemException(
"Cannot seek the file!").Attach(path());
67 return (uint64_t)result;
68 #elif defined(_WIN32) || defined(_WIN64)
72 if (!SetFilePointerEx(_file, seek, &result, FILE_CURRENT))
73 throwex FileSystemException(
"Cannot seek the file!").Attach(path());
74 return (uint64_t)result.QuadPart;
80 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
84 int result = fstat(_file, &status);
86 throwex FileSystemException(
"Cannot get the current file size!").Attach(path());
87 return (uint64_t)status.st_size;
92 int result = stat(path().
string().c_str(), &status);
94 throwex FileSystemException(
"Cannot get the current file size!").Attach(path());
95 return (uint64_t)status.st_size;
97 #elif defined(_WIN32) || defined(_WIN64)
100 LARGE_INTEGER result;
101 if (!GetFileSizeEx(_file, &result))
102 throwex FileSystemException(
"Cannot get the current file size!").Attach(path());
103 return (uint64_t)result.QuadPart;
107 WIN32_FILE_ATTRIBUTE_DATA fad;
108 if (!GetFileAttributesExW(path().
wstring().c_str(), GetFileExInfoStandard, &fad))
109 throwex FileSystemException(
"Cannot get the current file size!").Attach(path());
111 LARGE_INTEGER result;
112 result.HighPart = fad.nFileSizeHigh;
113 result.LowPart = fad.nFileSizeLow;
114 return (uint64_t)result.QuadPart;
121 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
123 #elif defined(_WIN32) || defined(_WIN64)
124 return (_file != INVALID_HANDLE_VALUE);
144 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
171 _file = open(path().
string().c_str(), O_CREAT | O_EXCL | ((read && write) ? O_RDWR : (read ? O_RDONLY : (write ? O_WRONLY : 0))), mode);
173 throwex FileSystemException(
"Cannot create a new file!").Attach(path());
174 #elif defined(_WIN32) || defined(_WIN64)
175 DWORD dwFlagsAndAttributes = 0;
177 dwFlagsAndAttributes |= FILE_ATTRIBUTE_NORMAL;
179 dwFlagsAndAttributes |= FILE_ATTRIBUTE_ARCHIVE;
181 dwFlagsAndAttributes |= FILE_ATTRIBUTE_HIDDEN;
183 dwFlagsAndAttributes |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
185 dwFlagsAndAttributes |= FILE_ATTRIBUTE_OFFLINE;
187 dwFlagsAndAttributes |= FILE_ATTRIBUTE_READONLY;
189 dwFlagsAndAttributes |= FILE_ATTRIBUTE_SYSTEM;
191 dwFlagsAndAttributes |= FILE_ATTRIBUTE_TEMPORARY;
193 _file = CreateFileW(path().
wstring().c_str(), (read ? GENERIC_READ : 0) | (write ? GENERIC_WRITE : 0), FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, CREATE_NEW, dwFlagsAndAttributes,
nullptr);
194 if (_file == INVALID_HANDLE_VALUE)
195 throwex FileSystemException(
"Cannot create a new file!").Attach(path());
202 _read_buffer.resize(buffer);
209 _write_buffer.resize(buffer);
218 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
245 _file = open(path().
string().c_str(), ((read && write) ? O_RDWR : (read ? O_RDONLY : (write ? O_WRONLY : 0))) | (truncate ? O_TRUNC : 0), mode);
247 throwex FileSystemException(
"Cannot create a new file!").Attach(path());
248 #elif defined(_WIN32) || defined(_WIN64)
249 DWORD dwFlagsAndAttributes = 0;
251 dwFlagsAndAttributes |= FILE_ATTRIBUTE_NORMAL;
253 dwFlagsAndAttributes |= FILE_ATTRIBUTE_ARCHIVE;
255 dwFlagsAndAttributes |= FILE_ATTRIBUTE_HIDDEN;
257 dwFlagsAndAttributes |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
259 dwFlagsAndAttributes |= FILE_ATTRIBUTE_OFFLINE;
261 dwFlagsAndAttributes |= FILE_ATTRIBUTE_READONLY;
263 dwFlagsAndAttributes |= FILE_ATTRIBUTE_SYSTEM;
265 dwFlagsAndAttributes |= FILE_ATTRIBUTE_TEMPORARY;
267 _file = CreateFileW(path().
wstring().c_str(), (read ? GENERIC_READ : 0) | (write ? GENERIC_WRITE : 0), FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, (truncate ? TRUNCATE_EXISTING : OPEN_EXISTING), dwFlagsAndAttributes,
nullptr);
268 if (_file == INVALID_HANDLE_VALUE)
269 throwex FileSystemException(
"Cannot open existing file!").Attach(path());
276 _read_buffer.resize(buffer);
283 _write_buffer.resize(buffer);
292 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
319 _file = open(path().
string().c_str(), O_CREAT | ((read && write) ? O_RDWR : (read ? O_RDONLY : (write ? O_WRONLY : 0))) | (truncate ? O_TRUNC : 0), mode);
321 throwex FileSystemException(
"Cannot create a new file!").Attach(path());
322 #elif defined(_WIN32) || defined(_WIN64)
323 DWORD dwFlagsAndAttributes = 0;
325 dwFlagsAndAttributes |= FILE_ATTRIBUTE_NORMAL;
327 dwFlagsAndAttributes |= FILE_ATTRIBUTE_ARCHIVE;
329 dwFlagsAndAttributes |= FILE_ATTRIBUTE_HIDDEN;
331 dwFlagsAndAttributes |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
333 dwFlagsAndAttributes |= FILE_ATTRIBUTE_OFFLINE;
335 dwFlagsAndAttributes |= FILE_ATTRIBUTE_READONLY;
337 dwFlagsAndAttributes |= FILE_ATTRIBUTE_SYSTEM;
339 dwFlagsAndAttributes |= FILE_ATTRIBUTE_TEMPORARY;
341 _file = CreateFileW(path().
wstring().c_str(), (read ? GENERIC_READ : 0) | (write ? GENERIC_WRITE : 0), FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, (truncate ? CREATE_ALWAYS : OPEN_ALWAYS), dwFlagsAndAttributes,
nullptr);
342 if (_file == INVALID_HANDLE_VALUE)
343 throwex FileSystemException(
"Cannot open existing file!").Attach(path());
350 _read_buffer.resize(buffer);
357 _write_buffer.resize(buffer);
360 size_t Read(
void* buffer,
size_t size)
362 if ((buffer ==
nullptr) || (
size == 0))
367 throwex FileSystemException(
"File is not opened for reading!").Attach(path());
370 if (_read_buffer.empty())
372 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
373 ssize_t result = read(_file, buffer,
size);
375 throwex FileSystemException(
"Cannot read from the file!").Attach(path());
376 return (
size_t)result;
377 #elif defined(_WIN32) || defined(_WIN64)
379 if (!ReadFile(_file, buffer, (DWORD)
size, &result,
nullptr))
380 throwex FileSystemException(
"Cannot read from the file!").Attach(path());
381 return (
size_t)result;
385 uint8_t* bytes = (uint8_t*)buffer;
391 if (_read_index == _read_size)
394 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
395 ssize_t result = read(_file, _read_buffer.data(), _read_buffer.size());
397 throwex FileSystemException(
"Cannot read from the file!").Attach(path());
398 _read_size = (size_t)result;
399 #elif defined(_WIN32) || defined(_WIN64)
401 if (!ReadFile(_file, _read_buffer.data(), (DWORD)_read_buffer.size(), &result,
nullptr))
402 throwex FileSystemException(
"Cannot read from the file!").Attach(path());
403 _read_size = (size_t)result;
411 size_t remain = _read_size - _read_index;
412 size_t num = (
size < remain) ?
size : remain;
413 std::memcpy(bytes, _read_buffer.data() + _read_index, num);
423 size_t Write(
const void* buffer,
size_t size)
425 if ((buffer ==
nullptr) || (
size == 0))
430 throwex FileSystemException(
"File is not opened for writing!").Attach(path());
433 if (_write_buffer.empty())
435 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
436 ssize_t result = write(_file, buffer,
size);
438 throwex FileSystemException(
"Cannot write into the file!").Attach(path());
439 return (
size_t)result;
440 #elif defined(_WIN32) || defined(_WIN64)
442 if (!WriteFile(_file, buffer, (DWORD)
size, &result,
nullptr))
443 throwex FileSystemException(
"Cannot write into the file!").Attach(path());
444 return (
size_t)result;
448 const uint8_t* bytes = (
const uint8_t*)buffer;
454 if (_write_size == _write_buffer.size())
456 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
457 ssize_t result = write(_file, _write_buffer.data() + _write_index, (_write_size - _write_index));
459 throwex FileSystemException(
"Cannot write into the file!").Attach(path());
460 _write_index += (size_t)result;
461 #elif defined(_WIN32) || defined(_WIN64)
463 if (!WriteFile(_file, _write_buffer.data() + _write_index, (DWORD)(_write_size - _write_index), &result,
nullptr))
464 throwex FileSystemException(
"Cannot write into the file!").Attach(path());
465 _write_index += (size_t)result;
468 if (_write_index != _write_size)
477 size_t remain = _write_buffer.size() - _write_size;
478 size_t num = (
size < remain) ?
size : remain;
479 std::memcpy(_write_buffer.data() + _write_size, bytes, num);
493 throwex FileSystemException(
"File is not opened!").Attach(path());
500 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
501 off_t result = lseek(_file, (off_t)
offset, SEEK_SET);
502 if (result == (off_t)-1)
503 throwex FileSystemException(
"Cannot seek the file!").Attach(path());
504 #elif defined(_WIN32) || defined(_WIN64)
506 LARGE_INTEGER result;
508 if (!SetFilePointerEx(_file, seek, &result, FILE_BEGIN))
509 throwex FileSystemException(
"Cannot seek the file!").Attach(path());
515 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
518 int result = ftruncate(_file, (off_t)
size);
520 throwex FileSystemException(
"Cannot resize the current file!").Attach(path());
524 int result = truncate(path().
string().c_str(), (off_t)
size);
526 throwex FileSystemException(
"Cannot resize the current file!").Attach(path());
528 #elif defined(_WIN32) || defined(_WIN64)
533 if (!SetEndOfFile(_file))
534 throwex FileSystemException(
"Cannot resize the current file!").Attach(path());
550 throwex FileSystemException(
"File is not opened for writing!").Attach(path());
551 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
553 size_t remain = _write_size - _write_index;
556 ssize_t result = write(_file, _write_buffer.data() + _write_index, (_write_size - _write_index));
558 throwex FileSystemException(
"Cannot write into the file during the flush operation!").Attach(path());
559 _write_index += (size_t)result;
560 if (_write_index != _write_size)
561 throwex FileSystemException(
"Cannot write all remaining data into the file during the flush operation!").Attach(path());
567 #elif defined(_WIN32) || defined(_WIN64)
569 size_t remain = _write_size - _write_index;
573 if (!WriteFile(_file, _write_buffer.data() + _write_index, (DWORD)(_write_size - _write_index), &result,
nullptr))
574 throwex FileSystemException(
"Cannot write into the file during the flush operation!").Attach(path());
575 _write_index += (size_t)result;
576 if (_write_index != _write_size)
577 throwex FileSystemException(
"Cannot write all remaining data into the file during the flush operation!").Attach(path());
589 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
590 int result = fsync(_file);
592 throwex FileSystemException(
"Cannot flush the file buffers!").Attach(path());
593 #elif defined(_WIN32) || defined(_WIN64)
594 if (!FlushFileBuffers(_file))
595 throwex FileSystemException(
"Cannot flush the file buffers!").Attach(path());
603 throwex FileSystemException(
"File is not opened!").Attach(path());
607 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
608 int result = close(_file);
610 throwex FileSystemException(
"Cannot close the file descriptor!").Attach(path());
612 #elif defined(_WIN32) || defined(_WIN64)
613 if (!CloseHandle(_file))
614 throwex FileSystemException(
"Cannot close the file handle!").Attach(path());
615 _file = INVALID_HANDLE_VALUE;
621 _read_buffer.clear();
627 _write_buffer.clear();
632 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
634 #elif defined(_WIN32) || defined(_WIN64)
641 std::vector<uint8_t> _read_buffer;
647 std::vector<uint8_t> _write_buffer;
660 static_assert((StorageSize >=
sizeof(Impl)),
"File::StorageSize must be increased!");
661 static_assert(((StorageAlign %
alignof(Impl)) == 0),
"File::StorageAlign must be adjusted!");
664 new(&_storage)Impl(
this);
671 static_assert((StorageSize >=
sizeof(Impl)),
"File::StorageSize must be increased!");
672 static_assert(((StorageAlign %
alignof(Impl)) == 0),
"File::StorageAlign must be adjusted!");
675 new(&_storage)Impl(
this);
682 static_assert((StorageSize >=
sizeof(Impl)),
"File::StorageSize must be increased!");
683 static_assert(((StorageAlign %
alignof(Impl)) == 0),
"File::StorageAlign must be adjusted!");
686 new(&_storage)Impl(
this);
697 reinterpret_cast<Impl*
>(&_storage)->~Impl();
702 File(file).swap(*
this);
717 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
719 int result = stat(
string().c_str(), &status);
722 if ((errno == ENOENT) || (errno == ENOTDIR))
728 if (S_ISDIR(status.st_mode))
730 else if (S_ISREG(status.st_mode))
732 else if (S_ISBLK(status.st_mode))
734 else if (S_ISCHR(status.st_mode))
736 else if (S_ISFIFO(status.st_mode))
738 else if (S_ISSOCK(status.st_mode))
742 #elif defined(_WIN32) || defined(_WIN64)
747 return (
attributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
756 void File::Open(
bool read,
bool write,
bool truncate,
const Flags<FileAttributes>& attributes,
const Flags<FilePermissions>& permissions,
size_t buffer) { impl().Open(read, write, truncate,
attributes,
permissions, buffer); }
757 void File::OpenOrCreate(
bool read,
bool write,
bool truncate,
const Flags<FileAttributes>& attributes,
const Flags<FilePermissions>& permissions,
size_t buffer) { impl().OpenOrCreate(read, write, truncate,
attributes,
permissions, buffer); }
759 size_t File::Read(
void* buffer,
size_t size) {
return impl().Read(buffer,
size); }
760 size_t File::Write(
const void* buffer,
size_t size) {
return impl().Write(buffer,
size); }
770 temp.Open(
true,
false);
771 std::vector<uint8_t> result =
temp.ReadAllBytes();
779 temp.Open(
true,
false);
780 std::string result =
temp.ReadAllText();
788 temp.Open(
true,
false);
789 std::vector<std::string> result =
temp.ReadAllLines();
797 temp.OpenOrCreate(
false,
true,
true);
798 size_t result =
temp.Write(buffer,
size);
806 temp.OpenOrCreate(
false,
true,
true);
807 size_t result =
temp.Write(text);
815 temp.OpenOrCreate(
false,
true,
true);
816 size_t result =
temp.Write(lines);
824 temp.OpenOrCreate(
false,
true,
true);
832 swap(_storage, file._storage);
833 swap(impl()._path, file.impl()._path);
void Close()
Close the file.
size_t Read(void *buffer, size_t size) override
Read a bytes buffer from the opened file.
static const Flags< FilePermissions > DEFAULT_PERMISSIONS
Default file permissions (IRUSR | IWUSR | IRGRP | IROTH)
void Resize(uint64_t size)
Resize the current file.
static size_t WriteAllLines(const Path &path, const std::vector< std::string > &lines)
Write text lines into the given file.
static size_t WriteAllText(const Path &path, const std::string &text)
Write a text string into the given file.
File()
Initialize file with an empty path.
void OpenOrCreate(bool read, bool write, bool truncate=false, const Flags< FileAttributes > &attributes=File::DEFAULT_ATTRIBUTES, const Flags< FilePermissions > &permissions=File::DEFAULT_PERMISSIONS, size_t buffer=File::DEFAULT_BUFFER)
Open or create file.
uint64_t size() const
Get the current file size.
bool IsFileReadOpened() const
Is the file opened for reading?
virtual size_t Write(const void *buffer, size_t size)=0
Write a byte buffer base method.
bool IsFileOpened() const
Is the file opened?
static const size_t DEFAULT_BUFFER
Default file buffer size (8192)
void Flush() override
Flush the file.
bool IsFileWriteOpened() const
Is the file opened for writing?
File & operator=(const Path &path)
void Create(bool read, bool write, const Flags< FileAttributes > &attributes=File::DEFAULT_ATTRIBUTES, const Flags< FilePermissions > &permissions=File::DEFAULT_PERMISSIONS, size_t buffer=File::DEFAULT_BUFFER)
Create a new file.
bool IsFileExists() const
Is the file exists?
void Open(bool read, bool write, bool truncate=false, const Flags< FileAttributes > &attributes=File::DEFAULT_ATTRIBUTES, const Flags< FilePermissions > &permissions=File::DEFAULT_PERMISSIONS, size_t buffer=File::DEFAULT_BUFFER)
Open an existing file.
std::vector< std::string > ReadAllLines()
Read all text lines.
void Seek(uint64_t offset)
Seek into the opened file.
static const Flags< FileAttributes > DEFAULT_ATTRIBUTES
Default file attributes (Normal)
std::vector< uint8_t > ReadAllBytes()
Read all bytes.
std::string ReadAllText()
Read all text.
void swap(File &file) noexcept
Swap two instances.
static size_t WriteAllBytes(const Path &path, const void *buffer, size_t size)
Write a bytes buffer into the given file.
static void WriteEmpty(const Path &path)
Write an empty file.
uint64_t offset() const
Get the current read/write offset of the opened file.
FileSystemException & Attach(const Path &path)
Attach the given path to the exception.
std::wstring wstring() const
Get the path value as a wide string.
Flags< FileAttributes > attributes() const
Get the path file attributes.
Path()
Initialize path with an empty value.
void swap(Path &path) noexcept
Swap two instances.
Flags< FilePermissions > permissions() const
Get the path file permissions.
static Path temp()
Get the temporary path of the process.
static Path current()
Get the current path of the process.
std::string _path
Path string.
Aligned storage validator.
#define throwex
Throw extended exception macro.
Fatal abort execution definition.
#define fatality(...)
Fatal abort execution extended macro.
Filesystem file definition.
C++ Common project definitions.
void swap(FileCache &cache1, FileCache &cache2) noexcept
@ IXOTH
Execute or search permission bit for other users.
@ IWUSR
Write permission bit for the owner of the file.
@ IWGRP
Write permission bit for the group owner of the file.
@ IXUSR
Execute (for ordinary files) or search (for directories) permission bit for the owner of the file.
@ ISVTX
This is the sticky bit.
@ IRGRP
Read permission bit for the group owner of the file.
@ IRUSR
Read permission bit for the owner of the file.
@ IXGRP
Execute or search permission bit for the group owner of the file.
@ IWOTH
Write permission bit for other users.
@ IROTH
Read permission bit for other users.
@ ISUID
This is the set-user-ID on execute bit.
@ ISGID
This is the set-group-ID on execute bit.
Aligned storage validator definition.