iutest  1.17.99.14
iutest_file.hpp
[詳解]
1 //======================================================================
2 //-----------------------------------------------------------------------
13 //-----------------------------------------------------------------------
14 //======================================================================
15 #ifndef INCG_IRIS_IUTEST_FILE_HPP_77D2C2B9_F504_4BB5_BA56_D97A2EB37DC6_
16 #define INCG_IRIS_IUTEST_FILE_HPP_77D2C2B9_F504_4BB5_BA56_D97A2EB37DC6_
17 
18 //======================================================================
19 // include
20 // IWYU pragma: begin_exports
21 #include "iutest_internal_defs.hpp"
22 #include "iutest_stream.hpp"
23 
24 #if defined(IUTEST_OS_WINDOWS)
25 #include <io.h>
26 #include <fcntl.h>
27 #include <share.h>
28 #endif
29 // IWYU pragma: end_exports
30 
31 namespace iutest
32 {
33 
34 //======================================================================
35 // class
39 class IFile : public detail::IOutStream, public detail::IInStream
40 {
41 public:
43  enum OpenFlag
44  {
45  OpenRead = 0x00000001,
46  OpenWrite = 0x00000002,
47  OpenAppend = 0x00000003
48  };
49 public:
50  virtual ~IFile() {}
51 
52 public:
59  bool Open(const char* filename, int mode)
60  {
61  return OpenImpl(filename, mode);
62  }
63 
64 #if IUTEST_HAS_STD_FILESYSTEM
71  bool Open(const ::std::filesystem::path& path, int mode)
72  {
73  return Open(path.string().c_str(), mode);
74  }
75 #endif
76 
78  virtual void Close() = 0;
79 private:
80  virtual bool OpenImpl(const char* filename, int mode) = 0;
81 };
82 
83 namespace detail
84 {
85 
89 class IFileSystem
90 {
91 public:
92  IFileSystem()
93  {
94  SetInstance(this);
95  }
96  virtual ~IFileSystem()
97  {
98  SetInstance(NULL);
99  }
100 
101 public:
102  virtual void Initialize() {}
103 
104 public:
105  static IFileSystem* GetInstance() { return GetInstanceVariable().pInstance; }
106 
107 public:
108  static IFile* New()
109  {
110  IFileSystem* fs = GetInstance();
111  if( fs == NULL )
112  {
113  return NULL;
114  }
115  IFile* p = fs->Create();
116  return p;
117  }
118  static void Free(IFile* ptr)
119  {
120  IFileSystem* fs = GetInstance();
121  if( fs == NULL )
122  {
123  return;
124  }
125  fs->Delete(ptr);
126  }
127 
128  static bool ReadAll(const char* filename, ::std::string& dst)
129  {
130  IFile* fp = detail::IFileSystem::New();
131  if(fp == NULL)
132  {
133  return false;
134  }
135 
136  if(!fp->Open(filename, IFile::OpenRead))
137  {
138  detail::IFileSystem::Free(fp);
139  return false;
140  }
141 
142  dst = fp->ReadAll();
143  detail::IFileSystem::Free(fp);
144  return true;
145  }
146 
147 private:
148  virtual IFile* Create() = 0;
149  virtual void Delete(IFile*) = 0;
150 
151 private:
152  struct InstanceVariable
153  {
154  IFileSystem* pInstance;
155  };
156 
157  static InstanceVariable& GetInstanceVariable() { static InstanceVariable v; return v; }
158  static void SetInstance(IFileSystem* pFileSystem) { GetInstanceVariable().pInstance = pFileSystem; }
159 };
160 
161 } // end of namespace detail
162 } // end of namespace iutest
163 
164 namespace iutest
165 {
166 
170 template<typename FILE>
171 class FileSystem IUTEST_CXX_FINAL : public detail::IFileSystem
172 {
173 private:
174  virtual IFile* Create() IUTEST_CXX_OVERRIDE { return new FILE; }
175  virtual void Delete(IFile* ptr) IUTEST_CXX_OVERRIDE { detail::Delete<FILE>(static_cast<FILE*>(ptr)); }
176 };
177 
178 
179 #if IUTEST_HAS_FOPEN
180 
184 class StdioFile : public IFile
185 {
186 protected:
187  FILE* m_fp;
188 public:
189  StdioFile() IUTEST_CXX_NOEXCEPT_SPEC : m_fp(NULL) {}
190  virtual ~StdioFile() { StdioFile::Close(); }
191 public:
195  virtual void Close() IUTEST_CXX_OVERRIDE
196  {
197  if( m_fp != NULL )
198  {
199  fclose(m_fp);
200  m_fp = NULL;
201  }
202  }
209  virtual bool Write(const void* buf, size_t size, size_t cnt) IUTEST_CXX_OVERRIDE
210  {
211  if( fwrite(buf, size, cnt, m_fp) < cnt )
212  {
213  return false;
214  }
215  if( fflush(m_fp) != 0 )
216  {
217  return false;
218  }
219  return true;
220  }
221 
228  virtual bool Read(void* buf, size_t size, size_t cnt) IUTEST_CXX_OVERRIDE
229  {
230  if( fread(buf, size, cnt, m_fp) < cnt )
231  {
232  return false;
233  }
234  return true;
235  }
236 
238  virtual iu_uint_max_t GetSize() IUTEST_CXX_OVERRIDE
239  {
240  return GetSize(m_fp);
241  }
242 
243 public:
244  void Flush()
245  {
246  fflush(m_fp);
247  }
248 
249 public:
250  static iu_uint_max_t GetSize(FILE* fp)
251  {
252  return internal::posix::FileSize(fp);
253  }
254  static iu_uint_max_t GetSizeBySeekSet(FILE* fp)
255  {
256  return internal::posix::FileSizeBySeekSet(fp);
257  }
258 private:
259  virtual bool OpenImpl(const char* filename, int mode) IUTEST_CXX_OVERRIDE
260  {
261  Close();
262  switch( mode )
263  {
264  case IFile::OpenRead:
265  m_fp = internal::posix::FileOpen(filename, "rb");
266  break;
267  case IFile::OpenWrite:
268  m_fp = internal::posix::FileOpen(filename, "wb");
269  break;
270  case IFile::OpenAppend:
271  m_fp = internal::posix::FileOpen(filename, "ab");
272  break;
273  default:
274  break;
275  }
276  return m_fp != NULL;
277  }
278 };
279 
280 class StdErrorFile : public StdioFile
281 {
282 public:
284  virtual ~StdErrorFile() { Close(); }
285 public:
289  virtual void Close() IUTEST_CXX_OVERRIDE
290  {
291  m_fp = NULL;
292  }
293 private:
294  virtual bool OpenImpl(const char* , int ) IUTEST_CXX_OVERRIDE
295  {
296  m_fp = stderr;
297  return true;
298  }
299 };
300 
301 class TempFile : public IFile
302 {
303 public:
305  : m_fd(-1)
306  {
307  }
308 
309  virtual ~TempFile() { Close(); }
310 
311 public:
315  virtual void Close() IUTEST_CXX_OVERRIDE
316  {
317  m_file.Close();
318  if( m_fd != -1 )
319  {
320  internal::posix::FdClose(m_fd);
321  m_fd = -1;
322  }
323  }
330  virtual bool Write(const void* buf, size_t size, size_t cnt) IUTEST_CXX_OVERRIDE
331  {
332  return m_file.Write(buf, size, cnt);
333  }
334 
341  virtual bool Read(void* buf, size_t size, size_t cnt) IUTEST_CXX_OVERRIDE
342  {
343  return m_file.Read(buf, size, cnt);
344  }
345 
347  virtual iu_uint_max_t GetSize() IUTEST_CXX_OVERRIDE
348  {
349  return m_file.GetSize();
350  }
351 
352 public:
353  int GetDescriptor() const { return m_fd; }
354  const ::std::string& GetFileName() const { return m_filename; }
355 
356  bool Open(int mode)
357  {
358  return OpenImpl(m_filename.c_str(), mode);
359  }
360 
361  void Delete()
362  {
363  Close();
364  if( !m_filename.empty() )
365  {
366  remove(m_filename.c_str());
367  m_filename = "";
368  }
369  }
370 
371  bool Create(const char* basename)
372  {
373 #if defined(IUTEST_OS_WINDOWS)
374  char tmp_dir[IUTEST_MAX_PATH] = { '\0' };
375  GetTempPathA(sizeof(tmp_dir), tmp_dir);
376 
377  char name_template[IUTEST_MAX_PATH] = { '\0' };
378  UINT ret = GetTempFileNameA(tmp_dir, basename, 0, name_template);
379  IUTEST_CHECK_(ret != 0) << "Unable to create a temporary file in " << tmp_dir;
380 #if defined(_CRT_FUNCTIONS_REQUIRED)
381 IUTEST_PRAGMA_CRT_SECURE_WARN_DISABLE_BEGIN()
382  const int fd = _creat(name_template, _S_IREAD | _S_IWRITE);
383 IUTEST_PRAGMA_CRT_SECURE_WARN_DISABLE_END()
384 #else
385 #if defined(IUTEST_OS_WINDOWS_MINGW)
386  const int fd = _sopen(name_template, _O_CREAT | _O_RDWR, _SH_DENYNO, _S_IREAD | _S_IWRITE);
387 #else
388  int fd = -1;
389  _sopen_s(&fd, name_template, _O_CREAT | _O_RDWR, _SH_DENYNO, _S_IREAD | _S_IWRITE);
390 #endif
391 #endif
392 #else
393 #if defined(IUTEST_OS_LINUX_ANDROID)
394  ::std::string name_template = "/data/local/tmp/";
395 #elif defined(IUTEST_OS_IOS)
396  char user_temp_dir[IUTEST_MAX_PATH];
397  ::confstr(_CS_DARWIN_USER_TEMP_DIR, user_temp_dir, sizeof(user_temp_dir));
398  ::std::string name_template = user_temp_dir;
399  name_template += "/";
400 #else
401  ::std::string name_template = "/tmp/";
402 #endif
403  name_template += basename;
404  name_template += ".XXXXXX";
405  const int fd = internal::posix::Mkstemp(const_cast<char*>(name_template.data()));
406 #endif
407  m_fd = fd;
408  m_filename = name_template;
409  return m_fd != -1;
410  }
411 
412 private:
413  bool Open(const char*, int);
414 
415  virtual bool OpenImpl(const char* filename, int mode) IUTEST_CXX_OVERRIDE
416  {
417  return m_file.Open(filename, mode);
418  }
419 
420 private:
421  StdioFile m_file;
422  int m_fd;
423  ::std::string m_filename;
424 };
425 
426 #endif
427 
428 
429 #if IUTEST_HAS_STRINGSTREAM
430 
434 class StringStreamFile : public IFile
435 {
436 public:
437  virtual ~StringStreamFile() { StringStreamFile::Close(); }
438 public:
442  virtual void Close() IUTEST_CXX_OVERRIDE
443  {
444  }
445 
452  virtual bool Write(const void* buf, size_t size, size_t cnt) IUTEST_CXX_OVERRIDE
453  {
454  for( size_t i=0; i < cnt; ++i )
455  {
456  ss.write(static_cast<const char*>(buf), size);
457  }
458  return true;
459  }
460 
467  virtual bool Read(void* buf, size_t size, size_t cnt) IUTEST_CXX_OVERRIDE
468  {
469  char* p = static_cast<char*>(buf);
470  for( size_t i = 0; i < cnt; ++i )
471  {
472  ss.read(p, size);
473  p += size;
474  }
475  return true;
476  }
477 
479  virtual iu_uint_max_t GetSize() IUTEST_CXX_OVERRIDE
480  {
481  ::std::stringstream::pos_type pre = ss.tellg();
482  ss.seekg(0, ::std::ios::end);
483  ::std::stringstream::pos_type size = ss.tellg();
484  ss.seekg(pre, ::std::ios::beg);
485  return static_cast<iu_uint_max_t>(size);
486  }
487 
489  virtual ::std::string ReadAll() IUTEST_CXX_OVERRIDE
490  {
491  return ss.str();
492  }
493 private:
494  virtual bool OpenImpl(const char* , int ) IUTEST_CXX_OVERRIDE
495  {
496  ss.clear();
497  return true;
498  }
499 protected:
500  ::std::stringstream ss;
501 };
502 
503 #endif
504 
505 namespace detail
506 {
507 
511 class NoEffectFile IUTEST_CXX_FINAL : public IFile
512 {
513 public:
514  virtual void Close() IUTEST_CXX_OVERRIDE {}
515  virtual bool Write(const void*, size_t, size_t) IUTEST_CXX_OVERRIDE { return true; }
516  virtual bool Read(void*, size_t, size_t) IUTEST_CXX_OVERRIDE { return true; }
517  virtual iu_uint_max_t GetSize() IUTEST_CXX_OVERRIDE { return 0; }
518 private:
519  virtual bool OpenImpl(const char*, int) IUTEST_CXX_OVERRIDE { return true; }
520 };
521 
522 } // end of namespace detail
523 } // end of namespace iutest
524 
525 #endif // INCG_IRIS_IUTEST_FILE_HPP_77D2C2B9_F504_4BB5_BA56_D97A2EB37DC6_
ファイルクラスインターフェイス
Definition: iutest_file.hpp:41
bool Open(const char *filename, int mode)
開く
Definition: iutest_file.hpp:60
OpenFlag
ファイルオープンモードフラグ
Definition: iutest_file.hpp:45
@ OpenAppend
追記
Definition: iutest_file.hpp:48
@ OpenWrite
書き込み
Definition: iutest_file.hpp:47
@ OpenRead
読み込み
Definition: iutest_file.hpp:46
virtual void Close()=0
閉じる
Definition: iutest_file.hpp:282
virtual void Close() IUTEST_CXX_OVERRIDE
閉じる
Definition: iutest_file.hpp:290
標準ファイルクラス
Definition: iutest_file.hpp:186
virtual bool Write(const void *buf, size_t size, size_t cnt) IUTEST_CXX_OVERRIDE
書き込み
Definition: iutest_file.hpp:210
virtual bool Read(void *buf, size_t size, size_t cnt) IUTEST_CXX_OVERRIDE
読み込み
Definition: iutest_file.hpp:229
virtual iu_uint_max_t GetSize() IUTEST_CXX_OVERRIDE
サイズ取得
Definition: iutest_file.hpp:239
virtual void Close() IUTEST_CXX_OVERRIDE
閉じる
Definition: iutest_file.hpp:196
文字列バッファ書き込み IFile インターフェースクラス
Definition: iutest_file.hpp:436
virtual iu_uint_max_t GetSize() IUTEST_CXX_OVERRIDE
サイズ取得
Definition: iutest_file.hpp:480
virtual bool Read(void *buf, size_t size, size_t cnt) IUTEST_CXX_OVERRIDE
読み込み
Definition: iutest_file.hpp:468
virtual void Close() IUTEST_CXX_OVERRIDE
閉じる
Definition: iutest_file.hpp:443
virtual ::std::string ReadAll() IUTEST_CXX_OVERRIDE
全読み込み
Definition: iutest_file.hpp:490
virtual bool Write(const void *buf, size_t size, size_t cnt) IUTEST_CXX_OVERRIDE
書き込み
Definition: iutest_file.hpp:453
Definition: iutest_file.hpp:303
virtual bool Read(void *buf, size_t size, size_t cnt) IUTEST_CXX_OVERRIDE
読み込み
Definition: iutest_file.hpp:342
virtual iu_uint_max_t GetSize() IUTEST_CXX_OVERRIDE
サイズ取得
Definition: iutest_file.hpp:348
virtual bool Write(const void *buf, size_t size, size_t cnt) IUTEST_CXX_OVERRIDE
書き込み
Definition: iutest_file.hpp:331
virtual void Close() IUTEST_CXX_OVERRIDE
閉じる
Definition: iutest_file.hpp:316
#define IUTEST_CXX_FINAL
final definition
Definition: iutest_compiler.hpp:756
#define IUTEST_CXX_OVERRIDE
override definition
Definition: iutest_compiler.hpp:747
#define IUTEST_CXX_NOEXCEPT_SPEC
noexcept specification definition
Definition: iutest_compiler.hpp:811
internal definition
#define IUTEST_CHECK_(condition)
内部エラーチェック
Definition: iutest_port.hpp:63
iutest root namespace
Definition: iutest_charcode.hpp:33