From d1db1ce2e00341bc24f2cc9b0842d40391117ec6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D0=BC=D0=B8=D1=80=20=D0=A7?= =?UTF-8?q?=D0=B8=D0=B6?= Date: Sun, 15 Sep 2024 14:55:46 +0200 Subject: [PATCH 01/16] speed up --- CMakeLists.txt | 51 ++- srcbpatch/streamreplacer.cpp | 851 ++++++++++++++++------------------- 2 files changed, 426 insertions(+), 476 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 00540d1..2722500 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,9 +11,9 @@ set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo;MinSizeRel" CACHE STRING "Configs" FORCE) # Set the build type to Debug if not explicitly specified -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Debug) -endif() +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug) +endif () message(STATUS "Initial COMPILER_FLAGS:" ${CMAKE_CXX_FLAGS}) @@ -27,7 +27,7 @@ message(STATUS "CMAKE_CXX_FLAGS:" ${CMAKE_CXX_FLAGS}) message(STATUS "CMAKE_CXX_COMPILER_ID:" ${CMAKE_CXX_COMPILER_ID}) set(CMAKE_EXE_LINKER_FLAGS "") -if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") +if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") # GCC (GNU Compiler) if (CMAKE_BUILD_TYPE STREQUAL "Debug") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DDEBUG -D_DEBUG -g -D_CONSOLE -Wno-unknown-pragmas -Wall -Werror -fno-rtti -pthread") @@ -40,8 +40,8 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") set(CMAKE_EXE_LINKER_FLAGS "-g -O2 -flto") else() message(FATAL_ERROR "Unsupported compilation mode") - endif() -elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang.*") #Clang or AppleClang or anything with Clang + endif () +elseif (CMAKE_CXX_COMPILER_ID MATCHES ".*Clang.*") #Clang or AppleClang or anything with Clang # clang (MAC Compiler) if (CMAKE_BUILD_TYPE STREQUAL "Debug") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DDEBUG -D_DEBUG -g -D_CONSOLE -Wno-unknown-pragmas -Wall -Werror -Wno-unqualified-std-cast-call -fno-rtti -pthread -stdlib=libc++") @@ -54,8 +54,8 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang.*") #Clang or AppleClang or anyth set(CMAKE_EXE_LINKER_FLAGS "-g -O2 -flto") else() message(FATAL_ERROR "Unsupported compilation mode") - endif() -elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + endif () +elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") # MSVC (Microsoft Visual C++) if (CMAKE_BUILD_TYPE STREQUAL "Debug") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /DWIN32 /D_WINDOWS /D_CONSOLE /DDEBUG /D_DEBUG /Zi /EHsc /W4 /WX /GR- /MDd") @@ -68,10 +68,10 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") set(CMAKE_EXE_LINKER_FLAGS "/DEBUG:FULL /OPT:REF /OPT:ICF /INCREMENTAL:NO") else() message(FATAL_ERROR "Unsupported compilation mode") - endif() -else() + endif () +else () message(FATAL_ERROR "Unsupported compiler") -endif() +endif () message(STATUS "CMAKE_CXX_FLAGS:" ${CMAKE_CXX_FLAGS}) @@ -84,17 +84,27 @@ FetchContent_GetProperties(googletest) #googletest_POPULATED #googletest_SOURCE_DIR #googletest_BUILD_DIR -if(NOT googletest_POPULATED) +if (NOT googletest_POPULATED) FetchContent_Populate(googletest) add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BUILD_DIR}) -endif() +endif () + +include(FetchContent) + +FetchContent_Declare( + robin_map + GIT_REPOSITORY https://github.com/Tessil/robin-map.git + GIT_TAG master +) + +FetchContent_MakeAvailable(robin_map) include_directories(${wild_library}) include_directories(src${pname}) # Source files set(SOURCE_FILES - bpatch.cpp + bpatch.cpp ) #set(HEADER_FILES #) @@ -103,14 +113,14 @@ set(SOURCE_FILES add_executable(${pname} ${SOURCE_FILES}) # Set the name of the executable based on the platform -if(WIN32) +if (WIN32) set_target_properties(${pname} PROPERTIES OUTPUT_NAME "${pname}") -else() +else () set_target_properties(${pname} PROPERTIES OUTPUT_NAME "${pname}") -endif() +endif () # Configuration-specific settings -if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") +if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") # For GCC and Clang, use the -m64 flag to target 64-bit set_target_properties(${pname} PROPERTIES COMPILE_OPTIONS "$<$:-O3>" @@ -126,16 +136,17 @@ set_target_properties(${pname} PROPERTIES ) -else() +else () message(FATAL_ERROR "Unsupported compiler") -endif() +endif () add_subdirectory(${wild_library}) add_subdirectory(src${pname}) add_subdirectory(test${pname}) target_link_libraries(${pname} src${pname} ${wild_library}) +target_include_directories(${pname} PUBLIC ${robin_map_SOURCE_DIR}/include) # Console commands for building on Windows with Visual Studio # !!!!!!!!!!!!! diff --git a/srcbpatch/streamreplacer.cpp b/srcbpatch/streamreplacer.cpp index bb2ba01..47a9c59 100644 --- a/srcbpatch/streamreplacer.cpp +++ b/srcbpatch/streamreplacer.cpp @@ -3,546 +3,485 @@ #include "fileprocessing.h" #include "streamreplacer.h" -namespace bpatch -{ -using namespace std; - -//-------------------------------------------------- -/// -/// Replacer to last in chain. All incoming data should be trasferred to a Writer interface -/// -class WriterReplacer final : public StreamReplacer -{ -public: - WriterReplacer(Writer* const pWriter): pWriter_(pWriter) {}; - - virtual void DoReplacements(const char toProcess, const bool aEod) const override; - virtual void SetNextReplacer(std::unique_ptr&& pNext) override; -protected: - Writer* const pWriter_; -}; - - -void WriterReplacer::DoReplacements(const char toProcess, const bool aEod) const -{ - pWriter_->WriteCharacter(toProcess, aEod); -} - - -void WriterReplacer::SetNextReplacer(std::unique_ptr&&) -{ - throw logic_error("Writer Replacer should be unchangeable. Contact with maintainer."); -} - - -unique_ptr StreamReplacer::ReplacerLastInChain(Writer* const pWriter) -{ - return unique_ptr(new WriterReplacer(pWriter)); -} - -//-------------------------------------------------- - -/// -/// common part for set next replacer -/// -class ReplacerWithNext: public StreamReplacer -{ -protected: - /// to pass processing further - std::unique_ptr pNext_; - -public: - void SetNextReplacer(std::unique_ptr&& pNext) override - { - std::swap(pNext_, pNext); - } +#include -}; +namespace bpatch { + using namespace std; + //-------------------------------------------------- + /// + /// Replacer to last in chain. All incoming data should be trasferred to a Writer interface + /// + class WriterReplacer final : public StreamReplacer { + public: + WriterReplacer(Writer *const pWriter): pWriter_(pWriter) { + }; -//-------------------------------------------------- -struct ReplacerPairHolder -{ - ReplacerPairHolder(unique_ptr& src, // what to replace - unique_ptr& trg) // to what - : src_(src) - , trg_(trg) - {} + virtual void DoReplacements(const char toProcess, const bool aEod) const override; - unique_ptr& src_; // what to replace - unique_ptr& trg_; // with what -}; + virtual void SetNextReplacer(std::unique_ptr &&pNext) override; + protected: + Writer *const pWriter_; + }; -//-------------------------------------------------- -class UsualReplacer final : public ReplacerWithNext -{ -public: - UsualReplacer(unique_ptr& src, // what to replace - unique_ptr& trg) // with what - : src_(src->access()) - , trg_(trg->access()) - { - cachedData_.resize(src_.size()); + + void WriterReplacer::DoReplacements(const char toProcess, const bool aEod) const { + pWriter_->WriteCharacter(toProcess, aEod); } - void DoReplacements(const char toProcess, const bool aEod) const override; -protected: - const span& src_; // what to replace - const span& trg_; // with what + void WriterReplacer::SetNextReplacer(std::unique_ptr &&) { + throw logic_error("Writer Replacer should be unchangeable. Contact with maintainer."); + } - mutable size_t cachedAmount_ = 0; // we cached this amount of data - // this is used to hold temporary data while the logic is - // looking for the new beginning of the cached value - mutable vector cachedData_; -}; + unique_ptr StreamReplacer::ReplacerLastInChain(Writer *const pWriter) { + return unique_ptr(new WriterReplacer(pWriter)); + } + //-------------------------------------------------- -void UsualReplacer::DoReplacements(const char toProcess, const bool aEod) const -{ - if (nullptr == pNext_) - { - throw logic_error("Replacement chain has been broken. Communicate with maintainer"); - } + /// + /// common part for set next replacer + /// + class ReplacerWithNext : public StreamReplacer { + protected: + /// to pass processing further + std::unique_ptr pNext_; + + public: + void SetNextReplacer(std::unique_ptr &&pNext) override { + std::swap(pNext_, pNext); + } + }; - // no more data - // just send cached amount - if (aEod) - { - for (size_t i = 0; i < cachedAmount_; ++i) - { - pNext_->DoReplacements(src_[i], false); + + //-------------------------------------------------- + struct ReplacerPairHolder { + ReplacerPairHolder(unique_ptr &src, // what to replace + unique_ptr &trg) // to what + : src_(src) + , trg_(trg) { } - cachedAmount_ = 0; - pNext_->DoReplacements(toProcess, true); - return; - } - if (src_[cachedAmount_] == toProcess) // check for match - { - if (++cachedAmount_ >= src_.size()) - {// send target - do replacement - for (size_t q = 0; q < trg_.size(); ++q) { pNext_->DoReplacements(trg_[q], false); } - cachedAmount_ = 0; + unique_ptr &src_; // what to replace + unique_ptr &trg_; // with what + }; + + + //-------------------------------------------------- + class UsualReplacer final : public ReplacerWithNext { + public: + UsualReplacer(unique_ptr &src, // what to replace + unique_ptr &trg) // with what + : src_(src->access()) + , trg_(trg->access()) { + cachedData_.resize(src_.size()); } - return; - } - // here: toProcess is not our char - // lets check for fast track (255/256 probability) - if (0 == cachedAmount_) - { - pNext_->DoReplacements(toProcess, false); - return; - } + void DoReplacements(const char toProcess, const bool aEod) const override; - // here: We have some cached data - // at least 1 char need to be send further - // remaining cached data including toProcess need to be reprocessed for match + protected: + const span &src_; // what to replace + const span &trg_; // with what - memcpy(cachedData_.data(), src_.data(), cachedAmount_); - cachedData_[cachedAmount_++]= toProcess; - size_t i = 0; - do - { - pNext_->DoReplacements(cachedData_[i++], false); // send 1 byte after another - } while (0 != memcmp(src_.data(), cachedData_.data() + i, --cachedAmount_)); - // Everything that was needed has already been sent - // cachedAmount_ is zero or greater -} - - -/// -/// creates replacer -/// -/// what we are going to replace -/// this is the result of the replacement -/// Replacer for building replacement chain -static unique_ptr CreateSimpleReplacer( - unique_ptr& src, // what to replace - unique_ptr& trg) // with what -{ - return unique_ptr(new UsualReplacer(src, trg)); -} - - -//-------------------------------------------------- -/// -/// |--SRC 1 TRG 1 | -/// O - |-- ... | - o -/// |--SRC N TRG N | -/// -class ChoiceReplacer final : public ReplacerWithNext -{ - typedef struct - { - span src_; - span trg_; - }ChoiceReplacerPair; + mutable size_t cachedAmount_ = 0; // we cached this amount of data -public: - /// - /// creating ChoiceReplacer from provided pairs - /// - /// vector os source & target pairs - ChoiceReplacer(StreamReplacerChoice& choice) - { - size_t bufferSize = 0; // to allocate buffer - const size_t sz = choice.size(); - rpairs_.resize(sz); - for (size_t i = 0; i < sz; ++i) + // this is used to hold temporary data while the logic is + // looking for the new beginning of the cached value + mutable vector cachedData_; + }; + + + void UsualReplacer::DoReplacements(const char toProcess, const bool aEod) const { + if (nullptr == pNext_) { + throw logic_error("Replacement chain has been broken. Communicate with maintainer"); + } + + // no more data + // just send cached amount + if (aEod) { + for (size_t i = 0; i < cachedAmount_; ++i) { + pNext_->DoReplacements(src_[i], false); + } + cachedAmount_ = 0; + pNext_->DoReplacements(toProcess, true); + return; + } + + if (src_[cachedAmount_] == toProcess) // check for match { - auto& vPair = choice[i]; // copy from - auto& rpair = rpairs_[i];// copy to - - rpair.src_ = vPair.first->access(); - const size_t sourceSize = rpair.src_.size(); - if (bufferSize < sourceSize) - { - bufferSize = sourceSize; // calculate necessary buffer size + if (++cachedAmount_ >= src_.size()) { + // send target - do replacement + for (size_t q = 0; q < trg_.size(); ++q) { pNext_->DoReplacements(trg_[q], false); } + cachedAmount_ = 0; } + return; + } - rpair.trg_ = vPair.second->access(); + // here: toProcess is not our char + // lets check for fast track (255/256 probability) + if (0 == cachedAmount_) { + pNext_->DoReplacements(toProcess, false); + return; } - cachedData_.resize(bufferSize); + // here: We have some cached data + // at least 1 char need to be send further + // remaining cached data including toProcess need to be reprocessed for match + + memcpy(cachedData_.data(), src_.data(), cachedAmount_); + cachedData_[cachedAmount_++] = toProcess; + size_t i = 0; + do { + pNext_->DoReplacements(cachedData_[i++], false); // send 1 byte after another + } while (0 != memcmp(src_.data(), cachedData_.data() + i, --cachedAmount_)); + // Everything that was needed has already been sent + // cachedAmount_ is zero or greater } - void DoReplacements(const char toProcess, const bool aEod) const override; -protected: /// - /// check for partial or full match of the data from cachedData_ - /// with any of lexemes sequentially - /// and provides type of the match and index if found + /// creates replacer /// - /// search in pairs from this index - /// what type of match we want to find : only full or partial also - /// bool: partial, bool: full, size_t: index - tuple FindMatch(const size_t indexFrom, const bool fullOnly) const + /// what we are going to replace + /// this is the result of the replacement + /// Replacer for building replacement chain + static unique_ptr CreateSimpleReplacer( + unique_ptr &src, // what to replace + unique_ptr &trg) // with what { - for (size_t i = indexFrom; i < rpairs_.size(); ++i) - { - const auto& srcSpan = rpairs_[i].src_; - const size_t cmpLength = (srcSpan.size() > cachedAmount_) ? cachedAmount_ : srcSpan.size(); + return unique_ptr(new UsualReplacer(src, trg)); + } - if (0 == memcmp(srcSpan.data(), cachedData_.data(), cmpLength)) - { // match - if (cmpLength == srcSpan.size()) - { - return {false, true, i}; + + class TrieNode { + public: + tsl::robin_map > children; + std::string_view target; + }; + + class Trie { + public: + enum MatchType { none, partial, full }; + + TrieNode root; + TrieNode *lastNode = &root; + + void insert(std::string_view key, std::string_view value) { + TrieNode *node = &root; + for (char c: key) { + if (!node->children[c]) { + node->children[c] = std::make_unique(); } - if (!fullOnly) - { - return {true, false, i}; + node = node->children[c].get(); + } + node->target = value; + } + + [[nodiscard]] std::pair search(const std::string_view &key) { + TrieNode *node = lastNode; + for (char c: key) { + auto res = node->children.find(c); + if (res == node->children.end()) { + if (node == &root) { + lastNode = &root; + return std::make_pair(std::string_view(), none); + } + lastNode = node; + return {"", partial}; } + node = res->second.get(); } - // continue - no match here + return {node->target, full}; } - return {false, false, 0}; - } + }; + + + //-------------------------------------------------- + /// + /// |--SRC 1 TRG 1 | + /// O - |-- ... | - o + /// |--SRC N TRG N | + /// + class ChoiceReplacer final : public ReplacerWithNext { + typedef struct { + span src_; + span trg_; + } ChoiceReplacerPair; + + public: + /// + /// creating ChoiceReplacer from provided pairs + /// + /// vector os source & target pairs + ChoiceReplacer(StreamReplacerChoice &choice) { + size_t bufferSize = 0; // to allocate buffer + const size_t sz = choice.size(); + for (size_t i = 0; i < sz; ++i) { + auto &vPair = choice[i]; + const size_t sourceSize = vPair.first->access().size(); + if (bufferSize < sourceSize) { + bufferSize = sourceSize; // calculate necessary buffer size + } + const span &src = vPair.first->access(); + const span &trg = vPair.second->access(); + trie_.insert(string_view(src.data(), src.size()), string_view(trg.data(), trg.size())); + } - /// - /// Sends target to next replacers, and resets partial match index to zero - /// - /// the array we need to send - void SendAndResetPartialMatch(const span& target) const - { - for (const char c : target) - { - pNext_->DoReplacements(c, false); + cachedData_.resize(bufferSize); } - indexOfPartialMatch_ = 0; - } - /// - /// Clean srcMatchedLength bytes of cache from the beginning - /// - /// number of bytes we have to clear - void CleanTheCache(size_t srcMatchedLength) const - { - shift_left(cachedData_.data(), - cachedData_.data() + cachedAmount_, - static_cast::difference_type>(srcMatchedLength)); - cachedAmount_ -= srcMatchedLength; - } + void DoReplacements(const char toProcess, const bool aEod) const override; - /// - /// The end of the data sign has been received and the cached data need to be either send or replaced & send - /// - /// character received along with end of data sign - void DoReplacementsAtTheEndOfTheData(const char toProcess) const - { - while (cachedAmount_ > 0) - { - const auto [partialMatch, fullMatch, matchPairIndex] = FindMatch(indexOfPartialMatch_, true); - if (fullMatch) - { - const auto& rpair = rpairs_[matchPairIndex]; - SendAndResetPartialMatch(rpair.trg_); - CleanTheCache(rpair.src_.size()); - } - else // No full match -> send 1 char from cache - { - SendAndResetPartialMatch(std::span (cachedData_.data(), 1)); - CleanTheCache(1); + protected: + /// + /// Sends target to next replacers, and resets partial match index to zero + /// + /// the array we need to send + void SendAndResetPartialMatch(const span &target) const { + for (const char c: target) { + pNext_->DoReplacements(c, false); } } - pNext_->DoReplacements(toProcess, true); - } -protected: - // our pairs sorted by priority - only one of them could be replaced for concrete pos - vector rpairs_; + /// + /// Clean srcMatchedLength bytes of cache from the beginning + /// + /// number of bytes we have to clear + void CleanTheCache(size_t srcMatchedLength) const { + shift_left(cachedData_.data(), + cachedData_.data() + cachedAmount_, + static_cast::difference_type>( + srcMatchedLength)); + cachedAmount_ -= srcMatchedLength; + } - mutable size_t cachedAmount_ = 0; // we cached this amount of data - mutable size_t indexOfPartialMatch_ = 0; // this index from rpairs_ represents last partial match + /// + /// The end of the data sign has been received and the cached data need to be either send or replaced & send + /// + /// character received along with end of data sign + void DoReplacementsAtTheEndOfTheData(const char toProcess) const { + while (cachedAmount_ > 0) { + const auto [match, type] = trie_.search(std::string_view(cachedData_.data(), cachedAmount_)); + if (type == Trie::full) { + SendAndResetPartialMatch(match); + CleanTheCache(cachedAmount_); + } else // No full match -> send 1 char from cache + { + SendAndResetPartialMatch(std::span(cachedData_.data(), 1)); + CleanTheCache(1); + } + } + pNext_->DoReplacements(toProcess, true); + } - // this is used to hold temporary data while the logic is - // looking for the new beginning of the cached value - mutable vector cachedData_; -}; + protected: + // our pairs sorted by priority - only one of them could be replaced for concrete pos + mutable Trie trie_; -void ChoiceReplacer::DoReplacements(const char toProcess, const bool aEod) const -{ - if (nullptr == pNext_) - { - throw logic_error("Replacement chain has been broken. Communicate with maintainer"); - } + mutable size_t cachedAmount_ = 0; // we cached this amount of data - if (aEod) [[unlikely]] - { - DoReplacementsAtTheEndOfTheData(toProcess); - return; - } + // this is used to hold temporary data while the logic is + // looking for the new beginning of the cached value + mutable vector cachedData_; + }; - cachedData_[cachedAmount_++] = toProcess; - while (cachedAmount_ > 0) - { - const auto [partialMatch, fullMatch, matchPairIndex] = FindMatch(indexOfPartialMatch_, false); - if (fullMatch) - { - const auto& rpair = rpairs_[matchPairIndex]; - SendAndResetPartialMatch(rpair.trg_); - CleanTheCache(rpair.src_.size()); - return; + void ChoiceReplacer::DoReplacements(const char toProcess, const bool aEod) const { + if (nullptr == pNext_) { + throw logic_error("Replacement chain has been broken. Communicate with maintainer"); } - if (partialMatch) + + if (aEod) [[unlikely]] { - indexOfPartialMatch_ = matchPairIndex; + DoReplacementsAtTheEndOfTheData(toProcess); return; } - // No any match -> send 1 char from cache - SendAndResetPartialMatch(std::span (cachedData_.data(), 1)); - CleanTheCache(1); - } -} - -namespace -{ - static std::string_view warningDuplicatePattern("Warning: Duplicate pattern to replace found. Second lexeme will be ignored."); -}; - -//-------------------------------------------------- -/// -/// replaces for lexemes of the same length -/// -class UniformLexemeReplacer final : public ReplacerWithNext -{ -public: - UniformLexemeReplacer(StreamReplacerChoice& choice, const size_t sz) - : cachedData_(sz) - { - for (AbstractLexemesPair& alpair : choice) - { - const span& src = alpair.first->access(); - const span& trg = alpair.second->access(); - if (auto result = replaceOptions_.insert( - { - string_view(src.data(), src.size()), - string_view(trg.data(), trg.size()), - }); !result.second) - { - cout << coloredconsole::toconsole(warningDuplicatePattern) << endl; + + cachedData_[cachedAmount_++] = toProcess; + while (cachedAmount_ > 0) { + const auto [match, type] = trie_.search(std::string_view(cachedData_.data(), cachedAmount_)); + if (type == Trie::full) { + SendAndResetPartialMatch(match); + CleanTheCache(cachedAmount_); + return; } + if (type == Trie::partial) { + return; + } + // No any match -> send 1 char from cache + SendAndResetPartialMatch(std::span(cachedData_.data(), 1)); + CleanTheCache(1); } } - void DoReplacements(const char toProcess, const bool aEod) const override; + namespace { + static std::string_view warningDuplicatePattern( + "Warning: Duplicate pattern to replace found. Second lexeme will be ignored."); + }; -protected: - // here we hold pairs of sources and targets - unordered_map replaceOptions_; - mutable size_t cachedAmount_ = 0; // we cache this amount of data in the cachedData_ + //-------------------------------------------------- + /// + /// replaces for lexemes of the same length + /// + class UniformLexemeReplacer final : public ReplacerWithNext { + public: + UniformLexemeReplacer(StreamReplacerChoice &choice, const size_t sz) + : cachedData_(sz) { + for (AbstractLexemesPair &alpair: choice) { + const span &src = alpair.first->access(); + const span &trg = alpair.second->access(); + trie_.insert(string_view(src.data(), src.size()), string_view(trg.data(), trg.size())); + } + } - // this is used to hold temporary data while the logic is - // looking for the new beginning of the cached value - mutable vector cachedData_; -}; + void DoReplacements(const char toProcess, const bool aEod) const override; + protected: + // here we hold pairs of sources and targets + mutable Trie trie_; + mutable size_t cachedAmount_ = 0; // we cache this amount of data in the cachedData_ -void UniformLexemeReplacer::DoReplacements(const char toProcess, const bool aEod) const -{ - if (nullptr == pNext_) - { - throw logic_error("Replacement chain has been broken. Communicate with maintainer"); - } + // this is used to hold temporary data while the logic is + // looking for the new beginning of the cached value + mutable vector cachedData_; + }; - // no more data - if (aEod) - { - if (cachedAmount_ > 0) - { - for (size_t q = 0; q < cachedAmount_; ++q) { pNext_->DoReplacements(cachedData_[q], false); } - cachedAmount_ = 0; + + void UniformLexemeReplacer::DoReplacements(const char toProcess, const bool aEod) const { + if (nullptr == pNext_) { + throw logic_error("Replacement chain has been broken. Communicate with maintainer"); } - pNext_->DoReplacements(toProcess, aEod); // send end of the data further - return; - } // if (aEod) + + // no more data + if (aEod) { + if (cachedAmount_ > 0) { + for (size_t q = 0; q < cachedAmount_; ++q) { pNext_->DoReplacements(cachedData_[q], false); } + cachedAmount_ = 0; + } + pNext_->DoReplacements(toProcess, aEod); // send end of the data further + return; + } // if (aEod) - // set buffer of cached at once - char* const& pBuffer = cachedData_.data(); - pBuffer[cachedAmount_++] = toProcess; - if (cachedAmount_ >= cachedData_.size()) - { - if (const auto it = replaceOptions_.find(string_view(pBuffer, cachedAmount_)); it != replaceOptions_.cend()) - { // found - string_view trg = it->second; - for (size_t q = 0; q < trg.size(); ++q) { pNext_->DoReplacements(trg[q], false); } - cachedAmount_ = 0; - } - else - { // not found - pNext_->DoReplacements(pBuffer[0], false); // send 1 char - std::shift_left(pBuffer, pBuffer + cachedAmount_--, 1); + // set buffer of cached at once + cachedData_[cachedAmount_++] = toProcess; + if (cachedAmount_ == cachedData_.size()) { + string_view key(cachedData_.data(), cachedAmount_); + if (auto [target, type] = trie_.search(key); type == Trie::full) { + for (char c: target) { + pNext_->DoReplacements(c, false); + } + cachedAmount_ = 0; + } else { + pNext_->DoReplacements(cachedData_[0], false); + std::shift_left(cachedData_.begin(), cachedData_.begin() + cachedAmount_, 1); + --cachedAmount_; + } } } -} -//-------------------------------------------------- -/// -/// replaces for lexemes of the same length -/// -class LexemeOf1Replacer final : public ReplacerWithNext -{ -public: - LexemeOf1Replacer(StreamReplacerChoice& choice) - { - for (AbstractLexemesPair& alpair : choice) - { - const size_t index = static_cast(*(reinterpret_cast(alpair.first->access().data()))); - if (replaces_[index].present_) - { - cout << coloredconsole::toconsole(warningDuplicatePattern) << endl; - } - else - { - replaces_[index].present_ = true; - replaces_[index].trg_ = alpair.second->access(); + //-------------------------------------------------- + /// + /// replaces for lexemes of the same length + /// + class LexemeOf1Replacer final : public ReplacerWithNext { + public: + LexemeOf1Replacer(StreamReplacerChoice &choice) { + for (AbstractLexemesPair &alpair: choice) { + const size_t index = static_cast(*(reinterpret_cast(alpair.first-> + access().data()))); + if (replaces_[index].present_) { + cout << coloredconsole::toconsole(warningDuplicatePattern) << endl; + } else { + replaces_[index].present_ = true; + replaces_[index].trg_ = alpair.second->access(); + } } } - } - void DoReplacements(const char toProcess, const bool aEod) const override; + void DoReplacements(const char toProcess, const bool aEod) const override; -protected: - struct - { - bool present_ = false; // if this char is present - span trg_; - } replaces_[256]; -}; + protected: + struct { + bool present_ = false; // if this char is present + span trg_; + } replaces_[256]; + }; -void LexemeOf1Replacer::DoReplacements(const char toProcess, const bool aEod) const -{ - if (nullptr == pNext_) - { - throw logic_error("Replacement chain has been broken. Communicate with maintainer"); - } + void LexemeOf1Replacer::DoReplacements(const char toProcess, const bool aEod) const { + if (nullptr == pNext_) { + throw logic_error("Replacement chain has been broken. Communicate with maintainer"); + } - // no more data - if (aEod) - { - pNext_->DoReplacements(toProcess, aEod); - return; - } // if (aEod) + // no more data + if (aEod) { + pNext_->DoReplacements(toProcess, aEod); + return; + } // if (aEod) - const size_t index = static_cast(*(reinterpret_cast(&toProcess))); - if (replaces_[index].present_) - { - auto& trg = replaces_[index].trg_; - for (size_t q = 0; q < trg.size(); ++q) { pNext_->DoReplacements(trg[q], false); } - } - else - { - pNext_->DoReplacements(toProcess, aEod); - } -} - - -//-------------------------------------------------- -/// -/// creates replacer for lexemes of the same length -/// since this fact allows to use unordered_map for faster search -/// -/// set of pairs of src & trg lexemes - one of which -/// can be processed. The one that was found first. -/// size of all source lexemes -/// Replacer for building replacement chain -unique_ptr CreateEqualLengthReplacer(StreamReplacerChoice& choice, const size_t sz) -{ - if (sz == 1) - { - return unique_ptr(new LexemeOf1Replacer(choice)); - } - return unique_ptr(new UniformLexemeReplacer(choice, sz)); -} - -//-------------------------------------------------- -/// -/// creates replacer for choose specific lexeme among others to replace -/// -/// set of pairs of src & trg lexemes - one of which -/// can be processed. The one that was found first. -/// Replacer for building replacement chain -unique_ptr CreateMultipleReplacer(StreamReplacerChoice& choice) -{ - const size_t szSrc = choice.cbegin()->first->access().size(); // save size of the first lexeme - - // check for sources of the same length - for (const AbstractLexemesPair& alpair: choice) - { - if (alpair.first->access().size() != szSrc) - { - return unique_ptr(new ChoiceReplacer(choice)); + const size_t index = static_cast(*(reinterpret_cast(&toProcess))); + if (replaces_[index].present_) { + auto &trg = replaces_[index].trg_; + for (size_t q = 0; q < trg.size(); ++q) { pNext_->DoReplacements(trg[q], false); } + } else { + pNext_->DoReplacements(toProcess, aEod); } } - return CreateEqualLengthReplacer(choice, szSrc); // create optimized replacer for lexemes of the same length -} - -//-------------------------------------------------- -unique_ptr StreamReplacer::CreateReplacer(StreamReplacerChoice& choice) -{ - for (const AbstractLexemesPair& alpair: choice) - { - if (alpair.first->access().empty()) - throw logic_error("Pattern to replace cannot be empty"); + //-------------------------------------------------- + /// + /// creates replacer for lexemes of the same length + /// since this fact allows to use unordered_map for faster search + /// + /// set of pairs of src & trg lexemes - one of which + /// can be processed. The one that was found first. + /// size of all source lexemes + /// Replacer for building replacement chain + unique_ptr CreateEqualLengthReplacer(StreamReplacerChoice &choice, const size_t sz) { + if (sz == 1) { + return unique_ptr(new LexemeOf1Replacer(choice)); + } + return unique_ptr(new UniformLexemeReplacer(choice, sz)); } - if (choice.size() == 1) - { - const AbstractLexemesPair& alexemesPair = *choice.cbegin(); - return CreateSimpleReplacer(alexemesPair.first, alexemesPair.second); + //-------------------------------------------------- + /// + /// creates replacer for choose specific lexeme among others to replace + /// + /// set of pairs of src & trg lexemes - one of which + /// can be processed. The one that was found first. + /// Replacer for building replacement chain + unique_ptr CreateMultipleReplacer(StreamReplacerChoice &choice) { + const size_t szSrc = choice.cbegin()->first->access().size(); // save size of the first lexeme + + // check for sources of the same length + for (const AbstractLexemesPair &alpair: choice) { + if (alpair.first->access().size() != szSrc) { + return unique_ptr(new ChoiceReplacer(choice)); + } + } + + return CreateEqualLengthReplacer(choice, szSrc); // create optimized replacer for lexemes of the same length } - return CreateMultipleReplacer(choice); -} + + //-------------------------------------------------- + unique_ptr StreamReplacer::CreateReplacer(StreamReplacerChoice &choice) { + for (const AbstractLexemesPair &alpair: choice) { + if (alpair.first->access().empty()) + throw logic_error("Pattern to replace cannot be empty"); + } + + if (choice.size() == 1) { + const AbstractLexemesPair &alexemesPair = *choice.cbegin(); + return CreateSimpleReplacer(alexemesPair.first, alexemesPair.second); + } + return CreateMultipleReplacer(choice); + } }; // namespace bpatch From 555b2369698ad53f35871e8efa4d47c6127d0b7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D0=BC=D0=B8=D1=80=20=D0=A7?= =?UTF-8?q?=D0=B8=D0=B6?= Date: Sun, 15 Sep 2024 18:48:25 +0200 Subject: [PATCH 02/16] trie fix --- IntegrationTests/in_tests.sh | 0 IntegrationTests/scripts/fromhex8bytes.json | 813 ++++++++++++++++++++ srcbpatch/streamreplacer.cpp | 62 +- 3 files changed, 865 insertions(+), 10 deletions(-) mode change 100644 => 100755 IntegrationTests/in_tests.sh create mode 100644 IntegrationTests/scripts/fromhex8bytes.json diff --git a/IntegrationTests/in_tests.sh b/IntegrationTests/in_tests.sh old mode 100644 new mode 100755 diff --git a/IntegrationTests/scripts/fromhex8bytes.json b/IntegrationTests/scripts/fromhex8bytes.json new file mode 100644 index 0000000..625fc6e --- /dev/null +++ b/IntegrationTests/scripts/fromhex8bytes.json @@ -0,0 +1,813 @@ +{ + "dictionary": { + "hexadecimal": { + "0": ["00", "01", "02", "03", "04", "05", "06", "07", "08"], + "1": ["01", "01", "02", "03", "04", "05", "06", "07", "08"], + "2": ["02", "01", "02", "03", "04", "05", "06", "07", "08"], + "3": ["03", "01", "02", "03", "04", "05", "06", "07", "08"], + "4": ["04", "01", "02", "03", "04", "05", "06", "07", "08"], + "5": ["05", "01", "02", "03", "04", "05", "06", "07", "08"], + "6": ["06", "01", "02", "03", "04", "05", "06", "07", "08"], + "7": ["07", "01", "02", "03", "04", "05", "06", "07", "08"], + "8": ["08", "01", "02", "03", "04", "05", "06", "07", "08"], + "9": ["09", "01", "02", "03", "04", "05", "06", "07", "08"], + "10": ["0A", "01", "02", "03", "04", "05", "06", "07", "08"], + "11": ["0B", "01", "02", "03", "04", "05", "06", "07", "08"], + "12": ["0C", "01", "02", "03", "04", "05", "06", "07", "08"], + "13": ["0D", "01", "02", "03", "04", "05", "06", "07", "08"], + "14": ["0E", "01", "02", "03", "04", "05", "06", "07", "08"], + "15": ["0F", "01", "02", "03", "04", "05", "06", "07", "08"], + "16": ["10", "01", "02", "03", "04", "05", "06", "07", "08"], + "17": ["11", "01", "02", "03", "04", "05", "06", "07", "08"], + "18": ["12", "01", "02", "03", "04", "05", "06", "07", "08"], + "19": ["13", "01", "02", "03", "04", "05", "06", "07", "08"], + "20": ["14", "01", "02", "03", "04", "05", "06", "07", "08"], + "21": ["15", "01", "02", "03", "04", "05", "06", "07", "08"], + "22": ["16", "01", "02", "03", "04", "05", "06", "07", "08"], + "23": ["17", "01", "02", "03", "04", "05", "06", "07", "08"], + "24": ["18", "01", "02", "03", "04", "05", "06", "07", "08"], + "25": ["19", "01", "02", "03", "04", "05", "06", "07", "08"], + "26": ["1A", "01", "02", "03", "04", "05", "06", "07", "08"], + "27": ["1B", "01", "02", "03", "04", "05", "06", "07", "08"], + "28": ["1C", "01", "02", "03", "04", "05", "06", "07", "08"], + "29": ["1D", "01", "02", "03", "04", "05", "06", "07", "08"], + "30": ["1E", "01", "02", "03", "04", "05", "06", "07", "08"], + "31": ["1F", "01", "02", "03", "04", "05", "06", "07", "08"], + "32": ["20", "01", "02", "03", "04", "05", "06", "07", "08"], + "33": ["21", "01", "02", "03", "04", "05", "06", "07", "08"], + "34": ["22", "01", "02", "03", "04", "05", "06", "07", "08"], + "35": ["23", "01", "02", "03", "04", "05", "06", "07", "08"], + "36": ["24", "01", "02", "03", "04", "05", "06", "07", "08"], + "37": ["25", "01", "02", "03", "04", "05", "06", "07", "08"], + "38": ["26", "01", "02", "03", "04", "05", "06", "07", "08"], + "39": ["27", "01", "02", "03", "04", "05", "06", "07", "08"], + "40": ["28", "01", "02", "03", "04", "05", "06", "07", "08"], + "41": ["29", "01", "02", "03", "04", "05", "06", "07", "08"], + "42": ["2A", "01", "02", "03", "04", "05", "06", "07", "08"], + "43": ["2B", "01", "02", "03", "04", "05", "06", "07", "08"], + "44": ["2C", "01", "02", "03", "04", "05", "06", "07", "08"], + "45": ["2D", "01", "02", "03", "04", "05", "06", "07", "08"], + "46": ["2E", "01", "02", "03", "04", "05", "06", "07", "08"], + "47": ["2F", "01", "02", "03", "04", "05", "06", "07", "08"], + "48": ["30", "01", "02", "03", "04", "05", "06", "07", "08"], + "49": ["31", "01", "02", "03", "04", "05", "06", "07", "08"], + "50": ["32", "01", "02", "03", "04", "05", "06", "07", "08"], + "51": ["33", "01", "02", "03", "04", "05", "06", "07", "08"], + "52": ["34", "01", "02", "03", "04", "05", "06", "07", "08"], + "53": ["35", "01", "02", "03", "04", "05", "06", "07", "08"], + "54": ["36", "01", "02", "03", "04", "05", "06", "07", "08"], + "55": ["37", "01", "02", "03", "04", "05", "06", "07", "08"], + "56": ["38", "01", "02", "03", "04", "05", "06", "07", "08"], + "57": ["39", "01", "02", "03", "04", "05", "06", "07", "08"], + "58": ["3A", "01", "02", "03", "04", "05", "06", "07", "08"], + "59": ["3B", "01", "02", "03", "04", "05", "06", "07", "08"], + "60": ["3C", "01", "02", "03", "04", "05", "06", "07", "08"], + "61": ["3D", "01", "02", "03", "04", "05", "06", "07", "08"], + "62": ["3E", "01", "02", "03", "04", "05", "06", "07", "08"], + "63": ["3F", "01", "02", "03", "04", "05", "06", "07", "08"], + "64": ["40", "01", "02", "03", "04", "05", "06", "07", "08"], + "65": ["41", "01", "02", "03", "04", "05", "06", "07", "08"], + "66": ["42", "01", "02", "03", "04", "05", "06", "07", "08"], + "67": ["43", "01", "02", "03", "04", "05", "06", "07", "08"], + "68": ["44", "01", "02", "03", "04", "05", "06", "07", "08"], + "69": ["45", "01", "02", "03", "04", "05", "06", "07", "08"], + "70": ["46", "01", "02", "03", "04", "05", "06", "07", "08"], + "71": ["47", "01", "02", "03", "04", "05", "06", "07", "08"], + "72": ["48", "01", "02", "03", "04", "05", "06", "07", "08"], + "73": ["49", "01", "02", "03", "04", "05", "06", "07", "08"], + "74": ["4A", "01", "02", "03", "04", "05", "06", "07", "08"], + "75": ["4B", "01", "02", "03", "04", "05", "06", "07", "08"], + "76": ["4C", "01", "02", "03", "04", "05", "06", "07", "08"], + "77": ["4D", "01", "02", "03", "04", "05", "06", "07", "08"], + "78": ["4E", "01", "02", "03", "04", "05", "06", "07", "08"], + "79": ["4F", "01", "02", "03", "04", "05", "06", "07", "08"], + "80": ["50", "01", "02", "03", "04", "05", "06", "07", "08"], + "81": ["51", "01", "02", "03", "04", "05", "06", "07", "08"], + "82": ["52", "01", "02", "03", "04", "05", "06", "07", "08"], + "83": ["53", "01", "02", "03", "04", "05", "06", "07", "08"], + "84": ["54", "01", "02", "03", "04", "05", "06", "07", "08"], + "85": ["55", "01", "02", "03", "04", "05", "06", "07", "08"], + "86": ["56", "01", "02", "03", "04", "05", "06", "07", "08"], + "87": ["57", "01", "02", "03", "04", "05", "06", "07", "08"], + "88": ["58", "01", "02", "03", "04", "05", "06", "07", "08"], + "89": ["59", "01", "02", "03", "04", "05", "06", "07", "08"], + "90": ["5A", "01", "02", "03", "04", "05", "06", "07", "08"], + "91": ["5B", "01", "02", "03", "04", "05", "06", "07", "08"], + "92": ["5C", "01", "02", "03", "04", "05", "06", "07", "08"], + "93": ["5D", "01", "02", "03", "04", "05", "06", "07", "08"], + "94": ["5E", "01", "02", "03", "04", "05", "06", "07", "08"], + "95": ["5F", "01", "02", "03", "04", "05", "06", "07", "08"], + "96": ["60", "01", "02", "03", "04", "05", "06", "07", "08"], + "97": ["61", "01", "02", "03", "04", "05", "06", "07", "08"], + "98": ["62", "01", "02", "03", "04", "05", "06", "07", "08"], + "99": ["63", "01", "02", "03", "04", "05", "06", "07", "08"], + "100": ["64", "01", "02", "03", "04", "05", "06", "07", "08"], + "101": ["65", "01", "02", "03", "04", "05", "06", "07", "08"], + "102": ["66", "01", "02", "03", "04", "05", "06", "07", "08"], + "103": ["67", "01", "02", "03", "04", "05", "06", "07", "08"], + "104": ["68", "01", "02", "03", "04", "05", "06", "07", "08"], + "105": ["69", "01", "02", "03", "04", "05", "06", "07", "08"], + "106": ["6A", "01", "02", "03", "04", "05", "06", "07", "08"], + "107": ["6B", "01", "02", "03", "04", "05", "06", "07", "08"], + "108": ["6C", "01", "02", "03", "04", "05", "06", "07", "08"], + "109": ["6D", "01", "02", "03", "04", "05", "06", "07", "08"], + "110": ["6E", "01", "02", "03", "04", "05", "06", "07", "08"], + "111": ["6F", "01", "02", "03", "04", "05", "06", "07", "08"], + "112": ["70", "01", "02", "03", "04", "05", "06", "07", "08"], + "113": ["71", "01", "02", "03", "04", "05", "06", "07", "08"], + "114": ["72", "01", "02", "03", "04", "05", "06", "07", "08"], + "115": ["73", "01", "02", "03", "04", "05", "06", "07", "08"], + "116": ["74", "01", "02", "03", "04", "05", "06", "07", "08"], + "117": ["75", "01", "02", "03", "04", "05", "06", "07", "08"], + "118": ["76", "01", "02", "03", "04", "05", "06", "07", "08"], + "119": ["77", "01", "02", "03", "04", "05", "06", "07", "08"], + "120": ["78", "01", "02", "03", "04", "05", "06", "07", "08"], + "121": ["79", "01", "02", "03", "04", "05", "06", "07", "08"], + "122": ["7A", "01", "02", "03", "04", "05", "06", "07", "08"], + "123": ["7B", "01", "02", "03", "04", "05", "06", "07", "08"], + "124": ["7C", "01", "02", "03", "04", "05", "06", "07", "08"], + "125": ["7D", "01", "02", "03", "04", "05", "06", "07", "08"], + "126": ["7E", "01", "02", "03", "04", "05", "06", "07", "08"], + "127": ["7F", "01", "02", "03", "04", "05", "06", "07", "08"], + "128": ["80", "01", "02", "03", "04", "05", "06", "07", "08"], + "129": ["81", "01", "02", "03", "04", "05", "06", "07", "08"], + "130": ["82", "01", "02", "03", "04", "05", "06", "07", "08"], + "131": ["83", "01", "02", "03", "04", "05", "06", "07", "08"], + "132": ["84", "01", "02", "03", "04", "05", "06", "07", "08"], + "133": ["85", "01", "02", "03", "04", "05", "06", "07", "08"], + "134": ["86", "01", "02", "03", "04", "05", "06", "07", "08"], + "135": ["87", "01", "02", "03", "04", "05", "06", "07", "08"], + "136": ["88", "01", "02", "03", "04", "05", "06", "07", "08"], + "137": ["89", "01", "02", "03", "04", "05", "06", "07", "08"], + "138": ["8A", "01", "02", "03", "04", "05", "06", "07", "08"], + "139": ["8B", "01", "02", "03", "04", "05", "06", "07", "08"], + "140": ["8C", "01", "02", "03", "04", "05", "06", "07", "08"], + "141": ["8D", "01", "02", "03", "04", "05", "06", "07", "08"], + "142": ["8E", "01", "02", "03", "04", "05", "06", "07", "08"], + "143": ["8F", "01", "02", "03", "04", "05", "06", "07", "08"], + "144": ["90", "01", "02", "03", "04", "05", "06", "07", "08"], + "145": ["91", "01", "02", "03", "04", "05", "06", "07", "08"], + "146": ["92", "01", "02", "03", "04", "05", "06", "07", "08"], + "147": ["93", "01", "02", "03", "04", "05", "06", "07", "08"], + "148": ["94", "01", "02", "03", "04", "05", "06", "07", "08"], + "149": ["95", "01", "02", "03", "04", "05", "06", "07", "08"], + "150": ["96", "01", "02", "03", "04", "05", "06", "07", "08"], + "151": ["97", "01", "02", "03", "04", "05", "06", "07", "08"], + "152": ["98", "01", "02", "03", "04", "05", "06", "07", "08"], + "153": ["99", "01", "02", "03", "04", "05", "06", "07", "08"], + "154": ["9A", "01", "02", "03", "04", "05", "06", "07", "08"], + "155": ["9B", "01", "02", "03", "04", "05", "06", "07", "08"], + "156": ["9C", "01", "02", "03", "04", "05", "06", "07", "08"], + "157": ["9D", "01", "02", "03", "04", "05", "06", "07", "08"], + "158": ["9E", "01", "02", "03", "04", "05", "06", "07", "08"], + "159": ["9F", "01", "02", "03", "04", "05", "06", "07", "08"], + "160": ["A0", "01", "02", "03", "04", "05", "06", "07", "08"], + "161": ["A1", "01", "02", "03", "04", "05", "06", "07", "08"], + "162": ["A2", "01", "02", "03", "04", "05", "06", "07", "08"], + "163": ["A3", "01", "02", "03", "04", "05", "06", "07", "08"], + "164": ["A4", "01", "02", "03", "04", "05", "06", "07", "08"], + "165": ["A5", "01", "02", "03", "04", "05", "06", "07", "08"], + "166": ["A6", "01", "02", "03", "04", "05", "06", "07", "08"], + "167": ["A7", "01", "02", "03", "04", "05", "06", "07", "08"], + "168": ["A8", "01", "02", "03", "04", "05", "06", "07", "08"], + "169": ["A9", "01", "02", "03", "04", "05", "06", "07", "08"], + "170": ["AA", "01", "02", "03", "04", "05", "06", "07", "08"], + "171": ["AB", "01", "02", "03", "04", "05", "06", "07", "08"], + "172": ["AC", "01", "02", "03", "04", "05", "06", "07", "08"], + "173": ["AD", "01", "02", "03", "04", "05", "06", "07", "08"], + "174": ["AE", "01", "02", "03", "04", "05", "06", "07", "08"], + "175": ["AF", "01", "02", "03", "04", "05", "06", "07", "08"], + "176": ["B0", "01", "02", "03", "04", "05", "06", "07", "08"], + "177": ["B1", "01", "02", "03", "04", "05", "06", "07", "08"], + "178": ["B2", "01", "02", "03", "04", "05", "06", "07", "08"], + "179": ["B3", "01", "02", "03", "04", "05", "06", "07", "08"], + "180": ["B4", "01", "02", "03", "04", "05", "06", "07", "08"], + "181": ["B5", "01", "02", "03", "04", "05", "06", "07", "08"], + "182": ["B6", "01", "02", "03", "04", "05", "06", "07", "08"], + "183": ["B7", "01", "02", "03", "04", "05", "06", "07", "08"], + "184": ["B8", "01", "02", "03", "04", "05", "06", "07", "08"], + "185": ["B9", "01", "02", "03", "04", "05", "06", "07", "08"], + "186": ["BA", "01", "02", "03", "04", "05", "06", "07", "08"], + "187": ["BB", "01", "02", "03", "04", "05", "06", "07", "08"], + "188": ["BC", "01", "02", "03", "04", "05", "06", "07", "08"], + "189": ["BD", "01", "02", "03", "04", "05", "06", "07", "08"], + "190": ["BE", "01", "02", "03", "04", "05", "06", "07", "08"], + "191": ["BF", "01", "02", "03", "04", "05", "06", "07", "08"], + "192": ["C0", "01", "02", "03", "04", "05", "06", "07", "08"], + "193": ["C1", "01", "02", "03", "04", "05", "06", "07", "08"], + "194": ["C2", "01", "02", "03", "04", "05", "06", "07", "08"], + "195": ["C3", "01", "02", "03", "04", "05", "06", "07", "08"], + "196": ["C4", "01", "02", "03", "04", "05", "06", "07", "08"], + "197": ["C5", "01", "02", "03", "04", "05", "06", "07", "08"], + "198": ["C6", "01", "02", "03", "04", "05", "06", "07", "08"], + "199": ["C7", "01", "02", "03", "04", "05", "06", "07", "08"], + "200": ["C8", "01", "02", "03", "04", "05", "06", "07", "08"], + "201": ["C9", "01", "02", "03", "04", "05", "06", "07", "08"], + "202": ["CA", "01", "02", "03", "04", "05", "06", "07", "08"], + "203": ["CB", "01", "02", "03", "04", "05", "06", "07", "08"], + "204": ["CC", "01", "02", "03", "04", "05", "06", "07", "08"], + "205": ["CD", "01", "02", "03", "04", "05", "06", "07", "08"], + "206": ["CE", "01", "02", "03", "04", "05", "06", "07", "08"], + "207": ["CF", "01", "02", "03", "04", "05", "06", "07", "08"], + "208": ["D0", "01", "02", "03", "04", "05", "06", "07", "08"], + "209": ["D1", "01", "02", "03", "04", "05", "06", "07", "08"], + "210": ["D2", "01", "02", "03", "04", "05", "06", "07", "08"], + "211": ["D3", "01", "02", "03", "04", "05", "06", "07", "08"], + "212": ["D4", "01", "02", "03", "04", "05", "06", "07", "08"], + "213": ["D5", "01", "02", "03", "04", "05", "06", "07", "08"], + "214": ["D6", "01", "02", "03", "04", "05", "06", "07", "08"], + "215": ["D7", "01", "02", "03", "04", "05", "06", "07", "08"], + "216": ["D8", "01", "02", "03", "04", "05", "06", "07", "08"], + "217": ["D9", "01", "02", "03", "04", "05", "06", "07", "08"], + "218": ["DA", "01", "02", "03", "04", "05", "06", "07", "08"], + "219": ["DB", "01", "02", "03", "04", "05", "06", "07", "08"], + "220": ["DC", "01", "02", "03", "04", "05", "06", "07", "08"], + "221": ["DD", "01", "02", "03", "04", "05", "06", "07", "08"], + "222": ["DE", "01", "02", "03", "04", "05", "06", "07", "08"], + "223": ["DF", "01", "02", "03", "04", "05", "06", "07", "08"], + "224": ["E0", "01", "02", "03", "04", "05", "06", "07", "08"], + "225": ["E1", "01", "02", "03", "04", "05", "06", "07", "08"], + "226": ["E2", "01", "02", "03", "04", "05", "06", "07", "08"], + "227": ["E3", "01", "02", "03", "04", "05", "06", "07", "08"], + "228": ["E4", "01", "02", "03", "04", "05", "06", "07", "08"], + "229": ["E5", "01", "02", "03", "04", "05", "06", "07", "08"], + "230": ["E6", "01", "02", "03", "04", "05", "06", "07", "08"], + "231": ["E7", "01", "02", "03", "04", "05", "06", "07", "08"], + "232": ["E8", "01", "02", "03", "04", "05", "06", "07", "08"], + "233": ["E9", "01", "02", "03", "04", "05", "06", "07", "08"], + "234": ["EA", "01", "02", "03", "04", "05", "06", "07", "08"], + "235": ["EB", "01", "02", "03", "04", "05", "06", "07", "08"], + "236": ["EC", "01", "02", "03", "04", "05", "06", "07", "08"], + "237": ["ED", "01", "02", "03", "04", "05", "06", "07", "08"], + "238": ["EE", "01", "02", "03", "04", "05", "06", "07", "08"], + "239": ["EF", "01", "02", "03", "04", "05", "06", "07", "08"], + "240": ["F0", "01", "02", "03", "04", "05", "06", "07", "08"], + "241": ["F1", "01", "02", "03", "04", "05", "06", "07", "08"], + "242": ["F2", "01", "02", "03", "04", "05", "06", "07", "08"], + "243": ["F3", "01", "02", "03", "04", "05", "06", "07", "08"], + "244": ["F4", "01", "02", "03", "04", "05", "06", "07", "08"], + "245": ["F5", "01", "02", "03", "04", "05", "06", "07", "08"], + "246": ["F6", "01", "02", "03", "04", "05", "06", "07", "08"], + "247": ["F7", "01", "02", "03", "04", "05", "06", "07", "08"], + "248": ["F8", "01", "02", "03", "04", "05", "06", "07", "08"], + "249": ["F9", "01", "02", "03", "04", "05", "06", "07", "08"], + "250": ["FA", "01", "02", "03", "04", "05", "06", "07", "08"], + "251": ["FB", "01", "02", "03", "04", "05", "06", "07", "08"], + "252": ["FC", "01", "02", "03", "04", "05", "06", "07", "08"], + "253": ["FD", "01", "02", "03", "04", "05", "06", "07", "08"], + "254": ["FE", "01", "02", "03", "04", "05", "06", "07", "08"], + "255": ["FE", "10", "20", "30", "40", "50", "60", "70", "8F"] + }, + "text": + { + "a":"a", + "b":"b", + "c":"c", + "d":"d", + "e":"e", + "f":"f", + "A":"A", + "B":"B", + "C":"C", + "D":"D", + "E":"E", + "F":"F", + "LF":"\n", + "CR":"\r", + "tab":"\t", + "whitespace":" ", + "empty":"", + "t0":"00", + "t1":"01", + "t2":"02", + "t3":"03", + "t4":"04", + "t5":"05", + "t6":"06", + "t7":"07", + "t8":"08", + "t9":"09", + "t10":"0A", + "t11":"0B", + "t12":"0C", + "t13":"0D", + "t14":"0E", + "t15":"0F", + "t16":"10", + "t17":"11", + "t18":"12", + "t19":"13", + "t20":"14", + "t21":"15", + "t22":"16", + "t23":"17", + "t24":"18", + "t25":"19", + "t26":"1A", + "t27":"1B", + "t28":"1C", + "t29":"1D", + "t30":"1E", + "t31":"1F", + "t32":"20", + "t33":"21", + "t34":"22", + "t35":"23", + "t36":"24", + "t37":"25", + "t38":"26", + "t39":"27", + "t40":"28", + "t41":"29", + "t42":"2A", + "t43":"2B", + "t44":"2C", + "t45":"2D", + "t46":"2E", + "t47":"2F", + "t48":"30", + "t49":"31", + "t50":"32", + "t51":"33", + "t52":"34", + "t53":"35", + "t54":"36", + "t55":"37", + "t56":"38", + "t57":"39", + "t58":"3A", + "t59":"3B", + "t60":"3C", + "t61":"3D", + "t62":"3E", + "t63":"3F", + "t64":"40", + "t65":"41", + "t66":"42", + "t67":"43", + "t68":"44", + "t69":"45", + "t70":"46", + "t71":"47", + "t72":"48", + "t73":"49", + "t74":"4A", + "t75":"4B", + "t76":"4C", + "t77":"4D", + "t78":"4E", + "t79":"4F", + "t80":"50", + "t81":"51", + "t82":"52", + "t83":"53", + "t84":"54", + "t85":"55", + "t86":"56", + "t87":"57", + "t88":"58", + "t89":"59", + "t90":"5A", + "t91":"5B", + "t92":"5C", + "t93":"5D", + "t94":"5E", + "t95":"5F", + "t96":"60", + "t97":"61", + "t98":"62", + "t99":"63", + "t100":"64", + "t101":"65", + "t102":"66", + "t103":"67", + "t104":"68", + "t105":"69", + "t106":"6A", + "t107":"6B", + "t108":"6C", + "t109":"6D", + "t110":"6E", + "t111":"6F", + "t112":"70", + "t113":"71", + "t114":"72", + "t115":"73", + "t116":"74", + "t117":"75", + "t118":"76", + "t119":"77", + "t120":"78", + "t121":"79", + "t122":"7A", + "t123":"7B", + "t124":"7C", + "t125":"7D", + "t126":"7E", + "t127":"7F", + "t128":"80", + "t129":"81", + "t130":"82", + "t131":"83", + "t132":"84", + "t133":"85", + "t134":"86", + "t135":"87", + "t136":"88", + "t137":"89", + "t138":"8A", + "t139":"8B", + "t140":"8C", + "t141":"8D", + "t142":"8E", + "t143":"8F", + "t144":"90", + "t145":"91", + "t146":"92", + "t147":"93", + "t148":"94", + "t149":"95", + "t150":"96", + "t151":"97", + "t152":"98", + "t153":"99", + "t154":"9A", + "t155":"9B", + "t156":"9C", + "t157":"9D", + "t158":"9E", + "t159":"9F", + "t160":"A0", + "t161":"A1", + "t162":"A2", + "t163":"A3", + "t164":"A4", + "t165":"A5", + "t166":"A6", + "t167":"A7", + "t168":"A8", + "t169":"A9", + "t170":"AA", + "t171":"AB", + "t172":"AC", + "t173":"AD", + "t174":"AE", + "t175":"AF", + "t176":"B0", + "t177":"B1", + "t178":"B2", + "t179":"B3", + "t180":"B4", + "t181":"B5", + "t182":"B6", + "t183":"B7", + "t184":"B8", + "t185":"B9", + "t186":"BA", + "t187":"BB", + "t188":"BC", + "t189":"BD", + "t190":"BE", + "t191":"BF", + "t192":"C0", + "t193":"C1", + "t194":"C2", + "t195":"C3", + "t196":"C4", + "t197":"C5", + "t198":"C6", + "t199":"C7", + "t200":"C8", + "t201":"C9", + "t202":"CA", + "t203":"CB", + "t204":"CC", + "t205":"CD", + "t206":"CE", + "t207":"CF", + "t208":"D0", + "t209":"D1", + "t210":"D2", + "t211":"D3", + "t212":"D4", + "t213":"D5", + "t214":"D6", + "t215":"D7", + "t216":"D8", + "t217":"D9", + "t218":"DA", + "t219":"DB", + "t220":"DC", + "t221":"DD", + "t222":"DE", + "t223":"DF", + "t224":"E0", + "t225":"E1", + "t226":"E2", + "t227":"E3", + "t228":"E4", + "t229":"E5", + "t230":"E6", + "t231":"E7", + "t232":"E8", + "t233":"E9", + "t234":"EA", + "t235":"EB", + "t236":"EC", + "t237":"ED", + "t238":"EE", + "t239":"EF", + "t240":"F0", + "t241":"F1", + "t242":"F2", + "t243":"F3", + "t244":"F4", + "t245":"F5", + "t246":"F6", + "t247":"F7", + "t248":"F8", + "t249":"F9", + "t250":"FA", + "t251":"FB", + "t252":"FC", + "t253":"FD", + "t254":"FE", + "t255":"FF" + } + }, + "todo": [ + { + "replace": + { + "LF":"empty", + "CR":"empty", + "tab":"empty", + "whitespace":"empty", + "a":"A", + "b":"B", + "c":"C", + "d":"D", + "e":"E", + "f":"F" + }, + "replace": { + "t0":"0", + "t1":"1", + "t2":"2", + "t3":"3", + "t4":"4", + "t5":"5", + "t6":"6", + "t7":"7", + "t8":"8", + "t9":"9", + "t10":"10", + "t11":"11", + "t12":"12", + "t13":"13", + "t14":"14", + "t15":"15", + "t16":"16", + "t17":"17", + "t18":"18", + "t19":"19", + "t20":"20", + "t21":"21", + "t22":"22", + "t23":"23", + "t24":"24", + "t25":"25", + "t26":"26", + "t27":"27", + "t28":"28", + "t29":"29", + "t30":"30", + "t31":"31", + "t32":"32", + "t33":"33", + "t34":"34", + "t35":"35", + "t36":"36", + "t37":"37", + "t38":"38", + "t39":"39", + "t40":"40", + "t41":"41", + "t42":"42", + "t43":"43", + "t44":"44", + "t45":"45", + "t46":"46", + "t47":"47", + "t48":"48", + "t49":"49", + "t50":"50", + "t51":"51", + "t52":"52", + "t53":"53", + "t54":"54", + "t55":"55", + "t56":"56", + "t57":"57", + "t58":"58", + "t59":"59", + "t60":"60", + "t61":"61", + "t62":"62", + "t63":"63", + "t64":"64", + "t65":"65", + "t66":"66", + "t67":"67", + "t68":"68", + "t69":"69", + "t70":"70", + "t71":"71", + "t72":"72", + "t73":"73", + "t74":"74", + "t75":"75", + "t76":"76", + "t77":"77", + "t78":"78", + "t79":"79", + "t80":"80", + "t81":"81", + "t82":"82", + "t83":"83", + "t84":"84", + "t85":"85", + "t86":"86", + "t87":"87", + "t88":"88", + "t89":"89", + "t90":"90", + "t91":"91", + "t92":"92", + "t93":"93", + "t94":"94", + "t95":"95", + "t96":"96", + "t97":"97", + "t98":"98", + "t99":"99", + "t100":"100", + "t101":"101", + "t102":"102", + "t103":"103", + "t104":"104", + "t105":"105", + "t106":"106", + "t107":"107", + "t108":"108", + "t109":"109", + "t110":"110", + "t111":"111", + "t112":"112", + "t113":"113", + "t114":"114", + "t115":"115", + "t116":"116", + "t117":"117", + "t118":"118", + "t119":"119", + "t120":"120", + "t121":"121", + "t122":"122", + "t123":"123", + "t124":"124", + "t125":"125", + "t126":"126", + "t127":"127", + "t128":"128", + "t129":"129", + "t130":"130", + "t131":"131", + "t132":"132", + "t133":"133", + "t134":"134", + "t135":"135", + "t136":"136", + "t137":"137", + "t138":"138", + "t139":"139", + "t140":"140", + "t141":"141", + "t142":"142", + "t143":"143", + "t144":"144", + "t145":"145", + "t146":"146", + "t147":"147", + "t148":"148", + "t149":"149", + "t150":"150", + "t151":"151", + "t152":"152", + "t153":"153", + "t154":"154", + "t155":"155", + "t156":"156", + "t157":"157", + "t158":"158", + "t159":"159", + "t160":"160", + "t161":"161", + "t162":"162", + "t163":"163", + "t164":"164", + "t165":"165", + "t166":"166", + "t167":"167", + "t168":"168", + "t169":"169", + "t170":"170", + "t171":"171", + "t172":"172", + "t173":"173", + "t174":"174", + "t175":"175", + "t176":"176", + "t177":"177", + "t178":"178", + "t179":"179", + "t180":"180", + "t181":"181", + "t182":"182", + "t183":"183", + "t184":"184", + "t185":"185", + "t186":"186", + "t187":"187", + "t188":"188", + "t189":"189", + "t190":"190", + "t191":"191", + "t192":"192", + "t193":"193", + "t194":"194", + "t195":"195", + "t196":"196", + "t197":"197", + "t198":"198", + "t199":"199", + "t200":"200", + "t201":"201", + "t202":"202", + "t203":"203", + "t204":"204", + "t205":"205", + "t206":"206", + "t207":"207", + "t208":"208", + "t209":"209", + "t210":"210", + "t211":"211", + "t212":"212", + "t213":"213", + "t214":"214", + "t215":"215", + "t216":"216", + "t217":"217", + "t218":"218", + "t219":"219", + "t220":"220", + "t221":"221", + "t222":"222", + "t223":"223", + "t224":"224", + "t225":"225", + "t226":"226", + "t227":"227", + "t228":"228", + "t229":"229", + "t230":"230", + "t231":"231", + "t232":"232", + "t233":"233", + "t234":"234", + "t235":"235", + "t236":"236", + "t237":"237", + "t238":"238", + "t239":"239", + "t240":"240", + "t241":"241", + "t242":"242", + "t243":"243", + "t244":"244", + "t245":"245", + "t246":"246", + "t247":"247", + "t248":"248", + "t249":"249", + "t250":"250", + "t251":"251", + "t252":"252", + "t253":"253", + "t254":"254", + "t255":"255" + } + } + ] +} \ No newline at end of file diff --git a/srcbpatch/streamreplacer.cpp b/srcbpatch/streamreplacer.cpp index 47a9c59..e072ea4 100644 --- a/srcbpatch/streamreplacer.cpp +++ b/srcbpatch/streamreplacer.cpp @@ -158,8 +158,8 @@ namespace bpatch { class TrieNode { public: - tsl::robin_map > children; - std::string_view target; + std::unordered_map> children; + std::optional target; }; class Trie { @@ -180,21 +180,62 @@ namespace bpatch { node->target = value; } - [[nodiscard]] std::pair search(const std::string_view &key) { + [[nodiscard]] std::pair search(const std::string_view& cachedData) { + TrieNode *node = &root; + for (char c: cachedData) { + auto res = node->children.find(c); + if (res == node->children.end()) { + return std::make_pair(std::string_view(), none); + } + node = res->second.get(); + } + + // full match + if (node->target) { + return std::make_pair(node->target.value(), full); + } + // partial + return {std::string_view(), partial}; + } + + void Eod() { + lastNode = &root; + } + + [[nodiscard]] std::pair accumulateSearch(const char key) { + TrieNode *node = lastNode; + auto res = node->children.find(key); + if (res == node->children.end()) { + lastNode = &root; + return std::make_pair(std::string_view(), none); + } + node = res->second.get(); + // full match + if (node->target) { + return std::make_pair(node->target.value(), full); + } + // partial + lastNode = node; + return {std::string_view(), partial}; + } + + [[nodiscard]] std::pair accumulateSearch(const std::string_view &key) { TrieNode *node = lastNode; for (char c: key) { auto res = node->children.find(c); if (res == node->children.end()) { - if (node == &root) { - lastNode = &root; - return std::make_pair(std::string_view(), none); - } - lastNode = node; - return {"", partial}; + lastNode = &root; + return std::make_pair(std::string_view(), none); } node = res->second.get(); } - return {node->target, full}; + // full match + if (node->target) { + return std::make_pair(node->target.value(), full); + } + // partial + lastNode = node; + return {std::string_view(), partial}; } }; @@ -274,6 +315,7 @@ namespace bpatch { CleanTheCache(1); } } + trie_.Eod(); pNext_->DoReplacements(toProcess, true); } From 4010dc08185bc555a75bd9db56260fddc6589b6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D0=BC=D0=B8=D1=80=20=D0=A7?= =?UTF-8?q?=D0=B8=D0=B6?= Date: Sun, 15 Sep 2024 19:01:48 +0200 Subject: [PATCH 03/16] from hex works --- IntegrationTests/scripts/fromhex8bytes.json | 813 -------------------- srcbpatch/streamreplacer.cpp | 230 +++--- 2 files changed, 142 insertions(+), 901 deletions(-) delete mode 100644 IntegrationTests/scripts/fromhex8bytes.json diff --git a/IntegrationTests/scripts/fromhex8bytes.json b/IntegrationTests/scripts/fromhex8bytes.json deleted file mode 100644 index 625fc6e..0000000 --- a/IntegrationTests/scripts/fromhex8bytes.json +++ /dev/null @@ -1,813 +0,0 @@ -{ - "dictionary": { - "hexadecimal": { - "0": ["00", "01", "02", "03", "04", "05", "06", "07", "08"], - "1": ["01", "01", "02", "03", "04", "05", "06", "07", "08"], - "2": ["02", "01", "02", "03", "04", "05", "06", "07", "08"], - "3": ["03", "01", "02", "03", "04", "05", "06", "07", "08"], - "4": ["04", "01", "02", "03", "04", "05", "06", "07", "08"], - "5": ["05", "01", "02", "03", "04", "05", "06", "07", "08"], - "6": ["06", "01", "02", "03", "04", "05", "06", "07", "08"], - "7": ["07", "01", "02", "03", "04", "05", "06", "07", "08"], - "8": ["08", "01", "02", "03", "04", "05", "06", "07", "08"], - "9": ["09", "01", "02", "03", "04", "05", "06", "07", "08"], - "10": ["0A", "01", "02", "03", "04", "05", "06", "07", "08"], - "11": ["0B", "01", "02", "03", "04", "05", "06", "07", "08"], - "12": ["0C", "01", "02", "03", "04", "05", "06", "07", "08"], - "13": ["0D", "01", "02", "03", "04", "05", "06", "07", "08"], - "14": ["0E", "01", "02", "03", "04", "05", "06", "07", "08"], - "15": ["0F", "01", "02", "03", "04", "05", "06", "07", "08"], - "16": ["10", "01", "02", "03", "04", "05", "06", "07", "08"], - "17": ["11", "01", "02", "03", "04", "05", "06", "07", "08"], - "18": ["12", "01", "02", "03", "04", "05", "06", "07", "08"], - "19": ["13", "01", "02", "03", "04", "05", "06", "07", "08"], - "20": ["14", "01", "02", "03", "04", "05", "06", "07", "08"], - "21": ["15", "01", "02", "03", "04", "05", "06", "07", "08"], - "22": ["16", "01", "02", "03", "04", "05", "06", "07", "08"], - "23": ["17", "01", "02", "03", "04", "05", "06", "07", "08"], - "24": ["18", "01", "02", "03", "04", "05", "06", "07", "08"], - "25": ["19", "01", "02", "03", "04", "05", "06", "07", "08"], - "26": ["1A", "01", "02", "03", "04", "05", "06", "07", "08"], - "27": ["1B", "01", "02", "03", "04", "05", "06", "07", "08"], - "28": ["1C", "01", "02", "03", "04", "05", "06", "07", "08"], - "29": ["1D", "01", "02", "03", "04", "05", "06", "07", "08"], - "30": ["1E", "01", "02", "03", "04", "05", "06", "07", "08"], - "31": ["1F", "01", "02", "03", "04", "05", "06", "07", "08"], - "32": ["20", "01", "02", "03", "04", "05", "06", "07", "08"], - "33": ["21", "01", "02", "03", "04", "05", "06", "07", "08"], - "34": ["22", "01", "02", "03", "04", "05", "06", "07", "08"], - "35": ["23", "01", "02", "03", "04", "05", "06", "07", "08"], - "36": ["24", "01", "02", "03", "04", "05", "06", "07", "08"], - "37": ["25", "01", "02", "03", "04", "05", "06", "07", "08"], - "38": ["26", "01", "02", "03", "04", "05", "06", "07", "08"], - "39": ["27", "01", "02", "03", "04", "05", "06", "07", "08"], - "40": ["28", "01", "02", "03", "04", "05", "06", "07", "08"], - "41": ["29", "01", "02", "03", "04", "05", "06", "07", "08"], - "42": ["2A", "01", "02", "03", "04", "05", "06", "07", "08"], - "43": ["2B", "01", "02", "03", "04", "05", "06", "07", "08"], - "44": ["2C", "01", "02", "03", "04", "05", "06", "07", "08"], - "45": ["2D", "01", "02", "03", "04", "05", "06", "07", "08"], - "46": ["2E", "01", "02", "03", "04", "05", "06", "07", "08"], - "47": ["2F", "01", "02", "03", "04", "05", "06", "07", "08"], - "48": ["30", "01", "02", "03", "04", "05", "06", "07", "08"], - "49": ["31", "01", "02", "03", "04", "05", "06", "07", "08"], - "50": ["32", "01", "02", "03", "04", "05", "06", "07", "08"], - "51": ["33", "01", "02", "03", "04", "05", "06", "07", "08"], - "52": ["34", "01", "02", "03", "04", "05", "06", "07", "08"], - "53": ["35", "01", "02", "03", "04", "05", "06", "07", "08"], - "54": ["36", "01", "02", "03", "04", "05", "06", "07", "08"], - "55": ["37", "01", "02", "03", "04", "05", "06", "07", "08"], - "56": ["38", "01", "02", "03", "04", "05", "06", "07", "08"], - "57": ["39", "01", "02", "03", "04", "05", "06", "07", "08"], - "58": ["3A", "01", "02", "03", "04", "05", "06", "07", "08"], - "59": ["3B", "01", "02", "03", "04", "05", "06", "07", "08"], - "60": ["3C", "01", "02", "03", "04", "05", "06", "07", "08"], - "61": ["3D", "01", "02", "03", "04", "05", "06", "07", "08"], - "62": ["3E", "01", "02", "03", "04", "05", "06", "07", "08"], - "63": ["3F", "01", "02", "03", "04", "05", "06", "07", "08"], - "64": ["40", "01", "02", "03", "04", "05", "06", "07", "08"], - "65": ["41", "01", "02", "03", "04", "05", "06", "07", "08"], - "66": ["42", "01", "02", "03", "04", "05", "06", "07", "08"], - "67": ["43", "01", "02", "03", "04", "05", "06", "07", "08"], - "68": ["44", "01", "02", "03", "04", "05", "06", "07", "08"], - "69": ["45", "01", "02", "03", "04", "05", "06", "07", "08"], - "70": ["46", "01", "02", "03", "04", "05", "06", "07", "08"], - "71": ["47", "01", "02", "03", "04", "05", "06", "07", "08"], - "72": ["48", "01", "02", "03", "04", "05", "06", "07", "08"], - "73": ["49", "01", "02", "03", "04", "05", "06", "07", "08"], - "74": ["4A", "01", "02", "03", "04", "05", "06", "07", "08"], - "75": ["4B", "01", "02", "03", "04", "05", "06", "07", "08"], - "76": ["4C", "01", "02", "03", "04", "05", "06", "07", "08"], - "77": ["4D", "01", "02", "03", "04", "05", "06", "07", "08"], - "78": ["4E", "01", "02", "03", "04", "05", "06", "07", "08"], - "79": ["4F", "01", "02", "03", "04", "05", "06", "07", "08"], - "80": ["50", "01", "02", "03", "04", "05", "06", "07", "08"], - "81": ["51", "01", "02", "03", "04", "05", "06", "07", "08"], - "82": ["52", "01", "02", "03", "04", "05", "06", "07", "08"], - "83": ["53", "01", "02", "03", "04", "05", "06", "07", "08"], - "84": ["54", "01", "02", "03", "04", "05", "06", "07", "08"], - "85": ["55", "01", "02", "03", "04", "05", "06", "07", "08"], - "86": ["56", "01", "02", "03", "04", "05", "06", "07", "08"], - "87": ["57", "01", "02", "03", "04", "05", "06", "07", "08"], - "88": ["58", "01", "02", "03", "04", "05", "06", "07", "08"], - "89": ["59", "01", "02", "03", "04", "05", "06", "07", "08"], - "90": ["5A", "01", "02", "03", "04", "05", "06", "07", "08"], - "91": ["5B", "01", "02", "03", "04", "05", "06", "07", "08"], - "92": ["5C", "01", "02", "03", "04", "05", "06", "07", "08"], - "93": ["5D", "01", "02", "03", "04", "05", "06", "07", "08"], - "94": ["5E", "01", "02", "03", "04", "05", "06", "07", "08"], - "95": ["5F", "01", "02", "03", "04", "05", "06", "07", "08"], - "96": ["60", "01", "02", "03", "04", "05", "06", "07", "08"], - "97": ["61", "01", "02", "03", "04", "05", "06", "07", "08"], - "98": ["62", "01", "02", "03", "04", "05", "06", "07", "08"], - "99": ["63", "01", "02", "03", "04", "05", "06", "07", "08"], - "100": ["64", "01", "02", "03", "04", "05", "06", "07", "08"], - "101": ["65", "01", "02", "03", "04", "05", "06", "07", "08"], - "102": ["66", "01", "02", "03", "04", "05", "06", "07", "08"], - "103": ["67", "01", "02", "03", "04", "05", "06", "07", "08"], - "104": ["68", "01", "02", "03", "04", "05", "06", "07", "08"], - "105": ["69", "01", "02", "03", "04", "05", "06", "07", "08"], - "106": ["6A", "01", "02", "03", "04", "05", "06", "07", "08"], - "107": ["6B", "01", "02", "03", "04", "05", "06", "07", "08"], - "108": ["6C", "01", "02", "03", "04", "05", "06", "07", "08"], - "109": ["6D", "01", "02", "03", "04", "05", "06", "07", "08"], - "110": ["6E", "01", "02", "03", "04", "05", "06", "07", "08"], - "111": ["6F", "01", "02", "03", "04", "05", "06", "07", "08"], - "112": ["70", "01", "02", "03", "04", "05", "06", "07", "08"], - "113": ["71", "01", "02", "03", "04", "05", "06", "07", "08"], - "114": ["72", "01", "02", "03", "04", "05", "06", "07", "08"], - "115": ["73", "01", "02", "03", "04", "05", "06", "07", "08"], - "116": ["74", "01", "02", "03", "04", "05", "06", "07", "08"], - "117": ["75", "01", "02", "03", "04", "05", "06", "07", "08"], - "118": ["76", "01", "02", "03", "04", "05", "06", "07", "08"], - "119": ["77", "01", "02", "03", "04", "05", "06", "07", "08"], - "120": ["78", "01", "02", "03", "04", "05", "06", "07", "08"], - "121": ["79", "01", "02", "03", "04", "05", "06", "07", "08"], - "122": ["7A", "01", "02", "03", "04", "05", "06", "07", "08"], - "123": ["7B", "01", "02", "03", "04", "05", "06", "07", "08"], - "124": ["7C", "01", "02", "03", "04", "05", "06", "07", "08"], - "125": ["7D", "01", "02", "03", "04", "05", "06", "07", "08"], - "126": ["7E", "01", "02", "03", "04", "05", "06", "07", "08"], - "127": ["7F", "01", "02", "03", "04", "05", "06", "07", "08"], - "128": ["80", "01", "02", "03", "04", "05", "06", "07", "08"], - "129": ["81", "01", "02", "03", "04", "05", "06", "07", "08"], - "130": ["82", "01", "02", "03", "04", "05", "06", "07", "08"], - "131": ["83", "01", "02", "03", "04", "05", "06", "07", "08"], - "132": ["84", "01", "02", "03", "04", "05", "06", "07", "08"], - "133": ["85", "01", "02", "03", "04", "05", "06", "07", "08"], - "134": ["86", "01", "02", "03", "04", "05", "06", "07", "08"], - "135": ["87", "01", "02", "03", "04", "05", "06", "07", "08"], - "136": ["88", "01", "02", "03", "04", "05", "06", "07", "08"], - "137": ["89", "01", "02", "03", "04", "05", "06", "07", "08"], - "138": ["8A", "01", "02", "03", "04", "05", "06", "07", "08"], - "139": ["8B", "01", "02", "03", "04", "05", "06", "07", "08"], - "140": ["8C", "01", "02", "03", "04", "05", "06", "07", "08"], - "141": ["8D", "01", "02", "03", "04", "05", "06", "07", "08"], - "142": ["8E", "01", "02", "03", "04", "05", "06", "07", "08"], - "143": ["8F", "01", "02", "03", "04", "05", "06", "07", "08"], - "144": ["90", "01", "02", "03", "04", "05", "06", "07", "08"], - "145": ["91", "01", "02", "03", "04", "05", "06", "07", "08"], - "146": ["92", "01", "02", "03", "04", "05", "06", "07", "08"], - "147": ["93", "01", "02", "03", "04", "05", "06", "07", "08"], - "148": ["94", "01", "02", "03", "04", "05", "06", "07", "08"], - "149": ["95", "01", "02", "03", "04", "05", "06", "07", "08"], - "150": ["96", "01", "02", "03", "04", "05", "06", "07", "08"], - "151": ["97", "01", "02", "03", "04", "05", "06", "07", "08"], - "152": ["98", "01", "02", "03", "04", "05", "06", "07", "08"], - "153": ["99", "01", "02", "03", "04", "05", "06", "07", "08"], - "154": ["9A", "01", "02", "03", "04", "05", "06", "07", "08"], - "155": ["9B", "01", "02", "03", "04", "05", "06", "07", "08"], - "156": ["9C", "01", "02", "03", "04", "05", "06", "07", "08"], - "157": ["9D", "01", "02", "03", "04", "05", "06", "07", "08"], - "158": ["9E", "01", "02", "03", "04", "05", "06", "07", "08"], - "159": ["9F", "01", "02", "03", "04", "05", "06", "07", "08"], - "160": ["A0", "01", "02", "03", "04", "05", "06", "07", "08"], - "161": ["A1", "01", "02", "03", "04", "05", "06", "07", "08"], - "162": ["A2", "01", "02", "03", "04", "05", "06", "07", "08"], - "163": ["A3", "01", "02", "03", "04", "05", "06", "07", "08"], - "164": ["A4", "01", "02", "03", "04", "05", "06", "07", "08"], - "165": ["A5", "01", "02", "03", "04", "05", "06", "07", "08"], - "166": ["A6", "01", "02", "03", "04", "05", "06", "07", "08"], - "167": ["A7", "01", "02", "03", "04", "05", "06", "07", "08"], - "168": ["A8", "01", "02", "03", "04", "05", "06", "07", "08"], - "169": ["A9", "01", "02", "03", "04", "05", "06", "07", "08"], - "170": ["AA", "01", "02", "03", "04", "05", "06", "07", "08"], - "171": ["AB", "01", "02", "03", "04", "05", "06", "07", "08"], - "172": ["AC", "01", "02", "03", "04", "05", "06", "07", "08"], - "173": ["AD", "01", "02", "03", "04", "05", "06", "07", "08"], - "174": ["AE", "01", "02", "03", "04", "05", "06", "07", "08"], - "175": ["AF", "01", "02", "03", "04", "05", "06", "07", "08"], - "176": ["B0", "01", "02", "03", "04", "05", "06", "07", "08"], - "177": ["B1", "01", "02", "03", "04", "05", "06", "07", "08"], - "178": ["B2", "01", "02", "03", "04", "05", "06", "07", "08"], - "179": ["B3", "01", "02", "03", "04", "05", "06", "07", "08"], - "180": ["B4", "01", "02", "03", "04", "05", "06", "07", "08"], - "181": ["B5", "01", "02", "03", "04", "05", "06", "07", "08"], - "182": ["B6", "01", "02", "03", "04", "05", "06", "07", "08"], - "183": ["B7", "01", "02", "03", "04", "05", "06", "07", "08"], - "184": ["B8", "01", "02", "03", "04", "05", "06", "07", "08"], - "185": ["B9", "01", "02", "03", "04", "05", "06", "07", "08"], - "186": ["BA", "01", "02", "03", "04", "05", "06", "07", "08"], - "187": ["BB", "01", "02", "03", "04", "05", "06", "07", "08"], - "188": ["BC", "01", "02", "03", "04", "05", "06", "07", "08"], - "189": ["BD", "01", "02", "03", "04", "05", "06", "07", "08"], - "190": ["BE", "01", "02", "03", "04", "05", "06", "07", "08"], - "191": ["BF", "01", "02", "03", "04", "05", "06", "07", "08"], - "192": ["C0", "01", "02", "03", "04", "05", "06", "07", "08"], - "193": ["C1", "01", "02", "03", "04", "05", "06", "07", "08"], - "194": ["C2", "01", "02", "03", "04", "05", "06", "07", "08"], - "195": ["C3", "01", "02", "03", "04", "05", "06", "07", "08"], - "196": ["C4", "01", "02", "03", "04", "05", "06", "07", "08"], - "197": ["C5", "01", "02", "03", "04", "05", "06", "07", "08"], - "198": ["C6", "01", "02", "03", "04", "05", "06", "07", "08"], - "199": ["C7", "01", "02", "03", "04", "05", "06", "07", "08"], - "200": ["C8", "01", "02", "03", "04", "05", "06", "07", "08"], - "201": ["C9", "01", "02", "03", "04", "05", "06", "07", "08"], - "202": ["CA", "01", "02", "03", "04", "05", "06", "07", "08"], - "203": ["CB", "01", "02", "03", "04", "05", "06", "07", "08"], - "204": ["CC", "01", "02", "03", "04", "05", "06", "07", "08"], - "205": ["CD", "01", "02", "03", "04", "05", "06", "07", "08"], - "206": ["CE", "01", "02", "03", "04", "05", "06", "07", "08"], - "207": ["CF", "01", "02", "03", "04", "05", "06", "07", "08"], - "208": ["D0", "01", "02", "03", "04", "05", "06", "07", "08"], - "209": ["D1", "01", "02", "03", "04", "05", "06", "07", "08"], - "210": ["D2", "01", "02", "03", "04", "05", "06", "07", "08"], - "211": ["D3", "01", "02", "03", "04", "05", "06", "07", "08"], - "212": ["D4", "01", "02", "03", "04", "05", "06", "07", "08"], - "213": ["D5", "01", "02", "03", "04", "05", "06", "07", "08"], - "214": ["D6", "01", "02", "03", "04", "05", "06", "07", "08"], - "215": ["D7", "01", "02", "03", "04", "05", "06", "07", "08"], - "216": ["D8", "01", "02", "03", "04", "05", "06", "07", "08"], - "217": ["D9", "01", "02", "03", "04", "05", "06", "07", "08"], - "218": ["DA", "01", "02", "03", "04", "05", "06", "07", "08"], - "219": ["DB", "01", "02", "03", "04", "05", "06", "07", "08"], - "220": ["DC", "01", "02", "03", "04", "05", "06", "07", "08"], - "221": ["DD", "01", "02", "03", "04", "05", "06", "07", "08"], - "222": ["DE", "01", "02", "03", "04", "05", "06", "07", "08"], - "223": ["DF", "01", "02", "03", "04", "05", "06", "07", "08"], - "224": ["E0", "01", "02", "03", "04", "05", "06", "07", "08"], - "225": ["E1", "01", "02", "03", "04", "05", "06", "07", "08"], - "226": ["E2", "01", "02", "03", "04", "05", "06", "07", "08"], - "227": ["E3", "01", "02", "03", "04", "05", "06", "07", "08"], - "228": ["E4", "01", "02", "03", "04", "05", "06", "07", "08"], - "229": ["E5", "01", "02", "03", "04", "05", "06", "07", "08"], - "230": ["E6", "01", "02", "03", "04", "05", "06", "07", "08"], - "231": ["E7", "01", "02", "03", "04", "05", "06", "07", "08"], - "232": ["E8", "01", "02", "03", "04", "05", "06", "07", "08"], - "233": ["E9", "01", "02", "03", "04", "05", "06", "07", "08"], - "234": ["EA", "01", "02", "03", "04", "05", "06", "07", "08"], - "235": ["EB", "01", "02", "03", "04", "05", "06", "07", "08"], - "236": ["EC", "01", "02", "03", "04", "05", "06", "07", "08"], - "237": ["ED", "01", "02", "03", "04", "05", "06", "07", "08"], - "238": ["EE", "01", "02", "03", "04", "05", "06", "07", "08"], - "239": ["EF", "01", "02", "03", "04", "05", "06", "07", "08"], - "240": ["F0", "01", "02", "03", "04", "05", "06", "07", "08"], - "241": ["F1", "01", "02", "03", "04", "05", "06", "07", "08"], - "242": ["F2", "01", "02", "03", "04", "05", "06", "07", "08"], - "243": ["F3", "01", "02", "03", "04", "05", "06", "07", "08"], - "244": ["F4", "01", "02", "03", "04", "05", "06", "07", "08"], - "245": ["F5", "01", "02", "03", "04", "05", "06", "07", "08"], - "246": ["F6", "01", "02", "03", "04", "05", "06", "07", "08"], - "247": ["F7", "01", "02", "03", "04", "05", "06", "07", "08"], - "248": ["F8", "01", "02", "03", "04", "05", "06", "07", "08"], - "249": ["F9", "01", "02", "03", "04", "05", "06", "07", "08"], - "250": ["FA", "01", "02", "03", "04", "05", "06", "07", "08"], - "251": ["FB", "01", "02", "03", "04", "05", "06", "07", "08"], - "252": ["FC", "01", "02", "03", "04", "05", "06", "07", "08"], - "253": ["FD", "01", "02", "03", "04", "05", "06", "07", "08"], - "254": ["FE", "01", "02", "03", "04", "05", "06", "07", "08"], - "255": ["FE", "10", "20", "30", "40", "50", "60", "70", "8F"] - }, - "text": - { - "a":"a", - "b":"b", - "c":"c", - "d":"d", - "e":"e", - "f":"f", - "A":"A", - "B":"B", - "C":"C", - "D":"D", - "E":"E", - "F":"F", - "LF":"\n", - "CR":"\r", - "tab":"\t", - "whitespace":" ", - "empty":"", - "t0":"00", - "t1":"01", - "t2":"02", - "t3":"03", - "t4":"04", - "t5":"05", - "t6":"06", - "t7":"07", - "t8":"08", - "t9":"09", - "t10":"0A", - "t11":"0B", - "t12":"0C", - "t13":"0D", - "t14":"0E", - "t15":"0F", - "t16":"10", - "t17":"11", - "t18":"12", - "t19":"13", - "t20":"14", - "t21":"15", - "t22":"16", - "t23":"17", - "t24":"18", - "t25":"19", - "t26":"1A", - "t27":"1B", - "t28":"1C", - "t29":"1D", - "t30":"1E", - "t31":"1F", - "t32":"20", - "t33":"21", - "t34":"22", - "t35":"23", - "t36":"24", - "t37":"25", - "t38":"26", - "t39":"27", - "t40":"28", - "t41":"29", - "t42":"2A", - "t43":"2B", - "t44":"2C", - "t45":"2D", - "t46":"2E", - "t47":"2F", - "t48":"30", - "t49":"31", - "t50":"32", - "t51":"33", - "t52":"34", - "t53":"35", - "t54":"36", - "t55":"37", - "t56":"38", - "t57":"39", - "t58":"3A", - "t59":"3B", - "t60":"3C", - "t61":"3D", - "t62":"3E", - "t63":"3F", - "t64":"40", - "t65":"41", - "t66":"42", - "t67":"43", - "t68":"44", - "t69":"45", - "t70":"46", - "t71":"47", - "t72":"48", - "t73":"49", - "t74":"4A", - "t75":"4B", - "t76":"4C", - "t77":"4D", - "t78":"4E", - "t79":"4F", - "t80":"50", - "t81":"51", - "t82":"52", - "t83":"53", - "t84":"54", - "t85":"55", - "t86":"56", - "t87":"57", - "t88":"58", - "t89":"59", - "t90":"5A", - "t91":"5B", - "t92":"5C", - "t93":"5D", - "t94":"5E", - "t95":"5F", - "t96":"60", - "t97":"61", - "t98":"62", - "t99":"63", - "t100":"64", - "t101":"65", - "t102":"66", - "t103":"67", - "t104":"68", - "t105":"69", - "t106":"6A", - "t107":"6B", - "t108":"6C", - "t109":"6D", - "t110":"6E", - "t111":"6F", - "t112":"70", - "t113":"71", - "t114":"72", - "t115":"73", - "t116":"74", - "t117":"75", - "t118":"76", - "t119":"77", - "t120":"78", - "t121":"79", - "t122":"7A", - "t123":"7B", - "t124":"7C", - "t125":"7D", - "t126":"7E", - "t127":"7F", - "t128":"80", - "t129":"81", - "t130":"82", - "t131":"83", - "t132":"84", - "t133":"85", - "t134":"86", - "t135":"87", - "t136":"88", - "t137":"89", - "t138":"8A", - "t139":"8B", - "t140":"8C", - "t141":"8D", - "t142":"8E", - "t143":"8F", - "t144":"90", - "t145":"91", - "t146":"92", - "t147":"93", - "t148":"94", - "t149":"95", - "t150":"96", - "t151":"97", - "t152":"98", - "t153":"99", - "t154":"9A", - "t155":"9B", - "t156":"9C", - "t157":"9D", - "t158":"9E", - "t159":"9F", - "t160":"A0", - "t161":"A1", - "t162":"A2", - "t163":"A3", - "t164":"A4", - "t165":"A5", - "t166":"A6", - "t167":"A7", - "t168":"A8", - "t169":"A9", - "t170":"AA", - "t171":"AB", - "t172":"AC", - "t173":"AD", - "t174":"AE", - "t175":"AF", - "t176":"B0", - "t177":"B1", - "t178":"B2", - "t179":"B3", - "t180":"B4", - "t181":"B5", - "t182":"B6", - "t183":"B7", - "t184":"B8", - "t185":"B9", - "t186":"BA", - "t187":"BB", - "t188":"BC", - "t189":"BD", - "t190":"BE", - "t191":"BF", - "t192":"C0", - "t193":"C1", - "t194":"C2", - "t195":"C3", - "t196":"C4", - "t197":"C5", - "t198":"C6", - "t199":"C7", - "t200":"C8", - "t201":"C9", - "t202":"CA", - "t203":"CB", - "t204":"CC", - "t205":"CD", - "t206":"CE", - "t207":"CF", - "t208":"D0", - "t209":"D1", - "t210":"D2", - "t211":"D3", - "t212":"D4", - "t213":"D5", - "t214":"D6", - "t215":"D7", - "t216":"D8", - "t217":"D9", - "t218":"DA", - "t219":"DB", - "t220":"DC", - "t221":"DD", - "t222":"DE", - "t223":"DF", - "t224":"E0", - "t225":"E1", - "t226":"E2", - "t227":"E3", - "t228":"E4", - "t229":"E5", - "t230":"E6", - "t231":"E7", - "t232":"E8", - "t233":"E9", - "t234":"EA", - "t235":"EB", - "t236":"EC", - "t237":"ED", - "t238":"EE", - "t239":"EF", - "t240":"F0", - "t241":"F1", - "t242":"F2", - "t243":"F3", - "t244":"F4", - "t245":"F5", - "t246":"F6", - "t247":"F7", - "t248":"F8", - "t249":"F9", - "t250":"FA", - "t251":"FB", - "t252":"FC", - "t253":"FD", - "t254":"FE", - "t255":"FF" - } - }, - "todo": [ - { - "replace": - { - "LF":"empty", - "CR":"empty", - "tab":"empty", - "whitespace":"empty", - "a":"A", - "b":"B", - "c":"C", - "d":"D", - "e":"E", - "f":"F" - }, - "replace": { - "t0":"0", - "t1":"1", - "t2":"2", - "t3":"3", - "t4":"4", - "t5":"5", - "t6":"6", - "t7":"7", - "t8":"8", - "t9":"9", - "t10":"10", - "t11":"11", - "t12":"12", - "t13":"13", - "t14":"14", - "t15":"15", - "t16":"16", - "t17":"17", - "t18":"18", - "t19":"19", - "t20":"20", - "t21":"21", - "t22":"22", - "t23":"23", - "t24":"24", - "t25":"25", - "t26":"26", - "t27":"27", - "t28":"28", - "t29":"29", - "t30":"30", - "t31":"31", - "t32":"32", - "t33":"33", - "t34":"34", - "t35":"35", - "t36":"36", - "t37":"37", - "t38":"38", - "t39":"39", - "t40":"40", - "t41":"41", - "t42":"42", - "t43":"43", - "t44":"44", - "t45":"45", - "t46":"46", - "t47":"47", - "t48":"48", - "t49":"49", - "t50":"50", - "t51":"51", - "t52":"52", - "t53":"53", - "t54":"54", - "t55":"55", - "t56":"56", - "t57":"57", - "t58":"58", - "t59":"59", - "t60":"60", - "t61":"61", - "t62":"62", - "t63":"63", - "t64":"64", - "t65":"65", - "t66":"66", - "t67":"67", - "t68":"68", - "t69":"69", - "t70":"70", - "t71":"71", - "t72":"72", - "t73":"73", - "t74":"74", - "t75":"75", - "t76":"76", - "t77":"77", - "t78":"78", - "t79":"79", - "t80":"80", - "t81":"81", - "t82":"82", - "t83":"83", - "t84":"84", - "t85":"85", - "t86":"86", - "t87":"87", - "t88":"88", - "t89":"89", - "t90":"90", - "t91":"91", - "t92":"92", - "t93":"93", - "t94":"94", - "t95":"95", - "t96":"96", - "t97":"97", - "t98":"98", - "t99":"99", - "t100":"100", - "t101":"101", - "t102":"102", - "t103":"103", - "t104":"104", - "t105":"105", - "t106":"106", - "t107":"107", - "t108":"108", - "t109":"109", - "t110":"110", - "t111":"111", - "t112":"112", - "t113":"113", - "t114":"114", - "t115":"115", - "t116":"116", - "t117":"117", - "t118":"118", - "t119":"119", - "t120":"120", - "t121":"121", - "t122":"122", - "t123":"123", - "t124":"124", - "t125":"125", - "t126":"126", - "t127":"127", - "t128":"128", - "t129":"129", - "t130":"130", - "t131":"131", - "t132":"132", - "t133":"133", - "t134":"134", - "t135":"135", - "t136":"136", - "t137":"137", - "t138":"138", - "t139":"139", - "t140":"140", - "t141":"141", - "t142":"142", - "t143":"143", - "t144":"144", - "t145":"145", - "t146":"146", - "t147":"147", - "t148":"148", - "t149":"149", - "t150":"150", - "t151":"151", - "t152":"152", - "t153":"153", - "t154":"154", - "t155":"155", - "t156":"156", - "t157":"157", - "t158":"158", - "t159":"159", - "t160":"160", - "t161":"161", - "t162":"162", - "t163":"163", - "t164":"164", - "t165":"165", - "t166":"166", - "t167":"167", - "t168":"168", - "t169":"169", - "t170":"170", - "t171":"171", - "t172":"172", - "t173":"173", - "t174":"174", - "t175":"175", - "t176":"176", - "t177":"177", - "t178":"178", - "t179":"179", - "t180":"180", - "t181":"181", - "t182":"182", - "t183":"183", - "t184":"184", - "t185":"185", - "t186":"186", - "t187":"187", - "t188":"188", - "t189":"189", - "t190":"190", - "t191":"191", - "t192":"192", - "t193":"193", - "t194":"194", - "t195":"195", - "t196":"196", - "t197":"197", - "t198":"198", - "t199":"199", - "t200":"200", - "t201":"201", - "t202":"202", - "t203":"203", - "t204":"204", - "t205":"205", - "t206":"206", - "t207":"207", - "t208":"208", - "t209":"209", - "t210":"210", - "t211":"211", - "t212":"212", - "t213":"213", - "t214":"214", - "t215":"215", - "t216":"216", - "t217":"217", - "t218":"218", - "t219":"219", - "t220":"220", - "t221":"221", - "t222":"222", - "t223":"223", - "t224":"224", - "t225":"225", - "t226":"226", - "t227":"227", - "t228":"228", - "t229":"229", - "t230":"230", - "t231":"231", - "t232":"232", - "t233":"233", - "t234":"234", - "t235":"235", - "t236":"236", - "t237":"237", - "t238":"238", - "t239":"239", - "t240":"240", - "t241":"241", - "t242":"242", - "t243":"243", - "t244":"244", - "t245":"245", - "t246":"246", - "t247":"247", - "t248":"248", - "t249":"249", - "t250":"250", - "t251":"251", - "t252":"252", - "t253":"253", - "t254":"254", - "t255":"255" - } - } - ] -} \ No newline at end of file diff --git a/srcbpatch/streamreplacer.cpp b/srcbpatch/streamreplacer.cpp index e072ea4..a9d363e 100644 --- a/srcbpatch/streamreplacer.cpp +++ b/srcbpatch/streamreplacer.cpp @@ -246,117 +246,171 @@ namespace bpatch { /// O - |-- ... | - o /// |--SRC N TRG N | /// - class ChoiceReplacer final : public ReplacerWithNext { - typedef struct { - span src_; - span trg_; - } ChoiceReplacerPair; + class ChoiceReplacer final : public ReplacerWithNext +{ + typedef struct + { + span src_; + span trg_; + }ChoiceReplacerPair; - public: - /// - /// creating ChoiceReplacer from provided pairs - /// - /// vector os source & target pairs - ChoiceReplacer(StreamReplacerChoice &choice) { - size_t bufferSize = 0; // to allocate buffer - const size_t sz = choice.size(); - for (size_t i = 0; i < sz; ++i) { - auto &vPair = choice[i]; - const size_t sourceSize = vPair.first->access().size(); - if (bufferSize < sourceSize) { - bufferSize = sourceSize; // calculate necessary buffer size - } - const span &src = vPair.first->access(); - const span &trg = vPair.second->access(); - trie_.insert(string_view(src.data(), src.size()), string_view(trg.data(), trg.size())); +public: + /// + /// creating ChoiceReplacer from provided pairs + /// + /// vector os source & target pairs + ChoiceReplacer(StreamReplacerChoice& choice) + { + size_t bufferSize = 0; // to allocate buffer + const size_t sz = choice.size(); + rpairs_.resize(sz); + for (size_t i = 0; i < sz; ++i) + { + auto& vPair = choice[i]; // copy from + auto& rpair = rpairs_[i];// copy to + + rpair.src_ = vPair.first->access(); + const size_t sourceSize = rpair.src_.size(); + if (bufferSize < sourceSize) + { + bufferSize = sourceSize; // calculate necessary buffer size } - cachedData_.resize(bufferSize); + rpair.trg_ = vPair.second->access(); } - void DoReplacements(const char toProcess, const bool aEod) const override; + cachedData_.resize(bufferSize); + } - protected: - /// - /// Sends target to next replacers, and resets partial match index to zero - /// - /// the array we need to send - void SendAndResetPartialMatch(const span &target) const { - for (const char c: target) { - pNext_->DoReplacements(c, false); + void DoReplacements(const char toProcess, const bool aEod) const override; + +protected: + /// + /// check for partial or full match of the data from cachedData_ + /// with any of lexemes sequentially + /// and provides type of the match and index if found + /// + /// search in pairs from this index + /// what type of match we want to find : only full or partial also + /// bool: partial, bool: full, size_t: index + tuple FindMatch(const size_t indexFrom, const bool fullOnly) const + { + for (size_t i = indexFrom; i < rpairs_.size(); ++i) + { + const auto& srcSpan = rpairs_[i].src_; + const size_t cmpLength = (srcSpan.size() > cachedAmount_) ? cachedAmount_ : srcSpan.size(); + + if (0 == memcmp(srcSpan.data(), cachedData_.data(), cmpLength)) + { // match + if (cmpLength == srcSpan.size()) + { + return {false, true, i}; + } + if (!fullOnly) + { + return {true, false, i}; + } } + // continue - no match here } + return {false, false, 0}; + } - /// - /// Clean srcMatchedLength bytes of cache from the beginning - /// - /// number of bytes we have to clear - void CleanTheCache(size_t srcMatchedLength) const { - shift_left(cachedData_.data(), - cachedData_.data() + cachedAmount_, - static_cast::difference_type>( - srcMatchedLength)); - cachedAmount_ -= srcMatchedLength; + /// + /// Sends target to next replacers, and resets partial match index to zero + /// + /// the array we need to send + void SendAndResetPartialMatch(const span& target) const + { + for (const char c : target) + { + pNext_->DoReplacements(c, false); } + indexOfPartialMatch_ = 0; + } - /// - /// The end of the data sign has been received and the cached data need to be either send or replaced & send - /// - /// character received along with end of data sign - void DoReplacementsAtTheEndOfTheData(const char toProcess) const { - while (cachedAmount_ > 0) { - const auto [match, type] = trie_.search(std::string_view(cachedData_.data(), cachedAmount_)); - if (type == Trie::full) { - SendAndResetPartialMatch(match); - CleanTheCache(cachedAmount_); - } else // No full match -> send 1 char from cache - { - SendAndResetPartialMatch(std::span(cachedData_.data(), 1)); - CleanTheCache(1); - } + /// + /// Clean srcMatchedLength bytes of cache from the beginning + /// + /// number of bytes we have to clear + void CleanTheCache(size_t srcMatchedLength) const + { + shift_left(cachedData_.data(), + cachedData_.data() + cachedAmount_, + static_cast::difference_type>(srcMatchedLength)); + cachedAmount_ -= srcMatchedLength; + } + + /// + /// The end of the data sign has been received and the cached data need to be either send or replaced & send + /// + /// character received along with end of data sign + void DoReplacementsAtTheEndOfTheData(const char toProcess) const + { + while (cachedAmount_ > 0) + { + const auto [partialMatch, fullMatch, matchPairIndex] = FindMatch(indexOfPartialMatch_, true); + if (fullMatch) + { + const auto& rpair = rpairs_[matchPairIndex]; + SendAndResetPartialMatch(rpair.trg_); + CleanTheCache(rpair.src_.size()); + } + else // No full match -> send 1 char from cache + { + SendAndResetPartialMatch(std::span (cachedData_.data(), 1)); + CleanTheCache(1); } - trie_.Eod(); - pNext_->DoReplacements(toProcess, true); } + pNext_->DoReplacements(toProcess, true); + } - protected: - // our pairs sorted by priority - only one of them could be replaced for concrete pos - mutable Trie trie_; +protected: + // our pairs sorted by priority - only one of them could be replaced for concrete pos + vector rpairs_; - mutable size_t cachedAmount_ = 0; // we cached this amount of data + mutable size_t cachedAmount_ = 0; // we cached this amount of data + mutable size_t indexOfPartialMatch_ = 0; // this index from rpairs_ represents last partial match - // this is used to hold temporary data while the logic is - // looking for the new beginning of the cached value - mutable vector cachedData_; - }; + // this is used to hold temporary data while the logic is + // looking for the new beginning of the cached value + mutable vector cachedData_; +}; - void ChoiceReplacer::DoReplacements(const char toProcess, const bool aEod) const { - if (nullptr == pNext_) { - throw logic_error("Replacement chain has been broken. Communicate with maintainer"); - } +void ChoiceReplacer::DoReplacements(const char toProcess, const bool aEod) const +{ + if (nullptr == pNext_) + { + throw logic_error("Replacement chain has been broken. Communicate with maintainer"); + } + + if (aEod) [[unlikely]] + { + DoReplacementsAtTheEndOfTheData(toProcess); + return; + } - if (aEod) [[unlikely]] + cachedData_[cachedAmount_++] = toProcess; + while (cachedAmount_ > 0) + { + const auto [partialMatch, fullMatch, matchPairIndex] = FindMatch(indexOfPartialMatch_, false); + if (fullMatch) { - DoReplacementsAtTheEndOfTheData(toProcess); + const auto& rpair = rpairs_[matchPairIndex]; + SendAndResetPartialMatch(rpair.trg_); + CleanTheCache(rpair.src_.size()); return; } - - cachedData_[cachedAmount_++] = toProcess; - while (cachedAmount_ > 0) { - const auto [match, type] = trie_.search(std::string_view(cachedData_.data(), cachedAmount_)); - if (type == Trie::full) { - SendAndResetPartialMatch(match); - CleanTheCache(cachedAmount_); - return; - } - if (type == Trie::partial) { - return; - } - // No any match -> send 1 char from cache - SendAndResetPartialMatch(std::span(cachedData_.data(), 1)); - CleanTheCache(1); + if (partialMatch) + { + indexOfPartialMatch_ = matchPairIndex; + return; } + // No any match -> send 1 char from cache + SendAndResetPartialMatch(std::span (cachedData_.data(), 1)); + CleanTheCache(1); } +} namespace { static std::string_view warningDuplicatePattern( From 2f7a9e5720a87858cf102cabd3772565dac35b2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D0=BC=D0=B8=D1=80=20=D0=A7?= =?UTF-8?q?=D0=B8=D0=B6?= Date: Sun, 15 Sep 2024 21:43:37 +0200 Subject: [PATCH 04/16] fix --- srcbpatch/streamreplacer.cpp | 250 ++++++++++++++--------------------- 1 file changed, 99 insertions(+), 151 deletions(-) diff --git a/srcbpatch/streamreplacer.cpp b/srcbpatch/streamreplacer.cpp index a9d363e..9842365 100644 --- a/srcbpatch/streamreplacer.cpp +++ b/srcbpatch/streamreplacer.cpp @@ -160,6 +160,7 @@ namespace bpatch { public: std::unordered_map> children; std::optional target; + size_t depth = 0; }; class Trie { @@ -171,31 +172,32 @@ namespace bpatch { void insert(std::string_view key, std::string_view value) { TrieNode *node = &root; - for (char c: key) { + for (char c : key) { if (!node->children[c]) { node->children[c] = std::make_unique(); } node = node->children[c].get(); } node->target = value; + node->depth = key.size(); } - [[nodiscard]] std::pair search(const std::string_view& cachedData) { + [[nodiscard]] std::tuple searchFull(const std::string_view& cachedData) { TrieNode *node = &root; for (char c: cachedData) { auto res = node->children.find(c); if (res == node->children.end()) { - return std::make_pair(std::string_view(), none); + return std::make_tuple(std::string_view(), 0, none); } node = res->second.get(); + // full match + if (node->target) { + return std::make_tuple(node->target.value(), node->depth, full); + } } - // full match - if (node->target) { - return std::make_pair(node->target.value(), full); - } // partial - return {std::string_view(), partial}; + return {std::string_view(), 0, partial}; } void Eod() { @@ -246,171 +248,117 @@ namespace bpatch { /// O - |-- ... | - o /// |--SRC N TRG N | /// - class ChoiceReplacer final : public ReplacerWithNext -{ - typedef struct - { - span src_; - span trg_; - }ChoiceReplacerPair; + class ChoiceReplacer final : public ReplacerWithNext { + typedef struct { + span src_; + span trg_; + } ChoiceReplacerPair; -public: - /// - /// creating ChoiceReplacer from provided pairs - /// - /// vector os source & target pairs - ChoiceReplacer(StreamReplacerChoice& choice) - { - size_t bufferSize = 0; // to allocate buffer - const size_t sz = choice.size(); - rpairs_.resize(sz); - for (size_t i = 0; i < sz; ++i) - { - auto& vPair = choice[i]; // copy from - auto& rpair = rpairs_[i];// copy to - - rpair.src_ = vPair.first->access(); - const size_t sourceSize = rpair.src_.size(); - if (bufferSize < sourceSize) - { - bufferSize = sourceSize; // calculate necessary buffer size + public: + /// + /// creating ChoiceReplacer from provided pairs + /// + /// vector os source & target pairs + ChoiceReplacer(StreamReplacerChoice &choice) { + size_t bufferSize = 0; // to allocate buffer + const size_t sz = choice.size(); + for (size_t i = 0; i < sz; ++i) { + auto &vPair = choice[i]; + const size_t sourceSize = vPair.first->access().size(); + if (bufferSize < sourceSize) { + bufferSize = sourceSize; // calculate necessary buffer size + } + const span &src = vPair.first->access(); + const span &trg = vPair.second->access(); + trie_.insert(string_view(src.data(), src.size()), string_view(trg.data(), trg.size())); } - rpair.trg_ = vPair.second->access(); + cachedData_.resize(bufferSize); } - cachedData_.resize(bufferSize); - } - - void DoReplacements(const char toProcess, const bool aEod) const override; - -protected: - /// - /// check for partial or full match of the data from cachedData_ - /// with any of lexemes sequentially - /// and provides type of the match and index if found - /// - /// search in pairs from this index - /// what type of match we want to find : only full or partial also - /// bool: partial, bool: full, size_t: index - tuple FindMatch(const size_t indexFrom, const bool fullOnly) const - { - for (size_t i = indexFrom; i < rpairs_.size(); ++i) - { - const auto& srcSpan = rpairs_[i].src_; - const size_t cmpLength = (srcSpan.size() > cachedAmount_) ? cachedAmount_ : srcSpan.size(); + void DoReplacements(const char toProcess, const bool aEod) const override; - if (0 == memcmp(srcSpan.data(), cachedData_.data(), cmpLength)) - { // match - if (cmpLength == srcSpan.size()) - { - return {false, true, i}; - } - if (!fullOnly) - { - return {true, false, i}; - } + protected: + /// + /// Sends target to next replacers, and resets partial match index to zero + /// + /// the array we need to send + void SendAndResetPartialMatch(const span &target) const { + for (const char c: target) { + pNext_->DoReplacements(c, false); } - // continue - no match here } - return {false, false, 0}; - } - /// - /// Sends target to next replacers, and resets partial match index to zero - /// - /// the array we need to send - void SendAndResetPartialMatch(const span& target) const - { - for (const char c : target) - { - pNext_->DoReplacements(c, false); + /// + /// Clean srcMatchedLength bytes of cache from the beginning + /// + /// number of bytes we have to clear + void CleanTheCache(size_t srcMatchedLength) const { + shift_left(cachedData_.data(), + cachedData_.data() + cachedAmount_, + static_cast::difference_type>( + srcMatchedLength)); + cachedAmount_ -= srcMatchedLength; + trie_.Eod(); } - indexOfPartialMatch_ = 0; - } - /// - /// Clean srcMatchedLength bytes of cache from the beginning - /// - /// number of bytes we have to clear - void CleanTheCache(size_t srcMatchedLength) const - { - shift_left(cachedData_.data(), - cachedData_.data() + cachedAmount_, - static_cast::difference_type>(srcMatchedLength)); - cachedAmount_ -= srcMatchedLength; - } - - /// - /// The end of the data sign has been received and the cached data need to be either send or replaced & send - /// - /// character received along with end of data sign - void DoReplacementsAtTheEndOfTheData(const char toProcess) const - { - while (cachedAmount_ > 0) - { - const auto [partialMatch, fullMatch, matchPairIndex] = FindMatch(indexOfPartialMatch_, true); - if (fullMatch) - { - const auto& rpair = rpairs_[matchPairIndex]; - SendAndResetPartialMatch(rpair.trg_); - CleanTheCache(rpair.src_.size()); - } - else // No full match -> send 1 char from cache - { - SendAndResetPartialMatch(std::span (cachedData_.data(), 1)); - CleanTheCache(1); + /// + /// The end of the data sign has been received and the cached data need to be either send or replaced & send + /// + /// character received along with end of data sign + void DoReplacementsAtTheEndOfTheData(const char toProcess) const { + while (cachedAmount_ > 0) { + const auto [match, srcSize, type] = trie_.searchFull(std::string_view(cachedData_.data(), cachedAmount_)); + if (type == Trie::full) { + SendAndResetPartialMatch(match); + CleanTheCache(srcSize); + } else // No full match -> send 1 char from cache + { + SendAndResetPartialMatch(std::span(cachedData_.data(), 1)); + CleanTheCache(1); + } } + pNext_->DoReplacements(toProcess, true); } - pNext_->DoReplacements(toProcess, true); - } -protected: - // our pairs sorted by priority - only one of them could be replaced for concrete pos - vector rpairs_; - - mutable size_t cachedAmount_ = 0; // we cached this amount of data - mutable size_t indexOfPartialMatch_ = 0; // this index from rpairs_ represents last partial match + protected: + // our pairs sorted by priority - only one of them could be replaced for concrete pos + mutable Trie trie_; - // this is used to hold temporary data while the logic is - // looking for the new beginning of the cached value - mutable vector cachedData_; -}; + mutable size_t cachedAmount_ = 0; // we cached this amount of data -void ChoiceReplacer::DoReplacements(const char toProcess, const bool aEod) const -{ - if (nullptr == pNext_) - { - throw logic_error("Replacement chain has been broken. Communicate with maintainer"); - } + // this is used to hold temporary data while the logic is + // looking for the new beginning of the cached value + mutable vector cachedData_; + }; - if (aEod) [[unlikely]] - { - DoReplacementsAtTheEndOfTheData(toProcess); - return; - } + void ChoiceReplacer::DoReplacements(const char toProcess, const bool aEod) const { + if (nullptr == pNext_) { + throw logic_error("Replacement chain has been broken. Communicate with maintainer"); + } - cachedData_[cachedAmount_++] = toProcess; - while (cachedAmount_ > 0) - { - const auto [partialMatch, fullMatch, matchPairIndex] = FindMatch(indexOfPartialMatch_, false); - if (fullMatch) + if (aEod) [[unlikely]] { - const auto& rpair = rpairs_[matchPairIndex]; - SendAndResetPartialMatch(rpair.trg_); - CleanTheCache(rpair.src_.size()); + DoReplacementsAtTheEndOfTheData(toProcess); return; } - if (partialMatch) - { - indexOfPartialMatch_ = matchPairIndex; - return; + + cachedData_[cachedAmount_++] = toProcess; + while (cachedAmount_ > 0) { + const auto [match, srcSize, type] = trie_.searchFull(std::string_view(cachedData_.data(), cachedAmount_)); + if (type == Trie::full) { + SendAndResetPartialMatch(match); + CleanTheCache(srcSize); + return; + } + if (type == Trie::partial) { + return; + } + // No any match -> send 1 char from cache + SendAndResetPartialMatch(std::span(cachedData_.data(), 1)); + CleanTheCache(1); } - // No any match -> send 1 char from cache - SendAndResetPartialMatch(std::span (cachedData_.data(), 1)); - CleanTheCache(1); } -} namespace { static std::string_view warningDuplicatePattern( @@ -466,7 +414,7 @@ void ChoiceReplacer::DoReplacements(const char toProcess, const bool aEod) const cachedData_[cachedAmount_++] = toProcess; if (cachedAmount_ == cachedData_.size()) { string_view key(cachedData_.data(), cachedAmount_); - if (auto [target, type] = trie_.search(key); type == Trie::full) { + if (auto [target, srcSize, type] = trie_.searchFull(key); type == Trie::full) { for (char c: target) { pNext_->DoReplacements(c, false); } From 10a94f62fa4d1a4c4e29563fe1eb4118b5fe55c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D0=BC=D0=B8=D1=80=20=D0=A7?= =?UTF-8?q?=D0=B8=D0=B6?= Date: Sun, 15 Sep 2024 22:52:44 +0200 Subject: [PATCH 05/16] implemented Trie for UniformLexemeReplacer --- CMakeLists.txt | 1 - IntegrationTests/scripts/fromhex8bytes.json | 813 ++++++++++++++++++ srcbpatch/CMakeLists.txt | 3 + srcbpatch/streamreplacer.cpp | 885 ++++++++++---------- srcbpatch/trie.cpp | 34 + srcbpatch/trie.h | 31 + 6 files changed, 1326 insertions(+), 441 deletions(-) create mode 100644 IntegrationTests/scripts/fromhex8bytes.json create mode 100644 srcbpatch/trie.cpp create mode 100644 srcbpatch/trie.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2722500..a88885e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -146,7 +146,6 @@ add_subdirectory(src${pname}) add_subdirectory(test${pname}) target_link_libraries(${pname} src${pname} ${wild_library}) -target_include_directories(${pname} PUBLIC ${robin_map_SOURCE_DIR}/include) # Console commands for building on Windows with Visual Studio # !!!!!!!!!!!!! diff --git a/IntegrationTests/scripts/fromhex8bytes.json b/IntegrationTests/scripts/fromhex8bytes.json new file mode 100644 index 0000000..625fc6e --- /dev/null +++ b/IntegrationTests/scripts/fromhex8bytes.json @@ -0,0 +1,813 @@ +{ + "dictionary": { + "hexadecimal": { + "0": ["00", "01", "02", "03", "04", "05", "06", "07", "08"], + "1": ["01", "01", "02", "03", "04", "05", "06", "07", "08"], + "2": ["02", "01", "02", "03", "04", "05", "06", "07", "08"], + "3": ["03", "01", "02", "03", "04", "05", "06", "07", "08"], + "4": ["04", "01", "02", "03", "04", "05", "06", "07", "08"], + "5": ["05", "01", "02", "03", "04", "05", "06", "07", "08"], + "6": ["06", "01", "02", "03", "04", "05", "06", "07", "08"], + "7": ["07", "01", "02", "03", "04", "05", "06", "07", "08"], + "8": ["08", "01", "02", "03", "04", "05", "06", "07", "08"], + "9": ["09", "01", "02", "03", "04", "05", "06", "07", "08"], + "10": ["0A", "01", "02", "03", "04", "05", "06", "07", "08"], + "11": ["0B", "01", "02", "03", "04", "05", "06", "07", "08"], + "12": ["0C", "01", "02", "03", "04", "05", "06", "07", "08"], + "13": ["0D", "01", "02", "03", "04", "05", "06", "07", "08"], + "14": ["0E", "01", "02", "03", "04", "05", "06", "07", "08"], + "15": ["0F", "01", "02", "03", "04", "05", "06", "07", "08"], + "16": ["10", "01", "02", "03", "04", "05", "06", "07", "08"], + "17": ["11", "01", "02", "03", "04", "05", "06", "07", "08"], + "18": ["12", "01", "02", "03", "04", "05", "06", "07", "08"], + "19": ["13", "01", "02", "03", "04", "05", "06", "07", "08"], + "20": ["14", "01", "02", "03", "04", "05", "06", "07", "08"], + "21": ["15", "01", "02", "03", "04", "05", "06", "07", "08"], + "22": ["16", "01", "02", "03", "04", "05", "06", "07", "08"], + "23": ["17", "01", "02", "03", "04", "05", "06", "07", "08"], + "24": ["18", "01", "02", "03", "04", "05", "06", "07", "08"], + "25": ["19", "01", "02", "03", "04", "05", "06", "07", "08"], + "26": ["1A", "01", "02", "03", "04", "05", "06", "07", "08"], + "27": ["1B", "01", "02", "03", "04", "05", "06", "07", "08"], + "28": ["1C", "01", "02", "03", "04", "05", "06", "07", "08"], + "29": ["1D", "01", "02", "03", "04", "05", "06", "07", "08"], + "30": ["1E", "01", "02", "03", "04", "05", "06", "07", "08"], + "31": ["1F", "01", "02", "03", "04", "05", "06", "07", "08"], + "32": ["20", "01", "02", "03", "04", "05", "06", "07", "08"], + "33": ["21", "01", "02", "03", "04", "05", "06", "07", "08"], + "34": ["22", "01", "02", "03", "04", "05", "06", "07", "08"], + "35": ["23", "01", "02", "03", "04", "05", "06", "07", "08"], + "36": ["24", "01", "02", "03", "04", "05", "06", "07", "08"], + "37": ["25", "01", "02", "03", "04", "05", "06", "07", "08"], + "38": ["26", "01", "02", "03", "04", "05", "06", "07", "08"], + "39": ["27", "01", "02", "03", "04", "05", "06", "07", "08"], + "40": ["28", "01", "02", "03", "04", "05", "06", "07", "08"], + "41": ["29", "01", "02", "03", "04", "05", "06", "07", "08"], + "42": ["2A", "01", "02", "03", "04", "05", "06", "07", "08"], + "43": ["2B", "01", "02", "03", "04", "05", "06", "07", "08"], + "44": ["2C", "01", "02", "03", "04", "05", "06", "07", "08"], + "45": ["2D", "01", "02", "03", "04", "05", "06", "07", "08"], + "46": ["2E", "01", "02", "03", "04", "05", "06", "07", "08"], + "47": ["2F", "01", "02", "03", "04", "05", "06", "07", "08"], + "48": ["30", "01", "02", "03", "04", "05", "06", "07", "08"], + "49": ["31", "01", "02", "03", "04", "05", "06", "07", "08"], + "50": ["32", "01", "02", "03", "04", "05", "06", "07", "08"], + "51": ["33", "01", "02", "03", "04", "05", "06", "07", "08"], + "52": ["34", "01", "02", "03", "04", "05", "06", "07", "08"], + "53": ["35", "01", "02", "03", "04", "05", "06", "07", "08"], + "54": ["36", "01", "02", "03", "04", "05", "06", "07", "08"], + "55": ["37", "01", "02", "03", "04", "05", "06", "07", "08"], + "56": ["38", "01", "02", "03", "04", "05", "06", "07", "08"], + "57": ["39", "01", "02", "03", "04", "05", "06", "07", "08"], + "58": ["3A", "01", "02", "03", "04", "05", "06", "07", "08"], + "59": ["3B", "01", "02", "03", "04", "05", "06", "07", "08"], + "60": ["3C", "01", "02", "03", "04", "05", "06", "07", "08"], + "61": ["3D", "01", "02", "03", "04", "05", "06", "07", "08"], + "62": ["3E", "01", "02", "03", "04", "05", "06", "07", "08"], + "63": ["3F", "01", "02", "03", "04", "05", "06", "07", "08"], + "64": ["40", "01", "02", "03", "04", "05", "06", "07", "08"], + "65": ["41", "01", "02", "03", "04", "05", "06", "07", "08"], + "66": ["42", "01", "02", "03", "04", "05", "06", "07", "08"], + "67": ["43", "01", "02", "03", "04", "05", "06", "07", "08"], + "68": ["44", "01", "02", "03", "04", "05", "06", "07", "08"], + "69": ["45", "01", "02", "03", "04", "05", "06", "07", "08"], + "70": ["46", "01", "02", "03", "04", "05", "06", "07", "08"], + "71": ["47", "01", "02", "03", "04", "05", "06", "07", "08"], + "72": ["48", "01", "02", "03", "04", "05", "06", "07", "08"], + "73": ["49", "01", "02", "03", "04", "05", "06", "07", "08"], + "74": ["4A", "01", "02", "03", "04", "05", "06", "07", "08"], + "75": ["4B", "01", "02", "03", "04", "05", "06", "07", "08"], + "76": ["4C", "01", "02", "03", "04", "05", "06", "07", "08"], + "77": ["4D", "01", "02", "03", "04", "05", "06", "07", "08"], + "78": ["4E", "01", "02", "03", "04", "05", "06", "07", "08"], + "79": ["4F", "01", "02", "03", "04", "05", "06", "07", "08"], + "80": ["50", "01", "02", "03", "04", "05", "06", "07", "08"], + "81": ["51", "01", "02", "03", "04", "05", "06", "07", "08"], + "82": ["52", "01", "02", "03", "04", "05", "06", "07", "08"], + "83": ["53", "01", "02", "03", "04", "05", "06", "07", "08"], + "84": ["54", "01", "02", "03", "04", "05", "06", "07", "08"], + "85": ["55", "01", "02", "03", "04", "05", "06", "07", "08"], + "86": ["56", "01", "02", "03", "04", "05", "06", "07", "08"], + "87": ["57", "01", "02", "03", "04", "05", "06", "07", "08"], + "88": ["58", "01", "02", "03", "04", "05", "06", "07", "08"], + "89": ["59", "01", "02", "03", "04", "05", "06", "07", "08"], + "90": ["5A", "01", "02", "03", "04", "05", "06", "07", "08"], + "91": ["5B", "01", "02", "03", "04", "05", "06", "07", "08"], + "92": ["5C", "01", "02", "03", "04", "05", "06", "07", "08"], + "93": ["5D", "01", "02", "03", "04", "05", "06", "07", "08"], + "94": ["5E", "01", "02", "03", "04", "05", "06", "07", "08"], + "95": ["5F", "01", "02", "03", "04", "05", "06", "07", "08"], + "96": ["60", "01", "02", "03", "04", "05", "06", "07", "08"], + "97": ["61", "01", "02", "03", "04", "05", "06", "07", "08"], + "98": ["62", "01", "02", "03", "04", "05", "06", "07", "08"], + "99": ["63", "01", "02", "03", "04", "05", "06", "07", "08"], + "100": ["64", "01", "02", "03", "04", "05", "06", "07", "08"], + "101": ["65", "01", "02", "03", "04", "05", "06", "07", "08"], + "102": ["66", "01", "02", "03", "04", "05", "06", "07", "08"], + "103": ["67", "01", "02", "03", "04", "05", "06", "07", "08"], + "104": ["68", "01", "02", "03", "04", "05", "06", "07", "08"], + "105": ["69", "01", "02", "03", "04", "05", "06", "07", "08"], + "106": ["6A", "01", "02", "03", "04", "05", "06", "07", "08"], + "107": ["6B", "01", "02", "03", "04", "05", "06", "07", "08"], + "108": ["6C", "01", "02", "03", "04", "05", "06", "07", "08"], + "109": ["6D", "01", "02", "03", "04", "05", "06", "07", "08"], + "110": ["6E", "01", "02", "03", "04", "05", "06", "07", "08"], + "111": ["6F", "01", "02", "03", "04", "05", "06", "07", "08"], + "112": ["70", "01", "02", "03", "04", "05", "06", "07", "08"], + "113": ["71", "01", "02", "03", "04", "05", "06", "07", "08"], + "114": ["72", "01", "02", "03", "04", "05", "06", "07", "08"], + "115": ["73", "01", "02", "03", "04", "05", "06", "07", "08"], + "116": ["74", "01", "02", "03", "04", "05", "06", "07", "08"], + "117": ["75", "01", "02", "03", "04", "05", "06", "07", "08"], + "118": ["76", "01", "02", "03", "04", "05", "06", "07", "08"], + "119": ["77", "01", "02", "03", "04", "05", "06", "07", "08"], + "120": ["78", "01", "02", "03", "04", "05", "06", "07", "08"], + "121": ["79", "01", "02", "03", "04", "05", "06", "07", "08"], + "122": ["7A", "01", "02", "03", "04", "05", "06", "07", "08"], + "123": ["7B", "01", "02", "03", "04", "05", "06", "07", "08"], + "124": ["7C", "01", "02", "03", "04", "05", "06", "07", "08"], + "125": ["7D", "01", "02", "03", "04", "05", "06", "07", "08"], + "126": ["7E", "01", "02", "03", "04", "05", "06", "07", "08"], + "127": ["7F", "01", "02", "03", "04", "05", "06", "07", "08"], + "128": ["80", "01", "02", "03", "04", "05", "06", "07", "08"], + "129": ["81", "01", "02", "03", "04", "05", "06", "07", "08"], + "130": ["82", "01", "02", "03", "04", "05", "06", "07", "08"], + "131": ["83", "01", "02", "03", "04", "05", "06", "07", "08"], + "132": ["84", "01", "02", "03", "04", "05", "06", "07", "08"], + "133": ["85", "01", "02", "03", "04", "05", "06", "07", "08"], + "134": ["86", "01", "02", "03", "04", "05", "06", "07", "08"], + "135": ["87", "01", "02", "03", "04", "05", "06", "07", "08"], + "136": ["88", "01", "02", "03", "04", "05", "06", "07", "08"], + "137": ["89", "01", "02", "03", "04", "05", "06", "07", "08"], + "138": ["8A", "01", "02", "03", "04", "05", "06", "07", "08"], + "139": ["8B", "01", "02", "03", "04", "05", "06", "07", "08"], + "140": ["8C", "01", "02", "03", "04", "05", "06", "07", "08"], + "141": ["8D", "01", "02", "03", "04", "05", "06", "07", "08"], + "142": ["8E", "01", "02", "03", "04", "05", "06", "07", "08"], + "143": ["8F", "01", "02", "03", "04", "05", "06", "07", "08"], + "144": ["90", "01", "02", "03", "04", "05", "06", "07", "08"], + "145": ["91", "01", "02", "03", "04", "05", "06", "07", "08"], + "146": ["92", "01", "02", "03", "04", "05", "06", "07", "08"], + "147": ["93", "01", "02", "03", "04", "05", "06", "07", "08"], + "148": ["94", "01", "02", "03", "04", "05", "06", "07", "08"], + "149": ["95", "01", "02", "03", "04", "05", "06", "07", "08"], + "150": ["96", "01", "02", "03", "04", "05", "06", "07", "08"], + "151": ["97", "01", "02", "03", "04", "05", "06", "07", "08"], + "152": ["98", "01", "02", "03", "04", "05", "06", "07", "08"], + "153": ["99", "01", "02", "03", "04", "05", "06", "07", "08"], + "154": ["9A", "01", "02", "03", "04", "05", "06", "07", "08"], + "155": ["9B", "01", "02", "03", "04", "05", "06", "07", "08"], + "156": ["9C", "01", "02", "03", "04", "05", "06", "07", "08"], + "157": ["9D", "01", "02", "03", "04", "05", "06", "07", "08"], + "158": ["9E", "01", "02", "03", "04", "05", "06", "07", "08"], + "159": ["9F", "01", "02", "03", "04", "05", "06", "07", "08"], + "160": ["A0", "01", "02", "03", "04", "05", "06", "07", "08"], + "161": ["A1", "01", "02", "03", "04", "05", "06", "07", "08"], + "162": ["A2", "01", "02", "03", "04", "05", "06", "07", "08"], + "163": ["A3", "01", "02", "03", "04", "05", "06", "07", "08"], + "164": ["A4", "01", "02", "03", "04", "05", "06", "07", "08"], + "165": ["A5", "01", "02", "03", "04", "05", "06", "07", "08"], + "166": ["A6", "01", "02", "03", "04", "05", "06", "07", "08"], + "167": ["A7", "01", "02", "03", "04", "05", "06", "07", "08"], + "168": ["A8", "01", "02", "03", "04", "05", "06", "07", "08"], + "169": ["A9", "01", "02", "03", "04", "05", "06", "07", "08"], + "170": ["AA", "01", "02", "03", "04", "05", "06", "07", "08"], + "171": ["AB", "01", "02", "03", "04", "05", "06", "07", "08"], + "172": ["AC", "01", "02", "03", "04", "05", "06", "07", "08"], + "173": ["AD", "01", "02", "03", "04", "05", "06", "07", "08"], + "174": ["AE", "01", "02", "03", "04", "05", "06", "07", "08"], + "175": ["AF", "01", "02", "03", "04", "05", "06", "07", "08"], + "176": ["B0", "01", "02", "03", "04", "05", "06", "07", "08"], + "177": ["B1", "01", "02", "03", "04", "05", "06", "07", "08"], + "178": ["B2", "01", "02", "03", "04", "05", "06", "07", "08"], + "179": ["B3", "01", "02", "03", "04", "05", "06", "07", "08"], + "180": ["B4", "01", "02", "03", "04", "05", "06", "07", "08"], + "181": ["B5", "01", "02", "03", "04", "05", "06", "07", "08"], + "182": ["B6", "01", "02", "03", "04", "05", "06", "07", "08"], + "183": ["B7", "01", "02", "03", "04", "05", "06", "07", "08"], + "184": ["B8", "01", "02", "03", "04", "05", "06", "07", "08"], + "185": ["B9", "01", "02", "03", "04", "05", "06", "07", "08"], + "186": ["BA", "01", "02", "03", "04", "05", "06", "07", "08"], + "187": ["BB", "01", "02", "03", "04", "05", "06", "07", "08"], + "188": ["BC", "01", "02", "03", "04", "05", "06", "07", "08"], + "189": ["BD", "01", "02", "03", "04", "05", "06", "07", "08"], + "190": ["BE", "01", "02", "03", "04", "05", "06", "07", "08"], + "191": ["BF", "01", "02", "03", "04", "05", "06", "07", "08"], + "192": ["C0", "01", "02", "03", "04", "05", "06", "07", "08"], + "193": ["C1", "01", "02", "03", "04", "05", "06", "07", "08"], + "194": ["C2", "01", "02", "03", "04", "05", "06", "07", "08"], + "195": ["C3", "01", "02", "03", "04", "05", "06", "07", "08"], + "196": ["C4", "01", "02", "03", "04", "05", "06", "07", "08"], + "197": ["C5", "01", "02", "03", "04", "05", "06", "07", "08"], + "198": ["C6", "01", "02", "03", "04", "05", "06", "07", "08"], + "199": ["C7", "01", "02", "03", "04", "05", "06", "07", "08"], + "200": ["C8", "01", "02", "03", "04", "05", "06", "07", "08"], + "201": ["C9", "01", "02", "03", "04", "05", "06", "07", "08"], + "202": ["CA", "01", "02", "03", "04", "05", "06", "07", "08"], + "203": ["CB", "01", "02", "03", "04", "05", "06", "07", "08"], + "204": ["CC", "01", "02", "03", "04", "05", "06", "07", "08"], + "205": ["CD", "01", "02", "03", "04", "05", "06", "07", "08"], + "206": ["CE", "01", "02", "03", "04", "05", "06", "07", "08"], + "207": ["CF", "01", "02", "03", "04", "05", "06", "07", "08"], + "208": ["D0", "01", "02", "03", "04", "05", "06", "07", "08"], + "209": ["D1", "01", "02", "03", "04", "05", "06", "07", "08"], + "210": ["D2", "01", "02", "03", "04", "05", "06", "07", "08"], + "211": ["D3", "01", "02", "03", "04", "05", "06", "07", "08"], + "212": ["D4", "01", "02", "03", "04", "05", "06", "07", "08"], + "213": ["D5", "01", "02", "03", "04", "05", "06", "07", "08"], + "214": ["D6", "01", "02", "03", "04", "05", "06", "07", "08"], + "215": ["D7", "01", "02", "03", "04", "05", "06", "07", "08"], + "216": ["D8", "01", "02", "03", "04", "05", "06", "07", "08"], + "217": ["D9", "01", "02", "03", "04", "05", "06", "07", "08"], + "218": ["DA", "01", "02", "03", "04", "05", "06", "07", "08"], + "219": ["DB", "01", "02", "03", "04", "05", "06", "07", "08"], + "220": ["DC", "01", "02", "03", "04", "05", "06", "07", "08"], + "221": ["DD", "01", "02", "03", "04", "05", "06", "07", "08"], + "222": ["DE", "01", "02", "03", "04", "05", "06", "07", "08"], + "223": ["DF", "01", "02", "03", "04", "05", "06", "07", "08"], + "224": ["E0", "01", "02", "03", "04", "05", "06", "07", "08"], + "225": ["E1", "01", "02", "03", "04", "05", "06", "07", "08"], + "226": ["E2", "01", "02", "03", "04", "05", "06", "07", "08"], + "227": ["E3", "01", "02", "03", "04", "05", "06", "07", "08"], + "228": ["E4", "01", "02", "03", "04", "05", "06", "07", "08"], + "229": ["E5", "01", "02", "03", "04", "05", "06", "07", "08"], + "230": ["E6", "01", "02", "03", "04", "05", "06", "07", "08"], + "231": ["E7", "01", "02", "03", "04", "05", "06", "07", "08"], + "232": ["E8", "01", "02", "03", "04", "05", "06", "07", "08"], + "233": ["E9", "01", "02", "03", "04", "05", "06", "07", "08"], + "234": ["EA", "01", "02", "03", "04", "05", "06", "07", "08"], + "235": ["EB", "01", "02", "03", "04", "05", "06", "07", "08"], + "236": ["EC", "01", "02", "03", "04", "05", "06", "07", "08"], + "237": ["ED", "01", "02", "03", "04", "05", "06", "07", "08"], + "238": ["EE", "01", "02", "03", "04", "05", "06", "07", "08"], + "239": ["EF", "01", "02", "03", "04", "05", "06", "07", "08"], + "240": ["F0", "01", "02", "03", "04", "05", "06", "07", "08"], + "241": ["F1", "01", "02", "03", "04", "05", "06", "07", "08"], + "242": ["F2", "01", "02", "03", "04", "05", "06", "07", "08"], + "243": ["F3", "01", "02", "03", "04", "05", "06", "07", "08"], + "244": ["F4", "01", "02", "03", "04", "05", "06", "07", "08"], + "245": ["F5", "01", "02", "03", "04", "05", "06", "07", "08"], + "246": ["F6", "01", "02", "03", "04", "05", "06", "07", "08"], + "247": ["F7", "01", "02", "03", "04", "05", "06", "07", "08"], + "248": ["F8", "01", "02", "03", "04", "05", "06", "07", "08"], + "249": ["F9", "01", "02", "03", "04", "05", "06", "07", "08"], + "250": ["FA", "01", "02", "03", "04", "05", "06", "07", "08"], + "251": ["FB", "01", "02", "03", "04", "05", "06", "07", "08"], + "252": ["FC", "01", "02", "03", "04", "05", "06", "07", "08"], + "253": ["FD", "01", "02", "03", "04", "05", "06", "07", "08"], + "254": ["FE", "01", "02", "03", "04", "05", "06", "07", "08"], + "255": ["FE", "10", "20", "30", "40", "50", "60", "70", "8F"] + }, + "text": + { + "a":"a", + "b":"b", + "c":"c", + "d":"d", + "e":"e", + "f":"f", + "A":"A", + "B":"B", + "C":"C", + "D":"D", + "E":"E", + "F":"F", + "LF":"\n", + "CR":"\r", + "tab":"\t", + "whitespace":" ", + "empty":"", + "t0":"00", + "t1":"01", + "t2":"02", + "t3":"03", + "t4":"04", + "t5":"05", + "t6":"06", + "t7":"07", + "t8":"08", + "t9":"09", + "t10":"0A", + "t11":"0B", + "t12":"0C", + "t13":"0D", + "t14":"0E", + "t15":"0F", + "t16":"10", + "t17":"11", + "t18":"12", + "t19":"13", + "t20":"14", + "t21":"15", + "t22":"16", + "t23":"17", + "t24":"18", + "t25":"19", + "t26":"1A", + "t27":"1B", + "t28":"1C", + "t29":"1D", + "t30":"1E", + "t31":"1F", + "t32":"20", + "t33":"21", + "t34":"22", + "t35":"23", + "t36":"24", + "t37":"25", + "t38":"26", + "t39":"27", + "t40":"28", + "t41":"29", + "t42":"2A", + "t43":"2B", + "t44":"2C", + "t45":"2D", + "t46":"2E", + "t47":"2F", + "t48":"30", + "t49":"31", + "t50":"32", + "t51":"33", + "t52":"34", + "t53":"35", + "t54":"36", + "t55":"37", + "t56":"38", + "t57":"39", + "t58":"3A", + "t59":"3B", + "t60":"3C", + "t61":"3D", + "t62":"3E", + "t63":"3F", + "t64":"40", + "t65":"41", + "t66":"42", + "t67":"43", + "t68":"44", + "t69":"45", + "t70":"46", + "t71":"47", + "t72":"48", + "t73":"49", + "t74":"4A", + "t75":"4B", + "t76":"4C", + "t77":"4D", + "t78":"4E", + "t79":"4F", + "t80":"50", + "t81":"51", + "t82":"52", + "t83":"53", + "t84":"54", + "t85":"55", + "t86":"56", + "t87":"57", + "t88":"58", + "t89":"59", + "t90":"5A", + "t91":"5B", + "t92":"5C", + "t93":"5D", + "t94":"5E", + "t95":"5F", + "t96":"60", + "t97":"61", + "t98":"62", + "t99":"63", + "t100":"64", + "t101":"65", + "t102":"66", + "t103":"67", + "t104":"68", + "t105":"69", + "t106":"6A", + "t107":"6B", + "t108":"6C", + "t109":"6D", + "t110":"6E", + "t111":"6F", + "t112":"70", + "t113":"71", + "t114":"72", + "t115":"73", + "t116":"74", + "t117":"75", + "t118":"76", + "t119":"77", + "t120":"78", + "t121":"79", + "t122":"7A", + "t123":"7B", + "t124":"7C", + "t125":"7D", + "t126":"7E", + "t127":"7F", + "t128":"80", + "t129":"81", + "t130":"82", + "t131":"83", + "t132":"84", + "t133":"85", + "t134":"86", + "t135":"87", + "t136":"88", + "t137":"89", + "t138":"8A", + "t139":"8B", + "t140":"8C", + "t141":"8D", + "t142":"8E", + "t143":"8F", + "t144":"90", + "t145":"91", + "t146":"92", + "t147":"93", + "t148":"94", + "t149":"95", + "t150":"96", + "t151":"97", + "t152":"98", + "t153":"99", + "t154":"9A", + "t155":"9B", + "t156":"9C", + "t157":"9D", + "t158":"9E", + "t159":"9F", + "t160":"A0", + "t161":"A1", + "t162":"A2", + "t163":"A3", + "t164":"A4", + "t165":"A5", + "t166":"A6", + "t167":"A7", + "t168":"A8", + "t169":"A9", + "t170":"AA", + "t171":"AB", + "t172":"AC", + "t173":"AD", + "t174":"AE", + "t175":"AF", + "t176":"B0", + "t177":"B1", + "t178":"B2", + "t179":"B3", + "t180":"B4", + "t181":"B5", + "t182":"B6", + "t183":"B7", + "t184":"B8", + "t185":"B9", + "t186":"BA", + "t187":"BB", + "t188":"BC", + "t189":"BD", + "t190":"BE", + "t191":"BF", + "t192":"C0", + "t193":"C1", + "t194":"C2", + "t195":"C3", + "t196":"C4", + "t197":"C5", + "t198":"C6", + "t199":"C7", + "t200":"C8", + "t201":"C9", + "t202":"CA", + "t203":"CB", + "t204":"CC", + "t205":"CD", + "t206":"CE", + "t207":"CF", + "t208":"D0", + "t209":"D1", + "t210":"D2", + "t211":"D3", + "t212":"D4", + "t213":"D5", + "t214":"D6", + "t215":"D7", + "t216":"D8", + "t217":"D9", + "t218":"DA", + "t219":"DB", + "t220":"DC", + "t221":"DD", + "t222":"DE", + "t223":"DF", + "t224":"E0", + "t225":"E1", + "t226":"E2", + "t227":"E3", + "t228":"E4", + "t229":"E5", + "t230":"E6", + "t231":"E7", + "t232":"E8", + "t233":"E9", + "t234":"EA", + "t235":"EB", + "t236":"EC", + "t237":"ED", + "t238":"EE", + "t239":"EF", + "t240":"F0", + "t241":"F1", + "t242":"F2", + "t243":"F3", + "t244":"F4", + "t245":"F5", + "t246":"F6", + "t247":"F7", + "t248":"F8", + "t249":"F9", + "t250":"FA", + "t251":"FB", + "t252":"FC", + "t253":"FD", + "t254":"FE", + "t255":"FF" + } + }, + "todo": [ + { + "replace": + { + "LF":"empty", + "CR":"empty", + "tab":"empty", + "whitespace":"empty", + "a":"A", + "b":"B", + "c":"C", + "d":"D", + "e":"E", + "f":"F" + }, + "replace": { + "t0":"0", + "t1":"1", + "t2":"2", + "t3":"3", + "t4":"4", + "t5":"5", + "t6":"6", + "t7":"7", + "t8":"8", + "t9":"9", + "t10":"10", + "t11":"11", + "t12":"12", + "t13":"13", + "t14":"14", + "t15":"15", + "t16":"16", + "t17":"17", + "t18":"18", + "t19":"19", + "t20":"20", + "t21":"21", + "t22":"22", + "t23":"23", + "t24":"24", + "t25":"25", + "t26":"26", + "t27":"27", + "t28":"28", + "t29":"29", + "t30":"30", + "t31":"31", + "t32":"32", + "t33":"33", + "t34":"34", + "t35":"35", + "t36":"36", + "t37":"37", + "t38":"38", + "t39":"39", + "t40":"40", + "t41":"41", + "t42":"42", + "t43":"43", + "t44":"44", + "t45":"45", + "t46":"46", + "t47":"47", + "t48":"48", + "t49":"49", + "t50":"50", + "t51":"51", + "t52":"52", + "t53":"53", + "t54":"54", + "t55":"55", + "t56":"56", + "t57":"57", + "t58":"58", + "t59":"59", + "t60":"60", + "t61":"61", + "t62":"62", + "t63":"63", + "t64":"64", + "t65":"65", + "t66":"66", + "t67":"67", + "t68":"68", + "t69":"69", + "t70":"70", + "t71":"71", + "t72":"72", + "t73":"73", + "t74":"74", + "t75":"75", + "t76":"76", + "t77":"77", + "t78":"78", + "t79":"79", + "t80":"80", + "t81":"81", + "t82":"82", + "t83":"83", + "t84":"84", + "t85":"85", + "t86":"86", + "t87":"87", + "t88":"88", + "t89":"89", + "t90":"90", + "t91":"91", + "t92":"92", + "t93":"93", + "t94":"94", + "t95":"95", + "t96":"96", + "t97":"97", + "t98":"98", + "t99":"99", + "t100":"100", + "t101":"101", + "t102":"102", + "t103":"103", + "t104":"104", + "t105":"105", + "t106":"106", + "t107":"107", + "t108":"108", + "t109":"109", + "t110":"110", + "t111":"111", + "t112":"112", + "t113":"113", + "t114":"114", + "t115":"115", + "t116":"116", + "t117":"117", + "t118":"118", + "t119":"119", + "t120":"120", + "t121":"121", + "t122":"122", + "t123":"123", + "t124":"124", + "t125":"125", + "t126":"126", + "t127":"127", + "t128":"128", + "t129":"129", + "t130":"130", + "t131":"131", + "t132":"132", + "t133":"133", + "t134":"134", + "t135":"135", + "t136":"136", + "t137":"137", + "t138":"138", + "t139":"139", + "t140":"140", + "t141":"141", + "t142":"142", + "t143":"143", + "t144":"144", + "t145":"145", + "t146":"146", + "t147":"147", + "t148":"148", + "t149":"149", + "t150":"150", + "t151":"151", + "t152":"152", + "t153":"153", + "t154":"154", + "t155":"155", + "t156":"156", + "t157":"157", + "t158":"158", + "t159":"159", + "t160":"160", + "t161":"161", + "t162":"162", + "t163":"163", + "t164":"164", + "t165":"165", + "t166":"166", + "t167":"167", + "t168":"168", + "t169":"169", + "t170":"170", + "t171":"171", + "t172":"172", + "t173":"173", + "t174":"174", + "t175":"175", + "t176":"176", + "t177":"177", + "t178":"178", + "t179":"179", + "t180":"180", + "t181":"181", + "t182":"182", + "t183":"183", + "t184":"184", + "t185":"185", + "t186":"186", + "t187":"187", + "t188":"188", + "t189":"189", + "t190":"190", + "t191":"191", + "t192":"192", + "t193":"193", + "t194":"194", + "t195":"195", + "t196":"196", + "t197":"197", + "t198":"198", + "t199":"199", + "t200":"200", + "t201":"201", + "t202":"202", + "t203":"203", + "t204":"204", + "t205":"205", + "t206":"206", + "t207":"207", + "t208":"208", + "t209":"209", + "t210":"210", + "t211":"211", + "t212":"212", + "t213":"213", + "t214":"214", + "t215":"215", + "t216":"216", + "t217":"217", + "t218":"218", + "t219":"219", + "t220":"220", + "t221":"221", + "t222":"222", + "t223":"223", + "t224":"224", + "t225":"225", + "t226":"226", + "t227":"227", + "t228":"228", + "t229":"229", + "t230":"230", + "t231":"231", + "t232":"232", + "t233":"233", + "t234":"234", + "t235":"235", + "t236":"236", + "t237":"237", + "t238":"238", + "t239":"239", + "t240":"240", + "t241":"241", + "t242":"242", + "t243":"243", + "t244":"244", + "t245":"245", + "t246":"246", + "t247":"247", + "t248":"248", + "t249":"249", + "t250":"250", + "t251":"251", + "t252":"252", + "t253":"253", + "t254":"254", + "t255":"255" + } + } + ] +} \ No newline at end of file diff --git a/srcbpatch/CMakeLists.txt b/srcbpatch/CMakeLists.txt index b3446cc..6420327 100644 --- a/srcbpatch/CMakeLists.txt +++ b/srcbpatch/CMakeLists.txt @@ -21,6 +21,7 @@ set(SOURCE_FILES stdafx.cpp streamreplacer.cpp timemeasurer.cpp + trie.cpp ) set(HEADER_FILES actionscollection.h @@ -37,6 +38,7 @@ set(HEADER_FILES stdafx.h streamreplacer.h timemeasurer.h + trie.h ) # Define the executable target @@ -44,3 +46,4 @@ add_library(${PROJECT_NAME} ${SOURCE_FILES} ${HEADER_FILES}) # Precompiled header target_precompile_headers(${PROJECT_NAME} PRIVATE stdafx.h) +target_include_directories(${PROJECT_NAME} PUBLIC ${robin_map_SOURCE_DIR}/include) diff --git a/srcbpatch/streamreplacer.cpp b/srcbpatch/streamreplacer.cpp index 9842365..da11d57 100644 --- a/srcbpatch/streamreplacer.cpp +++ b/srcbpatch/streamreplacer.cpp @@ -2,530 +2,535 @@ #include "binarylexeme.h" #include "fileprocessing.h" #include "streamreplacer.h" +#include "trie.h" + +namespace bpatch +{ +using namespace std; + +//-------------------------------------------------- +/// +/// Replacer to last in chain. All incoming data should be trasferred to a Writer interface +/// +class WriterReplacer final : public StreamReplacer +{ +public: + WriterReplacer(Writer* const pWriter): pWriter_(pWriter) {}; + + virtual void DoReplacements(const char toProcess, const bool aEod) const override; + virtual void SetNextReplacer(std::unique_ptr&& pNext) override; +protected: + Writer* const pWriter_; +}; + + +void WriterReplacer::DoReplacements(const char toProcess, const bool aEod) const +{ + pWriter_->WriteCharacter(toProcess, aEod); +} + + +void WriterReplacer::SetNextReplacer(std::unique_ptr&&) +{ + throw logic_error("Writer Replacer should be unchangeable. Contact with maintainer."); +} + + +unique_ptr StreamReplacer::ReplacerLastInChain(Writer* const pWriter) +{ + return unique_ptr(new WriterReplacer(pWriter)); +} + +//-------------------------------------------------- + +/// +/// common part for set next replacer +/// +class ReplacerWithNext: public StreamReplacer +{ +protected: + /// to pass processing further + std::unique_ptr pNext_; + +public: + void SetNextReplacer(std::unique_ptr&& pNext) override + { + std::swap(pNext_, pNext); + } -#include - -namespace bpatch { - using namespace std; - - //-------------------------------------------------- - /// - /// Replacer to last in chain. All incoming data should be trasferred to a Writer interface - /// - class WriterReplacer final : public StreamReplacer { - public: - WriterReplacer(Writer *const pWriter): pWriter_(pWriter) { - }; +}; - virtual void DoReplacements(const char toProcess, const bool aEod) const override; - virtual void SetNextReplacer(std::unique_ptr &&pNext) override; +//-------------------------------------------------- +struct ReplacerPairHolder +{ + ReplacerPairHolder(unique_ptr& src, // what to replace + unique_ptr& trg) // to what + : src_(src) + , trg_(trg) + {} - protected: - Writer *const pWriter_; - }; + unique_ptr& src_; // what to replace + unique_ptr& trg_; // with what +}; - void WriterReplacer::DoReplacements(const char toProcess, const bool aEod) const { - pWriter_->WriteCharacter(toProcess, aEod); +//-------------------------------------------------- +class UsualReplacer final : public ReplacerWithNext +{ +public: + UsualReplacer(unique_ptr& src, // what to replace + unique_ptr& trg) // with what + : src_(src->access()) + , trg_(trg->access()) + { + cachedData_.resize(src_.size()); } + void DoReplacements(const char toProcess, const bool aEod) const override; - void WriterReplacer::SetNextReplacer(std::unique_ptr &&) { - throw logic_error("Writer Replacer should be unchangeable. Contact with maintainer."); - } +protected: + const span& src_; // what to replace + const span& trg_; // with what + mutable size_t cachedAmount_ = 0; // we cached this amount of data - unique_ptr StreamReplacer::ReplacerLastInChain(Writer *const pWriter) { - return unique_ptr(new WriterReplacer(pWriter)); - } - - //-------------------------------------------------- + // this is used to hold temporary data while the logic is + // looking for the new beginning of the cached value + mutable vector cachedData_; +}; - /// - /// common part for set next replacer - /// - class ReplacerWithNext : public StreamReplacer { - protected: - /// to pass processing further - std::unique_ptr pNext_; - - public: - void SetNextReplacer(std::unique_ptr &&pNext) override { - std::swap(pNext_, pNext); - } - }; +void UsualReplacer::DoReplacements(const char toProcess, const bool aEod) const +{ + if (nullptr == pNext_) + { + throw logic_error("Replacement chain has been broken. Communicate with maintainer"); + } - //-------------------------------------------------- - struct ReplacerPairHolder { - ReplacerPairHolder(unique_ptr &src, // what to replace - unique_ptr &trg) // to what - : src_(src) - , trg_(trg) { + // no more data + // just send cached amount + if (aEod) + { + for (size_t i = 0; i < cachedAmount_; ++i) + { + pNext_->DoReplacements(src_[i], false); } + cachedAmount_ = 0; + pNext_->DoReplacements(toProcess, true); + return; + } - unique_ptr &src_; // what to replace - unique_ptr &trg_; // with what - }; - - - //-------------------------------------------------- - class UsualReplacer final : public ReplacerWithNext { - public: - UsualReplacer(unique_ptr &src, // what to replace - unique_ptr &trg) // with what - : src_(src->access()) - , trg_(trg->access()) { - cachedData_.resize(src_.size()); + if (src_[cachedAmount_] == toProcess) // check for match + { + if (++cachedAmount_ >= src_.size()) + {// send target - do replacement + for (size_t q = 0; q < trg_.size(); ++q) { pNext_->DoReplacements(trg_[q], false); } + cachedAmount_ = 0; } + return; + } - void DoReplacements(const char toProcess, const bool aEod) const override; - - protected: - const span &src_; // what to replace - const span &trg_; // with what - - mutable size_t cachedAmount_ = 0; // we cached this amount of data - - // this is used to hold temporary data while the logic is - // looking for the new beginning of the cached value - mutable vector cachedData_; - }; - + // here: toProcess is not our char + // lets check for fast track (255/256 probability) + if (0 == cachedAmount_) + { + pNext_->DoReplacements(toProcess, false); + return; + } - void UsualReplacer::DoReplacements(const char toProcess, const bool aEod) const { - if (nullptr == pNext_) { - throw logic_error("Replacement chain has been broken. Communicate with maintainer"); - } + // here: We have some cached data + // at least 1 char need to be send further + // remaining cached data including toProcess need to be reprocessed for match - // no more data - // just send cached amount - if (aEod) { - for (size_t i = 0; i < cachedAmount_; ++i) { - pNext_->DoReplacements(src_[i], false); - } - cachedAmount_ = 0; - pNext_->DoReplacements(toProcess, true); - return; - } + memcpy(cachedData_.data(), src_.data(), cachedAmount_); + cachedData_[cachedAmount_++]= toProcess; + size_t i = 0; + do + { + pNext_->DoReplacements(cachedData_[i++], false); // send 1 byte after another + } while (0 != memcmp(src_.data(), cachedData_.data() + i, --cachedAmount_)); + // Everything that was needed has already been sent + // cachedAmount_ is zero or greater +} + + +/// +/// creates replacer +/// +/// what we are going to replace +/// this is the result of the replacement +/// Replacer for building replacement chain +static unique_ptr CreateSimpleReplacer( + unique_ptr& src, // what to replace + unique_ptr& trg) // with what +{ + return unique_ptr(new UsualReplacer(src, trg)); +} + + +//-------------------------------------------------- +/// +/// |--SRC 1 TRG 1 | +/// O - |-- ... | - o +/// |--SRC N TRG N | +/// +class ChoiceReplacer final : public ReplacerWithNext +{ + typedef struct + { + span src_; + span trg_; + }ChoiceReplacerPair; - if (src_[cachedAmount_] == toProcess) // check for match +public: + /// + /// creating ChoiceReplacer from provided pairs + /// + /// vector os source & target pairs + ChoiceReplacer(StreamReplacerChoice& choice) + { + size_t bufferSize = 0; // to allocate buffer + const size_t sz = choice.size(); + rpairs_.resize(sz); + for (size_t i = 0; i < sz; ++i) { - if (++cachedAmount_ >= src_.size()) { - // send target - do replacement - for (size_t q = 0; q < trg_.size(); ++q) { pNext_->DoReplacements(trg_[q], false); } - cachedAmount_ = 0; + auto& vPair = choice[i]; // copy from + auto& rpair = rpairs_[i];// copy to + + rpair.src_ = vPair.first->access(); + const size_t sourceSize = rpair.src_.size(); + if (bufferSize < sourceSize) + { + bufferSize = sourceSize; // calculate necessary buffer size } - return; - } - // here: toProcess is not our char - // lets check for fast track (255/256 probability) - if (0 == cachedAmount_) { - pNext_->DoReplacements(toProcess, false); - return; + rpair.trg_ = vPair.second->access(); } - // here: We have some cached data - // at least 1 char need to be send further - // remaining cached data including toProcess need to be reprocessed for match - - memcpy(cachedData_.data(), src_.data(), cachedAmount_); - cachedData_[cachedAmount_++] = toProcess; - size_t i = 0; - do { - pNext_->DoReplacements(cachedData_[i++], false); // send 1 byte after another - } while (0 != memcmp(src_.data(), cachedData_.data() + i, --cachedAmount_)); - // Everything that was needed has already been sent - // cachedAmount_ is zero or greater + cachedData_.resize(bufferSize); } + void DoReplacements(const char toProcess, const bool aEod) const override; +protected: /// - /// creates replacer + /// check for partial or full match of the data from cachedData_ + /// with any of lexemes sequentially + /// and provides type of the match and index if found /// - /// what we are going to replace - /// this is the result of the replacement - /// Replacer for building replacement chain - static unique_ptr CreateSimpleReplacer( - unique_ptr &src, // what to replace - unique_ptr &trg) // with what + /// search in pairs from this index + /// what type of match we want to find : only full or partial also + /// bool: partial, bool: full, size_t: index + tuple FindMatch(const size_t indexFrom, const bool fullOnly) const { - return unique_ptr(new UsualReplacer(src, trg)); - } - - - class TrieNode { - public: - std::unordered_map> children; - std::optional target; - size_t depth = 0; - }; - - class Trie { - public: - enum MatchType { none, partial, full }; - - TrieNode root; - TrieNode *lastNode = &root; - - void insert(std::string_view key, std::string_view value) { - TrieNode *node = &root; - for (char c : key) { - if (!node->children[c]) { - node->children[c] = std::make_unique(); - } - node = node->children[c].get(); - } - node->target = value; - node->depth = key.size(); - } + for (size_t i = indexFrom; i < rpairs_.size(); ++i) + { + const auto& srcSpan = rpairs_[i].src_; + const size_t cmpLength = (srcSpan.size() > cachedAmount_) ? cachedAmount_ : srcSpan.size(); - [[nodiscard]] std::tuple searchFull(const std::string_view& cachedData) { - TrieNode *node = &root; - for (char c: cachedData) { - auto res = node->children.find(c); - if (res == node->children.end()) { - return std::make_tuple(std::string_view(), 0, none); + if (0 == memcmp(srcSpan.data(), cachedData_.data(), cmpLength)) + { // match + if (cmpLength == srcSpan.size()) + { + return {false, true, i}; } - node = res->second.get(); - // full match - if (node->target) { - return std::make_tuple(node->target.value(), node->depth, full); + if (!fullOnly) + { + return {true, false, i}; } } - - // partial - return {std::string_view(), 0, partial}; + // continue - no match here } + return {false, false, 0}; + } - void Eod() { - lastNode = &root; + /// + /// Sends target to next replacers, and resets partial match index to zero + /// + /// the array we need to send + void SendAndResetPartialMatch(const span& target) const + { + for (const char c : target) + { + pNext_->DoReplacements(c, false); } + indexOfPartialMatch_ = 0; + } - [[nodiscard]] std::pair accumulateSearch(const char key) { - TrieNode *node = lastNode; - auto res = node->children.find(key); - if (res == node->children.end()) { - lastNode = &root; - return std::make_pair(std::string_view(), none); - } - node = res->second.get(); - // full match - if (node->target) { - return std::make_pair(node->target.value(), full); - } - // partial - lastNode = node; - return {std::string_view(), partial}; - } + /// + /// Clean srcMatchedLength bytes of cache from the beginning + /// + /// number of bytes we have to clear + void CleanTheCache(size_t srcMatchedLength) const + { + shift_left(cachedData_.data(), + cachedData_.data() + cachedAmount_, + static_cast::difference_type>(srcMatchedLength)); + cachedAmount_ -= srcMatchedLength; + } - [[nodiscard]] std::pair accumulateSearch(const std::string_view &key) { - TrieNode *node = lastNode; - for (char c: key) { - auto res = node->children.find(c); - if (res == node->children.end()) { - lastNode = &root; - return std::make_pair(std::string_view(), none); - } - node = res->second.get(); - } - // full match - if (node->target) { - return std::make_pair(node->target.value(), full); - } - // partial - lastNode = node; - return {std::string_view(), partial}; - } - }; - - - //-------------------------------------------------- - /// - /// |--SRC 1 TRG 1 | - /// O - |-- ... | - o - /// |--SRC N TRG N | - /// - class ChoiceReplacer final : public ReplacerWithNext { - typedef struct { - span src_; - span trg_; - } ChoiceReplacerPair; - - public: - /// - /// creating ChoiceReplacer from provided pairs - /// - /// vector os source & target pairs - ChoiceReplacer(StreamReplacerChoice &choice) { - size_t bufferSize = 0; // to allocate buffer - const size_t sz = choice.size(); - for (size_t i = 0; i < sz; ++i) { - auto &vPair = choice[i]; - const size_t sourceSize = vPair.first->access().size(); - if (bufferSize < sourceSize) { - bufferSize = sourceSize; // calculate necessary buffer size - } - const span &src = vPair.first->access(); - const span &trg = vPair.second->access(); - trie_.insert(string_view(src.data(), src.size()), string_view(trg.data(), trg.size())); + /// + /// The end of the data sign has been received and the cached data need to be either send or replaced & send + /// + /// character received along with end of data sign + void DoReplacementsAtTheEndOfTheData(const char toProcess) const + { + while (cachedAmount_ > 0) + { + const auto [partialMatch, fullMatch, matchPairIndex] = FindMatch(indexOfPartialMatch_, true); + if (fullMatch) + { + const auto& rpair = rpairs_[matchPairIndex]; + SendAndResetPartialMatch(rpair.trg_); + CleanTheCache(rpair.src_.size()); } - - cachedData_.resize(bufferSize); - } - - void DoReplacements(const char toProcess, const bool aEod) const override; - - protected: - /// - /// Sends target to next replacers, and resets partial match index to zero - /// - /// the array we need to send - void SendAndResetPartialMatch(const span &target) const { - for (const char c: target) { - pNext_->DoReplacements(c, false); + else // No full match -> send 1 char from cache + { + SendAndResetPartialMatch(std::span (cachedData_.data(), 1)); + CleanTheCache(1); } } + pNext_->DoReplacements(toProcess, true); + } - /// - /// Clean srcMatchedLength bytes of cache from the beginning - /// - /// number of bytes we have to clear - void CleanTheCache(size_t srcMatchedLength) const { - shift_left(cachedData_.data(), - cachedData_.data() + cachedAmount_, - static_cast::difference_type>( - srcMatchedLength)); - cachedAmount_ -= srcMatchedLength; - trie_.Eod(); - } +protected: + // our pairs sorted by priority - only one of them could be replaced for concrete pos + vector rpairs_; - /// - /// The end of the data sign has been received and the cached data need to be either send or replaced & send - /// - /// character received along with end of data sign - void DoReplacementsAtTheEndOfTheData(const char toProcess) const { - while (cachedAmount_ > 0) { - const auto [match, srcSize, type] = trie_.searchFull(std::string_view(cachedData_.data(), cachedAmount_)); - if (type == Trie::full) { - SendAndResetPartialMatch(match); - CleanTheCache(srcSize); - } else // No full match -> send 1 char from cache - { - SendAndResetPartialMatch(std::span(cachedData_.data(), 1)); - CleanTheCache(1); - } - } - pNext_->DoReplacements(toProcess, true); - } + mutable size_t cachedAmount_ = 0; // we cached this amount of data + mutable size_t indexOfPartialMatch_ = 0; // this index from rpairs_ represents last partial match - protected: - // our pairs sorted by priority - only one of them could be replaced for concrete pos - mutable Trie trie_; + // this is used to hold temporary data while the logic is + // looking for the new beginning of the cached value + mutable vector cachedData_; +}; - mutable size_t cachedAmount_ = 0; // we cached this amount of data +void ChoiceReplacer::DoReplacements(const char toProcess, const bool aEod) const +{ + if (nullptr == pNext_) + { + throw logic_error("Replacement chain has been broken. Communicate with maintainer"); + } - // this is used to hold temporary data while the logic is - // looking for the new beginning of the cached value - mutable vector cachedData_; - }; + if (aEod) [[unlikely]] + { + DoReplacementsAtTheEndOfTheData(toProcess); + return; + } - void ChoiceReplacer::DoReplacements(const char toProcess, const bool aEod) const { - if (nullptr == pNext_) { - throw logic_error("Replacement chain has been broken. Communicate with maintainer"); + cachedData_[cachedAmount_++] = toProcess; + while (cachedAmount_ > 0) + { + const auto [partialMatch, fullMatch, matchPairIndex] = FindMatch(indexOfPartialMatch_, false); + if (fullMatch) + { + const auto& rpair = rpairs_[matchPairIndex]; + SendAndResetPartialMatch(rpair.trg_); + CleanTheCache(rpair.src_.size()); + return; } - - if (aEod) [[unlikely]] + if (partialMatch) { - DoReplacementsAtTheEndOfTheData(toProcess); + indexOfPartialMatch_ = matchPairIndex; return; } - - cachedData_[cachedAmount_++] = toProcess; - while (cachedAmount_ > 0) { - const auto [match, srcSize, type] = trie_.searchFull(std::string_view(cachedData_.data(), cachedAmount_)); - if (type == Trie::full) { - SendAndResetPartialMatch(match); - CleanTheCache(srcSize); - return; - } - if (type == Trie::partial) { - return; - } - // No any match -> send 1 char from cache - SendAndResetPartialMatch(std::span(cachedData_.data(), 1)); - CleanTheCache(1); + // No any match -> send 1 char from cache + SendAndResetPartialMatch(std::span (cachedData_.data(), 1)); + CleanTheCache(1); + } +} + +namespace +{ + static std::string_view warningDuplicatePattern("Warning: Duplicate pattern to replace found. Second lexeme will be ignored."); +}; + +//-------------------------------------------------- +/// +/// replaces for lexemes of the same length +/// +class UniformLexemeReplacer final : public ReplacerWithNext { +public: + UniformLexemeReplacer(StreamReplacerChoice &choice, const size_t sz) + : cachedData_(sz) { + for (AbstractLexemesPair &alpair: choice) { + const span &src = alpair.first->access(); + const span &trg = alpair.second->access(); + trie_.insert(string_view(src.data(), src.size()), string_view(trg.data(), trg.size())); } } - namespace { - static std::string_view warningDuplicatePattern( - "Warning: Duplicate pattern to replace found. Second lexeme will be ignored."); - }; - - - //-------------------------------------------------- - /// - /// replaces for lexemes of the same length - /// - class UniformLexemeReplacer final : public ReplacerWithNext { - public: - UniformLexemeReplacer(StreamReplacerChoice &choice, const size_t sz) - : cachedData_(sz) { - for (AbstractLexemesPair &alpair: choice) { - const span &src = alpair.first->access(); - const span &trg = alpair.second->access(); - trie_.insert(string_view(src.data(), src.size()), string_view(trg.data(), trg.size())); - } - } + void DoReplacements(const char toProcess, const bool aEod) const override; - void DoReplacements(const char toProcess, const bool aEod) const override; +protected: + // here we hold pairs of sources and targets + mutable Trie trie_; + mutable size_t cachedAmount_ = 0; // we cache this amount of data in the cachedData_ - protected: - // here we hold pairs of sources and targets - mutable Trie trie_; - mutable size_t cachedAmount_ = 0; // we cache this amount of data in the cachedData_ + // this is used to hold temporary data while the logic is + // looking for the new beginning of the cached value + mutable vector cachedData_; +}; - // this is used to hold temporary data while the logic is - // looking for the new beginning of the cached value - mutable vector cachedData_; - }; +void UniformLexemeReplacer::DoReplacements(const char toProcess, const bool aEod) const +{ + if (nullptr == pNext_) + { + throw logic_error("Replacement chain has been broken. Communicate with maintainer"); + } - void UniformLexemeReplacer::DoReplacements(const char toProcess, const bool aEod) const { - if (nullptr == pNext_) { - throw logic_error("Replacement chain has been broken. Communicate with maintainer"); + // no more data + if (aEod) + { + if (cachedAmount_ > 0) + { + for (size_t q = 0; q < cachedAmount_; ++q) { pNext_->DoReplacements(cachedData_[q], false); } + cachedAmount_ = 0; } + pNext_->DoReplacements(toProcess, aEod); // send end of the data further + return; + } // if (aEod) - // no more data - if (aEod) { - if (cachedAmount_ > 0) { - for (size_t q = 0; q < cachedAmount_; ++q) { pNext_->DoReplacements(cachedData_[q], false); } - cachedAmount_ = 0; - } - pNext_->DoReplacements(toProcess, aEod); // send end of the data further - return; - } // if (aEod) - - // set buffer of cached at once - cachedData_[cachedAmount_++] = toProcess; - if (cachedAmount_ == cachedData_.size()) { - string_view key(cachedData_.data(), cachedAmount_); - if (auto [target, srcSize, type] = trie_.searchFull(key); type == Trie::full) { - for (char c: target) { - pNext_->DoReplacements(c, false); - } - cachedAmount_ = 0; - } else { - pNext_->DoReplacements(cachedData_[0], false); - std::shift_left(cachedData_.begin(), cachedData_.begin() + cachedAmount_, 1); - --cachedAmount_; + // set buffer of cached at once + cachedData_[cachedAmount_++] = toProcess; + if (cachedAmount_ == cachedData_.size()) { + string_view key(cachedData_.data(), cachedAmount_); + if (auto [target, fullMatch] = trie_.searchFullMatch(key); fullMatch) { + for (char c: target) { + pNext_->DoReplacements(c, false); } + cachedAmount_ = 0; + } else { + pNext_->DoReplacements(cachedData_[0], false); + std::shift_left(cachedData_.begin(), cachedData_.begin() + cachedAmount_, 1); + --cachedAmount_; } } +} - //-------------------------------------------------- - /// - /// replaces for lexemes of the same length - /// - class LexemeOf1Replacer final : public ReplacerWithNext { - public: - LexemeOf1Replacer(StreamReplacerChoice &choice) { - for (AbstractLexemesPair &alpair: choice) { - const size_t index = static_cast(*(reinterpret_cast(alpair.first-> - access().data()))); - if (replaces_[index].present_) { - cout << coloredconsole::toconsole(warningDuplicatePattern) << endl; - } else { - replaces_[index].present_ = true; - replaces_[index].trg_ = alpair.second->access(); - } +//-------------------------------------------------- +/// +/// replaces for lexemes of the same length +/// +class LexemeOf1Replacer final : public ReplacerWithNext +{ +public: + LexemeOf1Replacer(StreamReplacerChoice& choice) + { + for (AbstractLexemesPair& alpair : choice) + { + const size_t index = static_cast(*(reinterpret_cast(alpair.first->access().data()))); + if (replaces_[index].present_) + { + cout << coloredconsole::toconsole(warningDuplicatePattern) << endl; + } + else + { + replaces_[index].present_ = true; + replaces_[index].trg_ = alpair.second->access(); } } + } - void DoReplacements(const char toProcess, const bool aEod) const override; - - protected: - struct { - bool present_ = false; // if this char is present - span trg_; - } replaces_[256]; - }; - + void DoReplacements(const char toProcess, const bool aEod) const override; - void LexemeOf1Replacer::DoReplacements(const char toProcess, const bool aEod) const { - if (nullptr == pNext_) { - throw logic_error("Replacement chain has been broken. Communicate with maintainer"); - } +protected: + struct + { + bool present_ = false; // if this char is present + span trg_; + } replaces_[256]; +}; - // no more data - if (aEod) { - pNext_->DoReplacements(toProcess, aEod); - return; - } // if (aEod) - const size_t index = static_cast(*(reinterpret_cast(&toProcess))); - if (replaces_[index].present_) { - auto &trg = replaces_[index].trg_; - for (size_t q = 0; q < trg.size(); ++q) { pNext_->DoReplacements(trg[q], false); } - } else { - pNext_->DoReplacements(toProcess, aEod); - } +void LexemeOf1Replacer::DoReplacements(const char toProcess, const bool aEod) const +{ + if (nullptr == pNext_) + { + throw logic_error("Replacement chain has been broken. Communicate with maintainer"); } + // no more data + if (aEod) + { + pNext_->DoReplacements(toProcess, aEod); + return; + } // if (aEod) - //-------------------------------------------------- - /// - /// creates replacer for lexemes of the same length - /// since this fact allows to use unordered_map for faster search - /// - /// set of pairs of src & trg lexemes - one of which - /// can be processed. The one that was found first. - /// size of all source lexemes - /// Replacer for building replacement chain - unique_ptr CreateEqualLengthReplacer(StreamReplacerChoice &choice, const size_t sz) { - if (sz == 1) { - return unique_ptr(new LexemeOf1Replacer(choice)); - } - return unique_ptr(new UniformLexemeReplacer(choice, sz)); + const size_t index = static_cast(*(reinterpret_cast(&toProcess))); + if (replaces_[index].present_) + { + auto& trg = replaces_[index].trg_; + for (size_t q = 0; q < trg.size(); ++q) { pNext_->DoReplacements(trg[q], false); } } - - //-------------------------------------------------- - /// - /// creates replacer for choose specific lexeme among others to replace - /// - /// set of pairs of src & trg lexemes - one of which - /// can be processed. The one that was found first. - /// Replacer for building replacement chain - unique_ptr CreateMultipleReplacer(StreamReplacerChoice &choice) { - const size_t szSrc = choice.cbegin()->first->access().size(); // save size of the first lexeme - - // check for sources of the same length - for (const AbstractLexemesPair &alpair: choice) { - if (alpair.first->access().size() != szSrc) { - return unique_ptr(new ChoiceReplacer(choice)); - } + else + { + pNext_->DoReplacements(toProcess, aEod); + } +} + + +//-------------------------------------------------- +/// +/// creates replacer for lexemes of the same length +/// since this fact allows to use unordered_map for faster search +/// +/// set of pairs of src & trg lexemes - one of which +/// can be processed. The one that was found first. +/// size of all source lexemes +/// Replacer for building replacement chain +unique_ptr CreateEqualLengthReplacer(StreamReplacerChoice& choice, const size_t sz) +{ + if (sz == 1) + { + return unique_ptr(new LexemeOf1Replacer(choice)); + } + return unique_ptr(new UniformLexemeReplacer(choice, sz)); +} + +//-------------------------------------------------- +/// +/// creates replacer for choose specific lexeme among others to replace +/// +/// set of pairs of src & trg lexemes - one of which +/// can be processed. The one that was found first. +/// Replacer for building replacement chain +unique_ptr CreateMultipleReplacer(StreamReplacerChoice& choice) +{ + const size_t szSrc = choice.cbegin()->first->access().size(); // save size of the first lexeme + + // check for sources of the same length + for (const AbstractLexemesPair& alpair: choice) + { + if (alpair.first->access().size() != szSrc) + { + return unique_ptr(new ChoiceReplacer(choice)); } - - return CreateEqualLengthReplacer(choice, szSrc); // create optimized replacer for lexemes of the same length } + return CreateEqualLengthReplacer(choice, szSrc); // create optimized replacer for lexemes of the same length +} - //-------------------------------------------------- - unique_ptr StreamReplacer::CreateReplacer(StreamReplacerChoice &choice) { - for (const AbstractLexemesPair &alpair: choice) { - if (alpair.first->access().empty()) - throw logic_error("Pattern to replace cannot be empty"); - } - if (choice.size() == 1) { - const AbstractLexemesPair &alexemesPair = *choice.cbegin(); - return CreateSimpleReplacer(alexemesPair.first, alexemesPair.second); - } - return CreateMultipleReplacer(choice); +//-------------------------------------------------- +unique_ptr StreamReplacer::CreateReplacer(StreamReplacerChoice& choice) +{ + for (const AbstractLexemesPair& alpair: choice) + { + if (alpair.first->access().empty()) + throw logic_error("Pattern to replace cannot be empty"); } + + if (choice.size() == 1) + { + const AbstractLexemesPair& alexemesPair = *choice.cbegin(); + return CreateSimpleReplacer(alexemesPair.first, alexemesPair.second); + } + return CreateMultipleReplacer(choice); +} + }; // namespace bpatch diff --git a/srcbpatch/trie.cpp b/srcbpatch/trie.cpp new file mode 100644 index 0000000..2288941 --- /dev/null +++ b/srcbpatch/trie.cpp @@ -0,0 +1,34 @@ +#include "trie.h" + +void Trie::insert(std::string_view key, std::string_view value) +{ + TrieNode *node = &root; + for (char character : key) + { + auto [it, inserted] = node->children.try_emplace(character, std::make_unique()); + node = it->second.get(); + } + node->target = value; +} + +[[nodiscard]] std::pair Trie::searchFullMatch(const std::string_view& cachedData) +{ + TrieNode *node = &root; + for (char c: cachedData) + { + auto res = node->children.find(c); + if (res == node->children.end()) + { + return std::make_tuple(std::string_view(), false); + } + node = res->second.get(); + } + + // full match + if (node->target) + { + return std::make_tuple(node->target.value(), true); + } + + return std::make_tuple(std::string_view(), false); +} diff --git a/srcbpatch/trie.h b/srcbpatch/trie.h new file mode 100644 index 0000000..6d9e395 --- /dev/null +++ b/srcbpatch/trie.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include + +class TrieNode { + public: + tsl::robin_map> children; + std::optional target; + }; + +/// @brief Frefix tree class to speed up UniformLexemeReplacer::DoReplace +class Trie { +public: + /// + /// Adds a new key-value pair in prefix tree + /// + /// source lexemme + /// target lexemme + void insert(std::string_view key, std::string_view value); + + /// + /// Looking for a full match in prefix tree + /// + /// key to find + /// string_view: target, bool: FullMatch + [[nodiscard]] std::pair searchFullMatch(const std::string_view& cachedData); + +private: + TrieNode root; +}; \ No newline at end of file From 3ab3a5baf6f7424c5e049abba8a66a4e51559129 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D0=BC=D0=B8=D1=80=20=D0=A7?= =?UTF-8?q?=D0=B8=D0=B6?= Date: Sun, 15 Sep 2024 23:01:54 +0200 Subject: [PATCH 06/16] build fix --- rebuild.sh | 2 +- srcbpatch/trie.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rebuild.sh b/rebuild.sh index 0fb991f..7ce9af8 100644 --- a/rebuild.sh +++ b/rebuild.sh @@ -11,7 +11,7 @@ if [ "$1" != "" ]; then fi # Check if MODE is not Debug, if true set it to Release -if [ "$MODE" != "Debug" ] && [ "$MODE" != "RelWithDebInfo" ]; then +if [ "$MODE" != "Debug" ]; then MODE=Release fi diff --git a/srcbpatch/trie.cpp b/srcbpatch/trie.cpp index 2288941..2d20a26 100644 --- a/srcbpatch/trie.cpp +++ b/srcbpatch/trie.cpp @@ -19,7 +19,7 @@ void Trie::insert(std::string_view key, std::string_view value) auto res = node->children.find(c); if (res == node->children.end()) { - return std::make_tuple(std::string_view(), false); + return std::make_pair(std::string_view(), false); } node = res->second.get(); } @@ -27,8 +27,8 @@ void Trie::insert(std::string_view key, std::string_view value) // full match if (node->target) { - return std::make_tuple(node->target.value(), true); + return std::make_pair(node->target.value(), true); } - return std::make_tuple(std::string_view(), false); + return std::make_pair(std::string_view(), false); } From 3501ee9241d8f792e490e26cad14a010579868b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D0=BC=D0=B8=D1=80=20=D0=A7?= =?UTF-8?q?=D0=B8=D0=B6?= Date: Sun, 15 Sep 2024 23:12:58 +0200 Subject: [PATCH 07/16] build fix --- CMakeLists.txt | 40 ++++++++++++++++++------------------ rebuild.sh | 2 +- srcbpatch/streamreplacer.cpp | 3 ++- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a88885e..ab5b9b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,9 +11,9 @@ set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo;MinSizeRel" CACHE STRING "Configs" FORCE) # Set the build type to Debug if not explicitly specified -if (NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Debug) -endif () +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug) +endif() message(STATUS "Initial COMPILER_FLAGS:" ${CMAKE_CXX_FLAGS}) @@ -27,7 +27,7 @@ message(STATUS "CMAKE_CXX_FLAGS:" ${CMAKE_CXX_FLAGS}) message(STATUS "CMAKE_CXX_COMPILER_ID:" ${CMAKE_CXX_COMPILER_ID}) set(CMAKE_EXE_LINKER_FLAGS "") -if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") # GCC (GNU Compiler) if (CMAKE_BUILD_TYPE STREQUAL "Debug") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DDEBUG -D_DEBUG -g -D_CONSOLE -Wno-unknown-pragmas -Wall -Werror -fno-rtti -pthread") @@ -40,8 +40,8 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") set(CMAKE_EXE_LINKER_FLAGS "-g -O2 -flto") else() message(FATAL_ERROR "Unsupported compilation mode") - endif () -elseif (CMAKE_CXX_COMPILER_ID MATCHES ".*Clang.*") #Clang or AppleClang or anything with Clang + endif() +elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang.*") #Clang or AppleClang or anything with Clang # clang (MAC Compiler) if (CMAKE_BUILD_TYPE STREQUAL "Debug") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DDEBUG -D_DEBUG -g -D_CONSOLE -Wno-unknown-pragmas -Wall -Werror -Wno-unqualified-std-cast-call -fno-rtti -pthread -stdlib=libc++") @@ -54,8 +54,8 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES ".*Clang.*") #Clang or AppleClang or anyt set(CMAKE_EXE_LINKER_FLAGS "-g -O2 -flto") else() message(FATAL_ERROR "Unsupported compilation mode") - endif () -elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + endif() +elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") # MSVC (Microsoft Visual C++) if (CMAKE_BUILD_TYPE STREQUAL "Debug") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /DWIN32 /D_WINDOWS /D_CONSOLE /DDEBUG /D_DEBUG /Zi /EHsc /W4 /WX /GR- /MDd") @@ -68,10 +68,10 @@ elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") set(CMAKE_EXE_LINKER_FLAGS "/DEBUG:FULL /OPT:REF /OPT:ICF /INCREMENTAL:NO") else() message(FATAL_ERROR "Unsupported compilation mode") - endif () -else () + endif() +else() message(FATAL_ERROR "Unsupported compiler") -endif () +endif() message(STATUS "CMAKE_CXX_FLAGS:" ${CMAKE_CXX_FLAGS}) @@ -84,10 +84,10 @@ FetchContent_GetProperties(googletest) #googletest_POPULATED #googletest_SOURCE_DIR #googletest_BUILD_DIR -if (NOT googletest_POPULATED) +if(NOT googletest_POPULATED) FetchContent_Populate(googletest) add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BUILD_DIR}) -endif () +endif() include(FetchContent) @@ -104,7 +104,7 @@ include_directories(src${pname}) # Source files set(SOURCE_FILES - bpatch.cpp + bpatch.cpp ) #set(HEADER_FILES #) @@ -113,14 +113,14 @@ set(SOURCE_FILES add_executable(${pname} ${SOURCE_FILES}) # Set the name of the executable based on the platform -if (WIN32) +if(WIN32) set_target_properties(${pname} PROPERTIES OUTPUT_NAME "${pname}") -else () +else() set_target_properties(${pname} PROPERTIES OUTPUT_NAME "${pname}") -endif () +endif() # Configuration-specific settings -if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") # For GCC and Clang, use the -m64 flag to target 64-bit set_target_properties(${pname} PROPERTIES COMPILE_OPTIONS "$<$:-O3>" @@ -136,10 +136,10 @@ set_target_properties(${pname} PROPERTIES ) -else () +else() message(FATAL_ERROR "Unsupported compiler") -endif () +endif() add_subdirectory(${wild_library}) add_subdirectory(src${pname}) diff --git a/rebuild.sh b/rebuild.sh index 7ce9af8..0fb991f 100644 --- a/rebuild.sh +++ b/rebuild.sh @@ -11,7 +11,7 @@ if [ "$1" != "" ]; then fi # Check if MODE is not Debug, if true set it to Release -if [ "$MODE" != "Debug" ]; then +if [ "$MODE" != "Debug" ] && [ "$MODE" != "RelWithDebInfo" ]; then MODE=Release fi diff --git a/srcbpatch/streamreplacer.cpp b/srcbpatch/streamreplacer.cpp index da11d57..66ffcbf 100644 --- a/srcbpatch/streamreplacer.cpp +++ b/srcbpatch/streamreplacer.cpp @@ -350,7 +350,8 @@ namespace /// /// replaces for lexemes of the same length /// -class UniformLexemeReplacer final : public ReplacerWithNext { +class UniformLexemeReplacer final : public ReplacerWithNext +{ public: UniformLexemeReplacer(StreamReplacerChoice &choice, const size_t sz) : cachedData_(sz) { From b620e22918bf6b5a191e9bca2411e8b90d971446 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D0=BC=D0=B8=D1=80=20=D0=A7?= =?UTF-8?q?=D0=B8=D0=B6?= Date: Sun, 15 Sep 2024 23:26:49 +0200 Subject: [PATCH 08/16] remove windows warning and revern unexpected changes --- IntegrationTests/in_tests.sh | 0 srcbpatch/streamreplacer.cpp | 31 +++++++++++++++++++------------ srcbpatch/trie.h | 10 ++++++++++ 3 files changed, 29 insertions(+), 12 deletions(-) mode change 100755 => 100644 IntegrationTests/in_tests.sh diff --git a/IntegrationTests/in_tests.sh b/IntegrationTests/in_tests.sh old mode 100755 new mode 100644 diff --git a/srcbpatch/streamreplacer.cpp b/srcbpatch/streamreplacer.cpp index 66ffcbf..c7748b2 100644 --- a/srcbpatch/streamreplacer.cpp +++ b/srcbpatch/streamreplacer.cpp @@ -353,11 +353,13 @@ namespace class UniformLexemeReplacer final : public ReplacerWithNext { public: - UniformLexemeReplacer(StreamReplacerChoice &choice, const size_t sz) - : cachedData_(sz) { - for (AbstractLexemesPair &alpair: choice) { - const span &src = alpair.first->access(); - const span &trg = alpair.second->access(); + UniformLexemeReplacer(StreamReplacerChoice& choice, const size_t sz) + : cachedData_(sz) + { + for (AbstractLexemesPair& alpair : choice) + { + const span& src = alpair.first->access(); + const span& trg = alpair.second->access(); trie_.insert(string_view(src.data(), src.size()), string_view(trg.data(), trg.size())); } } @@ -397,17 +399,22 @@ void UniformLexemeReplacer::DoReplacements(const char toProcess, const bool aEod // set buffer of cached at once cachedData_[cachedAmount_++] = toProcess; - if (cachedAmount_ == cachedData_.size()) { + if (cachedAmount_ == cachedData_.size()) + { string_view key(cachedData_.data(), cachedAmount_); - if (auto [target, fullMatch] = trie_.searchFullMatch(key); fullMatch) { - for (char c: target) { - pNext_->DoReplacements(c, false); + if (auto [target, fullMatch] = trie_.searchFullMatch(key); fullMatch) + { + for (char q: target) + { + pNext_->DoReplacements(q, false); } cachedAmount_ = 0; - } else { + } + else + { + // not found pNext_->DoReplacements(cachedData_[0], false); - std::shift_left(cachedData_.begin(), cachedData_.begin() + cachedAmount_, 1); - --cachedAmount_; + std::shift_left(cachedData_.begin(), cachedData_.begin() + cachedAmount_--, 1); } } } diff --git a/srcbpatch/trie.h b/srcbpatch/trie.h index 6d9e395..c1ea3cb 100644 --- a/srcbpatch/trie.h +++ b/srcbpatch/trie.h @@ -1,8 +1,18 @@ #pragma once #include + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4324) +#endif + #include +#ifdef _MSC_VER +#pragma warning(pop) +#endif + class TrieNode { public: tsl::robin_map> children; From 9d254b681d98b0ffbe8467fdbe1f946c58f244fa Mon Sep 17 00:00:00 2001 From: Vladimir Date: Mon, 16 Sep 2024 18:41:43 +0200 Subject: [PATCH 09/16] fixed windows warning --- srcbpatch/trie.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/srcbpatch/trie.h b/srcbpatch/trie.h index c1ea3cb..bc3f822 100644 --- a/srcbpatch/trie.h +++ b/srcbpatch/trie.h @@ -2,15 +2,14 @@ #include -#ifdef _MSC_VER -#pragma warning(push) +#ifdef _WIN32 +#pragma warning(disable : 4127) #pragma warning(disable : 4324) #endif - #include - -#ifdef _MSC_VER -#pragma warning(pop) +#ifdef _WIN32 +#pragma warning(default : 4127) +#pragma warning(disable : 4324) #endif class TrieNode { From 0615d737762f8f3e3e90e8d4f0daf8dd905c53ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D0=BC=D0=B8=D1=80=20=D0=A7?= =?UTF-8?q?=D0=B8=D0=B6?= Date: Mon, 16 Sep 2024 19:11:12 +0200 Subject: [PATCH 10/16] switc from string_view to span --- srcbpatch/streamreplacer.cpp | 3 +-- srcbpatch/trie.cpp | 6 +++--- srcbpatch/trie.h | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/srcbpatch/streamreplacer.cpp b/srcbpatch/streamreplacer.cpp index c7748b2..c5c7dc5 100644 --- a/srcbpatch/streamreplacer.cpp +++ b/srcbpatch/streamreplacer.cpp @@ -401,8 +401,7 @@ void UniformLexemeReplacer::DoReplacements(const char toProcess, const bool aEod cachedData_[cachedAmount_++] = toProcess; if (cachedAmount_ == cachedData_.size()) { - string_view key(cachedData_.data(), cachedAmount_); - if (auto [target, fullMatch] = trie_.searchFullMatch(key); fullMatch) + if (auto [target, fullMatch] = trie_.searchFullMatch(std::span (cachedData_.data(), cachedAmount_)); fullMatch) { for (char q: target) { diff --git a/srcbpatch/trie.cpp b/srcbpatch/trie.cpp index 2d20a26..dbf0bcf 100644 --- a/srcbpatch/trie.cpp +++ b/srcbpatch/trie.cpp @@ -2,7 +2,7 @@ void Trie::insert(std::string_view key, std::string_view value) { - TrieNode *node = &root; + TrieNode* node = &root; for (char character : key) { auto [it, inserted] = node->children.try_emplace(character, std::make_unique()); @@ -11,9 +11,9 @@ void Trie::insert(std::string_view key, std::string_view value) node->target = value; } -[[nodiscard]] std::pair Trie::searchFullMatch(const std::string_view& cachedData) +[[nodiscard]] std::pair Trie::searchFullMatch(const std::span& cachedData) { - TrieNode *node = &root; + TrieNode* node = &root; for (char c: cachedData) { auto res = node->children.find(c); diff --git a/srcbpatch/trie.h b/srcbpatch/trie.h index bc3f822..3caf645 100644 --- a/srcbpatch/trie.h +++ b/srcbpatch/trie.h @@ -33,7 +33,7 @@ class Trie { /// /// key to find /// string_view: target, bool: FullMatch - [[nodiscard]] std::pair searchFullMatch(const std::string_view& cachedData); + [[nodiscard]] std::pair searchFullMatch(const std::span& cachedData); private: TrieNode root; From 113788688eeba4bb17a9bb1beaf0c5a0080e2ed6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D0=BC=D0=B8=D1=80=20=D0=A7?= =?UTF-8?q?=D0=B8=D0=B6?= Date: Wed, 18 Sep 2024 22:44:35 +0200 Subject: [PATCH 11/16] fix tests --- IntegrationTests/scripts/fromhex.json | 13 - IntegrationTests/scripts/fromhex8bytes.json | 542 +++++++++----------- 2 files changed, 256 insertions(+), 299 deletions(-) diff --git a/IntegrationTests/scripts/fromhex.json b/IntegrationTests/scripts/fromhex.json index e21cb8b..20b0bc9 100644 --- a/IntegrationTests/scripts/fromhex.json +++ b/IntegrationTests/scripts/fromhex.json @@ -538,19 +538,6 @@ }, "todo": [ { - "replace": - { -"LF":"empty", -"CR":"empty", -"tab":"empty", -"whitespace":"empty", -"a":"A", -"b":"B", -"c":"C", -"d":"D", -"e":"E", -"f":"F" - }, "replace": { "t0":"0", "t1":"1", diff --git a/IntegrationTests/scripts/fromhex8bytes.json b/IntegrationTests/scripts/fromhex8bytes.json index 625fc6e..1f37e14 100644 --- a/IntegrationTests/scripts/fromhex8bytes.json +++ b/IntegrationTests/scripts/fromhex8bytes.json @@ -260,23 +260,6 @@ }, "text": { - "a":"a", - "b":"b", - "c":"c", - "d":"d", - "e":"e", - "f":"f", - "A":"A", - "B":"B", - "C":"C", - "D":"D", - "E":"E", - "F":"F", - "LF":"\n", - "CR":"\r", - "tab":"\t", - "whitespace":" ", - "empty":"", "t0":"00", "t1":"01", "t2":"02", @@ -537,276 +520,263 @@ }, "todo": [ { - "replace": - { - "LF":"empty", - "CR":"empty", - "tab":"empty", - "whitespace":"empty", - "a":"A", - "b":"B", - "c":"C", - "d":"D", - "e":"E", - "f":"F" - }, "replace": { - "t0":"0", - "t1":"1", - "t2":"2", - "t3":"3", - "t4":"4", - "t5":"5", - "t6":"6", - "t7":"7", - "t8":"8", - "t9":"9", - "t10":"10", - "t11":"11", - "t12":"12", - "t13":"13", - "t14":"14", - "t15":"15", - "t16":"16", - "t17":"17", - "t18":"18", - "t19":"19", - "t20":"20", - "t21":"21", - "t22":"22", - "t23":"23", - "t24":"24", - "t25":"25", - "t26":"26", - "t27":"27", - "t28":"28", - "t29":"29", - "t30":"30", - "t31":"31", - "t32":"32", - "t33":"33", - "t34":"34", - "t35":"35", - "t36":"36", - "t37":"37", - "t38":"38", - "t39":"39", - "t40":"40", - "t41":"41", - "t42":"42", - "t43":"43", - "t44":"44", - "t45":"45", - "t46":"46", - "t47":"47", - "t48":"48", - "t49":"49", - "t50":"50", - "t51":"51", - "t52":"52", - "t53":"53", - "t54":"54", - "t55":"55", - "t56":"56", - "t57":"57", - "t58":"58", - "t59":"59", - "t60":"60", - "t61":"61", - "t62":"62", - "t63":"63", - "t64":"64", - "t65":"65", - "t66":"66", - "t67":"67", - "t68":"68", - "t69":"69", - "t70":"70", - "t71":"71", - "t72":"72", - "t73":"73", - "t74":"74", - "t75":"75", - "t76":"76", - "t77":"77", - "t78":"78", - "t79":"79", - "t80":"80", - "t81":"81", - "t82":"82", - "t83":"83", - "t84":"84", - "t85":"85", - "t86":"86", - "t87":"87", - "t88":"88", - "t89":"89", - "t90":"90", - "t91":"91", - "t92":"92", - "t93":"93", - "t94":"94", - "t95":"95", - "t96":"96", - "t97":"97", - "t98":"98", - "t99":"99", - "t100":"100", - "t101":"101", - "t102":"102", - "t103":"103", - "t104":"104", - "t105":"105", - "t106":"106", - "t107":"107", - "t108":"108", - "t109":"109", - "t110":"110", - "t111":"111", - "t112":"112", - "t113":"113", - "t114":"114", - "t115":"115", - "t116":"116", - "t117":"117", - "t118":"118", - "t119":"119", - "t120":"120", - "t121":"121", - "t122":"122", - "t123":"123", - "t124":"124", - "t125":"125", - "t126":"126", - "t127":"127", - "t128":"128", - "t129":"129", - "t130":"130", - "t131":"131", - "t132":"132", - "t133":"133", - "t134":"134", - "t135":"135", - "t136":"136", - "t137":"137", - "t138":"138", - "t139":"139", - "t140":"140", - "t141":"141", - "t142":"142", - "t143":"143", - "t144":"144", - "t145":"145", - "t146":"146", - "t147":"147", - "t148":"148", - "t149":"149", - "t150":"150", - "t151":"151", - "t152":"152", - "t153":"153", - "t154":"154", - "t155":"155", - "t156":"156", - "t157":"157", - "t158":"158", - "t159":"159", - "t160":"160", - "t161":"161", - "t162":"162", - "t163":"163", - "t164":"164", - "t165":"165", - "t166":"166", - "t167":"167", - "t168":"168", - "t169":"169", - "t170":"170", - "t171":"171", - "t172":"172", - "t173":"173", - "t174":"174", - "t175":"175", - "t176":"176", - "t177":"177", - "t178":"178", - "t179":"179", - "t180":"180", - "t181":"181", - "t182":"182", - "t183":"183", - "t184":"184", - "t185":"185", - "t186":"186", - "t187":"187", - "t188":"188", - "t189":"189", - "t190":"190", - "t191":"191", - "t192":"192", - "t193":"193", - "t194":"194", - "t195":"195", - "t196":"196", - "t197":"197", - "t198":"198", - "t199":"199", - "t200":"200", - "t201":"201", - "t202":"202", - "t203":"203", - "t204":"204", - "t205":"205", - "t206":"206", - "t207":"207", - "t208":"208", - "t209":"209", - "t210":"210", - "t211":"211", - "t212":"212", - "t213":"213", - "t214":"214", - "t215":"215", - "t216":"216", - "t217":"217", - "t218":"218", - "t219":"219", - "t220":"220", - "t221":"221", - "t222":"222", - "t223":"223", - "t224":"224", - "t225":"225", - "t226":"226", - "t227":"227", - "t228":"228", - "t229":"229", - "t230":"230", - "t231":"231", - "t232":"232", - "t233":"233", - "t234":"234", - "t235":"235", - "t236":"236", - "t237":"237", - "t238":"238", - "t239":"239", - "t240":"240", - "t241":"241", - "t242":"242", - "t243":"243", - "t244":"244", - "t245":"245", - "t246":"246", - "t247":"247", - "t248":"248", - "t249":"249", - "t250":"250", - "t251":"251", - "t252":"252", - "t253":"253", - "t254":"254", - "t255":"255" + "0": "t0", + "1": "t1", + "2": "t2", + "3": "t3", + "4": "t4", + "5": "t5", + "6": "t6", + "7": "t7", + "8": "t8", + "9": "t9", + "10": "t10", + "11": "t11", + "12": "t12", + "13": "t13", + "14": "t14", + "15": "t15", + "16": "t16", + "17": "t17", + "18": "t18", + "19": "t19", + "20": "t20", + "21": "t21", + "22": "t22", + "23": "t23", + "24": "t24", + "25": "t25", + "26": "t26", + "27": "t27", + "28": "t28", + "29": "t29", + "30": "t30", + "31": "t31", + "32": "t32", + "33": "t33", + "34": "t34", + "35": "t35", + "36": "t36", + "37": "t37", + "38": "t38", + "39": "t39", + "40": "t40", + "41": "t41", + "42": "t42", + "43": "t43", + "44": "t44", + "45": "t45", + "46": "t46", + "47": "t47", + "48": "t48", + "49": "t49", + "50": "t50", + "51": "t51", + "52": "t52", + "53": "t53", + "54": "t54", + "55": "t55", + "56": "t56", + "57": "t57", + "58": "t58", + "59": "t59", + "60": "t60", + "61": "t61", + "62": "t62", + "63": "t63", + "64": "t64", + "65": "t65", + "66": "t66", + "67": "t67", + "68": "t68", + "69": "t69", + "70": "t70", + "71": "t71", + "72": "t72", + "73": "t73", + "74": "t74", + "75": "t75", + "76": "t76", + "77": "t77", + "78": "t78", + "79": "t79", + "80": "t80", + "81": "t81", + "82": "t82", + "83": "t83", + "84": "t84", + "85": "t85", + "86": "t86", + "87": "t87", + "88": "t88", + "89": "t89", + "90": "t90", + "91": "t91", + "92": "t92", + "93": "t93", + "94": "t94", + "95": "t95", + "96": "t96", + "97": "t97", + "98": "t98", + "99": "t99", + "100": "t100", + "101": "t101", + "102": "t102", + "103": "t103", + "104": "t104", + "105": "t105", + "106": "t106", + "107": "t107", + "108": "t108", + "109": "t109", + "110": "t110", + "111": "t111", + "112": "t112", + "113": "t113", + "114": "t114", + "115": "t115", + "116": "t116", + "117": "t117", + "118": "t118", + "119": "t119", + "120": "t120", + "121": "t121", + "122": "t122", + "123": "t123", + "124": "t124", + "125": "t125", + "126": "t126", + "127": "t127", + "128": "t128", + "129": "t129", + "130": "t130", + "131": "t131", + "132": "t132", + "133": "t133", + "134": "t134", + "135": "t135", + "136": "t136", + "137": "t137", + "138": "t138", + "139": "t139", + "140": "t140", + "141": "t141", + "142": "t142", + "143": "t143", + "144": "t144", + "145": "t145", + "146": "t146", + "147": "t147", + "148": "t148", + "149": "t149", + "150": "t150", + "151": "t151", + "152": "t152", + "153": "t153", + "154": "t154", + "155": "t155", + "156": "t156", + "157": "t157", + "158": "t158", + "159": "t159", + "160": "t160", + "161": "t161", + "162": "t162", + "163": "t163", + "164": "t164", + "165": "t165", + "166": "t166", + "167": "t167", + "168": "t168", + "169": "t169", + "170": "t170", + "171": "t171", + "172": "t172", + "173": "t173", + "174": "t174", + "175": "t175", + "176": "t176", + "177": "t177", + "178": "t178", + "179": "t179", + "180": "t180", + "181": "t181", + "182": "t182", + "183": "t183", + "184": "t184", + "185": "t185", + "186": "t186", + "187": "t187", + "188": "t188", + "189": "t189", + "190": "t190", + "191": "t191", + "192": "t192", + "193": "t193", + "194": "t194", + "195": "t195", + "196": "t196", + "197": "t197", + "198": "t198", + "199": "t199", + "200": "t200", + "201": "t201", + "202": "t202", + "203": "t203", + "204": "t204", + "205": "t205", + "206": "t206", + "207": "t207", + "208": "t208", + "209": "t209", + "210": "t210", + "211": "t211", + "212": "t212", + "213": "t213", + "214": "t214", + "215": "t215", + "216": "t216", + "217": "t217", + "218": "t218", + "219": "t219", + "220": "t220", + "221": "t221", + "222": "t222", + "223": "t223", + "224": "t224", + "225": "t225", + "226": "t226", + "227": "t227", + "228": "t228", + "229": "t229", + "230": "t230", + "231": "t231", + "232": "t232", + "233": "t233", + "234": "t234", + "235": "t235", + "236": "t236", + "237": "t237", + "238": "t238", + "239": "t239", + "240": "t240", + "241": "t241", + "242": "t242", + "243": "t243", + "244": "t244", + "245": "t245", + "246": "t246", + "247": "t247", + "248": "t248", + "249": "t249", + "250": "t250", + "251": "t251", + "252": "t252", + "253": "t253", + "254": "t254", + "255": "t255" } } ] From 02022668058904cfeea3f5148c998d0701502894 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D0=BC=D0=B8=D1=80=20=D0=A7?= =?UTF-8?q?=D0=B8=D0=B6?= Date: Wed, 18 Sep 2024 23:03:04 +0200 Subject: [PATCH 12/16] added 257 bytes fromex test --- IntegrationTests/scripts/{fromhex.json => fromhex1byte.json} | 0 .../scripts/{fromhex8bytes.json => fromhex9bytes.json} | 0 README.md | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) rename IntegrationTests/scripts/{fromhex.json => fromhex1byte.json} (100%) rename IntegrationTests/scripts/{fromhex8bytes.json => fromhex9bytes.json} (100%) diff --git a/IntegrationTests/scripts/fromhex.json b/IntegrationTests/scripts/fromhex1byte.json similarity index 100% rename from IntegrationTests/scripts/fromhex.json rename to IntegrationTests/scripts/fromhex1byte.json diff --git a/IntegrationTests/scripts/fromhex8bytes.json b/IntegrationTests/scripts/fromhex9bytes.json similarity index 100% rename from IntegrationTests/scripts/fromhex8bytes.json rename to IntegrationTests/scripts/fromhex9bytes.json diff --git a/README.md b/README.md index 0bba837..d6ee7e0 100644 --- a/README.md +++ b/README.md @@ -498,5 +498,5 @@ Feel free to use email bpatchzaytsev@gmail.com along with the title: [bin4_data]:./IntegrationTests/binaries/bin4.data [bin5_data]:./IntegrationTests/binaries/bin5.data [tohex_json]:./IntegrationTests/scripts/tohex.json -[fromhex_json]:./IntegrationTests/scripts/fromhex.json +[fromhex_json]:./IntegrationTests/scripts/fromhex1byte.json [JSON]:https://www.json.org/json-en.html From 77d9dfa354d2cf008ea4e719d0f77f527a22ea18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D0=BC=D0=B8=D1=80=20=D0=A7?= =?UTF-8?q?=D0=B8=D0=B6?= Date: Thu, 19 Sep 2024 23:01:45 +0200 Subject: [PATCH 13/16] switch from robin_map to std::unordered_map --- CMakeLists.txt | 10 ---------- srcbpatch/trie.h | 12 +----------- 2 files changed, 1 insertion(+), 21 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ab5b9b3..00540d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -89,16 +89,6 @@ if(NOT googletest_POPULATED) add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BUILD_DIR}) endif() -include(FetchContent) - -FetchContent_Declare( - robin_map - GIT_REPOSITORY https://github.com/Tessil/robin-map.git - GIT_TAG master -) - -FetchContent_MakeAvailable(robin_map) - include_directories(${wild_library}) include_directories(src${pname}) diff --git a/srcbpatch/trie.h b/srcbpatch/trie.h index 3caf645..70a718d 100644 --- a/srcbpatch/trie.h +++ b/srcbpatch/trie.h @@ -2,19 +2,9 @@ #include -#ifdef _WIN32 -#pragma warning(disable : 4127) -#pragma warning(disable : 4324) -#endif -#include -#ifdef _WIN32 -#pragma warning(default : 4127) -#pragma warning(disable : 4324) -#endif - class TrieNode { public: - tsl::robin_map> children; + std::unordered_map> children; std::optional target; }; From 693f190cedd5211f3833a692d31d363fa9c2abb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D0=BC=D0=B8=D1=80=20=D0=A7?= =?UTF-8?q?=D0=B8=D0=B6?= Date: Mon, 23 Sep 2024 22:23:25 +0200 Subject: [PATCH 14/16] moved to std::reference_wrapper> --- srcbpatch/trie.cpp | 23 +++++++++++++---------- srcbpatch/trie.h | 15 +++++++++++---- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/srcbpatch/trie.cpp b/srcbpatch/trie.cpp index dbf0bcf..2891133 100644 --- a/srcbpatch/trie.cpp +++ b/srcbpatch/trie.cpp @@ -2,22 +2,25 @@ void Trie::insert(std::string_view key, std::string_view value) { - TrieNode* node = &root; + std::reference_wrapper node = root; for (char character : key) { - auto [it, inserted] = node->children.try_emplace(character, std::make_unique()); - node = it->second.get(); + if (!node.get().children.contains(character)) [[unlikely]] { + nodes.emplace_back(); + node.get().children.emplace(character, nodes.back()); + } + node = node.get().children.at(character); } - node->target = value; + node.get().target = value; } -[[nodiscard]] std::pair Trie::searchFullMatch(const std::span& cachedData) +[[nodiscard]] std::pair Trie::searchFullMatch(const std::span& cachedData) const { - TrieNode* node = &root; + std::reference_wrapper node = root; for (char c: cachedData) { - auto res = node->children.find(c); - if (res == node->children.end()) + auto res = node.get().children.find(c); + if (res == node.get().children.end()) { return std::make_pair(std::string_view(), false); } @@ -25,9 +28,9 @@ void Trie::insert(std::string_view key, std::string_view value) } // full match - if (node->target) + if (node.get().target) { - return std::make_pair(node->target.value(), true); + return std::make_pair(node.get().target.value(), true); } return std::make_pair(std::string_view(), false); diff --git a/srcbpatch/trie.h b/srcbpatch/trie.h index 70a718d..702f789 100644 --- a/srcbpatch/trie.h +++ b/srcbpatch/trie.h @@ -2,14 +2,18 @@ #include +/// @brief A node of prefix Trie, each node contains current target (if exist) and child nodes in children. +/// And doesn't contain a char of current node class TrieNode { public: - std::unordered_map> children; + /// a list of child nodes of current node. + std::unordered_map> children; + /// target of curretn node (if there are node target at this node in our lexemmePairs --> target is std::nullopt) std::optional target; - }; +}; /// @brief Frefix tree class to speed up UniformLexemeReplacer::DoReplace -class Trie { +class Trie final{ public: /// /// Adds a new key-value pair in prefix tree @@ -23,8 +27,11 @@ class Trie { /// /// key to find /// string_view: target, bool: FullMatch - [[nodiscard]] std::pair searchFullMatch(const std::span& cachedData); + [[nodiscard]] std::pair searchFullMatch(const std::span& cachedData) const; private: + /// a root node, doesn't contains target value TrieNode root; + /// holds all the nodes of Trie. While default Trie uses pointers, we are going to user reference_wrapper to this deque elements + std::deque nodes; }; \ No newline at end of file From e3543b3bfa524b2b9a47db9a226a1c47302450f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D0=BC=D0=B8=D1=80=20=D0=A7?= =?UTF-8?q?=D0=B8=D0=B6?= Date: Mon, 23 Sep 2024 22:24:25 +0200 Subject: [PATCH 15/16] revert changes in tests --- .../{fromhex1byte.json => fromhex.json} | 13 + IntegrationTests/scripts/fromhex9bytes.json | 783 ------------------ README.md | 2 +- srcbpatch/CMakeLists.txt | 1 - srcbpatch/trie.cpp | 7 +- srcbpatch/trie.h | 1 + 6 files changed, 17 insertions(+), 790 deletions(-) rename IntegrationTests/scripts/{fromhex1byte.json => fromhex.json} (98%) delete mode 100644 IntegrationTests/scripts/fromhex9bytes.json diff --git a/IntegrationTests/scripts/fromhex1byte.json b/IntegrationTests/scripts/fromhex.json similarity index 98% rename from IntegrationTests/scripts/fromhex1byte.json rename to IntegrationTests/scripts/fromhex.json index 20b0bc9..e21cb8b 100644 --- a/IntegrationTests/scripts/fromhex1byte.json +++ b/IntegrationTests/scripts/fromhex.json @@ -538,6 +538,19 @@ }, "todo": [ { + "replace": + { +"LF":"empty", +"CR":"empty", +"tab":"empty", +"whitespace":"empty", +"a":"A", +"b":"B", +"c":"C", +"d":"D", +"e":"E", +"f":"F" + }, "replace": { "t0":"0", "t1":"1", diff --git a/IntegrationTests/scripts/fromhex9bytes.json b/IntegrationTests/scripts/fromhex9bytes.json deleted file mode 100644 index 1f37e14..0000000 --- a/IntegrationTests/scripts/fromhex9bytes.json +++ /dev/null @@ -1,783 +0,0 @@ -{ - "dictionary": { - "hexadecimal": { - "0": ["00", "01", "02", "03", "04", "05", "06", "07", "08"], - "1": ["01", "01", "02", "03", "04", "05", "06", "07", "08"], - "2": ["02", "01", "02", "03", "04", "05", "06", "07", "08"], - "3": ["03", "01", "02", "03", "04", "05", "06", "07", "08"], - "4": ["04", "01", "02", "03", "04", "05", "06", "07", "08"], - "5": ["05", "01", "02", "03", "04", "05", "06", "07", "08"], - "6": ["06", "01", "02", "03", "04", "05", "06", "07", "08"], - "7": ["07", "01", "02", "03", "04", "05", "06", "07", "08"], - "8": ["08", "01", "02", "03", "04", "05", "06", "07", "08"], - "9": ["09", "01", "02", "03", "04", "05", "06", "07", "08"], - "10": ["0A", "01", "02", "03", "04", "05", "06", "07", "08"], - "11": ["0B", "01", "02", "03", "04", "05", "06", "07", "08"], - "12": ["0C", "01", "02", "03", "04", "05", "06", "07", "08"], - "13": ["0D", "01", "02", "03", "04", "05", "06", "07", "08"], - "14": ["0E", "01", "02", "03", "04", "05", "06", "07", "08"], - "15": ["0F", "01", "02", "03", "04", "05", "06", "07", "08"], - "16": ["10", "01", "02", "03", "04", "05", "06", "07", "08"], - "17": ["11", "01", "02", "03", "04", "05", "06", "07", "08"], - "18": ["12", "01", "02", "03", "04", "05", "06", "07", "08"], - "19": ["13", "01", "02", "03", "04", "05", "06", "07", "08"], - "20": ["14", "01", "02", "03", "04", "05", "06", "07", "08"], - "21": ["15", "01", "02", "03", "04", "05", "06", "07", "08"], - "22": ["16", "01", "02", "03", "04", "05", "06", "07", "08"], - "23": ["17", "01", "02", "03", "04", "05", "06", "07", "08"], - "24": ["18", "01", "02", "03", "04", "05", "06", "07", "08"], - "25": ["19", "01", "02", "03", "04", "05", "06", "07", "08"], - "26": ["1A", "01", "02", "03", "04", "05", "06", "07", "08"], - "27": ["1B", "01", "02", "03", "04", "05", "06", "07", "08"], - "28": ["1C", "01", "02", "03", "04", "05", "06", "07", "08"], - "29": ["1D", "01", "02", "03", "04", "05", "06", "07", "08"], - "30": ["1E", "01", "02", "03", "04", "05", "06", "07", "08"], - "31": ["1F", "01", "02", "03", "04", "05", "06", "07", "08"], - "32": ["20", "01", "02", "03", "04", "05", "06", "07", "08"], - "33": ["21", "01", "02", "03", "04", "05", "06", "07", "08"], - "34": ["22", "01", "02", "03", "04", "05", "06", "07", "08"], - "35": ["23", "01", "02", "03", "04", "05", "06", "07", "08"], - "36": ["24", "01", "02", "03", "04", "05", "06", "07", "08"], - "37": ["25", "01", "02", "03", "04", "05", "06", "07", "08"], - "38": ["26", "01", "02", "03", "04", "05", "06", "07", "08"], - "39": ["27", "01", "02", "03", "04", "05", "06", "07", "08"], - "40": ["28", "01", "02", "03", "04", "05", "06", "07", "08"], - "41": ["29", "01", "02", "03", "04", "05", "06", "07", "08"], - "42": ["2A", "01", "02", "03", "04", "05", "06", "07", "08"], - "43": ["2B", "01", "02", "03", "04", "05", "06", "07", "08"], - "44": ["2C", "01", "02", "03", "04", "05", "06", "07", "08"], - "45": ["2D", "01", "02", "03", "04", "05", "06", "07", "08"], - "46": ["2E", "01", "02", "03", "04", "05", "06", "07", "08"], - "47": ["2F", "01", "02", "03", "04", "05", "06", "07", "08"], - "48": ["30", "01", "02", "03", "04", "05", "06", "07", "08"], - "49": ["31", "01", "02", "03", "04", "05", "06", "07", "08"], - "50": ["32", "01", "02", "03", "04", "05", "06", "07", "08"], - "51": ["33", "01", "02", "03", "04", "05", "06", "07", "08"], - "52": ["34", "01", "02", "03", "04", "05", "06", "07", "08"], - "53": ["35", "01", "02", "03", "04", "05", "06", "07", "08"], - "54": ["36", "01", "02", "03", "04", "05", "06", "07", "08"], - "55": ["37", "01", "02", "03", "04", "05", "06", "07", "08"], - "56": ["38", "01", "02", "03", "04", "05", "06", "07", "08"], - "57": ["39", "01", "02", "03", "04", "05", "06", "07", "08"], - "58": ["3A", "01", "02", "03", "04", "05", "06", "07", "08"], - "59": ["3B", "01", "02", "03", "04", "05", "06", "07", "08"], - "60": ["3C", "01", "02", "03", "04", "05", "06", "07", "08"], - "61": ["3D", "01", "02", "03", "04", "05", "06", "07", "08"], - "62": ["3E", "01", "02", "03", "04", "05", "06", "07", "08"], - "63": ["3F", "01", "02", "03", "04", "05", "06", "07", "08"], - "64": ["40", "01", "02", "03", "04", "05", "06", "07", "08"], - "65": ["41", "01", "02", "03", "04", "05", "06", "07", "08"], - "66": ["42", "01", "02", "03", "04", "05", "06", "07", "08"], - "67": ["43", "01", "02", "03", "04", "05", "06", "07", "08"], - "68": ["44", "01", "02", "03", "04", "05", "06", "07", "08"], - "69": ["45", "01", "02", "03", "04", "05", "06", "07", "08"], - "70": ["46", "01", "02", "03", "04", "05", "06", "07", "08"], - "71": ["47", "01", "02", "03", "04", "05", "06", "07", "08"], - "72": ["48", "01", "02", "03", "04", "05", "06", "07", "08"], - "73": ["49", "01", "02", "03", "04", "05", "06", "07", "08"], - "74": ["4A", "01", "02", "03", "04", "05", "06", "07", "08"], - "75": ["4B", "01", "02", "03", "04", "05", "06", "07", "08"], - "76": ["4C", "01", "02", "03", "04", "05", "06", "07", "08"], - "77": ["4D", "01", "02", "03", "04", "05", "06", "07", "08"], - "78": ["4E", "01", "02", "03", "04", "05", "06", "07", "08"], - "79": ["4F", "01", "02", "03", "04", "05", "06", "07", "08"], - "80": ["50", "01", "02", "03", "04", "05", "06", "07", "08"], - "81": ["51", "01", "02", "03", "04", "05", "06", "07", "08"], - "82": ["52", "01", "02", "03", "04", "05", "06", "07", "08"], - "83": ["53", "01", "02", "03", "04", "05", "06", "07", "08"], - "84": ["54", "01", "02", "03", "04", "05", "06", "07", "08"], - "85": ["55", "01", "02", "03", "04", "05", "06", "07", "08"], - "86": ["56", "01", "02", "03", "04", "05", "06", "07", "08"], - "87": ["57", "01", "02", "03", "04", "05", "06", "07", "08"], - "88": ["58", "01", "02", "03", "04", "05", "06", "07", "08"], - "89": ["59", "01", "02", "03", "04", "05", "06", "07", "08"], - "90": ["5A", "01", "02", "03", "04", "05", "06", "07", "08"], - "91": ["5B", "01", "02", "03", "04", "05", "06", "07", "08"], - "92": ["5C", "01", "02", "03", "04", "05", "06", "07", "08"], - "93": ["5D", "01", "02", "03", "04", "05", "06", "07", "08"], - "94": ["5E", "01", "02", "03", "04", "05", "06", "07", "08"], - "95": ["5F", "01", "02", "03", "04", "05", "06", "07", "08"], - "96": ["60", "01", "02", "03", "04", "05", "06", "07", "08"], - "97": ["61", "01", "02", "03", "04", "05", "06", "07", "08"], - "98": ["62", "01", "02", "03", "04", "05", "06", "07", "08"], - "99": ["63", "01", "02", "03", "04", "05", "06", "07", "08"], - "100": ["64", "01", "02", "03", "04", "05", "06", "07", "08"], - "101": ["65", "01", "02", "03", "04", "05", "06", "07", "08"], - "102": ["66", "01", "02", "03", "04", "05", "06", "07", "08"], - "103": ["67", "01", "02", "03", "04", "05", "06", "07", "08"], - "104": ["68", "01", "02", "03", "04", "05", "06", "07", "08"], - "105": ["69", "01", "02", "03", "04", "05", "06", "07", "08"], - "106": ["6A", "01", "02", "03", "04", "05", "06", "07", "08"], - "107": ["6B", "01", "02", "03", "04", "05", "06", "07", "08"], - "108": ["6C", "01", "02", "03", "04", "05", "06", "07", "08"], - "109": ["6D", "01", "02", "03", "04", "05", "06", "07", "08"], - "110": ["6E", "01", "02", "03", "04", "05", "06", "07", "08"], - "111": ["6F", "01", "02", "03", "04", "05", "06", "07", "08"], - "112": ["70", "01", "02", "03", "04", "05", "06", "07", "08"], - "113": ["71", "01", "02", "03", "04", "05", "06", "07", "08"], - "114": ["72", "01", "02", "03", "04", "05", "06", "07", "08"], - "115": ["73", "01", "02", "03", "04", "05", "06", "07", "08"], - "116": ["74", "01", "02", "03", "04", "05", "06", "07", "08"], - "117": ["75", "01", "02", "03", "04", "05", "06", "07", "08"], - "118": ["76", "01", "02", "03", "04", "05", "06", "07", "08"], - "119": ["77", "01", "02", "03", "04", "05", "06", "07", "08"], - "120": ["78", "01", "02", "03", "04", "05", "06", "07", "08"], - "121": ["79", "01", "02", "03", "04", "05", "06", "07", "08"], - "122": ["7A", "01", "02", "03", "04", "05", "06", "07", "08"], - "123": ["7B", "01", "02", "03", "04", "05", "06", "07", "08"], - "124": ["7C", "01", "02", "03", "04", "05", "06", "07", "08"], - "125": ["7D", "01", "02", "03", "04", "05", "06", "07", "08"], - "126": ["7E", "01", "02", "03", "04", "05", "06", "07", "08"], - "127": ["7F", "01", "02", "03", "04", "05", "06", "07", "08"], - "128": ["80", "01", "02", "03", "04", "05", "06", "07", "08"], - "129": ["81", "01", "02", "03", "04", "05", "06", "07", "08"], - "130": ["82", "01", "02", "03", "04", "05", "06", "07", "08"], - "131": ["83", "01", "02", "03", "04", "05", "06", "07", "08"], - "132": ["84", "01", "02", "03", "04", "05", "06", "07", "08"], - "133": ["85", "01", "02", "03", "04", "05", "06", "07", "08"], - "134": ["86", "01", "02", "03", "04", "05", "06", "07", "08"], - "135": ["87", "01", "02", "03", "04", "05", "06", "07", "08"], - "136": ["88", "01", "02", "03", "04", "05", "06", "07", "08"], - "137": ["89", "01", "02", "03", "04", "05", "06", "07", "08"], - "138": ["8A", "01", "02", "03", "04", "05", "06", "07", "08"], - "139": ["8B", "01", "02", "03", "04", "05", "06", "07", "08"], - "140": ["8C", "01", "02", "03", "04", "05", "06", "07", "08"], - "141": ["8D", "01", "02", "03", "04", "05", "06", "07", "08"], - "142": ["8E", "01", "02", "03", "04", "05", "06", "07", "08"], - "143": ["8F", "01", "02", "03", "04", "05", "06", "07", "08"], - "144": ["90", "01", "02", "03", "04", "05", "06", "07", "08"], - "145": ["91", "01", "02", "03", "04", "05", "06", "07", "08"], - "146": ["92", "01", "02", "03", "04", "05", "06", "07", "08"], - "147": ["93", "01", "02", "03", "04", "05", "06", "07", "08"], - "148": ["94", "01", "02", "03", "04", "05", "06", "07", "08"], - "149": ["95", "01", "02", "03", "04", "05", "06", "07", "08"], - "150": ["96", "01", "02", "03", "04", "05", "06", "07", "08"], - "151": ["97", "01", "02", "03", "04", "05", "06", "07", "08"], - "152": ["98", "01", "02", "03", "04", "05", "06", "07", "08"], - "153": ["99", "01", "02", "03", "04", "05", "06", "07", "08"], - "154": ["9A", "01", "02", "03", "04", "05", "06", "07", "08"], - "155": ["9B", "01", "02", "03", "04", "05", "06", "07", "08"], - "156": ["9C", "01", "02", "03", "04", "05", "06", "07", "08"], - "157": ["9D", "01", "02", "03", "04", "05", "06", "07", "08"], - "158": ["9E", "01", "02", "03", "04", "05", "06", "07", "08"], - "159": ["9F", "01", "02", "03", "04", "05", "06", "07", "08"], - "160": ["A0", "01", "02", "03", "04", "05", "06", "07", "08"], - "161": ["A1", "01", "02", "03", "04", "05", "06", "07", "08"], - "162": ["A2", "01", "02", "03", "04", "05", "06", "07", "08"], - "163": ["A3", "01", "02", "03", "04", "05", "06", "07", "08"], - "164": ["A4", "01", "02", "03", "04", "05", "06", "07", "08"], - "165": ["A5", "01", "02", "03", "04", "05", "06", "07", "08"], - "166": ["A6", "01", "02", "03", "04", "05", "06", "07", "08"], - "167": ["A7", "01", "02", "03", "04", "05", "06", "07", "08"], - "168": ["A8", "01", "02", "03", "04", "05", "06", "07", "08"], - "169": ["A9", "01", "02", "03", "04", "05", "06", "07", "08"], - "170": ["AA", "01", "02", "03", "04", "05", "06", "07", "08"], - "171": ["AB", "01", "02", "03", "04", "05", "06", "07", "08"], - "172": ["AC", "01", "02", "03", "04", "05", "06", "07", "08"], - "173": ["AD", "01", "02", "03", "04", "05", "06", "07", "08"], - "174": ["AE", "01", "02", "03", "04", "05", "06", "07", "08"], - "175": ["AF", "01", "02", "03", "04", "05", "06", "07", "08"], - "176": ["B0", "01", "02", "03", "04", "05", "06", "07", "08"], - "177": ["B1", "01", "02", "03", "04", "05", "06", "07", "08"], - "178": ["B2", "01", "02", "03", "04", "05", "06", "07", "08"], - "179": ["B3", "01", "02", "03", "04", "05", "06", "07", "08"], - "180": ["B4", "01", "02", "03", "04", "05", "06", "07", "08"], - "181": ["B5", "01", "02", "03", "04", "05", "06", "07", "08"], - "182": ["B6", "01", "02", "03", "04", "05", "06", "07", "08"], - "183": ["B7", "01", "02", "03", "04", "05", "06", "07", "08"], - "184": ["B8", "01", "02", "03", "04", "05", "06", "07", "08"], - "185": ["B9", "01", "02", "03", "04", "05", "06", "07", "08"], - "186": ["BA", "01", "02", "03", "04", "05", "06", "07", "08"], - "187": ["BB", "01", "02", "03", "04", "05", "06", "07", "08"], - "188": ["BC", "01", "02", "03", "04", "05", "06", "07", "08"], - "189": ["BD", "01", "02", "03", "04", "05", "06", "07", "08"], - "190": ["BE", "01", "02", "03", "04", "05", "06", "07", "08"], - "191": ["BF", "01", "02", "03", "04", "05", "06", "07", "08"], - "192": ["C0", "01", "02", "03", "04", "05", "06", "07", "08"], - "193": ["C1", "01", "02", "03", "04", "05", "06", "07", "08"], - "194": ["C2", "01", "02", "03", "04", "05", "06", "07", "08"], - "195": ["C3", "01", "02", "03", "04", "05", "06", "07", "08"], - "196": ["C4", "01", "02", "03", "04", "05", "06", "07", "08"], - "197": ["C5", "01", "02", "03", "04", "05", "06", "07", "08"], - "198": ["C6", "01", "02", "03", "04", "05", "06", "07", "08"], - "199": ["C7", "01", "02", "03", "04", "05", "06", "07", "08"], - "200": ["C8", "01", "02", "03", "04", "05", "06", "07", "08"], - "201": ["C9", "01", "02", "03", "04", "05", "06", "07", "08"], - "202": ["CA", "01", "02", "03", "04", "05", "06", "07", "08"], - "203": ["CB", "01", "02", "03", "04", "05", "06", "07", "08"], - "204": ["CC", "01", "02", "03", "04", "05", "06", "07", "08"], - "205": ["CD", "01", "02", "03", "04", "05", "06", "07", "08"], - "206": ["CE", "01", "02", "03", "04", "05", "06", "07", "08"], - "207": ["CF", "01", "02", "03", "04", "05", "06", "07", "08"], - "208": ["D0", "01", "02", "03", "04", "05", "06", "07", "08"], - "209": ["D1", "01", "02", "03", "04", "05", "06", "07", "08"], - "210": ["D2", "01", "02", "03", "04", "05", "06", "07", "08"], - "211": ["D3", "01", "02", "03", "04", "05", "06", "07", "08"], - "212": ["D4", "01", "02", "03", "04", "05", "06", "07", "08"], - "213": ["D5", "01", "02", "03", "04", "05", "06", "07", "08"], - "214": ["D6", "01", "02", "03", "04", "05", "06", "07", "08"], - "215": ["D7", "01", "02", "03", "04", "05", "06", "07", "08"], - "216": ["D8", "01", "02", "03", "04", "05", "06", "07", "08"], - "217": ["D9", "01", "02", "03", "04", "05", "06", "07", "08"], - "218": ["DA", "01", "02", "03", "04", "05", "06", "07", "08"], - "219": ["DB", "01", "02", "03", "04", "05", "06", "07", "08"], - "220": ["DC", "01", "02", "03", "04", "05", "06", "07", "08"], - "221": ["DD", "01", "02", "03", "04", "05", "06", "07", "08"], - "222": ["DE", "01", "02", "03", "04", "05", "06", "07", "08"], - "223": ["DF", "01", "02", "03", "04", "05", "06", "07", "08"], - "224": ["E0", "01", "02", "03", "04", "05", "06", "07", "08"], - "225": ["E1", "01", "02", "03", "04", "05", "06", "07", "08"], - "226": ["E2", "01", "02", "03", "04", "05", "06", "07", "08"], - "227": ["E3", "01", "02", "03", "04", "05", "06", "07", "08"], - "228": ["E4", "01", "02", "03", "04", "05", "06", "07", "08"], - "229": ["E5", "01", "02", "03", "04", "05", "06", "07", "08"], - "230": ["E6", "01", "02", "03", "04", "05", "06", "07", "08"], - "231": ["E7", "01", "02", "03", "04", "05", "06", "07", "08"], - "232": ["E8", "01", "02", "03", "04", "05", "06", "07", "08"], - "233": ["E9", "01", "02", "03", "04", "05", "06", "07", "08"], - "234": ["EA", "01", "02", "03", "04", "05", "06", "07", "08"], - "235": ["EB", "01", "02", "03", "04", "05", "06", "07", "08"], - "236": ["EC", "01", "02", "03", "04", "05", "06", "07", "08"], - "237": ["ED", "01", "02", "03", "04", "05", "06", "07", "08"], - "238": ["EE", "01", "02", "03", "04", "05", "06", "07", "08"], - "239": ["EF", "01", "02", "03", "04", "05", "06", "07", "08"], - "240": ["F0", "01", "02", "03", "04", "05", "06", "07", "08"], - "241": ["F1", "01", "02", "03", "04", "05", "06", "07", "08"], - "242": ["F2", "01", "02", "03", "04", "05", "06", "07", "08"], - "243": ["F3", "01", "02", "03", "04", "05", "06", "07", "08"], - "244": ["F4", "01", "02", "03", "04", "05", "06", "07", "08"], - "245": ["F5", "01", "02", "03", "04", "05", "06", "07", "08"], - "246": ["F6", "01", "02", "03", "04", "05", "06", "07", "08"], - "247": ["F7", "01", "02", "03", "04", "05", "06", "07", "08"], - "248": ["F8", "01", "02", "03", "04", "05", "06", "07", "08"], - "249": ["F9", "01", "02", "03", "04", "05", "06", "07", "08"], - "250": ["FA", "01", "02", "03", "04", "05", "06", "07", "08"], - "251": ["FB", "01", "02", "03", "04", "05", "06", "07", "08"], - "252": ["FC", "01", "02", "03", "04", "05", "06", "07", "08"], - "253": ["FD", "01", "02", "03", "04", "05", "06", "07", "08"], - "254": ["FE", "01", "02", "03", "04", "05", "06", "07", "08"], - "255": ["FE", "10", "20", "30", "40", "50", "60", "70", "8F"] - }, - "text": - { - "t0":"00", - "t1":"01", - "t2":"02", - "t3":"03", - "t4":"04", - "t5":"05", - "t6":"06", - "t7":"07", - "t8":"08", - "t9":"09", - "t10":"0A", - "t11":"0B", - "t12":"0C", - "t13":"0D", - "t14":"0E", - "t15":"0F", - "t16":"10", - "t17":"11", - "t18":"12", - "t19":"13", - "t20":"14", - "t21":"15", - "t22":"16", - "t23":"17", - "t24":"18", - "t25":"19", - "t26":"1A", - "t27":"1B", - "t28":"1C", - "t29":"1D", - "t30":"1E", - "t31":"1F", - "t32":"20", - "t33":"21", - "t34":"22", - "t35":"23", - "t36":"24", - "t37":"25", - "t38":"26", - "t39":"27", - "t40":"28", - "t41":"29", - "t42":"2A", - "t43":"2B", - "t44":"2C", - "t45":"2D", - "t46":"2E", - "t47":"2F", - "t48":"30", - "t49":"31", - "t50":"32", - "t51":"33", - "t52":"34", - "t53":"35", - "t54":"36", - "t55":"37", - "t56":"38", - "t57":"39", - "t58":"3A", - "t59":"3B", - "t60":"3C", - "t61":"3D", - "t62":"3E", - "t63":"3F", - "t64":"40", - "t65":"41", - "t66":"42", - "t67":"43", - "t68":"44", - "t69":"45", - "t70":"46", - "t71":"47", - "t72":"48", - "t73":"49", - "t74":"4A", - "t75":"4B", - "t76":"4C", - "t77":"4D", - "t78":"4E", - "t79":"4F", - "t80":"50", - "t81":"51", - "t82":"52", - "t83":"53", - "t84":"54", - "t85":"55", - "t86":"56", - "t87":"57", - "t88":"58", - "t89":"59", - "t90":"5A", - "t91":"5B", - "t92":"5C", - "t93":"5D", - "t94":"5E", - "t95":"5F", - "t96":"60", - "t97":"61", - "t98":"62", - "t99":"63", - "t100":"64", - "t101":"65", - "t102":"66", - "t103":"67", - "t104":"68", - "t105":"69", - "t106":"6A", - "t107":"6B", - "t108":"6C", - "t109":"6D", - "t110":"6E", - "t111":"6F", - "t112":"70", - "t113":"71", - "t114":"72", - "t115":"73", - "t116":"74", - "t117":"75", - "t118":"76", - "t119":"77", - "t120":"78", - "t121":"79", - "t122":"7A", - "t123":"7B", - "t124":"7C", - "t125":"7D", - "t126":"7E", - "t127":"7F", - "t128":"80", - "t129":"81", - "t130":"82", - "t131":"83", - "t132":"84", - "t133":"85", - "t134":"86", - "t135":"87", - "t136":"88", - "t137":"89", - "t138":"8A", - "t139":"8B", - "t140":"8C", - "t141":"8D", - "t142":"8E", - "t143":"8F", - "t144":"90", - "t145":"91", - "t146":"92", - "t147":"93", - "t148":"94", - "t149":"95", - "t150":"96", - "t151":"97", - "t152":"98", - "t153":"99", - "t154":"9A", - "t155":"9B", - "t156":"9C", - "t157":"9D", - "t158":"9E", - "t159":"9F", - "t160":"A0", - "t161":"A1", - "t162":"A2", - "t163":"A3", - "t164":"A4", - "t165":"A5", - "t166":"A6", - "t167":"A7", - "t168":"A8", - "t169":"A9", - "t170":"AA", - "t171":"AB", - "t172":"AC", - "t173":"AD", - "t174":"AE", - "t175":"AF", - "t176":"B0", - "t177":"B1", - "t178":"B2", - "t179":"B3", - "t180":"B4", - "t181":"B5", - "t182":"B6", - "t183":"B7", - "t184":"B8", - "t185":"B9", - "t186":"BA", - "t187":"BB", - "t188":"BC", - "t189":"BD", - "t190":"BE", - "t191":"BF", - "t192":"C0", - "t193":"C1", - "t194":"C2", - "t195":"C3", - "t196":"C4", - "t197":"C5", - "t198":"C6", - "t199":"C7", - "t200":"C8", - "t201":"C9", - "t202":"CA", - "t203":"CB", - "t204":"CC", - "t205":"CD", - "t206":"CE", - "t207":"CF", - "t208":"D0", - "t209":"D1", - "t210":"D2", - "t211":"D3", - "t212":"D4", - "t213":"D5", - "t214":"D6", - "t215":"D7", - "t216":"D8", - "t217":"D9", - "t218":"DA", - "t219":"DB", - "t220":"DC", - "t221":"DD", - "t222":"DE", - "t223":"DF", - "t224":"E0", - "t225":"E1", - "t226":"E2", - "t227":"E3", - "t228":"E4", - "t229":"E5", - "t230":"E6", - "t231":"E7", - "t232":"E8", - "t233":"E9", - "t234":"EA", - "t235":"EB", - "t236":"EC", - "t237":"ED", - "t238":"EE", - "t239":"EF", - "t240":"F0", - "t241":"F1", - "t242":"F2", - "t243":"F3", - "t244":"F4", - "t245":"F5", - "t246":"F6", - "t247":"F7", - "t248":"F8", - "t249":"F9", - "t250":"FA", - "t251":"FB", - "t252":"FC", - "t253":"FD", - "t254":"FE", - "t255":"FF" - } - }, - "todo": [ - { - "replace": { - "0": "t0", - "1": "t1", - "2": "t2", - "3": "t3", - "4": "t4", - "5": "t5", - "6": "t6", - "7": "t7", - "8": "t8", - "9": "t9", - "10": "t10", - "11": "t11", - "12": "t12", - "13": "t13", - "14": "t14", - "15": "t15", - "16": "t16", - "17": "t17", - "18": "t18", - "19": "t19", - "20": "t20", - "21": "t21", - "22": "t22", - "23": "t23", - "24": "t24", - "25": "t25", - "26": "t26", - "27": "t27", - "28": "t28", - "29": "t29", - "30": "t30", - "31": "t31", - "32": "t32", - "33": "t33", - "34": "t34", - "35": "t35", - "36": "t36", - "37": "t37", - "38": "t38", - "39": "t39", - "40": "t40", - "41": "t41", - "42": "t42", - "43": "t43", - "44": "t44", - "45": "t45", - "46": "t46", - "47": "t47", - "48": "t48", - "49": "t49", - "50": "t50", - "51": "t51", - "52": "t52", - "53": "t53", - "54": "t54", - "55": "t55", - "56": "t56", - "57": "t57", - "58": "t58", - "59": "t59", - "60": "t60", - "61": "t61", - "62": "t62", - "63": "t63", - "64": "t64", - "65": "t65", - "66": "t66", - "67": "t67", - "68": "t68", - "69": "t69", - "70": "t70", - "71": "t71", - "72": "t72", - "73": "t73", - "74": "t74", - "75": "t75", - "76": "t76", - "77": "t77", - "78": "t78", - "79": "t79", - "80": "t80", - "81": "t81", - "82": "t82", - "83": "t83", - "84": "t84", - "85": "t85", - "86": "t86", - "87": "t87", - "88": "t88", - "89": "t89", - "90": "t90", - "91": "t91", - "92": "t92", - "93": "t93", - "94": "t94", - "95": "t95", - "96": "t96", - "97": "t97", - "98": "t98", - "99": "t99", - "100": "t100", - "101": "t101", - "102": "t102", - "103": "t103", - "104": "t104", - "105": "t105", - "106": "t106", - "107": "t107", - "108": "t108", - "109": "t109", - "110": "t110", - "111": "t111", - "112": "t112", - "113": "t113", - "114": "t114", - "115": "t115", - "116": "t116", - "117": "t117", - "118": "t118", - "119": "t119", - "120": "t120", - "121": "t121", - "122": "t122", - "123": "t123", - "124": "t124", - "125": "t125", - "126": "t126", - "127": "t127", - "128": "t128", - "129": "t129", - "130": "t130", - "131": "t131", - "132": "t132", - "133": "t133", - "134": "t134", - "135": "t135", - "136": "t136", - "137": "t137", - "138": "t138", - "139": "t139", - "140": "t140", - "141": "t141", - "142": "t142", - "143": "t143", - "144": "t144", - "145": "t145", - "146": "t146", - "147": "t147", - "148": "t148", - "149": "t149", - "150": "t150", - "151": "t151", - "152": "t152", - "153": "t153", - "154": "t154", - "155": "t155", - "156": "t156", - "157": "t157", - "158": "t158", - "159": "t159", - "160": "t160", - "161": "t161", - "162": "t162", - "163": "t163", - "164": "t164", - "165": "t165", - "166": "t166", - "167": "t167", - "168": "t168", - "169": "t169", - "170": "t170", - "171": "t171", - "172": "t172", - "173": "t173", - "174": "t174", - "175": "t175", - "176": "t176", - "177": "t177", - "178": "t178", - "179": "t179", - "180": "t180", - "181": "t181", - "182": "t182", - "183": "t183", - "184": "t184", - "185": "t185", - "186": "t186", - "187": "t187", - "188": "t188", - "189": "t189", - "190": "t190", - "191": "t191", - "192": "t192", - "193": "t193", - "194": "t194", - "195": "t195", - "196": "t196", - "197": "t197", - "198": "t198", - "199": "t199", - "200": "t200", - "201": "t201", - "202": "t202", - "203": "t203", - "204": "t204", - "205": "t205", - "206": "t206", - "207": "t207", - "208": "t208", - "209": "t209", - "210": "t210", - "211": "t211", - "212": "t212", - "213": "t213", - "214": "t214", - "215": "t215", - "216": "t216", - "217": "t217", - "218": "t218", - "219": "t219", - "220": "t220", - "221": "t221", - "222": "t222", - "223": "t223", - "224": "t224", - "225": "t225", - "226": "t226", - "227": "t227", - "228": "t228", - "229": "t229", - "230": "t230", - "231": "t231", - "232": "t232", - "233": "t233", - "234": "t234", - "235": "t235", - "236": "t236", - "237": "t237", - "238": "t238", - "239": "t239", - "240": "t240", - "241": "t241", - "242": "t242", - "243": "t243", - "244": "t244", - "245": "t245", - "246": "t246", - "247": "t247", - "248": "t248", - "249": "t249", - "250": "t250", - "251": "t251", - "252": "t252", - "253": "t253", - "254": "t254", - "255": "t255" - } - } - ] -} \ No newline at end of file diff --git a/README.md b/README.md index d6ee7e0..0bba837 100644 --- a/README.md +++ b/README.md @@ -498,5 +498,5 @@ Feel free to use email bpatchzaytsev@gmail.com along with the title: [bin4_data]:./IntegrationTests/binaries/bin4.data [bin5_data]:./IntegrationTests/binaries/bin5.data [tohex_json]:./IntegrationTests/scripts/tohex.json -[fromhex_json]:./IntegrationTests/scripts/fromhex1byte.json +[fromhex_json]:./IntegrationTests/scripts/fromhex.json [JSON]:https://www.json.org/json-en.html diff --git a/srcbpatch/CMakeLists.txt b/srcbpatch/CMakeLists.txt index 6420327..2ad9493 100644 --- a/srcbpatch/CMakeLists.txt +++ b/srcbpatch/CMakeLists.txt @@ -46,4 +46,3 @@ add_library(${PROJECT_NAME} ${SOURCE_FILES} ${HEADER_FILES}) # Precompiled header target_precompile_headers(${PROJECT_NAME} PRIVATE stdafx.h) -target_include_directories(${PROJECT_NAME} PUBLIC ${robin_map_SOURCE_DIR}/include) diff --git a/srcbpatch/trie.cpp b/srcbpatch/trie.cpp index 2891133..b7311c5 100644 --- a/srcbpatch/trie.cpp +++ b/srcbpatch/trie.cpp @@ -5,11 +5,8 @@ void Trie::insert(std::string_view key, std::string_view value) std::reference_wrapper node = root; for (char character : key) { - if (!node.get().children.contains(character)) [[unlikely]] { - nodes.emplace_back(); - node.get().children.emplace(character, nodes.back()); - } - node = node.get().children.at(character); + auto [it, inserted] = node.get().children.emplace(character, nodes.emplace_back()); + node = it->second.get(); } node.get().target = value; } diff --git a/srcbpatch/trie.h b/srcbpatch/trie.h index 702f789..c5923c3 100644 --- a/srcbpatch/trie.h +++ b/srcbpatch/trie.h @@ -1,6 +1,7 @@ #pragma once #include +#include /// @brief A node of prefix Trie, each node contains current target (if exist) and child nodes in children. /// And doesn't contain a char of current node From a3bf0dd870499ceb54694b394d4742d4d239ea8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D0=BC=D0=B8=D1=80=20=D0=A7?= =?UTF-8?q?=D0=B8=D0=B6?= Date: Mon, 23 Sep 2024 22:49:44 +0200 Subject: [PATCH 16/16] fix some typo --- srcbpatch/trie.cpp | 4 ++-- srcbpatch/trie.h | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/srcbpatch/trie.cpp b/srcbpatch/trie.cpp index b7311c5..4ca31a5 100644 --- a/srcbpatch/trie.cpp +++ b/srcbpatch/trie.cpp @@ -11,10 +11,10 @@ void Trie::insert(std::string_view key, std::string_view value) node.get().target = value; } -[[nodiscard]] std::pair Trie::searchFullMatch(const std::span& cachedData) const +[[nodiscard]] std::pair Trie::searchFullMatch(std::span cachedData) const { std::reference_wrapper node = root; - for (char c: cachedData) + for (char c : cachedData) { auto res = node.get().children.find(c); if (res == node.get().children.end()) diff --git a/srcbpatch/trie.h b/srcbpatch/trie.h index c5923c3..fde36b1 100644 --- a/srcbpatch/trie.h +++ b/srcbpatch/trie.h @@ -9,18 +9,18 @@ class TrieNode { public: /// a list of child nodes of current node. std::unordered_map> children; - /// target of curretn node (if there are node target at this node in our lexemmePairs --> target is std::nullopt) + /// target of current node (if there are node target at this node in our lexemePairs --> target is std::nullopt) std::optional target; }; -/// @brief Frefix tree class to speed up UniformLexemeReplacer::DoReplace +/// @brief Prefix tree class to speed up UniformLexemeReplacer::DoReplace class Trie final{ public: /// /// Adds a new key-value pair in prefix tree /// - /// source lexemme - /// target lexemme + /// source lexeme + /// target lexeme void insert(std::string_view key, std::string_view value); /// @@ -28,11 +28,11 @@ class Trie final{ /// /// key to find /// string_view: target, bool: FullMatch - [[nodiscard]] std::pair searchFullMatch(const std::span& cachedData) const; + [[nodiscard]] std::pair searchFullMatch(std::span cachedData) const; private: /// a root node, doesn't contains target value TrieNode root; - /// holds all the nodes of Trie. While default Trie uses pointers, we are going to user reference_wrapper to this deque elements + /// holds all the nodes of Trie. While default Trie uses pointers, we are going to use reference_wrapper to this deque elements std::deque nodes; }; \ No newline at end of file