IOFile.h 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. // Copyright 2008 Dolphin Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <array>
  5. #include <cstddef>
  6. #include <cstdio>
  7. #include <string>
  8. #include <string_view>
  9. #include "Common/CommonTypes.h"
  10. namespace File
  11. {
  12. enum class SeekOrigin
  13. {
  14. Begin,
  15. Current,
  16. End,
  17. };
  18. enum class SharedAccess
  19. {
  20. Default,
  21. Read,
  22. };
  23. // simple wrapper for cstdlib file functions to
  24. // hopefully will make error checking easier
  25. // and make forgetting an fclose() harder
  26. class IOFile
  27. {
  28. public:
  29. IOFile();
  30. IOFile(std::FILE* file);
  31. IOFile(const std::string& filename, const char openmode[],
  32. SharedAccess sh = SharedAccess::Default);
  33. ~IOFile();
  34. IOFile(const IOFile&) = delete;
  35. IOFile& operator=(const IOFile&) = delete;
  36. IOFile(IOFile&& other) noexcept;
  37. IOFile& operator=(IOFile&& other) noexcept;
  38. void Swap(IOFile& other) noexcept;
  39. bool Open(const std::string& filename, const char openmode[],
  40. SharedAccess sh = SharedAccess::Default);
  41. bool Close();
  42. IOFile Duplicate(const char openmode[]) const;
  43. template <typename T>
  44. bool ReadArray(T* elements, size_t count, size_t* num_read = nullptr)
  45. {
  46. size_t read_count = 0;
  47. if (!IsOpen() || count != (read_count = std::fread(elements, sizeof(T), count, m_file)))
  48. m_good = false;
  49. if (num_read)
  50. *num_read = read_count;
  51. return m_good;
  52. }
  53. template <typename T>
  54. bool WriteArray(const T* elements, size_t count)
  55. {
  56. if (!IsOpen() || count != std::fwrite(elements, sizeof(T), count, m_file))
  57. m_good = false;
  58. return m_good;
  59. }
  60. template <typename T, std::size_t N>
  61. bool ReadArray(std::array<T, N>* elements, size_t* num_read = nullptr)
  62. {
  63. return ReadArray(elements->data(), elements->size(), num_read);
  64. }
  65. template <typename T, std::size_t N>
  66. bool WriteArray(const std::array<T, N>& elements)
  67. {
  68. return WriteArray(elements.data(), elements.size());
  69. }
  70. bool ReadBytes(void* data, size_t length)
  71. {
  72. return ReadArray(reinterpret_cast<char*>(data), length);
  73. }
  74. bool WriteBytes(const void* data, size_t length)
  75. {
  76. return WriteArray(reinterpret_cast<const char*>(data), length);
  77. }
  78. bool WriteString(std::string_view str) { return WriteBytes(str.data(), str.size()); }
  79. bool IsOpen() const { return nullptr != m_file; }
  80. // m_good is set to false when a read, write or other function fails
  81. bool IsGood() const { return m_good; }
  82. explicit operator bool() const { return IsGood() && IsOpen(); }
  83. std::FILE* GetHandle() { return m_file; }
  84. void SetHandle(std::FILE* file);
  85. bool Seek(s64 offset, SeekOrigin origin);
  86. u64 Tell() const;
  87. u64 GetSize() const;
  88. bool Resize(u64 size);
  89. bool Flush();
  90. // clear error state
  91. void ClearError()
  92. {
  93. m_good = true;
  94. if (IsOpen())
  95. std::clearerr(m_file);
  96. }
  97. private:
  98. std::FILE* m_file;
  99. bool m_good;
  100. };
  101. } // namespace File