aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2021-09-18 11:58:27 +0100
committergingerBill <bill@gingerbill.org>2021-09-18 11:58:27 +0100
commit3713f11461ed2cd42af3cfa00afd536b98f8ca54 (patch)
tree9e33da2409323aab7b4e3b4ed74c86ab376cdd8f /src
parent4cb7f056440130cb8160a8eaea4a47b270975483 (diff)
Refactor `init_tokenizer_with_data` to file memory mapping (Windows only currently)
Diffstat (limited to 'src')
-rw-r--r--src/common.cpp121
-rw-r--r--src/tokenizer.cpp54
2 files changed, 145 insertions, 30 deletions
diff --git a/src/common.cpp b/src/common.cpp
index b132c26b0..8a220c799 100644
--- a/src/common.cpp
+++ b/src/common.cpp
@@ -850,6 +850,127 @@ ReadDirectoryError read_directory(String path, Array<FileInfo> *fi) {
+struct MemoryMappedFile {
+ void *handle;
+
+ void *data;
+ i32 size;
+};
+enum MemoryMappedFileError {
+ MemoryMappedFile_None,
+
+ MemoryMappedFile_Empty,
+ MemoryMappedFile_FileTooLarge,
+ MemoryMappedFile_Invalid,
+ MemoryMappedFile_NotExists,
+ MemoryMappedFile_Permission,
+
+ MemoryMappedFile_COUNT,
+};
+
+MemoryMappedFileError memory_map_file_32(char const *fullpath, MemoryMappedFile *memory_mapped_file) {
+ MemoryMappedFileError err = MemoryMappedFile_None;
+
+#if defined(GB_SYSTEM_WINDOWS)
+ isize w_len = 0;
+ wchar_t *w_str = gb__alloc_utf8_to_ucs2(temporary_allocator(), fullpath, &w_len);
+ if (w_str == nullptr) {
+ return MemoryMappedFile_Invalid;
+ }
+ i64 file_size = 0;
+ LARGE_INTEGER li_file_size = {};
+ HANDLE handle = nullptr;
+ HANDLE file_mapping = nullptr;
+ void *file_data = nullptr;
+
+ handle = CreateFileW(w_str, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
+ if (handle == INVALID_HANDLE_VALUE) {
+ handle = nullptr;
+ goto window_handle_file_error;
+ }
+
+ li_file_size = {};
+ if (!GetFileSizeEx(handle, &li_file_size)) {
+ goto window_handle_file_error;
+ }
+ file_size = cast(i64)li_file_size.QuadPart;
+ if (file_size > I32_MAX) {
+ CloseHandle(handle);
+ return MemoryMappedFile_FileTooLarge;
+ }
+
+ if (file_size == 0) {
+ CloseHandle(handle);
+ err = MemoryMappedFile_Empty;
+ memory_mapped_file->handle = nullptr;
+ memory_mapped_file->data = nullptr;
+ memory_mapped_file->size = 0;
+ return err;
+ }
+
+ file_mapping = CreateFileMappingW(handle, nullptr, PAGE_READONLY, 0, 0, nullptr);
+ CloseHandle(handle);
+
+ file_data = MapViewOfFileEx(file_mapping, FILE_MAP_READ, 0, 0, 0/*file_size*/, nullptr/*base address*/);
+ memory_mapped_file->handle = cast(void *)file_mapping;
+ memory_mapped_file->data = file_data;
+ memory_mapped_file->size = cast(i32)file_size;
+ return err;
+
+window_handle_file_error:;
+ {
+ DWORD handle_err = GetLastError();
+ CloseHandle(handle);
+ err = MemoryMappedFile_Invalid;
+ switch (handle_err) {
+ case ERROR_FILE_NOT_FOUND:
+ case ERROR_PATH_NOT_FOUND:
+ case ERROR_INVALID_DRIVE:
+ err = MemoryMappedFile_NotExists;
+ break;
+ case ERROR_ACCESS_DENIED:
+ case ERROR_INVALID_ACCESS:
+ err = MemoryMappedFile_Permission;
+ break;
+ }
+ return err;
+ }
+
+#else
+ // TODO(bill): Memory map rather than copy contents
+ gbFileContents fc = gb_file_read_contents(heap_allocator(), true, fullpath);
+
+ if (fc.size > I32_MAX) {
+ err = MemoryMappedFile_FileTooLarge;
+ gb_file_free_contents(&fc);
+ } else if (fc.data != nullptr) {
+ memory_mapped_file->handle = nullptr;
+ memory_mapped_file->data = fc.data;
+ memory_mapped_file->size = cast(i32)fc.size;
+ } else {
+ gbFile f = {};
+ gbFileError file_err = gb_file_open(&f, fullpath);
+ defer (gb_file_close(&f));
+
+ switch (file_err) {
+ case gbFileError_Invalid: err = MemoryMappedFile_Invalid; break;
+ case gbFileError_NotExists: err = MemoryMappedFile_NotExists; break;
+ case gbFileError_Permission: err = MemoryMappedFile_Permission; break;
+ }
+
+ if (err == MemoryMappedFile_None && gb_file_size(&f) == 0) {
+ err = MemoryMappedFile_Empty;
+ }
+ }
+ return err;
+#endif
+}
+
+
+
+
+
+
#define USE_DAMERAU_LEVENSHTEIN 1
isize levenstein_distance_case_insensitive(String const &a, String const &b) {
diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp
index 35d6775a3..2251b4f96 100644
--- a/src/tokenizer.cpp
+++ b/src/tokenizer.cpp
@@ -802,39 +802,33 @@ void init_tokenizer_with_data(Tokenizer *t, String const &fullpath, void *data,
}
}
-TokenizerInitError init_tokenizer_from_fullpath(Tokenizer *t, String const &fullpath) {
- TokenizerInitError err = TokenizerInit_None;
-
- char *c_str = alloc_cstring(temporary_allocator(), fullpath);
-
- // TODO(bill): Memory map rather than copy contents
- gbFileContents fc = gb_file_read_contents(heap_allocator(), true, c_str);
+TokenizerInitError memory_mapped_file_error_map_to_tokenizer[MemoryMappedFile_COUNT] = {
+ TokenizerInit_None, /*MemoryMappedFile_None*/
+ TokenizerInit_Empty, /*MemoryMappedFile_Empty*/
+ TokenizerInit_FileTooLarge, /*MemoryMappedFile_FileTooLarge*/
+ TokenizerInit_Invalid, /*MemoryMappedFile_Invalid*/
+ TokenizerInit_NotExists, /*MemoryMappedFile_NotExists*/
+ TokenizerInit_Permission, /*MemoryMappedFile_Permission*/
+};
- if (fc.size > I32_MAX) {
- t->fullpath = fullpath;
- t->line_count = 1;
- err = TokenizerInit_FileTooLarge;
- gb_file_free_contents(&fc);
- } else if (fc.data != nullptr) {
- init_tokenizer_with_data(t, fullpath, fc.data, fc.size);
- } else {
+TokenizerInitError init_tokenizer_from_fullpath(Tokenizer *t, String const &fullpath) {
+ MemoryMappedFile memory_mapped_file = {};
+ MemoryMappedFileError mmf_err = memory_map_file_32(
+ alloc_cstring(temporary_allocator(), fullpath),
+ &memory_mapped_file
+ );
+
+ TokenizerInitError err = memory_mapped_file_error_map_to_tokenizer[mmf_err];
+ switch (mmf_err) {
+ case MemoryMappedFile_None:
+ init_tokenizer_with_data(t, fullpath, memory_mapped_file.data, cast(isize)memory_mapped_file.size);
+ break;
+ case MemoryMappedFile_FileTooLarge:
+ case MemoryMappedFile_Empty:
t->fullpath = fullpath;
t->line_count = 1;
- gbFile f = {};
- gbFileError file_err = gb_file_open(&f, c_str);
- defer (gb_file_close(&f));
-
- switch (file_err) {
- case gbFileError_Invalid: err = TokenizerInit_Invalid; break;
- case gbFileError_NotExists: err = TokenizerInit_NotExists; break;
- case gbFileError_Permission: err = TokenizerInit_Permission; break;
- }
-
- if (err == TokenizerInit_None && gb_file_size(&f) == 0) {
- err = TokenizerInit_Empty;
- }
- }
-
+ break;
+ }
return err;
}