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