From 2b5a4541fb6f806c02a1f6e65a1ff2610f29751f Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Sat, 31 Oct 2020 16:02:26 +0100 Subject: issue #8129: Image path is now case sensitive (take 2) --- src/filename.h | 33 +++++++++++++++++++++++++++++++- src/linkedmap.h | 59 +++++++++++++++++++++++++-------------------------------- 2 files changed, 58 insertions(+), 34 deletions(-) diff --git a/src/filename.h b/src/filename.h index f8ea2e1..d236046 100644 --- a/src/filename.h +++ b/src/filename.h @@ -20,6 +20,7 @@ #include #include "linkedmap.h" +#include "config.h" class FileDef; @@ -38,8 +39,38 @@ class FileName : public std::vector< std::unique_ptr > QCString m_pathName; }; +//! Custom combined key compare and hash functor that uses a lower case string in +//! case CASE_SENSE_NAMES is set to NO. +class FileNameFn +{ + public: + //! used as hash function + std::size_t operator()(const std::string& input) const noexcept + { + return std::hash()(searchKey(input)); + } + //! used as equal operator + bool operator() (const std::string &t1, const std::string &t2) const + { + return searchKey(t1) == searchKey(t2); + } + private: + std::string searchKey(std::string input) const + { + std::string key = input; + if (!Config_getBool(CASE_SENSE_NAMES)) + { + // convert key to lower case + std::transform(key.begin(),key.end(),key.begin(), + [](char c){ return (char)std::tolower(c); }); + } + return key; + } +}; + /** Ordered dictionary of FileName objects. */ -class FileNameLinkedMap : public LinkedMap +class FileNameLinkedMap : public LinkedMap > { }; diff --git a/src/linkedmap.h b/src/linkedmap.h index e61f99b..9ca0fa2 100644 --- a/src/linkedmap.h +++ b/src/linkedmap.h @@ -23,30 +23,18 @@ #include #include -#include "config.h" - -inline std::string LinkedMap_make_key(const char *k,bool case_sensitivity_support) -{ - std::string key(k ? k : ""); - if (case_sensitivity_support && !Config_getBool(CASE_SENSE_NAMES)) - { - // convert key to lower case - std::transform(key.begin(),key.end(),key.begin(),[](char c){ return std::tolower(c); }); - } - return key; -} - -//! @brief Container class representing a vector of objects with unique keys. +//! @brief Container class representing a vector of objects with keys. //! @details Objects can efficiently be looked up given the key. //! Objects are owned by the container. //! When adding objects the order of addition is kept, and used while iterating. -template +template, + class KeyEqual = std::equal_to, + class Map = std::unordered_map > class LinkedMap { public: using Ptr = std::unique_ptr; using Vec = std::vector; - using Map = std::unordered_map; using iterator = typename Vec::iterator; using const_iterator = typename Vec::const_iterator; using reverse_iterator = typename Vec::reverse_iterator; @@ -54,9 +42,10 @@ class LinkedMap //! Find an object given the key. //! Returns a pointer to the element if found or nullptr if it is not found. - const T *find(const char *key) const + const T *find(const char *key_) const { - auto it = m_lookup.find(LinkedMap_make_key(key,case_sensitivity_support)); + std::string key(key_ ? key_ : ""); + auto it = m_lookup.find(key); return it!=m_lookup.end() ? it->second : nullptr; } @@ -75,7 +64,7 @@ class LinkedMap T *result = find(k); if (result==nullptr) { - std::string key = LinkedMap_make_key(k,case_sensitivity_support); + std::string key(k ? k : ""); Ptr ptr = std::make_unique(key.c_str(),std::forward(args)...); result = ptr.get(); m_lookup.insert({key,result}); @@ -93,7 +82,7 @@ class LinkedMap T *result = find(k); if (result==nullptr) { - std::string key = LinkedMap_make_key(k,case_sensitivity_support); + std::string key(k ? k : ""); Ptr ptr = std::make_unique(key.c_str(),std::forward(args)...); result = ptr.get(); m_lookup.insert({key,result}); @@ -103,10 +92,11 @@ class LinkedMap } //! Removes an object from the container and deletes it. - //! Returns true if the object was delete or false it is was not found. - bool del(const char *key) + //! Returns true if the object was deleted or false it is was not found. + bool del(const char *key_) { - auto it = m_lookup.find(LinkedMap_make_key(key,case_sensitivity_support)); + std::string key(key_ ? key_ : ""); + auto it = m_lookup.find(key); if (it!=m_lookup.end()) { auto vecit = std::find_if(m_entries.begin(),m_entries.end(),[obj=it->second](auto &el) { return el.get()==obj; }); @@ -143,17 +133,18 @@ class LinkedMap Vec m_entries; }; -//! @brief Container class representing a vector of objects with unique keys. +//! @brief Container class representing a vector of objects with keys. //! @details Objects can be efficiently be looked up given the key. //! Objects are \e not owned by the container, the container will only hold references. //! When adding objects the order of addition is kept, and used while iterating. -template +template, + class KeyEqual = std::equal_to, + class Map = std::unordered_map > class LinkedRefMap { public: using Ptr = T*; using Vec = std::vector; - using Map = std::unordered_map; using iterator = typename Vec::iterator; using const_iterator = typename Vec::const_iterator; using reverse_iterator = typename Vec::reverse_iterator; @@ -161,9 +152,10 @@ class LinkedRefMap //! find an object given the key. //! Returns a pointer to the object if found or nullptr if it is not found. - const T *find(const char *key) const + const T *find(const char *key_) const { - auto it = m_lookup.find(LinkedMap_make_key(key,case_sensitivity_support)); + std::string key(key_ ? key_ : ""); + auto it = m_lookup.find(key); return it!=m_lookup.end() ? it->second : nullptr; } @@ -180,7 +172,7 @@ class LinkedRefMap { if (find(k)==nullptr) // new element { - std::string key = LinkedMap_make_key(k,case_sensitivity_support); + std::string key(k ? k : ""); m_lookup.insert({key,obj}); m_entries.push_back(obj); return true; @@ -198,7 +190,7 @@ class LinkedRefMap { if (find(k)==nullptr) // new element { - std::string key = LinkedMap_make_key(k,case_sensitivity_support); + std::string key(k ? k : ""); m_lookup.insert({key,obj}); m_entries.insert(m_entries.begin(),obj); return true; @@ -210,10 +202,11 @@ class LinkedRefMap } //! Removes an object from the container and deletes it. - //! Returns true if the object was delete or false it is was not found. - bool del(const char *key) + //! Returns true if the object was deleted or false it is was not found. + bool del(const char *key_) { - auto it = m_lookup.find(LinkedMap_make_key(key,case_sensitivity_support)); + std::string key(key_ ? key_ : ""); + auto it = m_lookup.find(key); if (it!=m_lookup.end()) { auto vecit = std::find_if(m_entries.begin(),m_entries.end(),[obj=it->second](auto &el) { return el.get()==obj; }); -- cgit v0.12