OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 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 CONTENT_COMMON_PROPERTY_BAG_H_ | |
6 #define CONTENT_COMMON_PROPERTY_BAG_H_ | |
7 #pragma once | |
8 | |
9 #include <map> | |
10 | |
11 #include "base/basictypes.h" | |
12 #include "content/common/content_export.h" | |
13 | |
14 template <typename T> | |
15 class linked_ptr; | |
16 class PropertyAccessorBase; | |
17 | |
18 // A property bag holds a generalized list of arbitrary metadata called | |
19 // properties. Each property is a class type derived from PropertyBag::Prop | |
20 // that can be set and retrieved. | |
21 // | |
22 // The property bag is not read or written directly. Instead, callers go | |
23 // through a PropertyAccessor. The Accessor generates the unique IDs that | |
24 // identify different properties. The Accessor is templatized to also provide | |
25 // typesafety to the callers. | |
26 // | |
27 // Example: | |
28 // // Note: you don't want to use Singleton for your Accessor if you're using | |
29 // // a simple type like int or string as the data, since it will enforce that | |
30 // // there is only one singleton for that type, which will conflict. If | |
31 // // you're putting in some struct that's unique to you, go ahead. | |
32 // PropertyAccessor<int>* my_accessor() const { | |
33 // static PropertyAccessor<int>* accessor = NULL; | |
34 // if (!accessor) accessor = new PropertyAccessor<int>; | |
35 // return accessor; | |
36 // } | |
37 // | |
38 // void doit(SomeObjectThatImplementsPropertyBag* object) { | |
39 // PropertyAccessor<int>* accessor = my_accessor(); | |
40 // int* property = accessor->GetProperty(object); | |
41 // if (property) | |
42 // ... use property ... | |
43 // | |
44 // accessor->SetProperty(object, 22); | |
45 // } | |
46 class CONTENT_EXPORT PropertyBag { | |
47 public: | |
48 // The type that uniquely identifies a property type. | |
49 typedef int PropID; | |
50 enum { NULL_PROP_ID = -1 }; // Invalid property ID. | |
51 | |
52 // Properties are all derived from this class. They must be deletable and | |
53 // copyable | |
54 class Prop { | |
55 public: | |
56 virtual ~Prop() {} | |
57 | |
58 // Copies the property and returns a pointer to the new one. The caller is | |
59 // responsible for managing the lifetime. | |
60 virtual Prop* copy() = 0; | |
61 }; | |
62 | |
63 PropertyBag(); | |
64 PropertyBag(const PropertyBag& other); | |
65 virtual ~PropertyBag(); | |
66 | |
67 PropertyBag& operator=(const PropertyBag& other); | |
68 | |
69 private: | |
70 friend class PropertyAccessorBase; | |
71 | |
72 typedef std::map<PropID, linked_ptr<Prop> > PropertyMap; | |
73 | |
74 // Used by the PropertyAccessor to set the property with the given ID. | |
75 // Ownership of the given pointer will be transferred to us. Any existing | |
76 // property matching the given ID will be deleted. | |
77 void SetProperty(PropID id, Prop* prop); | |
78 | |
79 // Used by the PropertyAccessor to retrieve the property with the given ID. | |
80 // The returned pointer will be NULL if there is no match. Ownership of the | |
81 // pointer will stay with the property bag. | |
82 Prop* GetProperty(PropID id); | |
83 const Prop* GetProperty(PropID id) const; | |
84 | |
85 // Deletes the property with the given ID from the bag if it exists. | |
86 void DeleteProperty(PropID id); | |
87 | |
88 PropertyMap props_; | |
89 | |
90 // Copy and assign is explicitly allowed for this class. | |
91 }; | |
92 | |
93 // PropertyAccessorBase ------------------------------------------------------- | |
94 | |
95 // Manages getting the unique IDs to identify a property. Callers should use | |
96 // PropertyAccessor below instead. | |
97 class CONTENT_EXPORT PropertyAccessorBase { | |
98 public: | |
99 PropertyAccessorBase(); | |
100 virtual ~PropertyAccessorBase() {} | |
101 | |
102 // Removes our property, if any, from the given property bag. | |
103 void DeleteProperty(PropertyBag* bag) { | |
104 bag->DeleteProperty(prop_id_); | |
105 } | |
106 | |
107 protected: | |
108 void SetPropertyInternal(PropertyBag* bag, PropertyBag::Prop* prop) { | |
109 bag->SetProperty(prop_id_, prop); | |
110 } | |
111 PropertyBag::Prop* GetPropertyInternal(PropertyBag* bag) { | |
112 return bag->GetProperty(prop_id_); | |
113 } | |
114 const PropertyBag::Prop* GetPropertyInternal(const PropertyBag* bag) const { | |
115 return bag->GetProperty(prop_id_); | |
116 } | |
117 | |
118 private: | |
119 // Identifier for this property. | |
120 PropertyBag::PropID prop_id_; | |
121 | |
122 DISALLOW_COPY_AND_ASSIGN(PropertyAccessorBase); | |
123 }; | |
124 | |
125 // PropertyAccessor ----------------------------------------------------------- | |
126 | |
127 // Provides typesafe accessor functions for a property bag, and manages the | |
128 // unique identifiers for properties via the PropertyAccessorBase. | |
129 template<class T> | |
130 class PropertyAccessor : public PropertyAccessorBase { | |
131 public: | |
132 PropertyAccessor() : PropertyAccessorBase() {} | |
133 virtual ~PropertyAccessor() {} | |
134 | |
135 // Makes a copy of the |prop| object for storage. | |
136 void SetProperty(PropertyBag* bag, const T& prop) { | |
137 SetPropertyInternal(bag, new Container(prop)); | |
138 } | |
139 | |
140 // Returns our property in the given bag or NULL if there is no match. The | |
141 // returned pointer's ownership will stay with the property bag. | |
142 T* GetProperty(PropertyBag* bag) { | |
143 PropertyBag::Prop* prop = GetPropertyInternal(bag); | |
144 if (!prop) | |
145 return NULL; | |
146 return static_cast<Container*>(prop)->get(); | |
147 } | |
148 const T* GetProperty(const PropertyBag* bag) const { | |
149 const PropertyBag::Prop* prop = GetPropertyInternal(bag); | |
150 if (!prop) | |
151 return NULL; | |
152 return static_cast<const Container*>(prop)->get(); | |
153 } | |
154 | |
155 // See also DeleteProperty on thn PropertyAccessorBase. | |
156 | |
157 private: | |
158 class Container : public PropertyBag::Prop { | |
159 public: | |
160 explicit Container(const T& data) : data_(data) {} | |
161 | |
162 T* get() { return &data_; } | |
163 const T* get() const { return &data_; } | |
164 | |
165 private: | |
166 virtual Prop* copy() { | |
167 return new Container(data_); | |
168 } | |
169 | |
170 T data_; | |
171 }; | |
172 | |
173 DISALLOW_COPY_AND_ASSIGN(PropertyAccessor); | |
174 }; | |
175 | |
176 #endif // CONTENT_COMMON_PROPERTY_BAG_H_ | |
OLD | NEW |