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 CONTENT_COMMON_PROPERTY_BAG_H_
6 #define CONTENT_COMMON_PROPERTY_BAG_H_
11 #include "base/basictypes.h"
15 class PropertyAccessorBase
;
17 // A property bag holds a generalized list of arbitrary metadata called
18 // properties. Each property is a class type derived from PropertyBag::Prop
19 // that can be set and retrieved.
21 // The property bag is not read or written directly. Instead, callers go
22 // through a PropertyAccessor. The Accessor generates the unique IDs that
23 // identify different properties. The Accessor is templatized to also provide
24 // typesafety to the callers.
27 // // Note: you don't want to use Singleton for your Accessor if you're using
28 // // a simple type like int or string as the data, since it will enforce that
29 // // there is only one singleton for that type, which will conflict. If
30 // // you're putting in some struct that's unique to you, go ahead.
31 // PropertyAccessor<int>* my_accessor() const {
32 // static PropertyAccessor<int>* accessor = NULL;
33 // if (!accessor) accessor = new PropertyAccessor<int>;
37 // void doit(SomeObjectThatImplementsPropertyBag* object) {
38 // PropertyAccessor<int>* accessor = my_accessor();
39 // int* property = accessor->GetProperty(object);
41 // ... use property ...
43 // accessor->SetProperty(object, 22);
47 // The type that uniquely identifies a property type.
49 enum { NULL_PROP_ID
= -1 }; // Invalid property ID.
51 // Properties are all derived from this class. They must be deletable and
57 // Copies the property and returns a pointer to the new one. The caller is
58 // responsible for managing the lifetime.
59 virtual Prop
* copy() = 0;
63 PropertyBag(const PropertyBag
& other
);
64 virtual ~PropertyBag();
66 PropertyBag
& operator=(const PropertyBag
& other
);
69 friend class PropertyAccessorBase
;
71 typedef std::map
<PropID
, linked_ptr
<Prop
> > PropertyMap
;
73 // Used by the PropertyAccessor to set the property with the given ID.
74 // Ownership of the given pointer will be transferred to us. Any existing
75 // property matching the given ID will be deleted.
76 void SetProperty(PropID id
, Prop
* prop
);
78 // Used by the PropertyAccessor to retrieve the property with the given ID.
79 // The returned pointer will be NULL if there is no match. Ownership of the
80 // pointer will stay with the property bag.
81 Prop
* GetProperty(PropID id
);
82 const Prop
* GetProperty(PropID id
) const;
84 // Deletes the property with the given ID from the bag if it exists.
85 void DeleteProperty(PropID id
);
89 // Copy and assign is explicitly allowed for this class.
92 // PropertyAccessorBase -------------------------------------------------------
94 // Manages getting the unique IDs to identify a property. Callers should use
95 // PropertyAccessor below instead.
96 class PropertyAccessorBase
{
98 PropertyAccessorBase();
99 virtual ~PropertyAccessorBase() {}
101 // Removes our property, if any, from the given property bag.
102 void DeleteProperty(PropertyBag
* bag
) {
103 bag
->DeleteProperty(prop_id_
);
107 void SetPropertyInternal(PropertyBag
* bag
, PropertyBag::Prop
* prop
) {
108 bag
->SetProperty(prop_id_
, prop
);
110 PropertyBag::Prop
* GetPropertyInternal(PropertyBag
* bag
) {
111 return bag
->GetProperty(prop_id_
);
113 const PropertyBag::Prop
* GetPropertyInternal(const PropertyBag
* bag
) const {
114 return bag
->GetProperty(prop_id_
);
118 // Identifier for this property.
119 PropertyBag::PropID prop_id_
;
121 DISALLOW_COPY_AND_ASSIGN(PropertyAccessorBase
);
124 // PropertyAccessor -----------------------------------------------------------
126 // Provides typesafe accessor functions for a property bag, and manages the
127 // unique identifiers for properties via the PropertyAccessorBase.
129 class PropertyAccessor
: public PropertyAccessorBase
{
131 PropertyAccessor() : PropertyAccessorBase() {}
132 virtual ~PropertyAccessor() {}
134 // Makes a copy of the |prop| object for storage.
135 void SetProperty(PropertyBag
* bag
, const T
& prop
) {
136 SetPropertyInternal(bag
, new Container(prop
));
139 // Returns our property in the given bag or NULL if there is no match. The
140 // returned pointer's ownership will stay with the property bag.
141 T
* GetProperty(PropertyBag
* bag
) {
142 PropertyBag::Prop
* prop
= GetPropertyInternal(bag
);
145 return static_cast<Container
*>(prop
)->get();
147 const T
* GetProperty(const PropertyBag
* bag
) const {
148 const PropertyBag::Prop
* prop
= GetPropertyInternal(bag
);
151 return static_cast<const Container
*>(prop
)->get();
154 // See also DeleteProperty on thn PropertyAccessorBase.
157 class Container
: public PropertyBag::Prop
{
159 explicit Container(const T
& data
) : data_(data
) {}
161 T
* get() { return &data_
; }
162 const T
* get() const { return &data_
; }
165 virtual Prop
* copy() {
166 return new Container(data_
);
172 DISALLOW_COPY_AND_ASSIGN(PropertyAccessor
);
175 #endif // CONTENT_COMMON_PROPERTY_BAG_H_