FileStream.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. #include "StdInc.h"
  2. #include "FileStream.h"
  3. #include "../minizip/unzip.h"
  4. #include <cstdio>
  5. #ifdef _WIN32
  6. #ifndef _CRT_SECURE_NO_WARNINGS
  7. #define _CRT_SECURE_NO_WARNINGS
  8. #endif
  9. #include <cwchar>
  10. #define CHAR_LITERAL(s) L##s
  11. using CharType = wchar_t;
  12. #else
  13. #define CHAR_LITERAL(s) s
  14. using CharType = char;
  15. #endif
  16. inline FILE* do_open(const CharType* name, const CharType* mode)
  17. {
  18. #ifdef _WIN32
  19. return _wfopen(name, mode);
  20. #else
  21. return std::fopen(name, mode);
  22. #endif
  23. }
  24. #define GETFILE static_cast<std::FILE*>(filePtr)
  25. voidpf ZCALLBACK MinizipOpenFunc(voidpf opaque, const void* filename, int mode)
  26. {
  27. const CharType* mode_fopen = [mode]() -> const CharType*
  28. {
  29. if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ)
  30. return CHAR_LITERAL("rb");
  31. else if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
  32. return CHAR_LITERAL("r+b");
  33. else if (mode & ZLIB_FILEFUNC_MODE_CREATE)
  34. return CHAR_LITERAL("wb");
  35. return nullptr;
  36. }();
  37. if (filename != nullptr && mode_fopen != nullptr)
  38. return do_open(static_cast<const CharType*>(filename), mode_fopen);
  39. else
  40. return nullptr;
  41. }
  42. zlib_filefunc64_def* FileStream::GetMinizipFilefunc()
  43. {
  44. static zlib_filefunc64_def MinizipFilefunc;
  45. static bool initialized = false;
  46. if (!initialized) {
  47. fill_fopen64_filefunc((&MinizipFilefunc));
  48. MinizipFilefunc.zopen64_file = &MinizipOpenFunc;
  49. initialized = true;
  50. }
  51. return &MinizipFilefunc;
  52. }
  53. template class boost::iostreams::stream<FileBuf>;
  54. /*static*/
  55. bool FileStream::CreateFile(const boost::filesystem::path& filename)
  56. {
  57. FILE* f = do_open(filename.c_str(), CHAR_LITERAL("wb"));
  58. bool result = (f != nullptr);
  59. fclose(f);
  60. return result;
  61. }
  62. FileBuf::FileBuf(const boost::filesystem::path& filename, std::ios_base::openmode mode)
  63. {
  64. auto openmode = [mode]() -> std::basic_string<CharType>
  65. {
  66. using namespace std;
  67. switch (mode & (~ios_base::ate & ~ios_base::binary))
  68. {
  69. case (ios_base::in):
  70. return CHAR_LITERAL("r");
  71. case (ios_base::out):
  72. case (ios_base::out | ios_base::trunc):
  73. return CHAR_LITERAL("w");
  74. case (ios_base::app):
  75. case (ios_base::out | ios_base::app):
  76. return CHAR_LITERAL("a");
  77. case (ios_base::out | ios_base::in):
  78. return CHAR_LITERAL("r+");
  79. case (ios_base::out | ios_base::in | ios_base::trunc):
  80. return CHAR_LITERAL("w+");
  81. case (ios_base::out | ios_base::in | ios_base::app):
  82. case (ios_base::in | ios_base::app):
  83. return CHAR_LITERAL("a+");
  84. default:
  85. throw std::ios_base::failure("invalid open mode");
  86. }
  87. }();
  88. if (mode & std::ios_base::binary)
  89. openmode += CHAR_LITERAL('b');
  90. filePtr = do_open(filename.c_str(), openmode.c_str());
  91. if (filePtr == nullptr)
  92. throw std::ios_base::failure("could not open file");
  93. if (mode & std::ios_base::ate) {
  94. if (std::fseek(GETFILE, 0, SEEK_END)) {
  95. fclose(GETFILE);
  96. throw std::ios_base::failure("could not open file");
  97. }
  98. }
  99. }
  100. void FileBuf::close()
  101. {
  102. std::fclose(GETFILE);
  103. }
  104. std::streamsize FileBuf::read(char* s, std::streamsize n)
  105. {
  106. return static_cast<std::streamsize>(std::fread(s, 1, n, GETFILE));
  107. }
  108. std::streamsize FileBuf::write(const char* s, std::streamsize n)
  109. {
  110. return static_cast<std::streamsize>(std::fwrite(s, 1, n, GETFILE));
  111. }
  112. std::streamoff FileBuf::seek(std::streamoff off, std::ios_base::seekdir way)
  113. {
  114. const auto src = [way]() -> int
  115. {
  116. switch(way)
  117. {
  118. case std::ios_base::beg:
  119. return SEEK_SET;
  120. case std::ios_base::cur:
  121. return SEEK_CUR;
  122. case std::ios_base::end:
  123. return SEEK_END;
  124. default:
  125. throw std::ios_base::failure("bad seek direction");
  126. }
  127. }();
  128. if(std::fseek(GETFILE, off, src))
  129. throw std::ios_base::failure("bad seek offset");
  130. return static_cast<std::streamsize>(std::ftell(GETFILE));
  131. }