lemon/bits/debug_map.h
author deba
Tue, 30 Oct 2007 10:51:07 +0000
changeset 2504 46a82ce84cc6
parent 2386 81b47fc5c444
child 2553 bfced05fa852
permissions -rw-r--r--
Bug fix
     1 /* -*- C++ -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library
     4  *
     5  * Copyright (C) 2003-2007
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     9  * Permission to use, modify and distribute this software is granted
    10  * provided that this copyright notice appears in all copies. For
    11  * precise terms see the accompanying LICENSE file.
    12  *
    13  * This software is provided "AS IS" with no warranty of any kind,
    14  * express or implied, and with no claim as to its suitability for any
    15  * purpose.
    16  *
    17  */
    18 
    19 #ifndef LEMON_BITS_DEBUG_MAP_H
    20 #define LEMON_BITS_DEBUG_MAP_H
    21 
    22 #include <vector>
    23 #include <algorithm>
    24 
    25 #include <lemon/bits/traits.h>
    26 #include <lemon/bits/utility.h>
    27 #include <lemon/error.h>
    28 
    29 #include <lemon/bits/alteration_notifier.h>
    30 
    31 #include <lemon/concept_check.h>
    32 #include <lemon/concepts/maps.h>
    33 
    34 ///\ingroup graphbits
    35 ///
    36 ///\file
    37 ///\brief Vector based graph maps for debugging.
    38 namespace lemon {
    39 
    40 #ifndef LEMON_STRICT_DEBUG_MAP
    41 #define LEMON_STRICT_DEBUG_MAP false
    42 #endif
    43 
    44   /// \ingroup graphbits
    45   ///
    46   /// \brief Graph map based on the std::vector storage.
    47   ///
    48   /// The DebugMap template class is graph map structure what
    49   /// automatically updates the map when a key is added to or erased from
    50   /// the map. This map also checks some programming failures by example
    51   /// multiple addition of items, erasing of not existing item or
    52   /// not erased items at the destruction of the map. It helps the
    53   /// programmer to avoid segmentation faults and memory leaks.
    54   ///
    55   /// \param Notifier The AlterationNotifier that will notify this map.
    56   /// \param Item The item type of the graph items.
    57   /// \param Value The value type of the map.
    58   /// 
    59   /// \author Balazs Dezso  	
    60   template <typename _Graph, typename _Item, typename _Value>
    61   class DebugMap 
    62     : public ItemSetTraits<_Graph, _Item>::ItemNotifier::ObserverBase {
    63   private:
    64 		
    65     /// The container type of the map.
    66     typedef std::vector<_Value> Container;	
    67 
    68     /// The container type of the debug flags.
    69     typedef std::vector<bool> Flag;	
    70 
    71   public:
    72 
    73     static const bool strictCheck = LEMON_STRICT_DEBUG_MAP;
    74 
    75     struct MapError {
    76     public:
    77       virtual ~MapError() {}
    78       virtual const char* what() const throw() {
    79         return "lemon::DebugMap::MapError";
    80       }
    81     };
    82 
    83     /// The graph type of the map. 
    84     typedef _Graph Graph;
    85     /// The item type of the map.
    86     typedef _Item Item;
    87     /// The reference map tag.
    88     typedef True ReferenceMapTag;
    89 
    90     /// The key type of the map.
    91     typedef _Item Key;
    92     /// The value type of the map.
    93     typedef _Value Value;
    94 
    95     /// The notifier type.
    96     typedef typename ItemSetTraits<_Graph, _Item>::ItemNotifier Notifier;
    97 
    98     /// The map type.
    99     typedef DebugMap Map;
   100     /// The base class of the map.
   101     typedef typename Notifier::ObserverBase Parent;
   102 
   103     /// The reference type of the map;
   104     typedef typename Container::reference Reference;
   105     /// The const reference type of the map;
   106     typedef typename Container::const_reference ConstReference;
   107 
   108 
   109     /// \brief Constructor to attach the new map into the notifier.
   110     ///
   111     /// It constructs a map and attachs it into the notifier.
   112     /// It adds all the items of the graph to the map.
   113     DebugMap(const Graph& graph) {
   114       Parent::attach(graph.notifier(Item()));
   115       container.resize(Parent::notifier()->maxId() + 1);
   116       flag.resize(Parent::notifier()->maxId() + 1, false);
   117       const typename Parent::Notifier* notifier = Parent::notifier();
   118       Item it;
   119       for (notifier->first(it); it != INVALID; notifier->next(it)) {
   120         flag[Parent::notifier()->id(it)] = true;
   121       }
   122     }
   123 
   124     /// \brief Constructor uses given value to initialize the map. 
   125     ///
   126     /// It constructs a map uses a given value to initialize the map. 
   127     /// It adds all the items of the graph to the map.
   128     DebugMap(const Graph& graph, const Value& value) {
   129       Parent::attach(graph.notifier(Item()));
   130       container.resize(Parent::notifier()->maxId() + 1, value);
   131       flag.resize(Parent::notifier()->maxId() + 1, false);
   132       const typename Parent::Notifier* notifier = Parent::notifier();
   133       Item it;
   134       for (notifier->first(it); it != INVALID; notifier->next(it)) {
   135         flag[Parent::notifier()->id(it)] = true;
   136       }
   137     }
   138 
   139     /// \brief Copy constructor
   140     ///
   141     /// Copy constructor.
   142     DebugMap(const DebugMap& _copy) : Parent() {
   143       if (_copy.attached()) {
   144 	Parent::attach(*_copy.notifier());
   145 	container = _copy.container;
   146       }
   147       flag.resize(Parent::notifier()->maxId() + 1, false);
   148       const typename Parent::Notifier* notifier = Parent::notifier();
   149       Item it;
   150       for (notifier->first(it); it != INVALID; notifier->next(it)) {
   151         flag[Parent::notifier()->id(it)] = true;
   152         LEMON_ASSERT(_copy.flag[Parent::notifier()->id(it)], MapError());
   153       }
   154     }
   155 
   156     /// \brief Destructor
   157     ///
   158     /// Destructor.
   159     ~DebugMap() {
   160       const typename Parent::Notifier* notifier = Parent::notifier();
   161       if (notifier != 0) {
   162         Item it;
   163         for (notifier->first(it); it != INVALID; notifier->next(it)) {
   164           LEMON_ASSERT(flag[Parent::notifier()->id(it)], MapError());
   165           flag[Parent::notifier()->id(it)] = false;
   166         }
   167       }
   168       for (int i = 0; i < int(flag.size()); ++i) {
   169         LEMON_ASSERT(!flag[i], MapError());
   170       }
   171     }
   172 
   173     /// \brief Assign operator.
   174     ///
   175     /// This operator assigns for each item in the map the
   176     /// value mapped to the same item in the copied map.  
   177     /// The parameter map should be indiced with the same
   178     /// itemset because this assign operator does not change
   179     /// the container of the map. 
   180     DebugMap& operator=(const DebugMap& cmap) {
   181       return operator=<DebugMap>(cmap);
   182     }
   183 
   184 
   185     /// \brief Template assign operator.
   186     ///
   187     /// The given parameter should be conform to the ReadMap
   188     /// concecpt and could be indiced by the current item set of
   189     /// the NodeMap. In this case the value for each item
   190     /// is assigned by the value of the given ReadMap. 
   191     template <typename CMap>
   192     DebugMap& operator=(const CMap& cmap) {
   193       checkConcept<concepts::ReadMap<Key, _Value>, CMap>();
   194       const typename Parent::Notifier* notifier = Parent::notifier();
   195       Item it;
   196       for (notifier->first(it); it != INVALID; notifier->next(it)) {
   197         set(it, cmap[it]);
   198       }
   199       return *this;
   200     }
   201     
   202   public:
   203 
   204     /// \brief The subcript operator.
   205     ///
   206     /// The subscript operator. The map can be subscripted by the
   207     /// actual items of the graph.      
   208     Reference operator[](const Key& key) {
   209       LEMON_ASSERT(flag[Parent::notifier()->id(key)], MapError());
   210       return container[Parent::notifier()->id(key)];
   211     } 
   212 		
   213     /// \brief The const subcript operator.
   214     ///
   215     /// The const subscript operator. The map can be subscripted by the
   216     /// actual items of the graph. 
   217     ConstReference operator[](const Key& key) const {
   218       LEMON_ASSERT(flag[Parent::notifier()->id(key)], MapError());
   219       return container[Parent::notifier()->id(key)];
   220     }
   221 
   222 
   223     /// \brief The setter function of the map.
   224     ///
   225     /// It the same as operator[](key) = value expression.
   226     void set(const Key& key, const Value& value) {
   227       (*this)[key] = value;
   228     }
   229 
   230   protected:
   231 
   232     /// \brief Adds a new key to the map.
   233     ///		
   234     /// It adds a new key to the map. It called by the observer notifier
   235     /// and it overrides the add() member function of the observer base.     
   236     virtual void add(const Key& key) {
   237       int id = Parent::notifier()->id(key);
   238       if (id >= int(container.size())) {
   239 	container.resize(id + 1);
   240         flag.resize(id + 1, false);
   241       }
   242       LEMON_ASSERT(!flag[Parent::notifier()->id(key)], MapError());
   243       flag[Parent::notifier()->id(key)] = true;
   244       if (strictCheck) {
   245         std::vector<bool> fl(flag.size(), false);
   246         const typename Parent::Notifier* notifier = Parent::notifier();
   247         Item it;
   248         for (notifier->first(it); it != INVALID; notifier->next(it)) {
   249           int jd = Parent::notifier()->id(it);
   250           fl[jd] = true;
   251         }
   252         LEMON_ASSERT(fl == flag, MapError());
   253       }
   254     }
   255 
   256     /// \brief Adds more new keys to the map.
   257     ///		
   258     /// It adds more new keys to the map. It called by the observer notifier
   259     /// and it overrides the add() member function of the observer base.     
   260     virtual void add(const std::vector<Key>& keys) {
   261       int max = container.size() - 1;
   262       for (int i = 0; i < int(keys.size()); ++i) {
   263         int id = Parent::notifier()->id(keys[i]);
   264         if (id >= max) {
   265           max = id;
   266         }
   267       }
   268       container.resize(max + 1);
   269       flag.resize(max + 1, false);
   270       for (int i = 0; i < int(keys.size()); ++i) {
   271         LEMON_ASSERT(!flag[Parent::notifier()->id(keys[i])], MapError());
   272         flag[Parent::notifier()->id(keys[i])] = true;
   273       }
   274       if (strictCheck) {
   275         std::vector<bool> fl(flag.size(), false);
   276         const typename Parent::Notifier* notifier = Parent::notifier();
   277         Item it;
   278         for (notifier->first(it); it != INVALID; notifier->next(it)) {
   279           int id = Parent::notifier()->id(it);
   280           fl[id] = true;
   281         }
   282         LEMON_ASSERT(fl == flag, MapError());
   283       }
   284     }
   285 
   286     /// \brief Erase a key from the map.
   287     ///
   288     /// Erase a key from the map. It called by the observer notifier
   289     /// and it overrides the erase() member function of the observer base.     
   290     virtual void erase(const Key& key) {
   291       if (strictCheck) {
   292         std::vector<bool> fl(flag.size(), false);
   293         const typename Parent::Notifier* notifier = Parent::notifier();
   294         Item it;
   295         for (notifier->first(it); it != INVALID; notifier->next(it)) {
   296           int id = Parent::notifier()->id(it);
   297           fl[id] = true;
   298         }
   299         LEMON_ASSERT(fl == flag, MapError());
   300       }
   301       container[Parent::notifier()->id(key)] = Value();
   302       LEMON_ASSERT(flag[Parent::notifier()->id(key)], MapError());
   303       flag[Parent::notifier()->id(key)] = false;
   304     }
   305 
   306     /// \brief Erase more keys from the map.
   307     ///
   308     /// Erase more keys from the map. It called by the observer notifier
   309     /// and it overrides the erase() member function of the observer base.     
   310     virtual void erase(const std::vector<Key>& keys) {
   311       if (strictCheck) {
   312         std::vector<bool> fl(flag.size(), false);
   313         const typename Parent::Notifier* notifier = Parent::notifier();
   314         Item it;
   315         for (notifier->first(it); it != INVALID; notifier->next(it)) {
   316           int id = Parent::notifier()->id(it);
   317           fl[id] = true;
   318         }
   319         LEMON_ASSERT(fl == flag, MapError());
   320       }
   321       for (int i = 0; i < int(keys.size()); ++i) {
   322 	container[Parent::notifier()->id(keys[i])] = Value();
   323         LEMON_ASSERT(flag[Parent::notifier()->id(keys[i])], MapError());
   324         flag[Parent::notifier()->id(keys[i])] = false;
   325       }
   326     }
   327     
   328     /// \brief Buildes the map.
   329     ///	
   330     /// It buildes the map. It called by the observer notifier
   331     /// and it overrides the build() member function of the observer base.
   332     virtual void build() { 
   333       if (strictCheck) {
   334         for (int i = 0; i < int(flag.size()); ++i) {
   335           LEMON_ASSERT(flag[i], MapError());
   336         }
   337       }
   338       int size = Parent::notifier()->maxId() + 1;
   339       container.reserve(size);
   340       container.resize(size);
   341       flag.reserve(size);
   342       flag.resize(size, false);
   343       const typename Parent::Notifier* notifier = Parent::notifier();
   344       Item it;
   345       for (notifier->first(it); it != INVALID; notifier->next(it)) {
   346         int id = Parent::notifier()->id(it);
   347         LEMON_ASSERT(!flag[id], MapError());
   348         flag[id] = true;
   349       }
   350     }
   351 
   352     /// \brief Clear the map.
   353     ///
   354     /// It erase all items from the map. It called by the observer notifier
   355     /// and it overrides the clear() member function of the observer base.     
   356     virtual void clear() { 
   357       const typename Parent::Notifier* notifier = Parent::notifier();
   358       Item it;
   359       for (notifier->first(it); it != INVALID; notifier->next(it)) {
   360         int id = Parent::notifier()->id(it);
   361         LEMON_ASSERT(flag[id], MapError());
   362         flag[id] = false;
   363       }
   364       if (strictCheck) {
   365         for (int i = 0; i < int(flag.size()); ++i) {
   366           LEMON_ASSERT(!flag[i], MapError());
   367         }
   368       }
   369       container.clear();
   370       flag.clear();
   371     }
   372     
   373   private:
   374 		
   375     Container container;
   376     Flag flag;
   377 
   378   };
   379 
   380 }
   381 
   382 #endif