Merge m-c to inbound.
[gecko.git] / gfx / 2d / UserData.h
blobe803dc04e1ebc7a01d13a43f4361d6ebcc0479d2
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/. */
6 #ifndef MOZILLA_GFX_USERDATA_H_
7 #define MOZILLA_GFX_USERDATA_H_
9 #include <stdlib.h>
10 #include "Types.h"
11 #include "mozilla/Assertions.h"
13 namespace mozilla {
14 namespace gfx {
16 struct UserDataKey {
17 int unused;
20 /* this class is basically a clone of the user data concept from cairo */
21 class UserData
23 typedef void (*destroyFunc)(void *data);
24 public:
25 UserData() : count(0), entries(nullptr) {}
27 /* Attaches untyped userData associated with key. destroy is called on destruction */
28 void Add(UserDataKey *key, void *userData, destroyFunc destroy)
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);
35 entries[i].userData = userData;
36 entries[i].destroy = destroy;
37 return;
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)));
47 if (!entries) {
48 MOZ_CRASH();
51 entries[count].key = key;
52 entries[count].userData = userData;
53 entries[count].destroy = destroy;
55 count++;
58 /* Remove and return user data associated with key, without destroying it */
59 void* Remove(UserDataKey *key)
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];
69 return userData;
72 return nullptr;
75 /* Retrives the userData for the associated key */
76 void *Get(UserDataKey *key) const
78 for (int i=0; i<count; i++) {
79 if (key == entries[i].key) {
80 return entries[i].userData;
83 return nullptr;
86 bool Has(UserDataKey *key)
88 for (int i=0; i<count; i++) {
89 if (key == entries[i].key) {
90 return true;
93 return false;
96 void Destroy()
98 for (int i=0; i<count; i++) {
99 if (entries[i].destroy) {
100 entries[i].destroy(entries[i].userData);
103 free(entries);
104 entries = nullptr;
105 count = 0;
108 ~UserData()
110 Destroy();
113 private:
114 struct Entry {
115 const UserDataKey *key;
116 void *userData;
117 destroyFunc destroy;
120 int count;
121 Entry *entries;
128 #endif /* MOZILLA_GFX_USERDATA_H_ */