diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..6c22a49 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: ["https://chaoses-ib.github.io/funding/微信赞赏码.png", "https://chaoses-ib.github.io/funding/支付宝收款码.png", "感谢捐赠,捐赠时请备注仓库名,便于记录。"] diff --git a/Hijacker/Hijacker.rc b/Hijacker/Hijacker.rc index f780c67..b6d79fa 100644 --- a/Hijacker/Hijacker.rc +++ b/Hijacker/Hijacker.rc @@ -51,8 +51,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,3,0,1 - PRODUCTVERSION 0,3,0,1 + FILEVERSION 0,4,0,1 + PRODUCTVERSION 0,4,0,1 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -69,12 +69,12 @@ BEGIN BEGIN VALUE "CompanyName", "https://github.com/Chaoses-Ib/IbEverythingExt" VALUE "FileDescription", "Everything ƴչ" - VALUE "FileVersion", "0.3.0.1" + VALUE "FileVersion", "0.4.0.1" VALUE "InternalName", "Hijacker.dll" VALUE "LegalCopyright", "Copyright (C) 2021 Ib" VALUE "OriginalFilename", "WindowsCodecs.dll" VALUE "ProductName", "IbEverythingExt" - VALUE "ProductVersion", "0.3.0.1" + VALUE "ProductVersion", "0.4.0.1" END END BLOCK "VarFileInfo" diff --git a/Hijacker/Hijacker.vcxproj b/Hijacker/Hijacker.vcxproj index 92fdef4..36ee00d 100644 --- a/Hijacker/Hijacker.vcxproj +++ b/Hijacker/Hijacker.vcxproj @@ -171,15 +171,20 @@ + + + + + Create Create @@ -188,6 +193,7 @@ + diff --git a/Hijacker/Hijacker.vcxproj.filters b/Hijacker/Hijacker.vcxproj.filters index 5e724d9..f00bf57 100644 --- a/Hijacker/Hijacker.vcxproj.filters +++ b/Hijacker/Hijacker.vcxproj.filters @@ -33,6 +33,15 @@ Header Files + + Header Files + + + Header Files + + + Header Files + @@ -50,6 +59,15 @@ Source Files + + Source Files + + + Source Files + + + Source Files + diff --git a/Hijacker/config.cpp b/Hijacker/config.cpp new file mode 100644 index 0000000..bc2b0d7 --- /dev/null +++ b/Hijacker/config.cpp @@ -0,0 +1,25 @@ +#include "pch.h" +#include "config.hpp" +#include +#include +#include + +#pragma comment(lib, "Shlwapi.lib") + +Config config{}; + +void config_init() { + wchar_t path[MAX_PATH]; + GetModuleFileNameW(nullptr, path, std::size(path)); + PathRemoveFileSpecW(path); + PathAppendW(path, L"IbEverythingExt.yaml"); + + std::ifstream in(path); + if (in) { + YAML::Node root = YAML::Load(in); + config.pinyin_search = root["pinyin_search"].as(); + config.quick_select = root["quick_select"].as(); + } +} + +void config_destroy() {} \ No newline at end of file diff --git a/Hijacker/config.hpp b/Hijacker/config.hpp new file mode 100644 index 0000000..8e848b1 --- /dev/null +++ b/Hijacker/config.hpp @@ -0,0 +1,10 @@ +#pragma once + +struct Config { + bool pinyin_search = true; + bool quick_select = true; +}; +extern Config config; + +void config_init(); +void config_destroy(); \ No newline at end of file diff --git a/Hijacker/dllmain.cpp b/Hijacker/dllmain.cpp index 4f8e211..f1ee1b5 100644 --- a/Hijacker/dllmain.cpp +++ b/Hijacker/dllmain.cpp @@ -3,13 +3,19 @@ #include #include #include "helper.hpp" +#include "config.hpp" +#include "ipc.hpp" #include "pinyin.hpp" +#include "quick_select.hpp" #include "search_history.hpp" -#include +constexpr wchar_t prop_main_title[] = L"IbEverythingExt.Title"; constexpr wchar_t prop_edit_content[] = L"IbEverythingExt.Content"; constexpr wchar_t prop_edit_processed_content[] = L"IbEverythingExt.ProcessedContent"; -constexpr wchar_t prop_main_title[] = L"IbEverythingExt.Title"; + +std::wstring instance_name{}; +std::wstring class_everything = L"EVERYTHING"; +std::wstring title_suffix = L" - Everything"; std::unordered_map content_map{}; @@ -77,13 +83,23 @@ std::wstring* edit_process_content(const std::wstring& content) { } modifiers; auto process_keyword = [&out, &disabled, &modifiers](const std::wstring_view& keyword) { - if (disabled || keyword.empty()) { + if (keyword.empty()) + disabled = true; + else if (keyword[0] == L'"') { + if (keyword.size() >= 4 && keyword[2] == L':') // '"C:"' + disabled = true; + } else { + if (keyword.size() >= 2 && keyword[1] == L':') // 'C:' + disabled = true; + } + + if (disabled) { disabled = false; if (modifiers.startwith) out << L"startwith:"; if (modifiers.endwith) out << L"endwith:"; - out << keyword << L' '; + out << keyword; return; } @@ -111,7 +127,7 @@ std::wstring* edit_process_content(const std::wstring& content) { } } } - + out << L"regex:"; /* @@ -266,24 +282,15 @@ std::wstring* edit_process_content(const std::wstring& content) { if (!quoted) out << L'"'; */ - - out << L' '; }; wchar_t c; - bool escape = false; - bool skip_escape_reset = false; bool in_quotes = false; std::wistringstream::pos_type last_colon_next{}; while (in.get(c)) { switch (c) { - case L'\\': - escape = true; - skip_escape_reset = true; - break; case L'"': - if (!escape) - in_quotes = !in_quotes; + in_quotes = !in_quotes; break; case L':': if (!in_quotes) { @@ -291,6 +298,8 @@ std::wstring* edit_process_content(const std::wstring& content) { auto colon_next = in.tellg(); size_t size = colon_next - last_colon_next; + if (size <= 2) // "C:" + break; std::wstring modifier(size, L'\0'); in.seekg(last_colon_next); in.read(modifier.data(), size); @@ -299,8 +308,7 @@ std::wstring* edit_process_content(const std::wstring& content) { if (disabled || is_modifier_in_blacklist(modifier)) { disabled = true; out << modifier; - } - else if (modifier == L"py:"sv || modifier == L"endwith:"sv || modifier == L"startwith:"sv) { + } else if (modifier == L"py:"sv || modifier == L"endwith:"sv || modifier == L"startwith:"sv) { if (modifier == L"py:"sv) modifiers.py = true; else if (modifier == L"endwith:"sv) @@ -308,8 +316,7 @@ std::wstring* edit_process_content(const std::wstring& content) { else if (modifier == L"startwith:"sv) modifiers.startwith = true; // remove (these modifiers will be implemented with regex) - } - else { + } else { if (modifier == L"nowholefilename:"sv) modifiers.nowholefilename = true; else if (modifier == L"nowildcards:"sv) @@ -318,44 +325,51 @@ std::wstring* edit_process_content(const std::wstring& content) { } } break; + case L'!': + if (in.tellg() == last_colon_next + std::streamoff(1)) { + out << c; + last_colon_next += 1; + } + break; case L' ': if (!in_quotes) { // keyword size_t size = in.tellg() - last_colon_next - 1; - if (size) { // not L" " - std::wstring keyword(size, L'\0'); + std::wstring keyword(size, L'\0'); + if (size) { in.seekg(last_colon_next); in.read(keyword.data(), size); - - process_keyword(keyword); - modifiers = {}; + in.ignore(); // ignore L' ' } + + process_keyword(keyword); + out << L' '; + + modifiers = {}; last_colon_next = in.tellg(); } break; } - if (skip_escape_reset) - skip_escape_reset = false; - else - escape = false; } // stream EOF in.clear(); + size_t size = in.tellg() - last_colon_next; std::wstring keyword(size, L'\0'); in.seekg(last_colon_next); in.read(keyword.data(), size); + process_keyword(keyword); + // return the result if constexpr (debug) DebugOStream() << content << L" -> " << out.str() << std::endl; - return new std::wstring(out.str()); } -WNDPROC edit_window_proc_prev; -LRESULT CALLBACK edit_window_proc( +WNDPROC edit_window_proc_0; +LRESULT CALLBACK edit_window_proc_1( _In_ HWND hwnd, _In_ UINT uMsg, _In_ WPARAM wParam, @@ -368,9 +382,9 @@ LRESULT CALLBACK edit_window_proc( DebugOStream() << L"WM_GETTEXTLENGTH\n"; // retrieve the content - LRESULT result = CallWindowProcW(edit_window_proc_prev, hwnd, uMsg, wParam, lParam); - wchar_t* buf = new wchar_t[result + 1 + std::size(" - Everything") - 1]; // for both the content and the title - LRESULT content_len = CallWindowProcW(edit_window_proc_prev, hwnd, WM_GETTEXT, result + 1, (LPARAM)buf); + LRESULT result = CallWindowProcW(edit_window_proc_0, hwnd, uMsg, wParam, lParam); + wchar_t* buf = new wchar_t[result + 1 + title_suffix.size()]; // for both the content and the title + LRESULT content_len = CallWindowProcW(edit_window_proc_0, hwnd, WM_GETTEXT, result + 1, (LPARAM)buf); // save the content auto content = (std::wstring*)GetPropW(hwnd, prop_edit_content); @@ -390,9 +404,9 @@ LRESULT CALLBACK edit_window_proc( // make the title if (content_len) - std::copy_n(L" - Everything", std::size(L" - Everything"), buf + content_len); + std::copy_n(title_suffix.c_str(), title_suffix.size() + 1, buf + content_len); else - std::copy_n(L"Everything", std::size(L"Everything"), buf); + std::copy_n(title_suffix.c_str() + std::size(L" - ") - 1, title_suffix.size() + 1 - (std::size(L" - ") - 1), buf); // save the title HWND main = GetAncestor(hwnd, GA_ROOT); @@ -427,172 +441,123 @@ LRESULT CALLBACK edit_window_proc( } break; } - return CallWindowProcW(edit_window_proc_prev, hwnd, uMsg, wParam, lParam); + return CallWindowProcW(edit_window_proc_0, hwnd, uMsg, wParam, lParam); } -#pragma pack(push, 1) -template -struct EVERYTHING_IPC_QUERY2 { - // something wrong with MSVC - //using namespace Everythings; - - DWORD reply_hwnd; // !: not sizeof(HWND) - DWORD reply_copydata_message; - Everythings::SearchFlags search_flags; - DWORD offset; - DWORD max_results; - Everythings::RequestFlags request_flags; - Everythings::Sort sort_type; - CharT search_string[1]; // '\0' - - static size_t query_size() { - return sizeof(EVERYTHING_IPC_QUERY2) - sizeof(CharT); - } -}; - -template -struct EVERYTHING_IPC_QUERY { - // something wrong with MSVC - //using namespace Everythings; - - DWORD reply_hwnd; // !: not sizeof(HWND) - DWORD reply_copydata_message; - Everythings::SearchFlags search_flags; - DWORD offset; - DWORD max_results; - CharT search_string[1]; // '\0' - - static size_t query_size() { - return sizeof(EVERYTHING_IPC_QUERY) - sizeof(CharT); +/* +WNDPROC edit_window_proc_2; +LRESULT CALLBACK edit_window_proc_3( + _In_ HWND hwnd, + _In_ UINT uMsg, + _In_ WPARAM wParam, + _In_ LPARAM lParam) +{ + switch (uMsg) { + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + if constexpr (debug) + DebugOStream() << (uMsg == WM_KEYDOWN ? L"WM_KEYDOWN: " : L"WM_SYSKEYDOWN: ") << wParam << L'\n'; + break; } -}; -#pragma pack(pop) + return CallWindowProcW(edit_window_proc_2, hwnd, uMsg, wParam, lParam); +} +*/ -WNDPROC ipc_window_proc_prev; -LRESULT CALLBACK ipc_window_proc( +/* +WNDPROC list_window_proc_0; +LRESULT CALLBACK list_window_proc_1( _In_ HWND hwnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam) { - using namespace Everythings; + switch (uMsg) { + } + return CallWindowProcW(list_window_proc_0, hwnd, uMsg, wParam, lParam); +} +*/ +/* +WNDPROC list_window_proc_2; +LRESULT CALLBACK list_window_proc_3( + _In_ HWND hwnd, + _In_ UINT uMsg, + _In_ WPARAM wParam, + _In_ LPARAM lParam) +{ switch (uMsg) { - case WM_COPYDATA: - { - if constexpr (debug) - DebugOStream() << L"WM_COPYDATA\n"; - if (!wParam) - break; - - bool known = false; - - static DWORD last_pid = 0; // window will be different every time when using the official SDK - static bool last_known = false; - DWORD pid; - GetWindowThreadProcessId((HWND)wParam, &pid); - if (pid == last_pid) - known = last_known; - else { - HANDLE process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, pid); - - wchar_t path_buf[MAX_PATH]; - DWORD size = std::size(path_buf); - QueryFullProcessImageNameW(process, 0, path_buf, &size); - std::wstring_view path(path_buf, size); - if constexpr (debug) - DebugOStream() << path << L'\n'; - - if (path.ends_with(L"\\explorer.exe")) // stnkl/EverythingToolbar - known = true; - else if (path.ends_with(L"\\uTools.exe")) // uTools - known = true; - - CloseHandle(process); - - last_pid = pid; - last_known = known; + } + return CallWindowProcW(list_window_proc_2, hwnd, uMsg, wParam, lParam); +} +*/ + +auto SetWindowTextW_real = SetWindowTextW; +BOOL WINAPI SetWindowTextW_detour( + _In_ HWND hWnd, + _In_opt_ LPCWSTR lpString) +{ + using namespace std::literals; + + wchar_t buf[256]; + if (int len = GetClassNameW(hWnd, buf, std::size(buf))) { + std::wstring_view sv(buf, len); + + if (sv == class_everything) { + // set the title + if (auto title = (const wchar_t*)GetPropW(hWnd, prop_main_title)) { + SetWindowTextW_real(hWnd, title); + return true; + } + } else if (sv == L"Edit"sv) { + auto processed_content = (std::wstring*)GetPropW(hWnd, prop_edit_processed_content); + if (processed_content && *processed_content == lpString) { + // prevent modifying edit + return true; } - if (!known) - break; - - constexpr uintptr_t EVERYTHING_IPC_COPYDATAQUERYA = 1; - constexpr uintptr_t EVERYTHING_IPC_COPYDATAQUERYW = 2; - constexpr uintptr_t EVERYTHING_IPC_COPYDATA_QUERY2A = 17; - constexpr uintptr_t EVERYTHING_IPC_COPYDATA_QUERY2W = 18; - auto common_process = [hwnd, uMsg, wParam](uintptr_t command, uint8_t* query, size_t query_size, std::wstring_view search) { - std::unique_ptr processed_search{ edit_process_content(std::wstring(search)) }; - - size_t size = query_size + processed_search->size() * sizeof(wchar_t) + sizeof L'\0'; - auto buf = std::make_unique(size); - std::copy_n(query, query_size, buf.get()); - processed_search->copy((wchar_t*)(buf.get() + query_size), processed_search->size() + 1); - - COPYDATASTRUCT processed_copydata{ - command, - size, - (PVOID)buf.get() - }; - - return CallWindowProcW(ipc_window_proc_prev, hwnd, uMsg, wParam, (LPARAM)&processed_copydata); - }; - COPYDATASTRUCT* copydata = ib::Addr(lParam); - switch (copydata->dwData) { - case EVERYTHING_IPC_COPYDATA_QUERY2W: - { - EVERYTHING_IPC_QUERY2 *query = ib::Addr(copydata->lpData); - if (query->search_flags & Search::Regex) - break; - std::wstring_view search{ query->search_string, (copydata->cbData - query->query_size()) / sizeof(wchar_t) - 1 }; - return common_process(copydata->dwData, (uint8_t*)query, query->query_size(), search); - } - break; - case EVERYTHING_IPC_COPYDATA_QUERY2A: - { - EVERYTHING_IPC_QUERY2 *query = ib::Addr(copydata->lpData); - if (query->search_flags & Search::Regex) - break; + auto iter = content_map.find(lpString); + if (iter != content_map.end()) + return SetWindowTextW_real(hWnd, iter->second.c_str()); + } + } + return SetWindowTextW_real(hWnd, lpString); +} - size_t search_len = copydata->cbData - query->query_size() - sizeof(char); - auto search_buf = std::make_unique(search_len); +/* +auto SetWindowLongPtrW_real = SetWindowLongPtrW; +LONG_PTR WINAPI SetWindowLongPtrW_detour( + _In_ HWND hWnd, + _In_ int nIndex, + _In_ LONG_PTR dwNewLong) +{ + using namespace std::literals; - std::wstring_view search{ search_buf.get(), (size_t)MultiByteToWideChar(CP_ACP, 0, query->search_string, search_len, search_buf.get(), search_len) }; - return common_process(EVERYTHING_IPC_COPYDATA_QUERY2W, (uint8_t*)query, query->query_size(), search); - } - break; - case EVERYTHING_IPC_COPYDATAQUERYW: + if (nIndex == GWLP_WNDPROC) { + wchar_t buf[256]; + if (int len = GetClassNameW(hWnd, buf, std::size(buf))) { + std::wstring_view class_name(buf, len); + if (class_name == L"Edit"sv) { + if (int len = GetClassNameW(GetParent(hWnd), buf, std::size(buf)); + std::wstring_view(buf, len) == L"EVERYTHING_TOOLBAR"sv) { - EVERYTHING_IPC_QUERY *query = ib::Addr(copydata->lpData); - if (query->search_flags & Search::Regex) - break; - - std::wstring_view search{ query->search_string, (copydata->cbData - query->query_size()) / sizeof(wchar_t) - 1 }; - return common_process(copydata->dwData, (uint8_t*)query, query->query_size(), search); + edit_window_proc_0 = (WNDPROC)SetWindowLongPtrW_real(hWnd, nIndex, (LONG_PTR)edit_window_proc_3); + edit_window_proc_2 = (WNDPROC)dwNewLong; + return (LONG_PTR)edit_window_proc_1; } - break; - case EVERYTHING_IPC_COPYDATAQUERYA: + } else if (class_name == L"SysListView32"sv) { + if (int len = GetClassNameW(GetParent(hWnd), buf, std::size(buf)); + std::wstring_view(buf, len) == class_everything) { - EVERYTHING_IPC_QUERY *query = ib::Addr(copydata->lpData); - if (query->search_flags & Search::Regex) - break; - - size_t search_len = copydata->cbData - query->query_size() - sizeof(char); - auto search_buf = std::make_unique(search_len); - - std::wstring_view search{ search_buf.get(), (size_t)MultiByteToWideChar(CP_ACP, 0, query->search_string, search_len, search_buf.get(), search_len) }; - return common_process(EVERYTHING_IPC_COPYDATAQUERYW, (uint8_t*)query, query->query_size(), search); + list_window_proc_0 = (WNDPROC)SetWindowLongPtrW_real(hWnd, nIndex, (LONG_PTR)list_window_proc_3); + list_window_proc_2 = (WNDPROC)dwNewLong; + return (LONG_PTR)list_window_proc_1; } - break; - default: - if constexpr (debug) - DebugOStream() << L"command: " << copydata->dwData << L'\n'; } } - break; } - return CallWindowProcW(ipc_window_proc_prev, hwnd, uMsg, wParam, lParam); + return SetWindowLongPtrW_real(hWnd, nIndex, dwNewLong); } +*/ auto CreateWindowExW_real = CreateWindowExW; HWND WINAPI CreateWindowExW_detour( @@ -611,67 +576,83 @@ HWND WINAPI CreateWindowExW_detour( { using namespace std::literals; + // EVERYTHING + // EVERYTHING_TOOLBAR + // Edit + // SysListView32 + // msctls_statusbar32 + // ComboBox + // EVERYTHING_PREVIEW + HWND wnd = CreateWindowExW_real(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); if ((uintptr_t)lpClassName > 0xFFFF) { - if (lpClassName == L"EVERYTHING"sv) { - if constexpr (debug) - DebugOStream() << L"EVERYTHING\n"; - - std::thread t(query_and_merge_into_pinyin_regexs); - t.detach(); - } else if (lpClassName == L"Edit"sv) { - wchar_t buf[std::size(L"EVERYTHING_TOOLBAR")]; - if (int len = GetClassNameW(hWndParent, buf, std::size(buf))) { - if (std::wstring_view(buf, len) == L"EVERYTHING_TOOLBAR"sv) { - edit_window_proc_prev = (WNDPROC)SetWindowLongPtrW(wnd, GWLP_WNDPROC, (LONG_PTR)edit_window_proc); - } - } - } else if (lpClassName == L"EVERYTHING_TASKBAR_NOTIFICATION"sv) { - if constexpr (debug) - DebugOStream() << L"EVERYTHING_TASKBAR_NOTIFICATION\n"; - - ipc_window_proc_prev = (WNDPROC)SetWindowLongPtrW(wnd, GWLP_WNDPROC, (LONG_PTR)ipc_window_proc); + std::wstring_view class_name(lpClassName); + if constexpr (debug) + DebugOStream() << class_name << L", parent: " << hWndParent << L'\n'; - std::thread t(query_and_merge_into_pinyin_regexs); - t.detach(); - } - } - return wnd; -} + // named instances + if (class_name.ends_with(L')') && instance_name.empty()) { + size_t n = class_name.find(L"_("sv); + if (n != class_name.npos) { + size_t begin = n + std::size(L"_("sv); + instance_name = class_name.substr(begin, class_name.size() - 1 - begin); -auto SetWindowTextW_real = SetWindowTextW; -BOOL WINAPI SetWindowTextW_detour( - _In_ HWND hWnd, - _In_opt_ LPCWSTR lpString) -{ - using namespace std::literals; + class_everything += class_name.substr(n); - wchar_t buf[std::size(L"EVERYTHING")]; - if (int len = GetClassNameW(hWnd, buf, std::size(buf))) { - std::wstring_view sv(buf, len); + title_suffix += L" ("sv; + title_suffix += instance_name; + title_suffix += L')'; + } + } - if (sv == L"EVERYTHING"sv) { - // set the title - if (auto title = (const wchar_t*)GetPropW(hWnd, prop_main_title)) { - SetWindowTextW_real(hWnd, title); - return true; + if (class_name == class_everything) { + if (config.pinyin_search) { + std::thread t(pinyin_query_and_merge); + t.detach(); } - } else if (sv == L"Edit"sv) { - auto processed_content = (std::wstring*)GetPropW(hWnd, prop_edit_processed_content); - if (processed_content && *processed_content == lpString) { - // prevent modifying edit - return true; + } else if (class_name == L"Edit"sv) { + if (config.pinyin_search) { + wchar_t buf[std::size(L"EVERYTHING_TOOLBAR")]; + if (int len = GetClassNameW(hWndParent, buf, std::size(buf))) { + if (std::wstring_view(buf, len) == L"EVERYTHING_TOOLBAR"sv) { + edit_window_proc_0 = (WNDPROC)SetWindowLongPtrW(wnd, GWLP_WNDPROC, (LONG_PTR)edit_window_proc_1); + } + } } + } else if (class_name == L"SysListView32"sv) { + if (config.quick_select) { + wchar_t buf[256]; + if (int len = GetClassNameW(hWndParent, buf, std::size(buf))) { + if (std::wstring_view(buf, len) == class_everything) { + // bind list to editor + HWND toolbar = FindWindowExW(hWndParent, nullptr, L"EVERYTHING_TOOLBAR", nullptr); + SetPropW(FindWindowExW(toolbar, nullptr, L"Edit", nullptr), prop_edit_list, wnd); + + // create quick list + // X == Y == nWidth == nHeight == 0 + HWND quick_list = quick_list_create(hWndParent, hInstance); + SetPropW(wnd, prop_list_quick_list, quick_list); + } + } + } + } else if (class_name.starts_with(L"EVERYTHING_TASKBAR_NOTIFICATION"sv)) { + ipc_init(instance_name); - auto iter = content_map.find(lpString); - if (iter != content_map.end()) - return SetWindowTextW_real(hWnd, iter->second.c_str()); + if (config.pinyin_search) { + ipc_window_proc_prev = (WNDPROC)SetWindowLongPtrW(wnd, GWLP_WNDPROC, (LONG_PTR)ipc_window_proc); + + std::thread t(pinyin_query_and_merge); + t.detach(); + } + if (config.quick_select) + quick_select_init(); } } - return SetWindowTextW_real(hWnd, lpString); + return wnd; } +/* BOOL CALLBACK enum_window_proc( _In_ HWND hwnd, _In_ LPARAM lParam) @@ -685,13 +666,14 @@ BOOL CALLBACK enum_window_proc( if (std::wstring_view(buf, len) == L"EVERYTHING"sv) { if (HWND toolbar = FindWindowExW(hwnd, 0, L"EVERYTHING_TOOLBAR", nullptr)) if (HWND edit = FindWindowExW(toolbar, 0, L"Edit", nullptr)) - edit_window_proc_prev = (WNDPROC)SetWindowLongPtrW(edit, GWLP_WNDPROC, (LONG_PTR)edit_window_proc); + edit_window_proc_0 = (WNDPROC)SetWindowLongPtrW(edit, GWLP_WNDPROC, (LONG_PTR)edit_window_proc_1); } } } return true; } +*/ #include @@ -707,12 +689,16 @@ BOOL APIENTRY DllMain( HMODULE hModule, DebugOStream() << L"DLL_PROCESS_ATTACH\n"; IbDetourAttach(&CreateWindowExW_real, CreateWindowExW_detour); - IbDetourAttach(&SetWindowTextW_real, SetWindowTextW_detour); + //IbDetourAttach(&SetWindowLongPtrW_real, SetWindowLongPtrW_detour); // may be loaded after creating windows? it seems that only netutil.dll does //EnumWindows(enum_window_proc,GetCurrentThreadId()); - search_history_init(); + config_init(); + if (config.pinyin_search) { + IbDetourAttach(&SetWindowTextW_real, SetWindowTextW_detour); + search_history_init(); + } break; case DLL_THREAD_ATTACH: break; @@ -722,9 +708,16 @@ BOOL APIENTRY DllMain( HMODULE hModule, if constexpr (debug) DebugOStream() << L"DLL_PROCESS_DETACH\n"; - search_history_destroy(); - - IbDetourDetach(&SetWindowTextW_real, SetWindowTextW_detour); + if (config.quick_select) + quick_select_destroy(); + if (config.pinyin_search) { + search_history_destroy(); + IbDetourDetach(&SetWindowTextW_real, SetWindowTextW_detour); + } + ipc_destroy(); + config_destroy(); + + //IbDetourDetach(&SetWindowLongPtrW_real, SetWindowLongPtrW_detour); IbDetourDetach(&CreateWindowExW_real, CreateWindowExW_detour); break; } diff --git a/Hijacker/ipc.cpp b/Hijacker/ipc.cpp new file mode 100644 index 0000000..ba7c786 --- /dev/null +++ b/Hijacker/ipc.cpp @@ -0,0 +1,188 @@ +#include "pch.h" +#include "ipc.hpp" +#include "helper.hpp" + +ib::Holder ipc_ev; +Everythings::EverythingMT::Version ipc_version; + +void ipc_init(std::wstring_view instance_name) { + ipc_ev.create(instance_name); + ipc_version = ipc_ev->get_version(); +} + +void ipc_destroy() { + ipc_ev.destroy(); +} + + +extern std::wstring* edit_process_content(const std::wstring& content); + +#pragma pack(push, 1) +template +struct EVERYTHING_IPC_QUERY2 { + // something wrong with MSVC + //using namespace Everythings; + + DWORD reply_hwnd; // !: not sizeof(HWND) + DWORD reply_copydata_message; + Everythings::SearchFlags search_flags; + DWORD offset; + DWORD max_results; + Everythings::RequestFlags request_flags; + Everythings::Sort sort_type; + CharT search_string[1]; // '\0' + + static size_t query_size() { + return sizeof(EVERYTHING_IPC_QUERY2) - sizeof(CharT); + } +}; + +template +struct EVERYTHING_IPC_QUERY { + // something wrong with MSVC + //using namespace Everythings; + + DWORD reply_hwnd; // !: not sizeof(HWND) + DWORD reply_copydata_message; + Everythings::SearchFlags search_flags; + DWORD offset; + DWORD max_results; + CharT search_string[1]; // '\0' + + static size_t query_size() { + return sizeof(EVERYTHING_IPC_QUERY) - sizeof(CharT); + } +}; +#pragma pack(pop) + +WNDPROC ipc_window_proc_prev; +LRESULT CALLBACK ipc_window_proc( + _In_ HWND hwnd, + _In_ UINT uMsg, + _In_ WPARAM wParam, + _In_ LPARAM lParam) +{ + using namespace Everythings; + + switch (uMsg) { + case WM_COPYDATA: + { + if constexpr (debug) + DebugOStream() << L"WM_COPYDATA\n"; + if (!wParam) + break; + + bool known = false; + + static DWORD last_pid = 0; // window will be different every time when using the official SDK + static bool last_known = false; + DWORD pid; + GetWindowThreadProcessId((HWND)wParam, &pid); + if (pid == last_pid) + known = last_known; + else { + HANDLE process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, pid); + + wchar_t path_buf[MAX_PATH]; + DWORD size = std::size(path_buf); + QueryFullProcessImageNameW(process, 0, path_buf, &size); + std::wstring_view path(path_buf, size); + if constexpr (debug) + DebugOStream() << path << L'\n'; + + if (path.ends_with(L"\\explorer.exe")) // stnkl/EverythingToolbar + known = true; + else if (path.ends_with(L"\\Flow.Launcher.exe")) // Flow Launcher + known = true; + else if (path.ends_with(L"\\HuoChat.exe")) // HuoChat + known = true; + else if (path.ends_with(L"\\uTools.exe")) // uTools + known = true; + else if (path.ends_with(L"\\Wox.exe")) // Wox + known = true; + + CloseHandle(process); + + last_pid = pid; + last_known = known; + } + if (!known) + break; + + constexpr uintptr_t EVERYTHING_IPC_COPYDATAQUERYA = 1; + constexpr uintptr_t EVERYTHING_IPC_COPYDATAQUERYW = 2; + constexpr uintptr_t EVERYTHING_IPC_COPYDATA_QUERY2A = 17; + constexpr uintptr_t EVERYTHING_IPC_COPYDATA_QUERY2W = 18; + auto common_process = [hwnd, uMsg, wParam](uintptr_t command, uint8_t* query, size_t query_size, std::wstring_view search) { + std::unique_ptr processed_search{ edit_process_content(std::wstring(search)) }; + + size_t size = query_size + processed_search->size() * sizeof(wchar_t) + sizeof L'\0'; + auto buf = std::make_unique(size); + std::copy_n(query, query_size, buf.get()); + processed_search->copy((wchar_t*)(buf.get() + query_size), processed_search->size() + 1); + + COPYDATASTRUCT processed_copydata{ + command, + size, + (PVOID)buf.get() + }; + + return CallWindowProcW(ipc_window_proc_prev, hwnd, uMsg, wParam, (LPARAM)&processed_copydata); + }; + COPYDATASTRUCT* copydata = ib::Addr(lParam); + switch (copydata->dwData) { + case EVERYTHING_IPC_COPYDATA_QUERY2W: + { + EVERYTHING_IPC_QUERY2 *query = ib::Addr(copydata->lpData); + if (query->search_flags & Search::Regex) + break; + + std::wstring_view search{ query->search_string, (copydata->cbData - query->query_size()) / sizeof(wchar_t) - 1 }; + return common_process(copydata->dwData, (uint8_t*)query, query->query_size(), search); + } + break; + case EVERYTHING_IPC_COPYDATA_QUERY2A: + { + EVERYTHING_IPC_QUERY2 *query = ib::Addr(copydata->lpData); + if (query->search_flags & Search::Regex) + break; + + size_t search_len = copydata->cbData - query->query_size() - sizeof(char); + auto search_buf = std::make_unique(search_len); + + std::wstring_view search{ search_buf.get(), (size_t)MultiByteToWideChar(CP_ACP, 0, query->search_string, search_len, search_buf.get(), search_len) }; + return common_process(EVERYTHING_IPC_COPYDATA_QUERY2W, (uint8_t*)query, query->query_size(), search); + } + break; + case EVERYTHING_IPC_COPYDATAQUERYW: + { + EVERYTHING_IPC_QUERY *query = ib::Addr(copydata->lpData); + if (query->search_flags & Search::Regex) + break; + + std::wstring_view search{ query->search_string, (copydata->cbData - query->query_size()) / sizeof(wchar_t) - 1 }; + return common_process(copydata->dwData, (uint8_t*)query, query->query_size(), search); + } + break; + case EVERYTHING_IPC_COPYDATAQUERYA: + { + EVERYTHING_IPC_QUERY *query = ib::Addr(copydata->lpData); + if (query->search_flags & Search::Regex) + break; + + size_t search_len = copydata->cbData - query->query_size() - sizeof(char); + auto search_buf = std::make_unique(search_len); + + std::wstring_view search{ search_buf.get(), (size_t)MultiByteToWideChar(CP_ACP, 0, query->search_string, search_len, search_buf.get(), search_len) }; + return common_process(EVERYTHING_IPC_COPYDATAQUERYW, (uint8_t*)query, query->query_size(), search); + } + break; + default: + if constexpr (debug) + DebugOStream() << L"command: " << copydata->dwData << L'\n'; + } + } + break; + } + return CallWindowProcW(ipc_window_proc_prev, hwnd, uMsg, wParam, lParam); +} \ No newline at end of file diff --git a/Hijacker/ipc.hpp b/Hijacker/ipc.hpp new file mode 100644 index 0000000..a4c4cf3 --- /dev/null +++ b/Hijacker/ipc.hpp @@ -0,0 +1,15 @@ +#pragma once +#include + +extern ib::Holder ipc_ev; +extern Everythings::EverythingMT::Version ipc_version; +void ipc_init(std::wstring_view instance_name); +void ipc_destroy(); + + +extern WNDPROC ipc_window_proc_prev; +LRESULT CALLBACK ipc_window_proc( + _In_ HWND hwnd, + _In_ UINT uMsg, + _In_ WPARAM wParam, + _In_ LPARAM lParam); \ No newline at end of file diff --git a/Hijacker/pinyin.cpp b/Hijacker/pinyin.cpp index e20bd70..7784d73 100644 --- a/Hijacker/pinyin.cpp +++ b/Hijacker/pinyin.cpp @@ -1,8 +1,8 @@ #include "pch.h" #include "pinyin.hpp" #include -#include #include "helper.hpp" +#include "ipc.hpp" std::wstring pinyin_regexs[26]{}; std::pair pinyin_pair_regexs[26][26]{}; @@ -42,11 +42,10 @@ struct Utf16PairOrd : Utf16Pair { } }; -void query_and_merge_into_pinyin_regexs() { +void pinyin_query_and_merge() { using namespace Everythings; using namespace std::literals; - - static EverythingMT ev; + static DWORD last_query = 0; static std::mutex mutex; // be careful @@ -57,14 +56,14 @@ void query_and_merge_into_pinyin_regexs() { std::wstring query; if (!last_query) { query = L"regex:[〇-𰻞]"; - ev.database_loaded_future().get(); + ipc_ev->database_loaded_future().get(); last_query = GetTickCount() / 1000; } else { DWORD time = GetTickCount() / 1000; query = L"rc:last" + std::to_wstring(time - last_query + 1) + L"secs regex:[〇-𰻞]"; last_query = time; } - QueryResults results = ev.query_send(query, Search::MatchCase, Request::FileName).get(); + QueryResults results = ipc_ev->query_send(query, Search::MatchCase, Request::FileName).get(); // merge functions //"拼" diff --git a/Hijacker/pinyin.hpp b/Hijacker/pinyin.hpp index 1aa432d..849717e 100644 --- a/Hijacker/pinyin.hpp +++ b/Hijacker/pinyin.hpp @@ -27,4 +27,5 @@ struct Utf16Pair { bool in(std::wstring_view sv) const; }; -void query_and_merge_into_pinyin_regexs(); \ No newline at end of file +// require ipc_init +void pinyin_query_and_merge(); \ No newline at end of file diff --git a/Hijacker/quick_select.cpp b/Hijacker/quick_select.cpp new file mode 100644 index 0000000..3db4a53 --- /dev/null +++ b/Hijacker/quick_select.cpp @@ -0,0 +1,246 @@ +#include "pch.h" +#include "quick_select.hpp" +#include +#include "helper.hpp" +#include "ipc.hpp" + +extern decltype(&CreateWindowExW) CreateWindowExW_real; +//extern decltype(&SetWindowLongPtrW) SetWindowLongPtrW_real; + +HHOOK keyboard_hook; +LRESULT CALLBACK keyboard_proc( + _In_ int code, + _In_ WPARAM wParam, + _In_ LPARAM lParam) +{ + bool down = !(lParam & 0xC0000000); + if constexpr (debug) + DebugOStream() << L"keyboard_proc: " << code << L", " << wParam << L", " << std::hex << lParam << L'(' << down << L')' << L'\n'; + + do { + static enum { + None, + Alt, + AltCtrl, + AltShift + } hotkey; + + if (down) { + if (bool alt = GetKeyState(VK_MENU) & 0x8000) { + HWND focus = GetFocus(); + HWND list = (HWND)GetPropW(focus, prop_edit_list); + if (!list) { // not in Search Edit + HWND quick_list = (HWND)GetPropW(focus, prop_list_quick_list); + if (!quick_list) // not in Result List + break; + list = focus; + } + + int num; + if ('0' <= wParam && wParam <= '9') + num = wParam == '0' ? 9 : wParam - '1'; + else if ('A' <= wParam && wParam <= 'Z') + num = wParam - 'A' + 10; + else + break; + + bool ctrl = GetKeyState(VK_CONTROL) & 0x8000; + bool shift = GetKeyState(VK_SHIFT) & 0x8000; + if constexpr (debug) + DebugOStream() << (ctrl ? L"Ctrl " : L"") << (shift ? L"Shift " : L"") << (alt ? L"Alt " : L"") << (wchar_t)wParam << L'\n'; + + // these do not work, so we have to execute the hotkey when Alt is being releasing + /* + BYTE state[256]; + GetKeyboardState(state); + state[VK_MENU] &= ~0x8000; + SetKeyboardState(state); + */ + //PostMessageW(GetFocus(), WM_SYSKEYUP, VK_MENU, 0xC0'38'0001); + + if (focus != list) + SetFocus(list); + ListView_SetItemState(list, -1, 0, LVIS_SELECTED); + ListView_SetItemState(list, ListView_GetTopIndex(list) + num, LVIS_SELECTED, LVIS_SELECTED); + /* + RECT rect; + ListView_GetItemRect((HWND)GetPropW(list, prop_list_quick_list), num, &rect, LVIR_BOUNDS); + LPARAM coord = rect.right | (rect.top + 10) << 16; + PostMessageW(list, WM_LBUTTONDOWN, 0, coord); + PostMessageW(list, WM_LBUTTONUP, 0, coord); + */ + + if (!ctrl && !shift) + hotkey = Alt; + else if (ctrl && !shift) + hotkey = AltCtrl; + else if (!ctrl && shift) + hotkey = AltShift; + + return true; + } + } else if (hotkey != None && code == HC_ACTION) { // !down + // the order of releasing is uncertain + HWND list = GetFocus(); + switch (hotkey) { + case Alt: + if (wParam == VK_MENU) { + PostMessageW(list, WM_KEYDOWN, VK_RETURN, 0x00'1C'0001); + PostMessageW(list, WM_KEYUP, VK_RETURN, 0xC0'1C'0001); + hotkey = None; + } + break; + case AltCtrl: + if (wParam == VK_MENU) { + bool ctrl = GetKeyState(VK_CONTROL) & 0x8000; + if (!ctrl) + PostMessageW(list, WM_KEYDOWN, VK_CONTROL, 0x00'1D'0001); + PostMessageW(list, WM_KEYDOWN, VK_RETURN, 0x00'1C'0001); + PostMessageW(list, WM_KEYUP, VK_RETURN, 0xC0'1C'0001); + if (!ctrl) + PostMessageW(list, WM_KEYUP, VK_CONTROL, 0xC0'1D'0001); + hotkey = None; + } + break; + case AltShift: + if (wParam == VK_MENU && !(GetKeyState(VK_SHIFT) & 0x8000) + || wParam == VK_SHIFT && !(GetKeyState(VK_MENU) & 0x8000)) + { + //PostMessageW(list, WM_KEYDOWN, VK_APPS, 0x01'5D'0001); + //PostMessageW(list, WM_KEYUP, VK_APPS, 0xC1'5D'0001); + PostMessageW(list, WM_CONTEXTMENU, (WPARAM)list, -1); + hotkey = None; + } + break; + } + } + } while (false); + return CallNextHookEx(keyboard_hook, code, wParam, lParam); +} + +constexpr int quick_list_width = 24; + +auto SetWindowPos_real = SetWindowPos; +BOOL WINAPI SetWindowPos_detour( + _In_ HWND hWnd, + _In_opt_ HWND hWndInsertAfter, + _In_ int X, + _In_ int Y, + _In_ int cx, + _In_ int cy, + _In_ UINT uFlags) +{ + using namespace std::literals; + + if (X == 0 && uFlags == SWP_NOACTIVATE | SWP_NOZORDER) { + if (HWND quick_list = (HWND)GetPropW(hWnd, prop_list_quick_list)) { + SetWindowPos_real(quick_list, hWndInsertAfter, X, Y, quick_list_width, cy, uFlags); + + X = quick_list_width; + cx -= quick_list_width; + } + } + return SetWindowPos_real(hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags); +} + +auto DeferWindowPos_real = DeferWindowPos; +HDWP WINAPI DeferWindowPos_detour( + _In_ HDWP hWinPosInfo, + _In_ HWND hWnd, + _In_opt_ HWND hWndInsertAfter, + _In_ int x, + _In_ int y, + _In_ int cx, + _In_ int cy, + _In_ UINT uFlags) +{ + if (x == 0 && uFlags == SWP_NOACTIVATE | SWP_NOREPOSITION | SWP_NOZORDER) { + if (HWND quick_list = (HWND)GetPropW(hWnd, prop_list_quick_list)) { + DeferWindowPos_real(hWinPosInfo, quick_list, hWndInsertAfter, x, y, quick_list_width, cy, uFlags); + + x = quick_list_width; + cx -= quick_list_width; + } + } + return DeferWindowPos_real(hWinPosInfo, hWnd, hWndInsertAfter, x, y, cx, cy, uFlags); +} + +void quick_select_init() { + if (ipc_version.major >= 1 && ipc_version.minor >= 5) + IbDetourAttach(&DeferWindowPos_real, DeferWindowPos_detour); + else + IbDetourAttach(&SetWindowPos_real, SetWindowPos_detour); + + keyboard_hook = SetWindowsHookExW(WH_KEYBOARD, keyboard_proc, nullptr, GetCurrentThreadId()); +} + +void quick_select_destroy() { + UnhookWindowsHookEx(keyboard_hook); + + if (ipc_version.major >= 1 && ipc_version.minor >= 5) + IbDetourDetach(&DeferWindowPos_real, DeferWindowPos_detour); + else + IbDetourDetach(&SetWindowPos_real, SetWindowPos_detour); +} + +WNDPROC quick_list_window_proc_prev; +LRESULT CALLBACK quick_list_window_proc( + _In_ HWND hwnd, + _In_ UINT uMsg, + _In_ WPARAM wParam, + _In_ LPARAM lParam) +{ + switch (uMsg) { + case WM_NCCALCSIZE: + { + // prevent scroll bars + DWORD style = GetWindowLongW(hwnd, GWL_STYLE); + + DWORD new_style = style; + if (new_style & WS_VSCROLL) + new_style &= ~WS_VSCROLL; + if (new_style & WS_HSCROLL) + new_style &= ~WS_HSCROLL; + + if (new_style != style) + SetWindowLongW(hwnd, GWL_STYLE, new_style); + } + } + return CallWindowProcW(quick_list_window_proc_prev, hwnd, uMsg, wParam, lParam); +} + +HWND quick_list_create(HWND parent, HINSTANCE instance) { + HWND quick_list = CreateWindowExW_real(LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER, WC_LISTVIEWW, nullptr, WS_CHILD | WS_VISIBLE | LVS_REPORT, 0, 0, quick_list_width, 0, parent, nullptr, instance, nullptr); + quick_list_window_proc_prev = (WNDPROC)SetWindowLongPtrW(quick_list, GWLP_WNDPROC, (LONG_PTR)quick_list_window_proc); + + wchar_t header[] = L"键"; + LVCOLUMNW column{ + .mask = LVCF_WIDTH | LVCF_TEXT, + .cx = quick_list_width, + .pszText = header, + .cchTextMax = std::size(header) - 1 + }; + ListView_InsertColumn(quick_list, 0, &column); + + wchar_t s[] = L"1"; + LVITEM item{ + .mask = LVIF_TEXT, + .iSubItem = 0, + .pszText = s + }; + + for (; s[0] <= L'9'; s[0]++) { + ListView_InsertItem(quick_list, &item); + item.iItem++; + } + s[0] = L'0'; + ListView_InsertItem(quick_list, &item); + item.iItem++; + + for (s[0] = L'A'; s[0] <= L'Z'; s[0]++) { + ListView_InsertItem(quick_list, &item); + item.iItem++; + } + + return quick_list; +} \ No newline at end of file diff --git a/Hijacker/quick_select.hpp b/Hijacker/quick_select.hpp new file mode 100644 index 0000000..d19164f --- /dev/null +++ b/Hijacker/quick_select.hpp @@ -0,0 +1,10 @@ +#pragma once + +constexpr wchar_t prop_edit_list[] = L"IbEverythingExt.List"; +constexpr wchar_t prop_list_quick_list[] = L"IbEverythingExt.QuickList"; + +// require ipc_init +void quick_select_init(); +void quick_select_destroy(); + +HWND quick_list_create(HWND parent, HINSTANCE instance); \ No newline at end of file diff --git a/Hijacker/search_history.cpp b/Hijacker/search_history.cpp index 88f935c..69d28cf 100644 --- a/Hijacker/search_history.cpp +++ b/Hijacker/search_history.cpp @@ -48,104 +48,113 @@ BOOL WINAPI MoveFileExW_detour( ) { using namespace std::literals; - if (search_history_handle && std::wstring_view(lpExistingFileName).ends_with(L"Search History.csv.tmp"sv)) { - search_history_handle = nullptr; - - /* - Search,Search Count,Last Search Date - "a",4,132767094406609228 - "case:regex:""[aA][bB][cC]""[dD单到的]",2,132767108299260960 - */ - auto& history = search_history_to_write; - - std::ostringstream out(std::ios_base::binary); // may be longer than buffer (such as "a" -> "nopy:a") - out << "Search,Search Count,Last Search Date\r\n"sv; - - std::unordered_map search_map{}; - uint32_t i = "Search,Search Count,Last Search Date\r\n"sv.size(); - while (i < history.size()) { - if (history[i++] != '"') - break; - out << '"'; - - // parse Search and convert processed content to raw content - std::string search; + if (search_history_handle) { + if (std::wstring_view existing_file(lpExistingFileName); + existing_file.ends_with(L".csv.tmp"sv) && existing_file.find(L"\\Search History") != existing_file.npos) + { + search_history_handle = nullptr; + + /* + Search,Search Count,Last Search Date + "a",4,132767094406609228 + "case:regex:""[aA][bB][cC]""[dD单到的]",2,132767108299260960 + */ + auto& history = search_history_to_write; + + std::ostringstream out(std::ios_base::binary); // may be longer than buffer (such as "a" -> "nopy:a") + out << "Search,Search Count,Last Search Date\r\n"sv; + + std::unordered_map search_map{}; + uint32_t i = "Search,Search Count,Last Search Date\r\n"sv.size(); while (i < history.size()) { - char c = history[i++]; - if (c == '"') { - if (i < history.size() && history[i] == '"') { // "" - search.push_back('"'); - i++; - } else - break; - } else - search.push_back(c); - } - { - // search to search_u16 - // std::wstring_convert is deprecated in C++ 17 - std::wstring search_u16(search.size(), L'\0'); - search_u16.resize(MultiByteToWideChar(CP_UTF8, 0, search.data(), search.size(), search_u16.data(), search_u16.size())); - - // processed content -> content - auto iter = content_map.find(search_u16); - if (iter != content_map.end()) { - // content to content_u8 - std::string content_u8(iter->second.size() * 3, '\0'); - int length = WideCharToMultiByte(CP_UTF8, 0, iter->second.data(), iter->second.size(), content_u8.data(), content_u8.size(), nullptr, nullptr); - if (!length) { - if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + if (history[i++] != '"') + break; + out << '"'; + + // parse Search and convert processed content to raw content + std::string search; + while (i < history.size()) { + char c = history[i++]; + if (c == '"') { + if (i < history.size() && history[i] == '"') { // "" + search.push_back('"'); + i++; + } else break; - content_u8.resize(iter->second.size() * 4); - length = WideCharToMultiByte(CP_UTF8, 0, iter->second.data(), iter->second.size(), content_u8.data(), content_u8.size(), nullptr, nullptr); + } else + search.push_back(c); + } + { + // search to search_u16 + // std::wstring_convert is deprecated in C++ 17 + std::wstring search_u16(search.size(), L'\0'); + search_u16.resize(MultiByteToWideChar(CP_UTF8, 0, search.data(), search.size(), search_u16.data(), search_u16.size())); + + // processed content -> content + auto iter = content_map.find(search_u16); + if (iter != content_map.end()) { + // content to content_u8 + std::string content_u8(iter->second.size() * 3, '\0'); + int length = WideCharToMultiByte(CP_UTF8, 0, iter->second.data(), iter->second.size(), content_u8.data(), content_u8.size(), nullptr, nullptr); + if (!length) { + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + break; + content_u8.resize(iter->second.size() * 4); + length = WideCharToMultiByte(CP_UTF8, 0, iter->second.data(), iter->second.size(), content_u8.data(), content_u8.size(), nullptr, nullptr); + } + content_u8.resize(length); + + search = content_u8; } - content_u8.resize(length); - - search = content_u8; } - } - out << search << '"' << ','; - i++; // ',' + for (char c : search) { + if (c == '"') + out << '"'; + out << c; + } + out << '"' << ','; + i++; // ',' - // parse Search Count and do sums - uint32_t j = i; - while (j < history.size()) { - if (history[j++] == ',') - break; - } - j--; - uint32_t count = std::atoi(&history[i]); // (i, j - i) - auto iter = search_map.find(search); - if (iter == search_map.end()) { - search_map[search] = count; - } else { - count += iter->second; - search_map.erase(iter); - out << count; - i = j; - } + // parse Search Count and do sums + uint32_t j = i; + while (j < history.size()) { + if (history[j++] == ',') + break; + } + j--; + uint32_t count = std::atoi(&history[i]); // (i, j - i) + auto iter = search_map.find(search); + if (iter == search_map.end()) { + search_map[search] = count; + } else { + count += iter->second; + search_map.erase(iter); + out << count; + i = j; + } - // the remaining - while (i < history.size()) { - char c = history[i++]; - out << c; - if (c == '\n') - break; + // the remaining + while (i < history.size()) { + char c = history[i++]; + out << c; + if (c == '\n') + break; + } } - } - history.clear(); + history.clear(); - HANDLE file = CreateFileW(lpExistingFileName, GENERIC_WRITE, FILE_SHARE_READ, nullptr, CREATE_ALWAYS, 0, nullptr); - if (!file) - return false; + HANDLE file = CreateFileW(lpExistingFileName, GENERIC_WRITE, FILE_SHARE_READ, nullptr, CREATE_ALWAYS, 0, nullptr); + if (!file) + return false; - const std::string& out_str = out.str(); - DWORD written; - bool result = WriteFile_real(file, out_str.data(), out_str.size(), &written, nullptr); + const std::string& out_str = out.str(); + DWORD written; + bool result = WriteFile_real(file, out_str.data(), out_str.size(), &written, nullptr); - CloseHandle(file); - if (!result) - return false; + CloseHandle(file); + if (!result) + return false; + } } return MoveFileExW_real(lpExistingFileName, lpNewFileName, dwFlags); } diff --git a/README.md b/README.md index cbffebf..47a9eec 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,56 @@ # IbEverythingExt -[Everything](https://www.voidtools.com/) 拼音搜索扩展。 +[Everything](https://www.voidtools.com/) 拼音搜索、快速选择扩展。 ## 预览 ![](docs/preview.png) ## 安装 -1. 支持 Everything x64 安装版和便携版,不支持 Lite。 - v1.5 Alpha 需要进行[一定配置](../../issues/5)。 +1. 支持 [Everything](https://www.voidtools.com/zh-cn/downloads/) x64 安装版和便携版,不支持精简版(Lite)。 + [v1.5 Alpha](http://www.voidtools.com/forum/viewtopic.php?f=12&t=9787) 目前相比 v1.4 有大约 30% 的性能提升,但没有中文语言,且可能存在一些 bug,请根据自己的需要进行选择。 1. 从 [Releases](../../releases) 下载压缩包。 -1. 解压压缩包,将 WindowsCodecs.dll 放入 Everything 安装目录( `C:\Program Files\Everything` )。 +1. 解压压缩包,将 bin 目录下的文件放入 Everything 安装目录( `C:\Program Files\Everything` )。 1. 重启 Everything。(如果不生效,请确认你安装了 [VC++ 2019 x64 运行库](https://support.microsoft.com/topic/the-latest-supported-visual-c-downloads-2647da03-1eea-4433-9aff-95f26a218cc0)) -## 搜索说明 -* 拼音搜索支持包括辅助平面在内的 Unicode 汉字。 +## 拼音搜索 +* 支持包括辅助平面在内的 Unicode 汉字。 * 默认小写字母匹配拼音或字母,大写字母只匹配字母。 * 修饰符 * py: 小写字母只匹配拼音 * nopy: 禁用拼音搜索(对所有关键字生效) - + + +## 快速选择 +* `Alt+键`:打开(选中并按 Enter) +* `Alt+Ctrl+键`:定位(选中并按 Ctrl+Enter) +* `Alt+Shift+键`:打开右键菜单 +* 原 Alt 键的功能可以通过先单击 Alt 键再按键实现。 + +## 配置 +修改 `IbEverythingExt.yaml` 文件: +```yaml +# 拼音搜索 +pinyin_search: true +# 快速选择 +quick_select: true +``` +(`true` 为开启,`false` 为关闭) ## 第三方程序支持 +拼音搜索支持以下第三方程序调用: + * [stnkl/EverythingToolbar](https://github.com/stnkl/EverythingToolbar) - + +* [Flow Launcher](https://github.com/Flow-Launcher/Flow.Launcher) 的 [Everything 插件](https://github.com/Flow-Launcher/Flow.Launcher.Plugin.Everything) + +* [火柴(火萤酱)](https://www.huochaipro.com/)本地搜索 + * [uTools](https://u.tools) 本地搜索 - + +* [Wox](https://github.com/Wox-launcher/Wox) 的 Everything 插件 + + +(如果使用的是 Everything Alpha 版,因为 Alpha 版默认启用了命名实例,大部分程序都不支持调用,需要[通过配置关闭命名实例](../../issues/5)。) ## 构建 * Hijacker 和 Test @@ -35,7 +61,7 @@ 1. [vcpkg](https://github.com/microsoft/vcpkg) ``` set VCPKG_DEFAULT_TRIPLET=x64-windows-static-md - vcpkg install detours + vcpkg install detours yaml-cpp ``` (x86 版本的 VCPKG_DEFAULT_TRIPLET 应为 x86-windows-static-md) 1. Test 还需要: diff --git a/Test/Test.cpp b/Test/Test.cpp deleted file mode 100644 index 5e48fcb..0000000 --- a/Test/Test.cpp +++ /dev/null @@ -1,272 +0,0 @@ -#define BOOST_TEST_MODULE Test -#include - -#include -#include -#include - -#pragma comment(lib, "winmm.lib") - -using namespace std::literals; - -// GBK -std::wstring pinyin_regex = L"〇一丂与业丣严丫丿乁乂么义乊乐乑乙乚乛也乵乻亄予于-云亚亜亞亦亪亱亴亿仡以仪仰仸伃伇伊伒众优伛伝伢伿佁但佑佒佗余佚佣佯佻佾侇侌侑依侥俁俋俑俓俞俣俨俹俺俼倄倚倻偀偃偊偐偞偠偣偤偯傆傊傛傜傟傭傴傿僌僥僪僷儀億儗儥優儼允元兖兗兪养兿円冘冝冤冶凐刈刖剈剡剦劓劜劮劷勇勈勚勜勩勻匀匇匋匜匬医匽卣卬印厂厃厊压厌厑厓原厡厣厭厳厴厵又友叕台右叶叹吁吆吋吔吖吚吟听吲吳吾呀呎呓员呦呭呹呾咉咏咦咬咽咿哊哑哕哟員哩哽哾唀唁唈唌唖唡唫唷唹啘啞啢啨啱喁喅喐喑喓喗喛喝喦喩喭喲営喻嗂嗈嗌嘢嘤噊噎噖噞噟噢噦噫噮噰噳噾嚈嚘-嚛嚥嚴嚶囈囐囙囝因囦囩园囿圁圄圆圉圎園圓圔圛圜圠圧圩圪圫圯圻坄均块坨坱坳垔垚垟垠垣垦垭垸垼垽埇埏埜域埡埯埶埸堉堊堐堙堣堨堬堯堰堷塋塎塩塬墅墉墕墷墿壄壅壓壛壧壱壹夁夃夕夗夜夤夭央失夵夷夽奄奇奕奥奫妁妋妍妖妘妜妟妤妧妪妴妷姎姚姨姬姲姶姷姸姻娅娛娪娫娮娯娱婣婬婭婴婸婹媀媐媕媖媛媪媮媱媴媵嫄嫈嫕嫗嫚嫛嫞嫣嬄嬈嬊嬐嬑嬟嬩嬮嬰嬳嬴嬽嬿孆孍孕孧孲孴孾它宇宎宐宛宜宥宧宴容寃寅寓寙寱寲射將尉尢尤尧尭尹尾屵屹屿岄岆岈岟岩岳峄峓峟峣峪峫峳峾峿崎崕崖崛崟崤崦崯崳崵崸崺崾嵃嵎嵒嵓嵛嵤嵱嶎嶖嶢嶤嶧嶪嶫嶬嶮嶷嶼嶽嶾巆巊巌巖巗巘巚巡已巳巸币帟帠幆幺幼幽广庌应庘庡庮庵庸庽庾廕廙廮廱廴延异弇弈弋弌引弬弲彛-彠彥彦彧彮影彵役徉御徭徼忆忔応忧忬怈怏怞怠怡怣怨怮怺怿恌恙恞恱恹恽恿悀悁悅悆悇悒悘悠悥悦惌惐惥惲愈愉意愑愓愔愚愝愠愥愪愮愹愿慂慃慇慍慭慵慾憂憖憗憶應懊懌懕懙懚懨懩懮懿戉或戫戭戲戺扅扆扊扚扜扡扬扰扵抁抈抎抑抣抭抰抴押拁拗拥拸拽挜挧挹挻捐捓捙捝捥捳掎掖掗掜掞掩掾揂揄揅揖揘揚揜揞揠揲援揶揺搋搖搤摇摬摿撄撎撽擁擇擖擛擨擪擫擽攁攍攖攸攺敔敡敥敭敼斁斔斜斞斦於施斿旑旕旖旟旲旸昀昂易昖昙昜映昱昳晏晔晕景晹晻暆暈暍暎暘暚暥曀曄曅曎曕曗曜曣曮曰曱曳曵朄月有朓朠札杅杙杝杨杬杳枂枍枒枖枟枻枼枽柂柍柚柡柼栎栐栘栧栩栯栶样栺桋桙桜桠桯梀梄梎梧梬棛棜棩棪棫棭椅椏椬椰椸椻椼楀楆楊楌楡楢楥楧楪業楰楹榅榆榏榚榞榣榬様槦槱槷槸樂樣樮樱樴樾橒橪橼檃檍檐檥檭檹檼檿櫌櫞櫟櫩櫲櫻櫽櫾櫿欎欕欝欤欥欭欲欹欽歅歇歈歋歍歖歝歟歶殀殃殒殔殕殗殞殥殪殷殹殽毅毉毓毹氀氜氤氧氩氬氱氲氳永汋汓汙汧汩汼汽沂沄沅沇沋沶油沿泂泄泅泆泑泱泳泿洂洇洋洕洝洢洩洫洮浂浟浥浧浳浴涂涌涎涒涓涢涯液涴淊淡淢淤淫淯淵淹淾渁渆渊渏渔渕渝温渫渰渶渷游湙湚湛湡湧湮湯湲湵溁溋溎源溒溔溢溳溵滎滛滟滢滧滪滺滽漁漄演漜漪漹漾潁潆潏潒潝潩潭潯潱澐澚澞澤澦澭澲澳澺濙濚濥濦濴瀀瀁瀅瀛瀠瀯瀴瀷瀹灁灉灎灐灔灜灧灩灪灹炀炈炎炏炴烄烊烎烏烑烟烨烻焆焉焑焔焬焰焱焲焴焸煇煐煙煜煠煨煬煴煾熀熅熉熎熒熖熙熠熤熨熪熼燁燄燏燕燚營燠燡燱燿爍爓爗爚爩爰爷爺爻牅牏牖牗牙牪牰犄犹犽犾狁狋狏狕狖狠狱狳狺狿猌猒猗猚猨猰猶猷猺猿獂獄獈獝獟獶玅玉王玗玙玚玡玥玧玪玴珆珚珜珢珧珱琂琊琙琟琰瑀瑒瑗瑘瑛瑜瑤瑩瑶瑿璌璍璎璵瓔瓛瓵甇甖甗用甬由甴甸畇畩畬畭異畹疋疑疙疟疡疣疨疫痈痍痏痒痖痬痷瘀瘂瘉瘍瘐瘖瘗瘞瘟瘧瘱瘾瘿癊癌癒癔癕癢癭癮癰皣盁盂盈益盐盓盶盾眃眏眑眙眢眻眼睚睪睮瞖瞱瞸矅矆矞矣矨矱砑研砚砡砽硍硏硛硢硧硪硬硯硲硽碒碞碣碤磍磒磘磤礇礏礒礖礙礜礢礯礹礿祅祎祐祤禉禋禐禓禕禜禦禴禹禺秇秐秗秞秧秵移稏稢稦稶穎穓穥穵穻穾穿窅窈窑窔窨窫窬窯窰窳竩竽笌笎笖筃筄筍筠筩筵筼箊箢箷箹篔篗篶篽簃簷籅籆籎籝籞籥籯籰籲粌粤粥粵糿約紆紜紲紻絏絪綖維綺緎緓緣緤緰緷緸緼縁縈縊縕縜縯繄繇繘繧繩繶繹纅纋纓纡约纭绎绬缊缘缢缨罂罃罌罨罭羊羏羐羑羕羗羛羠羡義羪羬羭羱羽羿翊翌翳翼耀耘耛耰耴耶耺聈聐聱聶聿肀肄肊肙肬育肴胤胦胭胰脜脩腋腌腧腪腰腴膁膉膡膺臃臆臒臙臾舀舁舆與舒舣艅艈艗艞艤艳艶艷艺艾芅芋芌芩芫芸芽苂苃苅苑苚苡苢苭英茒茔茚茟茰茵荑荥荧荫药荶荺荼莖莚莜莠莤莸莹莺菀菴菸萒萓萟萤营萦萭萮萸萾葉葕葯葽葾蒀蒏蒑蒕蒝蒬蒮蒷蓔蓣蓥蓹蓺蔅蔚蔩蔫蔭蕍蕓蕕蕘蕥蕰蕴蕷蕹薀薁薏薗薟薬薳藀藇藙藝藥藴蘊蘌蘙蘛蘟蘡蘥蘨虉虞虤虵虶蚁蚎蚏蚓蚖蚘蚜蚰蚴蛇蛍蛘蛜蛡蛦蛹蛾蜍蜎蜏蜒蜕蜟蜮蜴蜵蝆蝇蝓蝘蝝蝣蝤蝧蝯蝹蝺蝿螈螔螘螠螢螸螾蟈蟫蟻蠅蠖蠮蠱蠳衍衏衘衙衣衤衧衪衵袁袂袎袘袣袬裀裔裕裛裫裷裺裿褎褑褕褗褘褞褤褮褹襗襼襾要覃覎覞覦覮觃觎觺觾言訁訑訔訚訝訞訡訢訧訮訲訳詇詍詏詑詒詠詣詳詽誃誉誒誘語説誼誾諛諭諲諹諺謁謍謚謜謠謡謣謻譍譩譯議譺譻譽讉讌讑讔讛讞讠议讶译诒诣语诱说谀谊谒谕谚谣谳谷豓豔豙豛豣豫豷貁貍貐貖貗貟貤貽賏賱賹贀贇贋贏贗贠贻赝赟赢赺越趛趯趼跀跃跇跠踊踦踰踴躍躒躽軅軈軉軋軏軮軺軼輅輍輏輐輑輗輢輰輵輶輼輿轅轙轝轧轶轺辕辥辷込迂迃迆迎运迓远迤迭迱迶迻逌逘這逞逰逳逸逺逾遃遇遊運遗遙遠遥遹遺邀邍邎邑邕邘邧邪邮邺郁郓郔郚郢郧郵郺郼郾鄅鄆鄓鄖鄘鄞鄢鄴鄾酀酉酏酑酓酛酝酭酳酽醃醖醞醟醧醫醳醶醷醼釅釉釋野釔釪釴釶釾釿鈅鈏鈗鈘鈝鈠鈨鈺鈾鉇鉈鉛鉞鉠鉯銀銉銕銚銥銦銪銹銿鋆鋊鋋鋙鋣鋭鋺錏錟錡錥鍈鍚鍝鍱鎁鎐鎑鎣鎰鎱鏔鏞鐊鐍鐚鐛鐭鐷鐿鑍鑠鑰钀钇钖钥钰钺铀铅铔铕铘铟铫铱银铻锳镒镛镱閆閘閱閲閹閻閼閾闄闇闉闫阅阈阉阎阏阣-阦阭阮阳阴阽陁陓院陨陭陰陶陻陽隁隂隃隅隐隒隕隠隩險隱隶隿雁雅雉雍雓雝雨雩雲雵霅霒霙霠霣霪霬霱霷靉靥靨靷靾靿鞅鞇鞕韗韞韫音韵韹韺韻韾頁頉預頤頥頨頴頵顊顏顑顒顔顗願顤顩页预颍颐颕颖颙颜颺颻飏飖食飫飬飮飲飴餆養餍餘餚餣餫饁饇饐饔饜饫饮饴馀馌馧馭馻駀駅駌駚駰騐験騕騟騴騵驁驈驗驛驜驠驭驿骃验骬骮髃髺鬰鬱鬳鬻魇魊魘魚魣魭魷鮋鮣鮧鮨鮽鯈鯒鯣鯲鰅鰋鰑鰩鰫鱅鱊鱦鱮鱼鱿鲉鲬鳐鳙鳦鳫鳱鳶鳿鴁鴈鴉鴛鴢鴥-鴨鴪鴬鴳鴹鴺鵒鵪鵶鵷鵺鶂鶃鶍鶑鶠鶢鶧鶯鶰鷁鷂鷃鷊鷕鷖鷛鷠鷣鷧鷪鷰鷸鷹鷾鸃鸆鸈鸉鸎鸑鸒鸙鸚鸢鸦鸭鸯鸳鹆鹓鹝鹞鹢鹥鹦鹬鹰鹽麀麌麙麣麲黓黝黟黡黤黦黫黬黭黰黳黶黿鼋鼘鼝鼬鼴鼹鼼齖齗齞齦齩齫齬齮齳齴齵齸齾龂龈龉龑龠龥"; -std::wstring pinyin_branch = L"〇|一|丂|与|业|丣|严|丫|丿|乁|乂|么|义|乊|乐|乑|乙|乚|乛|也|乵|乻|亄|予|于|亏|亐|云|亚|亜|亞|亦|亪|亱|亴|亿|仡|以|仪|仰|仸|伃|伇|伊|伒|众|优|伛|伝|伢|伿|佁|但|佑|佒|佗|余|佚|佣|佯|佻|佾|侇|侌|侑|依|侥|俁|俋|俑|俓|俞|俣|俨|俹|俺|俼|倄|倚|倻|偀|偃|偊|偐|偞|偠|偣|偤|偯|傆|傊|傛|傜|傟|傭|傴|傿|僌|僥|僪|僷|儀|億|儗|儥|優|儼|允|元|兖|兗|兪|养|兿|円|冘|冝|冤|冶|凐|刈|刖|剈|剡|剦|劓|劜|劮|劷|勇|勈|勚|勜|勩|勻|匀|匇|匋|匜|匬|医|匽|卣|卬|印|厂|厃|厊|压|厌|厑|厓|原|厡|厣|厭|厳|厴|厵|又|友|叕|台|右|叶|叹|吁|吆|吋|吔|吖|吚|吟|听|吲|吳|吾|呀|呎|呓|员|呦|呭|呹|呾|咉|咏|咦|咬|咽|咿|哊|哑|哕|哟|員|哩|哽|哾|唀|唁|唈|唌|唖|唡|唫|唷|唹|啘|啞|啢|啨|啱|喁|喅|喐|喑|喓|喗|喛|喝|喦|喩|喭|喲|営|喻|嗂|嗈|嗌|嘢|嘤|噊|噎|噖|噞|噟|噢|噦|噫|噮|噰|噳|噾|嚈|嚘|嚙|嚚|嚛|嚥|嚴|嚶|囈|囐|囙|囝|因|囦|囩|园|囿|圁|圄|圆|圉|圎|園|圓|圔|圛|圜|圠|圧|圩|圪|圫|圯|圻|坄|均|块|坨|坱|坳|垔|垚|垟|垠|垣|垦|垭|垸|垼|垽|埇|埏|埜|域|埡|埯|埶|埸|堉|堊|堐|堙|堣|堨|堬|堯|堰|堷|塋|塎|塩|塬|墅|墉|墕|墷|墿|壄|壅|壓|壛|壧|壱|壹|夁|夃|夕|夗|夜|夤|夭|央|失|夵|夷|夽|奄|奇|奕|奥|奫|妁|妋|妍|妖|妘|妜|妟|妤|妧|妪|妴|妷|姎|姚|姨|姬|姲|姶|姷|姸|姻|娅|娛|娪|娫|娮|娯|娱|婣|婬|婭|婴|婸|婹|媀|媐|媕|媖|媛|媪|媮|媱|媴|媵|嫄|嫈|嫕|嫗|嫚|嫛|嫞|嫣|嬄|嬈|嬊|嬐|嬑|嬟|嬩|嬮|嬰|嬳|嬴|嬽|嬿|孆|孍|孕|孧|孲|孴|孾|它|宇|宎|宐|宛|宜|宥|宧|宴|容|寃|寅|寓|寙|寱|寲|射|將|尉|尢|尤|尧|尭|尹|尾|屵|屹|屿|岄|岆|岈|岟|岩|岳|峄|峓|峟|峣|峪|峫|峳|峾|峿|崎|崕|崖|崛|崟|崤|崦|崯|崳|崵|崸|崺|崾|嵃|嵎|嵒|嵓|嵛|嵤|嵱|嶎|嶖|嶢|嶤|嶧|嶪|嶫|嶬|嶮|嶷|嶼|嶽|嶾|巆|巊|巌|巖|巗|巘|巚|巡|已|巳|巸|币|帟|帠|幆|幺|幼|幽|广|庌|应|庘|庡|庮|庵|庸|庽|庾|廕|廙|廮|廱|廴|延|异|弇|弈|弋|弌|引|弬|弲|彛|彜|彝|彞|彟|彠|彥|彦|彧|彮|影|彵|役|徉|御|徭|徼|忆|忔|応|忧|忬|怈|怏|怞|怠|怡|怣|怨|怮|怺|怿|恌|恙|恞|恱|恹|恽|恿|悀|悁|悅|悆|悇|悒|悘|悠|悥|悦|惌|惐|惥|惲|愈|愉|意|愑|愓|愔|愚|愝|愠|愥|愪|愮|愹|愿|慂|慃|慇|慍|慭|慵|慾|憂|憖|憗|憶|應|懊|懌|懕|懙|懚|懨|懩|懮|懿|戉|或|戫|戭|戲|戺|扅|扆|扊|扚|扜|扡|扬|扰|扵|抁|抈|抎|抑|抣|抭|抰|抴|押|拁|拗|拥|拸|拽|挜|挧|挹|挻|捐|捓|捙|捝|捥|捳|掎|掖|掗|掜|掞|掩|掾|揂|揄|揅|揖|揘|揚|揜|揞|揠|揲|援|揶|揺|搋|搖|搤|摇|摬|摿|撄|撎|撽|擁|擇|擖|擛|擨|擪|擫|擽|攁|攍|攖|攸|攺|敔|敡|敥|敭|敼|斁|斔|斜|斞|斦|於|施|斿|旑|旕|旖|旟|旲|旸|昀|昂|易|昖|昙|昜|映|昱|昳|晏|晔|晕|景|晹|晻|暆|暈|暍|暎|暘|暚|暥|曀|曄|曅|曎|曕|曗|曜|曣|曮|曰|曱|曳|曵|朄|月|有|朓|朠|札|杅|杙|杝|杨|杬|杳|枂|枍|枒|枖|枟|枻|枼|枽|柂|柍|柚|柡|柼|栎|栐|栘|栧|栩|栯|栶|样|栺|桋|桙|桜|桠|桯|梀|梄|梎|梧|梬|棛|棜|棩|棪|棫|棭|椅|椏|椬|椰|椸|椻|椼|楀|楆|楊|楌|楡|楢|楥|楧|楪|業|楰|楹|榅|榆|榏|榚|榞|榣|榬|様|槦|槱|槷|槸|樂|樣|樮|樱|樴|樾|橒|橪|橼|檃|檍|檐|檥|檭|檹|檼|檿|櫌|櫞|櫟|櫩|櫲|櫻|櫽|櫾|櫿|欎|欕|欝|欤|欥|欭|欲|欹|欽|歅|歇|歈|歋|歍|歖|歝|歟|歶|殀|殃|殒|殔|殕|殗|殞|殥|殪|殷|殹|殽|毅|毉|毓|毹|氀|氜|氤|氧|氩|氬|氱|氲|氳|永|汋|汓|汙|汧|汩|汼|汽|沂|沄|沅|沇|沋|沶|油|沿|泂|泄|泅|泆|泑|泱|泳|泿|洂|洇|洋|洕|洝|洢|洩|洫|洮|浂|浟|浥|浧|浳|浴|涂|涌|涎|涒|涓|涢|涯|液|涴|淊|淡|淢|淤|淫|淯|淵|淹|淾|渁|渆|渊|渏|渔|渕|渝|温|渫|渰|渶|渷|游|湙|湚|湛|湡|湧|湮|湯|湲|湵|溁|溋|溎|源|溒|溔|溢|溳|溵|滎|滛|滟|滢|滧|滪|滺|滽|漁|漄|演|漜|漪|漹|漾|潁|潆|潏|潒|潝|潩|潭|潯|潱|澐|澚|澞|澤|澦|澭|澲|澳|澺|濙|濚|濥|濦|濴|瀀|瀁|瀅|瀛|瀠|瀯|瀴|瀷|瀹|灁|灉|灎|灐|灔|灜|灧|灩|灪|灹|炀|炈|炎|炏|炴|烄|烊|烎|烏|烑|烟|烨|烻|焆|焉|焑|焔|焬|焰|焱|焲|焴|焸|煇|煐|煙|煜|煠|煨|煬|煴|煾|熀|熅|熉|熎|熒|熖|熙|熠|熤|熨|熪|熼|燁|燄|燏|燕|燚|營|燠|燡|燱|燿|爍|爓|爗|爚|爩|爰|爷|爺|爻|牅|牏|牖|牗|牙|牪|牰|犄|犹|犽|犾|狁|狋|狏|狕|狖|狠|狱|狳|狺|狿|猌|猒|猗|猚|猨|猰|猶|猷|猺|猿|獂|獄|獈|獝|獟|獶|玅|玉|王|玗|玙|玚|玡|玥|玧|玪|玴|珆|珚|珜|珢|珧|珱|琂|琊|琙|琟|琰|瑀|瑒|瑗|瑘|瑛|瑜|瑤|瑩|瑶|瑿|璌|璍|璎|璵|瓔|瓛|瓵|甇|甖|甗|用|甬|由|甴|甸|畇|畩|畬|畭|異|畹|疋|疑|疙|疟|疡|疣|疨|疫|痈|痍|痏|痒|痖|痬|痷|瘀|瘂|瘉|瘍|瘐|瘖|瘗|瘞|瘟|瘧|瘱|瘾|瘿|癊|癌|癒|癔|癕|癢|癭|癮|癰|皣|盁|盂|盈|益|盐|盓|盶|盾|眃|眏|眑|眙|眢|眻|眼|睚|睪|睮|瞖|瞱|瞸|矅|矆|矞|矣|矨|矱|砑|研|砚|砡|砽|硍|硏|硛|硢|硧|硪|硬|硯|硲|硽|碒|碞|碣|碤|磍|磒|磘|磤|礇|礏|礒|礖|礙|礜|礢|礯|礹|礿|祅|祎|祐|祤|禉|禋|禐|禓|禕|禜|禦|禴|禹|禺|秇|秐|秗|秞|秧|秵|移|稏|稢|稦|稶|穎|穓|穥|穵|穻|穾|穿|窅|窈|窑|窔|窨|窫|窬|窯|窰|窳|竩|竽|笌|笎|笖|筃|筄|筍|筠|筩|筵|筼|箊|箢|箷|箹|篔|篗|篶|篽|簃|簷|籅|籆|籎|籝|籞|籥|籯|籰|籲|粌|粤|粥|粵|糿|約|紆|紜|紲|紻|絏|絪|綖|維|綺|緎|緓|緣|緤|緰|緷|緸|緼|縁|縈|縊|縕|縜|縯|繄|繇|繘|繧|繩|繶|繹|纅|纋|纓|纡|约|纭|绎|绬|缊|缘|缢|缨|罂|罃|罌|罨|罭|羊|羏|羐|羑|羕|羗|羛|羠|羡|義|羪|羬|羭|羱|羽|羿|翊|翌|翳|翼|耀|耘|耛|耰|耴|耶|耺|聈|聐|聱|聶|聿|肀|肄|肊|肙|肬|育|肴|胤|胦|胭|胰|脜|脩|腋|腌|腧|腪|腰|腴|膁|膉|膡|膺|臃|臆|臒|臙|臾|舀|舁|舆|與|舒|舣|艅|艈|艗|艞|艤|艳|艶|艷|艺|艾|芅|芋|芌|芩|芫|芸|芽|苂|苃|苅|苑|苚|苡|苢|苭|英|茒|茔|茚|茟|茰|茵|荑|荥|荧|荫|药|荶|荺|荼|莖|莚|莜|莠|莤|莸|莹|莺|菀|菴|菸|萒|萓|萟|萤|营|萦|萭|萮|萸|萾|葉|葕|葯|葽|葾|蒀|蒏|蒑|蒕|蒝|蒬|蒮|蒷|蓔|蓣|蓥|蓹|蓺|蔅|蔚|蔩|蔫|蔭|蕍|蕓|蕕|蕘|蕥|蕰|蕴|蕷|蕹|薀|薁|薏|薗|薟|薬|薳|藀|藇|藙|藝|藥|藴|蘊|蘌|蘙|蘛|蘟|蘡|蘥|蘨|虉|虞|虤|虵|虶|蚁|蚎|蚏|蚓|蚖|蚘|蚜|蚰|蚴|蛇|蛍|蛘|蛜|蛡|蛦|蛹|蛾|蜍|蜎|蜏|蜒|蜕|蜟|蜮|蜴|蜵|蝆|蝇|蝓|蝘|蝝|蝣|蝤|蝧|蝯|蝹|蝺|蝿|螈|螔|螘|螠|螢|螸|螾|蟈|蟫|蟻|蠅|蠖|蠮|蠱|蠳|衍|衏|衘|衙|衣|衤|衧|衪|衵|袁|袂|袎|袘|袣|袬|裀|裔|裕|裛|裫|裷|裺|裿|褎|褑|褕|褗|褘|褞|褤|褮|褹|襗|襼|襾|要|覃|覎|覞|覦|覮|觃|觎|觺|觾|言|訁|訑|訔|訚|訝|訞|訡|訢|訧|訮|訲|訳|詇|詍|詏|詑|詒|詠|詣|詳|詽|誃|誉|誒|誘|語|説|誼|誾|諛|諭|諲|諹|諺|謁|謍|謚|謜|謠|謡|謣|謻|譍|譩|譯|議|譺|譻|譽|讉|讌|讑|讔|讛|讞|讠|议|讶|译|诒|诣|语|诱|说|谀|谊|谒|谕|谚|谣|谳|谷|豓|豔|豙|豛|豣|豫|豷|貁|貍|貐|貖|貗|貟|貤|貽|賏|賱|賹|贀|贇|贋|贏|贗|贠|贻|赝|赟|赢|赺|越|趛|趯|趼|跀|跃|跇|跠|踊|踦|踰|踴|躍|躒|躽|軅|軈|軉|軋|軏|軮|軺|軼|輅|輍|輏|輐|輑|輗|輢|輰|輵|輶|輼|輿|轅|轙|轝|轧|轶|轺|辕|辥|辷|込|迂|迃|迆|迎|运|迓|远|迤|迭|迱|迶|迻|逌|逘|這|逞|逰|逳|逸|逺|逾|遃|遇|遊|運|遗|遙|遠|遥|遹|遺|邀|邍|邎|邑|邕|邘|邧|邪|邮|邺|郁|郓|郔|郚|郢|郧|郵|郺|郼|郾|鄅|鄆|鄓|鄖|鄘|鄞|鄢|鄴|鄾|酀|酉|酏|酑|酓|酛|酝|酭|酳|酽|醃|醖|醞|醟|醧|醫|醳|醶|醷|醼|釅|釉|釋|野|釔|釪|釴|釶|釾|釿|鈅|鈏|鈗|鈘|鈝|鈠|鈨|鈺|鈾|鉇|鉈|鉛|鉞|鉠|鉯|銀|銉|銕|銚|銥|銦|銪|銹|銿|鋆|鋊|鋋|鋙|鋣|鋭|鋺|錏|錟|錡|錥|鍈|鍚|鍝|鍱|鎁|鎐|鎑|鎣|鎰|鎱|鏔|鏞|鐊|鐍|鐚|鐛|鐭|鐷|鐿|鑍|鑠|鑰|钀|钇|钖|钥|钰|钺|铀|铅|铔|铕|铘|铟|铫|铱|银|铻|锳|镒|镛|镱|閆|閘|閱|閲|閹|閻|閼|閾|闄|闇|闉|闫|阅|阈|阉|阎|阏|阣|阤|阥|阦|阭|阮|阳|阴|阽|陁|陓|院|陨|陭|陰|陶|陻|陽|隁|隂|隃|隅|隐|隒|隕|隠|隩|險|隱|隶|隿|雁|雅|雉|雍|雓|雝|雨|雩|雲|雵|霅|霒|霙|霠|霣|霪|霬|霱|霷|靉|靥|靨|靷|靾|靿|鞅|鞇|鞕|韗|韞|韫|音|韵|韹|韺|韻|韾|頁|頉|預|頤|頥|頨|頴|頵|顊|顏|顑|顒|顔|顗|願|顤|顩|页|预|颍|颐|颕|颖|颙|颜|颺|颻|飏|飖|食|飫|飬|飮|飲|飴|餆|養|餍|餘|餚|餣|餫|饁|饇|饐|饔|饜|饫|饮|饴|馀|馌|馧|馭|馻|駀|駅|駌|駚|駰|騐|験|騕|騟|騴|騵|驁|驈|驗|驛|驜|驠|驭|驿|骃|验|骬|骮|髃|髺|鬰|鬱|鬳|鬻|魇|魊|魘|魚|魣|魭|魷|鮋|鮣|鮧|鮨|鮽|鯈|鯒|鯣|鯲|鰅|鰋|鰑|鰩|鰫|鱅|鱊|鱦|鱮|鱼|鱿|鲉|鲬|鳐|鳙|鳦|鳫|鳱|鳶|鳿|鴁|鴈|鴉|鴛|鴢|鴥|鴦|鴧|鴨|鴪|鴬|鴳|鴹|鴺|鵒|鵪|鵶|鵷|鵺|鶂|鶃|鶍|鶑|鶠|鶢|鶧|鶯|鶰|鷁|鷂|鷃|鷊|鷕|鷖|鷛|鷠|鷣|鷧|鷪|鷰|鷸|鷹|鷾|鸃|鸆|鸈|鸉|鸎|鸑|鸒|鸙|鸚|鸢|鸦|鸭|鸯|鸳|鹆|鹓|鹝|鹞|鹢|鹥|鹦|鹬|鹰|鹽|麀|麌|麙|麣|麲|黓|黝|黟|黡|黤|黦|黫|黬|黭|黰|黳|黶|黿|鼋|鼘|鼝|鼬|鼴|鼹|鼼|齖|齗|齞|齦|齩|齫|齬|齮|齳|齴|齵|齸|齾|龂|龈|龉|龑|龠|龥"; -std::wstring pinyin_range = L"〇-龥"; - -std::wstring pinyin_regex_gb2312 = L"一与业严丫丿么义乐乙也予于亏云亚亦亿仡以仪仰伊众优伛伢但佑佗余佚佣佯佻佾侑依侥俑俞俣俨俺倚偃允元兖养冤冶刈刖剡劓勇匀医卣印厂压厌原厣又友台右叶叹吁吆吖吟听吲吾呀呓员呦咏咦咬咽咿哑哕哟哩哽唁唷喁喑喝喻嗌嘤噎噢噫囝因园囿圄圆圉圜圩圪圯圻均块坨坳垠垣垦垭垸埏域埯埸堙堰塬墅墉壅壹夕夜夤夭央失夷奄奇奕奥妁妍妖妤妪姚姨姬姻娅娱婴媛媪媵嫣嬴孕它宇宛宜宥宴容寅寓射尉尢尤尧尹尾屹屿岈岩岳峄峪崎崖崛崤崦崾嵛嶷巡已巳币幺幼幽广应庵庸庾廴延异弈弋引彝彦影役徉御徭徼忆忧怏怠怡怨怿恙恹恽恿悒悠悦愈愉意愚愠愿慵懊懿或扬扰抑押拗拥拽挹捐掎掖掩掾揄揖揞揠揲援揶搋摇撄攸斜於施旖昀昂易昙映昱晏晔晕景曜曰曳月有札杨杳柚栎栩样桠梧椅椰楹榆樱樾橼檐欤欲欹歇殃殒殪殷毅毓毹氤氧氩氲永汩汽沂沅油沿泄泅泱泳洇洋洫洮浴涂涌涎涓涯液淡淤淫淹渊渔渝温渫游湛湮源溢滟滢演漪漾潆潭澳瀛瀹炀炎烊烟烨焉焰焱煜煨熙熠熨燕燠爰爷爻牖牙犄犹狁狠狱狳狺猗猷猿玉王珧琊琰瑗瑛瑜瑶璎用甬由甸畹疋疑疙疟疡疣疫痈痍痒痖瘀瘐瘗瘟瘾瘿癌癔盂盈益盐盾眙眢眼睚矣砑研砚硪硬碣禹禺秧移穿窈窑窨窬窳竽筠筵箢粤粥繇纡约纭绎缘缢缨罂罨羊羡羽羿翊翌翳翼耀耘耶聱聿肀肄育肴胤胭胰腋腌腧腰腴膺臃臆臾舀舁舆舒舣艳艺艾芋芩芫芸芽苑苡英茔茚茵荑荥荧荫药荼莜莠莸莹莺菀菸萤营萦萸蓣蓥蔚蔫蕴蕹薏虞蚁蚓蚜蚰蚴蛇蛘蛹蛾蜍蜒蜕蜮蜴蝇蝓蝣蝤螈蠖衍衙衣衤袁袂裔裕要覃觎言誉讠议讶译诒诣语诱说谀谊谒谕谚谣谳谷豫贻赝赢越趼跃踊轧轶轺辕迂迎运迓远迤迭逞逸逾遇遗遥邀邑邕邪邮邺郁郓郢郧郾鄞鄢酉酏酝酽釉野钇钥钰钺铀铅铕铘铟铫铱银镒镛镱闫阅阈阉阎阏阮阳阴阽院陨陶隅隐隶雁雅雉雍雨雩霪靥鞅韫音韵页预颍颐颖颜食餍饔饫饮饴馀驭驿验鬻魇鱼鱿鳐鳙鸢鸦鸭鸯鸳鹆鹞鹦鹬鹰黝黟鼋鼬鼹龈龉龠"; -std::wstring pinyin_range_gb2312 = L"[一-龠]"; - -#include "dynamic_charset.h.user" // private data -//#define DYNAMIC_CHARSET_Y L"源页议游育娱乐汽语言元一么于音友有影" -//#define DYNAMIC_CHARSET_YY_1 L"娱语" -//#define DYNAMIC_CHARSET_YY_2 L"乐言" - - -BOOST_FIXTURE_TEST_SUITE(SingleCharQueryPerformance, Everythings::Everything) - void test_query(Everythings::Everything& ev, std::wstring_view query) { - using namespace Everythings; - - DWORD t = timeGetTime(); - ev.query_send(query, 0, Request::FileName); - QueryResults results = ev.query_get(); - t = timeGetTime() - t; - - BOOST_CHECK(results.found_num); - BOOST_TEST_MESSAGE(t << "ms"); - Sleep(2000); - } - - BOOST_AUTO_TEST_SUITE(Char) - - BOOST_AUTO_TEST_CASE(Char) { - test_query(*this, L"y"); - } - - BOOST_AUTO_TEST_CASE(Regex) { - test_query(*this, L"regex:y"); - } - - BOOST_AUTO_TEST_CASE(RegexSet) { - test_query(*this, L"regex:[y]"); - } - - BOOST_AUTO_TEST_SUITE_END() - - - BOOST_AUTO_TEST_SUITE(Pinyin) - - BOOST_AUTO_TEST_CASE(Base_v03) { - test_query(*this, L"regex:[y" DYNAMIC_CHARSET_Y L"]"); - } - - // very fast - BOOST_AUTO_TEST_CASE(LetterBranch) { - test_query(*this, L"regex:y|[" DYNAMIC_CHARSET_Y L"]"); - } - - BOOST_AUTO_TEST_CASE(LetterBranchCase) { - test_query(*this, L"case:regex:y|Y|[" DYNAMIC_CHARSET_Y L"]"); - } - - BOOST_AUTO_TEST_CASE(Base_v02) { - test_query(*this, L"case:regex:[yY" DYNAMIC_CHARSET_Y L"]"); - } - - // better - BOOST_AUTO_TEST_CASE(Dynamic) { - test_query(*this, L"regex:[y" DYNAMIC_CHARSET_Y L"]"); - } - - // better - BOOST_AUTO_TEST_CASE(Gb2312) { - test_query(*this, L"regex:[y" + pinyin_regex_gb2312 + L"]"); - } - - // faster but not the same - BOOST_AUTO_TEST_CASE(Count) { - // place count before regex! - test_query(*this, L"count:100 regex:[y" + pinyin_regex + L"]"); - } - - // faster but not the same - BOOST_AUTO_TEST_CASE(Boundary) { - test_query(*this, L"regex:\\b[y" + pinyin_regex + L"]"); - } - - // better - BOOST_AUTO_TEST_CASE(Case) { - test_query(*this, L"case:regex:[yY" + pinyin_regex + L"]"); - } - - BOOST_AUTO_TEST_CASE(Base_v01) { - test_query(*this, L"regex:[y" + pinyin_regex + L"]"); - } - - /* - // cpu killer - BOOST_AUTO_TEST_CASE(Branch) { - test_query(*this, L"regex:y|" + pinyin_branch); - } - */ - - // worse - BOOST_AUTO_TEST_CASE(Lookaround1) { - test_query(*this, L"regex:"); - } - - BOOST_AUTO_TEST_CASE(Lookaround2_1) { - // regex:"(?>y|(?=[一-龠])一)" - test_query(*this, L"regex:\"(?>y|(?=[" + pinyin_range + L"])[" + pinyin_regex + L"])\""); - } - - // worse than 1 - BOOST_AUTO_TEST_CASE(Lookaround2) { - // regex:"(y|(?=[一-龠])一)" - test_query(*this, L"regex:\"(y|(?=[" + pinyin_range + L"])[" + pinyin_regex + L"])\""); - } - - // worse than 2 - BOOST_AUTO_TEST_CASE(Lookaround3) { - // regex:"(y|(?![\x00-\xff])一)" - test_query(*this, L"regex:\"(y|(?![\\x00-\\xff])[" + pinyin_regex + L"])\""); - } - - // worse than 3 - BOOST_AUTO_TEST_CASE(Lookaround4) { - // regex:"(y|(?![一-龠])(?!)|一)" - test_query(*this, L"regex:\"(y|(?![" + pinyin_range + L"])(?!)|[" + pinyin_regex + L"])\""); - } - BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE_END() - - -BOOST_FIXTURE_TEST_SUITE(MultiCharsQueryPerformance, Everythings::Everything) - void test_query(Everythings::Everything& ev, std::wstring_view query) { - using namespace Everythings; - - DWORD t = timeGetTime(); - ev.query_send(query, 0, Request::FileName); - QueryResults results = ev.query_get(); - t = timeGetTime() - t; - - BOOST_CHECK(results.found_num); - BOOST_TEST_MESSAGE(t << "ms"); - Sleep(2000); - } - - BOOST_AUTO_TEST_SUITE(Char) - - BOOST_AUTO_TEST_CASE(Branch) { - test_query(*this, L"x|y"); - } - - // faster than set? - BOOST_AUTO_TEST_CASE(RegexBranch) { - test_query(*this, L"regex:x|y"); - } - - BOOST_AUTO_TEST_CASE(RegexSet) { - test_query(*this, L"regex:[xy]"); - } - - BOOST_AUTO_TEST_SUITE_END() - - - BOOST_AUTO_TEST_SUITE(Char100) - - BOOST_AUTO_TEST_CASE(RegexSet) { - test_query(*this, L"regex:[一与业严丫丿么义乐乙也予于亏云亚亦亿仡以仪仰伊众优伛伢但佑佗余佚佣佯佻佾侑依侥俑俞俣俨俺倚偃允元兖养冤冶刈刖剡劓勇匀医卣印厂压厌原厣又友台右叶叹吁吆吖吟听吲吾呀呓员呦咏咦咬咽咿哑哕哟哩哽唁唷喁喑喝喻嗌]"); - } - - // very slow - BOOST_AUTO_TEST_CASE(RegexBranch) { - test_query(*this, L"regex:一|与|业|严|丫|丿|么|义|乐|乙|也|予|于|亏|云|亚|亦|亿|仡|以|仪|仰|伊|众|优|伛|伢|但|佑|佗|余|佚|佣|佯|佻|佾|侑|依|侥|俑|俞|俣|俨|俺|倚|偃|允|元|兖|养|冤|冶|刈|刖|剡|劓|勇|匀|医|卣|印|厂|压|厌|原|厣|又|友|台|右|叶|叹|吁|吆|吖|吟|听|吲|吾|呀|呓|员|呦|咏|咦|咬|咽|咿|哑|哕|哟|哩|哽|唁|唷|喁|喑|喝|喻|嗌"); - } - - // very slow - BOOST_AUTO_TEST_CASE(Branch) { - test_query(*this, L"一|与|业|严|丫|丿|么|义|乐|乙|也|予|于|亏|云|亚|亦|亿|仡|以|仪|仰|伊|众|优|伛|伢|但|佑|佗|余|佚|佣|佯|佻|佾|侑|依|侥|俑|俞|俣|俨|俺|倚|偃|允|元|兖|养|冤|冶|刈|刖|剡|劓|勇|匀|医|卣|印|厂|压|厌|原|厣|又|友|台|右|叶|叹|吁|吆|吖|吟|听|吲|吾|呀|呓|员|呦|咏|咦|咬|咽|咿|哑|哕|哟|哩|哽|唁|唷|喁|喑|喝|喻|嗌"); - } - - BOOST_AUTO_TEST_SUITE_END() - - - BOOST_AUTO_TEST_SUITE(Pinyin) - - BOOST_AUTO_TEST_CASE(Base_v03) { - test_query(*this, L"regex:[y" DYNAMIC_CHARSET_YY_1 L"][y" DYNAMIC_CHARSET_YY_2 L"]"); - } - - // slower than Base_v02 - BOOST_AUTO_TEST_CASE(LetterBranch) { - // regex:"(y|[英])(y|[语])" - test_query(*this, L"regex:\"(y|[" DYNAMIC_CHARSET_YY_1 L"])(y|[" DYNAMIC_CHARSET_YY_2 L"])\""); - } - - BOOST_AUTO_TEST_CASE(LetterBranch_1) { - // regex:"(?:y|[英])(?:y|[语])" - test_query(*this, L"regex:\"(?:y|[" DYNAMIC_CHARSET_YY_1 L"])(?:y|[" DYNAMIC_CHARSET_YY_2 L"])\""); - } - - BOOST_AUTO_TEST_CASE(LetterBranch_2) { - // regex:"(?>y|[英])(?>y|[语])" - test_query(*this, L"regex:\"(?>y|[" DYNAMIC_CHARSET_YY_1 L"])(?>y|[" DYNAMIC_CHARSET_YY_2 L"])\""); - } - - BOOST_AUTO_TEST_CASE(Base_v02) { - test_query(*this, L"case:regex:[yY" DYNAMIC_CHARSET_YY_1 L"][yY" DYNAMIC_CHARSET_YY_2 L"]"); - } - - BOOST_AUTO_TEST_CASE(DynamicPair) { - test_query(*this, L"regex:[y" DYNAMIC_CHARSET_YY_1 L"][y" DYNAMIC_CHARSET_YY_2 L"]"); - } - - BOOST_AUTO_TEST_CASE(Dynamic) { - test_query(*this, L"regex:[y" DYNAMIC_CHARSET_Y L"]{2}"); - } - - BOOST_AUTO_TEST_CASE(Base_v01) { - test_query(*this, L"regex:[y" + pinyin_regex + L"]{2}"); - } - - BOOST_AUTO_TEST_CASE(Quantifier) { - test_query(*this, L"regex:[y" + pinyin_regex + L"]{2}"); - } - - BOOST_AUTO_TEST_CASE(Repeat) { - test_query(*this, L"regex:[y" + pinyin_regex + L"][y" + pinyin_regex + L"]"); - } - - BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE_END() - - -BOOST_FIXTURE_TEST_SUITE(DynamicCharset, Everythings::Everything) - void test_query(Everythings::Everything& ev, std::wstring_view query) { - using namespace Everythings; - - DWORD t = timeGetTime(); - ev.query_send(query, Search::MatchCase, Request::FileName); - QueryResults results = ev.query_get(); - t = timeGetTime() - t; - - BOOST_TEST_MESSAGE(results.available_num << ", " << t << "ms"); - Sleep(2000); - } - - BOOST_AUTO_TEST_CASE(GenerateQuery) { - test_query(*this, L"regex:[〇-𰻞]"); - } - - BOOST_AUTO_TEST_CASE(UpdateQuery) { - test_query(*this, L"rc:"); - } - - BOOST_AUTO_TEST_CASE(UpdateQueryRegex) { - test_query(*this, L"rc: regex:[〇-𰻞]"); - } - -BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file diff --git a/Test/Test.vcxproj b/Test/Test.vcxproj index d57e9ec..6594430 100644 --- a/Test/Test.vcxproj +++ b/Test/Test.vcxproj @@ -155,7 +155,12 @@ - + + + + + + diff --git a/Test/Test.vcxproj.filters b/Test/Test.vcxproj.filters index db0c6cf..c79b97c 100644 --- a/Test/Test.vcxproj.filters +++ b/Test/Test.vcxproj.filters @@ -15,8 +15,19 @@ - + Source Files + + Source Files + + + Source Files + + + + + Header Files + \ No newline at end of file diff --git a/Test/common.hpp b/Test/common.hpp new file mode 100644 index 0000000..31837b9 --- /dev/null +++ b/Test/common.hpp @@ -0,0 +1,23 @@ +#pragma once +#include + +#include +#include +#include + +#pragma comment(lib, "winmm.lib") + +using namespace std::literals; + +// GBK +inline std::wstring pinyin_regex = L"〇一丂与业丣严丫丿乁乂么义乊乐乑乙乚乛也乵乻亄予于-云亚亜亞亦亪亱亴亿仡以仪仰仸伃伇伊伒众优伛伝伢伿佁但佑佒佗余佚佣佯佻佾侇侌侑依侥俁俋俑俓俞俣俨俹俺俼倄倚倻偀偃偊偐偞偠偣偤偯傆傊傛傜傟傭傴傿僌僥僪僷儀億儗儥優儼允元兖兗兪养兿円冘冝冤冶凐刈刖剈剡剦劓劜劮劷勇勈勚勜勩勻匀匇匋匜匬医匽卣卬印厂厃厊压厌厑厓原厡厣厭厳厴厵又友叕台右叶叹吁吆吋吔吖吚吟听吲吳吾呀呎呓员呦呭呹呾咉咏咦咬咽咿哊哑哕哟員哩哽哾唀唁唈唌唖唡唫唷唹啘啞啢啨啱喁喅喐喑喓喗喛喝喦喩喭喲営喻嗂嗈嗌嘢嘤噊噎噖噞噟噢噦噫噮噰噳噾嚈嚘-嚛嚥嚴嚶囈囐囙囝因囦囩园囿圁圄圆圉圎園圓圔圛圜圠圧圩圪圫圯圻坄均块坨坱坳垔垚垟垠垣垦垭垸垼垽埇埏埜域埡埯埶埸堉堊堐堙堣堨堬堯堰堷塋塎塩塬墅墉墕墷墿壄壅壓壛壧壱壹夁夃夕夗夜夤夭央失夵夷夽奄奇奕奥奫妁妋妍妖妘妜妟妤妧妪妴妷姎姚姨姬姲姶姷姸姻娅娛娪娫娮娯娱婣婬婭婴婸婹媀媐媕媖媛媪媮媱媴媵嫄嫈嫕嫗嫚嫛嫞嫣嬄嬈嬊嬐嬑嬟嬩嬮嬰嬳嬴嬽嬿孆孍孕孧孲孴孾它宇宎宐宛宜宥宧宴容寃寅寓寙寱寲射將尉尢尤尧尭尹尾屵屹屿岄岆岈岟岩岳峄峓峟峣峪峫峳峾峿崎崕崖崛崟崤崦崯崳崵崸崺崾嵃嵎嵒嵓嵛嵤嵱嶎嶖嶢嶤嶧嶪嶫嶬嶮嶷嶼嶽嶾巆巊巌巖巗巘巚巡已巳巸币帟帠幆幺幼幽广庌应庘庡庮庵庸庽庾廕廙廮廱廴延异弇弈弋弌引弬弲彛-彠彥彦彧彮影彵役徉御徭徼忆忔応忧忬怈怏怞怠怡怣怨怮怺怿恌恙恞恱恹恽恿悀悁悅悆悇悒悘悠悥悦惌惐惥惲愈愉意愑愓愔愚愝愠愥愪愮愹愿慂慃慇慍慭慵慾憂憖憗憶應懊懌懕懙懚懨懩懮懿戉或戫戭戲戺扅扆扊扚扜扡扬扰扵抁抈抎抑抣抭抰抴押拁拗拥拸拽挜挧挹挻捐捓捙捝捥捳掎掖掗掜掞掩掾揂揄揅揖揘揚揜揞揠揲援揶揺搋搖搤摇摬摿撄撎撽擁擇擖擛擨擪擫擽攁攍攖攸攺敔敡敥敭敼斁斔斜斞斦於施斿旑旕旖旟旲旸昀昂易昖昙昜映昱昳晏晔晕景晹晻暆暈暍暎暘暚暥曀曄曅曎曕曗曜曣曮曰曱曳曵朄月有朓朠札杅杙杝杨杬杳枂枍枒枖枟枻枼枽柂柍柚柡柼栎栐栘栧栩栯栶样栺桋桙桜桠桯梀梄梎梧梬棛棜棩棪棫棭椅椏椬椰椸椻椼楀楆楊楌楡楢楥楧楪業楰楹榅榆榏榚榞榣榬様槦槱槷槸樂樣樮樱樴樾橒橪橼檃檍檐檥檭檹檼檿櫌櫞櫟櫩櫲櫻櫽櫾櫿欎欕欝欤欥欭欲欹欽歅歇歈歋歍歖歝歟歶殀殃殒殔殕殗殞殥殪殷殹殽毅毉毓毹氀氜氤氧氩氬氱氲氳永汋汓汙汧汩汼汽沂沄沅沇沋沶油沿泂泄泅泆泑泱泳泿洂洇洋洕洝洢洩洫洮浂浟浥浧浳浴涂涌涎涒涓涢涯液涴淊淡淢淤淫淯淵淹淾渁渆渊渏渔渕渝温渫渰渶渷游湙湚湛湡湧湮湯湲湵溁溋溎源溒溔溢溳溵滎滛滟滢滧滪滺滽漁漄演漜漪漹漾潁潆潏潒潝潩潭潯潱澐澚澞澤澦澭澲澳澺濙濚濥濦濴瀀瀁瀅瀛瀠瀯瀴瀷瀹灁灉灎灐灔灜灧灩灪灹炀炈炎炏炴烄烊烎烏烑烟烨烻焆焉焑焔焬焰焱焲焴焸煇煐煙煜煠煨煬煴煾熀熅熉熎熒熖熙熠熤熨熪熼燁燄燏燕燚營燠燡燱燿爍爓爗爚爩爰爷爺爻牅牏牖牗牙牪牰犄犹犽犾狁狋狏狕狖狠狱狳狺狿猌猒猗猚猨猰猶猷猺猿獂獄獈獝獟獶玅玉王玗玙玚玡玥玧玪玴珆珚珜珢珧珱琂琊琙琟琰瑀瑒瑗瑘瑛瑜瑤瑩瑶瑿璌璍璎璵瓔瓛瓵甇甖甗用甬由甴甸畇畩畬畭異畹疋疑疙疟疡疣疨疫痈痍痏痒痖痬痷瘀瘂瘉瘍瘐瘖瘗瘞瘟瘧瘱瘾瘿癊癌癒癔癕癢癭癮癰皣盁盂盈益盐盓盶盾眃眏眑眙眢眻眼睚睪睮瞖瞱瞸矅矆矞矣矨矱砑研砚砡砽硍硏硛硢硧硪硬硯硲硽碒碞碣碤磍磒磘磤礇礏礒礖礙礜礢礯礹礿祅祎祐祤禉禋禐禓禕禜禦禴禹禺秇秐秗秞秧秵移稏稢稦稶穎穓穥穵穻穾穿窅窈窑窔窨窫窬窯窰窳竩竽笌笎笖筃筄筍筠筩筵筼箊箢箷箹篔篗篶篽簃簷籅籆籎籝籞籥籯籰籲粌粤粥粵糿約紆紜紲紻絏絪綖維綺緎緓緣緤緰緷緸緼縁縈縊縕縜縯繄繇繘繧繩繶繹纅纋纓纡约纭绎绬缊缘缢缨罂罃罌罨罭羊羏羐羑羕羗羛羠羡義羪羬羭羱羽羿翊翌翳翼耀耘耛耰耴耶耺聈聐聱聶聿肀肄肊肙肬育肴胤胦胭胰脜脩腋腌腧腪腰腴膁膉膡膺臃臆臒臙臾舀舁舆與舒舣艅艈艗艞艤艳艶艷艺艾芅芋芌芩芫芸芽苂苃苅苑苚苡苢苭英茒茔茚茟茰茵荑荥荧荫药荶荺荼莖莚莜莠莤莸莹莺菀菴菸萒萓萟萤营萦萭萮萸萾葉葕葯葽葾蒀蒏蒑蒕蒝蒬蒮蒷蓔蓣蓥蓹蓺蔅蔚蔩蔫蔭蕍蕓蕕蕘蕥蕰蕴蕷蕹薀薁薏薗薟薬薳藀藇藙藝藥藴蘊蘌蘙蘛蘟蘡蘥蘨虉虞虤虵虶蚁蚎蚏蚓蚖蚘蚜蚰蚴蛇蛍蛘蛜蛡蛦蛹蛾蜍蜎蜏蜒蜕蜟蜮蜴蜵蝆蝇蝓蝘蝝蝣蝤蝧蝯蝹蝺蝿螈螔螘螠螢螸螾蟈蟫蟻蠅蠖蠮蠱蠳衍衏衘衙衣衤衧衪衵袁袂袎袘袣袬裀裔裕裛裫裷裺裿褎褑褕褗褘褞褤褮褹襗襼襾要覃覎覞覦覮觃觎觺觾言訁訑訔訚訝訞訡訢訧訮訲訳詇詍詏詑詒詠詣詳詽誃誉誒誘語説誼誾諛諭諲諹諺謁謍謚謜謠謡謣謻譍譩譯議譺譻譽讉讌讑讔讛讞讠议讶译诒诣语诱说谀谊谒谕谚谣谳谷豓豔豙豛豣豫豷貁貍貐貖貗貟貤貽賏賱賹贀贇贋贏贗贠贻赝赟赢赺越趛趯趼跀跃跇跠踊踦踰踴躍躒躽軅軈軉軋軏軮軺軼輅輍輏輐輑輗輢輰輵輶輼輿轅轙轝轧轶轺辕辥辷込迂迃迆迎运迓远迤迭迱迶迻逌逘這逞逰逳逸逺逾遃遇遊運遗遙遠遥遹遺邀邍邎邑邕邘邧邪邮邺郁郓郔郚郢郧郵郺郼郾鄅鄆鄓鄖鄘鄞鄢鄴鄾酀酉酏酑酓酛酝酭酳酽醃醖醞醟醧醫醳醶醷醼釅釉釋野釔釪釴釶釾釿鈅鈏鈗鈘鈝鈠鈨鈺鈾鉇鉈鉛鉞鉠鉯銀銉銕銚銥銦銪銹銿鋆鋊鋋鋙鋣鋭鋺錏錟錡錥鍈鍚鍝鍱鎁鎐鎑鎣鎰鎱鏔鏞鐊鐍鐚鐛鐭鐷鐿鑍鑠鑰钀钇钖钥钰钺铀铅铔铕铘铟铫铱银铻锳镒镛镱閆閘閱閲閹閻閼閾闄闇闉闫阅阈阉阎阏阣-阦阭阮阳阴阽陁陓院陨陭陰陶陻陽隁隂隃隅隐隒隕隠隩險隱隶隿雁雅雉雍雓雝雨雩雲雵霅霒霙霠霣霪霬霱霷靉靥靨靷靾靿鞅鞇鞕韗韞韫音韵韹韺韻韾頁頉預頤頥頨頴頵顊顏顑顒顔顗願顤顩页预颍颐颕颖颙颜颺颻飏飖食飫飬飮飲飴餆養餍餘餚餣餫饁饇饐饔饜饫饮饴馀馌馧馭馻駀駅駌駚駰騐験騕騟騴騵驁驈驗驛驜驠驭驿骃验骬骮髃髺鬰鬱鬳鬻魇魊魘魚魣魭魷鮋鮣鮧鮨鮽鯈鯒鯣鯲鰅鰋鰑鰩鰫鱅鱊鱦鱮鱼鱿鲉鲬鳐鳙鳦鳫鳱鳶鳿鴁鴈鴉鴛鴢鴥-鴨鴪鴬鴳鴹鴺鵒鵪鵶鵷鵺鶂鶃鶍鶑鶠鶢鶧鶯鶰鷁鷂鷃鷊鷕鷖鷛鷠鷣鷧鷪鷰鷸鷹鷾鸃鸆鸈鸉鸎鸑鸒鸙鸚鸢鸦鸭鸯鸳鹆鹓鹝鹞鹢鹥鹦鹬鹰鹽麀麌麙麣麲黓黝黟黡黤黦黫黬黭黰黳黶黿鼋鼘鼝鼬鼴鼹鼼齖齗齞齦齩齫齬齮齳齴齵齸齾龂龈龉龑龠龥"; +inline std::wstring pinyin_branch = L"〇|一|丂|与|业|丣|严|丫|丿|乁|乂|么|义|乊|乐|乑|乙|乚|乛|也|乵|乻|亄|予|于|亏|亐|云|亚|亜|亞|亦|亪|亱|亴|亿|仡|以|仪|仰|仸|伃|伇|伊|伒|众|优|伛|伝|伢|伿|佁|但|佑|佒|佗|余|佚|佣|佯|佻|佾|侇|侌|侑|依|侥|俁|俋|俑|俓|俞|俣|俨|俹|俺|俼|倄|倚|倻|偀|偃|偊|偐|偞|偠|偣|偤|偯|傆|傊|傛|傜|傟|傭|傴|傿|僌|僥|僪|僷|儀|億|儗|儥|優|儼|允|元|兖|兗|兪|养|兿|円|冘|冝|冤|冶|凐|刈|刖|剈|剡|剦|劓|劜|劮|劷|勇|勈|勚|勜|勩|勻|匀|匇|匋|匜|匬|医|匽|卣|卬|印|厂|厃|厊|压|厌|厑|厓|原|厡|厣|厭|厳|厴|厵|又|友|叕|台|右|叶|叹|吁|吆|吋|吔|吖|吚|吟|听|吲|吳|吾|呀|呎|呓|员|呦|呭|呹|呾|咉|咏|咦|咬|咽|咿|哊|哑|哕|哟|員|哩|哽|哾|唀|唁|唈|唌|唖|唡|唫|唷|唹|啘|啞|啢|啨|啱|喁|喅|喐|喑|喓|喗|喛|喝|喦|喩|喭|喲|営|喻|嗂|嗈|嗌|嘢|嘤|噊|噎|噖|噞|噟|噢|噦|噫|噮|噰|噳|噾|嚈|嚘|嚙|嚚|嚛|嚥|嚴|嚶|囈|囐|囙|囝|因|囦|囩|园|囿|圁|圄|圆|圉|圎|園|圓|圔|圛|圜|圠|圧|圩|圪|圫|圯|圻|坄|均|块|坨|坱|坳|垔|垚|垟|垠|垣|垦|垭|垸|垼|垽|埇|埏|埜|域|埡|埯|埶|埸|堉|堊|堐|堙|堣|堨|堬|堯|堰|堷|塋|塎|塩|塬|墅|墉|墕|墷|墿|壄|壅|壓|壛|壧|壱|壹|夁|夃|夕|夗|夜|夤|夭|央|失|夵|夷|夽|奄|奇|奕|奥|奫|妁|妋|妍|妖|妘|妜|妟|妤|妧|妪|妴|妷|姎|姚|姨|姬|姲|姶|姷|姸|姻|娅|娛|娪|娫|娮|娯|娱|婣|婬|婭|婴|婸|婹|媀|媐|媕|媖|媛|媪|媮|媱|媴|媵|嫄|嫈|嫕|嫗|嫚|嫛|嫞|嫣|嬄|嬈|嬊|嬐|嬑|嬟|嬩|嬮|嬰|嬳|嬴|嬽|嬿|孆|孍|孕|孧|孲|孴|孾|它|宇|宎|宐|宛|宜|宥|宧|宴|容|寃|寅|寓|寙|寱|寲|射|將|尉|尢|尤|尧|尭|尹|尾|屵|屹|屿|岄|岆|岈|岟|岩|岳|峄|峓|峟|峣|峪|峫|峳|峾|峿|崎|崕|崖|崛|崟|崤|崦|崯|崳|崵|崸|崺|崾|嵃|嵎|嵒|嵓|嵛|嵤|嵱|嶎|嶖|嶢|嶤|嶧|嶪|嶫|嶬|嶮|嶷|嶼|嶽|嶾|巆|巊|巌|巖|巗|巘|巚|巡|已|巳|巸|币|帟|帠|幆|幺|幼|幽|广|庌|应|庘|庡|庮|庵|庸|庽|庾|廕|廙|廮|廱|廴|延|异|弇|弈|弋|弌|引|弬|弲|彛|彜|彝|彞|彟|彠|彥|彦|彧|彮|影|彵|役|徉|御|徭|徼|忆|忔|応|忧|忬|怈|怏|怞|怠|怡|怣|怨|怮|怺|怿|恌|恙|恞|恱|恹|恽|恿|悀|悁|悅|悆|悇|悒|悘|悠|悥|悦|惌|惐|惥|惲|愈|愉|意|愑|愓|愔|愚|愝|愠|愥|愪|愮|愹|愿|慂|慃|慇|慍|慭|慵|慾|憂|憖|憗|憶|應|懊|懌|懕|懙|懚|懨|懩|懮|懿|戉|或|戫|戭|戲|戺|扅|扆|扊|扚|扜|扡|扬|扰|扵|抁|抈|抎|抑|抣|抭|抰|抴|押|拁|拗|拥|拸|拽|挜|挧|挹|挻|捐|捓|捙|捝|捥|捳|掎|掖|掗|掜|掞|掩|掾|揂|揄|揅|揖|揘|揚|揜|揞|揠|揲|援|揶|揺|搋|搖|搤|摇|摬|摿|撄|撎|撽|擁|擇|擖|擛|擨|擪|擫|擽|攁|攍|攖|攸|攺|敔|敡|敥|敭|敼|斁|斔|斜|斞|斦|於|施|斿|旑|旕|旖|旟|旲|旸|昀|昂|易|昖|昙|昜|映|昱|昳|晏|晔|晕|景|晹|晻|暆|暈|暍|暎|暘|暚|暥|曀|曄|曅|曎|曕|曗|曜|曣|曮|曰|曱|曳|曵|朄|月|有|朓|朠|札|杅|杙|杝|杨|杬|杳|枂|枍|枒|枖|枟|枻|枼|枽|柂|柍|柚|柡|柼|栎|栐|栘|栧|栩|栯|栶|样|栺|桋|桙|桜|桠|桯|梀|梄|梎|梧|梬|棛|棜|棩|棪|棫|棭|椅|椏|椬|椰|椸|椻|椼|楀|楆|楊|楌|楡|楢|楥|楧|楪|業|楰|楹|榅|榆|榏|榚|榞|榣|榬|様|槦|槱|槷|槸|樂|樣|樮|樱|樴|樾|橒|橪|橼|檃|檍|檐|檥|檭|檹|檼|檿|櫌|櫞|櫟|櫩|櫲|櫻|櫽|櫾|櫿|欎|欕|欝|欤|欥|欭|欲|欹|欽|歅|歇|歈|歋|歍|歖|歝|歟|歶|殀|殃|殒|殔|殕|殗|殞|殥|殪|殷|殹|殽|毅|毉|毓|毹|氀|氜|氤|氧|氩|氬|氱|氲|氳|永|汋|汓|汙|汧|汩|汼|汽|沂|沄|沅|沇|沋|沶|油|沿|泂|泄|泅|泆|泑|泱|泳|泿|洂|洇|洋|洕|洝|洢|洩|洫|洮|浂|浟|浥|浧|浳|浴|涂|涌|涎|涒|涓|涢|涯|液|涴|淊|淡|淢|淤|淫|淯|淵|淹|淾|渁|渆|渊|渏|渔|渕|渝|温|渫|渰|渶|渷|游|湙|湚|湛|湡|湧|湮|湯|湲|湵|溁|溋|溎|源|溒|溔|溢|溳|溵|滎|滛|滟|滢|滧|滪|滺|滽|漁|漄|演|漜|漪|漹|漾|潁|潆|潏|潒|潝|潩|潭|潯|潱|澐|澚|澞|澤|澦|澭|澲|澳|澺|濙|濚|濥|濦|濴|瀀|瀁|瀅|瀛|瀠|瀯|瀴|瀷|瀹|灁|灉|灎|灐|灔|灜|灧|灩|灪|灹|炀|炈|炎|炏|炴|烄|烊|烎|烏|烑|烟|烨|烻|焆|焉|焑|焔|焬|焰|焱|焲|焴|焸|煇|煐|煙|煜|煠|煨|煬|煴|煾|熀|熅|熉|熎|熒|熖|熙|熠|熤|熨|熪|熼|燁|燄|燏|燕|燚|營|燠|燡|燱|燿|爍|爓|爗|爚|爩|爰|爷|爺|爻|牅|牏|牖|牗|牙|牪|牰|犄|犹|犽|犾|狁|狋|狏|狕|狖|狠|狱|狳|狺|狿|猌|猒|猗|猚|猨|猰|猶|猷|猺|猿|獂|獄|獈|獝|獟|獶|玅|玉|王|玗|玙|玚|玡|玥|玧|玪|玴|珆|珚|珜|珢|珧|珱|琂|琊|琙|琟|琰|瑀|瑒|瑗|瑘|瑛|瑜|瑤|瑩|瑶|瑿|璌|璍|璎|璵|瓔|瓛|瓵|甇|甖|甗|用|甬|由|甴|甸|畇|畩|畬|畭|異|畹|疋|疑|疙|疟|疡|疣|疨|疫|痈|痍|痏|痒|痖|痬|痷|瘀|瘂|瘉|瘍|瘐|瘖|瘗|瘞|瘟|瘧|瘱|瘾|瘿|癊|癌|癒|癔|癕|癢|癭|癮|癰|皣|盁|盂|盈|益|盐|盓|盶|盾|眃|眏|眑|眙|眢|眻|眼|睚|睪|睮|瞖|瞱|瞸|矅|矆|矞|矣|矨|矱|砑|研|砚|砡|砽|硍|硏|硛|硢|硧|硪|硬|硯|硲|硽|碒|碞|碣|碤|磍|磒|磘|磤|礇|礏|礒|礖|礙|礜|礢|礯|礹|礿|祅|祎|祐|祤|禉|禋|禐|禓|禕|禜|禦|禴|禹|禺|秇|秐|秗|秞|秧|秵|移|稏|稢|稦|稶|穎|穓|穥|穵|穻|穾|穿|窅|窈|窑|窔|窨|窫|窬|窯|窰|窳|竩|竽|笌|笎|笖|筃|筄|筍|筠|筩|筵|筼|箊|箢|箷|箹|篔|篗|篶|篽|簃|簷|籅|籆|籎|籝|籞|籥|籯|籰|籲|粌|粤|粥|粵|糿|約|紆|紜|紲|紻|絏|絪|綖|維|綺|緎|緓|緣|緤|緰|緷|緸|緼|縁|縈|縊|縕|縜|縯|繄|繇|繘|繧|繩|繶|繹|纅|纋|纓|纡|约|纭|绎|绬|缊|缘|缢|缨|罂|罃|罌|罨|罭|羊|羏|羐|羑|羕|羗|羛|羠|羡|義|羪|羬|羭|羱|羽|羿|翊|翌|翳|翼|耀|耘|耛|耰|耴|耶|耺|聈|聐|聱|聶|聿|肀|肄|肊|肙|肬|育|肴|胤|胦|胭|胰|脜|脩|腋|腌|腧|腪|腰|腴|膁|膉|膡|膺|臃|臆|臒|臙|臾|舀|舁|舆|與|舒|舣|艅|艈|艗|艞|艤|艳|艶|艷|艺|艾|芅|芋|芌|芩|芫|芸|芽|苂|苃|苅|苑|苚|苡|苢|苭|英|茒|茔|茚|茟|茰|茵|荑|荥|荧|荫|药|荶|荺|荼|莖|莚|莜|莠|莤|莸|莹|莺|菀|菴|菸|萒|萓|萟|萤|营|萦|萭|萮|萸|萾|葉|葕|葯|葽|葾|蒀|蒏|蒑|蒕|蒝|蒬|蒮|蒷|蓔|蓣|蓥|蓹|蓺|蔅|蔚|蔩|蔫|蔭|蕍|蕓|蕕|蕘|蕥|蕰|蕴|蕷|蕹|薀|薁|薏|薗|薟|薬|薳|藀|藇|藙|藝|藥|藴|蘊|蘌|蘙|蘛|蘟|蘡|蘥|蘨|虉|虞|虤|虵|虶|蚁|蚎|蚏|蚓|蚖|蚘|蚜|蚰|蚴|蛇|蛍|蛘|蛜|蛡|蛦|蛹|蛾|蜍|蜎|蜏|蜒|蜕|蜟|蜮|蜴|蜵|蝆|蝇|蝓|蝘|蝝|蝣|蝤|蝧|蝯|蝹|蝺|蝿|螈|螔|螘|螠|螢|螸|螾|蟈|蟫|蟻|蠅|蠖|蠮|蠱|蠳|衍|衏|衘|衙|衣|衤|衧|衪|衵|袁|袂|袎|袘|袣|袬|裀|裔|裕|裛|裫|裷|裺|裿|褎|褑|褕|褗|褘|褞|褤|褮|褹|襗|襼|襾|要|覃|覎|覞|覦|覮|觃|觎|觺|觾|言|訁|訑|訔|訚|訝|訞|訡|訢|訧|訮|訲|訳|詇|詍|詏|詑|詒|詠|詣|詳|詽|誃|誉|誒|誘|語|説|誼|誾|諛|諭|諲|諹|諺|謁|謍|謚|謜|謠|謡|謣|謻|譍|譩|譯|議|譺|譻|譽|讉|讌|讑|讔|讛|讞|讠|议|讶|译|诒|诣|语|诱|说|谀|谊|谒|谕|谚|谣|谳|谷|豓|豔|豙|豛|豣|豫|豷|貁|貍|貐|貖|貗|貟|貤|貽|賏|賱|賹|贀|贇|贋|贏|贗|贠|贻|赝|赟|赢|赺|越|趛|趯|趼|跀|跃|跇|跠|踊|踦|踰|踴|躍|躒|躽|軅|軈|軉|軋|軏|軮|軺|軼|輅|輍|輏|輐|輑|輗|輢|輰|輵|輶|輼|輿|轅|轙|轝|轧|轶|轺|辕|辥|辷|込|迂|迃|迆|迎|运|迓|远|迤|迭|迱|迶|迻|逌|逘|這|逞|逰|逳|逸|逺|逾|遃|遇|遊|運|遗|遙|遠|遥|遹|遺|邀|邍|邎|邑|邕|邘|邧|邪|邮|邺|郁|郓|郔|郚|郢|郧|郵|郺|郼|郾|鄅|鄆|鄓|鄖|鄘|鄞|鄢|鄴|鄾|酀|酉|酏|酑|酓|酛|酝|酭|酳|酽|醃|醖|醞|醟|醧|醫|醳|醶|醷|醼|釅|釉|釋|野|釔|釪|釴|釶|釾|釿|鈅|鈏|鈗|鈘|鈝|鈠|鈨|鈺|鈾|鉇|鉈|鉛|鉞|鉠|鉯|銀|銉|銕|銚|銥|銦|銪|銹|銿|鋆|鋊|鋋|鋙|鋣|鋭|鋺|錏|錟|錡|錥|鍈|鍚|鍝|鍱|鎁|鎐|鎑|鎣|鎰|鎱|鏔|鏞|鐊|鐍|鐚|鐛|鐭|鐷|鐿|鑍|鑠|鑰|钀|钇|钖|钥|钰|钺|铀|铅|铔|铕|铘|铟|铫|铱|银|铻|锳|镒|镛|镱|閆|閘|閱|閲|閹|閻|閼|閾|闄|闇|闉|闫|阅|阈|阉|阎|阏|阣|阤|阥|阦|阭|阮|阳|阴|阽|陁|陓|院|陨|陭|陰|陶|陻|陽|隁|隂|隃|隅|隐|隒|隕|隠|隩|險|隱|隶|隿|雁|雅|雉|雍|雓|雝|雨|雩|雲|雵|霅|霒|霙|霠|霣|霪|霬|霱|霷|靉|靥|靨|靷|靾|靿|鞅|鞇|鞕|韗|韞|韫|音|韵|韹|韺|韻|韾|頁|頉|預|頤|頥|頨|頴|頵|顊|顏|顑|顒|顔|顗|願|顤|顩|页|预|颍|颐|颕|颖|颙|颜|颺|颻|飏|飖|食|飫|飬|飮|飲|飴|餆|養|餍|餘|餚|餣|餫|饁|饇|饐|饔|饜|饫|饮|饴|馀|馌|馧|馭|馻|駀|駅|駌|駚|駰|騐|験|騕|騟|騴|騵|驁|驈|驗|驛|驜|驠|驭|驿|骃|验|骬|骮|髃|髺|鬰|鬱|鬳|鬻|魇|魊|魘|魚|魣|魭|魷|鮋|鮣|鮧|鮨|鮽|鯈|鯒|鯣|鯲|鰅|鰋|鰑|鰩|鰫|鱅|鱊|鱦|鱮|鱼|鱿|鲉|鲬|鳐|鳙|鳦|鳫|鳱|鳶|鳿|鴁|鴈|鴉|鴛|鴢|鴥|鴦|鴧|鴨|鴪|鴬|鴳|鴹|鴺|鵒|鵪|鵶|鵷|鵺|鶂|鶃|鶍|鶑|鶠|鶢|鶧|鶯|鶰|鷁|鷂|鷃|鷊|鷕|鷖|鷛|鷠|鷣|鷧|鷪|鷰|鷸|鷹|鷾|鸃|鸆|鸈|鸉|鸎|鸑|鸒|鸙|鸚|鸢|鸦|鸭|鸯|鸳|鹆|鹓|鹝|鹞|鹢|鹥|鹦|鹬|鹰|鹽|麀|麌|麙|麣|麲|黓|黝|黟|黡|黤|黦|黫|黬|黭|黰|黳|黶|黿|鼋|鼘|鼝|鼬|鼴|鼹|鼼|齖|齗|齞|齦|齩|齫|齬|齮|齳|齴|齵|齸|齾|龂|龈|龉|龑|龠|龥"; +inline std::wstring pinyin_range = L"〇-龥"; + +inline std::wstring pinyin_regex_gb2312 = L"一与业严丫丿么义乐乙也予于亏云亚亦亿仡以仪仰伊众优伛伢但佑佗余佚佣佯佻佾侑依侥俑俞俣俨俺倚偃允元兖养冤冶刈刖剡劓勇匀医卣印厂压厌原厣又友台右叶叹吁吆吖吟听吲吾呀呓员呦咏咦咬咽咿哑哕哟哩哽唁唷喁喑喝喻嗌嘤噎噢噫囝因园囿圄圆圉圜圩圪圯圻均块坨坳垠垣垦垭垸埏域埯埸堙堰塬墅墉壅壹夕夜夤夭央失夷奄奇奕奥妁妍妖妤妪姚姨姬姻娅娱婴媛媪媵嫣嬴孕它宇宛宜宥宴容寅寓射尉尢尤尧尹尾屹屿岈岩岳峄峪崎崖崛崤崦崾嵛嶷巡已巳币幺幼幽广应庵庸庾廴延异弈弋引彝彦影役徉御徭徼忆忧怏怠怡怨怿恙恹恽恿悒悠悦愈愉意愚愠愿慵懊懿或扬扰抑押拗拥拽挹捐掎掖掩掾揄揖揞揠揲援揶搋摇撄攸斜於施旖昀昂易昙映昱晏晔晕景曜曰曳月有札杨杳柚栎栩样桠梧椅椰楹榆樱樾橼檐欤欲欹歇殃殒殪殷毅毓毹氤氧氩氲永汩汽沂沅油沿泄泅泱泳洇洋洫洮浴涂涌涎涓涯液淡淤淫淹渊渔渝温渫游湛湮源溢滟滢演漪漾潆潭澳瀛瀹炀炎烊烟烨焉焰焱煜煨熙熠熨燕燠爰爷爻牖牙犄犹狁狠狱狳狺猗猷猿玉王珧琊琰瑗瑛瑜瑶璎用甬由甸畹疋疑疙疟疡疣疫痈痍痒痖瘀瘐瘗瘟瘾瘿癌癔盂盈益盐盾眙眢眼睚矣砑研砚硪硬碣禹禺秧移穿窈窑窨窬窳竽筠筵箢粤粥繇纡约纭绎缘缢缨罂罨羊羡羽羿翊翌翳翼耀耘耶聱聿肀肄育肴胤胭胰腋腌腧腰腴膺臃臆臾舀舁舆舒舣艳艺艾芋芩芫芸芽苑苡英茔茚茵荑荥荧荫药荼莜莠莸莹莺菀菸萤营萦萸蓣蓥蔚蔫蕴蕹薏虞蚁蚓蚜蚰蚴蛇蛘蛹蛾蜍蜒蜕蜮蜴蝇蝓蝣蝤螈蠖衍衙衣衤袁袂裔裕要覃觎言誉讠议讶译诒诣语诱说谀谊谒谕谚谣谳谷豫贻赝赢越趼跃踊轧轶轺辕迂迎运迓远迤迭逞逸逾遇遗遥邀邑邕邪邮邺郁郓郢郧郾鄞鄢酉酏酝酽釉野钇钥钰钺铀铅铕铘铟铫铱银镒镛镱闫阅阈阉阎阏阮阳阴阽院陨陶隅隐隶雁雅雉雍雨雩霪靥鞅韫音韵页预颍颐颖颜食餍饔饫饮饴馀驭驿验鬻魇鱼鱿鳐鳙鸢鸦鸭鸯鸳鹆鹞鹦鹬鹰黝黟鼋鼬鼹龈龉龠"; +inline std::wstring pinyin_range_gb2312 = L"[一-龠]"; + +#include "dynamic_charset.h.user" // private data +//#define DYNAMIC_CHARSET_Y L"源页议游育娱乐汽语言元一么于音友有影" +//#define DYNAMIC_CHARSET_YY_1 L"娱语" +//#define DYNAMIC_CHARSET_YY_2 L"乐言" \ No newline at end of file diff --git a/Test/test.cpp b/Test/test.cpp new file mode 100644 index 0000000..89a700a --- /dev/null +++ b/Test/test.cpp @@ -0,0 +1,2 @@ +#define BOOST_TEST_MODULE Test +#include \ No newline at end of file diff --git a/Test/v1.4.cpp b/Test/v1.4.cpp new file mode 100644 index 0000000..84875f4 --- /dev/null +++ b/Test/v1.4.cpp @@ -0,0 +1,253 @@ +#include "common.hpp" + +BOOST_AUTO_TEST_SUITE(v1_4) + +BOOST_FIXTURE_TEST_SUITE(SingleCharQueryPerformance, Everythings::Everything) + void test_query(Everythings::Everything& ev, std::wstring_view query) { + using namespace Everythings; + + DWORD t = timeGetTime(); + ev.query_send(query, 0, Request::FileName); + QueryResults results = ev.query_get(); + t = timeGetTime() - t; + + BOOST_CHECK(results.found_num); + BOOST_TEST_MESSAGE(t << "ms"); + Sleep(2000); + } + + BOOST_AUTO_TEST_SUITE(Char) + + BOOST_AUTO_TEST_CASE(Char) { + test_query(*this, L"y"); + } + + BOOST_AUTO_TEST_CASE(Regex) { + test_query(*this, L"regex:y"); + } + + BOOST_AUTO_TEST_CASE(RegexSet) { + test_query(*this, L"regex:[y]"); + } + + BOOST_AUTO_TEST_SUITE_END() + + + BOOST_AUTO_TEST_SUITE(Pinyin) + + BOOST_AUTO_TEST_CASE(Base_v03) { + test_query(*this, L"regex:[y" DYNAMIC_CHARSET_Y L"]"); + } + + // very fast + BOOST_AUTO_TEST_CASE(LetterBranch) { + test_query(*this, L"regex:y|[" DYNAMIC_CHARSET_Y L"]"); + } + + BOOST_AUTO_TEST_CASE(LetterBranchCase) { + test_query(*this, L"case:regex:y|Y|[" DYNAMIC_CHARSET_Y L"]"); + } + + BOOST_AUTO_TEST_CASE(Base_v02) { + test_query(*this, L"case:regex:[yY" DYNAMIC_CHARSET_Y L"]"); + } + + // better + BOOST_AUTO_TEST_CASE(Dynamic) { + test_query(*this, L"regex:[y" DYNAMIC_CHARSET_Y L"]"); + } + + // better + BOOST_AUTO_TEST_CASE(Gb2312) { + test_query(*this, L"regex:[y" + pinyin_regex_gb2312 + L"]"); + } + + // faster but not the same + BOOST_AUTO_TEST_CASE(Count) { + // place count before regex! + test_query(*this, L"count:100 regex:[y" + pinyin_regex + L"]"); + } + + // faster but not the same + BOOST_AUTO_TEST_CASE(Boundary) { + test_query(*this, L"regex:\\b[y" + pinyin_regex + L"]"); + } + + // better + BOOST_AUTO_TEST_CASE(Case) { + test_query(*this, L"case:regex:[yY" + pinyin_regex + L"]"); + } + + BOOST_AUTO_TEST_CASE(Base_v01) { + test_query(*this, L"regex:[y" + pinyin_regex + L"]"); + } + + /* + // cpu killer + BOOST_AUTO_TEST_CASE(Branch) { + test_query(*this, L"regex:y|" + pinyin_branch); + } + */ + + // worse + BOOST_AUTO_TEST_CASE(Lookaround1) { + test_query(*this, L"regex:"); + } + + BOOST_AUTO_TEST_CASE(Lookaround2_1) { + // regex:"(?>y|(?=[一-龠])一)" + test_query(*this, L"regex:\"(?>y|(?=[" + pinyin_range + L"])[" + pinyin_regex + L"])\""); + } + + // worse than 1 + BOOST_AUTO_TEST_CASE(Lookaround2) { + // regex:"(y|(?=[一-龠])一)" + test_query(*this, L"regex:\"(y|(?=[" + pinyin_range + L"])[" + pinyin_regex + L"])\""); + } + + // worse than 2 + BOOST_AUTO_TEST_CASE(Lookaround3) { + // regex:"(y|(?![\x00-\xff])一)" + test_query(*this, L"regex:\"(y|(?![\\x00-\\xff])[" + pinyin_regex + L"])\""); + } + + // worse than 3 + BOOST_AUTO_TEST_CASE(Lookaround4) { + // regex:"(y|(?![一-龠])(?!)|一)" + test_query(*this, L"regex:\"(y|(?![" + pinyin_range + L"])(?!)|[" + pinyin_regex + L"])\""); + } + BOOST_AUTO_TEST_SUITE_END() + +BOOST_AUTO_TEST_SUITE_END() + + +BOOST_FIXTURE_TEST_SUITE(MultiCharsQueryPerformance, Everythings::Everything) + void test_query(Everythings::Everything& ev, std::wstring_view query) { + using namespace Everythings; + + DWORD t = timeGetTime(); + ev.query_send(query, 0, Request::FileName); + QueryResults results = ev.query_get(); + t = timeGetTime() - t; + + BOOST_CHECK(results.found_num); + BOOST_TEST_MESSAGE(t << "ms"); + Sleep(2000); + } + + BOOST_AUTO_TEST_SUITE(Char) + + BOOST_AUTO_TEST_CASE(Branch) { + test_query(*this, L"x|y"); + } + + // faster than set? + BOOST_AUTO_TEST_CASE(RegexBranch) { + test_query(*this, L"regex:x|y"); + } + + BOOST_AUTO_TEST_CASE(RegexSet) { + test_query(*this, L"regex:[xy]"); + } + + BOOST_AUTO_TEST_SUITE_END() + + + BOOST_AUTO_TEST_SUITE(Char100) + + BOOST_AUTO_TEST_CASE(RegexSet) { + test_query(*this, L"regex:[一与业严丫丿么义乐乙也予于亏云亚亦亿仡以仪仰伊众优伛伢但佑佗余佚佣佯佻佾侑依侥俑俞俣俨俺倚偃允元兖养冤冶刈刖剡劓勇匀医卣印厂压厌原厣又友台右叶叹吁吆吖吟听吲吾呀呓员呦咏咦咬咽咿哑哕哟哩哽唁唷喁喑喝喻嗌]"); + } + + // very slow + BOOST_AUTO_TEST_CASE(RegexBranch) { + test_query(*this, L"regex:一|与|业|严|丫|丿|么|义|乐|乙|也|予|于|亏|云|亚|亦|亿|仡|以|仪|仰|伊|众|优|伛|伢|但|佑|佗|余|佚|佣|佯|佻|佾|侑|依|侥|俑|俞|俣|俨|俺|倚|偃|允|元|兖|养|冤|冶|刈|刖|剡|劓|勇|匀|医|卣|印|厂|压|厌|原|厣|又|友|台|右|叶|叹|吁|吆|吖|吟|听|吲|吾|呀|呓|员|呦|咏|咦|咬|咽|咿|哑|哕|哟|哩|哽|唁|唷|喁|喑|喝|喻|嗌"); + } + + // very slow + BOOST_AUTO_TEST_CASE(Branch) { + test_query(*this, L"一|与|业|严|丫|丿|么|义|乐|乙|也|予|于|亏|云|亚|亦|亿|仡|以|仪|仰|伊|众|优|伛|伢|但|佑|佗|余|佚|佣|佯|佻|佾|侑|依|侥|俑|俞|俣|俨|俺|倚|偃|允|元|兖|养|冤|冶|刈|刖|剡|劓|勇|匀|医|卣|印|厂|压|厌|原|厣|又|友|台|右|叶|叹|吁|吆|吖|吟|听|吲|吾|呀|呓|员|呦|咏|咦|咬|咽|咿|哑|哕|哟|哩|哽|唁|唷|喁|喑|喝|喻|嗌"); + } + + BOOST_AUTO_TEST_SUITE_END() + + + BOOST_AUTO_TEST_SUITE(Pinyin) + + BOOST_AUTO_TEST_CASE(Base_v03) { + test_query(*this, L"regex:[y" DYNAMIC_CHARSET_YY_1 L"][y" DYNAMIC_CHARSET_YY_2 L"]"); + } + + // slower than Base_v02 + BOOST_AUTO_TEST_CASE(LetterBranch) { + // regex:"(y|[英])(y|[语])" + test_query(*this, L"regex:\"(y|[" DYNAMIC_CHARSET_YY_1 L"])(y|[" DYNAMIC_CHARSET_YY_2 L"])\""); + } + + BOOST_AUTO_TEST_CASE(LetterBranch_1) { + // regex:"(?:y|[英])(?:y|[语])" + test_query(*this, L"regex:\"(?:y|[" DYNAMIC_CHARSET_YY_1 L"])(?:y|[" DYNAMIC_CHARSET_YY_2 L"])\""); + } + + BOOST_AUTO_TEST_CASE(LetterBranch_2) { + // regex:"(?>y|[英])(?>y|[语])" + test_query(*this, L"regex:\"(?>y|[" DYNAMIC_CHARSET_YY_1 L"])(?>y|[" DYNAMIC_CHARSET_YY_2 L"])\""); + } + + BOOST_AUTO_TEST_CASE(Base_v02) { + test_query(*this, L"case:regex:[yY" DYNAMIC_CHARSET_YY_1 L"][yY" DYNAMIC_CHARSET_YY_2 L"]"); + } + + BOOST_AUTO_TEST_CASE(DynamicPair) { + test_query(*this, L"regex:[y" DYNAMIC_CHARSET_YY_1 L"][y" DYNAMIC_CHARSET_YY_2 L"]"); + } + + BOOST_AUTO_TEST_CASE(Dynamic) { + test_query(*this, L"regex:[y" DYNAMIC_CHARSET_Y L"]{2}"); + } + + BOOST_AUTO_TEST_CASE(Base_v01) { + test_query(*this, L"regex:[y" + pinyin_regex + L"]{2}"); + } + + BOOST_AUTO_TEST_CASE(Quantifier) { + test_query(*this, L"regex:[y" + pinyin_regex + L"]{2}"); + } + + BOOST_AUTO_TEST_CASE(Repeat) { + test_query(*this, L"regex:[y" + pinyin_regex + L"][y" + pinyin_regex + L"]"); + } + + BOOST_AUTO_TEST_SUITE_END() + +BOOST_AUTO_TEST_SUITE_END() + + +BOOST_FIXTURE_TEST_SUITE(DynamicCharset, Everythings::Everything) + void test_query(Everythings::Everything& ev, std::wstring_view query) { + using namespace Everythings; + + DWORD t = timeGetTime(); + ev.query_send(query, Search::MatchCase, Request::FileName); + QueryResults results = ev.query_get(); + t = timeGetTime() - t; + + BOOST_TEST_MESSAGE(results.available_num << ", " << t << "ms"); + Sleep(2000); + } + + BOOST_AUTO_TEST_CASE(GenerateQuery) { + test_query(*this, L"regex:[〇-𰻞]"); + } + + BOOST_AUTO_TEST_CASE(UpdateQuery) { + test_query(*this, L"rc:"); + } + + BOOST_AUTO_TEST_CASE(UpdateQueryRegex) { + test_query(*this, L"rc: regex:[〇-𰻞]"); + } + +BOOST_AUTO_TEST_SUITE_END() + +BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file diff --git a/Test/v1.5a.cpp b/Test/v1.5a.cpp new file mode 100644 index 0000000..8ae8edb --- /dev/null +++ b/Test/v1.5a.cpp @@ -0,0 +1,264 @@ +#include "common.hpp" + +BOOST_AUTO_TEST_SUITE(v1_5a) + +BOOST_FIXTURE_TEST_SUITE(SingleCharQueryPerformance, Everythings::Everything) + void test_query(std::wstring_view query) { + using namespace Everythings; + + Everything ev(L"1.5a"); + DWORD t = timeGetTime(); + ev.query_send(query, 0, Request::FileName); + QueryResults results = ev.query_get(); + t = timeGetTime() - t; + + BOOST_CHECK(results.found_num); + BOOST_TEST_MESSAGE(t << "ms"); + Sleep(2000); + } + + BOOST_AUTO_TEST_SUITE(Char) + + BOOST_AUTO_TEST_CASE(Char) { + test_query(L"y"); + } + + BOOST_AUTO_TEST_CASE(Regex) { + test_query(L"regex:y"); + } + + BOOST_AUTO_TEST_CASE(RegexSet) { + test_query(L"regex:[y]"); + } + + BOOST_AUTO_TEST_SUITE_END() + + + BOOST_AUTO_TEST_SUITE(Pinyin) + + BOOST_AUTO_TEST_CASE(Base_v03) { + test_query(L"regex:[y" DYNAMIC_CHARSET_Y L"]"); + } + + BOOST_AUTO_TEST_CASE(LetterBranch) { + test_query(L"regex:y|[" DYNAMIC_CHARSET_Y L"]"); + } + + BOOST_AUTO_TEST_CASE(LetterBranchCase) { + test_query(L"case:regex:y|Y|[" DYNAMIC_CHARSET_Y L"]"); + } + + BOOST_AUTO_TEST_CASE(Base_v02) { + test_query(L"case:regex:[yY" DYNAMIC_CHARSET_Y L"]"); + } + + // better + BOOST_AUTO_TEST_CASE(Dynamic) { + test_query(L"regex:[y" DYNAMIC_CHARSET_Y L"]"); + } + + // better + BOOST_AUTO_TEST_CASE(Gb2312) { + test_query(L"regex:[y" + pinyin_regex_gb2312 + L"]"); + } + + // faster but not the same + BOOST_AUTO_TEST_CASE(Count) { + // place count before regex! + test_query(L"count:100 regex:[y" + pinyin_regex + L"]"); + } + + // faster but not the same + BOOST_AUTO_TEST_CASE(Boundary) { + test_query(L"regex:\\b[y" + pinyin_regex + L"]"); + } + + // better + BOOST_AUTO_TEST_CASE(Case) { + test_query(L"case:regex:[yY" + pinyin_regex + L"]"); + } + + BOOST_AUTO_TEST_CASE(Base_v01) { + test_query(L"regex:[y" + pinyin_regex + L"]"); + } + + /* + // cpu killer + BOOST_AUTO_TEST_CASE(Branch) { + test_query(L"regex:y|" + pinyin_branch); + } + */ + + // worse + BOOST_AUTO_TEST_CASE(Lookaround1) { + test_query(L"regex:"); + } + + BOOST_AUTO_TEST_CASE(Lookaround2_1) { + // regex:(?>y|(?=[一-龠])一) + test_query(L"regex:(?>y|(?=[" + pinyin_range + L"])[" + pinyin_regex + L"])"); + } + + // worse than 1 + BOOST_AUTO_TEST_CASE(Lookaround2) { + // regex:(y|(?=[一-龠])一) + test_query(L"regex:(y|(?=[" + pinyin_range + L"])[" + pinyin_regex + L"])"); + } + + // worse than 2 + BOOST_AUTO_TEST_CASE(Lookaround3) { + // regex:(y|(?![\x00-\xff])一) + test_query(L"regex:(y|(?![\\x00-\\xff])[" + pinyin_regex + L"])"); + } + + // worse than 3 + BOOST_AUTO_TEST_CASE(Lookaround4) { + // regex:(y|(?![一-龠])(?!)|一) + test_query(L"regex:(y|(?![" + pinyin_range + L"])(?!)|[" + pinyin_regex + L"])"); + } + BOOST_AUTO_TEST_SUITE_END() + +BOOST_AUTO_TEST_SUITE_END() + + +BOOST_AUTO_TEST_SUITE(MultiCharsQueryPerformance) + void test_query(std::wstring_view query) { + using namespace Everythings; + + Everything ev(L"1.5a"); + DWORD t = timeGetTime(); + ev.query_send(query, 0, Request::FileName); + QueryResults results = ev.query_get(); + t = timeGetTime() - t; + + BOOST_CHECK(results.found_num); + BOOST_TEST_MESSAGE(t << "ms"); + Sleep(2000); + } + + BOOST_AUTO_TEST_SUITE(Char) + + BOOST_AUTO_TEST_CASE(Branch) { + test_query(L"x|y"); + } + + BOOST_AUTO_TEST_CASE(WildcardsSet) { + test_query(L"wildcards:*[xy]*"); + } + + // faster than set? + BOOST_AUTO_TEST_CASE(RegexBranch) { + test_query(L"regex:x|y"); + } + + BOOST_AUTO_TEST_CASE(RegexSet) { + test_query(L"regex:[xy]"); + } + + BOOST_AUTO_TEST_SUITE_END() + + + BOOST_AUTO_TEST_SUITE(Char100) + + BOOST_AUTO_TEST_CASE(RegexSet) { + test_query(L"regex:[一与业严丫丿么义乐乙也予于亏云亚亦亿仡以仪仰伊众优伛伢但佑佗余佚佣佯佻佾侑依侥俑俞俣俨俺倚偃允元兖养冤冶刈刖剡劓勇匀医卣印厂压厌原厣又友台右叶叹吁吆吖吟听吲吾呀呓员呦咏咦咬咽咿哑哕哟哩哽唁唷喁喑喝喻嗌]"); + } + + // slow + BOOST_AUTO_TEST_CASE(WildcardsSet) { + test_query(L"wildcards:*[一与业严丫丿么义乐乙也予于亏云亚亦亿仡以仪仰伊众优伛伢但佑佗余佚佣佯佻佾侑依侥俑俞俣俨俺倚偃允元兖养冤冶刈刖剡劓勇匀医卣印厂压厌原厣又友台右叶叹吁吆吖吟听吲吾呀呓员呦咏咦咬咽咿哑哕哟哩哽唁唷喁喑喝喻嗌]*"); + } + + // very slow + BOOST_AUTO_TEST_CASE(RegexBranch) { + test_query(L"regex:一|与|业|严|丫|丿|么|义|乐|乙|也|予|于|亏|云|亚|亦|亿|仡|以|仪|仰|伊|众|优|伛|伢|但|佑|佗|余|佚|佣|佯|佻|佾|侑|依|侥|俑|俞|俣|俨|俺|倚|偃|允|元|兖|养|冤|冶|刈|刖|剡|劓|勇|匀|医|卣|印|厂|压|厌|原|厣|又|友|台|右|叶|叹|吁|吆|吖|吟|听|吲|吾|呀|呓|员|呦|咏|咦|咬|咽|咿|哑|哕|哟|哩|哽|唁|唷|喁|喑|喝|喻|嗌"); + } + + // very slow + BOOST_AUTO_TEST_CASE(Branch) { + test_query(L"一|与|业|严|丫|丿|么|义|乐|乙|也|予|于|亏|云|亚|亦|亿|仡|以|仪|仰|伊|众|优|伛|伢|但|佑|佗|余|佚|佣|佯|佻|佾|侑|依|侥|俑|俞|俣|俨|俺|倚|偃|允|元|兖|养|冤|冶|刈|刖|剡|劓|勇|匀|医|卣|印|厂|压|厌|原|厣|又|友|台|右|叶|叹|吁|吆|吖|吟|听|吲|吾|呀|呓|员|呦|咏|咦|咬|咽|咿|哑|哕|哟|哩|哽|唁|唷|喁|喑|喝|喻|嗌"); + } + + BOOST_AUTO_TEST_SUITE_END() + + + BOOST_AUTO_TEST_SUITE(Pinyin) + + BOOST_AUTO_TEST_CASE(Base_v03) { + test_query(L"regex:[y" DYNAMIC_CHARSET_YY_1 L"][y" DYNAMIC_CHARSET_YY_2 L"]"); + } + + // slower than Base_v02 + BOOST_AUTO_TEST_CASE(LetterBranch) { + // regex:(y|[英])(y|[语]) + test_query(L"regex:(y|[" DYNAMIC_CHARSET_YY_1 L"])(y|[" DYNAMIC_CHARSET_YY_2 L"])"); + } + + BOOST_AUTO_TEST_CASE(LetterBranch_1) { + // regex:(?:y|[英])(?:y|[语]) + test_query(L"regex:(?:y|[" DYNAMIC_CHARSET_YY_1 L"])(?:y|[" DYNAMIC_CHARSET_YY_2 L"])"); + } + + BOOST_AUTO_TEST_CASE(LetterBranch_2) { + // regex:(?>y|[英])(?>y|[语]) + test_query(L"regex:(?>y|[" DYNAMIC_CHARSET_YY_1 L"])(?>y|[" DYNAMIC_CHARSET_YY_2 L"])"); + } + + BOOST_AUTO_TEST_CASE(Base_v02) { + test_query(L"case:regex:[yY" DYNAMIC_CHARSET_YY_1 L"][yY" DYNAMIC_CHARSET_YY_2 L"]"); + } + + BOOST_AUTO_TEST_CASE(DynamicPair) { + test_query(L"regex:[y" DYNAMIC_CHARSET_YY_1 L"][y" DYNAMIC_CHARSET_YY_2 L"]"); + } + + BOOST_AUTO_TEST_CASE(Dynamic) { + test_query(L"regex:[y" DYNAMIC_CHARSET_Y L"]{2}"); + } + + BOOST_AUTO_TEST_CASE(Base_v01) { + test_query(L"regex:[y" + pinyin_regex + L"]{2}"); + } + + BOOST_AUTO_TEST_CASE(Quantifier) { + test_query(L"regex:[y" + pinyin_regex + L"]{2}"); + } + + BOOST_AUTO_TEST_CASE(Repeat) { + test_query(L"regex:[y" + pinyin_regex + L"][y" + pinyin_regex + L"]"); + } + + BOOST_AUTO_TEST_SUITE_END() + +BOOST_AUTO_TEST_SUITE_END() + + +BOOST_FIXTURE_TEST_SUITE(DynamicCharset, Everythings::Everything) + void test_query(std::wstring_view query) { + using namespace Everythings; + + Everything ev(L"1.5a"); + DWORD t = timeGetTime(); + ev.query_send(query, Search::MatchCase, Request::FileName); + QueryResults results = ev.query_get(); + t = timeGetTime() - t; + + BOOST_TEST_MESSAGE(results.available_num << ", " << t << "ms"); + Sleep(2000); + } + + BOOST_AUTO_TEST_CASE(GenerateQuery) { + test_query(L"regex:[〇-𰻞]"); + } + + BOOST_AUTO_TEST_CASE(UpdateQuery) { + test_query(L"rc:"); + } + + BOOST_AUTO_TEST_CASE(UpdateQueryRegex) { + test_query(L"rc: regex:[〇-𰻞]"); + } + +BOOST_AUTO_TEST_SUITE_END() + +BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file diff --git a/docs/FlowLauncher.png b/docs/FlowLauncher.png new file mode 100644 index 0000000..5a1b889 Binary files /dev/null and b/docs/FlowLauncher.png differ diff --git a/docs/HuoChat.png b/docs/HuoChat.png new file mode 100644 index 0000000..903c731 Binary files /dev/null and b/docs/HuoChat.png differ diff --git a/docs/Wox.png b/docs/Wox.png new file mode 100644 index 0000000..6e09bd1 Binary files /dev/null and b/docs/Wox.png differ diff --git a/docs/preview.png b/docs/preview.png index 618d26f..0c59a1e 100644 Binary files a/docs/preview.png and b/docs/preview.png differ diff --git a/docs/search.png b/docs/search.png index 129aeed..d78f710 100644 Binary files a/docs/search.png and b/docs/search.png differ