Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(20)

Side by Side Diff: talk/session/media/typewrapping.h.pump

Issue 1691463002: Move talk/session/media -> webrtc/pc (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Last rebase Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « talk/session/media/srtpfilter_unittest.cc ('k') | talk/session/media/voicechannel.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // To generate typewrapping.h from typewrapping.h.pump, execute:
2 // /home/build/google3/third_party/gtest/scripts/pump.py typewrapping.h.pump
3
4 // Copyright 2009 Google Inc.
5 // Author: tschmelcher@google.com (Tristan Schmelcher)
6 //
7 // A template meta-programming framework for customizable rule-based
8 // type-checking of type wrappers and wrapper functions.
9 //
10 // This framework is useful in a scenario where there are a set of types that
11 // you choose to "wrap" by implementing new preferred types such that the new
12 // and the old can be converted back and forth in some way, but you already have
13 // a library of functions that expect the original types. Example:
14 //
15 // Type A wraps X
16 // Type B wraps Y
17 // Type C wraps Z
18 //
19 // And function X Foo(Y, Z) exists.
20 //
21 // Since A, B, and C are preferred, you choose to implement a wrapper function
22 // with this interface:
23 //
24 // A Foo2(B, C)
25 //
26 // However, this can lead to subtle discrepancies, because if the interface to
27 // Foo ever changes then Foo2 may become out-of-sync. e.g., Foo might have
28 // originally returned void, but later is changed to return an error code. If
29 // the programmer forgets to change Foo2, the code will probably still work, but
30 // with an implicit cast to void inserted by the compiler, potentially leading
31 // to run-time errors or errors in usage.
32 //
33 // The purpose of this library is to prevent these discrepancies from occurring.
34 // You use it as follows:
35 //
36 // First, declare a new wrapping ruleset:
37 //
38 // DECLARE_WRAPPING_RULESET(ruleset_name)
39 //
40 // Then declare rules on what types wrap which other types and how to convert
41 // them:
42 //
43 // DECLARE_WRAPPER(ruleset_name, A, X, variable_name, wrapping_code,
44 // unwrapping_code)
45 //
46 // Where wrapping_code and unwrapping_code are expressions giving the code to
47 // use to wrap and unwrap a variable with the name "variable_name". There are
48 // also some helper macros to declare common wrapping schemes.
49 //
50 // Then implement your wrapped functions like this:
51 //
52 // A Foo_Wrapped(B b, C c) {
53 // return WRAP_CALL2(ruleset_name, A, Foo, B, b, C, c);
54 // }
55 //
56 // WRAP_CALL2 will unwrap b and c (if B and C are wrapped types) and call Foo,
57 // then wrap the result to type A if different from the return type. More
58 // importantly, if the types in Foo's interface do not _exactly_ match the
59 // unwrapped forms of A, B, and C (after typedef-equivalence), then you will get
60 // a compile-time error for a static_cast from the real function type to the
61 // expected one (except on Mac where this check is infeasible), and with no icky
62 // template instantiation errors either!
63 //
64 // There are also macros to wrap/unwrap individual values according to whichever
65 // rule applies to their types:
66 //
67 // WRAP(ruleset_name, A, X, value) // Compile-time error if no associated rule.
68 //
69 // UNWRAP(ruleset_name, A, value) // Infers X. If A is not a wrapper, no change.
70 //
71 // UNWRAP_TYPE(ruleset_name, A) // Evaluates to X.
72 //
73 //
74 // Essentially, the library works by "storing" the DECLARE_WRAPPER calls in
75 // template specializations. When the wrapper or unwrapper is invoked, the
76 // normal C++ template system essentially "looks up" the rule for the given
77 // type(s).
78 //
79 // All of the auto-generated code can be inlined to produce zero impact on
80 // run-time performance and code size (though some compilers may require
81 // gentle encouragement in order for them to do so).
82
83 #ifndef TALK_SESSION_PHONE_TYPEWRAPPING_H_
84 #define TALK_SESSION_PHONE_TYPEWRAPPING_H_
85
86 #include "webrtc/base/common.h"
87
88 #ifdef OSX
89 // XCode's GCC doesn't respect typedef-equivalence when casting function pointer
90 // types, so we can't enforce that the wrapped function signatures strictly
91 // match the expected types. Instead we have to forego the nice user-friendly
92 // static_cast check (because it will spuriously fail) and make the Call()
93 // function into a member template below.
94 #define CAST_FUNCTION_(function, ...) \
95 function
96 #else
97 #define CAST_FUNCTION_(function, ...) \
98 static_cast<__VA_ARGS__>(function)
99 #endif
100
101 // Internal helper macros.
102 #define SMART_WRAPPER_(wrapper, toType, fromType, from) \
103 (wrapper<toType, fromType>::Wrap(from))
104
105 #define SMART_UNWRAPPER_(unwrapper, fromType, from) \
106 (unwrapper<fromType>::Unwrap(from))
107
108 #define SMART_UNWRAPPER_TYPE_(unwrapper, fromType) \
109 typename unwrapper<fromType>::ToType
110
111 $var n = 27
112 $range i 0..n
113
114 $for i [[
115 $range j 1..i
116
117 // The code that follows wraps calls to $i-argument functions, unwrapping the
118 // arguments and wrapping the return value as needed.
119
120 // The usual case.
121 template<
122 template <typename ToType, typename FromType> class Wrapper,
123 template <typename FromType> class Unwrapper,
124 typename ReturnType$for j [[,
125 typename ArgType$j]]>
126 class SmartFunctionWrapper$i {
127 public:
128 typedef SMART_UNWRAPPER_TYPE_(Unwrapper, ReturnType) OriginalReturnType;
129
130 $for j [[
131 typedef SMART_UNWRAPPER_TYPE_(Unwrapper, ArgType$j) OriginalArgType$j;
132
133 ]]
134 typedef OriginalReturnType (*OriginalFunctionType)($for j , [[
135
136 OriginalArgType$j]]);
137
138 #ifdef OSX
139 template <typename F>
140 static FORCE_INLINE ReturnType Call(F function
141 #else
142 static FORCE_INLINE ReturnType Call(OriginalFunctionType function
143 #endif
144 $for j [[,
145 ArgType$j v$j]]) {
146 return SMART_WRAPPER_(Wrapper, ReturnType, OriginalReturnType,
147 (*function)($for j , [[
148
149 SMART_UNWRAPPER_(Unwrapper, ArgType$j, v$j)]]));
150 }
151 };
152
153 // Special case for functions that return void. (SMART_WRAPPER_ involves
154 // passing the unwrapped value in a function call, which is not a legal thing to
155 // do with void, so we need a special case here that doesn't call
156 // SMART_WRAPPER_()).
157 template<
158 template <typename ToType, typename FromType> class Wrapper,
159 template <typename FromType> class Unwrapper$for j [[,
160 typename ArgType$j]]>
161 class SmartFunctionWrapper$i<
162 Wrapper,
163 Unwrapper,
164 void$for j [[,
165 ArgType$j]]> {
166 public:
167 typedef void OriginalReturnType;
168
169 $for j [[
170 typedef SMART_UNWRAPPER_TYPE_(Unwrapper, ArgType$j) OriginalArgType$j;
171
172 ]]
173 typedef OriginalReturnType (*OriginalFunctionType)($for j , [[
174
175 OriginalArgType$j]]);
176
177 #ifdef OSX
178 template <typename F>
179 static FORCE_INLINE void Call(F function
180 #else
181 static FORCE_INLINE void Call(OriginalFunctionType function
182 #endif
183 $for j [[,
184 ArgType$j v$j]]) {
185 (*function)($for j , [[
186
187 SMART_UNWRAPPER_(Unwrapper, ArgType$j, v$j)]]);
188 }
189 };
190
191
192 ]]
193 // Programmer interface follows. Only macros below here should be used outside
194 // this file.
195
196 #define DECLARE_WRAPPING_RULESET(ruleSet) \
197 namespace ruleSet { \
198 \
199 /* SmartWrapper is for wrapping values. */ \
200 template<typename ToType, typename FromType> \
201 class SmartWrapper; \
202 \
203 /* Special case where the types are the same. */ \
204 template<typename T1> \
205 class SmartWrapper<T1, T1> { \
206 public: \
207 static FORCE_INLINE T1 Wrap(T1 from) { \
208 return from; \
209 } \
210 }; \
211 \
212 /* Class for unwrapping (i.e., going to the original value). This is done
213 function-style rather than predicate-style. The default rule is to leave
214 the type unchanged. */ \
215 template<typename FromType> \
216 class SmartUnwrapper { \
217 public: \
218 typedef FromType ToType; \
219 static FORCE_INLINE ToType Unwrap(FromType from) { \
220 return from; \
221 } \
222 }; \
223 \
224 }
225
226 // Declares a wrapping rule.
227 #define DECLARE_WRAPPER(ruleSet, wrappedType, unwrappedType, var, wrapCode, unwr apCode) \
228 namespace ruleSet { \
229 \
230 template<> \
231 class SmartWrapper<wrappedType, unwrappedType> { \
232 public: \
233 static FORCE_INLINE wrappedType Wrap(unwrappedType var) { \
234 return wrapCode; \
235 } \
236 }; \
237 \
238 template<> \
239 class SmartUnwrapper<wrappedType> { \
240 public: \
241 typedef unwrappedType ToType; \
242 static FORCE_INLINE unwrappedType Unwrap(wrappedType var) { \
243 return unwrapCode; \
244 } \
245 }; \
246 \
247 }
248
249 // Helper macro for declaring a wrapper that wraps/unwraps with reinterpret_cast <>.
250 #define DECLARE_WRAPPER_BY_REINTERPRET_CAST(ruleSet, wrappedType, unwrappedType) \
251 DECLARE_WRAPPER(ruleSet, wrappedType, unwrappedType, FROM, reinterpret_cast<wr appedType>(FROM), reinterpret_cast<unwrappedType>(FROM))
252
253 // Helper macro for declaring a wrapper that wraps/unwraps implicitly.
254 #define DECLARE_WRAPPER_BY_IMPLICIT_CAST(ruleSet, wrappedType, unwrappedType) \
255 DECLARE_WRAPPER(ruleSet, wrappedType, unwrappedType, FROM, FROM, FROM)
256
257 // Helper macro for declaring that the pointer types for one type wrap the point er types for another type.
258 #define DECLARE_POINTER_WRAPPER(ruleSet, wrappedType, unwrappedType) \
259 DECLARE_WRAPPER_BY_REINTERPRET_CAST(ruleSet, wrappedType*, unwrappedType*) \
260 DECLARE_WRAPPER_BY_REINTERPRET_CAST(ruleSet, const wrappedType*, const unwrapp edType*) \
261 DECLARE_WRAPPER_BY_REINTERPRET_CAST(ruleSet, wrappedType* const, unwrappedType * const) \
262 DECLARE_WRAPPER_BY_REINTERPRET_CAST(ruleSet, const wrappedType* const, const u nwrappedType* const) \
263
264 // Macro to wrap a single value.
265 #define WRAP(ruleSet, toType, fromType, from) \
266 SMART_WRAPPER_(ruleSet::SmartWrapper, toType, fromType, from)
267
268 // Macro to unwrap a single value.
269 #define UNWRAP(ruleSet, fromType, from) \
270 SMART_UNWRAPPER_(ruleSet::SmartUnwrapper, fromType, from)
271
272 // Macro to get the unwrapped form of a type.
273 #define UNWRAP_TYPE(ruleSet, fromType) \
274 SMART_UNWRAPPER_TYPE_(ruleSet::SmartUnwrapper, from)
275
276 // Macros to wrap function calls.
277
278 $for i [[
279 $range j 1..i
280 #define WRAP_CALL$i(ruleSet, toType, function$for j [[, argType$j, arg$j]]) \
281 (SmartFunctionWrapper$i< \
282 ruleSet::SmartWrapper, \
283 ruleSet::SmartUnwrapper, \
284 toType$for j [[, \
285 argType$j]]>::Call( \
286 CAST_FUNCTION_( \
287 &function, \
288 SmartFunctionWrapper$i< \
289 ruleSet::SmartWrapper, \
290 ruleSet::SmartUnwrapper, \
291 toType$for j [[, \
292 argType$j]]>::OriginalFunctionType)$for j [[, \
293 arg$j]]))
294
295 ]]
296
297 #endif // TALK_SESSION_PHONE_TYPEWRAPPINGHELPERS_H_
OLDNEW
« no previous file with comments | « talk/session/media/srtpfilter_unittest.cc ('k') | talk/session/media/voicechannel.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698