diff --git a/deploy.ps1 b/deploy.ps1 index 8457ef5..ff115c6 100644 --- a/deploy.ps1 +++ b/deploy.ps1 @@ -15,6 +15,7 @@ foreach ($arch in @("86", "64")) { "Google Translate.dll", "Regex Filter.dll", "Remove Repetition.dll", + "Replacer.dll", "Thread Linker.dll", "platforms", "styles" diff --git a/extensions/CMakeLists.txt b/extensions/CMakeLists.txt index 6f141cb..78cbe4e 100644 --- a/extensions/CMakeLists.txt +++ b/extensions/CMakeLists.txt @@ -11,6 +11,7 @@ add_library(Extra\ Window SHARED extrawindow.cpp extensionimpl.cpp) add_library(Google\ Translate SHARED googletranslate.cpp extensionimpl.cpp) add_library(Regex\ Filter SHARED regexfilter.cpp extensionimpl.cpp) add_library(Remove\ Repetition SHARED removerepeat.cpp extensionimpl.cpp) +add_library(Replacer SHARED replacer.cpp extensionimpl.cpp) add_library(Thread\ Linker SHARED threadlinker.cpp extensionimpl.cpp) add_executable(Extension_Tests extensiontester.cpp) diff --git a/extensions/removerepeat.cpp b/extensions/removerepeat.cpp index 22aa47c..0af7847 100644 --- a/extensions/removerepeat.cpp +++ b/extensions/removerepeat.cpp @@ -66,6 +66,6 @@ TEST( ProcessSentence(empty, { &tester }); ProcessSentence(one, { &tester }); ProcessSentence(normal, { &tester }); - assert(empty == L"" && one == L" " && normal == L"This is a normal sentence. はい"); + assert(empty == L"" && one == L" " && normal == L"This is a normal sentence. はい"); } ); diff --git a/extensions/replacer.cpp b/extensions/replacer.cpp new file mode 100644 index 0000000..493f123 --- /dev/null +++ b/extensions/replacer.cpp @@ -0,0 +1,100 @@ +#include "extension.h" +#include "defs.h" +#include "text.h" +#include +#include + +std::shared_mutex m; + +struct +{ +public: + void Put(std::wstring original, std::wstring replacement) + { + Node* current = &root; + for (auto c : original) + if (Ignore(c)); + else if (auto& next = current->next[c]) current = next.get(); + else current = (next = std::make_unique()).get(); + current->value = replacement; + } + + std::pair Lookup(const std::wstring& text) + { + int length = 0; + Node* current = &root; + for (auto c : text) + if (Ignore(c)) ++length; + else if (auto& next = current->next[c]) ++length, current = next.get(); + else break; + return { length, current->value }; + } + +private: + static bool Ignore(wchar_t c) + { + return c <= 0x20 || std::iswspace(c); + } + + struct Node + { + std::unordered_map> next; + std::wstring value; + } root; +} replacementTrie; + +void Parse(const std::wstring& file) +{ + std::lock_guard l(m); + size_t end = 0; + while (true) + { + size_t original = file.find(L"|ORIG|", end); + size_t becomes = file.find(L"|BECOMES|", original); + end = file.find(L"|END|", becomes); + if (end != std::wstring::npos) replacementTrie.Put(file.substr(original + 6, becomes - original - 6), file.substr(becomes + 9, end - becomes - 9)); + else break; + } +} + +BOOL WINAPI DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + { + std::vector file(std::istreambuf_iterator(std::ifstream(REPLACE_SAVE_FILE, std::ios::binary)), {}); + Parse(std::wstring((wchar_t*)file.data(), file.size() / sizeof(wchar_t))); + } + break; + case DLL_PROCESS_DETACH: + { + } + break; + } + return TRUE; +} + +bool ProcessSentence(std::wstring& sentence, SentenceInfo) +{ + std::shared_lock l(m); + for (int i = 0; i < sentence.size(); ++i) + if (sentence.size() > 10000) return false; // defend against infinite looping + else if (auto[length, replacement] = replacementTrie.Lookup(sentence.substr(i)); !replacement.empty()) sentence.replace(i, length, replacement); + return true; +} + +TEST( + { + Parse(LR"(|ORIG|さよなら|BECOMES|goodbye|END| +|ORIG|バカ|BECOMES|idiot|END| +|ORIG|こんにちは|BECOMES|hello|END|)"); + std::wstring replaced = LR"(hello  + さよなら バカ こんにちは)"; + ProcessSentence(replaced, { nullptr }); + assert(replaced.rfind(L"さよなら") == std::wstring::npos); + assert(replaced.rfind(L"バカ") == std::wstring::npos); + assert(replaced.rfind(L"こんにちは") == std::wstring::npos); + replacementTrie = {}; + } +); diff --git a/include/defs.h b/include/defs.h index 542e81a..00680a6 100644 --- a/include/defs.h +++ b/include/defs.h @@ -25,6 +25,7 @@ constexpr auto CONFIG_FILE = u8"Textractor.ini"; constexpr auto HOOK_SAVE_FILE = u8"SavedHooks.txt"; constexpr auto GAME_SAVE_FILE = u8"SavedGames.txt"; constexpr auto EXTEN_SAVE_FILE = u8"SavedExtensions.txt"; +constexpr auto REPLACE_SAVE_FILE = u8"SavedReplacements.txt"; // Functions diff --git a/release/SavedReplacements.txt b/release/SavedReplacements.txt new file mode 100644 index 0000000..f53e807 Binary files /dev/null and b/release/SavedReplacements.txt differ