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 27namespace 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.) 57template <class T> 58class PropertyAccessor : public AccessorInterface<T> { 59 public: 60 explicit PropertyAccessor(T* property) 61 : property_(property), default_value_(*property) { 62 DCHECK(property); 63 } 64 ~PropertyAccessor() override {} 65 66 void Clear(Error* error) override { Set(default_value_, error); } 67 T Get(Error* /*error*/) override { return *property_; } 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 82template <class T> 83class ConstPropertyAccessor : public AccessorInterface<T> { 84 public: 85 explicit ConstPropertyAccessor(const T* property) : property_(property) { 86 DCHECK(property); 87 } 88 ~ConstPropertyAccessor() override {} 89 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 } 95 T Get(Error* /*error*/) override { return *property_; } 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 108template <class T> 109class WriteOnlyPropertyAccessor : public AccessorInterface<T> { 110 public: 111 explicit WriteOnlyPropertyAccessor(T* property) 112 : property_(property), default_value_(*property) { 113 DCHECK(property); 114 } 115 ~WriteOnlyPropertyAccessor() override {} 116 117 void Clear(Error* error) override { Set(default_value_, error); } 118 T Get(Error* error) override { 119 error->Populate(Error::kPermissionDenied, "Property is write-only"); 120 return T(); 121 } 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. 147template<class C, class T> 148class 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|. 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 } 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) {} 177 ~CustomAccessor() override {} 178 179 void Clear(Error* error) override { 180 if (clearer_) { 181 (target_->*clearer_)(error); 182 } else { 183 Set(default_value_, error); 184 } 185 } 186 T Get(Error* error) override { 187 return (target_->*getter_)(error); 188 } 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. 212template<class C, class T> 213class 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. 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 } 238 ~CustomWriteOnlyAccessor() override {} 239 240 void Clear(Error* error) override { 241 if (clearer_) { 242 (target_->*clearer_)(error); 243 } else { 244 Set(default_value_, error); 245 } 246 } 247 T Get(Error* error) override { 248 error->Populate(Error::kPermissionDenied, "Property is write-only"); 249 return T(); 250 } 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. 267template<class C, class T> 268class 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. 273 CustomReadOnlyAccessor(C* target, T(C::*getter)(Error* error) const) 274 : target_(target), getter_(getter) { 275 DCHECK(target); 276 DCHECK(getter); 277 } 278 ~CustomReadOnlyAccessor() override {} 279 280 void Clear(Error* error) override { 281 error->Populate(Error::kInvalidArguments, "Property is read-only"); 282 } 283 T Get(Error* error) override { 284 return (target_->*getter_)(error); 285 } 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. 300template<class C, class T, class A> 301class 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|. 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 } 325 ~CustomMappedAccessor() override {} 326 327 void Clear(Error* error) override { 328 (target_->*clearer_)(argument_, error); 329 } 330 T Get(Error* error) override { 331 return (target_->*getter_)(argument_, error); 332 } 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