<commit_before>#include "query.hpp"
#include "delimiters.hpp"
#include "latlon_match.hpp"
#include "string_match.hpp"
#include "../indexer/feature_visibility.hpp"
#include "../indexer/mercator.hpp"
#include "../base/stl_add.hpp"

namespace search
{
namespace impl
{
namespace
{

uint32_t KeywordMatch(strings::UniChar const * sA, uint32_t sizeA,
                      strings::UniChar const * sB, uint32_t sizeB,
                      uint32_t maxCost)
{
  /*
  if (sizeA != sizeB)
    return maxCost + 1;
  for (uint32_t i = 0; i< sizeA; ++i)
    if (sA[i] != sB[i])
      return maxCost + 1;
  return 0;
  */
  return StringMatchCost(sA, sizeA, sB, sizeB, DefaultMatchCost(), maxCost, false);
}

uint32_t PrefixMatch(strings::UniChar const * sA, uint32_t sizeA,
                     strings::UniChar const * sB, uint32_t sizeB,
                     uint32_t maxCost)
{
  /*
  if (sizeA > sizeB)
    return maxCost + 1;
  for (uint32_t i = 0; i< sizeA; ++i)
    if (sA[i] != sB[i])
      return maxCost + 1;
  return 0;
  */
  return StringMatchCost(sA, sizeA, sB, sizeB, DefaultMatchCost(), maxCost, true);
}

inline uint32_t GetMaxKeywordMatchScore() { return 512; }

inline KeywordMatcher MakeMatcher(vector<strings::UniString> const & tokens,
                                  strings::UniString const & prefix)
{
  uint32_t const maxPrefixMatchCost = min(static_cast<int>(GetMaxKeywordMatchScore()),
                                          256 * max(0, int(prefix.size()) - 1));
  return KeywordMatcher(tokens.empty() ? NULL : &tokens[0], tokens.size(),
                        prefix,
                        GetMaxKeywordMatchScore(), maxPrefixMatchCost,
                        &KeywordMatch, &PrefixMatch);
}

struct FeatureProcessor
{
  Query & m_query;

  explicit FeatureProcessor(Query & query) : m_query(query) {}

  void operator () (FeatureType const & feature) const
  {
    int const minVisibleScale = feature::MinDrawableScaleForText(feature);
    if (minVisibleScale < 0)
      return;

    KeywordMatcher matcher(MakeMatcher(m_query.m_keywords, m_query.m_prefix));
    feature.ForEachNameRef(matcher);
    if (matcher.GetPrefixMatchScore() <= GetMaxKeywordMatchScore())
    {
      uint32_t const matchScore = matcher.GetMatchScore();
      if (matchScore <= GetMaxKeywordMatchScore())
      {
        m_query.AddResult(IntermediateResult(feature, matcher.GetBestPrefixMatch(),
                                             matchScore, minVisibleScale));
      }
    }
  }
};

}  // unnamed namespace

Query::Query(string const & query, m2::RectD const & rect, IndexType const * pIndex)
  : m_queryText(query), m_rect(rect), m_pIndex(pIndex)
{
  search::Delimiters delims;
  SplitAndNormalizeAndSimplifyString(query, MakeBackInsertFunctor(m_keywords), delims);
  if (!m_keywords.empty() && !delims(strings::LastUniChar(query)))
  {<commit_msg>[search] feature::MinDrawableScaleForText() is slow, check it only if the feature matches.<commit_after>#include "query.hpp"
#include "delimiters.hpp"
#include "latlon_match.hpp"
#include "string_match.hpp"
#include "../indexer/feature_visibility.hpp"
#include "../indexer/mercator.hpp"
#include "../base/stl_add.hpp"

namespace search
{
namespace impl
{
namespace
{

uint32_t KeywordMatch(strings::UniChar const * sA, uint32_t sizeA,
                      strings::UniChar const * sB, uint32_t sizeB,
                      uint32_t maxCost)
{
  /*
  if (sizeA != sizeB)
    return maxCost + 1;
  for (uint32_t i = 0; i< sizeA; ++i)
    if (sA[i] != sB[i])
      return maxCost + 1;
  return 0;
  */
  return StringMatchCost(sA, sizeA, sB, sizeB, DefaultMatchCost(), maxCost, false);
}

uint32_t PrefixMatch(strings::UniChar const * sA, uint32_t sizeA,
                     strings::UniChar const * sB, uint32_t sizeB,
                     uint32_t maxCost)
{
  /*
  if (sizeA > sizeB)
    return maxCost + 1;
  for (uint32_t i = 0; i< sizeA; ++i)
    if (sA[i] != sB[i])
      return maxCost + 1;
  return 0;
  */
  return StringMatchCost(sA, sizeA, sB, sizeB, DefaultMatchCost(), maxCost, true);
}

inline uint32_t GetMaxKeywordMatchScore() { return 512; }

inline KeywordMatcher MakeMatcher(vector<strings::UniString> const & tokens,
                                  strings::UniString const & prefix)
{
  uint32_t const maxPrefixMatchCost = min(static_cast<int>(GetMaxKeywordMatchScore()),
                                          256 * max(0, int(prefix.size()) - 1));
  return KeywordMatcher(tokens.empty() ? NULL : &tokens[0], tokens.size(),
                        prefix,
                        GetMaxKeywordMatchScore(), maxPrefixMatchCost,
                        &KeywordMatch, &PrefixMatch);
}

struct FeatureProcessor
{
  Query & m_query;

  explicit FeatureProcessor(Query & query) : m_query(query) {}

  void operator () (FeatureType const & feature) const
  {
    KeywordMatcher matcher(MakeMatcher(m_query.m_keywords, m_query.m_prefix));
    feature.ForEachNameRef(matcher);
    if (matcher.GetPrefixMatchScore() <= GetMaxKeywordMatchScore())
    {
      uint32_t const matchScore = matcher.GetMatchScore();
      if (matchScore <= GetMaxKeywordMatchScore())
      {
        int const minVisibleScale = feature::MinDrawableScaleForText(feature);
        if (minVisibleScale < 0)
          return;

        m_query.AddResult(IntermediateResult(feature, matcher.GetBestPrefixMatch(),
                                             matchScore, minVisibleScale));
      }
    }
  }
};

}  // unnamed namespace

Query::Query(string const & query, m2::RectD const & rect, IndexType const * pIndex)
  : m_queryText(query), m_rect(rect), m_pIndex(pIndex)
{
  search::Delimiters delims;
  SplitAndNormalizeAndSimplifyString(query, MakeBackInsertFunctor(m_keywords), delims);
  if (!m_keywords.empty() && !delims(strings::LastUniChar(query)))
  {
{'fraction_non_alphanumeric': 0.11956708469335166, 'fraction_numerical': 0.015461260951726508, 'mean_word_length': 2.9284750337381915, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3693514', 'n_tokens_mistral': 1925, 'n_tokens_neox': 1844, 'n_words': 402}