Lib
QOLを高める
file.cpp
Go to the documentation of this file.
1 #include "stdafx.h"
2 #include "include/file.h"
3 #include "include/exceptions.h"
4 #include <windows.h>
5 #include <memory>
6 #include <array>
7 #include <string>
8 
9 namespace yappy {
10 namespace file {
11 
12 using error::throwTrace;
14 
15 namespace {
16 
17 class FileLoader : private util::noncopyable {
18 public:
19  FileLoader() = default;
20  virtual ~FileLoader() = default;
21  virtual std::vector<uint8_t> loadFile(const wchar_t *fileName) = 0;
22 };
23 
24 class FsFileLoader : public FileLoader {
25 public:
26  FsFileLoader(const wchar_t *rootDir) : m_rootDir(rootDir) {}
27  virtual ~FsFileLoader() override {}
28  virtual std::vector<uint8_t> loadFile(const wchar_t *fileName) override;
29 private:
30  std::wstring m_rootDir;
31 };
32 
33 class ArchiveFileLoader : public FileLoader {
34  // TODO: impl
35 };
36 
37 // impls
38 Bytes FsFileLoader::loadFile(const wchar_t *fileName)
39 {
40  std::wstring path;
41  if (fileName[0] == L'/') {
42  // Debug only, abs path
43  path = &fileName[1];
44  }
45  else if (fileName[0] == L'@') {
46  // Debug only, relative to executable
47  std::array<wchar_t, MAX_PATH> dir;
48  DWORD ret = ::GetModuleFileName(nullptr, dir.data(), static_cast<DWORD>(dir.size()));
49  checkWin32Result(ret != 0, "GetModuleFileName() failed");
50  *(::wcsrchr(dir.data(), L'\\') + 1) = L'\0';
51  path = dir.data();
52  path += &fileName[1];
53  }
54  else {
55  path += m_rootDir;
56  path += L'/';
57  path += fileName;
58  }
59 
60  // open
61  HANDLE tmphFile = ::CreateFile(
62  path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING,
63  FILE_ATTRIBUTE_NORMAL, nullptr);
64  checkWin32Result(tmphFile != INVALID_HANDLE_VALUE, "CreateFile() failed");
65  util::HandlePtr hFile(tmphFile);
66 
67  BOOL b = FALSE;
68  // get size to avoid realloc
69  LARGE_INTEGER fileSize = { 0 };
70  b = ::GetFileSizeEx(hFile.get(), &fileSize);
71  checkWin32Result(b != 0, "GetFileSizeEx() failed");
72  // 2GiB check
73  checkWin32Result(fileSize.HighPart == 0, "File size is too large");
74  checkWin32Result(fileSize.LowPart < 0x80000000, "File size is too large");
75  // read
76  Bytes bin(fileSize.LowPart);
77  DWORD readSize = 0;
78  b = ::ReadFile(hFile.get(), bin.data(), fileSize.LowPart, &readSize, nullptr);
79  error::checkWin32Result(b != 0, "ReadFile() failed");
80  error::checkWin32Result(fileSize.LowPart == readSize, "Read size is strange");
81 
82  // move return
83  return bin;
84 }
85 
86 // variables
87 std::unique_ptr<FileLoader> s_fileLoader(nullptr);
88 
89 } // namespace
90 
91 
92 void initWithFileSystem(const wchar_t *rootDir)
93 {
94  s_fileLoader.reset(new FsFileLoader(rootDir));
95 }
96 
97 void initWithArchiveFile(const wchar_t *archiveFile)
98 {
99  // TODO
100  throwTrace<std::logic_error>("Not implemented");
101 }
102 
103 std::vector<uint8_t> loadFile(const wchar_t *fileName)
104 {
105  if (s_fileLoader == nullptr) {
106  throwTrace<std::logic_error>("FileLoader is not initialized.");
107  }
108  return s_fileLoader->loadFile(fileName);
109 }
110 
111 } // namespace file
112 } // namespace yappy
Noncopyable class.
Definition: util.h:24
std::vector< uint8_t > loadFile(const wchar_t *fileName)
Load file from abstract file system.
Definition: file.cpp:103
Definition: config.cpp:6
void initWithFileSystem(const wchar_t *rootDir)
Uses real file system.
Definition: file.cpp:92
void initWithArchiveFile(const wchar_t *archiveFile)
Uses archive file.
Definition: file.cpp:97
std::unique_ptr< HANDLE, HandleDeleter > HandlePtr
unique_ptr of HANDLE with HandleDeleter.
Definition: util.h:64
std::vector< uint8_t > Bytes
File byte sequence. Vector of uint8_t.
Definition: file.h:25
void checkWin32Result(bool cond, const std::string &msg)
Definition: exceptions.h:50