blob: fb0d6dfac3e5bfd1cd59448ebee67156205f4ddd [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
5#ifndef SHILL_PROPERTY_ACCESSOR_
6#define SHILL_PROPERTY_ACCESSOR_
7
8#include <base/basictypes.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:
mukesh agrawal292dc0f2012-01-26 18:02:46 -080048 explicit PropertyAccessor(T *property)
49 : property_(property), default_value_(*property) {
Chris Masone3bd3c8c2011-06-13 08:20:26 -070050 DCHECK(property);
51 }
52 virtual ~PropertyAccessor() {}
53
mukesh agrawal292dc0f2012-01-26 18:02:46 -080054 void Clear(Error *error) { Set(default_value_, error); }
Gaurav Shah1b7a6162011-11-09 11:41:01 -080055 T Get(Error */*error*/) { return *property_; }
mukesh agrawalbebf1b82013-04-23 15:06:33 -070056 bool Set(const T &value, Error */*error*/) {
57 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:
65 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:
73 explicit ConstPropertyAccessor(const T *property) : property_(property) {
74 DCHECK(property);
75 }
76 virtual ~ConstPropertyAccessor() {}
77
mukesh agrawal292dc0f2012-01-26 18:02:46 -080078 void Clear(Error *error) {
79 // TODO(quiche): check if this is the right error.
80 // (maybe Error::kInvalidProperty instead?)
81 error->Populate(Error::kInvalidArguments, "Property is read-only");
82 }
Gaurav Shah1b7a6162011-11-09 11:41:01 -080083 T Get(Error */*error*/) { return *property_; }
mukesh agrawalbebf1b82013-04-23 15:06:33 -070084 bool Set(const T &/*value*/, Error *error) {
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:
92 const T * const property_;
93 DISALLOW_COPY_AND_ASSIGN(ConstPropertyAccessor);
94};
95
Gaurav Shah1b7a6162011-11-09 11:41:01 -080096template <class T>
97class WriteOnlyPropertyAccessor : public AccessorInterface<T> {
98 public:
mukesh agrawal292dc0f2012-01-26 18:02:46 -080099 explicit WriteOnlyPropertyAccessor(T *property)
100 : property_(property), default_value_(*property) {
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800101 DCHECK(property);
102 }
103 virtual ~WriteOnlyPropertyAccessor() {}
104
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800105 void Clear(Error *error) { Set(default_value_, error); }
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800106 T Get(Error *error) {
107 error->Populate(Error::kPermissionDenied, "Property is write-only");
108 return T();
109 }
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700110 bool Set(const T &value, Error */*error*/) {
111 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
123 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:
137 // |target| is the object on which to call the methods |getter| and |setter|
138 // |setter| is allowed to be NULL, in which case we will simply reject
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700139 // attempts to set via the accessor. |setter| should return true if the
140 // value was changed, and false otherwise.
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700141 // It is an error to pass NULL for either of the other two arguments.
mukesh agrawalffa3d042011-10-06 15:26:10 -0700142 CustomAccessor(C *target,
Hristo Stefanoved2c28c2011-11-29 15:37:30 -0800143 T(C::*getter)(Error *error),
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700144 bool(C::*setter)(const T &value, Error *error))
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700145 : target_(target),
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800146 default_value_(),
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700147 getter_(getter),
148 setter_(setter) {
149 DCHECK(target);
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800150 DCHECK(getter); // otherwise, use CustomWriteOnlyAccessor
151 if (setter_) {
152 Error e;
153 default_value_ = Get(&e);
154 }
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700155 }
156 virtual ~CustomAccessor() {}
157
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800158 void Clear(Error *error) { Set(default_value_, error); }
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800159 T Get(Error *error) {
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800160 return (target_->*getter_)(error);
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800161 }
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700162 bool Set(const T &value, Error *error) {
mukesh agrawalffa3d042011-10-06 15:26:10 -0700163 if (setter_) {
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700164 return (target_->*setter_)(value, error);
mukesh agrawalffa3d042011-10-06 15:26:10 -0700165 } else {
166 error->Populate(Error::kInvalidArguments, "Property is read-only");
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700167 return false;
mukesh agrawalffa3d042011-10-06 15:26:10 -0700168 }
169 }
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700170
171 private:
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800172 C *const target_;
173 // |default_value_| is non-const because it can't be initialized in
174 // the initializer list.
175 T default_value_;
176 T(C::*const getter_)(Error *error);
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700177 bool(C::*const setter_)(const T &value, Error *error);
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700178 DISALLOW_COPY_AND_ASSIGN(CustomAccessor);
179};
180
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800181// CustomWriteOnlyAccessor<> allows a custom writer method to be provided.
182// Get returns an error automatically. Clear resets the value to a
183// default value.
184template<class C, class T>
185class CustomWriteOnlyAccessor : public AccessorInterface<T> {
186 public:
187 // |target| is the object on which to call |setter| and |clearer|.
188 //
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700189 // |target| and |setter| must be non-NULL. |setter| should return true
190 // if the value was changed, and false otherwise.
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800191 //
192 // Either |clearer| or |default_value|, but not both, must be non-NULL.
193 // Whichever is non-NULL is used to clear the property.
194 CustomWriteOnlyAccessor(C *target,
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700195 bool(C::*setter)(const T &value, Error *error),
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800196 void(C::*clearer)(Error *error),
197 const T *default_value)
198 : target_(target),
199 setter_(setter),
200 clearer_(clearer),
201 default_value_() {
202 DCHECK(target);
203 DCHECK(setter);
204 DCHECK(clearer || default_value);
205 DCHECK(!clearer || !default_value);
206 if (default_value) {
207 default_value_ = *default_value;
208 }
209 }
210 virtual ~CustomWriteOnlyAccessor() {}
211
212 void Clear(Error *error) {
213 if (clearer_) {
214 (target_->*clearer_)(error);
215 } else {
216 Set(default_value_, error);
217 }
218 }
219 T Get(Error *error) {
220 error->Populate(Error::kPermissionDenied, "Property is write-only");
221 return T();
222 }
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700223 bool Set(const T &value, Error *error) {
224 return (target_->*setter_)(value, error);
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800225 }
226
227 private:
228 C *const target_;
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700229 bool(C::*const setter_)(const T &value, Error *error);
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800230 void(C::*const clearer_)(Error *error);
231 // |default_value_| is non-const because it can't be initialized in
232 // the initializer list.
233 T default_value_;
234 DISALLOW_COPY_AND_ASSIGN(CustomWriteOnlyAccessor);
235};
236
Paul Stewarta61593e2012-03-23 13:06:21 -0700237// CustomMappedAccessor<> passes an argument to the getter and setter
238// so that a generic method can be used, for example one that accesses the
239// property in a map.
240template<class C, class T, class A>
241class CustomMappedAccessor : public AccessorInterface<T> {
242 public:
243 // |target| is the object on which to call the methods |getter| and |setter|.
244 // |setter| is allowed to be NULL, in which case we will simply reject
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700245 // attempts to set via the accessor. |setter| should return true if the
246 // value was changed, and false otherwise.
Paul Stewarta61593e2012-03-23 13:06:21 -0700247 // |argument| is passed to the getter and setter methods to disambiguate
248 // between different properties in |target|.
249 // It is an error to pass NULL for any of |target|, |clearer| or |getter|.
250 CustomMappedAccessor(C *target,
251 void(C::*clearer)(const A &argument, Error *error),
252 T(C::*getter)(const A &argument, Error *error),
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700253 bool(C::*setter)(const A &argument, const T &value,
Paul Stewarta61593e2012-03-23 13:06:21 -0700254 Error *error),
255 const A &argument)
256 : target_(target),
257 clearer_(clearer),
258 getter_(getter),
259 setter_(setter),
260 argument_(argument) {
261 DCHECK(clearer);
262 DCHECK(target);
263 DCHECK(getter);
264 }
265 virtual ~CustomMappedAccessor() {}
266
267 void Clear(Error *error) {
268 (target_->*clearer_)(argument_, error);
269 }
270 T Get(Error *error) {
271 return (target_->*getter_)(argument_, error);
272 }
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700273 bool Set(const T &value, Error *error) {
Paul Stewarta61593e2012-03-23 13:06:21 -0700274 if (setter_) {
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700275 return (target_->*setter_)(argument_, value, error);
Paul Stewarta61593e2012-03-23 13:06:21 -0700276 } else {
277 error->Populate(Error::kInvalidArguments, "Property is read-only");
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700278 return false;
Paul Stewarta61593e2012-03-23 13:06:21 -0700279 }
280 }
281
282 private:
283 C *const target_;
284 void(C::*const clearer_)(const A &argument, Error *error);
285 T(C::*const getter_)(const A &argument, Error *error);
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700286 bool(C::*const setter_)(const A &argument, const T &value, Error *error);
Paul Stewarta61593e2012-03-23 13:06:21 -0700287 A argument_;
288 DISALLOW_COPY_AND_ASSIGN(CustomMappedAccessor);
289};
290
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700291} // namespace shill
292
293#endif // SHILL_PROPERTY_ACCESSOR_