FileStream.cpp 3.6 KB

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