LCOV - code coverage report
Current view: top level - tao_builds/jenkins/workspace/dds_doc_ace6tao2_wiro_linux_gcc_d1o0s1/OpenDDS/tools/dds/rtpsrelaylib - PartitionIndex.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 135 135 100.0 %
Date: 2023-04-30 01:32:43 Functions: 17 17 100.0 %

          Line data    Source code
       1             : #ifndef OPENDDS_RTPSRELAYLIB_PARTITION_INDEX_H
       2             : #define OPENDDS_RTPSRELAYLIB_PARTITION_INDEX_H
       3             : 
       4             : #include "Name.h"
       5             : #include "Utility.h"
       6             : 
       7             : #include <unordered_map>
       8             : 
       9             : namespace RtpsRelay {
      10             : 
      11             : struct GuidToParticipantGuid {
      12          21 :   OpenDDS::DCPS::GUID_t operator()(const OpenDDS::DCPS::GUID_t& x) const
      13             :   {
      14          21 :     return OpenDDS::DCPS::make_part_guid(x);
      15             :   }
      16             : };
      17             : 
      18             : struct Identity {
      19           1 :   std::string operator()(const std::string& x) const
      20             :   {
      21           1 :     return x;
      22             :   }
      23             : };
      24             : 
      25             : 
      26             : template<typename T, typename Transformer>
      27             : class TrieNode {
      28             : public:
      29             :   typedef std::shared_ptr<TrieNode> NodePtr;
      30             : 
      31           8 :   static void insert(NodePtr node, const Name& name, const typename T::value_type& guid)
      32             :   {
      33          47 :     for (const auto& atom : name) {
      34          39 :       const auto iter = node->children_.find(atom);
      35          39 :       if (iter == node->children_.end()) {
      36          38 :         NodePtr child(new TrieNode());
      37          38 :         node->children_[atom] = child;
      38          38 :         node = child;
      39          38 :       } else {
      40           1 :         node = iter->second;
      41             :       }
      42             :     }
      43             : 
      44           8 :     node->guids_.insert(guid);
      45           8 :   }
      46             : 
      47           3 :   static void remove(NodePtr node, const Name& name, const typename T::value_type& guid)
      48             :   {
      49           3 :     remove(node, name.begin(), name.end(), guid);
      50           3 :   }
      51             : 
      52          11 :   bool empty() const
      53             :   {
      54          11 :     return guids_.empty() && children_.empty();
      55             :   }
      56             : 
      57          22 :   static void lookup(NodePtr node, const Name& name, T& guids)
      58             :   {
      59          22 :     if (name.is_literal()) {
      60          13 :       lookup_literal(node, name.begin(), name.end(), false, guids);
      61             :     } else {
      62           9 :       lookup_pattern(node, name.begin(), name.end(), guids);
      63             :     }
      64          22 :   }
      65             : 
      66             : private:
      67             :   typedef std::unordered_map<Atom, NodePtr, AtomHash> ChildrenType;
      68             :   ChildrenType children_;
      69             :   T guids_;
      70             : 
      71          51 :   static void insert_guids(NodePtr node,
      72             :                            T& guids)
      73             :   {
      74          51 :     std::transform(node->guids_.begin(), node->guids_.end(), std::inserter(guids, guids.begin()), Transformer());
      75          51 :   }
      76             : 
      77         182 :   static void lookup_literal(NodePtr node,
      78             :                              Name::const_iterator begin,
      79             :                              Name::const_iterator end,
      80             :                              bool glob_only,
      81             :                              T& guids)
      82             :   {
      83         182 :     if (begin == end) {
      84          24 :       insert_guids(node, guids);
      85          24 :       lookup_globs(node, guids);
      86          24 :       return;
      87             :     }
      88             : 
      89         158 :     const auto& atom = *begin;
      90             : 
      91         368 :     for (const auto& pos : node->children_) {
      92         210 :       switch (pos.first.kind()) {
      93         119 :       case Atom::CHARACTER:
      94         119 :         if (!glob_only && pos.first == atom) {
      95          36 :           lookup_literal(pos.second, std::next(begin), end, false, guids);
      96             :         }
      97         119 :         break;
      98           6 :       case Atom::CHARACTER_CLASS:
      99           6 :         if (!glob_only && pos.first.characters().count(atom.character()) != 0) {
     100           5 :           lookup_literal(pos.second, std::next(begin), end, false, guids);
     101             :         }
     102           6 :         break;
     103           5 :       case Atom::NEGATED_CHARACTER_CLASS:
     104           5 :         if (!glob_only && pos.first.characters().count(atom.character()) == 0) {
     105           4 :           lookup_literal(pos.second, std::next(begin), end, false, guids);
     106             :         }
     107           5 :         break;
     108          21 :       case Atom::WILDCARD:
     109          21 :         if (!glob_only) {
     110           6 :           lookup_literal(pos.second, std::next(begin), end, false, guids);
     111             :         }
     112          21 :         break;
     113          59 :       case Atom::GLOB:
     114             :         // Glob consumes character and remains.
     115          59 :         lookup_literal(node, std::next(begin), end, true, guids);
     116             :         // Glob matches no characters.
     117          59 :         lookup_literal(pos.second, begin, end, false, guids);
     118          59 :         break;
     119             :       }
     120             :     }
     121             :   }
     122             : 
     123          41 :   static void lookup_globs(NodePtr node,
     124             :                            T& guids)
     125             :   {
     126          79 :     for (const auto& pos : node->children_) {
     127          38 :       if (pos.first.kind() == Atom::GLOB) {
     128          17 :         insert_guids(pos.second, guids);
     129          17 :         lookup_globs(pos.second, guids);
     130             :       }
     131             :     }
     132          41 :   }
     133             : 
     134         155 :   static void lookup_pattern(NodePtr node,
     135             :                              Name::const_iterator begin,
     136             :                              Name::const_iterator end,
     137             :                              T& guids)
     138             :   {
     139         155 :     if (begin == end) {
     140          10 :       insert_guids(node, guids);
     141          10 :       return;
     142             :     }
     143             : 
     144         145 :     const auto& atom = *begin;
     145             : 
     146         145 :     switch (atom.kind()) {
     147          74 :     case Atom::CHARACTER:
     148             :       {
     149          74 :         const auto pos = node->children_.find(atom);
     150          74 :         if (pos != node->children_.end()) {
     151          25 :           lookup_pattern(pos->second, std::next(begin), end, guids);
     152             :         }
     153             :       }
     154          74 :       break;
     155           2 :     case Atom::CHARACTER_CLASS:
     156           4 :       for (const auto& p : node->children_) {
     157           2 :         if (p.first.kind() == Atom::CHARACTER && atom.characters().count(p.first.character()) != 0) {
     158           2 :           lookup_pattern(p.second, std::next(begin), end, guids);
     159             :         }
     160             :       }
     161           2 :       break;
     162           2 :     case Atom::NEGATED_CHARACTER_CLASS:
     163           4 :       for (const auto& p : node->children_) {
     164           2 :         if (p.first.kind() == Atom::CHARACTER && atom.characters().count(p.first.character()) == 0) {
     165           2 :           lookup_pattern(p.second, std::next(begin), end, guids);
     166             :         }
     167             :       }
     168           2 :       break;
     169           2 :     case Atom::WILDCARD:
     170           7 :       for (const auto& p : node->children_) {
     171           5 :         if (p.first.kind() == Atom::CHARACTER) {
     172           3 :           lookup_pattern(p.second, std::next(begin), end, guids);
     173             :         }
     174             :       }
     175           2 :       break;
     176          65 :     case Atom::GLOB:
     177             :       // Glob consumes character and remains.
     178         116 :       for (const auto& p : node->children_) {
     179          51 :         if (p.first.kind() == Atom::CHARACTER) {
     180          49 :           lookup_pattern(p.second, begin, end, guids);
     181             :         }
     182             :       }
     183             :       // Glob matches no characters.
     184          65 :       lookup_pattern(node, std::next(begin), end, guids);
     185          65 :       break;
     186             :     }
     187             :   }
     188             : 
     189          14 :   static void remove(NodePtr node,
     190             :                      Name::const_iterator begin,
     191             :                      Name::const_iterator end,
     192             :                      const typename T::value_type& guid)
     193             :   {
     194          14 :     if (begin == end) {
     195           3 :       node->guids_.erase(guid);
     196           3 :       return;
     197             :     }
     198             : 
     199          11 :     const auto& atom = *begin;
     200          11 :     const auto pos = node->children_.find(atom);
     201          11 :     if (pos != node->children_.end()) {
     202          11 :       remove(pos->second, std::next(begin), end, guid);
     203          11 :       if (pos->second->empty()) {
     204          11 :         node->children_.erase(pos);
     205             :       }
     206             :     }
     207             :   }
     208             : };
     209             : 
     210             : template <typename T, typename Transformer>
     211             : class PartitionIndex {
     212             : public:
     213             :   typedef TrieNode<T, Transformer> TrieNodeT;
     214             : 
     215           4 :   PartitionIndex()
     216           4 :     : root_(new TrieNodeT())
     217           4 :   {}
     218             : 
     219           8 :   void insert(const std::string& name, const typename T::value_type& guid)
     220             :   {
     221           8 :     TrieNodeT::insert(root_, Name(name), guid);
     222           8 :     cache_.clear();
     223           8 :   }
     224             : 
     225           3 :   void remove(const std::string& name, const typename T::value_type& guid)
     226             :   {
     227           3 :     TrieNodeT::remove(root_, Name(name), guid);
     228           3 :     cache_.clear();
     229           3 :   }
     230             : 
     231             :   /// If 'allowed' is not nullptr, entries inserted into 'guids' must be in 'allowed'
     232          24 :   void lookup(const std::string& name, T& guids, const T* allowed = nullptr) const
     233             :   {
     234          24 :     LimitedInserter inserter(guids, allowed);
     235          24 :     const auto pos = cache_.find(name);
     236          24 :     if (pos != cache_.end()) {
     237           2 :       inserter.insert(pos->second.begin(), pos->second.end());
     238           2 :       return;
     239             :     }
     240          22 :     T& cache_temp = cache_[name];
     241          22 :     TrieNodeT::lookup(root_, Name(name), cache_temp);
     242          22 :     inserter.insert(cache_temp.begin(), cache_temp.end());
     243             :   }
     244             : 
     245             :   class LimitedInserter {
     246             :   public:
     247          24 :     LimitedInserter(T& output, const T* limits)
     248          24 :       : output_(output)
     249          24 :       , limits_(limits)
     250          24 :     {}
     251             : 
     252          24 :     void insert(const typename T::const_iterator& begin, const typename T::const_iterator& end)
     253             :     {
     254          24 :       if (limits_) {
     255           4 :         for (auto iter = begin; iter != end; ++iter) {
     256           3 :           if (limits_->count(*iter)) {
     257           2 :             output_.insert(*iter);
     258             :           }
     259             :         }
     260             :       } else {
     261          23 :         output_.insert(begin, end);
     262             :       }
     263          24 :     }
     264             : 
     265             :   private:
     266             :     T& output_;
     267             :     const T* limits_;
     268             :   };
     269             : 
     270             : private:
     271             :   typename TrieNodeT::NodePtr root_;
     272             :   typedef std::unordered_map<std::string, T> Cache;
     273             :   mutable Cache cache_;
     274             : };
     275             : 
     276             : }
     277             : 
     278             : #endif // RTPSRELAY_PARTITION_INDEX_H_

Generated by: LCOV version 1.16