home *** CD-ROM | disk | FTP | other *** search
- #include "file.h"
-
- #ifdef _WIN32
- #include <windows.h>
- #endif
-
- class File::Impl
- {
- public:
- inline Impl()
- : handle_(INVALID_HANDLE_VALUE)
- {
- }
-
- inline Impl(const char* const file_path, const OpenMode::Flags mode)
- : handle_(INVALID_HANDLE_VALUE)
- {
- open(file_path, mode);
- }
-
- inline ~Impl()
- {
- close();
- }
-
- bool open(const char* const file_path, const OpenMode::Flags mode)
- {
- DWORD access_mode = 0;
- if ((mode & OpenMode::kREAD) == OpenMode::kREAD)
- access_mode |= FILE_READ_DATA;
- else if ((mode & OpenMode::kWRITE) == OpenMode::kWRITE)
- access_mode |= FILE_WRITE_DATA;
- else if ((mode & OpenMode::kAPPEND) == OpenMode::kAPPEND)
- access_mode |= FILE_WRITE_DATA | FILE_APPEND_DATA;
- assert(access_mode != 0 && "No valid access mode specified.");
-
- DWORD share_mode = FILE_SHARE_READ;
- if ((mode & OpenMode::kSHARE) == OpenMode::kSHARE)
- share_mode |= FILE_SHARE_WRITE;
-
- DWORD creation_mode = 0;
- if ((mode & OpenMode::kRECREATE) == OpenMode::kRECREATE)
- creation_mode = CREATE_ALWAYS;
- else if ((mode & OpenMode::kREAD) == OpenMode::kREAD)
- creation_mode = OPEN_EXISTING;
- else if ((mode & OpenMode::kWRITE) == OpenMode::kWRITE)
- creation_mode = CREATE_NEW;
- else if ((mode & OpenMode::kAPPEND) == OpenMode::kAPPEND)
- creation_mode = OPEN_EXISTING;
- assert(creation_mode != 0 && "No valid creation mode specified.");
-
- DWORD flags = 0;
- if ((mode & OpenMode::kRANDOM_ACCESS) == OpenMode::kRANDOM_ACCESS)
- flags |= FILE_FLAG_RANDOM_ACCESS;
- else
- flags |= FILE_FLAG_SEQUENTIAL_SCAN;
- if ((mode & OpenMode::kWRITE_THROUGH) == OpenMode::kWRITE_THROUGH)
- flags |= FILE_FLAG_WRITE_THROUGH;
- if ((mode & OpenMode::kASYNC) == OpenMode::kASYNC)
- flags |= FILE_FLAG_OVERLAPPED;
-
- handle_ = CreateFileA(file_path, access_mode, share_mode, nullptr, creation_mode, flags, nullptr);
-
- return handle_ != INVALID_HANDLE_VALUE;
- }
-
- inline void close()
- {
- if (handle_ != INVALID_HANDLE_VALUE) {
- CloseHandle(handle_);
- handle_ = INVALID_HANDLE_VALUE;
- }
- }
-
- inline bool read(void* const data, const uint32_t size, uint32_t* const num_read)
- {
- assert(data != nullptr);
- DWORD count;
- if (!ReadFile(handle_, data, size, &count, nullptr)) {
- if (num_read)
- *num_read = count;
- return false;
- } else {
- if (num_read)
- *num_read = count;
- }
- return true;
- }
-
- inline bool write(const void* const data, const uint32_t size, uint32_t* const num_written)
- {
- assert(data != nullptr);
- DWORD count;
- if (!WriteFile(handle_, data, size, &count, nullptr)) {
- if (num_written)
- *num_written = count;
- return false;
- } else {
- if (num_written)
- *num_written = count;
- }
- return true;
- }
-
- inline bool seek(const uint64_t offset, const uint32_t mode, uint64_t* const position)
- {
- DWORD method;
- switch (mode) {
- case SeekMode::kBEGIN: method = FILE_BEGIN; break;
- case SeekMode::kCURRENT: method = FILE_CURRENT; break;
- case SeekMode::kEND: method = FILE_END; break;
- default:
- assert(0 && "Invalid seek mode");
- break;
- }
- LARGE_INTEGER distance, current;
- distance.QuadPart = offset;
- if (!SetFilePointerEx(handle_, distance, ¤t, method))
- return false;
- if (position)
- *position = current.QuadPart;
- return true;
- }
-
- inline uint64_t file_size() const
- {
- LARGE_INTEGER size;
- if (!GetFileSizeEx(handle_, &size))
- return -1;
- return size.QuadPart;
- }
-
- inline bool is_valid() const
- {
- return handle_ != INVALID_HANDLE_VALUE;
- }
-
- private:
- HANDLE handle_;
- };
-
- File::File()
- : impl_(new Impl())
- {
- }
-
- File::File(const char* const file_path, const OpenMode::Flags mode)
- : impl_(new Impl(file_path, mode))
- {
- }
-
- File::~File()
- {
- }
-
- bool File::open(const char* const file_path, const OpenMode::Flags mode)
- {
- return impl_->open(file_path, mode);
- }
-
- void File::close()
- {
- impl_->close();
- }
-
- bool File::read(void* const data, const uint32_t size, uint32_t* const num_read)
- {
- return impl_->read(data, size, num_read);
- }
-
- bool File::write(const void* const data, const uint32_t size, uint32_t* const num_written)
- {
- return impl_->write(data, size, num_written);
- }
-
- bool File::seek(const uint64_t offset, const SeekMode::Enum mode, uint64_t* const pos)
- {
- return impl_->seek(offset, mode, pos);
- }
-
- uint64_t File::file_size() const
- {
- return impl_->file_size();
- }
-
- bool File::is_valid() const
- {
- return impl_->is_valid();
- }
-
- bool read_file(const char* const file_path, char** const data, uint32_t* const size, const uint64_t offset)
- {
- assert(file_path != nullptr);
- assert(data != nullptr);
- assert(size != nullptr);
-
- File file(file_path, OpenMode::kREAD | OpenMode::kSHARE);
- if (!file.is_valid())
- return false;
-
- uint32_t buffer_size;
- if (*size == -1) {
- const uint64_t file_size = file.file_size();
- if (file_size - offset > UINT32_MAX)
- return false;
- buffer_size = static_cast<uint32_t>(file_size - offset);
- } else {
- buffer_size = *size;
- }
-
- std::unique_ptr<char[]> buffer(new char[buffer_size]);
- if (!file.read_at(buffer.get(), offset, buffer_size))
- return false;
- file.close();
-
- *data = buffer.release();
- *size = buffer_size;
-
- return true;
- }
-
- bool write_file(const char* const file_path, const char* const data, const uint32_t size, const uint64_t offset)
- {
- assert(file_path != nullptr);
- assert(data != nullptr);
-
- File file(file_path, OpenMode::kWRITE | OpenMode::kRECREATE);
- if (!file.is_valid())
- return false;
-
- if (!file.write_at(data, offset, size))
- return false;
- file.close();
-
- return true;
- }
-