| 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 |