home *** CD-ROM | disk | FTP | other *** search
/ Xentax forum attachments archive / xentax.7z / 7662 / gttool_src_bin.7z / gttool / src / file.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2014-08-01  |  5.5 KB  |  237 lines

  1. #include "file.h"
  2.  
  3. #ifdef _WIN32
  4.     #include <windows.h>
  5. #endif
  6.  
  7. class File::Impl
  8. {
  9. public:
  10.     inline Impl()
  11.         : handle_(INVALID_HANDLE_VALUE)
  12.     {
  13.     }
  14.  
  15.     inline Impl(const char* const file_path, const OpenMode::Flags mode)
  16.         : handle_(INVALID_HANDLE_VALUE)
  17.     {
  18.         open(file_path, mode);
  19.     }
  20.  
  21.     inline ~Impl()
  22.     {
  23.         close();
  24.     }
  25.  
  26.     bool open(const char* const file_path, const OpenMode::Flags mode) 
  27.     {
  28.         DWORD access_mode = 0;
  29.         if ((mode & OpenMode::kREAD) == OpenMode::kREAD)
  30.             access_mode |= FILE_READ_DATA;
  31.         else if ((mode & OpenMode::kWRITE) == OpenMode::kWRITE)
  32.             access_mode |= FILE_WRITE_DATA;
  33.         else if ((mode & OpenMode::kAPPEND) == OpenMode::kAPPEND)
  34.             access_mode |= FILE_WRITE_DATA | FILE_APPEND_DATA;
  35.         assert(access_mode != 0 && "No valid access mode specified.");
  36.  
  37.         DWORD share_mode = FILE_SHARE_READ;
  38.         if ((mode & OpenMode::kSHARE) == OpenMode::kSHARE)
  39.             share_mode |= FILE_SHARE_WRITE;
  40.  
  41.         DWORD creation_mode = 0;
  42.         if ((mode & OpenMode::kRECREATE) == OpenMode::kRECREATE)
  43.             creation_mode = CREATE_ALWAYS;
  44.         else if ((mode & OpenMode::kREAD) == OpenMode::kREAD)
  45.             creation_mode = OPEN_EXISTING;
  46.         else if ((mode & OpenMode::kWRITE) == OpenMode::kWRITE)
  47.             creation_mode = CREATE_NEW;
  48.         else if ((mode & OpenMode::kAPPEND) == OpenMode::kAPPEND)
  49.             creation_mode = OPEN_EXISTING;
  50.         assert(creation_mode != 0 && "No valid creation mode specified.");
  51.  
  52.         DWORD flags = 0;
  53.         if ((mode & OpenMode::kRANDOM_ACCESS) == OpenMode::kRANDOM_ACCESS)
  54.             flags |= FILE_FLAG_RANDOM_ACCESS;
  55.         else
  56.             flags |= FILE_FLAG_SEQUENTIAL_SCAN;
  57.         if ((mode & OpenMode::kWRITE_THROUGH) == OpenMode::kWRITE_THROUGH)
  58.             flags |= FILE_FLAG_WRITE_THROUGH;
  59.         if ((mode & OpenMode::kASYNC) == OpenMode::kASYNC)
  60.             flags |= FILE_FLAG_OVERLAPPED;
  61.  
  62.         handle_ = CreateFileA(file_path, access_mode, share_mode, nullptr, creation_mode, flags, nullptr);
  63.  
  64.         return handle_ != INVALID_HANDLE_VALUE;
  65.     }
  66.  
  67.     inline void close()
  68.     {
  69.         if (handle_ != INVALID_HANDLE_VALUE) {
  70.             CloseHandle(handle_);
  71.             handle_ = INVALID_HANDLE_VALUE;
  72.         }
  73.     }
  74.  
  75.     inline bool read(void* const data, const uint32_t size, uint32_t* const num_read)
  76.     {
  77.         assert(data != nullptr);
  78.         DWORD count;
  79.         if (!ReadFile(handle_, data, size, &count, nullptr)) {
  80.             if (num_read)
  81.                 *num_read = count;
  82.             return false;
  83.         } else {
  84.             if (num_read)
  85.                 *num_read = count;
  86.         }
  87.         return true;
  88.     }
  89.  
  90.     inline bool write(const void* const data, const uint32_t size, uint32_t* const num_written)
  91.     {
  92.         assert(data != nullptr);
  93.         DWORD count;
  94.         if (!WriteFile(handle_, data, size, &count, nullptr)) {
  95.             if (num_written)
  96.                 *num_written = count;
  97.             return false;
  98.         } else {
  99.             if (num_written)
  100.                 *num_written = count;
  101.         }
  102.         return true;
  103.     }
  104.  
  105.     inline bool seek(const uint64_t offset, const uint32_t mode, uint64_t* const position)
  106.     {
  107.         DWORD method;
  108.         switch (mode) {
  109.             case SeekMode::kBEGIN: method = FILE_BEGIN; break;
  110.             case SeekMode::kCURRENT: method = FILE_CURRENT; break;
  111.             case SeekMode::kEND: method = FILE_END; break;
  112.             default:
  113.                 assert(0 && "Invalid seek mode");
  114.                 break;
  115.         }
  116.         LARGE_INTEGER distance, current;
  117.         distance.QuadPart = offset;
  118.         if (!SetFilePointerEx(handle_, distance, ¤t, method))
  119.             return false;
  120.         if (position)
  121.             *position = current.QuadPart;
  122.         return true;
  123.     }
  124.  
  125.     inline uint64_t file_size() const
  126.     {
  127.         LARGE_INTEGER size;
  128.         if (!GetFileSizeEx(handle_, &size))
  129.             return -1;
  130.         return size.QuadPart;
  131.     }
  132.  
  133.     inline bool is_valid() const
  134.     {
  135.         return handle_ != INVALID_HANDLE_VALUE;
  136.     }
  137.  
  138. private:
  139.     HANDLE handle_;
  140. };
  141.  
  142. File::File()
  143.     : impl_(new Impl())
  144. {
  145. }
  146.  
  147. File::File(const char* const file_path, const OpenMode::Flags mode)
  148.     : impl_(new Impl(file_path, mode))
  149. {
  150. }
  151.  
  152. File::~File()
  153. {
  154. }
  155.  
  156. bool File::open(const char* const file_path, const OpenMode::Flags mode)
  157. {
  158.     return impl_->open(file_path, mode);
  159. }
  160.  
  161. void File::close()
  162. {
  163.     impl_->close();
  164. }
  165.  
  166. bool File::read(void* const data, const uint32_t size, uint32_t* const num_read)
  167. {
  168.     return impl_->read(data, size, num_read);
  169. }
  170.  
  171. bool File::write(const void* const data, const uint32_t size, uint32_t* const num_written)
  172. {
  173.     return impl_->write(data, size, num_written);
  174. }
  175.  
  176. bool File::seek(const uint64_t offset, const SeekMode::Enum mode, uint64_t* const pos)
  177. {
  178.     return impl_->seek(offset, mode, pos);
  179. }
  180.  
  181. uint64_t File::file_size() const
  182. {
  183.     return impl_->file_size();
  184. }
  185.  
  186. bool File::is_valid() const
  187. {
  188.     return impl_->is_valid();
  189. }
  190.  
  191. bool read_file(const char* const file_path, char** const data, uint32_t* const size, const uint64_t offset)
  192. {
  193.     assert(file_path != nullptr);
  194.     assert(data != nullptr);
  195.     assert(size != nullptr);
  196.  
  197.     File file(file_path, OpenMode::kREAD | OpenMode::kSHARE);
  198.     if (!file.is_valid())
  199.         return false;
  200.  
  201.     uint32_t buffer_size;
  202.     if (*size == -1) {
  203.         const uint64_t file_size = file.file_size();
  204.         if (file_size - offset > UINT32_MAX)
  205.             return false;
  206.         buffer_size = static_cast<uint32_t>(file_size - offset);
  207.     } else {
  208.         buffer_size = *size;
  209.     }
  210.  
  211.     std::unique_ptr<char[]> buffer(new char[buffer_size]);
  212.     if (!file.read_at(buffer.get(), offset, buffer_size))
  213.         return false;
  214.     file.close();
  215.  
  216.     *data = buffer.release();
  217.     *size = buffer_size;
  218.  
  219.     return true;
  220. }
  221.  
  222. bool write_file(const char* const file_path, const char* const data, const uint32_t size, const uint64_t offset)
  223. {
  224.     assert(file_path != nullptr);
  225.     assert(data != nullptr);
  226.  
  227.     File file(file_path, OpenMode::kWRITE | OpenMode::kRECREATE);
  228.     if (!file.is_valid())
  229.         return false;
  230.  
  231.     if (!file.write_at(data, offset, size))
  232.         return false;
  233.     file.close();
  234.  
  235.     return true;
  236. }
  237.