file.hpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. #pragma once
  2. #include <nall/file-buffer.hpp>
  3. namespace nall {
  4. struct file : inode {
  5. struct mode { enum : uint { read, write, modify, append }; };
  6. struct index { enum : uint { absolute, relative }; };
  7. file() = delete;
  8. static auto open(const string& filename, uint mode) -> file_buffer {
  9. return file_buffer{filename, mode};
  10. }
  11. static auto copy(const string& sourcename, const string& targetname) -> bool {
  12. if(sourcename == targetname) return true;
  13. if(auto reader = file::open(sourcename, mode::read)) {
  14. if(auto writer = file::open(targetname, mode::write)) {
  15. for(uint64_t n : range(reader.size())) writer.write(reader.read());
  16. return true;
  17. }
  18. }
  19. return false;
  20. }
  21. //attempt to rename file first
  22. //this will fail if paths point to different file systems; fall back to copy+remove in this case
  23. static auto move(const string& sourcename, const string& targetname) -> bool {
  24. if(sourcename == targetname) return true;
  25. if(rename(sourcename, targetname)) return true;
  26. if(!writable(sourcename)) return false;
  27. if(copy(sourcename, targetname)) return remove(sourcename), true;
  28. return false;
  29. }
  30. static auto truncate(const string& filename, uint64_t size) -> bool {
  31. #if defined(API_POSIX)
  32. return truncate(filename, size) == 0;
  33. #elif defined(API_WINDOWS)
  34. if(auto fp = _wfopen(utf16_t(filename), L"rb+")) {
  35. bool result = _chsize(fileno(fp), size) == 0;
  36. fclose(fp);
  37. return result;
  38. }
  39. return false;
  40. #endif
  41. }
  42. //returns false if specified filename is a directory
  43. static auto exists(const string& filename) -> bool {
  44. #if defined(API_POSIX)
  45. struct stat data;
  46. if(stat(filename, &data) != 0) return false;
  47. #elif defined(API_WINDOWS)
  48. struct __stat64 data;
  49. if(_wstat64(utf16_t(filename), &data) != 0) return false;
  50. #endif
  51. return !(data.st_mode & S_IFDIR);
  52. }
  53. static auto size(const string& filename) -> uint64_t {
  54. #if defined(API_POSIX)
  55. struct stat data;
  56. stat(filename, &data);
  57. #elif defined(API_WINDOWS)
  58. struct __stat64 data;
  59. _wstat64(utf16_t(filename), &data);
  60. #endif
  61. return S_ISREG(data.st_mode) ? data.st_size : 0u;
  62. }
  63. static auto read(const string& filename) -> vector<uint8_t> {
  64. vector<uint8_t> memory;
  65. if(auto fp = file::open(filename, mode::read)) {
  66. memory.resize(fp.size());
  67. fp.read(memory);
  68. }
  69. return memory;
  70. }
  71. static auto read(const string& filename, array_span<uint8_t> memory) -> bool {
  72. if(auto fp = file::open(filename, mode::read)) return fp.read(memory), true;
  73. return false;
  74. }
  75. static auto write(const string& filename, array_view<uint8_t> memory) -> bool {
  76. if(auto fp = file::open(filename, mode::write)) return fp.write(memory), true;
  77. return false;
  78. }
  79. //create an empty file (will replace existing files)
  80. static auto create(const string& filename) -> bool {
  81. if(auto fp = file::open(filename, mode::write)) return true;
  82. return false;
  83. }
  84. static auto sha256(const string& filename) -> string {
  85. return Hash::SHA256(read(filename)).digest();
  86. }
  87. };
  88. }