|
1 /* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- |
|
2 * This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #ifndef MOZILLA_GFX_USERDATA_H_ |
|
7 #define MOZILLA_GFX_USERDATA_H_ |
|
8 |
|
9 #include <stdlib.h> |
|
10 #include "Types.h" |
|
11 #include "mozilla/Assertions.h" |
|
12 |
|
13 namespace mozilla { |
|
14 namespace gfx { |
|
15 |
|
16 struct UserDataKey { |
|
17 int unused; |
|
18 }; |
|
19 |
|
20 /* this class is basically a clone of the user data concept from cairo */ |
|
21 class UserData |
|
22 { |
|
23 typedef void (*destroyFunc)(void *data); |
|
24 public: |
|
25 UserData() : count(0), entries(nullptr) {} |
|
26 |
|
27 /* Attaches untyped userData associated with key. destroy is called on destruction */ |
|
28 void Add(UserDataKey *key, void *userData, destroyFunc destroy) |
|
29 { |
|
30 for (int i=0; i<count; i++) { |
|
31 if (key == entries[i].key) { |
|
32 if (entries[i].destroy) { |
|
33 entries[i].destroy(entries[i].userData); |
|
34 } |
|
35 entries[i].userData = userData; |
|
36 entries[i].destroy = destroy; |
|
37 return; |
|
38 } |
|
39 } |
|
40 |
|
41 // We could keep entries in a std::vector instead of managing it by hand |
|
42 // but that would propagate an stl dependency out which we'd rather not |
|
43 // do (see bug 666609). Plus, the entries array is expect to stay small |
|
44 // so doing a realloc everytime we add a new entry shouldn't be too costly |
|
45 entries = static_cast<Entry*>(realloc(entries, sizeof(Entry)*(count+1))); |
|
46 |
|
47 if (!entries) { |
|
48 MOZ_CRASH(); |
|
49 } |
|
50 |
|
51 entries[count].key = key; |
|
52 entries[count].userData = userData; |
|
53 entries[count].destroy = destroy; |
|
54 |
|
55 count++; |
|
56 } |
|
57 |
|
58 /* Remove and return user data associated with key, without destroying it */ |
|
59 void* Remove(UserDataKey *key) |
|
60 { |
|
61 for (int i=0; i<count; i++) { |
|
62 if (key == entries[i].key) { |
|
63 void *userData = entries[i].userData; |
|
64 // decrement before looping so entries[i+1] doesn't read past the end: |
|
65 --count; |
|
66 for (;i<count; i++) { |
|
67 entries[i] = entries[i+1]; |
|
68 } |
|
69 return userData; |
|
70 } |
|
71 } |
|
72 return nullptr; |
|
73 } |
|
74 |
|
75 /* Retrives the userData for the associated key */ |
|
76 void *Get(UserDataKey *key) const |
|
77 { |
|
78 for (int i=0; i<count; i++) { |
|
79 if (key == entries[i].key) { |
|
80 return entries[i].userData; |
|
81 } |
|
82 } |
|
83 return nullptr; |
|
84 } |
|
85 |
|
86 bool Has(UserDataKey *key) |
|
87 { |
|
88 for (int i=0; i<count; i++) { |
|
89 if (key == entries[i].key) { |
|
90 return true; |
|
91 } |
|
92 } |
|
93 return false; |
|
94 } |
|
95 |
|
96 void Destroy() |
|
97 { |
|
98 for (int i=0; i<count; i++) { |
|
99 if (entries[i].destroy) { |
|
100 entries[i].destroy(entries[i].userData); |
|
101 } |
|
102 } |
|
103 free(entries); |
|
104 entries = nullptr; |
|
105 count = 0; |
|
106 } |
|
107 |
|
108 ~UserData() |
|
109 { |
|
110 Destroy(); |
|
111 } |
|
112 |
|
113 private: |
|
114 struct Entry { |
|
115 const UserDataKey *key; |
|
116 void *userData; |
|
117 destroyFunc destroy; |
|
118 }; |
|
119 |
|
120 int count; |
|
121 Entry *entries; |
|
122 |
|
123 }; |
|
124 |
|
125 } |
|
126 } |
|
127 |
|
128 #endif /* MOZILLA_GFX_USERDATA_H_ */ |