| 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 BASE_PROPERTY_BAG_H_ | |
| 6 #define BASE_PROPERTY_BAG_H_ | |
| 7 | |
| 8 #include <map> | |
| 9 | |
| 10 #include "base/basictypes.h" | |
| 11 #include "base/base_export.h" | |
| 12 | |
| 13 template <typename T> class linked_ptr; | |
| 14 | |
| 15 namespace base { | |
| 16 | |
| 17 class PropertyAccessorBase; | |
| 18 | |
| 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. | |
| 22 // | |
| 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. | |
| 27 // | |
| 28 // Example: | |
| 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>; | |
| 36 // return accessor; | |
| 37 // } | |
| 38 // | |
| 39 // void doit(SomeObjectThatImplementsPropertyBag* object) { | |
| 40 // PropertyAccessor<int>* accessor = my_accessor(); | |
| 41 // int* property = accessor->GetProperty(object); | |
| 42 // if (property) | |
| 43 // ... use property ... | |
| 44 // | |
| 45 // accessor->SetProperty(object, 22); | |
| 46 // } | |
| 47 class BASE_EXPORT PropertyBag { | |
| 48 public: | |
| 49 // The type that uniquely identifies a property type. | |
| 50 typedef int PropID; | |
| 51 enum { NULL_PROP_ID = -1 }; // Invalid property ID. | |
| 52 | |
| 53 // Properties are all derived from this class. They must be deletable and | |
| 54 // copyable | |
| 55 class Prop { | |
| 56 public: | |
| 57 virtual ~Prop() {} | |
| 58 | |
| 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; | |
| 62 }; | |
| 63 | |
| 64 PropertyBag(); | |
| 65 PropertyBag(const PropertyBag& other); | |
| 66 virtual ~PropertyBag(); | |
| 67 | |
| 68 PropertyBag& operator=(const PropertyBag& other); | |
| 69 | |
| 70 private: | |
| 71 friend class PropertyAccessorBase; | |
| 72 | |
| 73 typedef std::map<PropID, linked_ptr<Prop> > PropertyMap; | |
| 74 | |
| 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); | |
| 79 | |
| 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; | |
| 85 | |
| 86 // Deletes the property with the given ID from the bag if it exists. | |
| 87 void DeleteProperty(PropID id); | |
| 88 | |
| 89 PropertyMap props_; | |
| 90 | |
| 91 // Copy and assign is explicitly allowed for this class. | |
| 92 }; | |
| 93 | |
| 94 // PropertyAccessorBase ------------------------------------------------------- | |
| 95 | |
| 96 // Manages getting the unique IDs to identify a property. Callers should use | |
| 97 // PropertyAccessor below instead. | |
| 98 class BASE_EXPORT PropertyAccessorBase { | |
| 99 public: | |
| 100 PropertyAccessorBase(); | |
| 101 virtual ~PropertyAccessorBase() {} | |
| 102 | |
| 103 // Removes our property, if any, from the given property bag. | |
| 104 void DeleteProperty(PropertyBag* bag) { | |
| 105 bag->DeleteProperty(prop_id_); | |
| 106 } | |
| 107 | |
| 108 protected: | |
| 109 void SetPropertyInternal(PropertyBag* bag, PropertyBag::Prop* prop) { | |
| 110 bag->SetProperty(prop_id_, prop); | |
| 111 } | |
| 112 PropertyBag::Prop* GetPropertyInternal(PropertyBag* bag) { | |
| 113 return bag->GetProperty(prop_id_); | |
| 114 } | |
| 115 const PropertyBag::Prop* GetPropertyInternal(const PropertyBag* bag) const { | |
| 116 return bag->GetProperty(prop_id_); | |
| 117 } | |
| 118 | |
| 119 private: | |
| 120 // Identifier for this property. | |
| 121 PropertyBag::PropID prop_id_; | |
| 122 | |
| 123 DISALLOW_COPY_AND_ASSIGN(PropertyAccessorBase); | |
| 124 }; | |
| 125 | |
| 126 // PropertyAccessor ----------------------------------------------------------- | |
| 127 | |
| 128 // Provides typesafe accessor functions for a property bag, and manages the | |
| 129 // unique identifiers for properties via the PropertyAccessorBase. | |
| 130 template<class T> | |
| 131 class PropertyAccessor : public PropertyAccessorBase { | |
| 132 public: | |
| 133 PropertyAccessor() : PropertyAccessorBase() {} | |
| 134 virtual ~PropertyAccessor() {} | |
| 135 | |
| 136 // Makes a copy of the |prop| object for storage. | |
| 137 void SetProperty(PropertyBag* bag, const T& prop) { | |
| 138 SetPropertyInternal(bag, new Container(prop)); | |
| 139 } | |
| 140 | |
| 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); | |
| 145 if (!prop) | |
| 146 return NULL; | |
| 147 return static_cast<Container*>(prop)->get(); | |
| 148 } | |
| 149 const T* GetProperty(const PropertyBag* bag) const { | |
| 150 const PropertyBag::Prop* prop = GetPropertyInternal(bag); | |
| 151 if (!prop) | |
| 152 return NULL; | |
| 153 return static_cast<const Container*>(prop)->get(); | |
| 154 } | |
| 155 | |
| 156 // See also DeleteProperty on thn PropertyAccessorBase. | |
| 157 | |
| 158 private: | |
| 159 class Container : public PropertyBag::Prop { | |
| 160 public: | |
| 161 explicit Container(const T& data) : data_(data) {} | |
| 162 | |
| 163 T* get() { return &data_; } | |
| 164 const T* get() const { return &data_; } | |
| 165 | |
| 166 private: | |
| 167 virtual Prop* copy() { | |
| 168 return new Container(data_); | |
| 169 } | |
| 170 | |
| 171 T data_; | |
| 172 }; | |
| 173 | |
| 174 DISALLOW_COPY_AND_ASSIGN(PropertyAccessor); | |
| 175 }; | |
| 176 | |
| 177 } // namespace base | |
| 178 | |
| 179 #endif // BASE_PROPERTY_BAG_H_ | |
| OLD | NEW |