Last active
September 8, 2017 06:38
-
-
Save m13253/ae330104be2279f8044d5fef2fb773be to your computer and use it in GitHub Desktop.
Preload files into memory cache, for example IME database, in case you have a slow HDD.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <windows.h> | |
#include <string> | |
using namespace std::string_literals; | |
constexpr size_t buffer_size = 64*1024; | |
static char buffer[buffer_size]; | |
static DWORD PrintString(HANDLE h_stdout, std::wstring const& string) { | |
DWORD count; | |
WriteConsoleW(h_stdout, string.c_str(), string.length(), &count, NULL); | |
return count; | |
} | |
static HRESULT ReportError(HANDLE h_stdout, HRESULT error) { | |
LPWSTR msgbuf = NULL; | |
if(FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR) &msgbuf, 0, NULL) == 0) { | |
PrintString(h_stdout, L"Unknown error.\r\n"s); | |
return error; | |
} | |
PrintString(h_stdout, msgbuf); | |
LocalFree(msgbuf); | |
return error; | |
} | |
static HRESULT FirstNonzero(HRESULT first, HRESULT second) { | |
return first ? first : second; | |
} | |
static std::wstring CombinePath(std::wstring const& first, std::wstring const& second) { | |
std::wstring result; | |
result.reserve(first.length() + 1 + second.length()); | |
result += first; | |
result += L'\\'; | |
result += second; | |
return result; | |
} | |
static HRESULT PreloadFile(HANDLE h_stdout, std::wstring const& path) { | |
PrintString(h_stdout, path + L"\r\n"s); | |
HANDLE file = CreateFileW(path.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | |
if(file == INVALID_HANDLE_VALUE) { | |
return ReportError(h_stdout, GetLastError()); | |
} | |
DWORD ncharsread; | |
do { | |
if(!ReadFile(file, buffer, buffer_size, &ncharsread, NULL)) { | |
HRESULT error = GetLastError(); | |
CloseHandle(file); | |
return ReportError(h_stdout, error); | |
} | |
} while(ncharsread != 0); | |
CloseHandle(file); | |
return 0; | |
} | |
static HRESULT IterPath(HANDLE h_stdout, std::wstring const& path, std::wstring const& pattern) { | |
HRESULT retval = 0; | |
std::wstring combined = CombinePath(path, pattern); | |
PrintString(h_stdout, L"Search: "s + combined + L"\r\n"s); | |
WIN32_FIND_DATAW find_data; | |
HANDLE find = FindFirstFileW(combined.c_str(), &find_data); | |
if(find == INVALID_HANDLE_VALUE) { | |
return ReportError(h_stdout, GetLastError()); | |
} | |
do { | |
if(find_data.cFileName == L"."s || find_data.cFileName == L".."s) { | |
continue; | |
} | |
std::wstring sub_path = path + L'\\' + find_data.cFileName; | |
if((find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { | |
retval = FirstNonzero(retval, IterPath(h_stdout, sub_path, L"*"s)); | |
} else { | |
retval = FirstNonzero(retval, PreloadFile(h_stdout, sub_path)); | |
} | |
} while(FindNextFileW(find, &find_data)); | |
HRESULT error = GetLastError(); | |
FindClose(find); | |
if(error != ERROR_NO_MORE_FILES) { | |
return ReportError(h_stdout, error); | |
} | |
return retval; | |
} | |
int main(void) { | |
HRESULT error = 0; | |
HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); | |
LPCWSTR cmdline = GetCommandLineW(); | |
int argc; | |
LPWSTR *argv = CommandLineToArgvW(cmdline, &argc); | |
if(argc > 1) { | |
for(int argi = 1; argi < argc; ++argi) { | |
std::wstring path = argv[argi]; | |
size_t sep = path.rfind(L'\\'); | |
std::wstring pattern; | |
if(sep != path.npos) { | |
pattern = path.substr(sep+1); | |
path = path.substr(0, sep); | |
} else { | |
pattern = path; | |
path = L"."s; | |
} | |
if(pattern.empty()) { | |
pattern = L"*"s; | |
} | |
error = FirstNonzero(error, IterPath(h_stdout, path, pattern)); | |
} | |
} else { | |
PrintString(h_stdout, L"Usage: preload PATH [PATH ...]\r\n\r\nThis program preloads files into memory cache, for example IME database, in case you have a slow HDD.\r\n\r\n"s); | |
error = 1; | |
} | |
LocalFree(argv); | |
ExitProcess(error); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment