forked from organicmaps/organicmaps-tmp
[new downloader] Moving all CountryTree functionaltity to one file.
This commit is contained in:
parent
b0c77be128
commit
789422a1f5
9 changed files with 247 additions and 261 deletions
|
@ -144,11 +144,11 @@ namespace
|
|||
{
|
||||
class DoStoreCountriesSingleMwms
|
||||
{
|
||||
TCountriesFacade & m_cont;
|
||||
TCountryTree & m_cont;
|
||||
TMapping m_idsMapping;
|
||||
|
||||
public:
|
||||
DoStoreCountriesSingleMwms(TCountriesFacade & cont) : m_cont(cont) {}
|
||||
DoStoreCountriesSingleMwms(TCountryTree & cont) : m_cont(cont) {}
|
||||
|
||||
Country * operator()(TCountryId const & id, uint32_t mapSize, int depth, TCountryId const & parent)
|
||||
{
|
||||
|
@ -177,10 +177,10 @@ public:
|
|||
|
||||
class DoStoreCountriesTwoComponentMwms
|
||||
{
|
||||
TCountriesFacade & m_cont;
|
||||
TCountryTree & m_cont;
|
||||
|
||||
public:
|
||||
DoStoreCountriesTwoComponentMwms(TCountriesFacade & cont) : m_cont(cont) {}
|
||||
DoStoreCountriesTwoComponentMwms(TCountryTree & cont) : m_cont(cont) {}
|
||||
|
||||
void operator()(string const & file, uint32_t mapSize,
|
||||
uint32_t routingSize, int depth, TCountryId const & parent)
|
||||
|
@ -243,7 +243,7 @@ public:
|
|||
};
|
||||
} // namespace
|
||||
|
||||
int64_t LoadCountries(string const & jsonBuffer, TCountriesFacade & countries, TMapping * mapping /* = nullptr */)
|
||||
int64_t LoadCountries(string const & jsonBuffer, TCountryTree & countries, TMapping * mapping /* = nullptr */)
|
||||
{
|
||||
countries.Clear();
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "storage/country_decl.hpp"
|
||||
#include "storage/country_tree_facade.hpp"
|
||||
#include "storage/country_tree.hpp"
|
||||
#include "storage/index.hpp"
|
||||
#include "storage/storage_defines.hpp"
|
||||
|
||||
|
@ -25,7 +25,7 @@ namespace storage
|
|||
{
|
||||
using TMapping = map<TCountryId, TCountriesSet>;
|
||||
|
||||
/// This class keeps all the information about a country in country tree (TCountriesFacade).
|
||||
/// This class keeps all the information about a country in country tree (TCountryTree).
|
||||
/// It is guaranteed that every node represent a unique region has a unique |m_name| in country tree.
|
||||
/// If several nodes have the same |m_name| they represent the same region.
|
||||
/// It happends in case of disputed territories.
|
||||
|
@ -75,11 +75,11 @@ public:
|
|||
TCountryId const & Name() const { return m_name; }
|
||||
};
|
||||
|
||||
using TCountriesContainer = CountryTree<Country>;
|
||||
using TCountriesFacade = CountryTreeFacade<TCountryId, Country>;
|
||||
using TCountryTree = CountryTree<TCountryId, Country>;
|
||||
using TCountryTreeNode = TCountryTree::Node;
|
||||
|
||||
/// @return version of country file or -1 if error was encountered
|
||||
int64_t LoadCountries(string const & jsonBuffer, TCountriesFacade & countries, TMapping * mapping = nullptr);
|
||||
int64_t LoadCountries(string const & jsonBuffer, TCountryTree & countries, TMapping * mapping = nullptr);
|
||||
|
||||
void LoadCountryFile2CountryInfo(string const & jsonBuffer, map<string, CountryInfo> & id2info,
|
||||
bool & isSingleMwm);
|
||||
|
|
|
@ -6,138 +6,234 @@
|
|||
#include "std/unique_ptr.hpp"
|
||||
#include "std/vector.hpp"
|
||||
|
||||
/// This class is developed for using in CountryTreeFacade. It's a implementation of a tree.
|
||||
template <class K>
|
||||
struct NodeKeyHasher
|
||||
{
|
||||
size_t operator()(K const & k) const { return m_hash(k); }
|
||||
private:
|
||||
hash<K> m_hash;
|
||||
};
|
||||
|
||||
/// This class is developed for using in Storage. It's a implementation of a tree with ability
|
||||
/// of access to its nodes in constant time with the help of hash table.
|
||||
/// It should be filled with AddAtDepth method.
|
||||
/// This class is used in filled based on countries.txt (countries_migrate.txt).
|
||||
/// This class is used in Storage and filled based on countries.txt (countries_migrate.txt).
|
||||
/// While filling CountryTree nodes in countries.txt should be visited in DFS order.
|
||||
template <class T>
|
||||
template <class I, class T>
|
||||
class CountryTree
|
||||
{
|
||||
T m_value;
|
||||
|
||||
/// \brief m_children contains all first generation descendants of the node.
|
||||
/// Note. Once created the order of elements of |m_children| should not be changed.
|
||||
/// See implementation of AddAtDepth and Add methods for details.
|
||||
vector<unique_ptr<CountryTree<T>>> m_children;
|
||||
CountryTree<T> * m_parent;
|
||||
|
||||
/// @return reference is valid only up to the next tree structure modification
|
||||
CountryTree<T> * Add(T const & value)
|
||||
{
|
||||
m_children.emplace_back(make_unique<CountryTree<T>>(value, this));
|
||||
return m_children.back().get();
|
||||
}
|
||||
|
||||
public:
|
||||
CountryTree(T const & value = T(), CountryTree<T> * parent = nullptr)
|
||||
: m_value(value), m_parent(parent)
|
||||
/// This class is developed for using in CountryTree. It's a implementation of a tree.
|
||||
/// It should be filled with AddAtDepth method.
|
||||
/// This class is used in filled based on countries.txt (countries_migrate.txt).
|
||||
/// While filling Node nodes in countries.txt should be visited in DFS order.
|
||||
class Node
|
||||
{
|
||||
}
|
||||
T m_value;
|
||||
|
||||
/// \brief m_children contains all first generation descendants of the node.
|
||||
/// Note. Once created the order of elements of |m_children| should not be changed.
|
||||
/// See implementation of AddAtDepth and Add methods for details.
|
||||
vector<unique_ptr<Node>> m_children;
|
||||
Node * m_parent;
|
||||
|
||||
/// @return reference is valid only up to the next tree structure modification
|
||||
Node * Add(T const & value)
|
||||
{
|
||||
m_children.emplace_back(make_unique<Node>(value, this));
|
||||
return m_children.back().get();
|
||||
}
|
||||
|
||||
public:
|
||||
Node(T const & value = T(), Node * parent = nullptr)
|
||||
: m_value(value), m_parent(parent)
|
||||
{
|
||||
}
|
||||
|
||||
/// @return reference is valid only up to the next tree structure modification
|
||||
T const & Value() const { return m_value; }
|
||||
|
||||
/// @return reference is valid only up to the next tree structure modification
|
||||
T & Value() { return m_value; }
|
||||
|
||||
/// @return reference is valid only up to the next tree structure modification
|
||||
Node * AddAtDepth(int level, T const & value)
|
||||
{
|
||||
Node * node = this;
|
||||
while (level-- > 0 && !node->m_children.empty())
|
||||
node = node->m_children.back().get();
|
||||
ASSERT_EQUAL(level, -1, ());
|
||||
return node->Add(value);
|
||||
}
|
||||
|
||||
/// Deletes all children and makes tree empty
|
||||
void Clear() { m_children.clear(); }
|
||||
|
||||
bool operator<(Node const & other) const { return Value() < other.Value(); }
|
||||
|
||||
bool HasParent() const { return m_parent != nullptr; }
|
||||
|
||||
Node const & Parent() const
|
||||
{
|
||||
CHECK(HasParent(), ());
|
||||
return *m_parent;
|
||||
}
|
||||
|
||||
Node const & Child(size_t index) const
|
||||
{
|
||||
ASSERT_LESS(index, m_children.size(), ());
|
||||
return *m_children[index];
|
||||
}
|
||||
|
||||
size_t ChildrenCount() const { return m_children.size(); }
|
||||
|
||||
/// \brief Calls functor f for each first generation descendant of the node.
|
||||
template <class TFunctor>
|
||||
void ForEachChild(TFunctor && f)
|
||||
{
|
||||
for (auto & child : m_children)
|
||||
f(*child);
|
||||
}
|
||||
|
||||
template <class TFunctor>
|
||||
void ForEachChild(TFunctor && f) const
|
||||
{
|
||||
for (auto const & child : m_children)
|
||||
f(*child);
|
||||
}
|
||||
|
||||
/// \brief Calls functor f for all nodes (add descendant) in the tree.
|
||||
template <class TFunctor>
|
||||
void ForEachDescendant(TFunctor && f)
|
||||
{
|
||||
for (auto & child : m_children)
|
||||
{
|
||||
f(*child);
|
||||
child->ForEachDescendant(f);
|
||||
}
|
||||
}
|
||||
|
||||
template <class TFunctor>
|
||||
void ForEachDescendant(TFunctor && f) const
|
||||
{
|
||||
for (auto const & child: m_children)
|
||||
{
|
||||
f(*child);
|
||||
child->ForEachDescendant(f);
|
||||
}
|
||||
}
|
||||
|
||||
template <class TFunctor>
|
||||
void ForEachInSubtree(TFunctor && f)
|
||||
{
|
||||
f(*this);
|
||||
for (auto & child: m_children)
|
||||
child->ForEachInSubtree(f);
|
||||
}
|
||||
|
||||
template <class TFunctor>
|
||||
void ForEachInSubtree(TFunctor && f) const
|
||||
{
|
||||
f(*this);
|
||||
for (auto const & child: m_children)
|
||||
child->ForEachInSubtree(f);
|
||||
}
|
||||
|
||||
template <class TFunctor>
|
||||
void ForEachAncestorExceptForTheRoot(TFunctor && f)
|
||||
{
|
||||
if (m_parent == nullptr || m_parent->m_parent == nullptr)
|
||||
return;
|
||||
f(*m_parent);
|
||||
m_parent->ForEachAncestorExceptForTheRoot(f);
|
||||
}
|
||||
|
||||
template <class TFunctor>
|
||||
void ForEachAncestorExceptForTheRoot(TFunctor && f) const
|
||||
{
|
||||
if (m_parent == nullptr || m_parent->m_parent == nullptr)
|
||||
return;
|
||||
f(*m_parent);
|
||||
m_parent->ForEachAncestorExceptForTheRoot(f);
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
using TCountryTreeHashTable = unordered_multimap<I, Node *, NodeKeyHasher<I>>;
|
||||
public:
|
||||
|
||||
CountryTree(T const & value = T(), Node * parent = nullptr)
|
||||
: m_countryTree(value, parent) {}
|
||||
|
||||
/// @return reference is valid only up to the next tree structure modification
|
||||
T const & Value() const { return m_value; }
|
||||
T const & Value() const { return m_countryTree.Value(); }
|
||||
|
||||
/// @return reference is valid only up to the next tree structure modification
|
||||
T & Value() { return m_value; }
|
||||
T & Value() { return m_countryTree.Value(); }
|
||||
|
||||
/// @return reference is valid only up to the next tree structure modification
|
||||
CountryTree<T> * AddAtDepth(int level, T const & value)
|
||||
T & AddAtDepth(int level, T const & value)
|
||||
{
|
||||
CountryTree<T> * node = this;
|
||||
while (level-- > 0 && !node->m_children.empty())
|
||||
node = node->m_children.back().get();
|
||||
ASSERT_EQUAL(level, -1, ());
|
||||
return node->Add(value);
|
||||
Node * const added = m_countryTree.AddAtDepth(level, value);
|
||||
ASSERT(added, ());
|
||||
m_countryTreeHashTable.insert(make_pair(value.Name(), added));
|
||||
return added->Value();
|
||||
}
|
||||
|
||||
/// Deletes all children and makes tree empty
|
||||
void Clear() { m_children.clear(); }
|
||||
void Clear() { m_countryTree.Clear(); }
|
||||
|
||||
bool operator<(CountryTree<T> const & other) const { return Value() < other.Value(); }
|
||||
|
||||
bool HasParent() const { return m_parent != nullptr; }
|
||||
|
||||
CountryTree<T> const & Parent() const
|
||||
/// \brief Checks all nodes in tree to find an equal one. If there're several equal nodes
|
||||
/// returns the first found.
|
||||
/// \returns a poiter item in the tree if found and nullptr otherwise.
|
||||
void Find(T const & value, vector<Node const *> & found) const
|
||||
{
|
||||
CHECK(HasParent(), ());
|
||||
return *m_parent;
|
||||
}
|
||||
found.clear();
|
||||
|
||||
CountryTree<T> const & Child(size_t index) const
|
||||
{
|
||||
ASSERT_LESS(index, m_children.size(), ());
|
||||
return *m_children[index];
|
||||
}
|
||||
if (IsEqual(value, m_countryTree.Value()))
|
||||
found.push_back(&m_countryTree);
|
||||
|
||||
size_t ChildrenCount() const { return m_children.size(); }
|
||||
|
||||
/// \brief Calls functor f for each first generation descendant of the node.
|
||||
template <class TFunctor>
|
||||
void ForEachChild(TFunctor && f)
|
||||
{
|
||||
for (auto & child : m_children)
|
||||
f(*child);
|
||||
}
|
||||
|
||||
template <class TFunctor>
|
||||
void ForEachChild(TFunctor && f) const
|
||||
{
|
||||
for (auto const & child : m_children)
|
||||
f(*child);
|
||||
}
|
||||
|
||||
/// \brief Calls functor f for all nodes (add descendant) in the tree.
|
||||
template <class TFunctor>
|
||||
void ForEachDescendant(TFunctor && f)
|
||||
{
|
||||
for (auto & child : m_children)
|
||||
{
|
||||
f(*child);
|
||||
child->ForEachDescendant(f);
|
||||
}
|
||||
}
|
||||
|
||||
template <class TFunctor>
|
||||
void ForEachDescendant(TFunctor && f) const
|
||||
{
|
||||
for (auto const & child: m_children)
|
||||
{
|
||||
f(*child);
|
||||
child->ForEachDescendant(f);
|
||||
}
|
||||
}
|
||||
|
||||
template <class TFunctor>
|
||||
void ForEachInSubtree(TFunctor && f)
|
||||
{
|
||||
f(*this);
|
||||
for (auto & child: m_children)
|
||||
child->ForEachInSubtree(f);
|
||||
}
|
||||
|
||||
template <class TFunctor>
|
||||
void ForEachInSubtree(TFunctor && f) const
|
||||
{
|
||||
f(*this);
|
||||
for (auto const & child: m_children)
|
||||
child->ForEachInSubtree(f);
|
||||
}
|
||||
|
||||
template <class TFunctor>
|
||||
void ForEachAncestorExceptForTheRoot(TFunctor && f)
|
||||
{
|
||||
if (m_parent == nullptr || m_parent->m_parent == nullptr)
|
||||
auto const range = m_countryTreeHashTable.equal_range(value.Name());
|
||||
auto const end = m_countryTreeHashTable.end();
|
||||
if (range.first == end && range.second == end)
|
||||
return;
|
||||
f(*m_parent);
|
||||
m_parent->ForEachAncestorExceptForTheRoot(f);
|
||||
|
||||
for_each(range.first, range.second,
|
||||
[&found](typename TCountryTreeHashTable::value_type const & node) { found.push_back(&*node.second); });
|
||||
}
|
||||
|
||||
template <class TFunctor>
|
||||
void ForEachAncestorExceptForTheRoot(TFunctor && f) const
|
||||
Node const * const FindFirst(T const & value) const
|
||||
{
|
||||
if (m_parent == nullptr || m_parent->m_parent == nullptr)
|
||||
return;
|
||||
f(*m_parent);
|
||||
m_parent->ForEachAncestorExceptForTheRoot(f);
|
||||
vector<Node const *> found;
|
||||
Find(value, found);
|
||||
if (found.empty())
|
||||
return nullptr;
|
||||
return found[0];
|
||||
}
|
||||
|
||||
/// \brief Find only leaves.
|
||||
/// \note It's a termprary fucntion for compatablity with old countries.txt.
|
||||
/// When new countries.txt with unique ids will be added FindLeaf will be removed
|
||||
/// and Find will be used intead.
|
||||
/// @TODO(bykoianko) Remove this method on countries.txt update.
|
||||
Node const * const FindFirstLeaf(T const & value) const
|
||||
{
|
||||
vector<Node const *> found;
|
||||
Find(value, found);
|
||||
|
||||
for (auto node : found)
|
||||
{
|
||||
if (node->ChildrenCount() == 0)
|
||||
return node;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t ChildrenCount() const { return m_countryTree.ChildrenCount(); }
|
||||
|
||||
private:
|
||||
static bool IsEqual(T const & v1, T const & v2) { return !(v1 < v2) && !(v2 < v1); }
|
||||
|
||||
Node m_countryTree;
|
||||
TCountryTreeHashTable m_countryTreeHashTable;
|
||||
};
|
||||
|
|
|
@ -1,109 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "storage/country_tree.hpp"
|
||||
|
||||
#include "std/algorithm.hpp"
|
||||
#include "std/unordered_map.hpp"
|
||||
|
||||
template <class K>
|
||||
struct CountryTreeKeyHasher
|
||||
{
|
||||
size_t operator()(K const & k) const { return m_hash(k); }
|
||||
private:
|
||||
hash<string> m_hash;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CountryTreeKeyHasher<int>
|
||||
{
|
||||
size_t operator()(int k) const { return m_hash(k); }
|
||||
private:
|
||||
hash<int> m_hash;
|
||||
};
|
||||
|
||||
/// This class is developed for using in Storage. It's a implementation of a tree with ability
|
||||
/// of access to its nodes in constant time with the help of hash table.
|
||||
/// It should be filled with AddAtDepth method.
|
||||
/// This class is used in Storage and filled based on countries.txt (countries_migrate.txt).
|
||||
/// While filling CountryTree nodes in countries.txt should be visited in DFS order.
|
||||
template <class I, class T>
|
||||
class CountryTreeFacade
|
||||
{
|
||||
using TCountryTreeHashTable = unordered_multimap<I, CountryTree<T> *, CountryTreeKeyHasher<I>>;
|
||||
|
||||
CountryTree<T> m_countryTree;
|
||||
TCountryTreeHashTable m_countryTreeHashTable;
|
||||
|
||||
public:
|
||||
CountryTreeFacade(T const & value = T(), CountryTree<T> * parent = nullptr)
|
||||
: m_countryTree(value, parent) {}
|
||||
|
||||
/// @return reference is valid only up to the next tree structure modification
|
||||
T const & Value() const { return m_countryTree.Value(); }
|
||||
|
||||
/// @return reference is valid only up to the next tree structure modification
|
||||
T & Value() { return m_countryTree.Value(); }
|
||||
|
||||
/// @return reference is valid only up to the next tree structure modification
|
||||
T & AddAtDepth(int level, T const & value)
|
||||
{
|
||||
CountryTree<T> * const added = m_countryTree.AddAtDepth(level, value);
|
||||
ASSERT(added, ());
|
||||
m_countryTreeHashTable.insert(make_pair(value.Name(), added));
|
||||
return added->Value();
|
||||
}
|
||||
|
||||
/// Deletes all children and makes tree empty
|
||||
void Clear() { m_countryTree.Clear(); }
|
||||
|
||||
/// \brief Checks all nodes in tree to find an equal one. If there're several equal nodes
|
||||
/// returns the first found.
|
||||
/// \returns a poiter item in the tree if found and nullptr otherwise.
|
||||
void Find(T const & value, vector<CountryTree<T> const *> & found) const
|
||||
{
|
||||
found.clear();
|
||||
|
||||
if (IsEqual(value, m_countryTree.Value()))
|
||||
found.push_back(&m_countryTree);
|
||||
|
||||
auto const range = m_countryTreeHashTable.equal_range(value.Name());
|
||||
auto const end = m_countryTreeHashTable.end();
|
||||
if (range.first == end && range.second == end)
|
||||
return;
|
||||
|
||||
for_each(range.first, range.second,
|
||||
[&found](typename TCountryTreeHashTable::value_type const & node) { found.push_back(&*node.second); });
|
||||
}
|
||||
|
||||
CountryTree<T> const * const FindFirst(T const & value) const
|
||||
{
|
||||
vector<CountryTree<T> const *> found;
|
||||
Find(value, found);
|
||||
if (found.empty())
|
||||
return nullptr;
|
||||
return found[0];
|
||||
}
|
||||
|
||||
/// \brief Find only leaves.
|
||||
/// \note It's a termprary fucntion for compatablity with old countries.txt.
|
||||
/// When new countries.txt with unique ids will be added FindLeaf will be removed
|
||||
/// and Find will be used intead.
|
||||
/// @TODO(bykoianko) Remove this method on countries.txt update.
|
||||
CountryTree<T> const * const FindFirstLeaf(T const & value) const
|
||||
{
|
||||
vector<CountryTree<T> const *> found;
|
||||
Find(value, found);
|
||||
|
||||
for (auto node : found)
|
||||
{
|
||||
if (node->ChildrenCount() == 0)
|
||||
return node;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t ChildrenCount() const { return m_countryTree.ChildrenCount(); }
|
||||
|
||||
private:
|
||||
static bool IsEqual(T const & v1, T const & v2) { return !(v1 < v2) && !(v2 < v1); }
|
||||
};
|
|
@ -76,10 +76,10 @@ void DeleteFromDiskWithIndexes(LocalCountryFile const & localFile, MapOptions op
|
|||
localFile.DeleteFromDisk(options);
|
||||
}
|
||||
|
||||
TCountriesContainer const & LeafNodeFromCountryId(TCountriesFacade const & root,
|
||||
TCountryTreeNode const & LeafNodeFromCountryId(TCountryTree const & root,
|
||||
TCountryId const & countryId)
|
||||
{
|
||||
CountryTree<Country> const * node = root.FindFirstLeaf(Country(countryId));
|
||||
TCountryTreeNode const * node = root.FindFirstLeaf(Country(countryId));
|
||||
CHECK(node, ("Node with id =", countryId, "not found in country tree as a leaf."));
|
||||
return *node;
|
||||
}
|
||||
|
@ -321,7 +321,7 @@ Country const & Storage::CountryLeafByCountryId(TCountryId const & countryId) co
|
|||
|
||||
Country const & Storage::CountryByCountryId(TCountryId const & countryId) const
|
||||
{
|
||||
CountryTree<Country> const * node = m_countries.FindFirst(Country(countryId));
|
||||
TCountryTreeNode const * node = m_countries.FindFirst(Country(countryId));
|
||||
CHECK(node, ("Node with id =", countryId, "not found in country tree."));
|
||||
return node->Value();
|
||||
}
|
||||
|
@ -554,7 +554,7 @@ void Storage::NotifyStatusChangedForHierarchy(TCountryId const & countryId)
|
|||
NotifyStatusChanged(countryId);
|
||||
|
||||
// Notification status changing for ancestors in country tree.
|
||||
ForEachAncestorExceptForTheRoot(countryId, [&] (TCountryId const & parentId, TCountriesContainer const &)
|
||||
ForEachAncestorExceptForTheRoot(countryId, [&] (TCountryId const & parentId, TCountryTreeNode const &)
|
||||
{
|
||||
NotifyStatusChanged(parentId);
|
||||
});
|
||||
|
@ -729,10 +729,10 @@ void Storage::ReportProgressForHierarchy(TCountryId const & countryId,
|
|||
GetQueuedCountries(m_queue, setQueue);
|
||||
|
||||
auto calcProgress = [&]
|
||||
(TCountryId const & parentId, TCountriesContainer const & parentNode)
|
||||
(TCountryId const & parentId, TCountryTreeNode const & parentNode)
|
||||
{
|
||||
TCountriesVec descendants;
|
||||
parentNode.ForEachDescendant([&descendants](TCountriesContainer const & container)
|
||||
parentNode.ForEachDescendant([&descendants](TCountryTreeNode const & container)
|
||||
{
|
||||
descendants.push_back(container.Value().Name());
|
||||
});
|
||||
|
@ -1119,7 +1119,7 @@ void Storage::GetChildren(TCountryId const & parent, TCountriesVec & childrenId)
|
|||
{
|
||||
ASSERT_THREAD_CHECKER(m_threadChecker, ());
|
||||
|
||||
TCountriesContainer const * const parentNode = m_countries.FindFirst(Country(parent));
|
||||
TCountryTreeNode const * const parentNode = m_countries.FindFirst(Country(parent));
|
||||
if (parentNode == nullptr)
|
||||
{
|
||||
ASSERT(false, ("TCountryId =", parent, "not found in m_countries."));
|
||||
|
@ -1149,7 +1149,7 @@ void Storage::GetChildrenInGroups(TCountryId const & parent,
|
|||
{
|
||||
ASSERT_THREAD_CHECKER(m_threadChecker, ());
|
||||
|
||||
TCountriesContainer const * const parentNode = m_countries.FindFirst(Country(parent));
|
||||
TCountryTreeNode const * const parentNode = m_countries.FindFirst(Country(parent));
|
||||
if (parentNode == nullptr)
|
||||
{
|
||||
ASSERT(false, ("TCountryId =", parent, "not found in m_countries."));
|
||||
|
@ -1174,7 +1174,7 @@ void Storage::GetChildrenInGroups(TCountryId const & parent,
|
|||
|
||||
for (size_t i = 0; i < childrenCount; ++i)
|
||||
{
|
||||
TCountriesContainer const & child = parentNode->Child(i);
|
||||
TCountryTreeNode const & child = parentNode->Child(i);
|
||||
TCountryId const & childCountryId = child.Value().Name();
|
||||
if (HasCountryId(localMaps, childCountryId))
|
||||
{ // CountryId of child is a name of an mwm.
|
||||
|
@ -1184,7 +1184,7 @@ void Storage::GetChildrenInGroups(TCountryId const & parent,
|
|||
|
||||
// Child is a group of mwms.
|
||||
bool hasDownloadedDescendant = false;
|
||||
child.ForEachDescendant([&](TCountriesContainer const & descendant)
|
||||
child.ForEachDescendant([&](TCountryTreeNode const & descendant)
|
||||
{
|
||||
TCountryId const & countryId = descendant.Value().Name();
|
||||
if (!hasDownloadedDescendant && HasCountryId(localMaps, countryId))
|
||||
|
@ -1213,12 +1213,12 @@ void Storage::DownloadNode(TCountryId const & countryId)
|
|||
{
|
||||
ASSERT_THREAD_CHECKER(m_threadChecker, ());
|
||||
|
||||
TCountriesContainer const * const node = m_countries.FindFirst(Country(countryId));
|
||||
TCountryTreeNode const * const node = m_countries.FindFirst(Country(countryId));
|
||||
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
auto downloadAction = [this](TCountriesContainer const & descendantNode)
|
||||
auto downloadAction = [this](TCountryTreeNode const & descendantNode)
|
||||
{
|
||||
if (descendantNode.ChildrenCount() == 0)
|
||||
this->DownloadCountry(descendantNode.Value().Name(), MapOptions::MapWithCarRouting);
|
||||
|
@ -1231,12 +1231,12 @@ void Storage::DeleteNode(TCountryId const & countryId)
|
|||
{
|
||||
ASSERT_THREAD_CHECKER(m_threadChecker, ());
|
||||
|
||||
TCountriesContainer const * const node = m_countries.FindFirst(Country(countryId));
|
||||
TCountryTreeNode const * const node = m_countries.FindFirst(Country(countryId));
|
||||
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
auto deleteAction = [this](TCountriesContainer const & descendantNode)
|
||||
auto deleteAction = [this](TCountryTreeNode const & descendantNode)
|
||||
{
|
||||
if (descendantNode.ChildrenCount() == 0)
|
||||
this->DeleteCountry(descendantNode.Value().Name(), MapOptions::MapWithCarRouting);
|
||||
|
@ -1244,7 +1244,7 @@ void Storage::DeleteNode(TCountryId const & countryId)
|
|||
node->ForEachInSubtree(deleteAction);
|
||||
}
|
||||
|
||||
Status Storage::NodeStatus(TCountriesContainer const & node) const
|
||||
Status Storage::NodeStatus(TCountryTreeNode const & node) const
|
||||
{
|
||||
// Leaf node status.
|
||||
if (node.ChildrenCount() == 0)
|
||||
|
@ -1257,7 +1257,7 @@ Status Storage::NodeStatus(TCountriesContainer const & node) const
|
|||
Status const kEverythingDownloaded = Status::EOnDisk;
|
||||
|
||||
Status result = kEverythingDownloaded;
|
||||
auto groupStatusCalculator = [&result, this](TCountriesContainer const & nodeInSubtree)
|
||||
auto groupStatusCalculator = [&result, this](TCountryTreeNode const & nodeInSubtree)
|
||||
{
|
||||
if (result == kDownloadingInProgress || nodeInSubtree.ChildrenCount() != 0)
|
||||
return;
|
||||
|
@ -1292,13 +1292,13 @@ void Storage::GetNodeAttrs(TCountryId const & countryId, NodeAttrs & nodeAttrs)
|
|||
{
|
||||
ASSERT_THREAD_CHECKER(m_threadChecker, ());
|
||||
|
||||
vector<CountryTree<Country> const *> nodes;
|
||||
vector<TCountryTreeNode const *> nodes;
|
||||
m_countries.Find(Country(countryId), nodes);
|
||||
CHECK(!nodes.empty(), ());
|
||||
// If nodes.size() > 1 countryId corresponds to a disputed territories.
|
||||
// In that case it's guaranteed that most of attributes are equal for
|
||||
// each element of nodes. See Country class description for further details.
|
||||
TCountriesContainer const * const node = nodes[0];
|
||||
TCountryTreeNode const * const node = nodes[0];
|
||||
|
||||
Country const & nodeValue = node->Value();
|
||||
nodeAttrs.m_mwmCounter = nodeValue.GetSubtreeMwmCounter();
|
||||
|
@ -1310,7 +1310,7 @@ void Storage::GetNodeAttrs(TCountryId const & countryId, NodeAttrs & nodeAttrs)
|
|||
|
||||
// Status and progress.
|
||||
TCountriesVec descendants;
|
||||
node->ForEachDescendant([&descendants](TCountriesContainer const & d)
|
||||
node->ForEachDescendant([&descendants](TCountryTreeNode const & d)
|
||||
{
|
||||
descendants.push_back(d.Value().Name());
|
||||
});
|
||||
|
@ -1328,7 +1328,7 @@ void Storage::GetNodeAttrs(TCountryId const & countryId, NodeAttrs & nodeAttrs)
|
|||
// Local mwm information.
|
||||
nodeAttrs.m_localMwmCounter = 0;
|
||||
nodeAttrs.m_localMwmSize = 0;
|
||||
node->ForEachInSubtree([this, &nodeAttrs](TCountriesContainer const & d)
|
||||
node->ForEachInSubtree([this, &nodeAttrs](TCountryTreeNode const & d)
|
||||
{
|
||||
Storage::TLocalFilePtr const localFile = GetLatestLocalFile(d.Value().Name());
|
||||
if (localFile == nullptr)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include "storage/country.hpp"
|
||||
#include "storage/country_name_getter.hpp"
|
||||
#include "storage/country_tree_facade.hpp"
|
||||
#include "storage/country_tree.hpp"
|
||||
#include "storage/index.hpp"
|
||||
#include "storage/map_files_downloader.hpp"
|
||||
#include "storage/queued_country.hpp"
|
||||
|
@ -98,7 +98,7 @@ private:
|
|||
/// stores timestamp for update checks
|
||||
int64_t m_currentVersion;
|
||||
|
||||
TCountriesFacade m_countries;
|
||||
TCountryTree m_countries;
|
||||
|
||||
/// @todo. It appeared that our application uses m_queue from
|
||||
/// different threads without any synchronization. To reproduce it
|
||||
|
@ -492,7 +492,7 @@ private:
|
|||
Status CountryStatus(TCountryId const & countryId) const;
|
||||
|
||||
/// Returns status for a node (group node or not)
|
||||
Status NodeStatus(TCountriesContainer const & node) const;
|
||||
Status NodeStatus(TCountryTreeNode const & node) const;
|
||||
|
||||
void NotifyStatusChanged(TCountryId const & countryId);
|
||||
void NotifyStatusChangedForHierarchy(TCountryId const & countryId);
|
||||
|
@ -526,13 +526,13 @@ bool HasCountryId(TCountriesVec const & sortedCountryIds, TCountryId const & cou
|
|||
template <class ToDo>
|
||||
void Storage::ForEachInSubtree(TCountryId const & root, ToDo && toDo) const
|
||||
{
|
||||
TCountriesContainer const * const rootNode = m_countries.FindFirst(Country(root));
|
||||
TCountryTreeNode const * const rootNode = m_countries.FindFirst(Country(root));
|
||||
if (rootNode == nullptr)
|
||||
{
|
||||
ASSERT(false, ("TCountryId =", root, "not found in m_countries."));
|
||||
return;
|
||||
}
|
||||
rootNode->ForEachInSubtree([&toDo](TCountriesContainer const & container)
|
||||
rootNode->ForEachInSubtree([&toDo](TCountryTreeNode const & container)
|
||||
{
|
||||
Country const & value = container.Value();
|
||||
toDo(value.Name(), value.GetSubtreeMwmCounter() != 1 /* groupNode. */);
|
||||
|
@ -562,7 +562,7 @@ void Storage::ForEachInSubtreeAndInQueue(TCountryId const & root, ToDo && toDo)
|
|||
template <class ToDo>
|
||||
void Storage::ForEachAncestorExceptForTheRoot(TCountryId const & countryId, ToDo && toDo) const
|
||||
{
|
||||
vector<CountryTree<Country> const *> nodes;
|
||||
vector<TCountryTreeNode const *> nodes;
|
||||
m_countries.Find(Country(countryId), nodes);
|
||||
if (nodes.empty())
|
||||
{
|
||||
|
@ -575,7 +575,7 @@ void Storage::ForEachAncestorExceptForTheRoot(TCountryId const & countryId, ToDo
|
|||
// may be more than one. It means |childId| is present in the country tree more than once.
|
||||
for (auto const & node : nodes)
|
||||
{
|
||||
node->ForEachAncestorExceptForTheRoot([&](TCountriesContainer const & container)
|
||||
node->ForEachAncestorExceptForTheRoot([&](TCountryTreeNode const & container)
|
||||
{
|
||||
TCountryId const ancestorId = container.Value().Name();
|
||||
if (visitedAncestors.find(ancestorId) != visitedAncestors.end())
|
||||
|
|
|
@ -17,7 +17,6 @@ HEADERS += \
|
|||
country_name_getter.hpp \
|
||||
country_polygon.hpp \
|
||||
country_tree.hpp \
|
||||
country_tree_facade.hpp \
|
||||
http_map_files_downloader.hpp \
|
||||
index.hpp \
|
||||
map_files_downloader.hpp \
|
||||
|
|
|
@ -18,7 +18,7 @@ struct Calculator
|
|||
|
||||
UNIT_TEST(CountryTree_Smoke)
|
||||
{
|
||||
typedef CountryTree<int> TTree;
|
||||
typedef CountryTree<int, int>::Node TTree;
|
||||
TTree tree;
|
||||
|
||||
tree.AddAtDepth(0, 4);
|
||||
|
|
|
@ -1314,10 +1314,10 @@ UNIT_TEST(StorageTest_ForEachAncestorExceptForTheRoot)
|
|||
|
||||
// Two parent case.
|
||||
auto const forEachParentDisputableTerritory
|
||||
= [](TCountryId const & parentId, TCountriesContainer const & parentNode)
|
||||
= [](TCountryId const & parentId, TCountryTreeNode const & parentNode)
|
||||
{
|
||||
TCountriesVec descendants;
|
||||
parentNode.ForEachDescendant([&descendants](TCountriesContainer const & container)
|
||||
parentNode.ForEachDescendant([&descendants](TCountryTreeNode const & container)
|
||||
{
|
||||
descendants.push_back(container.Value().Name());
|
||||
});
|
||||
|
@ -1340,10 +1340,10 @@ UNIT_TEST(StorageTest_ForEachAncestorExceptForTheRoot)
|
|||
|
||||
// One parent case.
|
||||
auto const forEachParentIndisputableTerritory
|
||||
= [](TCountryId const & parentId, TCountriesContainer const & parentNode)
|
||||
= [](TCountryId const & parentId, TCountryTreeNode const & parentNode)
|
||||
{
|
||||
TCountriesVec descendants;
|
||||
parentNode.ForEachDescendant([&descendants](TCountriesContainer const & container)
|
||||
parentNode.ForEachDescendant([&descendants](TCountryTreeNode const & container)
|
||||
{
|
||||
descendants.push_back(container.Value().Name());
|
||||
});
|
||||
|
|
Loading…
Add table
Reference in a new issue