OLD | NEW |
---|---|
(Empty) | |
1 | |
2 /* | |
3 * Copyright 2013 Google Inc. | |
4 * | |
5 * Use of this source code is governed by a BSD-style license that can be | |
6 * found in the LICENSE file. | |
7 */ | |
8 | |
9 #ifndef GrTMultiset_DEFINED | |
10 #define GrTMultiset_DEFINED | |
11 | |
12 #include "GrTypes.h" | |
13 #include "SkTDynamicHash.h" | |
14 | |
15 /** A set that contains pointers to instances of T. Instances can be looked up w ith key Key. | |
16 * Multiple (possibly same) values can have the same key. | |
17 */ | |
18 template <typename T, | |
19 typename Key, | |
20 const Key& (GetKey)(const T&), | |
21 uint32_t (Hash)(const Key&), | |
22 bool (Equal)(const T&, const Key&)> | |
23 class GrTMultiset { | |
mtklein
2014/01/17 15:08:43
I think I'd prefer it if this were SkTMultiMap, in
Kimmo Kinnunen
2014/01/17 17:14:45
Done.
| |
24 struct ValueList { | |
25 ValueList(T* value) | |
26 : fValue(value), | |
27 fNext(NULL) { | |
mtklein
2014/01/17 15:08:43
We generally put the ',' in front of fNext here.
Kimmo Kinnunen
2014/01/17 17:14:45
Done.
| |
28 } | |
29 | |
30 static const Key& ListGetKey(const ValueList& e) { return GetKey(*e.fVal ue); } | |
31 static uint32_t ListHash(const Key& key) { return Hash(key); } | |
32 static bool ListEqual(const ValueList& a, const Key& b) { | |
33 return Equal(*a.fValue, b); | |
34 } | |
35 T* fValue; | |
36 ValueList* fNext; | |
37 }; | |
38 public: | |
39 GrTMultiset() | |
40 : fCount(0) { | |
41 } | |
42 | |
43 ~GrTMultiset() { | |
44 SkASSERT(fCount == 0); | |
45 SkASSERT(fHash.count() == 0); | |
46 } | |
47 | |
48 void insert(const Key& key, T* value) { | |
49 ValueList* list = fHash.find(key); | |
50 if (NULL != list) { | |
51 ValueList* newEntry = SkNEW_ARGS(ValueList, (list->fValue)); | |
52 newEntry->fNext = list->fNext; | |
mtklein
2014/01/17 15:08:43
Can you just add a small comment here that we alwa
Kimmo Kinnunen
2014/01/17 17:14:45
Correct. Done.
| |
53 list->fNext = newEntry; | |
54 list->fValue = value; | |
55 } else { | |
56 fHash.add(SkNEW_ARGS(ValueList, (value))); | |
57 } | |
58 | |
59 ++fCount; | |
60 } | |
61 | |
62 void remove(const Key& key, T* value) { | |
mtklein
2014/01/17 15:08:43
Curious, can we write this as const T* value? We'
Kimmo Kinnunen
2014/01/17 17:14:45
Done.
| |
63 ValueList* list = fHash.find(key); | |
mtklein
2014/01/17 15:08:43
NULL check list? If it's safe how it's used, SkAS
Kimmo Kinnunen
2014/01/17 17:14:45
Done, added an assert.
| |
64 ValueList* prev = NULL; | |
65 while (list->fValue != value) { | |
66 prev = list; | |
67 list = list->fNext; | |
68 } | |
69 | |
70 if (NULL != list->fNext) { | |
71 ValueList* next = list->fNext; | |
72 list->fValue = next->fValue; | |
73 list->fNext = next->fNext; | |
74 delete next; | |
mtklein
2014/01/17 15:08:43
Please use SkDELETE for all these. (There's no di
Kimmo Kinnunen
2014/01/17 17:14:45
Done.
| |
75 } else if (NULL != prev) { | |
76 prev->fNext = NULL; | |
77 delete list; | |
78 } else { | |
79 fHash.remove(key); | |
80 delete list; | |
81 } | |
82 | |
83 --fCount; | |
84 } | |
85 | |
86 T* find(const Key& key) const { | |
87 ValueList* list = fHash.find(key); | |
88 if (NULL != list) { | |
89 return list->fValue; | |
90 } | |
91 return NULL; | |
92 } | |
93 | |
94 template<class FindPredicate> | |
95 T* find(const Key& key, const FindPredicate f) { | |
96 ValueList* list = fHash.find(key); | |
97 while (NULL != list) { | |
98 if (f(list->fValue)){ | |
99 return list->fValue; | |
100 } | |
101 list = list->fNext; | |
102 } | |
103 return NULL; | |
104 } | |
105 | |
106 int count() const { return fCount; } | |
107 | |
108 private: | |
109 SkTDynamicHash<ValueList, | |
110 Key, | |
111 ValueList::ListGetKey, | |
112 ValueList::ListHash, | |
113 ValueList::ListEqual> fHash; | |
114 int fCount; | |
115 }; | |
116 | |
117 #endif | |
OLD | NEW |