1 /** 2 * @file unique_storage.h 3 * Unique storage of values 4 * 5 * @remark Copyright 2002 OProfile authors 6 * @remark Read the file COPYING 7 * 8 * @author Philippe Elie 9 * @author John Levon 10 */ 11 12 #ifndef UNIQUE_STORAGE_H 13 #define UNIQUE_STORAGE_H 14 15 #include <vector> 16 #include <map> 17 #include <stdexcept> 18 19 /** 20 * Store values such that only one copy of the value 21 * is ever stored. 22 * 23 * I is an arbitrary typename that's never 24 * used. 25 * 26 * It is a required parameter in order to enforce 27 * type-safety for a collection. 28 * 29 * The value type "V" must be default-constructible, 30 * and this is the value returned by a stored id_value 31 * where .set() is false 32 */ 33 template <typename I, typename V> class unique_storage { 34 35 public: 36 unique_storage() { 37 // id 0 38 values.push_back(V()); 39 } 40 41 virtual ~unique_storage() {} 42 43 typedef std::vector<V> stored_values; 44 45 /// the actual ID type 46 struct id_value { 47 /// id == 0 means "empty" / "undefined" 48 id_value() : id(0) {} 49 50 /// does this ID map to a non-default value ? 51 bool set() const { 52 return id; 53 } 54 55 bool operator<(id_value const & rhs) const { 56 return id < rhs.id; 57 } 58 59 bool operator==(id_value const & rhs) const { 60 return id == rhs.id; 61 } 62 63 bool operator!=(id_value const & rhs) const { 64 return !(id == rhs.id); 65 } 66 67 private: 68 friend class unique_storage<I, V>; 69 70 typedef typename stored_values::size_type size_type; 71 72 explicit id_value(size_type s) : id(s) {} 73 74 /// actual ID value 75 size_type id; 76 }; 77 78 79 /// ensure this value is available 80 id_value const create(V const & value) { 81 typename id_map::value_type val(value, id_value(values.size())); 82 std::pair<typename id_map::iterator, bool> 83 inserted = ids.insert(val); 84 if (inserted.second) 85 values.push_back(value); 86 87 return inserted.first->second; 88 } 89 90 91 /// return the stored value for the given ID 92 V const & get(id_value const & id) const { 93 // some stl lack at(), so we emulate it 94 if (id.id < values.size()) 95 return values[id.id]; 96 97 throw std::out_of_range("unique_storage::get(): out of bounds"); 98 } 99 100 private: 101 typedef std::map<V, id_value> id_map; 102 103 /// the contained values 104 stored_values values; 105 106 /// map from ID to value 107 id_map ids; 108 }; 109 110 #endif /* !UNIQUE_STORAGE_H */ 111