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.
5 #ifndef BASE_PROPERTY_BAG_H_
6 #define BASE_PROPERTY_BAG_H_
10 #include "base/basictypes.h"
11 #include "base/base_export.h"
13 template <typename T
> class linked_ptr
;
17 class PropertyAccessorBase
;
19 // A property bag holds a generalized list of arbitrary metadata called
20 // properties. Each property is a class type derived from PropertyBag::Prop
21 // that can be set and retrieved.
23 // The property bag is not read or written directly. Instead, callers go
24 // through a PropertyAccessor. The Accessor generates the unique IDs that
25 // identify different properties. The Accessor is templatized to also provide
26 // typesafety to the callers.
29 // // Note: you don't want to use Singleton for your Accessor if you're using
30 // // a simple type like int or string as the data, since it will enforce that
31 // // there is only one singleton for that type, which will conflict. If
32 // // you're putting in some struct that's unique to you, go ahead.
33 // PropertyAccessor<int>* my_accessor() const {
34 // static PropertyAccessor<int>* accessor = NULL;
35 // if (!accessor) accessor = new PropertyAccessor<int>;
39 // void doit(SomeObjectThatImplementsPropertyBag* object) {
40 // PropertyAccessor<int>* accessor = my_accessor();
41 // int* property = accessor->GetProperty(object);
43 // ... use property ...
45 // accessor->SetProperty(object, 22);
47 class BASE_EXPORT PropertyBag
{
49 // The type that uniquely identifies a property type.
51 enum { NULL_PROP_ID
= -1 }; // Invalid property ID.
53 // Properties are all derived from this class. They must be deletable and
59 // Copies the property and returns a pointer to the new one. The caller is
60 // responsible for managing the lifetime.
61 virtual Prop
* copy() = 0;
65 PropertyBag(const PropertyBag
& other
);
66 virtual ~PropertyBag();
68 PropertyBag
& operator=(const PropertyBag
& other
);
71 friend class PropertyAccessorBase
;
73 typedef std::map
<PropID
, linked_ptr
<Prop
> > PropertyMap
;
75 // Used by the PropertyAccessor to set the property with the given ID.
76 // Ownership of the given pointer will be transferred to us. Any existing
77 // property matching the given ID will be deleted.
78 void SetProperty(PropID id
, Prop
* prop
);
80 // Used by the PropertyAccessor to retrieve the property with the given ID.
81 // The returned pointer will be NULL if there is no match. Ownership of the
82 // pointer will stay with the property bag.
83 Prop
* GetProperty(PropID id
);
84 const Prop
* GetProperty(PropID id
) const;
86 // Deletes the property with the given ID from the bag if it exists.
87 void DeleteProperty(PropID id
);
91 // Copy and assign is explicitly allowed for this class.
94 // PropertyAccessorBase -------------------------------------------------------
96 // Manages getting the unique IDs to identify a property. Callers should use
97 // PropertyAccessor below instead.
98 class BASE_EXPORT PropertyAccessorBase
{
100 PropertyAccessorBase();
101 virtual ~PropertyAccessorBase() {}
103 // Removes our property, if any, from the given property bag.
104 void DeleteProperty(PropertyBag
* bag
) {
105 bag
->DeleteProperty(prop_id_
);
109 void SetPropertyInternal(PropertyBag
* bag
, PropertyBag::Prop
* prop
) {
110 bag
->SetProperty(prop_id_
, prop
);
112 PropertyBag::Prop
* GetPropertyInternal(PropertyBag
* bag
) {
113 return bag
->GetProperty(prop_id_
);
115 const PropertyBag::Prop
* GetPropertyInternal(const PropertyBag
* bag
) const {
116 return bag
->GetProperty(prop_id_
);
120 // Identifier for this property.
121 PropertyBag::PropID prop_id_
;
123 DISALLOW_COPY_AND_ASSIGN(PropertyAccessorBase
);
126 // PropertyAccessor -----------------------------------------------------------
128 // Provides typesafe accessor functions for a property bag, and manages the
129 // unique identifiers for properties via the PropertyAccessorBase.
131 class PropertyAccessor
: public PropertyAccessorBase
{
133 PropertyAccessor() : PropertyAccessorBase() {}
134 virtual ~PropertyAccessor() {}
136 // Makes a copy of the |prop| object for storage.
137 void SetProperty(PropertyBag
* bag
, const T
& prop
) {
138 SetPropertyInternal(bag
, new Container(prop
));
141 // Returns our property in the given bag or NULL if there is no match. The
142 // returned pointer's ownership will stay with the property bag.
143 T
* GetProperty(PropertyBag
* bag
) {
144 PropertyBag::Prop
* prop
= GetPropertyInternal(bag
);
147 return static_cast<Container
*>(prop
)->get();
149 const T
* GetProperty(const PropertyBag
* bag
) const {
150 const PropertyBag::Prop
* prop
= GetPropertyInternal(bag
);
153 return static_cast<const Container
*>(prop
)->get();
156 // See also DeleteProperty on thn PropertyAccessorBase.
159 class Container
: public PropertyBag::Prop
{
161 explicit Container(const T
& data
) : data_(data
) {}
163 T
* get() { return &data_
; }
164 const T
* get() const { return &data_
; }
167 virtual Prop
* copy() {
168 return new Container(data_
);
174 DISALLOW_COPY_AND_ASSIGN(PropertyAccessor
);
179 #endif // BASE_PROPERTY_BAG_H_