blob: 48b70ca95c051bb3fc7e9bf4e956d4f6bdd64bce [file] [log] [blame]
mukesh agrawal292dc0f2012-01-26 18:02:46 -08001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Chris Masone3bd3c8c2011-06-13 08:20:26 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Ben Chanc45688b2014-07-02 23:50:45 -07005#ifndef SHILL_PROPERTY_ACCESSOR_H_
6#define SHILL_PROPERTY_ACCESSOR_H_
Chris Masone3bd3c8c2011-06-13 08:20:26 -07007
Ben Chancc67c522014-09-03 07:19:18 -07008#include <base/macros.h>
Gaurav Shah1b7a6162011-11-09 11:41:01 -08009#include <gtest/gtest_prod.h> // for FRIEND_TEST.
Chris Masone3bd3c8c2011-06-13 08:20:26 -070010
11#include "shill/accessor_interface.h"
mukesh agrawalffa3d042011-10-06 15:26:10 -070012#include "shill/error.h"
Christopher Wileyd7783522012-08-10 14:21:47 -070013#include "shill/logging.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070014
15namespace shill {
16
17// Templated implementations of AccessorInterface<>.
mukesh agrawal292dc0f2012-01-26 18:02:46 -080018//
19// PropertyAccessor<>, ConstPropertyAccessor<>, and
20// WriteOnlyPropertyAccessor<> provide R/W, R/O, and W/O access
21// (respectively) to the value pointed to by |property|.
22//
23// This allows a class to easily map strings to member variables, so that
Chris Masone3bd3c8c2011-06-13 08:20:26 -070024// pieces of state stored in the class can be queried or updated by name.
25//
26// bool foo = true;
27// map<string, BoolAccessor> accessors;
28// accessors["foo"] = BoolAccessor(new PropertyAccessor<bool>(&foo));
29// bool new_foo = accessors["foo"]->Get(); // new_foo == true
30// accessors["foo"]->Set(false); // returns true, because setting is allowed.
31// // foo == false, new_foo == true
32// new_foo = accessors["foo"]->Get(); // new_foo == false
mukesh agrawal292dc0f2012-01-26 18:02:46 -080033// // Clear resets |foo| to its value when the PropertyAccessor was created.
34// accessors["foo"]->Clear(); // foo == true
mukesh agrawalbebf1b82013-04-23 15:06:33 -070035//
36// Generic accessors that provide write capability will check that the
37// new value differs from the present one. If the old and new values
38// are the same, the setter will not invoke the assignment operator, and
39// will return false.
40//
41// Custom accessors are responsible for handling set-to-same-value
42// themselves. It is not possible to handle that here, because some
43// custom getters return default values, rather than the actual
44// value. (I'm looking at you, WiFi::GetBgscanMethod.)
Chris Masone3bd3c8c2011-06-13 08:20:26 -070045template <class T>
46class PropertyAccessor : public AccessorInterface<T> {
47 public:
Paul Stewart1a212a62015-06-16 13:13:10 -070048 explicit PropertyAccessor(T* property)
mukesh agrawal292dc0f2012-01-26 18:02:46 -080049 : property_(property), default_value_(*property) {
Chris Masone3bd3c8c2011-06-13 08:20:26 -070050 DCHECK(property);
51 }
Ben Chan5ea763b2014-08-13 11:07:54 -070052 ~PropertyAccessor() override {}
Chris Masone3bd3c8c2011-06-13 08:20:26 -070053
Paul Stewart1a212a62015-06-16 13:13:10 -070054 void Clear(Error* error) override { Set(default_value_, error); }
55 T Get(Error* /*error*/) override { return *property_; }
56 bool Set(const T& value, Error* /*error*/) override {
mukesh agrawalbebf1b82013-04-23 15:06:33 -070057 if (*property_ == value) {
58 return false;
59 }
Chris Masone3bd3c8c2011-06-13 08:20:26 -070060 *property_ = value;
mukesh agrawalbebf1b82013-04-23 15:06:33 -070061 return true;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070062 }
63
64 private:
Paul Stewart1a212a62015-06-16 13:13:10 -070065 T* const property_;
mukesh agrawal292dc0f2012-01-26 18:02:46 -080066 const T default_value_;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070067 DISALLOW_COPY_AND_ASSIGN(PropertyAccessor);
68};
69
70template <class T>
71class ConstPropertyAccessor : public AccessorInterface<T> {
72 public:
Paul Stewart1a212a62015-06-16 13:13:10 -070073 explicit ConstPropertyAccessor(const T* property) : property_(property) {
Chris Masone3bd3c8c2011-06-13 08:20:26 -070074 DCHECK(property);
75 }
Ben Chan5ea763b2014-08-13 11:07:54 -070076 ~ConstPropertyAccessor() override {}
Chris Masone3bd3c8c2011-06-13 08:20:26 -070077
Paul Stewart1a212a62015-06-16 13:13:10 -070078 void Clear(Error* error) override {
mukesh agrawal292dc0f2012-01-26 18:02:46 -080079 // TODO(quiche): check if this is the right error.
80 // (maybe Error::kInvalidProperty instead?)
81 error->Populate(Error::kInvalidArguments, "Property is read-only");
82 }
Paul Stewart1a212a62015-06-16 13:13:10 -070083 T Get(Error* /*error*/) override { return *property_; }
84 bool Set(const T& /*value*/, Error* error) override {
mukesh agrawalffa3d042011-10-06 15:26:10 -070085 // TODO(quiche): check if this is the right error.
86 // (maybe Error::kPermissionDenied instead?)
87 error->Populate(Error::kInvalidArguments, "Property is read-only");
mukesh agrawalbebf1b82013-04-23 15:06:33 -070088 return false;
mukesh agrawalffa3d042011-10-06 15:26:10 -070089 }
Chris Masone3bd3c8c2011-06-13 08:20:26 -070090
91 private:
Paul Stewart1a212a62015-06-16 13:13:10 -070092 const T* const property_;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070093 DISALLOW_COPY_AND_ASSIGN(ConstPropertyAccessor);
94};
95
Gaurav Shah1b7a6162011-11-09 11:41:01 -080096template <class T>
97class WriteOnlyPropertyAccessor : public AccessorInterface<T> {
98 public:
Paul Stewart1a212a62015-06-16 13:13:10 -070099 explicit WriteOnlyPropertyAccessor(T* property)
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800100 : property_(property), default_value_(*property) {
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800101 DCHECK(property);
102 }
Ben Chan5ea763b2014-08-13 11:07:54 -0700103 ~WriteOnlyPropertyAccessor() override {}
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800104
Paul Stewart1a212a62015-06-16 13:13:10 -0700105 void Clear(Error* error) override { Set(default_value_, error); }
106 T Get(Error* error) override {
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800107 error->Populate(Error::kPermissionDenied, "Property is write-only");
108 return T();
109 }
Paul Stewart1a212a62015-06-16 13:13:10 -0700110 bool Set(const T& value, Error* /*error*/) override {
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700111 if (*property_ == value) {
112 return false;
113 }
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800114 *property_ = value;
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700115 return true;
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800116 }
117
118 private:
119 FRIEND_TEST(PropertyAccessorTest, SignedIntCorrectness);
120 FRIEND_TEST(PropertyAccessorTest, UnsignedIntCorrectness);
121 FRIEND_TEST(PropertyAccessorTest, StringCorrectness);
122
Paul Stewart1a212a62015-06-16 13:13:10 -0700123 T* const property_;
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800124 const T default_value_;
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800125 DISALLOW_COPY_AND_ASSIGN(WriteOnlyPropertyAccessor);
126};
127
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700128// CustomAccessor<> allows custom getter and setter methods to be provided.
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800129// Thus, if the state to be returned is to be derived on-demand, or if
130// setting the property requires validation, we can still fit it into the
131// AccessorInterface<> framework.
132//
133// If the property is write-only, use CustomWriteOnlyAccessor instead.
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700134template<class C, class T>
135class CustomAccessor : public AccessorInterface<T> {
136 public:
Paul Stewart985d7d52013-10-16 13:46:09 -0700137 // |target| is the object on which to call the methods |getter|, |setter|
138 // and |clearer|. |setter| is allowed to be NULL, in which case we will
139 // simply reject attempts to set via the accessor. |setter| should return
140 // true if the value was changed, and false otherwise. |clearer| is allowed
141 // to be NULL (which is what happens if it is not passed to the constructor),
142 // in which case, |setter| is called is called with the default value.
143 // It is an error to pass NULL for either |target| or |getter|.
Paul Stewart1a212a62015-06-16 13:13:10 -0700144 CustomAccessor(C* target,
145 T(C::*getter)(Error* error),
146 bool(C::*setter)(const T& value, Error* error),
147 void(C::*clearer)(Error* error))
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700148 : target_(target),
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800149 default_value_(),
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700150 getter_(getter),
Paul Stewart985d7d52013-10-16 13:46:09 -0700151 setter_(setter),
152 clearer_(clearer) {
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700153 DCHECK(target);
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800154 DCHECK(getter); // otherwise, use CustomWriteOnlyAccessor
155 if (setter_) {
156 Error e;
157 default_value_ = Get(&e);
158 }
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700159 }
Paul Stewart1a212a62015-06-16 13:13:10 -0700160 CustomAccessor(C* target,
161 T(C::*getter)(Error* error),
162 bool(C::*setter)(const T& value, Error* error))
Ben Chancc225ef2014-09-30 13:26:51 -0700163 : CustomAccessor(target, getter, setter, nullptr) {}
Ben Chan5ea763b2014-08-13 11:07:54 -0700164 ~CustomAccessor() override {}
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700165
Paul Stewart1a212a62015-06-16 13:13:10 -0700166 void Clear(Error* error) override {
Paul Stewart985d7d52013-10-16 13:46:09 -0700167 if (clearer_) {
168 (target_->*clearer_)(error);
169 } else {
170 Set(default_value_, error);
171 }
172 }
Paul Stewart1a212a62015-06-16 13:13:10 -0700173 T Get(Error* error) override {
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800174 return (target_->*getter_)(error);
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800175 }
Paul Stewart1a212a62015-06-16 13:13:10 -0700176 bool Set(const T& value, Error* error) override {
mukesh agrawalffa3d042011-10-06 15:26:10 -0700177 if (setter_) {
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700178 return (target_->*setter_)(value, error);
mukesh agrawalffa3d042011-10-06 15:26:10 -0700179 } else {
180 error->Populate(Error::kInvalidArguments, "Property is read-only");
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700181 return false;
mukesh agrawalffa3d042011-10-06 15:26:10 -0700182 }
183 }
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700184
185 private:
Paul Stewart1a212a62015-06-16 13:13:10 -0700186 C* const target_;
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800187 // |default_value_| is non-const because it can't be initialized in
188 // the initializer list.
189 T default_value_;
Paul Stewart1a212a62015-06-16 13:13:10 -0700190 T(C::*const getter_)(Error* error);
191 bool(C::*const setter_)(const T& value, Error* error); // NOLINT - "casting"
192 void(C::*const clearer_)(Error* error);
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700193 DISALLOW_COPY_AND_ASSIGN(CustomAccessor);
194};
195
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800196// CustomWriteOnlyAccessor<> allows a custom writer method to be provided.
197// Get returns an error automatically. Clear resets the value to a
198// default value.
199template<class C, class T>
200class CustomWriteOnlyAccessor : public AccessorInterface<T> {
201 public:
202 // |target| is the object on which to call |setter| and |clearer|.
203 //
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700204 // |target| and |setter| must be non-NULL. |setter| should return true
205 // if the value was changed, and false otherwise.
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800206 //
207 // Either |clearer| or |default_value|, but not both, must be non-NULL.
208 // Whichever is non-NULL is used to clear the property.
Paul Stewart1a212a62015-06-16 13:13:10 -0700209 CustomWriteOnlyAccessor(C* target,
210 bool(C::*setter)(const T& value, Error* error),
211 void(C::*clearer)(Error* error),
212 const T* default_value)
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800213 : target_(target),
214 setter_(setter),
215 clearer_(clearer),
216 default_value_() {
217 DCHECK(target);
218 DCHECK(setter);
219 DCHECK(clearer || default_value);
220 DCHECK(!clearer || !default_value);
221 if (default_value) {
222 default_value_ = *default_value;
223 }
224 }
Ben Chan5ea763b2014-08-13 11:07:54 -0700225 ~CustomWriteOnlyAccessor() override {}
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800226
Paul Stewart1a212a62015-06-16 13:13:10 -0700227 void Clear(Error* error) override {
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800228 if (clearer_) {
229 (target_->*clearer_)(error);
230 } else {
231 Set(default_value_, error);
232 }
233 }
Paul Stewart1a212a62015-06-16 13:13:10 -0700234 T Get(Error* error) override {
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800235 error->Populate(Error::kPermissionDenied, "Property is write-only");
236 return T();
237 }
Paul Stewart1a212a62015-06-16 13:13:10 -0700238 bool Set(const T& value, Error* error) override {
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700239 return (target_->*setter_)(value, error);
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800240 }
241
242 private:
Paul Stewart1a212a62015-06-16 13:13:10 -0700243 C* const target_;
244 bool(C::*const setter_)(const T& value, Error* error); // NOLINT - "casting"
245 void(C::*const clearer_)(Error* error);
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800246 // |default_value_| is non-const because it can't be initialized in
247 // the initializer list.
248 T default_value_;
249 DISALLOW_COPY_AND_ASSIGN(CustomWriteOnlyAccessor);
250};
251
Paul Stewart1cf7eb82013-12-03 19:34:36 -0800252// CustomReadOnlyAccessor<> allows a custom getter method to be provided.
253// Set and Clear return errors automatically.
254template<class C, class T>
255class CustomReadOnlyAccessor : public AccessorInterface<T> {
256 public:
257 // |target| is the object on which to call the |getter| method.
258 // |getter| is a const method. If a non-const method needs to be used,
259 // use the CustomAccessor with a NULL setter instead.
Paul Stewart1a212a62015-06-16 13:13:10 -0700260 CustomReadOnlyAccessor(C* target, T(C::*getter)(Error* error) const)
Paul Stewart1cf7eb82013-12-03 19:34:36 -0800261 : target_(target), getter_(getter) {
262 DCHECK(target);
263 DCHECK(getter);
264 }
Ben Chan5ea763b2014-08-13 11:07:54 -0700265 ~CustomReadOnlyAccessor() override {}
Paul Stewart1cf7eb82013-12-03 19:34:36 -0800266
Paul Stewart1a212a62015-06-16 13:13:10 -0700267 void Clear(Error* error) override {
Paul Stewart1cf7eb82013-12-03 19:34:36 -0800268 error->Populate(Error::kInvalidArguments, "Property is read-only");
269 }
Paul Stewart1a212a62015-06-16 13:13:10 -0700270 T Get(Error* error) override {
Paul Stewart1cf7eb82013-12-03 19:34:36 -0800271 return (target_->*getter_)(error);
272 }
Paul Stewart1a212a62015-06-16 13:13:10 -0700273 bool Set(const T& value, Error* error) override {
Paul Stewart1cf7eb82013-12-03 19:34:36 -0800274 error->Populate(Error::kInvalidArguments, "Property is read-only");
275 return false;
276 }
277
278 private:
Paul Stewart1a212a62015-06-16 13:13:10 -0700279 C* const target_;
280 T(C::*const getter_)(Error* error) const;
Paul Stewart1cf7eb82013-12-03 19:34:36 -0800281 DISALLOW_COPY_AND_ASSIGN(CustomReadOnlyAccessor);
282};
283
Paul Stewarta61593e2012-03-23 13:06:21 -0700284// CustomMappedAccessor<> passes an argument to the getter and setter
285// so that a generic method can be used, for example one that accesses the
286// property in a map.
287template<class C, class T, class A>
288class CustomMappedAccessor : public AccessorInterface<T> {
289 public:
290 // |target| is the object on which to call the methods |getter| and |setter|.
291 // |setter| is allowed to be NULL, in which case we will simply reject
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700292 // attempts to set via the accessor. |setter| should return true if the
293 // value was changed, and false otherwise.
Paul Stewarta61593e2012-03-23 13:06:21 -0700294 // |argument| is passed to the getter and setter methods to disambiguate
295 // between different properties in |target|.
296 // It is an error to pass NULL for any of |target|, |clearer| or |getter|.
Paul Stewart1a212a62015-06-16 13:13:10 -0700297 CustomMappedAccessor(C* target,
298 void(C::*clearer)(const A& argument, Error* error),
299 T(C::*getter)(const A& argument, Error* error),
300 bool(C::*setter)(const A& argument, const T& value,
301 Error* error),
302 const A& argument)
Paul Stewarta61593e2012-03-23 13:06:21 -0700303 : target_(target),
304 clearer_(clearer),
305 getter_(getter),
306 setter_(setter),
307 argument_(argument) {
308 DCHECK(clearer);
309 DCHECK(target);
310 DCHECK(getter);
311 }
Ben Chan5ea763b2014-08-13 11:07:54 -0700312 ~CustomMappedAccessor() override {}
Paul Stewarta61593e2012-03-23 13:06:21 -0700313
Paul Stewart1a212a62015-06-16 13:13:10 -0700314 void Clear(Error* error) override {
Paul Stewarta61593e2012-03-23 13:06:21 -0700315 (target_->*clearer_)(argument_, error);
316 }
Paul Stewart1a212a62015-06-16 13:13:10 -0700317 T Get(Error* error) override {
Paul Stewarta61593e2012-03-23 13:06:21 -0700318 return (target_->*getter_)(argument_, error);
319 }
Paul Stewart1a212a62015-06-16 13:13:10 -0700320 bool Set(const T& value, Error* error) override {
Paul Stewarta61593e2012-03-23 13:06:21 -0700321 if (setter_) {
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700322 return (target_->*setter_)(argument_, value, error);
Paul Stewarta61593e2012-03-23 13:06:21 -0700323 } else {
324 error->Populate(Error::kInvalidArguments, "Property is read-only");
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700325 return false;
Paul Stewarta61593e2012-03-23 13:06:21 -0700326 }
327 }
328
329 private:
Paul Stewart1a212a62015-06-16 13:13:10 -0700330 C* const target_;
331 void(C::*const clearer_)(const A& argument, Error* error);
332 T(C::*const getter_)(const A& argument, Error* error);
333 bool(C::*const setter_)(const A& argument, // NOLINT - "casting"
334 const T& value, Error* error);
Paul Stewarta61593e2012-03-23 13:06:21 -0700335 A argument_;
336 DISALLOW_COPY_AND_ASSIGN(CustomMappedAccessor);
337};
338
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700339} // namespace shill
340
Ben Chanc45688b2014-07-02 23:50:45 -0700341#endif // SHILL_PROPERTY_ACCESSOR_H_