blob: 58c085e908a5152910597bde886ce4c80e711aea [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
Chris Masone3bd3c8c2011-06-13 08:20:26 -070035template <class T>
36class PropertyAccessor : public AccessorInterface<T> {
37 public:
mukesh agrawal292dc0f2012-01-26 18:02:46 -080038 explicit PropertyAccessor(T *property)
39 : property_(property), default_value_(*property) {
Chris Masone3bd3c8c2011-06-13 08:20:26 -070040 DCHECK(property);
41 }
42 virtual ~PropertyAccessor() {}
43
mukesh agrawal292dc0f2012-01-26 18:02:46 -080044 void Clear(Error *error) { Set(default_value_, error); }
Gaurav Shah1b7a6162011-11-09 11:41:01 -080045 T Get(Error */*error*/) { return *property_; }
mukesh agrawalffa3d042011-10-06 15:26:10 -070046 void Set(const T &value, Error */*error*/) {
Chris Masone3bd3c8c2011-06-13 08:20:26 -070047 *property_ = value;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070048 }
49
50 private:
51 T * const property_;
mukesh agrawal292dc0f2012-01-26 18:02:46 -080052 const T default_value_;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070053 DISALLOW_COPY_AND_ASSIGN(PropertyAccessor);
54};
55
56template <class T>
57class ConstPropertyAccessor : public AccessorInterface<T> {
58 public:
59 explicit ConstPropertyAccessor(const T *property) : property_(property) {
60 DCHECK(property);
61 }
62 virtual ~ConstPropertyAccessor() {}
63
mukesh agrawal292dc0f2012-01-26 18:02:46 -080064 void Clear(Error *error) {
65 // TODO(quiche): check if this is the right error.
66 // (maybe Error::kInvalidProperty instead?)
67 error->Populate(Error::kInvalidArguments, "Property is read-only");
68 }
Gaurav Shah1b7a6162011-11-09 11:41:01 -080069 T Get(Error */*error*/) { return *property_; }
mukesh agrawalffa3d042011-10-06 15:26:10 -070070 void Set(const T &/*value*/, Error *error) {
71 // TODO(quiche): check if this is the right error.
72 // (maybe Error::kPermissionDenied instead?)
73 error->Populate(Error::kInvalidArguments, "Property is read-only");
74 }
Chris Masone3bd3c8c2011-06-13 08:20:26 -070075
76 private:
77 const T * const property_;
78 DISALLOW_COPY_AND_ASSIGN(ConstPropertyAccessor);
79};
80
Gaurav Shah1b7a6162011-11-09 11:41:01 -080081template <class T>
82class WriteOnlyPropertyAccessor : public AccessorInterface<T> {
83 public:
mukesh agrawal292dc0f2012-01-26 18:02:46 -080084 explicit WriteOnlyPropertyAccessor(T *property)
85 : property_(property), default_value_(*property) {
Gaurav Shah1b7a6162011-11-09 11:41:01 -080086 DCHECK(property);
87 }
88 virtual ~WriteOnlyPropertyAccessor() {}
89
mukesh agrawal292dc0f2012-01-26 18:02:46 -080090 void Clear(Error *error) { Set(default_value_, error); }
Gaurav Shah1b7a6162011-11-09 11:41:01 -080091 T Get(Error *error) {
92 error->Populate(Error::kPermissionDenied, "Property is write-only");
93 return T();
94 }
95 void Set(const T &value, Error */*error*/) {
96 *property_ = value;
97 }
98
99 private:
100 FRIEND_TEST(PropertyAccessorTest, SignedIntCorrectness);
101 FRIEND_TEST(PropertyAccessorTest, UnsignedIntCorrectness);
102 FRIEND_TEST(PropertyAccessorTest, StringCorrectness);
103
104 T * const property_;
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800105 const T default_value_;
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800106 DISALLOW_COPY_AND_ASSIGN(WriteOnlyPropertyAccessor);
107};
108
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700109// CustomAccessor<> allows custom getter and setter methods to be provided.
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800110// Thus, if the state to be returned is to be derived on-demand, or if
111// setting the property requires validation, we can still fit it into the
112// AccessorInterface<> framework.
113//
114// If the property is write-only, use CustomWriteOnlyAccessor instead.
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700115template<class C, class T>
116class CustomAccessor : public AccessorInterface<T> {
117 public:
118 // |target| is the object on which to call the methods |getter| and |setter|
119 // |setter| is allowed to be NULL, in which case we will simply reject
120 // attempts to set via the accessor.
121 // It is an error to pass NULL for either of the other two arguments.
mukesh agrawalffa3d042011-10-06 15:26:10 -0700122 CustomAccessor(C *target,
Hristo Stefanoved2c28c2011-11-29 15:37:30 -0800123 T(C::*getter)(Error *error),
124 void(C::*setter)(const T &value, Error *error))
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700125 : target_(target),
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800126 default_value_(),
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700127 getter_(getter),
128 setter_(setter) {
129 DCHECK(target);
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800130 DCHECK(getter); // otherwise, use CustomWriteOnlyAccessor
131 if (setter_) {
132 Error e;
133 default_value_ = Get(&e);
134 }
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700135 }
136 virtual ~CustomAccessor() {}
137
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800138 void Clear(Error *error) { Set(default_value_, error); }
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800139 T Get(Error *error) {
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800140 return (target_->*getter_)(error);
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800141 }
mukesh agrawalffa3d042011-10-06 15:26:10 -0700142 void Set(const T &value, Error *error) {
143 if (setter_) {
144 (target_->*setter_)(value, error);
145 } else {
146 error->Populate(Error::kInvalidArguments, "Property is read-only");
147 }
148 }
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700149
150 private:
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800151 C *const target_;
152 // |default_value_| is non-const because it can't be initialized in
153 // the initializer list.
154 T default_value_;
155 T(C::*const getter_)(Error *error);
156 void(C::*const setter_)(const T &value, Error *error);
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700157 DISALLOW_COPY_AND_ASSIGN(CustomAccessor);
158};
159
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800160// CustomWriteOnlyAccessor<> allows a custom writer method to be provided.
161// Get returns an error automatically. Clear resets the value to a
162// default value.
163template<class C, class T>
164class CustomWriteOnlyAccessor : public AccessorInterface<T> {
165 public:
166 // |target| is the object on which to call |setter| and |clearer|.
167 //
168 // |target| and |setter| must be non-NULL.
169 //
170 // Either |clearer| or |default_value|, but not both, must be non-NULL.
171 // Whichever is non-NULL is used to clear the property.
172 CustomWriteOnlyAccessor(C *target,
173 void(C::*setter)(const T &value, Error *error),
174 void(C::*clearer)(Error *error),
175 const T *default_value)
176 : target_(target),
177 setter_(setter),
178 clearer_(clearer),
179 default_value_() {
180 DCHECK(target);
181 DCHECK(setter);
182 DCHECK(clearer || default_value);
183 DCHECK(!clearer || !default_value);
184 if (default_value) {
185 default_value_ = *default_value;
186 }
187 }
188 virtual ~CustomWriteOnlyAccessor() {}
189
190 void Clear(Error *error) {
191 if (clearer_) {
192 (target_->*clearer_)(error);
193 } else {
194 Set(default_value_, error);
195 }
196 }
197 T Get(Error *error) {
198 error->Populate(Error::kPermissionDenied, "Property is write-only");
199 return T();
200 }
201 void Set(const T &value, Error *error) {
202 (target_->*setter_)(value, error);
203 }
204
205 private:
206 C *const target_;
207 void(C::*const setter_)(const T &value, Error *error);
208 void(C::*const clearer_)(Error *error);
209 // |default_value_| is non-const because it can't be initialized in
210 // the initializer list.
211 T default_value_;
212 DISALLOW_COPY_AND_ASSIGN(CustomWriteOnlyAccessor);
213};
214
Paul Stewarta61593e2012-03-23 13:06:21 -0700215// CustomMappedAccessor<> passes an argument to the getter and setter
216// so that a generic method can be used, for example one that accesses the
217// property in a map.
218template<class C, class T, class A>
219class CustomMappedAccessor : public AccessorInterface<T> {
220 public:
221 // |target| is the object on which to call the methods |getter| and |setter|.
222 // |setter| is allowed to be NULL, in which case we will simply reject
223 // attempts to set via the accessor.
224 // |argument| is passed to the getter and setter methods to disambiguate
225 // between different properties in |target|.
226 // It is an error to pass NULL for any of |target|, |clearer| or |getter|.
227 CustomMappedAccessor(C *target,
228 void(C::*clearer)(const A &argument, Error *error),
229 T(C::*getter)(const A &argument, Error *error),
Paul Stewartebd38562012-03-23 13:06:40 -0700230 void(C::*setter)(const A &argument, const T &value,
Paul Stewarta61593e2012-03-23 13:06:21 -0700231 Error *error),
232 const A &argument)
233 : target_(target),
234 clearer_(clearer),
235 getter_(getter),
236 setter_(setter),
237 argument_(argument) {
238 DCHECK(clearer);
239 DCHECK(target);
240 DCHECK(getter);
241 }
242 virtual ~CustomMappedAccessor() {}
243
244 void Clear(Error *error) {
245 (target_->*clearer_)(argument_, error);
246 }
247 T Get(Error *error) {
248 return (target_->*getter_)(argument_, error);
249 }
250 void Set(const T &value, Error *error) {
251 if (setter_) {
Paul Stewartebd38562012-03-23 13:06:40 -0700252 (target_->*setter_)(argument_, value, error);
Paul Stewarta61593e2012-03-23 13:06:21 -0700253 } else {
254 error->Populate(Error::kInvalidArguments, "Property is read-only");
255 }
256 }
257
258 private:
259 C *const target_;
260 void(C::*const clearer_)(const A &argument, Error *error);
261 T(C::*const getter_)(const A &argument, Error *error);
Paul Stewartebd38562012-03-23 13:06:40 -0700262 void(C::*const setter_)(const A &argument, const T &value, Error *error);
Paul Stewarta61593e2012-03-23 13:06:21 -0700263 A argument_;
264 DISALLOW_COPY_AND_ASSIGN(CustomMappedAccessor);
265};
266
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700267} // namespace shill
268
269#endif // SHILL_PROPERTY_ACCESSOR_