|
11 | 11 | #include "Lib/Utils/FileIO/FileIO.h"
|
12 | 12 | #include <iostream>
|
13 | 13 | #include <sstream>
|
| 14 | +#include <fstream> |
14 | 15 | #if defined(_WIN32) || defined(_WINDOWS)
|
15 | 16 | #include "windows.h"
|
| 17 | + #include <stdio.h> |
| 18 | + #include <fcntl.h> |
16 | 19 | #include <io.h> // File existence
|
17 | 20 | #include <direct.h> // Directory creation
|
18 | 21 | #define access _access_s
|
|
29 | 32 | //---------------------------------------------------------------------------
|
30 | 33 |
|
31 | 34 | //---------------------------------------------------------------------------
|
32 |
| -int filemap::Open_ReadMode(const char* FileName) |
| 35 | +struct private_buffered |
| 36 | +{ |
| 37 | + void* F; |
| 38 | + size_t Data_Shift = 0; |
| 39 | + size_t MaxSize = 0; |
| 40 | +}; |
| 41 | + |
| 42 | +//--------------------------------------------------------------------------- |
| 43 | +int filemap::Open_ReadMode(const char* FileName, method NewStyle, size_t Begin, size_t End) |
33 | 44 | {
|
34 | 45 | Close();
|
35 | 46 |
|
| 47 | + if (NewStyle != method::mmap) |
| 48 | + { |
| 49 | + Method = NewStyle; |
| 50 | + private_buffered* P = new private_buffered; |
| 51 | + P->MaxSize = End - Begin; |
| 52 | + size_t FileSize; |
| 53 | + |
| 54 | + switch (Method) |
| 55 | + { |
| 56 | + default: // case style::fstream: |
| 57 | + { |
| 58 | + auto F = new ifstream(FileName, ios::binary); |
| 59 | + F->seekg(0, F->end); |
| 60 | + FileSize = F->tellg(); |
| 61 | + F->seekg(Begin, F->beg); |
| 62 | + P->F = F; |
| 63 | + break; |
| 64 | + } |
| 65 | + case method::fopen: |
| 66 | + { |
| 67 | + auto F = fopen(FileName, "rb"); |
| 68 | + fseek(F, 0, SEEK_END); |
| 69 | + FileSize = ftell(F); |
| 70 | + fseek(F, (long)Begin, SEEK_SET); |
| 71 | + P->F = F; |
| 72 | + break; |
| 73 | + } |
| 74 | + case method::open: |
| 75 | + { |
| 76 | + struct stat Fstat; |
| 77 | + if (stat(FileName, &Fstat)) |
| 78 | + return 1; |
| 79 | + FileSize = Fstat.st_size; |
| 80 | + #if defined(_WIN32) || defined(_WINDOWS) |
| 81 | + auto F = _open(FileName, _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, _S_IREAD); |
| 82 | + #else //defined(_WIN32) || defined(_WINDOWS) |
| 83 | + auto F = open(FileName, O_RDONLY); |
| 84 | + #endif //defined(_WIN32) || defined(_WINDOWS) |
| 85 | + if (F == -1) |
| 86 | + return 1; |
| 87 | + P->F = (void*)F; |
| 88 | + break; |
| 89 | + } |
| 90 | + #if defined(_WIN32) || defined(_WINDOWS) |
| 91 | + case method::createfile: |
| 92 | + { |
| 93 | + DWORD FileSizeHigh; |
| 94 | + auto NewFile = CreateFileA(FileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); |
| 95 | + auto FileSizeLow = GetFileSize(NewFile, &FileSizeHigh); |
| 96 | + if ((FileSizeLow != INVALID_FILE_SIZE || GetLastError() == NO_ERROR) // If no error (special case with 32-bit max value) |
| 97 | + && (!FileSizeHigh || sizeof(size_t) >= 8)) // Mapping 4+ GiB files is not supported in 32-bit mode |
| 98 | + { |
| 99 | + FileSize = ((size_t)FileSizeHigh) << 32 | FileSizeLow; |
| 100 | + } |
| 101 | + else |
| 102 | + return 1; |
| 103 | + if (Begin) |
| 104 | + { |
| 105 | + LARGE_INTEGER GoTo; |
| 106 | + GoTo.QuadPart = Begin; |
| 107 | + if (!SetFilePointerEx(NewFile, GoTo, nullptr, 0)) |
| 108 | + return 1; |
| 109 | + P->Data_Shift = Begin; |
| 110 | + } |
| 111 | + P->F = NewFile; |
| 112 | + break; |
| 113 | + } |
| 114 | + #endif //defined(_WIN32) || defined(_WINDOWS) |
| 115 | + } |
| 116 | + |
| 117 | + auto Buffer = new uint8_t[P->MaxSize]; |
| 118 | + P->Data_Shift -= P->MaxSize; |
| 119 | + AssignBase(Buffer - P->Data_Shift, FileSize); |
| 120 | + Private2 = (decltype(Private2))P; |
| 121 | + |
| 122 | + return Remap(Begin, End); |
| 123 | + } |
| 124 | + |
36 | 125 | size_t NewSize;
|
37 | 126 | #if defined(_WIN32) || defined(_WINDOWS)
|
38 | 127 | auto NewFile = CreateFileA(FileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
@@ -99,12 +188,58 @@ inline int munmap_const(const void* addr, size_t length)
|
99 | 188 | #pragma GCC diagnostic pop
|
100 | 189 | #endif
|
101 | 190 | #endif
|
102 |
| -int filemap::Remap() |
| 191 | +int filemap::Remap(size_t Begin, size_t End) |
103 | 192 | {
|
104 | 193 | // Special case for 0-byte files
|
105 | 194 | if (Empty())
|
106 | 195 | return 0;
|
107 | 196 |
|
| 197 | + if (Method != method::mmap) |
| 198 | + { |
| 199 | + auto P = (private_buffered*)Private2; |
| 200 | + auto Buffer = Data() + P->Data_Shift; |
| 201 | + auto Buffer_MaxSize = P->MaxSize; |
| 202 | + Begin -= P->Data_Shift; |
| 203 | + if (!End) |
| 204 | + End = Size(); |
| 205 | + End -= P->Data_Shift; |
| 206 | + auto Buffer_Middle = Buffer + Begin; |
| 207 | + auto Buffer_Middle_Size = Buffer_MaxSize - Begin; |
| 208 | + memmove((void*)Buffer, (void*)Buffer_Middle, Buffer_Middle_Size); |
| 209 | + P->Data_Shift += Begin; |
| 210 | + AssignKeepSizeBase(Buffer - P->Data_Shift); |
| 211 | + Buffer += Buffer_Middle_Size; |
| 212 | + Buffer_MaxSize -= Buffer_Middle_Size; |
| 213 | + |
| 214 | + switch (Method) |
| 215 | + { |
| 216 | + default: // case style::fstream: |
| 217 | + { |
| 218 | + auto F = (ifstream*)P->F; |
| 219 | + F->read((char*)Buffer, Buffer_MaxSize); |
| 220 | + break; |
| 221 | + } |
| 222 | + case method::fopen: |
| 223 | + { |
| 224 | + auto F = (FILE*)P->F; |
| 225 | + if (fread((char*)Buffer, Buffer_MaxSize, 1, F) != 1) |
| 226 | + return 1; |
| 227 | + break; |
| 228 | + } |
| 229 | + case method::open: |
| 230 | + return 1; |
| 231 | + #if defined(_WIN32) || defined(_WINDOWS) |
| 232 | + case method::createfile: |
| 233 | + { |
| 234 | + ReadFile(P->F, (LPVOID)Buffer, (DWORD)Buffer_MaxSize, nullptr, 0); |
| 235 | + break; |
| 236 | + } |
| 237 | + #endif //defined(_WIN32) || defined(_WINDOWS) |
| 238 | + } |
| 239 | + |
| 240 | + return 0; |
| 241 | + } |
| 242 | + |
108 | 243 | // Close previous map
|
109 | 244 | if (Data())
|
110 | 245 | {
|
|
0 commit comments