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:
Diffstat (limited to 'indexer/data_source.cpp')
-rw-r--r--indexer/data_source.cpp244
1 files changed, 235 insertions, 9 deletions
diff --git a/indexer/data_source.cpp b/indexer/data_source.cpp
index bb6b7ea3ed..fffe4650d7 100644
--- a/indexer/data_source.cpp
+++ b/indexer/data_source.cpp
@@ -2,15 +2,172 @@
#include "base/logging.hpp"
+#include <limits>
+#include <type_traits>
+
using platform::CountryFile;
using platform::LocalCountryFile;
using namespace std;
-//////////////////////////////////////////////////////////////////////////////////
-// DataSourceBase implementation
-//////////////////////////////////////////////////////////////////////////////////
+namespace
+{
+template <typename Element>
+class ReadMWMFunctor
+{
+public:
+ using Fn = function<void(Element &)>;
+
+ ReadMWMFunctor(Fn const & fn, FeatureSourceFactory const & factory) : m_fn(fn), m_factory(factory)
+ {
+ }
+
+ template <typename T>
+ enable_if_t<is_same<T, FeatureID const>::value> ProcessElement(FeatureSource & src,
+ uint32_t index) const
+ {
+ if (FeatureStatus::Deleted == src.GetFeatureStatus(index))
+ return;
+
+ m_fn(src.GetFeatureId(index));
+ }
+
+ template <typename T>
+ enable_if_t<is_same<T, FeatureType>::value> ProcessElement(FeatureSource & src,
+ uint32_t index) const
+ {
+ FeatureType feature;
+ switch (src.GetFeatureStatus(index))
+ {
+ case FeatureStatus::Created: CHECK(false, ("Created features index should be generated."));
+ case FeatureStatus::Deleted:
+ case FeatureStatus::Obsolete: return;
+ case FeatureStatus::Modified:
+ {
+ VERIFY(src.GetModifiedFeature(index, feature), ());
+ break;
+ }
+ case FeatureStatus::Untouched:
+ {
+ src.GetOriginalFeature(index, feature);
+ break;
+ }
+ }
+ m_fn(feature);
+ }
+
+ // Reads features visible at |scale| covered by |cov| from mwm and applies |m_fn| to it.
+ // Feature reading process consists of two steps: untouched (original) features reading and
+ // touched (created, edited etc.) features reading.
+ void operator()(MwmSet::MwmHandle const & handle, covering::CoveringGetter & cov, int scale) const
+ {
+ auto src = m_factory(handle);
+
+ MwmValue const * pValue = handle.GetValue<MwmValue>();
+ if (pValue)
+ {
+ // Untouched (original) features reading. Applies covering |cov| to geometry index, gets
+ // feature ids from it, gets untouched features by ids from |src| and applies |m_fn| by
+ // ProcessElement.
+ feature::DataHeader const & header = pValue->GetHeader();
+ CheckUniqueIndexes checkUnique(header.GetFormat() >= version::Format::v5);
+
+ // In case of WorldCoasts we should pass correct scale in ForEachInIntervalAndScale.
+ auto const lastScale = header.GetLastScale();
+ if (scale > lastScale)
+ scale = lastScale;
+
+ // Use last coding scale for covering (see index_builder.cpp).
+ covering::Intervals const & intervals = cov.Get<RectId::DEPTH_LEVELS>(lastScale);
+ ScaleIndex<ModelReaderPtr> index(pValue->m_cont.GetReader(INDEX_FILE_TAG), pValue->m_factory);
+
+ // iterate through intervals
+ for (auto const & i : intervals)
+ {
+ index.ForEachInIntervalAndScale(i.first, i.second, scale, [&](uint32_t index) {
+ if (!checkUnique(index))
+ return;
+ ProcessElement<Element>(*src, index);
+ });
+ }
+ }
+ // Check created features container.
+ // Need to do it on a per-mwm basis, because Drape relies on features in a sorted order.
+ // Touched (created, edited) features reading.
+ src->ForEachInRectAndScale(cov.GetRect(), scale, m_fn);
+ }
+
+private:
+ Fn m_fn;
+ FeatureSourceFactory const & m_factory;
+};
+} // namespace
+
+//------------------------- DataSource::FeaturesLoaderGuard ----------------------
+
+string DataSource::FeaturesLoaderGuard::GetCountryFileName() const
+{
+ if (!m_handle.IsAlive())
+ return string();
+
+ return m_handle.GetValue<MwmValue>()->GetCountryFileName();
+}
+
+bool DataSource::FeaturesLoaderGuard::IsWorld() const
+{
+ if (!m_handle.IsAlive())
+ return false;
+
+ return m_handle.GetValue<MwmValue>()->GetHeader().GetType() == feature::DataHeader::world;
+}
+
+unique_ptr<FeatureType> DataSource::FeaturesLoaderGuard::GetOriginalFeatureByIndex(
+ uint32_t index) const
+{
+ auto feature = make_unique<FeatureType>();
+ if (GetOriginalFeatureByIndex(index, *feature))
+ return feature;
+
+ return {};
+}
-unique_ptr<MwmInfo> DataSourceBase::CreateInfo(platform::LocalCountryFile const & localFile) const
+unique_ptr<FeatureType> DataSource::FeaturesLoaderGuard::GetOriginalOrEditedFeatureByIndex(
+ uint32_t index) const
+{
+ auto feature = make_unique<FeatureType>();
+ if (!m_handle.IsAlive())
+ return {};
+
+ ASSERT_NOT_EQUAL(m_source->GetFeatureStatus(index), FeatureStatus::Created, ());
+ if (GetFeatureByIndex(index, *feature))
+ return feature;
+
+ return {};
+}
+
+/// Everyone, except Editor core, should use this method.
+WARN_UNUSED_RESULT bool DataSource::FeaturesLoaderGuard::GetFeatureByIndex(uint32_t index,
+ FeatureType & ft) const
+{
+ if (!m_handle.IsAlive())
+ return false;
+
+ ASSERT_NOT_EQUAL(FeatureStatus::Deleted, m_source->GetFeatureStatus(index),
+ ("Deleted feature was cached. It should not be here. Please review your code."));
+ if (m_source->GetModifiedFeature(index, ft))
+ return true;
+ return GetOriginalFeatureByIndex(index, ft);
+}
+
+/// Editor core only method, to get 'untouched', original version of feature.
+WARN_UNUSED_RESULT bool DataSource::FeaturesLoaderGuard::GetOriginalFeatureByIndex(
+ uint32_t index, FeatureType & ft) const
+{
+ return m_handle.IsAlive() ? m_source->GetOriginalFeature(index, ft) : false;
+}
+
+//---------------- DataSource -----------------------------------------------
+
+unique_ptr<MwmInfo> DataSource::CreateInfo(platform::LocalCountryFile const & localFile) const
{
MwmValue value(localFile);
@@ -32,7 +189,7 @@ unique_ptr<MwmInfo> DataSourceBase::CreateInfo(platform::LocalCountryFile const
return unique_ptr<MwmInfo>(move(info));
}
-unique_ptr<MwmSet::MwmValueBase> DataSourceBase::CreateValue(MwmInfo & info) const
+unique_ptr<MwmSet::MwmValueBase> DataSource::CreateValue(MwmInfo & info) const
{
// Create a section with rank table if it does not exist.
platform::LocalCountryFile const & localFile = info.GetLocalFile();
@@ -42,15 +199,15 @@ unique_ptr<MwmSet::MwmValueBase> DataSourceBase::CreateValue(MwmInfo & info) con
return unique_ptr<MwmSet::MwmValueBase>(move(p));
}
-pair<MwmSet::MwmId, MwmSet::RegResult> DataSourceBase::RegisterMap(LocalCountryFile const & localFile)
+pair<MwmSet::MwmId, MwmSet::RegResult> DataSource::RegisterMap(LocalCountryFile const & localFile)
{
return Register(localFile);
}
-bool DataSourceBase::DeregisterMap(CountryFile const & countryFile) { return Deregister(countryFile); }
+bool DataSource::DeregisterMap(CountryFile const & countryFile) { return Deregister(countryFile); }
-void DataSourceBase::ForEachInIntervals(ReaderCallback const & fn, covering::CoveringMode mode,
- m2::RectD const & rect, int scale) const
+void DataSource::ForEachInIntervals(ReaderCallback const & fn, covering::CoveringMode mode,
+ m2::RectD const & rect, int scale) const
{
vector<shared_ptr<MwmInfo>> mwms;
GetMwmsInfo(mwms);
@@ -80,3 +237,72 @@ void DataSourceBase::ForEachInIntervals(ReaderCallback const & fn, covering::Cov
if (worldID[1].IsAlive())
fn(GetMwmHandleById(worldID[1]), cov, scale);
}
+
+void DataSource::ForEachFeatureIDInRect(FeatureIdCallback const & f, m2::RectD const & rect,
+ int scale) const
+{
+ ReadMWMFunctor<FeatureID const> readFunctor(f, *m_factory);
+ ForEachInIntervals(readFunctor, covering::LowLevelsOnly, rect, scale);
+}
+
+void DataSource::ForEachInRect(FeatureCallback const & f, m2::RectD const & rect, int scale) const
+{
+ ReadMWMFunctor<FeatureType> readFunctor(f, *m_factory);
+ ForEachInIntervals(readFunctor, covering::ViewportWithLowLevels, rect, scale);
+}
+
+void DataSource::ForEachInScale(FeatureCallback const & f, int scale) const
+{
+ ReadMWMFunctor<FeatureType> readFunctor(f, *m_factory);
+ ForEachInIntervals(readFunctor, covering::FullCover, m2::RectD::GetInfiniteRect(), scale);
+}
+
+void DataSource::ForEachInRectForMWM(FeatureCallback const & f, m2::RectD const & rect, int scale,
+ MwmId const & id) const
+{
+ MwmHandle const handle = GetMwmHandleById(id);
+ if (handle.IsAlive())
+ {
+ covering::CoveringGetter cov(rect, covering::ViewportWithLowLevels);
+ ReadMWMFunctor<FeatureType> readFunctor(f, *m_factory);
+ readFunctor(handle, cov, scale);
+ }
+}
+
+void DataSource::ReadFeatures(FeatureConstCallback const & fn,
+ vector<FeatureID> const & features) const
+{
+ ASSERT(is_sorted(features.begin(), features.end()), ());
+
+ auto fidIter = features.begin();
+ auto const endIter = features.end();
+ while (fidIter != endIter)
+ {
+ MwmId const & id = fidIter->m_mwmId;
+ MwmHandle const handle = GetMwmHandleById(id);
+ if (handle.IsAlive())
+ {
+ // Prepare features reading.
+ auto src = (*m_factory)(handle);
+ do
+ {
+ auto const fts = src->GetFeatureStatus(fidIter->m_index);
+ ASSERT_NOT_EQUAL(
+ FeatureStatus::Deleted, fts,
+ ("Deleted feature was cached. It should not be here. Please review your code."));
+ FeatureType featureType;
+ if (fts == FeatureStatus::Modified || fts == FeatureStatus::Created)
+ VERIFY(src->GetModifiedFeature(fidIter->m_index, featureType), ());
+ else
+ src->GetOriginalFeature(fidIter->m_index, featureType);
+ fn(featureType);
+ } while (++fidIter != endIter && id == fidIter->m_mwmId);
+ }
+ else
+ {
+ // Skip unregistered mwm files.
+ while (++fidIter != endIter && id == fidIter->m_mwmId)
+ ;
+ }
+ }
+}