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