blob: 03fa7c085c8dc79ab8399d0ba868dec8848d59f9 [file] [log] [blame]
Chris Masone3bd3c8c2011-06-13 08:20:26 -07001// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2// 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>
Chris Masone27bf1032011-06-28 17:02:01 -07009#include <base/logging.h>
Gaurav Shah1b7a6162011-11-09 11:41:01 -080010#include <gtest/gtest_prod.h> // for FRIEND_TEST.
Chris Masone3bd3c8c2011-06-13 08:20:26 -070011
12#include "shill/accessor_interface.h"
mukesh agrawalffa3d042011-10-06 15:26:10 -070013#include "shill/error.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070014
15namespace shill {
16
17// Templated implementations of AccessorInterface<>.
18// PropertyAccessor<> and ConstPropertyAccessor<> respectively provide
19// R/W and R/O access to the value pointed to by |property|.
20// this allows a class to easily map strings to member variables, so that
21// pieces of state stored in the class can be queried or updated by name.
22//
23// bool foo = true;
24// map<string, BoolAccessor> accessors;
25// accessors["foo"] = BoolAccessor(new PropertyAccessor<bool>(&foo));
26// bool new_foo = accessors["foo"]->Get(); // new_foo == true
27// accessors["foo"]->Set(false); // returns true, because setting is allowed.
28// // foo == false, new_foo == true
29// new_foo = accessors["foo"]->Get(); // new_foo == false
30template <class T>
31class PropertyAccessor : public AccessorInterface<T> {
32 public:
33 explicit PropertyAccessor(T *property) : property_(property) {
34 DCHECK(property);
35 }
36 virtual ~PropertyAccessor() {}
37
Gaurav Shah1b7a6162011-11-09 11:41:01 -080038 T Get(Error */*error*/) { return *property_; }
mukesh agrawalffa3d042011-10-06 15:26:10 -070039 void Set(const T &value, Error */*error*/) {
Chris Masone3bd3c8c2011-06-13 08:20:26 -070040 *property_ = value;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070041 }
42
43 private:
44 T * const property_;
45 DISALLOW_COPY_AND_ASSIGN(PropertyAccessor);
46};
47
48template <class T>
49class ConstPropertyAccessor : public AccessorInterface<T> {
50 public:
51 explicit ConstPropertyAccessor(const T *property) : property_(property) {
52 DCHECK(property);
53 }
54 virtual ~ConstPropertyAccessor() {}
55
Gaurav Shah1b7a6162011-11-09 11:41:01 -080056 T Get(Error */*error*/) { return *property_; }
mukesh agrawalffa3d042011-10-06 15:26:10 -070057 void Set(const T &/*value*/, Error *error) {
58 // TODO(quiche): check if this is the right error.
59 // (maybe Error::kPermissionDenied instead?)
60 error->Populate(Error::kInvalidArguments, "Property is read-only");
61 }
Chris Masone3bd3c8c2011-06-13 08:20:26 -070062
63 private:
64 const T * const property_;
65 DISALLOW_COPY_AND_ASSIGN(ConstPropertyAccessor);
66};
67
Gaurav Shah1b7a6162011-11-09 11:41:01 -080068template <class T>
69class WriteOnlyPropertyAccessor : public AccessorInterface<T> {
70 public:
71 explicit WriteOnlyPropertyAccessor(T *property) : property_(property) {
72 DCHECK(property);
73 }
74 virtual ~WriteOnlyPropertyAccessor() {}
75
76 T Get(Error *error) {
77 error->Populate(Error::kPermissionDenied, "Property is write-only");
78 return T();
79 }
80 void Set(const T &value, Error */*error*/) {
81 *property_ = value;
82 }
83
84 private:
85 FRIEND_TEST(PropertyAccessorTest, SignedIntCorrectness);
86 FRIEND_TEST(PropertyAccessorTest, UnsignedIntCorrectness);
87 FRIEND_TEST(PropertyAccessorTest, StringCorrectness);
88
89 T * const property_;
90 DISALLOW_COPY_AND_ASSIGN(WriteOnlyPropertyAccessor);
91};
92
Chris Masone3bd3c8c2011-06-13 08:20:26 -070093// CustomAccessor<> allows custom getter and setter methods to be provided.
94// Thus, if the state to be returned is to be derived on-demand, we can
95// still fit it into the AccessorInterface<> framework.
96template<class C, class T>
97class CustomAccessor : public AccessorInterface<T> {
98 public:
99 // |target| is the object on which to call the methods |getter| and |setter|
100 // |setter| is allowed to be NULL, in which case we will simply reject
101 // attempts to set via the accessor.
102 // It is an error to pass NULL for either of the other two arguments.
mukesh agrawalffa3d042011-10-06 15:26:10 -0700103 CustomAccessor(C *target,
Hristo Stefanoved2c28c2011-11-29 15:37:30 -0800104 T(C::*getter)(Error *error),
105 void(C::*setter)(const T &value, Error *error))
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700106 : target_(target),
107 getter_(getter),
108 setter_(setter) {
109 DCHECK(target);
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700110 }
111 virtual ~CustomAccessor() {}
112
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800113 T Get(Error *error) {
114 if (getter_)
115 return storage_ = (target_->*getter_)(error);
116
117 error->Populate(Error::kPermissionDenied, "Property is write-only");
118 return T();
119 }
120
mukesh agrawalffa3d042011-10-06 15:26:10 -0700121 void Set(const T &value, Error *error) {
122 if (setter_) {
123 (target_->*setter_)(value, error);
124 } else {
125 error->Populate(Error::kInvalidArguments, "Property is read-only");
126 }
127 }
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700128
129 private:
130 C * const target_;
131 // Get() returns a const&, so we need to have internal storage to which to
132 // return a reference.
133 T storage_;
Hristo Stefanoved2c28c2011-11-29 15:37:30 -0800134 T(C::*getter_)(Error *error);
135 void(C::*setter_)(const T &value, Error *error);
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700136 DISALLOW_COPY_AND_ASSIGN(CustomAccessor);
137};
138
139} // namespace shill
140
141#endif // SHILL_PROPERTY_ACCESSOR_