#pragma once #include "indexer/scales.hpp" #include "coding/multilang_utf8_string.hpp" #include "base/assert.hpp" #include "base/small_set.hpp" #include "base/string_utils.hpp" #include "std/cstdint.hpp" #include "std/type_traits.hpp" #include "std/unordered_set.hpp" #include "std/utility.hpp" #include "std/vector.hpp" namespace search { class TokenRange; class QueryParams { public: using String = strings::UniString; using TypeIndices = vector; using Langs = base::SafeSmallSet; struct Token { Token() = default; Token(String const & original) : m_original(original) {} void AddSynonym(String const & s) { m_synonyms.push_back(s); } void AddSynonym(string const & s) { m_synonyms.push_back(strings::MakeUniString(s)); } // Calls |fn| on the original token and on synonyms. template typename enable_if::type, void>::value>::type ForEach( Fn && fn) const { fn(m_original); for_each(m_synonyms.begin(), m_synonyms.end(), forward(fn)); } // Calls |fn| on the original token and on synonyms until |fn| return false. template typename enable_if::type, bool>::value>::type ForEach( Fn && fn) const { if (!fn(m_original)) return; for (auto const & synonym : m_synonyms) { if (!fn(synonym)) return; } } void Clear() { m_original.clear(); m_synonyms.clear(); } String m_original; vector m_synonyms; }; QueryParams() = default; template void InitNoPrefix(It tokenBegin, It tokenEnd) { Clear(); for (; tokenBegin != tokenEnd; ++tokenBegin) m_tokens.emplace_back(*tokenBegin); m_typeIndices.resize(GetNumTokens()); } template void InitWithPrefix(It tokenBegin, It tokenEnd, String const & prefix) { Clear(); for (; tokenBegin != tokenEnd; ++tokenBegin) m_tokens.push_back(*tokenBegin); m_prefixToken.m_original = prefix; m_hasPrefix = true; m_typeIndices.resize(GetNumTokens()); } inline size_t GetNumTokens() const { return m_hasPrefix ? m_tokens.size() + 1: m_tokens.size(); } inline bool LastTokenIsPrefix() const { return m_hasPrefix; } inline bool IsEmpty() const { return GetNumTokens() == 0; } void Clear(); bool IsCategorySynonym(size_t i) const; TypeIndices & GetTypeIndices(size_t i); TypeIndices const & GetTypeIndices(size_t i) const; bool IsPrefixToken(size_t i) const; Token const & GetToken(size_t i) const; Token & GetToken(size_t i); // Returns true if all tokens in |range| have integral synonyms. bool IsNumberTokens(TokenRange const & range) const; void RemoveToken(size_t i); inline Langs & GetLangs() { return m_langs; } inline Langs const & GetLangs() const { return m_langs; } inline bool LangExists(int8_t lang) const { return m_langs.Contains(lang); } inline int GetScale() const { return m_scale; } private: friend string DebugPrint(QueryParams const & params); vector m_tokens; Token m_prefixToken; bool m_hasPrefix = false; vector m_typeIndices; Langs m_langs; int m_scale = scales::GetUpperScale(); }; string DebugPrint(QueryParams::Token const & token); } // namespace search