|
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
|
2 // Use of this source code is governed by a BSD-style license that can be |
|
3 // found in the LICENSE file. |
|
4 |
|
5 #ifndef BASE_ID_MAP_H__ |
|
6 #define BASE_ID_MAP_H__ |
|
7 |
|
8 #include "base/basictypes.h" |
|
9 #include "base/hash_tables.h" |
|
10 #include "base/logging.h" |
|
11 |
|
12 // This object maintains a list of IDs that can be quickly converted to |
|
13 // pointers to objects. It is implemented as a hash table, optimized for |
|
14 // relatively small data sets (in the common case, there will be exactly one |
|
15 // item in the list). |
|
16 // |
|
17 // Items can be inserted into the container with arbitrary ID, but the caller |
|
18 // must ensure they are unique. Inserting IDs and relying on automatically |
|
19 // generated ones is not allowed because they can collide. |
|
20 template<class T> |
|
21 class IDMap { |
|
22 private: |
|
23 typedef base::hash_map<int32_t, T*> HashTable; |
|
24 typedef typename HashTable::iterator iterator; |
|
25 |
|
26 public: |
|
27 // support const iterators over the items |
|
28 // Note, use iterator->first to get the ID, iterator->second to get the T* |
|
29 typedef typename HashTable::const_iterator const_iterator; |
|
30 |
|
31 IDMap() : next_id_(1) { |
|
32 } |
|
33 IDMap(const IDMap& other) : next_id_(other.next_id_), |
|
34 data_(other.data_) { |
|
35 } |
|
36 |
|
37 const_iterator begin() const { |
|
38 return data_.begin(); |
|
39 } |
|
40 const_iterator end() const { |
|
41 return data_.end(); |
|
42 } |
|
43 |
|
44 // Adds a view with an automatically generated unique ID. See AddWithID. |
|
45 int32_t Add(T* data) { |
|
46 int32_t this_id = next_id_; |
|
47 DCHECK(data_.find(this_id) == data_.end()) << "Inserting duplicate item"; |
|
48 data_[this_id] = data; |
|
49 next_id_++; |
|
50 return this_id; |
|
51 } |
|
52 |
|
53 // Adds a new data member with the specified ID. The ID must not be in |
|
54 // the list. The caller either must generate all unique IDs itself and use |
|
55 // this function, or allow this object to generate IDs and call Add. These |
|
56 // two methods may not be mixed, or duplicate IDs may be generated |
|
57 void AddWithID(T* data, int32_t id) { |
|
58 DCHECK(data_.find(id) == data_.end()) << "Inserting duplicate item"; |
|
59 data_[id] = data; |
|
60 } |
|
61 |
|
62 void Remove(int32_t id) { |
|
63 iterator i = data_.find(id); |
|
64 if (i == data_.end()) { |
|
65 NOTREACHED() << "Attempting to remove an item not in the list"; |
|
66 return; |
|
67 } |
|
68 data_.erase(i); |
|
69 } |
|
70 |
|
71 bool IsEmpty() const { |
|
72 return data_.empty(); |
|
73 } |
|
74 |
|
75 void Clear() { |
|
76 data_.clear(); |
|
77 } |
|
78 |
|
79 bool HasData(const T* data) const { |
|
80 // XXX would like to use <algorithm> here ... |
|
81 for (const_iterator it = begin(); it != end(); ++it) |
|
82 if (data == it->second) |
|
83 return true; |
|
84 return false; |
|
85 } |
|
86 |
|
87 T* Lookup(int32_t id) const { |
|
88 const_iterator i = data_.find(id); |
|
89 if (i == data_.end()) |
|
90 return NULL; |
|
91 return i->second; |
|
92 } |
|
93 |
|
94 size_t size() const { |
|
95 return data_.size(); |
|
96 } |
|
97 |
|
98 protected: |
|
99 // The next ID that we will return from Add() |
|
100 int32_t next_id_; |
|
101 |
|
102 HashTable data_; |
|
103 }; |
|
104 |
|
105 #endif // BASE_ID_MAP_H__ |