1 // Copyright (C) 2013 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #ifndef I18N_ADDRESSINPUT_CALLBACK_H_
16 #define I18N_ADDRESSINPUT_CALLBACK_H_
17
18 #include <libaddressinput/util/scoped_ptr.h>
19
20 #include <cassert>
21 #include <cstddef>
22 #include <string>
23
24 namespace i18n {
25 namespace addressinput {
26
27 // Stores a pointer to a method in an object. Sample usage:
28 // class MyClass {
29 // public:
30 // typedef Callback<std::string, std::string> MyConstRefCallback;
31 // typedef ScopdedPtrCallback<std::string, MyDataType> MyScopedPtrCallback;
32 //
33 // void GetStringAsynchronously() {
34 // scoped_ptr<MyCallback> callback(BuildCallback(
35 // this, &MyClass::OnStringReady));
36 // bool success = ...
37 // std::string key = ...
38 // std::string data = ...
39 // (*callback)(success, key, data);
40 // }
41 //
42 // void GetDataAsynchronously() {
43 // scoped_ptr<MyScopedPtrCallback> callback(BuildScopedPtrCallback(
44 // this, &MyClass::OnDataReady));
45 // bool success = ...
46 // std::string key = ...
47 // scoped_ptr<MyDataType> data = ...
48 // (*callback)(success, key, data.Pass());
49 // }
50 //
51 // void OnStringReady(bool success,
52 // const std::string& key,
53 // const std::string& data) {
54 // ...
55 // }
56 //
57 // void OnDataReady(bool success,
58 // const std::string& key,
59 // scoped_ptr<MyDataType> data) {
60 // ...
61 // }
62 // };
63 template <typename Sig> class Callback;
64 template <typename ReturnType, typename RequestType, typename ResponseType>
65 class Callback<ReturnType(RequestType, ResponseType)> {
66 public:
~Callback()67 virtual ~Callback() {}
68
69 virtual ReturnType operator()(bool success,
70 const RequestType& request,
71 const ResponseType& response) const = 0;
72 };
73
74 template <typename Sig> class ScopedPtrCallback;
75 template <typename ReturnType, typename RequestType, typename ResponseType>
76 class ScopedPtrCallback<ReturnType(RequestType, ResponseType)> {
77 public:
~ScopedPtrCallback()78 virtual ~ScopedPtrCallback() {}
79
80 virtual ReturnType operator()(bool success,
81 const RequestType& request,
82 scoped_ptr<ResponseType> response) const = 0;
83 };
84
85 namespace {
86
87 template <typename BaseType, typename ReturnType, typename RequestType,
88 typename ResponseType>
89 class CallbackImpl : public Callback<ReturnType(RequestType, ResponseType)> {
90 public:
91 typedef ReturnType (BaseType::*Method)(
92 bool, const RequestType&, const ResponseType&);
93
CallbackImpl(BaseType * instance,Method method)94 CallbackImpl(BaseType* instance, Method method)
95 : instance_(instance),
96 method_(method) {
97 assert(instance_ != NULL);
98 assert(method_ != NULL);
99 }
100
~CallbackImpl()101 virtual ~CallbackImpl() {}
102
103 // Callback implementation.
operator()104 virtual ReturnType operator()(bool success,
105 const RequestType& request,
106 const ResponseType& response) const {
107 return (instance_->*method_)(success, request, response);
108 }
109
110 private:
111 BaseType* instance_;
112 Method method_;
113 };
114
115 template <typename BaseType, typename ReturnType, typename RequestType,
116 typename ResponseType>
117 class ScopedPtrCallbackImpl :
118 public ScopedPtrCallback<ReturnType(RequestType, ResponseType)> {
119 public:
120 typedef ReturnType (BaseType::*Method)(
121 bool, const RequestType&, scoped_ptr<ResponseType>);
122
ScopedPtrCallbackImpl(BaseType * instance,Method method)123 ScopedPtrCallbackImpl(BaseType* instance, Method method)
124 : instance_(instance),
125 method_(method) {
126 assert(instance_ != NULL);
127 assert(method_ != NULL);
128 }
129
~ScopedPtrCallbackImpl()130 virtual ~ScopedPtrCallbackImpl() {}
131
132 // ScopedPtrCallback implementation.
operator()133 virtual ReturnType operator()(bool success,
134 const RequestType& request,
135 scoped_ptr<ResponseType> response) const {
136 return (instance_->*method_)(success, request, response.Pass());
137 }
138
139 private:
140 BaseType* instance_;
141 Method method_;
142 };
143
144 } // namespace
145
146 // Returns a callback to |instance->method| with constant reference to data.
147 template <typename BaseType, typename ReturnType, typename RequestType,
148 typename ResponseType>
BuildCallback(BaseType * instance,ReturnType (BaseType::* method)(bool,const RequestType &,const ResponseType &))149 scoped_ptr<Callback<ReturnType(RequestType, ResponseType)> > BuildCallback(
150 BaseType* instance,
151 ReturnType (BaseType::*method)(
152 bool, const RequestType&, const ResponseType&)) {
153 return scoped_ptr<Callback<ReturnType(RequestType, ResponseType)> >(
154 new CallbackImpl<BaseType, ReturnType, RequestType, ResponseType>(
155 instance, method));
156 }
157
158 // Returns a callback to |instance->method| with scoped pointer to data.
159 template <typename BaseType, typename ReturnType, typename RequestType,
160 typename ResponseType>
161 scoped_ptr<ScopedPtrCallback<ReturnType(RequestType, ResponseType)> >
BuildScopedPtrCallback(BaseType * instance,ReturnType (BaseType::* method)(bool,const RequestType &,scoped_ptr<ResponseType>))162 BuildScopedPtrCallback(
163 BaseType* instance,
164 ReturnType (BaseType::*method)(
165 bool, const RequestType&, scoped_ptr<ResponseType>)) {
166 return scoped_ptr<ScopedPtrCallback<ReturnType(RequestType, ResponseType)> >(
167 new ScopedPtrCallbackImpl<BaseType, ReturnType, RequestType,
168 ResponseType>(
169 instance, method));
170 }
171
172 } // namespace addressinput
173 } // namespace i18n
174
175 #endif // I18N_ADDRESSINPUT_CALLBACK_H_
176