blob: f4a9d521034230e2fe10ffecce91d77ace95ff2d [file] [log] [blame]
Peter Qiuc0beca52015-09-03 11:25:46 -07001//
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//
Chris Masone3bd3c8c2011-06-13 08:20:26 -070016
Ben Chanc45688b2014-07-02 23:50:45 -070017#ifndef SHILL_PROPERTY_ACCESSOR_H_
18#define SHILL_PROPERTY_ACCESSOR_H_
Chris Masone3bd3c8c2011-06-13 08:20:26 -070019
Ben Chancc67c522014-09-03 07:19:18 -070020#include <base/macros.h>
Gaurav Shah1b7a6162011-11-09 11:41:01 -080021#include <gtest/gtest_prod.h> // for FRIEND_TEST.
Chris Masone3bd3c8c2011-06-13 08:20:26 -070022
23#include "shill/accessor_interface.h"
mukesh agrawalffa3d042011-10-06 15:26:10 -070024#include "shill/error.h"
Christopher Wileyd7783522012-08-10 14:21:47 -070025#include "shill/logging.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070026
27namespace shill {
28
29// Templated implementations of AccessorInterface<>.
mukesh agrawal292dc0f2012-01-26 18:02:46 -080030//
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
Chris Masone3bd3c8c2011-06-13 08:20:26 -070036// 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
mukesh agrawal292dc0f2012-01-26 18:02:46 -080045// // Clear resets |foo| to its value when the PropertyAccessor was created.
46// accessors["foo"]->Clear(); // foo == true
mukesh agrawalbebf1b82013-04-23 15:06:33 -070047//
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.)
Chris Masone3bd3c8c2011-06-13 08:20:26 -070057template <class T>
58class PropertyAccessor : public AccessorInterface<T> {
59 public:
Paul Stewart1a212a62015-06-16 13:13:10 -070060 explicit PropertyAccessor(T* property)
mukesh agrawal292dc0f2012-01-26 18:02:46 -080061 : property_(property), default_value_(*property) {
Chris Masone3bd3c8c2011-06-13 08:20:26 -070062 DCHECK(property);
63 }
Ben Chan5ea763b2014-08-13 11:07:54 -070064 ~PropertyAccessor() override {}
Chris Masone3bd3c8c2011-06-13 08:20:26 -070065
Paul Stewart1a212a62015-06-16 13:13:10 -070066 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 {
mukesh agrawalbebf1b82013-04-23 15:06:33 -070069 if (*property_ == value) {
70 return false;
71 }
Chris Masone3bd3c8c2011-06-13 08:20:26 -070072 *property_ = value;
mukesh agrawalbebf1b82013-04-23 15:06:33 -070073 return true;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070074 }
75
76 private:
Paul Stewart1a212a62015-06-16 13:13:10 -070077 T* const property_;
mukesh agrawal292dc0f2012-01-26 18:02:46 -080078 const T default_value_;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070079 DISALLOW_COPY_AND_ASSIGN(PropertyAccessor);
80};
81
82template <class T>
83class ConstPropertyAccessor : public AccessorInterface<T> {
84 public:
Paul Stewart1a212a62015-06-16 13:13:10 -070085 explicit ConstPropertyAccessor(const T* property) : property_(property) {
Chris Masone3bd3c8c2011-06-13 08:20:26 -070086 DCHECK(property);
87 }
Ben Chan5ea763b2014-08-13 11:07:54 -070088 ~ConstPropertyAccessor() override {}
Chris Masone3bd3c8c2011-06-13 08:20:26 -070089
Paul Stewart1a212a62015-06-16 13:13:10 -070090 void Clear(Error* error) override {
mukesh agrawal292dc0f2012-01-26 18:02:46 -080091 // TODO(quiche): check if this is the right error.
92 // (maybe Error::kInvalidProperty instead?)
93 error->Populate(Error::kInvalidArguments, "Property is read-only");
94 }
Paul Stewart1a212a62015-06-16 13:13:10 -070095 T Get(Error* /*error*/) override { return *property_; }
96 bool Set(const T& /*value*/, Error* error) override {
mukesh agrawalffa3d042011-10-06 15:26:10 -070097 // TODO(quiche): check if this is the right error.
98 // (maybe Error::kPermissionDenied instead?)
99 error->Populate(Error::kInvalidArguments, "Property is read-only");
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700100 return false;
mukesh agrawalffa3d042011-10-06 15:26:10 -0700101 }
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700102
103 private:
Paul Stewart1a212a62015-06-16 13:13:10 -0700104 const T* const property_;
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700105 DISALLOW_COPY_AND_ASSIGN(ConstPropertyAccessor);
106};
107
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800108template <class T>
109class WriteOnlyPropertyAccessor : public AccessorInterface<T> {
110 public:
Paul Stewart1a212a62015-06-16 13:13:10 -0700111 explicit WriteOnlyPropertyAccessor(T* property)
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800112 : property_(property), default_value_(*property) {
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800113 DCHECK(property);
114 }
Ben Chan5ea763b2014-08-13 11:07:54 -0700115 ~WriteOnlyPropertyAccessor() override {}
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800116
Paul Stewart1a212a62015-06-16 13:13:10 -0700117 void Clear(Error* error) override { Set(default_value_, error); }
118 T Get(Error* error) override {
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800119 error->Populate(Error::kPermissionDenied, "Property is write-only");
120 return T();
121 }
Paul Stewart1a212a62015-06-16 13:13:10 -0700122 bool Set(const T& value, Error* /*error*/) override {
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700123 if (*property_ == value) {
124 return false;
125 }
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800126 *property_ = value;
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700127 return true;
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800128 }
129
130 private:
131 FRIEND_TEST(PropertyAccessorTest, SignedIntCorrectness);
132 FRIEND_TEST(PropertyAccessorTest, UnsignedIntCorrectness);
133 FRIEND_TEST(PropertyAccessorTest, StringCorrectness);
Victor Dodon1ee315f2016-01-05 15:26:22 -0800134 FRIEND_TEST(PropertyAccessorTest, ByteArrayCorrectness);
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800135
Paul Stewart1a212a62015-06-16 13:13:10 -0700136 T* const property_;
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800137 const T default_value_;
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800138 DISALLOW_COPY_AND_ASSIGN(WriteOnlyPropertyAccessor);
139};
140
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700141// CustomAccessor<> allows custom getter and setter methods to be provided.
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800142// 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.
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700147template<class C, class T>
148class CustomAccessor : public AccessorInterface<T> {
149 public:
Paul Stewart985d7d52013-10-16 13:46:09 -0700150 // |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|.
Paul Stewart1a212a62015-06-16 13:13:10 -0700157 CustomAccessor(C* target,
158 T(C::*getter)(Error* error),
159 bool(C::*setter)(const T& value, Error* error),
160 void(C::*clearer)(Error* error))
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700161 : target_(target),
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800162 default_value_(),
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700163 getter_(getter),
Paul Stewart985d7d52013-10-16 13:46:09 -0700164 setter_(setter),
165 clearer_(clearer) {
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700166 DCHECK(target);
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800167 DCHECK(getter); // otherwise, use CustomWriteOnlyAccessor
168 if (setter_) {
169 Error e;
170 default_value_ = Get(&e);
171 }
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700172 }
Paul Stewart1a212a62015-06-16 13:13:10 -0700173 CustomAccessor(C* target,
174 T(C::*getter)(Error* error),
175 bool(C::*setter)(const T& value, Error* error))
Ben Chancc225ef2014-09-30 13:26:51 -0700176 : CustomAccessor(target, getter, setter, nullptr) {}
Ben Chan5ea763b2014-08-13 11:07:54 -0700177 ~CustomAccessor() override {}
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700178
Paul Stewart1a212a62015-06-16 13:13:10 -0700179 void Clear(Error* error) override {
Paul Stewart985d7d52013-10-16 13:46:09 -0700180 if (clearer_) {
181 (target_->*clearer_)(error);
182 } else {
183 Set(default_value_, error);
184 }
185 }
Paul Stewart1a212a62015-06-16 13:13:10 -0700186 T Get(Error* error) override {
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800187 return (target_->*getter_)(error);
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800188 }
Paul Stewart1a212a62015-06-16 13:13:10 -0700189 bool Set(const T& value, Error* error) override {
mukesh agrawalffa3d042011-10-06 15:26:10 -0700190 if (setter_) {
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700191 return (target_->*setter_)(value, error);
mukesh agrawalffa3d042011-10-06 15:26:10 -0700192 } else {
193 error->Populate(Error::kInvalidArguments, "Property is read-only");
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700194 return false;
mukesh agrawalffa3d042011-10-06 15:26:10 -0700195 }
196 }
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700197
198 private:
Paul Stewart1a212a62015-06-16 13:13:10 -0700199 C* const target_;
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800200 // |default_value_| is non-const because it can't be initialized in
201 // the initializer list.
202 T default_value_;
Paul Stewart1a212a62015-06-16 13:13:10 -0700203 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);
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700206 DISALLOW_COPY_AND_ASSIGN(CustomAccessor);
207};
208
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800209// 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 //
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700217 // |target| and |setter| must be non-NULL. |setter| should return true
218 // if the value was changed, and false otherwise.
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800219 //
220 // Either |clearer| or |default_value|, but not both, must be non-NULL.
221 // Whichever is non-NULL is used to clear the property.
Paul Stewart1a212a62015-06-16 13:13:10 -0700222 CustomWriteOnlyAccessor(C* target,
223 bool(C::*setter)(const T& value, Error* error),
224 void(C::*clearer)(Error* error),
225 const T* default_value)
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800226 : 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 }
Ben Chan5ea763b2014-08-13 11:07:54 -0700238 ~CustomWriteOnlyAccessor() override {}
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800239
Paul Stewart1a212a62015-06-16 13:13:10 -0700240 void Clear(Error* error) override {
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800241 if (clearer_) {
242 (target_->*clearer_)(error);
243 } else {
244 Set(default_value_, error);
245 }
246 }
Paul Stewart1a212a62015-06-16 13:13:10 -0700247 T Get(Error* error) override {
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800248 error->Populate(Error::kPermissionDenied, "Property is write-only");
249 return T();
250 }
Paul Stewart1a212a62015-06-16 13:13:10 -0700251 bool Set(const T& value, Error* error) override {
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700252 return (target_->*setter_)(value, error);
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800253 }
254
255 private:
Paul Stewart1a212a62015-06-16 13:13:10 -0700256 C* const target_;
257 bool(C::*const setter_)(const T& value, Error* error); // NOLINT - "casting"
258 void(C::*const clearer_)(Error* error);
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800259 // |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
Paul Stewart1cf7eb82013-12-03 19:34:36 -0800265// 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.
Paul Stewart1a212a62015-06-16 13:13:10 -0700273 CustomReadOnlyAccessor(C* target, T(C::*getter)(Error* error) const)
Paul Stewart1cf7eb82013-12-03 19:34:36 -0800274 : target_(target), getter_(getter) {
275 DCHECK(target);
276 DCHECK(getter);
277 }
Ben Chan5ea763b2014-08-13 11:07:54 -0700278 ~CustomReadOnlyAccessor() override {}
Paul Stewart1cf7eb82013-12-03 19:34:36 -0800279
Paul Stewart1a212a62015-06-16 13:13:10 -0700280 void Clear(Error* error) override {
Paul Stewart1cf7eb82013-12-03 19:34:36 -0800281 error->Populate(Error::kInvalidArguments, "Property is read-only");
282 }
Paul Stewart1a212a62015-06-16 13:13:10 -0700283 T Get(Error* error) override {
Paul Stewart1cf7eb82013-12-03 19:34:36 -0800284 return (target_->*getter_)(error);
285 }
Paul Stewart1a212a62015-06-16 13:13:10 -0700286 bool Set(const T& value, Error* error) override {
Paul Stewart1cf7eb82013-12-03 19:34:36 -0800287 error->Populate(Error::kInvalidArguments, "Property is read-only");
288 return false;
289 }
290
291 private:
Paul Stewart1a212a62015-06-16 13:13:10 -0700292 C* const target_;
293 T(C::*const getter_)(Error* error) const;
Paul Stewart1cf7eb82013-12-03 19:34:36 -0800294 DISALLOW_COPY_AND_ASSIGN(CustomReadOnlyAccessor);
295};
296
Paul Stewarta61593e2012-03-23 13:06:21 -0700297// 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
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700305 // attempts to set via the accessor. |setter| should return true if the
306 // value was changed, and false otherwise.
Paul Stewarta61593e2012-03-23 13:06:21 -0700307 // |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|.
Paul Stewart1a212a62015-06-16 13:13:10 -0700310 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)
Paul Stewarta61593e2012-03-23 13:06:21 -0700316 : target_(target),
317 clearer_(clearer),
318 getter_(getter),
319 setter_(setter),
320 argument_(argument) {
321 DCHECK(clearer);
322 DCHECK(target);
323 DCHECK(getter);
324 }
Ben Chan5ea763b2014-08-13 11:07:54 -0700325 ~CustomMappedAccessor() override {}
Paul Stewarta61593e2012-03-23 13:06:21 -0700326
Paul Stewart1a212a62015-06-16 13:13:10 -0700327 void Clear(Error* error) override {
Paul Stewarta61593e2012-03-23 13:06:21 -0700328 (target_->*clearer_)(argument_, error);
329 }
Paul Stewart1a212a62015-06-16 13:13:10 -0700330 T Get(Error* error) override {
Paul Stewarta61593e2012-03-23 13:06:21 -0700331 return (target_->*getter_)(argument_, error);
332 }
Paul Stewart1a212a62015-06-16 13:13:10 -0700333 bool Set(const T& value, Error* error) override {
Paul Stewarta61593e2012-03-23 13:06:21 -0700334 if (setter_) {
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700335 return (target_->*setter_)(argument_, value, error);
Paul Stewarta61593e2012-03-23 13:06:21 -0700336 } else {
337 error->Populate(Error::kInvalidArguments, "Property is read-only");
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700338 return false;
Paul Stewarta61593e2012-03-23 13:06:21 -0700339 }
340 }
341
342 private:
Paul Stewart1a212a62015-06-16 13:13:10 -0700343 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);
Paul Stewarta61593e2012-03-23 13:06:21 -0700348 A argument_;
349 DISALLOW_COPY_AND_ASSIGN(CustomMappedAccessor);
350};
351
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700352} // namespace shill
353
Ben Chanc45688b2014-07-02 23:50:45 -0700354#endif // SHILL_PROPERTY_ACCESSOR_H_