|
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 | + union f |
| 38 | + { |
| 39 | + FILE* File; |
| 40 | + ifstream* Ifstream; |
| 41 | + int Int; |
| 42 | + #if defined(_WIN32) || defined(_WINDOWS) |
| 43 | + HANDLE Handle; |
| 44 | + #endif |
| 45 | + }; |
| 46 | + f F; |
| 47 | + size_t Data_Shift = 0; |
| 48 | + size_t MaxSize = 0; |
| 49 | +}; |
| 50 | + |
| 51 | +//--------------------------------------------------------------------------- |
| 52 | +int filemap::Open_ReadMode(const char* FileName, method NewStyle, size_t Begin, size_t End) |
33 | 53 | {
|
34 | 54 | Close();
|
35 | 55 |
|
| 56 | + if (NewStyle != method::mmap) |
| 57 | + { |
| 58 | + Method = NewStyle; |
| 59 | + private_buffered* P = new private_buffered; |
| 60 | + P->MaxSize = End - Begin; |
| 61 | + size_t FileSize; |
| 62 | + |
| 63 | + switch (Method) |
| 64 | + { |
| 65 | + default: // case style::fstream: |
| 66 | + { |
| 67 | + auto F = new ifstream(FileName, ios::binary); |
| 68 | + F->seekg(0, F->end); |
| 69 | + FileSize = F->tellg(); |
| 70 | + F->seekg(Begin, F->beg); |
| 71 | + P->F.Ifstream = F; |
| 72 | + break; |
| 73 | + } |
| 74 | + case method::fopen: |
| 75 | + { |
| 76 | + struct stat Fstat; |
| 77 | + if (stat(FileName, &Fstat)) |
| 78 | + return 1; |
| 79 | + FileSize = Fstat.st_size; |
| 80 | + auto F = fopen(FileName, "rb"); |
| 81 | + P->F.File = F; |
| 82 | + break; |
| 83 | + } |
| 84 | + case method::open: |
| 85 | + { |
| 86 | + struct stat Fstat; |
| 87 | + if (stat(FileName, &Fstat)) |
| 88 | + return 1; |
| 89 | + FileSize = Fstat.st_size; |
| 90 | + #if defined(_WIN32) || defined(_WINDOWS) |
| 91 | + auto F = _open(FileName, _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, _S_IREAD); |
| 92 | + #else //defined(_WIN32) || defined(_WINDOWS) |
| 93 | + auto F = open(FileName, O_RDONLY); |
| 94 | + #endif //defined(_WIN32) || defined(_WINDOWS) |
| 95 | + if (F == -1) |
| 96 | + return 1; |
| 97 | + P->F.Int = F; |
| 98 | + break; |
| 99 | + } |
| 100 | + #if defined(_WIN32) || defined(_WINDOWS) |
| 101 | + case method::createfile: |
| 102 | + { |
| 103 | + DWORD FileSizeHigh; |
| 104 | + auto NewFile = CreateFileA(FileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); |
| 105 | + auto FileSizeLow = GetFileSize(NewFile, &FileSizeHigh); |
| 106 | + if ((FileSizeLow != INVALID_FILE_SIZE || GetLastError() == NO_ERROR) // If no error (special case with 32-bit max value) |
| 107 | + && (!FileSizeHigh || sizeof(size_t) >= 8)) // Mapping 4+ GiB files is not supported in 32-bit mode |
| 108 | + { |
| 109 | + FileSize = ((size_t)FileSizeHigh) << 32 | FileSizeLow; |
| 110 | + } |
| 111 | + else |
| 112 | + return 1; |
| 113 | + if (Begin) |
| 114 | + { |
| 115 | + LARGE_INTEGER GoTo; |
| 116 | + GoTo.QuadPart = Begin; |
| 117 | + if (!SetFilePointerEx(NewFile, GoTo, nullptr, 0)) |
| 118 | + return 1; |
| 119 | + P->Data_Shift = Begin; |
| 120 | + } |
| 121 | + P->F.Handle = NewFile; |
| 122 | + break; |
| 123 | + } |
| 124 | + #endif //defined(_WIN32) || defined(_WINDOWS) |
| 125 | + } |
| 126 | + |
| 127 | + auto Buffer = new uint8_t[P->MaxSize]; |
| 128 | + P->Data_Shift -= P->MaxSize; |
| 129 | + AssignBase(Buffer - P->Data_Shift, FileSize); |
| 130 | + Private2 = (decltype(Private2))P; |
| 131 | + |
| 132 | + return Remap(Begin, End); |
| 133 | + } |
| 134 | + |
36 | 135 | size_t NewSize;
|
37 | 136 | #if defined(_WIN32) || defined(_WINDOWS)
|
38 | 137 | auto NewFile = CreateFileA(FileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
@@ -99,12 +198,63 @@ inline int munmap_const(const void* addr, size_t length)
|
99 | 198 | #pragma GCC diagnostic pop
|
100 | 199 | #endif
|
101 | 200 | #endif
|
102 |
| -int filemap::Remap() |
| 201 | +int filemap::Remap(size_t Begin, size_t End) |
103 | 202 | {
|
104 | 203 | // Special case for 0-byte files
|
105 | 204 | if (Empty())
|
106 | 205 | return 0;
|
107 | 206 |
|
| 207 | + if (Method != method::mmap) |
| 208 | + { |
| 209 | + auto P = (private_buffered*)Private2; |
| 210 | + auto Buffer = Data() + P->Data_Shift; |
| 211 | + auto Buffer_MaxSize = P->MaxSize; |
| 212 | + Begin -= P->Data_Shift; |
| 213 | + if (!End) |
| 214 | + End = Size(); |
| 215 | + End -= P->Data_Shift; |
| 216 | + auto Buffer_Middle = Buffer + Begin; |
| 217 | + auto Buffer_Middle_Size = Buffer_MaxSize - Begin; |
| 218 | + memmove((void*)Buffer, (void*)Buffer_Middle, Buffer_Middle_Size); |
| 219 | + P->Data_Shift += Begin; |
| 220 | + AssignKeepSizeBase(Buffer - P->Data_Shift); |
| 221 | + Buffer += Buffer_Middle_Size; |
| 222 | + Buffer_MaxSize -= Buffer_Middle_Size; |
| 223 | + |
| 224 | + switch (Method) |
| 225 | + { |
| 226 | + default: // case style::fstream: |
| 227 | + { |
| 228 | + auto F = P->F.Ifstream; |
| 229 | + F->read((char*)Buffer, Buffer_MaxSize); |
| 230 | + break; |
| 231 | + } |
| 232 | + case method::fopen: |
| 233 | + { |
| 234 | + auto F = P->F.File; |
| 235 | + if (fread((char*)Buffer, Buffer_MaxSize, 1, F) != 1) |
| 236 | + return 1; |
| 237 | + break; |
| 238 | + } |
| 239 | + case method::open: |
| 240 | + { |
| 241 | + auto F = P->F.Int; |
| 242 | + read(F, (void*)Buffer, Buffer_MaxSize); |
| 243 | + break; |
| 244 | + } |
| 245 | + #if defined(_WIN32) || defined(_WINDOWS) |
| 246 | + case method::createfile: |
| 247 | + { |
| 248 | + auto F = P->F.Handle; |
| 249 | + ReadFile(F, (LPVOID)Buffer, (DWORD)Buffer_MaxSize, nullptr, 0); |
| 250 | + break; |
| 251 | + } |
| 252 | + #endif //defined(_WIN32) || defined(_WINDOWS) |
| 253 | + } |
| 254 | + |
| 255 | + return 0; |
| 256 | + } |
| 257 | + |
108 | 258 | // Close previous map
|
109 | 259 | if (Data())
|
110 | 260 | {
|
|
0 commit comments