#pragma once #include "indexer/drawing_rule_def.hpp" #include "indexer/feature_decl.hpp" #include "indexer/map_style.hpp" #include "indexer/scales.hpp" #include "indexer/types_mapping.hpp" #include "base/macros.hpp" #include #include #include #include #include #include class ClassifObject; namespace ftype { inline uint32_t GetEmptyValue() { return 1; } void PushValue(uint32_t & type, uint8_t value); bool GetValue(uint32_t type, uint8_t level, uint8_t & value); void PopValue(uint32_t & type); void TruncValue(uint32_t & type, uint8_t level); uint8_t GetLevel(uint32_t type); } class ClassifObjectPtr { ClassifObject const * m_p; size_t m_ind; public: ClassifObjectPtr() : m_p(0), m_ind(0) {} ClassifObjectPtr(ClassifObject const * p, size_t i): m_p(p), m_ind(i) {} ClassifObject const * get() const { return m_p; } ClassifObject const * operator->() const { return m_p; } operator bool() const { return (m_p != 0); } size_t GetIndex() const { return m_ind; } }; class ClassifObject { struct less_name_t { bool operator() (ClassifObject const & r1, ClassifObject const & r2) const { return (r1.m_name < r2.m_name); } }; public: ClassifObject() {} // for serialization only ClassifObject(std::string const & s) : m_name(s) {} /// @name Fill from osm draw rule files. //@{ private: ClassifObject * AddImpl(std::string const & s); public: ClassifObject * Add(std::string const & s); ClassifObject * Find(std::string const & s); void AddDrawRule(drule::Key const & k); //@} /// @name Find substitution when reading osm features. //@{ ClassifObjectPtr BinaryFind(std::string const & s) const; //@} void Sort(); void Swap(ClassifObject & r); std::string const & GetName() const { return m_name; } ClassifObject const * GetObject(size_t i) const; void ConcatChildNames(std::string & s) const; void GetSuitable(int scale, feature::GeomType gt, drule::KeysT & keys) const; inline std::vector const & GetDrawingRules() const { return m_drawRule; } bool IsDrawable(int scale) const; bool IsDrawableAny() const; bool IsDrawableLike(feature::GeomType gt, bool emptyName = false) const; std::pair GetDrawScaleRange() const; template void ForEachObject(ToDo && toDo) { for (size_t i = 0; i < m_objs.size(); ++i) toDo(&m_objs[i]); } template void ForEachObjectInTree(ToDo && toDo, uint32_t const start) const { for (size_t i = 0; i < m_objs.size(); ++i) { uint32_t type = start; ftype::PushValue(type, static_cast(i)); toDo(&m_objs[i], type); m_objs[i].ForEachObjectInTree(toDo, type); } } using VisibleMask = std::bitset; void SetVisibilityOnScale(bool isVisible, int scale) { m_visibility.set(scale, isVisible); } /// @name Policies for classificator tree serialization. //@{ class BasePolicy { protected: std::vector m_stack; ClassifObject * Current() const { return m_stack.back(); } public: BasePolicy(ClassifObject * pRoot) { m_stack.push_back(pRoot); } void Start(size_t i) { m_stack.push_back(&(Current()->m_objs[i])); } void End() { m_stack.pop_back(); } }; class LoadPolicy : public BasePolicy { typedef BasePolicy base_type; public: LoadPolicy(ClassifObject * pRoot) : base_type(pRoot) {} void Name(std::string const & name) { Current()->m_name = name; } void Start(size_t i); void EndChilds(); }; //@} private: std::string m_name; std::vector m_drawRule; std::vector m_objs; VisibleMask m_visibility; }; inline void swap(ClassifObject & r1, ClassifObject & r2) { r1.Swap(r2); } class Classificator { public: Classificator() : m_root("world") {} ClassifObject * Add(ClassifObject * parent, std::string const & key, std::string const & value); /// @name Serialization-like functions. //@{ void ReadClassificator(std::istream & s); void ReadTypesMapping(std::istream & s); //@} void Clear(); bool HasTypesMapping() const { return m_mapping.IsLoaded(); } /// @return 0 in case of nonexisting type uint32_t GetTypeByPathSafe(std::vector const & path) const; /// Invokes ASSERT in case of nonexisting type uint32_t GetTypeByPath(std::vector const & path) const; uint32_t GetTypeByPath(std::initializer_list const & lst) const; /// @see GetReadableObjectName(). /// @returns 0 in case of nonexisting type. uint32_t GetTypeByReadableObjectName(std::string const & name) const; //@} uint32_t GetIndexForType(uint32_t t) const { return m_mapping.GetIndex(t); } // Throws std::out_of_range exception. uint32_t GetTypeForIndex(uint32_t i) const { return m_mapping.GetType(i); } bool IsTypeValid(uint32_t t) const { return m_mapping.HasIndex(t); } inline uint32_t GetCoastType() const { return m_coastType; } /// @name used in osm2type.cpp, not for public use. //@{ ClassifObject const * GetRoot() const { return &m_root; } ClassifObject * GetMutableRoot() { return &m_root; } //@} /// Iterate through all classificator tree. /// Functor receives pointer to object and uint32 type. template void ForEachTree(ToDo && toDo) const { GetRoot()->ForEachObjectInTree(std::forward(toDo), ftype::GetEmptyValue()); } template void ForEachInSubtree(ToDo && toDo, uint32_t root) const { toDo(root); GetObject(root)->ForEachObjectInTree([&toDo](ClassifObject const *, uint32_t c) { toDo(c); }, root); } /// @name Used only in feature_visibility.cpp, not for public use. //@{ template typename ToDo::ResultType ProcessObjects(uint32_t type, ToDo & toDo) const; ClassifObject const * GetObject(uint32_t type) const; std::string GetFullObjectName(uint32_t type) const; std::vector GetFullObjectNamePath(uint32_t type) const; //@} /// @return Object name to show in UI (not for debug purposes). std::string GetReadableObjectName(uint32_t type) const; private: static ClassifObject * AddV(ClassifObject * parent, std::string const & key, std::string const & value); /// Return type by path in classificator tree, for example /// path = ["natural", "caostline"]. //@{ template uint32_t GetTypeByPathImpl(Iter beg, Iter end) const; ClassifObject m_root; IndexAndTypeMapping m_mapping; uint32_t m_coastType = 0; DISALLOW_COPY_AND_MOVE(Classificator); }; Classificator & classif();