1 // 2 // Copyright (C) 2012 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #ifndef SHILL_PROPERTY_ACCESSOR_H_ 18 #define SHILL_PROPERTY_ACCESSOR_H_ 19 20 #include <base/macros.h> 21 #include <gtest/gtest_prod.h> // for FRIEND_TEST. 22 23 #include "shill/accessor_interface.h" 24 #include "shill/error.h" 25 #include "shill/logging.h" 26 27 namespace shill { 28 29 // Templated implementations of AccessorInterface<>. 30 // 31 // PropertyAccessor<>, ConstPropertyAccessor<>, and 32 // WriteOnlyPropertyAccessor<> provide R/W, R/O, and W/O access 33 // (respectively) to the value pointed to by |property|. 34 // 35 // This allows a class to easily map strings to member variables, so that 36 // pieces of state stored in the class can be queried or updated by name. 37 // 38 // bool foo = true; 39 // map<string, BoolAccessor> accessors; 40 // accessors["foo"] = BoolAccessor(new PropertyAccessor<bool>(&foo)); 41 // bool new_foo = accessors["foo"]->Get(); // new_foo == true 42 // accessors["foo"]->Set(false); // returns true, because setting is allowed. 43 // // foo == false, new_foo == true 44 // new_foo = accessors["foo"]->Get(); // new_foo == false 45 // // Clear resets |foo| to its value when the PropertyAccessor was created. 46 // accessors["foo"]->Clear(); // foo == true 47 // 48 // Generic accessors that provide write capability will check that the 49 // new value differs from the present one. If the old and new values 50 // are the same, the setter will not invoke the assignment operator, and 51 // will return false. 52 // 53 // Custom accessors are responsible for handling set-to-same-value 54 // themselves. It is not possible to handle that here, because some 55 // custom getters return default values, rather than the actual 56 // value. (I'm looking at you, WiFi::GetBgscanMethod.) 57 template <class T> 58 class PropertyAccessor : public AccessorInterface<T> { 59 public: PropertyAccessor(T * property)60 explicit PropertyAccessor(T* property) 61 : property_(property), default_value_(*property) { 62 DCHECK(property); 63 } ~PropertyAccessor()64 ~PropertyAccessor() override {} 65 Clear(Error * error)66 void Clear(Error* error) override { Set(default_value_, error); } Get(Error *)67 T Get(Error* /*error*/) override { return *property_; } Set(const T & value,Error *)68 bool Set(const T& value, Error* /*error*/) override { 69 if (*property_ == value) { 70 return false; 71 } 72 *property_ = value; 73 return true; 74 } 75 76 private: 77 T* const property_; 78 const T default_value_; 79 DISALLOW_COPY_AND_ASSIGN(PropertyAccessor); 80 }; 81 82 template <class T> 83 class ConstPropertyAccessor : public AccessorInterface<T> { 84 public: ConstPropertyAccessor(const T * property)85 explicit ConstPropertyAccessor(const T* property) : property_(property) { 86 DCHECK(property); 87 } ~ConstPropertyAccessor()88 ~ConstPropertyAccessor() override {} 89 Clear(Error * error)90 void Clear(Error* error) override { 91 // TODO(quiche): check if this is the right error. 92 // (maybe Error::kInvalidProperty instead?) 93 error->Populate(Error::kInvalidArguments, "Property is read-only"); 94 } Get(Error *)95 T Get(Error* /*error*/) override { return *property_; } Set(const T &,Error * error)96 bool Set(const T& /*value*/, Error* error) override { 97 // TODO(quiche): check if this is the right error. 98 // (maybe Error::kPermissionDenied instead?) 99 error->Populate(Error::kInvalidArguments, "Property is read-only"); 100 return false; 101 } 102 103 private: 104 const T* const property_; 105 DISALLOW_COPY_AND_ASSIGN(ConstPropertyAccessor); 106 }; 107 108 template <class T> 109 class WriteOnlyPropertyAccessor : public AccessorInterface<T> { 110 public: WriteOnlyPropertyAccessor(T * property)111 explicit WriteOnlyPropertyAccessor(T* property) 112 : property_(property), default_value_(*property) { 113 DCHECK(property); 114 } ~WriteOnlyPropertyAccessor()115 ~WriteOnlyPropertyAccessor() override {} 116 Clear(Error * error)117 void Clear(Error* error) override { Set(default_value_, error); } Get(Error * error)118 T Get(Error* error) override { 119 error->Populate(Error::kPermissionDenied, "Property is write-only"); 120 return T(); 121 } Set(const T & value,Error *)122 bool Set(const T& value, Error* /*error*/) override { 123 if (*property_ == value) { 124 return false; 125 } 126 *property_ = value; 127 return true; 128 } 129 130 private: 131 FRIEND_TEST(PropertyAccessorTest, SignedIntCorrectness); 132 FRIEND_TEST(PropertyAccessorTest, UnsignedIntCorrectness); 133 FRIEND_TEST(PropertyAccessorTest, StringCorrectness); 134 FRIEND_TEST(PropertyAccessorTest, ByteArrayCorrectness); 135 136 T* const property_; 137 const T default_value_; 138 DISALLOW_COPY_AND_ASSIGN(WriteOnlyPropertyAccessor); 139 }; 140 141 // CustomAccessor<> allows custom getter and setter methods to be provided. 142 // Thus, if the state to be returned is to be derived on-demand, or if 143 // setting the property requires validation, we can still fit it into the 144 // AccessorInterface<> framework. 145 // 146 // If the property is write-only, use CustomWriteOnlyAccessor instead. 147 template<class C, class T> 148 class CustomAccessor : public AccessorInterface<T> { 149 public: 150 // |target| is the object on which to call the methods |getter|, |setter| 151 // and |clearer|. |setter| is allowed to be NULL, in which case we will 152 // simply reject attempts to set via the accessor. |setter| should return 153 // true if the value was changed, and false otherwise. |clearer| is allowed 154 // to be NULL (which is what happens if it is not passed to the constructor), 155 // in which case, |setter| is called is called with the default value. 156 // It is an error to pass NULL for either |target| or |getter|. CustomAccessor(C * target,T (C::* getter)(Error * error),bool (C::* setter)(const T & value,Error * error),void (C::* clearer)(Error * error))157 CustomAccessor(C* target, 158 T(C::*getter)(Error* error), 159 bool(C::*setter)(const T& value, Error* error), 160 void(C::*clearer)(Error* error)) 161 : target_(target), 162 default_value_(), 163 getter_(getter), 164 setter_(setter), 165 clearer_(clearer) { 166 DCHECK(target); 167 DCHECK(getter); // otherwise, use CustomWriteOnlyAccessor 168 if (setter_) { 169 Error e; 170 default_value_ = Get(&e); 171 } 172 } CustomAccessor(C * target,T (C::* getter)(Error * error),bool (C::* setter)(const T & value,Error * error))173 CustomAccessor(C* target, 174 T(C::*getter)(Error* error), 175 bool(C::*setter)(const T& value, Error* error)) 176 : CustomAccessor(target, getter, setter, nullptr) {} ~CustomAccessor()177 ~CustomAccessor() override {} 178 Clear(Error * error)179 void Clear(Error* error) override { 180 if (clearer_) { 181 (target_->*clearer_)(error); 182 } else { 183 Set(default_value_, error); 184 } 185 } Get(Error * error)186 T Get(Error* error) override { 187 return (target_->*getter_)(error); 188 } Set(const T & value,Error * error)189 bool Set(const T& value, Error* error) override { 190 if (setter_) { 191 return (target_->*setter_)(value, error); 192 } else { 193 error->Populate(Error::kInvalidArguments, "Property is read-only"); 194 return false; 195 } 196 } 197 198 private: 199 C* const target_; 200 // |default_value_| is non-const because it can't be initialized in 201 // the initializer list. 202 T default_value_; 203 T(C::*const getter_)(Error* error); 204 bool(C::*const setter_)(const T& value, Error* error); // NOLINT - "casting" 205 void(C::*const clearer_)(Error* error); 206 DISALLOW_COPY_AND_ASSIGN(CustomAccessor); 207 }; 208 209 // CustomWriteOnlyAccessor<> allows a custom writer method to be provided. 210 // Get returns an error automatically. Clear resets the value to a 211 // default value. 212 template<class C, class T> 213 class CustomWriteOnlyAccessor : public AccessorInterface<T> { 214 public: 215 // |target| is the object on which to call |setter| and |clearer|. 216 // 217 // |target| and |setter| must be non-NULL. |setter| should return true 218 // if the value was changed, and false otherwise. 219 // 220 // Either |clearer| or |default_value|, but not both, must be non-NULL. 221 // Whichever is non-NULL is used to clear the property. CustomWriteOnlyAccessor(C * target,bool (C::* setter)(const T & value,Error * error),void (C::* clearer)(Error * error),const T * default_value)222 CustomWriteOnlyAccessor(C* target, 223 bool(C::*setter)(const T& value, Error* error), 224 void(C::*clearer)(Error* error), 225 const T* default_value) 226 : target_(target), 227 setter_(setter), 228 clearer_(clearer), 229 default_value_() { 230 DCHECK(target); 231 DCHECK(setter); 232 DCHECK(clearer || default_value); 233 DCHECK(!clearer || !default_value); 234 if (default_value) { 235 default_value_ = *default_value; 236 } 237 } ~CustomWriteOnlyAccessor()238 ~CustomWriteOnlyAccessor() override {} 239 Clear(Error * error)240 void Clear(Error* error) override { 241 if (clearer_) { 242 (target_->*clearer_)(error); 243 } else { 244 Set(default_value_, error); 245 } 246 } Get(Error * error)247 T Get(Error* error) override { 248 error->Populate(Error::kPermissionDenied, "Property is write-only"); 249 return T(); 250 } Set(const T & value,Error * error)251 bool Set(const T& value, Error* error) override { 252 return (target_->*setter_)(value, error); 253 } 254 255 private: 256 C* const target_; 257 bool(C::*const setter_)(const T& value, Error* error); // NOLINT - "casting" 258 void(C::*const clearer_)(Error* error); 259 // |default_value_| is non-const because it can't be initialized in 260 // the initializer list. 261 T default_value_; 262 DISALLOW_COPY_AND_ASSIGN(CustomWriteOnlyAccessor); 263 }; 264 265 // CustomReadOnlyAccessor<> allows a custom getter method to be provided. 266 // Set and Clear return errors automatically. 267 template<class C, class T> 268 class CustomReadOnlyAccessor : public AccessorInterface<T> { 269 public: 270 // |target| is the object on which to call the |getter| method. 271 // |getter| is a const method. If a non-const method needs to be used, 272 // use the CustomAccessor with a NULL setter instead. CustomReadOnlyAccessor(C * target,T (C::* getter)(Error * error)const)273 CustomReadOnlyAccessor(C* target, T(C::*getter)(Error* error) const) 274 : target_(target), getter_(getter) { 275 DCHECK(target); 276 DCHECK(getter); 277 } ~CustomReadOnlyAccessor()278 ~CustomReadOnlyAccessor() override {} 279 Clear(Error * error)280 void Clear(Error* error) override { 281 error->Populate(Error::kInvalidArguments, "Property is read-only"); 282 } Get(Error * error)283 T Get(Error* error) override { 284 return (target_->*getter_)(error); 285 } Set(const T & value,Error * error)286 bool Set(const T& value, Error* error) override { 287 error->Populate(Error::kInvalidArguments, "Property is read-only"); 288 return false; 289 } 290 291 private: 292 C* const target_; 293 T(C::*const getter_)(Error* error) const; 294 DISALLOW_COPY_AND_ASSIGN(CustomReadOnlyAccessor); 295 }; 296 297 // CustomMappedAccessor<> passes an argument to the getter and setter 298 // so that a generic method can be used, for example one that accesses the 299 // property in a map. 300 template<class C, class T, class A> 301 class CustomMappedAccessor : public AccessorInterface<T> { 302 public: 303 // |target| is the object on which to call the methods |getter| and |setter|. 304 // |setter| is allowed to be NULL, in which case we will simply reject 305 // attempts to set via the accessor. |setter| should return true if the 306 // value was changed, and false otherwise. 307 // |argument| is passed to the getter and setter methods to disambiguate 308 // between different properties in |target|. 309 // It is an error to pass NULL for any of |target|, |clearer| or |getter|. CustomMappedAccessor(C * target,void (C::* clearer)(const A & argument,Error * error),T (C::* getter)(const A & argument,Error * error),bool (C::* setter)(const A & argument,const T & value,Error * error),const A & argument)310 CustomMappedAccessor(C* target, 311 void(C::*clearer)(const A& argument, Error* error), 312 T(C::*getter)(const A& argument, Error* error), 313 bool(C::*setter)(const A& argument, const T& value, 314 Error* error), 315 const A& argument) 316 : target_(target), 317 clearer_(clearer), 318 getter_(getter), 319 setter_(setter), 320 argument_(argument) { 321 DCHECK(clearer); 322 DCHECK(target); 323 DCHECK(getter); 324 } ~CustomMappedAccessor()325 ~CustomMappedAccessor() override {} 326 Clear(Error * error)327 void Clear(Error* error) override { 328 (target_->*clearer_)(argument_, error); 329 } Get(Error * error)330 T Get(Error* error) override { 331 return (target_->*getter_)(argument_, error); 332 } Set(const T & value,Error * error)333 bool Set(const T& value, Error* error) override { 334 if (setter_) { 335 return (target_->*setter_)(argument_, value, error); 336 } else { 337 error->Populate(Error::kInvalidArguments, "Property is read-only"); 338 return false; 339 } 340 } 341 342 private: 343 C* const target_; 344 void(C::*const clearer_)(const A& argument, Error* error); 345 T(C::*const getter_)(const A& argument, Error* error); 346 bool(C::*const setter_)(const A& argument, // NOLINT - "casting" 347 const T& value, Error* error); 348 A argument_; 349 DISALLOW_COPY_AND_ASSIGN(CustomMappedAccessor); 350 }; 351 352 } // namespace shill 353 354 #endif // SHILL_PROPERTY_ACCESSOR_H_ 355