Line data Source code
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 526 : UserData() : count(0), entries(nullptr) {}
26 :
27 : /* Attaches untyped userData associated with key. destroy is called on destruction */
28 775 : void Add(UserDataKey *key, void *userData, destroyFunc destroy)
29 : {
30 787 : for (int i=0; i<count; i++) {
31 535 : if (key == entries[i].key) {
32 523 : if (entries[i].destroy) {
33 523 : entries[i].destroy(entries[i].userData);
34 : }
35 523 : entries[i].userData = userData;
36 523 : entries[i].destroy = destroy;
37 523 : 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 252 : entries = static_cast<Entry*>(realloc(entries, sizeof(Entry)*(count+1)));
46 :
47 252 : if (!entries) {
48 0 : MOZ_CRASH("GFX: UserData::Add");
49 : }
50 :
51 252 : entries[count].key = key;
52 252 : entries[count].userData = userData;
53 252 : entries[count].destroy = destroy;
54 :
55 252 : count++;
56 : }
57 :
58 : /* Remove and return user data associated with key, without destroying it */
59 24 : void* Remove(UserDataKey *key)
60 : {
61 48 : for (int i=0; i<count; i++) {
62 24 : if (key == entries[i].key) {
63 0 : void *userData = entries[i].userData;
64 : // decrement before looping so entries[i+1] doesn't read past the end:
65 0 : --count;
66 0 : for (;i<count; i++) {
67 0 : entries[i] = entries[i+1];
68 : }
69 0 : return userData;
70 : }
71 : }
72 24 : return nullptr;
73 : }
74 :
75 : /* Remove and destroy a given key */
76 0 : void RemoveAndDestroy(UserDataKey *key)
77 : {
78 0 : for (int i=0; i<count; i++) {
79 0 : if (key == entries[i].key) {
80 0 : entries[i].destroy(entries[i].userData);
81 : // decrement before looping so entries[i+1] doesn't read past the end:
82 0 : --count;
83 0 : for (;i<count; i++) {
84 0 : entries[i] = entries[i+1];
85 : }
86 : }
87 : }
88 0 : }
89 :
90 : /* Retrives the userData for the associated key */
91 6083 : void *Get(UserDataKey *key) const
92 : {
93 6746 : for (int i=0; i<count; i++) {
94 5935 : if (key == entries[i].key) {
95 5272 : return entries[i].userData;
96 : }
97 : }
98 811 : return nullptr;
99 : }
100 :
101 889 : bool Has(UserDataKey *key)
102 : {
103 1449 : for (int i=0; i<count; i++) {
104 793 : if (key == entries[i].key) {
105 233 : return true;
106 : }
107 : }
108 656 : return false;
109 : }
110 :
111 345 : void Destroy()
112 : {
113 560 : for (int i=0; i<count; i++) {
114 215 : if (entries[i].destroy) {
115 215 : entries[i].destroy(entries[i].userData);
116 : }
117 : }
118 345 : free(entries);
119 345 : entries = nullptr;
120 345 : count = 0;
121 345 : }
122 :
123 345 : ~UserData()
124 345 : {
125 345 : Destroy();
126 345 : }
127 :
128 : private:
129 : struct Entry {
130 : const UserDataKey *key;
131 : void *userData;
132 : destroyFunc destroy;
133 : };
134 :
135 : int count;
136 : Entry *entries;
137 :
138 : };
139 :
140 : } // namespace gfx
141 : } // namespace mozilla
142 :
143 : #endif /* MOZILLA_GFX_USERDATA_H_ */
|