Home | History | Annotate | Download | only in shill
      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:
     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 
     82 template <class T>
     83 class 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 
    108 template <class T>
    109 class 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.
    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|.
    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.
    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.
    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.
    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.
    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.
    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|.
    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