| /** |
| * @file unique_storage.h |
| * Unique storage of values |
| * |
| * @remark Copyright 2002 OProfile authors |
| * @remark Read the file COPYING |
| * |
| * @author Philippe Elie |
| * @author John Levon |
| */ |
| |
| #ifndef UNIQUE_STORAGE_H |
| #define UNIQUE_STORAGE_H |
| |
| #include <vector> |
| #include <map> |
| #include <stdexcept> |
| |
| /** |
| * Store values such that only one copy of the value |
| * is ever stored. |
| * |
| * I is an arbitrary typename that's never |
| * used. |
| * |
| * It is a required parameter in order to enforce |
| * type-safety for a collection. |
| * |
| * The value type "V" must be default-constructible, |
| * and this is the value returned by a stored id_value |
| * where .set() is false |
| */ |
| template <typename I, typename V> class unique_storage { |
| |
| public: |
| unique_storage() { |
| // id 0 |
| values.push_back(V()); |
| } |
| |
| virtual ~unique_storage() {} |
| |
| typedef std::vector<V> stored_values; |
| |
| /// the actual ID type |
| struct id_value { |
| /// id == 0 means "empty" / "undefined" |
| id_value() : id(0) {} |
| |
| /// does this ID map to a non-default value ? |
| bool set() const { |
| return id; |
| } |
| |
| bool operator<(id_value const & rhs) const { |
| return id < rhs.id; |
| } |
| |
| bool operator==(id_value const & rhs) const { |
| return id == rhs.id; |
| } |
| |
| bool operator!=(id_value const & rhs) const { |
| return !(id == rhs.id); |
| } |
| |
| private: |
| friend class unique_storage<I, V>; |
| |
| typedef typename stored_values::size_type size_type; |
| |
| explicit id_value(size_type s) : id(s) {} |
| |
| /// actual ID value |
| size_type id; |
| }; |
| |
| |
| /// ensure this value is available |
| id_value const create(V const & value) { |
| typename id_map::value_type val(value, id_value(values.size())); |
| std::pair<typename id_map::iterator, bool> |
| inserted = ids.insert(val); |
| if (inserted.second) |
| values.push_back(value); |
| |
| return inserted.first->second; |
| } |
| |
| |
| /// return the stored value for the given ID |
| V const & get(id_value const & id) const { |
| // some stl lack at(), so we emulate it |
| if (id.id < values.size()) |
| return values[id.id]; |
| |
| throw std::out_of_range("unique_storage::get(): out of bounds"); |
| } |
| |
| private: |
| typedef std::map<V, id_value> id_map; |
| |
| /// the contained values |
| stored_values values; |
| |
| /// map from ID to value |
| id_map ids; |
| }; |
| |
| #endif /* !UNIQUE_STORAGE_H */ |