Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--base/base_tests/stl_helpers_test.cpp24
-rw-r--r--base/mem_trie.hpp2
-rw-r--r--base/stl_helpers.hpp26
-rw-r--r--indexer/categories_holder.cpp48
-rw-r--r--indexer/categories_holder.hpp46
-rw-r--r--indexer/indexer_tests/categories_test.cpp43
6 files changed, 147 insertions, 42 deletions
diff --git a/base/base_tests/stl_helpers_test.cpp b/base/base_tests/stl_helpers_test.cpp
index 029df6af98..71462cfbaf 100644
--- a/base/base_tests/stl_helpers_test.cpp
+++ b/base/base_tests/stl_helpers_test.cpp
@@ -125,4 +125,28 @@ UNIT_TEST(SortUnique_VectorTest)
TestSortUnique<vector>();
TestSortUnique<deque>();
}
+
+UNIT_TEST(IgnoreFirstArgument)
+{
+ {
+ int s = 0;
+ auto f1 = [&](int a, int b) { s += a + b; };
+ auto f2 = [&](int a, int b) { s -= a + b; };
+ auto f3 = my::MakeIgnoreFirstArgument(f2);
+
+ f1(2, 3);
+ TEST_EQUAL(s, 5, ());
+ f3(1, 2, 3);
+ TEST_EQUAL(s, 0, ());
+ }
+
+ {
+ auto f1 = [](int a, int b) -> int { return a + b; };
+ auto f2 = my::MakeIgnoreFirstArgument(f1);
+
+ auto const x = f1(2, 3);
+ auto const y = f2("ignored", 2, 3);
+ TEST_EQUAL(x, y, ());
+ }
+}
} // namespace
diff --git a/base/mem_trie.hpp b/base/mem_trie.hpp
index 3c8547b8ce..fdd35af365 100644
--- a/base/mem_trie.hpp
+++ b/base/mem_trie.hpp
@@ -49,7 +49,7 @@ public:
ForEachInSubtree(m_root, prefix, std::forward<ToDo>(toDo));
}
- // Calls |toDo| for each key-value pair in a node that is reachable
+ // Calls |toDo| for each key-value pair in the node that is reachable
// by |prefix| from the trie root. Does nothing if such node does
// not exist.
template <typename ToDo>
diff --git a/base/stl_helpers.hpp b/base/stl_helpers.hpp
index 2130dd03d7..5ee22b6897 100644
--- a/base/stl_helpers.hpp
+++ b/base/stl_helpers.hpp
@@ -2,6 +2,7 @@
#include <algorithm>
#include <functional>
+#include <type_traits>
#include <utility>
#include <vector>
@@ -137,4 +138,29 @@ typename std::underlying_type<T>::type Key(T value)
{
return static_cast<typename std::underlying_type<T>::type>(value);
}
+
+// Use this if you want to make a functor whose first
+// argument is ignored and the rest are forwarded to |fn|.
+template <typename Fn>
+class IgnoreFirstArgument
+{
+public:
+ template <typename Gn>
+ IgnoreFirstArgument(Gn && gn) : m_fn(std::forward<Gn>(gn)) {}
+
+ template <typename Arg, typename... Args>
+ typename std::result_of<Fn(Args &&...)>::type operator()(Arg && arg, Args &&... args)
+ {
+ return m_fn(std::forward<Args>(args)...);
+ }
+
+private:
+ Fn m_fn;
+};
+
+template <typename Fn>
+IgnoreFirstArgument<Fn> MakeIgnoreFirstArgument(Fn && fn)
+{
+ return IgnoreFirstArgument<Fn>(std::forward<Fn>(fn));
+}
} // namespace my
diff --git a/indexer/categories_holder.cpp b/indexer/categories_holder.cpp
index 71b78c58d6..382d21f7f9 100644
--- a/indexer/categories_holder.cpp
+++ b/indexer/categories_holder.cpp
@@ -195,23 +195,29 @@ void CategoriesHolder::AddCategory(Category & cat, vector<uint32_t> & types)
shared_ptr<Category> p(new Category());
p->Swap(cat);
- for (size_t i = 0; i < types.size(); ++i)
- m_type2cat.insert(make_pair(types[i], p));
+ for (uint32_t const t : types)
+ m_type2cat.insert(make_pair(t, p));
- for (size_t i = 0; i < p->m_synonyms.size(); ++i)
+ for (auto const & synonym : p->m_synonyms)
{
- ASSERT(p->m_synonyms[i].m_locale != kUnsupportedLocaleCode, ());
+ auto const locale = synonym.m_locale;
+ ASSERT_NOT_EQUAL(locale, kUnsupportedLocaleCode, ());
- StringT const uniName = search::NormalizeAndSimplifyString(p->m_synonyms[i].m_name);
+ auto const uniName = search::NormalizeAndSimplifyString(synonym.m_name);
- vector<StringT> tokens;
+ vector<String> tokens;
SplitUniString(uniName, MakeBackInsertFunctor(tokens), search::Delimiters());
- for (size_t j = 0; j < tokens.size(); ++j)
- for (size_t k = 0; k < types.size(); ++k)
- if (ValidKeyToken(tokens[j]))
- m_name2type.insert(
- make_pair(make_pair(p->m_synonyms[i].m_locale, tokens[j]), types[k]));
+ for (auto const & token : tokens)
+ {
+ if (!ValidKeyToken(token))
+ continue;
+ for (uint32_t const t : types)
+ {
+ auto it = m_name2type.emplace(locale, make_unique<Trie>()).first;
+ it->second->Add(token, t);
+ }
+ }
}
}
@@ -219,7 +225,7 @@ void CategoriesHolder::AddCategory(Category & cat, vector<uint32_t> & types)
types.clear();
}
-bool CategoriesHolder::ValidKeyToken(StringT const & s)
+bool CategoriesHolder::ValidKeyToken(String const & s)
{
if (s.size() > 2)
return true;
@@ -306,17 +312,19 @@ void CategoriesHolder::LoadFromStream(istream & s)
bool CategoriesHolder::GetNameByType(uint32_t type, int8_t locale, string & name) const
{
- pair<IteratorT, IteratorT> const range = m_type2cat.equal_range(type);
+ auto const range = m_type2cat.equal_range(type);
- for (IteratorT i = range.first; i != range.second; ++i)
+ for (auto it = range.first; it != range.second; ++it)
{
- Category const & cat = *i->second;
- for (size_t j = 0; j < cat.m_synonyms.size(); ++j)
- if (cat.m_synonyms[j].m_locale == locale)
+ Category const & cat = *it->second;
+ for (auto const & synonym : cat.m_synonyms)
+ {
+ if (synonym.m_locale == locale)
{
- name = cat.m_synonyms[j].m_name;
+ name = synonym.m_name;
return true;
}
+ }
}
if (range.first != range.second)
@@ -352,7 +360,7 @@ string CategoriesHolder::GetReadableFeatureType(uint32_t type, int8_t locale) co
bool CategoriesHolder::IsTypeExist(uint32_t type) const
{
- pair<IteratorT, IteratorT> const range = m_type2cat.equal_range(type);
+ auto const range = m_type2cat.equal_range(type);
return range.first != range.second;
}
@@ -379,8 +387,10 @@ int8_t CategoriesHolder::MapLocaleToInteger(string const & locale)
strings::AsciiToLower(lower);
for (char const * s : {"hant", "tw", "hk", "mo"})
+ {
if (lower.find(s) != string::npos)
return 12; // Traditional Chinese
+ }
return 17; // Simplified Chinese by default for all other cases
}
diff --git a/indexer/categories_holder.hpp b/indexer/categories_holder.hpp
index 0c12622d5e..ba40e43460 100644
--- a/indexer/categories_holder.hpp
+++ b/indexer/categories_holder.hpp
@@ -1,4 +1,7 @@
#pragma once
+
+#include "base/mem_trie.hpp"
+#include "base/stl_helpers.hpp"
#include "base/string_utils.hpp"
#include "std/deque.hpp"
@@ -11,7 +14,6 @@
#include "std/utility.hpp"
#include "std/vector.hpp"
-
class Reader;
class CategoriesHolder
@@ -47,13 +49,15 @@ public:
using GroupTranslations = unordered_map<string, vector<Category::Name>>;
private:
- typedef strings::UniString StringT;
- typedef multimap<uint32_t, shared_ptr<Category> > Type2CategoryContT;
- typedef multimap<pair<int8_t, StringT>, uint32_t> Name2CatContT;
- typedef Type2CategoryContT::const_iterator IteratorT;
+ using String = strings::UniString;
+ using Type2CategoryCont = multimap<uint32_t, shared_ptr<Category>>;
+ using Trie = my::MemTrie<String, uint32_t>;
+
+ Type2CategoryCont m_type2cat;
+
+ // Maps locale and category token to the list of corresponding types.
+ map<int8_t, unique_ptr<Trie>> m_name2type;
- Type2CategoryContT m_type2cat;
- Name2CatContT m_name2type;
GroupTranslations m_groupTranslations;
public:
@@ -71,8 +75,8 @@ public:
template <class ToDo>
void ForEachCategory(ToDo && toDo) const
{
- for (IteratorT i = m_type2cat.begin(); i != m_type2cat.end(); ++i)
- toDo(*i->second);
+ for (auto const & p : m_type2cat)
+ toDo(*p.second);
}
template <class ToDo>
@@ -85,9 +89,11 @@ public:
template <class ToDo>
void ForEachName(ToDo && toDo) const
{
- for (IteratorT i = m_type2cat.begin(); i != m_type2cat.end(); ++i)
- for (size_t j = 0; j < i->second->m_synonyms.size(); ++j)
- toDo(i->second->m_synonyms[j]);
+ for (auto const & p : m_type2cat)
+ {
+ for (auto const & synonym : p.second->m_synonyms)
+ toDo(synonym);
+ }
}
template <class ToDo>
@@ -101,16 +107,12 @@ public:
}
template <class ToDo>
- void ForEachTypeByName(int8_t locale, StringT const & name, ToDo && toDo) const
+ void ForEachTypeByName(int8_t locale, String const & name, ToDo && toDo) const
{
- typedef typename Name2CatContT::const_iterator IterT;
-
- pair<IterT, IterT> range = m_name2type.equal_range(make_pair(locale, name));
- while (range.first != range.second)
- {
- toDo(range.first->second);
- ++range.first;
- }
+ auto const it = m_name2type.find(locale);
+ if (it == m_name2type.end())
+ return;
+ it->second->ForEachInNode(name, my::MakeIgnoreFirstArgument(forward<ToDo>(toDo)));
}
inline GroupTranslations const & GetGroupTranslations() const { return m_groupTranslations; }
@@ -142,7 +144,7 @@ public:
private:
void AddCategory(Category & cat, vector<uint32_t> & types);
- static bool ValidKeyToken(StringT const & s);
+ static bool ValidKeyToken(String const & s);
};
inline void swap(CategoriesHolder & a, CategoriesHolder & b)
diff --git a/indexer/indexer_tests/categories_test.cpp b/indexer/indexer_tests/categories_test.cpp
index bea439e730..5bc2698013 100644
--- a/indexer/indexer_tests/categories_test.cpp
+++ b/indexer/indexer_tests/categories_test.cpp
@@ -20,6 +20,7 @@
#include "std/transform_iterator.hpp"
#include "base/stl_helpers.hpp"
+#include "base/string_utils.hpp"
using namespace indexer;
@@ -222,6 +223,48 @@ UNIT_TEST(CategoriesHolder_DisplayedName)
});
}
+UNIT_TEST(CategoriesHolder_ForEach)
+{
+ char const kCategories[] =
+ "amenity-bar\n"
+ "en:abc|ddd-eee\n"
+ "\n"
+ "amenity-pub\n"
+ "en:ddd\n"
+ "\n"
+ "amenity-cafe\n"
+ "en:abc eee\n"
+ "\n"
+ "amenity-restaurant\n"
+ "en:ddd|eee\n"
+ "\n"
+ "";
+
+ classificator::Load();
+ CategoriesHolder holder(make_unique<MemReader>(kCategories, ARRAY_SIZE(kCategories) - 1));
+
+ {
+ uint32_t counter = 0;
+ holder.ForEachTypeByName(CategoriesHolder::kEnglishCode, strings::MakeUniString("abc"),
+ [&](uint32_t /* type */) { ++counter; });
+ TEST_EQUAL(counter, 2, ());
+ }
+
+ {
+ uint32_t counter = 0;
+ holder.ForEachTypeByName(CategoriesHolder::kEnglishCode, strings::MakeUniString("ddd"),
+ [&](uint32_t /* type */) { ++counter; });
+ TEST_EQUAL(counter, 3, ());
+ }
+
+ {
+ uint32_t counter = 0;
+ holder.ForEachTypeByName(CategoriesHolder::kEnglishCode, strings::MakeUniString("eee"),
+ [&](uint32_t /* type */) { ++counter; });
+ TEST_EQUAL(counter, 3, ());
+ }
+}
+
UNIT_TEST(CategoriesIndex_Smoke)
{
classificator::Load();