🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

150 lines
4.4 KiB

  1. #include "config.h"
  2. #include "alfstream.h"
  3. #include "strutils.h"
  4. #ifdef _WIN32
  5. namespace al {
  6. auto filebuf::underflow() -> int_type
  7. {
  8. if(mFile != INVALID_HANDLE_VALUE && gptr() == egptr())
  9. {
  10. // Read in the next chunk of data, and set the pointers on success
  11. DWORD got{};
  12. if(ReadFile(mFile, mBuffer.data(), static_cast<DWORD>(mBuffer.size()), &got, nullptr))
  13. setg(mBuffer.data(), mBuffer.data(), mBuffer.data()+got);
  14. }
  15. if(gptr() == egptr())
  16. return traits_type::eof();
  17. return traits_type::to_int_type(*gptr());
  18. }
  19. auto filebuf::seekoff(off_type offset, std::ios_base::seekdir whence, std::ios_base::openmode mode) -> pos_type
  20. {
  21. if(mFile == INVALID_HANDLE_VALUE || (mode&std::ios_base::out) || !(mode&std::ios_base::in))
  22. return traits_type::eof();
  23. LARGE_INTEGER fpos{};
  24. switch(whence)
  25. {
  26. case std::ios_base::beg:
  27. fpos.QuadPart = offset;
  28. if(!SetFilePointerEx(mFile, fpos, &fpos, FILE_BEGIN))
  29. return traits_type::eof();
  30. break;
  31. case std::ios_base::cur:
  32. // If the offset remains in the current buffer range, just
  33. // update the pointer.
  34. if((offset >= 0 && offset < off_type(egptr()-gptr())) ||
  35. (offset < 0 && -offset <= off_type(gptr()-eback())))
  36. {
  37. // Get the current file offset to report the correct read
  38. // offset.
  39. fpos.QuadPart = 0;
  40. if(!SetFilePointerEx(mFile, fpos, &fpos, FILE_CURRENT))
  41. return traits_type::eof();
  42. setg(eback(), gptr()+offset, egptr());
  43. return fpos.QuadPart - off_type(egptr()-gptr());
  44. }
  45. // Need to offset for the file offset being at egptr() while
  46. // the requested offset is relative to gptr().
  47. offset -= off_type(egptr()-gptr());
  48. fpos.QuadPart = offset;
  49. if(!SetFilePointerEx(mFile, fpos, &fpos, FILE_CURRENT))
  50. return traits_type::eof();
  51. break;
  52. case std::ios_base::end:
  53. fpos.QuadPart = offset;
  54. if(!SetFilePointerEx(mFile, fpos, &fpos, FILE_END))
  55. return traits_type::eof();
  56. break;
  57. default:
  58. return traits_type::eof();
  59. }
  60. setg(nullptr, nullptr, nullptr);
  61. return fpos.QuadPart;
  62. }
  63. auto filebuf::seekpos(pos_type pos, std::ios_base::openmode mode) -> pos_type
  64. {
  65. // Simplified version of seekoff
  66. if(mFile == INVALID_HANDLE_VALUE || (mode&std::ios_base::out) || !(mode&std::ios_base::in))
  67. return traits_type::eof();
  68. LARGE_INTEGER fpos{};
  69. fpos.QuadPart = pos;
  70. if(!SetFilePointerEx(mFile, fpos, &fpos, FILE_BEGIN))
  71. return traits_type::eof();
  72. setg(nullptr, nullptr, nullptr);
  73. return fpos.QuadPart;
  74. }
  75. filebuf::~filebuf()
  76. { close(); }
  77. bool filebuf::open(const wchar_t *filename, std::ios_base::openmode mode)
  78. {
  79. if((mode&std::ios_base::out) || !(mode&std::ios_base::in))
  80. return false;
  81. HANDLE f{CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING,
  82. FILE_ATTRIBUTE_NORMAL, nullptr)};
  83. if(f == INVALID_HANDLE_VALUE) return false;
  84. if(mFile != INVALID_HANDLE_VALUE)
  85. CloseHandle(mFile);
  86. mFile = f;
  87. setg(nullptr, nullptr, nullptr);
  88. return true;
  89. }
  90. bool filebuf::open(const char *filename, std::ios_base::openmode mode)
  91. {
  92. std::wstring wname{utf8_to_wstr(filename)};
  93. return open(wname.c_str(), mode);
  94. }
  95. void filebuf::close()
  96. {
  97. if(mFile != INVALID_HANDLE_VALUE)
  98. CloseHandle(mFile);
  99. mFile = INVALID_HANDLE_VALUE;
  100. }
  101. ifstream::ifstream(const wchar_t *filename, std::ios_base::openmode mode)
  102. : std::istream{nullptr}
  103. {
  104. init(&mStreamBuf);
  105. // Set the failbit if the file failed to open.
  106. if((mode&std::ios_base::out) || !mStreamBuf.open(filename, mode|std::ios_base::in))
  107. clear(failbit);
  108. }
  109. ifstream::ifstream(const char *filename, std::ios_base::openmode mode)
  110. : std::istream{nullptr}
  111. {
  112. init(&mStreamBuf);
  113. // Set the failbit if the file failed to open.
  114. if((mode&std::ios_base::out) || !mStreamBuf.open(filename, mode|std::ios_base::in))
  115. clear(failbit);
  116. }
  117. /* This is only here to ensure the compiler doesn't define an implicit
  118. * destructor, which it tries to automatically inline and subsequently complain
  119. * it can't inline without excessive code growth.
  120. */
  121. ifstream::~ifstream() { }
  122. } // namespace al
  123. #endif