| 17 | #ifndef _WIN32 |
| 18 | template<typename T> |
| 19 | static bool LoadFileImpl(T& Data, const fextl::string& Filepath, size_t FixedSize) { |
| 20 | int FD = open(Filepath.c_str(), O_RDONLY); |
| 21 | |
| 22 | if (FD == -1) { |
| 23 | return false; |
| 24 | } |
| 25 | |
| 26 | size_t FileSize {}; |
| 27 | if (FixedSize == 0) { |
| 28 | struct stat buf; |
| 29 | if (fstat(FD, &buf) == 0) { |
| 30 | FileSize = buf.st_size; |
| 31 | } |
| 32 | } else { |
| 33 | FileSize = FixedSize; |
| 34 | } |
| 35 | |
| 36 | ssize_t CurrentOffset = 0; |
| 37 | ssize_t Read = -1; |
| 38 | bool LoadedFile {}; |
| 39 | if (FileSize) { |
| 40 | // File size is known upfront |
| 41 | Data.resize(FileSize); |
| 42 | while (CurrentOffset != FileSize && (Read = pread(FD, &Data.at(CurrentOffset), FileSize, 0)) > 0) { |
| 43 | CurrentOffset += Read; |
| 44 | } |
| 45 | |
| 46 | LoadedFile = CurrentOffset == FileSize && Read != -1; |
| 47 | } else { |
| 48 | // The file is either empty or its size is unknown (e.g. procfs data). |
| 49 | // Try reading in chunks instead |
| 50 | constexpr size_t READ_SIZE = 4096; |
| 51 | Data.resize(READ_SIZE); |
| 52 | |
| 53 | while ((Read = pread(FD, &Data.at(CurrentOffset), READ_SIZE, CurrentOffset)) > 0) { |
| 54 | CurrentOffset += Read; |
| 55 | if ((CurrentOffset + READ_SIZE) > Data.size()) { |
| 56 | Data.resize(CurrentOffset + READ_SIZE); |
| 57 | } |
| 58 | } |
| 59 | |
| 60 | if (Read == -1) { |
| 61 | Data.clear(); |
| 62 | close(FD); |
| 63 | return false; |
| 64 | } |
| 65 | |
| 66 | // Final resize to ensure there is no garbage data past the end. |
| 67 | Data.resize(CurrentOffset + Read); |
| 68 | |
| 69 | LoadedFile = true; |
| 70 | } |
| 71 | close(FD); |
| 72 | return LoadedFile; |
| 73 | } |
| 74 | |
| 75 | ssize_t LoadFileToBuffer(const fextl::string& Filepath, std::span<char> Buffer) { |
| 76 | int FD = open(Filepath.c_str(), O_RDONLY); |