From 327c3174bd0b18880cdf80962cca204f18e73015 Mon Sep 17 00:00:00 2001 From: Matteo Nicoli Date: Wed, 15 Jan 2025 22:02:57 +0100 Subject: [PATCH 1/6] #648 get_entry_matching_value may return more than one value --- components/core/src/clp/DictionaryReader.hpp | 15 +++++++++------ .../core/src/clp/EncodedVariableInterpreter.cpp | 12 +++++++----- components/core/src/clp_s/DictionaryReader.hpp | 15 +++++++++------ components/core/src/clp_s/search/Output.cpp | 6 +++--- .../clp_search/EncodedVariableInterpreter.cpp | 12 +++++++----- components/core/src/glt/DictionaryReader.hpp | 15 +++++++++------ .../core/src/glt/EncodedVariableInterpreter.cpp | 13 ++++++++----- 7 files changed, 52 insertions(+), 36 deletions(-) diff --git a/components/core/src/clp/DictionaryReader.hpp b/components/core/src/clp/DictionaryReader.hpp index 694240ad5..05f051b71 100644 --- a/components/core/src/clp/DictionaryReader.hpp +++ b/components/core/src/clp/DictionaryReader.hpp @@ -82,9 +82,9 @@ class DictionaryReader { * Gets the entry exactly matching the given search string * @param search_string * @param ignore_case - * @return nullptr if an exact match is not found, the entry otherwise + * @return a (possibly empty) list of entries */ - EntryType const* + std::vector get_entry_matching_value(std::string const& search_string, bool ignore_case) const; /** * Gets the entries that match a given wildcard string @@ -233,26 +233,29 @@ std::string const& DictionaryReader::get_value(Dict } template -EntryType const* DictionaryReader::get_entry_matching_value( +std::vector +DictionaryReader::get_entry_matching_value( std::string const& search_string, bool ignore_case ) const { + std::vector entries; if (false == ignore_case) { for (auto const& entry : m_entries) { if (entry.get_value() == search_string) { - return &entry; + entries.push_back(&entry); + return entries; /* early exit for case sensitive branch */ } } } else { auto const& search_string_uppercase = boost::algorithm::to_upper_copy(search_string); for (auto const& entry : m_entries) { if (boost::algorithm::to_upper_copy(entry.get_value()) == search_string_uppercase) { - return &entry; + entries.push_back(&entry); } } } - return nullptr; + return entries; } template diff --git a/components/core/src/clp/EncodedVariableInterpreter.cpp b/components/core/src/clp/EncodedVariableInterpreter.cpp index 8170f2ddc..d1b07dd44 100644 --- a/components/core/src/clp/EncodedVariableInterpreter.cpp +++ b/components/core/src/clp/EncodedVariableInterpreter.cpp @@ -386,15 +386,17 @@ bool EncodedVariableInterpreter::encode_and_search_dictionary( LogTypeDictionaryEntry::add_float_var(logtype); sub_query.add_non_dict_var(encoded_var); } else { - auto entry = var_dict.get_entry_matching_value(var_str, ignore_case); - if (nullptr == entry) { + auto entries = var_dict.get_entry_matching_value(var_str, ignore_case); + if (entries.empty()) { // Not in dictionary return false; } - encoded_var = encode_var_dict_id(entry->get_id()); + for (auto i = 0; i < entries.size(); i++) { + encoded_var = encode_var_dict_id(entries[i]->get_id()); - LogTypeDictionaryEntry::add_dict_var(logtype); - sub_query.add_dict_var(encoded_var, entry); + LogTypeDictionaryEntry::add_dict_var(logtype); + sub_query.add_dict_var(encoded_var, entries[i]); + } } return true; diff --git a/components/core/src/clp_s/DictionaryReader.hpp b/components/core/src/clp_s/DictionaryReader.hpp index a5f1582cc..5646d7b69 100644 --- a/components/core/src/clp_s/DictionaryReader.hpp +++ b/components/core/src/clp_s/DictionaryReader.hpp @@ -64,9 +64,9 @@ class DictionaryReader { * Gets the entry exactly matching the given search string * @param search_string * @param ignore_case - * @return nullptr if an exact match is not found, the entry otherwise + * @return a (possibly empty) list of entries */ - EntryType const* + std::vector get_entry_matching_value(std::string const& search_string, bool ignore_case) const; /** @@ -156,26 +156,29 @@ std::string const& DictionaryReader::get_value(Dict } template -EntryType const* DictionaryReader::get_entry_matching_value( +std::vector +DictionaryReader::get_entry_matching_value( std::string const& search_string, bool ignore_case ) const { + std::vector entries; if (false == ignore_case) { for (auto const& entry : m_entries) { if (entry.get_value() == search_string) { - return &entry; + entries.push_back(&entry); + return entries; /* early exit for case sensitive branch */ } } } else { auto const& search_string_uppercase = boost::algorithm::to_upper_copy(search_string); for (auto const& entry : m_entries) { if (boost::algorithm::to_upper_copy(entry.get_value()) == search_string_uppercase) { - return &entry; + entries.push_back(&entry); } } } - return nullptr; + return entries; } template diff --git a/components/core/src/clp_s/search/Output.cpp b/components/core/src/clp_s/search/Output.cpp index 4833fab94..00da0e671 100644 --- a/components/core/src/clp_s/search/Output.cpp +++ b/components/core/src/clp_s/search/Output.cpp @@ -932,13 +932,13 @@ void Output::populate_string_queries(std::shared_ptr const& expr) { } } - auto const* entry = m_var_dict->get_entry_matching_value( + auto entries = m_var_dict->get_entry_matching_value( unescaped_query_string, m_ignore_case ); - if (entry != nullptr) { - matching_vars.insert(entry->get_id()); + for (auto i = 0; i < entries.size(); i++) { + matching_vars.insert(entries[i]->get_id()); } } else if (EncodedVariableInterpreter:: wildcard_search_dictionary_and_get_encoded_matches( diff --git a/components/core/src/clp_s/search/clp_search/EncodedVariableInterpreter.cpp b/components/core/src/clp_s/search/clp_search/EncodedVariableInterpreter.cpp index 241f3dde7..febc5407e 100644 --- a/components/core/src/clp_s/search/clp_search/EncodedVariableInterpreter.cpp +++ b/components/core/src/clp_s/search/clp_search/EncodedVariableInterpreter.cpp @@ -34,15 +34,17 @@ bool EncodedVariableInterpreter::encode_and_search_dictionary( LogTypeDictionaryEntry::add_double_var(logtype); sub_query.add_non_dict_var(encoded_var); } else { - auto entry = var_dict.get_entry_matching_value(var_str, ignore_case); - if (nullptr == entry) { + auto entries = var_dict.get_entry_matching_value(var_str, ignore_case); + if (entries.empty()) { // Not in dictionary return false; } - encoded_var = VariableEncoder::encode_var_dict_id(entry->get_id()); + for (auto i = 0; i < entries.size(); i++) { + encoded_var = VariableEncoder::encode_var_dict_id(entries[i]->get_id()); - LogTypeDictionaryEntry::add_non_double_var(logtype); - sub_query.add_dict_var(encoded_var, entry); + LogTypeDictionaryEntry::add_non_double_var(logtype); + sub_query.add_dict_var(encoded_var, entries[i]); + } } return true; diff --git a/components/core/src/glt/DictionaryReader.hpp b/components/core/src/glt/DictionaryReader.hpp index 7eb4ac8f2..f056c81f1 100644 --- a/components/core/src/glt/DictionaryReader.hpp +++ b/components/core/src/glt/DictionaryReader.hpp @@ -82,9 +82,9 @@ class DictionaryReader { * Gets the entry exactly matching the given search string * @param search_string * @param ignore_case - * @return nullptr if an exact match is not found, the entry otherwise + * @return a (possibly empty) list of entries */ - EntryType const* + std::vector get_entry_matching_value(std::string const& search_string, bool ignore_case) const; /** * Gets the entries that match a given wildcard string @@ -228,26 +228,29 @@ std::string const& DictionaryReader::get_value(Dict } template -EntryType const* DictionaryReader::get_entry_matching_value( +std::vector +DictionaryReader::get_entry_matching_value( std::string const& search_string, bool ignore_case ) const { + std::vector entries; if (false == ignore_case) { for (auto const& entry : m_entries) { if (entry.get_value() == search_string) { - return &entry; + entries.push_back(&entry); + return entries; /* early exit for case sensitive branch */ } } } else { auto const& search_string_uppercase = boost::algorithm::to_upper_copy(search_string); for (auto const& entry : m_entries) { if (boost::algorithm::to_upper_copy(entry.get_value()) == search_string_uppercase) { - return &entry; + entries.push_back(&entry); } } } - return nullptr; + return entries; } template diff --git a/components/core/src/glt/EncodedVariableInterpreter.cpp b/components/core/src/glt/EncodedVariableInterpreter.cpp index e509b88af..d3efccb17 100644 --- a/components/core/src/glt/EncodedVariableInterpreter.cpp +++ b/components/core/src/glt/EncodedVariableInterpreter.cpp @@ -451,15 +451,18 @@ bool EncodedVariableInterpreter::encode_and_search_dictionary( LogTypeDictionaryEntry::add_float_var(logtype); sub_query.add_non_dict_var(encoded_var); } else { - auto entry = var_dict.get_entry_matching_value(var_str, ignore_case); - if (nullptr == entry) { + auto entries = var_dict.get_entry_matching_value(var_str, ignore_case); + if (entries.empty()) { // Not in dictionary return false; } - encoded_var = encode_var_dict_id(entry->get_id()); - LogTypeDictionaryEntry::add_dict_var(logtype); - sub_query.add_dict_var(encoded_var, entry); + for (auto i = 0; i < entries.size(); i++) { + encoded_var = encode_var_dict_id(entries[i]->get_id()); + + LogTypeDictionaryEntry::add_dict_var(logtype); + sub_query.add_dict_var(encoded_var, entries[i]); + } } return true; From b4fdba211f7bb507e1e62f6acec0650db64e50d0 Mon Sep 17 00:00:00 2001 From: Matteo Nicoli Date: Sat, 18 Jan 2025 02:05:24 +0100 Subject: [PATCH 2/6] #648 fix encode_and_search_dictionary --- components/core/src/clp/DictionaryReader.hpp | 10 +++++----- components/core/src/clp/EncodedVariableInterpreter.cpp | 10 ++++++---- components/core/src/clp_s/DictionaryReader.hpp | 10 +++++----- components/core/src/clp_s/search/Output.cpp | 4 ++-- .../search/clp_search/EncodedVariableInterpreter.cpp | 10 ++++++---- components/core/src/glt/DictionaryReader.hpp | 10 +++++----- components/core/src/glt/EncodedVariableInterpreter.cpp | 10 +++++----- 7 files changed, 34 insertions(+), 30 deletions(-) diff --git a/components/core/src/clp/DictionaryReader.hpp b/components/core/src/clp/DictionaryReader.hpp index 05f051b71..8ac07ddb9 100644 --- a/components/core/src/clp/DictionaryReader.hpp +++ b/components/core/src/clp/DictionaryReader.hpp @@ -84,7 +84,7 @@ class DictionaryReader { * @param ignore_case * @return a (possibly empty) list of entries */ - std::vector + std::unordered_set get_entry_matching_value(std::string const& search_string, bool ignore_case) const; /** * Gets the entries that match a given wildcard string @@ -233,16 +233,16 @@ std::string const& DictionaryReader::get_value(Dict } template -std::vector +std::unordered_set DictionaryReader::get_entry_matching_value( std::string const& search_string, bool ignore_case ) const { - std::vector entries; + std::unordered_set entries; if (false == ignore_case) { for (auto const& entry : m_entries) { if (entry.get_value() == search_string) { - entries.push_back(&entry); + entries.insert(&entry); return entries; /* early exit for case sensitive branch */ } } @@ -250,7 +250,7 @@ DictionaryReader::get_entry_matching_value( auto const& search_string_uppercase = boost::algorithm::to_upper_copy(search_string); for (auto const& entry : m_entries) { if (boost::algorithm::to_upper_copy(entry.get_value()) == search_string_uppercase) { - entries.push_back(&entry); + entries.insert(&entry); } } } diff --git a/components/core/src/clp/EncodedVariableInterpreter.cpp b/components/core/src/clp/EncodedVariableInterpreter.cpp index d1b07dd44..ca9591dec 100644 --- a/components/core/src/clp/EncodedVariableInterpreter.cpp +++ b/components/core/src/clp/EncodedVariableInterpreter.cpp @@ -387,16 +387,18 @@ bool EncodedVariableInterpreter::encode_and_search_dictionary( sub_query.add_non_dict_var(encoded_var); } else { auto entries = var_dict.get_entry_matching_value(var_str, ignore_case); + std::unordered_set encoded_vars; + if (entries.empty()) { // Not in dictionary return false; } - for (auto i = 0; i < entries.size(); i++) { - encoded_var = encode_var_dict_id(entries[i]->get_id()); - LogTypeDictionaryEntry::add_dict_var(logtype); - sub_query.add_dict_var(encoded_var, entries[i]); + for (auto entry : entries) { + encoded_vars.insert(encode_var_dict_id(entry->get_id())); } + LogTypeDictionaryEntry::add_dict_var(logtype); + sub_query.add_imprecise_dict_var(encoded_vars, entries); } return true; diff --git a/components/core/src/clp_s/DictionaryReader.hpp b/components/core/src/clp_s/DictionaryReader.hpp index 5646d7b69..3fcf0c578 100644 --- a/components/core/src/clp_s/DictionaryReader.hpp +++ b/components/core/src/clp_s/DictionaryReader.hpp @@ -66,7 +66,7 @@ class DictionaryReader { * @param ignore_case * @return a (possibly empty) list of entries */ - std::vector + std::unordered_set get_entry_matching_value(std::string const& search_string, bool ignore_case) const; /** @@ -156,16 +156,16 @@ std::string const& DictionaryReader::get_value(Dict } template -std::vector +std::unordered_set DictionaryReader::get_entry_matching_value( std::string const& search_string, bool ignore_case ) const { - std::vector entries; + std::unordered_set entries; if (false == ignore_case) { for (auto const& entry : m_entries) { if (entry.get_value() == search_string) { - entries.push_back(&entry); + entries.insert(&entry); return entries; /* early exit for case sensitive branch */ } } @@ -173,7 +173,7 @@ DictionaryReader::get_entry_matching_value( auto const& search_string_uppercase = boost::algorithm::to_upper_copy(search_string); for (auto const& entry : m_entries) { if (boost::algorithm::to_upper_copy(entry.get_value()) == search_string_uppercase) { - entries.push_back(&entry); + entries.insert(&entry); } } } diff --git a/components/core/src/clp_s/search/Output.cpp b/components/core/src/clp_s/search/Output.cpp index 00da0e671..e2c268b79 100644 --- a/components/core/src/clp_s/search/Output.cpp +++ b/components/core/src/clp_s/search/Output.cpp @@ -937,8 +937,8 @@ void Output::populate_string_queries(std::shared_ptr const& expr) { m_ignore_case ); - for (auto i = 0; i < entries.size(); i++) { - matching_vars.insert(entries[i]->get_id()); + for (auto entry : entries) { + matching_vars.insert(entry->get_id()); } } else if (EncodedVariableInterpreter:: wildcard_search_dictionary_and_get_encoded_matches( diff --git a/components/core/src/clp_s/search/clp_search/EncodedVariableInterpreter.cpp b/components/core/src/clp_s/search/clp_search/EncodedVariableInterpreter.cpp index febc5407e..6eb503e3f 100644 --- a/components/core/src/clp_s/search/clp_search/EncodedVariableInterpreter.cpp +++ b/components/core/src/clp_s/search/clp_search/EncodedVariableInterpreter.cpp @@ -35,16 +35,18 @@ bool EncodedVariableInterpreter::encode_and_search_dictionary( sub_query.add_non_dict_var(encoded_var); } else { auto entries = var_dict.get_entry_matching_value(var_str, ignore_case); + std::unordered_set encoded_vars; + if (entries.empty()) { // Not in dictionary return false; } - for (auto i = 0; i < entries.size(); i++) { - encoded_var = VariableEncoder::encode_var_dict_id(entries[i]->get_id()); - LogTypeDictionaryEntry::add_non_double_var(logtype); - sub_query.add_dict_var(encoded_var, entries[i]); + for (auto entry : entries) { + encoded_vars.insert(VariableEncoder::encode_var_dict_id(entry->get_id())); } + LogTypeDictionaryEntry::add_non_double_var(logtype); + sub_query.add_imprecise_dict_var(encoded_vars, entries); } return true; diff --git a/components/core/src/glt/DictionaryReader.hpp b/components/core/src/glt/DictionaryReader.hpp index f056c81f1..1c6775eef 100644 --- a/components/core/src/glt/DictionaryReader.hpp +++ b/components/core/src/glt/DictionaryReader.hpp @@ -84,7 +84,7 @@ class DictionaryReader { * @param ignore_case * @return a (possibly empty) list of entries */ - std::vector + std::unordered_set get_entry_matching_value(std::string const& search_string, bool ignore_case) const; /** * Gets the entries that match a given wildcard string @@ -228,16 +228,16 @@ std::string const& DictionaryReader::get_value(Dict } template -std::vector +std::unordered_set DictionaryReader::get_entry_matching_value( std::string const& search_string, bool ignore_case ) const { - std::vector entries; + std::unordered_set entries; if (false == ignore_case) { for (auto const& entry : m_entries) { if (entry.get_value() == search_string) { - entries.push_back(&entry); + entries.insert(&entry); return entries; /* early exit for case sensitive branch */ } } @@ -245,7 +245,7 @@ DictionaryReader::get_entry_matching_value( auto const& search_string_uppercase = boost::algorithm::to_upper_copy(search_string); for (auto const& entry : m_entries) { if (boost::algorithm::to_upper_copy(entry.get_value()) == search_string_uppercase) { - entries.push_back(&entry); + entries.insert(&entry); } } } diff --git a/components/core/src/glt/EncodedVariableInterpreter.cpp b/components/core/src/glt/EncodedVariableInterpreter.cpp index d3efccb17..71ffea103 100644 --- a/components/core/src/glt/EncodedVariableInterpreter.cpp +++ b/components/core/src/glt/EncodedVariableInterpreter.cpp @@ -452,17 +452,17 @@ bool EncodedVariableInterpreter::encode_and_search_dictionary( sub_query.add_non_dict_var(encoded_var); } else { auto entries = var_dict.get_entry_matching_value(var_str, ignore_case); + std::unordered_set encoded_vars; if (entries.empty()) { // Not in dictionary return false; } - for (auto i = 0; i < entries.size(); i++) { - encoded_var = encode_var_dict_id(entries[i]->get_id()); - - LogTypeDictionaryEntry::add_dict_var(logtype); - sub_query.add_dict_var(encoded_var, entries[i]); + for (auto entry : entries) { + encoded_vars.insert(encode_var_dict_id(entry->get_id())); } + LogTypeDictionaryEntry::add_dict_var(logtype); + sub_query.add_imprecise_dict_var(encoded_vars, entries); } return true; From 8a515f8bfeb16292cfeb5e49917598264d598185 Mon Sep 17 00:00:00 2001 From: Matteo Nicoli Date: Tue, 21 Jan 2025 02:19:03 +0100 Subject: [PATCH 3/6] #648 added test section --- components/core/src/clp/DictionaryReader.hpp | 2 +- .../core/src/clp_s/DictionaryReader.hpp | 2 +- components/core/src/glt/DictionaryReader.hpp | 2 +- .../tests/test-EncodedVariableInterpreter.cpp | 37 +++++++++++++++++++ 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/components/core/src/clp/DictionaryReader.hpp b/components/core/src/clp/DictionaryReader.hpp index 8ac07ddb9..0472d99ab 100644 --- a/components/core/src/clp/DictionaryReader.hpp +++ b/components/core/src/clp/DictionaryReader.hpp @@ -82,7 +82,7 @@ class DictionaryReader { * Gets the entry exactly matching the given search string * @param search_string * @param ignore_case - * @return a (possibly empty) list of entries + * @return a (possibly empty) set of entries */ std::unordered_set get_entry_matching_value(std::string const& search_string, bool ignore_case) const; diff --git a/components/core/src/clp_s/DictionaryReader.hpp b/components/core/src/clp_s/DictionaryReader.hpp index 3fcf0c578..9cbfc871b 100644 --- a/components/core/src/clp_s/DictionaryReader.hpp +++ b/components/core/src/clp_s/DictionaryReader.hpp @@ -64,7 +64,7 @@ class DictionaryReader { * Gets the entry exactly matching the given search string * @param search_string * @param ignore_case - * @return a (possibly empty) list of entries + * @return a (possibly empty) set of entries */ std::unordered_set get_entry_matching_value(std::string const& search_string, bool ignore_case) const; diff --git a/components/core/src/glt/DictionaryReader.hpp b/components/core/src/glt/DictionaryReader.hpp index 1c6775eef..f96695fee 100644 --- a/components/core/src/glt/DictionaryReader.hpp +++ b/components/core/src/glt/DictionaryReader.hpp @@ -82,7 +82,7 @@ class DictionaryReader { * Gets the entry exactly matching the given search string * @param search_string * @param ignore_case - * @return a (possibly empty) list of entries + * @return a (possibly empty) set of entries */ std::unordered_set get_entry_matching_value(std::string const& search_string, bool ignore_case) const; diff --git a/components/core/tests/test-EncodedVariableInterpreter.cpp b/components/core/tests/test-EncodedVariableInterpreter.cpp index 6ab0687a9..70b990bc4 100644 --- a/components/core/tests/test-EncodedVariableInterpreter.cpp +++ b/components/core/tests/test-EncodedVariableInterpreter.cpp @@ -376,6 +376,43 @@ TEST_CASE("EncodedVariableInterpreter", "[EncodedVariableInterpreter]") { )); } + SECTION("Test multiple metching values") { + char const cVarDictPath[] = "var.dict"; + char const cVarSegmentIndexPath[] = "var.segindex"; + vector var_strs = {"python2.7.3", "Python2.7.3", "PyThOn2.7.3", "PYTHON2.7.3"}; + clp::VariableDictionaryWriter var_dict_writer; + var_dict_writer.open(cVarDictPath, cVarSegmentIndexPath, cVariableDictionaryIdMax); + vector encoded_vars; + vector var_ids; + clp::LogTypeDictionaryEntry logtype_dict_entry; + for (auto var_str : var_strs) { + EncodedVariableInterpreter::encode_and_add_to_dictionary( + var_str, + logtype_dict_entry, + var_dict_writer, + encoded_vars, + var_ids + ); + } + var_dict_writer.close(); + + clp::VariableDictionaryReader var_dict_reader; + var_dict_reader.open(cVarDictPath, cVarSegmentIndexPath); + var_dict_reader.read_new_entries(); + + REQUIRE(var_dict_reader.get_entry_matching_value(var_strs[0], true).size() + == var_strs.size()); + REQUIRE(var_dict_reader.get_entry_matching_value(var_strs[0], false).size() == 1); + + var_dict_reader.close(); + + // Clean-up + int retval = unlink(cVarDictPath); + REQUIRE(0 == retval); + retval = unlink(cVarSegmentIndexPath); + REQUIRE(0 == retval); + } + SECTION("Test encoding and decoding") { string msg; From aaac6a05bf7d55f03e1f2945badb43125aa331e8 Mon Sep 17 00:00:00 2001 From: Matteo Nicoli Date: Thu, 23 Jan 2025 02:56:18 +0100 Subject: [PATCH 4/6] #648 fix --- components/core/src/clp/DictionaryReader.hpp | 12 ++++++------ .../src/clp/EncodedVariableInterpreter.cpp | 18 +++++++++++++++--- components/core/src/clp_s/DictionaryReader.hpp | 12 ++++++------ .../clp_search/EncodedVariableInterpreter.cpp | 18 +++++++++++++++--- components/core/src/glt/DictionaryReader.hpp | 15 ++++++--------- .../src/glt/EncodedVariableInterpreter.cpp | 11 ++++------- 6 files changed, 52 insertions(+), 34 deletions(-) diff --git a/components/core/src/clp/DictionaryReader.hpp b/components/core/src/clp/DictionaryReader.hpp index 0472d99ab..a994fe091 100644 --- a/components/core/src/clp/DictionaryReader.hpp +++ b/components/core/src/clp/DictionaryReader.hpp @@ -82,9 +82,9 @@ class DictionaryReader { * Gets the entry exactly matching the given search string * @param search_string * @param ignore_case - * @return a (possibly empty) set of entries + * @return a (possibly empty) vector of entries */ - std::unordered_set + std::vector get_entry_matching_value(std::string const& search_string, bool ignore_case) const; /** * Gets the entries that match a given wildcard string @@ -233,16 +233,16 @@ std::string const& DictionaryReader::get_value(Dict } template -std::unordered_set +std::vector DictionaryReader::get_entry_matching_value( std::string const& search_string, bool ignore_case ) const { - std::unordered_set entries; + std::vector entries; if (false == ignore_case) { for (auto const& entry : m_entries) { if (entry.get_value() == search_string) { - entries.insert(&entry); + entries.push_back(&entry); return entries; /* early exit for case sensitive branch */ } } @@ -250,7 +250,7 @@ DictionaryReader::get_entry_matching_value( auto const& search_string_uppercase = boost::algorithm::to_upper_copy(search_string); for (auto const& entry : m_entries) { if (boost::algorithm::to_upper_copy(entry.get_value()) == search_string_uppercase) { - entries.insert(&entry); + entries.push_back(&entry); } } } diff --git a/components/core/src/clp/EncodedVariableInterpreter.cpp b/components/core/src/clp/EncodedVariableInterpreter.cpp index ca9591dec..e05803b61 100644 --- a/components/core/src/clp/EncodedVariableInterpreter.cpp +++ b/components/core/src/clp/EncodedVariableInterpreter.cpp @@ -387,18 +387,30 @@ bool EncodedVariableInterpreter::encode_and_search_dictionary( sub_query.add_non_dict_var(encoded_var); } else { auto entries = var_dict.get_entry_matching_value(var_str, ignore_case); - std::unordered_set encoded_vars; if (entries.empty()) { // Not in dictionary return false; } + LogTypeDictionaryEntry::add_dict_var(logtype); + + if (entries.size() == 1) { + clp::VariableDictionaryEntry const* entry = entries[0]; + auto encoded_var = encode_var_dict_id(entry->get_id()); + sub_query.add_dict_var(encoded_var, entry); + return true; + } + + std::unordered_set encoded_vars; + std::unordered_set entries_set( + entries.begin(), + entries.end() + ); for (auto entry : entries) { encoded_vars.insert(encode_var_dict_id(entry->get_id())); } - LogTypeDictionaryEntry::add_dict_var(logtype); - sub_query.add_imprecise_dict_var(encoded_vars, entries); + sub_query.add_imprecise_dict_var(encoded_vars, entries_set); } return true; diff --git a/components/core/src/clp_s/DictionaryReader.hpp b/components/core/src/clp_s/DictionaryReader.hpp index 9cbfc871b..20b63fd8d 100644 --- a/components/core/src/clp_s/DictionaryReader.hpp +++ b/components/core/src/clp_s/DictionaryReader.hpp @@ -64,9 +64,9 @@ class DictionaryReader { * Gets the entry exactly matching the given search string * @param search_string * @param ignore_case - * @return a (possibly empty) set of entries + * @return a (possibly empty) vector of entries */ - std::unordered_set + std::vector get_entry_matching_value(std::string const& search_string, bool ignore_case) const; /** @@ -156,16 +156,16 @@ std::string const& DictionaryReader::get_value(Dict } template -std::unordered_set +std::vector DictionaryReader::get_entry_matching_value( std::string const& search_string, bool ignore_case ) const { - std::unordered_set entries; + std::vector entries; if (false == ignore_case) { for (auto const& entry : m_entries) { if (entry.get_value() == search_string) { - entries.insert(&entry); + entries.push_back(&entry); return entries; /* early exit for case sensitive branch */ } } @@ -173,7 +173,7 @@ DictionaryReader::get_entry_matching_value( auto const& search_string_uppercase = boost::algorithm::to_upper_copy(search_string); for (auto const& entry : m_entries) { if (boost::algorithm::to_upper_copy(entry.get_value()) == search_string_uppercase) { - entries.insert(&entry); + entries.push_back(&entry); } } } diff --git a/components/core/src/clp_s/search/clp_search/EncodedVariableInterpreter.cpp b/components/core/src/clp_s/search/clp_search/EncodedVariableInterpreter.cpp index 6eb503e3f..b77537b06 100644 --- a/components/core/src/clp_s/search/clp_search/EncodedVariableInterpreter.cpp +++ b/components/core/src/clp_s/search/clp_search/EncodedVariableInterpreter.cpp @@ -35,18 +35,30 @@ bool EncodedVariableInterpreter::encode_and_search_dictionary( sub_query.add_non_dict_var(encoded_var); } else { auto entries = var_dict.get_entry_matching_value(var_str, ignore_case); - std::unordered_set encoded_vars; if (entries.empty()) { // Not in dictionary return false; } + LogTypeDictionaryEntry::add_non_double_var(logtype); + + if (entries.size() == 1) { + VariableDictionaryEntry const* entry = entries[0]; + auto encoded_var = VariableEncoder::encode_var_dict_id(entry->get_id()); + sub_query.add_dict_var(encoded_var, entry); + return true; + } + + std::unordered_set encoded_vars; + std::unordered_set entries_set( + entries.begin(), + entries.end() + ); for (auto entry : entries) { encoded_vars.insert(VariableEncoder::encode_var_dict_id(entry->get_id())); } - LogTypeDictionaryEntry::add_non_double_var(logtype); - sub_query.add_imprecise_dict_var(encoded_vars, entries); + sub_query.add_imprecise_dict_var(encoded_vars, entries_set); } return true; diff --git a/components/core/src/glt/DictionaryReader.hpp b/components/core/src/glt/DictionaryReader.hpp index f96695fee..7eb4ac8f2 100644 --- a/components/core/src/glt/DictionaryReader.hpp +++ b/components/core/src/glt/DictionaryReader.hpp @@ -82,9 +82,9 @@ class DictionaryReader { * Gets the entry exactly matching the given search string * @param search_string * @param ignore_case - * @return a (possibly empty) set of entries + * @return nullptr if an exact match is not found, the entry otherwise */ - std::unordered_set + EntryType const* get_entry_matching_value(std::string const& search_string, bool ignore_case) const; /** * Gets the entries that match a given wildcard string @@ -228,29 +228,26 @@ std::string const& DictionaryReader::get_value(Dict } template -std::unordered_set -DictionaryReader::get_entry_matching_value( +EntryType const* DictionaryReader::get_entry_matching_value( std::string const& search_string, bool ignore_case ) const { - std::unordered_set entries; if (false == ignore_case) { for (auto const& entry : m_entries) { if (entry.get_value() == search_string) { - entries.insert(&entry); - return entries; /* early exit for case sensitive branch */ + return &entry; } } } else { auto const& search_string_uppercase = boost::algorithm::to_upper_copy(search_string); for (auto const& entry : m_entries) { if (boost::algorithm::to_upper_copy(entry.get_value()) == search_string_uppercase) { - entries.insert(&entry); + return &entry; } } } - return entries; + return nullptr; } template diff --git a/components/core/src/glt/EncodedVariableInterpreter.cpp b/components/core/src/glt/EncodedVariableInterpreter.cpp index 71ffea103..e509b88af 100644 --- a/components/core/src/glt/EncodedVariableInterpreter.cpp +++ b/components/core/src/glt/EncodedVariableInterpreter.cpp @@ -451,18 +451,15 @@ bool EncodedVariableInterpreter::encode_and_search_dictionary( LogTypeDictionaryEntry::add_float_var(logtype); sub_query.add_non_dict_var(encoded_var); } else { - auto entries = var_dict.get_entry_matching_value(var_str, ignore_case); - std::unordered_set encoded_vars; - if (entries.empty()) { + auto entry = var_dict.get_entry_matching_value(var_str, ignore_case); + if (nullptr == entry) { // Not in dictionary return false; } + encoded_var = encode_var_dict_id(entry->get_id()); - for (auto entry : entries) { - encoded_vars.insert(encode_var_dict_id(entry->get_id())); - } LogTypeDictionaryEntry::add_dict_var(logtype); - sub_query.add_imprecise_dict_var(encoded_vars, entries); + sub_query.add_dict_var(encoded_var, entry); } return true; From aecae495bd23fac2a8ec63add02b45ad46ff6edd Mon Sep 17 00:00:00 2001 From: Matteo Nicoli Date: Sat, 25 Jan 2025 02:50:16 +0100 Subject: [PATCH 5/6] review fix --- components/core/src/clp/DictionaryReader.hpp | 3 ++- .../core/src/clp/EncodedVariableInterpreter.cpp | 11 +++++------ components/core/src/clp_s/DictionaryReader.hpp | 3 ++- components/core/src/clp_s/search/Output.cpp | 4 ++-- .../search/clp_search/EncodedVariableInterpreter.cpp | 9 ++++----- .../core/tests/test-EncodedVariableInterpreter.cpp | 12 ++++++++---- 6 files changed, 23 insertions(+), 19 deletions(-) diff --git a/components/core/src/clp/DictionaryReader.hpp b/components/core/src/clp/DictionaryReader.hpp index a994fe091..6dfaa282b 100644 --- a/components/core/src/clp/DictionaryReader.hpp +++ b/components/core/src/clp/DictionaryReader.hpp @@ -243,7 +243,8 @@ DictionaryReader::get_entry_matching_value( for (auto const& entry : m_entries) { if (entry.get_value() == search_string) { entries.push_back(&entry); - return entries; /* early exit for case sensitive branch */ + // early exit for case sensitive branch + return entries; } } } else { diff --git a/components/core/src/clp/EncodedVariableInterpreter.cpp b/components/core/src/clp/EncodedVariableInterpreter.cpp index e05803b61..6a64e2542 100644 --- a/components/core/src/clp/EncodedVariableInterpreter.cpp +++ b/components/core/src/clp/EncodedVariableInterpreter.cpp @@ -386,8 +386,7 @@ bool EncodedVariableInterpreter::encode_and_search_dictionary( LogTypeDictionaryEntry::add_float_var(logtype); sub_query.add_non_dict_var(encoded_var); } else { - auto entries = var_dict.get_entry_matching_value(var_str, ignore_case); - + auto const entries = var_dict.get_entry_matching_value(var_str, ignore_case); if (entries.empty()) { // Not in dictionary return false; @@ -396,18 +395,18 @@ bool EncodedVariableInterpreter::encode_and_search_dictionary( LogTypeDictionaryEntry::add_dict_var(logtype); if (entries.size() == 1) { - clp::VariableDictionaryEntry const* entry = entries[0]; - auto encoded_var = encode_var_dict_id(entry->get_id()); + auto const* entry = entries.at(0); + encoded_var = encode_var_dict_id(entry->get_id()); sub_query.add_dict_var(encoded_var, entry); return true; } std::unordered_set encoded_vars; - std::unordered_set entries_set( + std::unordered_set const entries_set( entries.begin(), entries.end() ); - for (auto entry : entries) { + for (auto const entry : entries) { encoded_vars.insert(encode_var_dict_id(entry->get_id())); } sub_query.add_imprecise_dict_var(encoded_vars, entries_set); diff --git a/components/core/src/clp_s/DictionaryReader.hpp b/components/core/src/clp_s/DictionaryReader.hpp index 20b63fd8d..2d44b1a19 100644 --- a/components/core/src/clp_s/DictionaryReader.hpp +++ b/components/core/src/clp_s/DictionaryReader.hpp @@ -166,7 +166,8 @@ DictionaryReader::get_entry_matching_value( for (auto const& entry : m_entries) { if (entry.get_value() == search_string) { entries.push_back(&entry); - return entries; /* early exit for case sensitive branch */ + // early exit for case sensitive branch + return entries; } } } else { diff --git a/components/core/src/clp_s/search/Output.cpp b/components/core/src/clp_s/search/Output.cpp index e2c268b79..6276c346b 100644 --- a/components/core/src/clp_s/search/Output.cpp +++ b/components/core/src/clp_s/search/Output.cpp @@ -932,12 +932,12 @@ void Output::populate_string_queries(std::shared_ptr const& expr) { } } - auto entries = m_var_dict->get_entry_matching_value( + auto const entries = m_var_dict->get_entry_matching_value( unescaped_query_string, m_ignore_case ); - for (auto entry : entries) { + for (auto const& entry : entries) { matching_vars.insert(entry->get_id()); } } else if (EncodedVariableInterpreter:: diff --git a/components/core/src/clp_s/search/clp_search/EncodedVariableInterpreter.cpp b/components/core/src/clp_s/search/clp_search/EncodedVariableInterpreter.cpp index b77537b06..5d589d003 100644 --- a/components/core/src/clp_s/search/clp_search/EncodedVariableInterpreter.cpp +++ b/components/core/src/clp_s/search/clp_search/EncodedVariableInterpreter.cpp @@ -34,8 +34,7 @@ bool EncodedVariableInterpreter::encode_and_search_dictionary( LogTypeDictionaryEntry::add_double_var(logtype); sub_query.add_non_dict_var(encoded_var); } else { - auto entries = var_dict.get_entry_matching_value(var_str, ignore_case); - + auto const entries = var_dict.get_entry_matching_value(var_str, ignore_case); if (entries.empty()) { // Not in dictionary return false; @@ -44,8 +43,8 @@ bool EncodedVariableInterpreter::encode_and_search_dictionary( LogTypeDictionaryEntry::add_non_double_var(logtype); if (entries.size() == 1) { - VariableDictionaryEntry const* entry = entries[0]; - auto encoded_var = VariableEncoder::encode_var_dict_id(entry->get_id()); + auto const* entry = entries.at(0); + encoded_var = VariableEncoder::encode_var_dict_id(entry->get_id()); sub_query.add_dict_var(encoded_var, entry); return true; } @@ -55,7 +54,7 @@ bool EncodedVariableInterpreter::encode_and_search_dictionary( entries.begin(), entries.end() ); - for (auto entry : entries) { + for (auto const entry : entries) { encoded_vars.insert(VariableEncoder::encode_var_dict_id(entry->get_id())); } sub_query.add_imprecise_dict_var(encoded_vars, entries_set); diff --git a/components/core/tests/test-EncodedVariableInterpreter.cpp b/components/core/tests/test-EncodedVariableInterpreter.cpp index 70b990bc4..3568c2bbb 100644 --- a/components/core/tests/test-EncodedVariableInterpreter.cpp +++ b/components/core/tests/test-EncodedVariableInterpreter.cpp @@ -381,13 +381,17 @@ TEST_CASE("EncodedVariableInterpreter", "[EncodedVariableInterpreter]") { char const cVarSegmentIndexPath[] = "var.segindex"; vector var_strs = {"python2.7.3", "Python2.7.3", "PyThOn2.7.3", "PYTHON2.7.3"}; clp::VariableDictionaryWriter var_dict_writer; + var_dict_writer.open(cVarDictPath, cVarSegmentIndexPath, cVariableDictionaryIdMax); + vector encoded_vars; vector var_ids; clp::LogTypeDictionaryEntry logtype_dict_entry; - for (auto var_str : var_strs) { + string const msg_template = "here is a string with a dictionary var: "; + + for (auto const& var_str : var_strs) { EncodedVariableInterpreter::encode_and_add_to_dictionary( - var_str, + msg_template + var_str, logtype_dict_entry, var_dict_writer, encoded_vars, @@ -400,9 +404,9 @@ TEST_CASE("EncodedVariableInterpreter", "[EncodedVariableInterpreter]") { var_dict_reader.open(cVarDictPath, cVarSegmentIndexPath); var_dict_reader.read_new_entries(); - REQUIRE(var_dict_reader.get_entry_matching_value(var_strs[0], true).size() + REQUIRE(var_dict_reader.get_entry_matching_value(var_strs.at(0), true).size() == var_strs.size()); - REQUIRE(var_dict_reader.get_entry_matching_value(var_strs[0], false).size() == 1); + REQUIRE(var_dict_reader.get_entry_matching_value(var_strs.at(0), false).size() == 1); var_dict_reader.close(); From 882475727a5d95753c7f4bca878d30a88c43fc91 Mon Sep 17 00:00:00 2001 From: Matteo Nicoli Date: Thu, 30 Jan 2025 17:49:39 +0100 Subject: [PATCH 6/6] lint suggestion fixed --- components/core/tests/test-EncodedVariableInterpreter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/core/tests/test-EncodedVariableInterpreter.cpp b/components/core/tests/test-EncodedVariableInterpreter.cpp index 3568c2bbb..904aa7111 100644 --- a/components/core/tests/test-EncodedVariableInterpreter.cpp +++ b/components/core/tests/test-EncodedVariableInterpreter.cpp @@ -387,7 +387,7 @@ TEST_CASE("EncodedVariableInterpreter", "[EncodedVariableInterpreter]") { vector encoded_vars; vector var_ids; clp::LogTypeDictionaryEntry logtype_dict_entry; - string const msg_template = "here is a string with a dictionary var: "; + string const msg_template = "here is a string with a dictionary var: "; for (auto const& var_str : var_strs) { EncodedVariableInterpreter::encode_and_add_to_dictionary(