• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 ** Inline definitions for handlers.h, which are particularly long and a bit
3 ** tricky.
4 */
5 
6 #ifndef UPB_HANDLERS_INL_H_
7 #define UPB_HANDLERS_INL_H_
8 
9 #include <limits.h>
10 #include <stddef.h>
11 #include "upb/handlers.h"
12 
13 #include "upb/port_def.inc"
14 
15 #ifdef __cplusplus
16 
17 /* Type detection and typedefs for integer types.
18  * For platforms where there are multiple 32-bit or 64-bit types, we need to be
19  * able to enumerate them so we can properly create overloads for all variants.
20  *
21  * If any platform existed where there were three integer types with the same
22  * size, this would have to become more complicated.  For example, short, int,
23  * and long could all be 32-bits.  Even more diabolically, short, int, long,
24  * and long long could all be 64 bits and still be standard-compliant.
25  * However, few platforms are this strange, and it's unlikely that upb will be
26  * used on the strangest ones. */
27 
28 /* Can't count on stdint.h limits like INT32_MAX, because in C++ these are
29  * only defined when __STDC_LIMIT_MACROS are defined before the *first* include
30  * of stdint.h.  We can't guarantee that someone else didn't include these first
31  * without defining __STDC_LIMIT_MACROS. */
32 #define UPB_INT32_MAX 0x7fffffffLL
33 #define UPB_INT32_MIN (-UPB_INT32_MAX - 1)
34 #define UPB_INT64_MAX 0x7fffffffffffffffLL
35 #define UPB_INT64_MIN (-UPB_INT64_MAX - 1)
36 
37 #if INT_MAX == UPB_INT32_MAX && INT_MIN == UPB_INT32_MIN
38 #define UPB_INT_IS_32BITS 1
39 #endif
40 
41 #if LONG_MAX == UPB_INT32_MAX && LONG_MIN == UPB_INT32_MIN
42 #define UPB_LONG_IS_32BITS 1
43 #endif
44 
45 #if LONG_MAX == UPB_INT64_MAX && LONG_MIN == UPB_INT64_MIN
46 #define UPB_LONG_IS_64BITS 1
47 #endif
48 
49 #if LLONG_MAX == UPB_INT64_MAX && LLONG_MIN == UPB_INT64_MIN
50 #define UPB_LLONG_IS_64BITS 1
51 #endif
52 
53 /* We use macros instead of typedefs so we can undefine them later and avoid
54  * leaking them outside this header file. */
55 #if UPB_INT_IS_32BITS
56 #define UPB_INT32_T int
57 #define UPB_UINT32_T unsigned int
58 
59 #if UPB_LONG_IS_32BITS
60 #define UPB_TWO_32BIT_TYPES 1
61 #define UPB_INT32ALT_T long
62 #define UPB_UINT32ALT_T unsigned long
63 #endif  /* UPB_LONG_IS_32BITS */
64 
65 #elif UPB_LONG_IS_32BITS  /* && !UPB_INT_IS_32BITS */
66 #define UPB_INT32_T long
67 #define UPB_UINT32_T unsigned long
68 #endif  /* UPB_INT_IS_32BITS */
69 
70 
71 #if UPB_LONG_IS_64BITS
72 #define UPB_INT64_T long
73 #define UPB_UINT64_T unsigned long
74 
75 #if UPB_LLONG_IS_64BITS
76 #define UPB_TWO_64BIT_TYPES 1
77 #define UPB_INT64ALT_T long long
78 #define UPB_UINT64ALT_T unsigned long long
79 #endif  /* UPB_LLONG_IS_64BITS */
80 
81 #elif UPB_LLONG_IS_64BITS  /* && !UPB_LONG_IS_64BITS */
82 #define UPB_INT64_T long long
83 #define UPB_UINT64_T unsigned long long
84 #endif  /* UPB_LONG_IS_64BITS */
85 
86 #undef UPB_INT32_MAX
87 #undef UPB_INT32_MIN
88 #undef UPB_INT64_MAX
89 #undef UPB_INT64_MIN
90 #undef UPB_INT_IS_32BITS
91 #undef UPB_LONG_IS_32BITS
92 #undef UPB_LONG_IS_64BITS
93 #undef UPB_LLONG_IS_64BITS
94 
95 
96 namespace upb {
97 
98 typedef void CleanupFunc(void *ptr);
99 
100 /* Template to remove "const" from "const T*" and just return "T*".
101  *
102  * We define a nonsense default because otherwise it will fail to instantiate as
103  * a function parameter type even in cases where we don't expect any caller to
104  * actually match the overload. */
105 class CouldntRemoveConst {};
106 template <class T> struct remove_constptr { typedef CouldntRemoveConst type; };
107 template <class T> struct remove_constptr<const T *> { typedef T *type; };
108 
109 /* Template that we use below to remove a template specialization from
110  * consideration if it matches a specific type. */
111 template <class T, class U> struct disable_if_same { typedef void Type; };
112 template <class T> struct disable_if_same<T, T> {};
113 
114 template <class T> void DeletePointer(void *p) { delete static_cast<T>(p); }
115 
116 template <class T1, class T2>
117 struct FirstUnlessVoidOrBool {
118   typedef T1 value;
119 };
120 
121 template <class T2>
122 struct FirstUnlessVoidOrBool<void, T2> {
123   typedef T2 value;
124 };
125 
126 template <class T2>
127 struct FirstUnlessVoidOrBool<bool, T2> {
128   typedef T2 value;
129 };
130 
131 template<class T, class U>
132 struct is_same {
133   static bool value;
134 };
135 
136 template<class T>
137 struct is_same<T, T> {
138   static bool value;
139 };
140 
141 template<class T, class U>
142 bool is_same<T, U>::value = false;
143 
144 template<class T>
145 bool is_same<T, T>::value = true;
146 
147 /* FuncInfo *******************************************************************/
148 
149 /* Info about the user's original, pre-wrapped function. */
150 template <class C, class R = void>
151 struct FuncInfo {
152   /* The type of the closure that the function takes (its first param). */
153   typedef C Closure;
154 
155   /* The return type. */
156   typedef R Return;
157 };
158 
159 /* Func ***********************************************************************/
160 
161 /* Func1, Func2, Func3: Template classes representing a function and its
162  * signature.
163  *
164  * Since the function is a template parameter, calling the function can be
165  * inlined at compile-time and does not require a function pointer at runtime.
166  * These functions are not bound to a handler data so have no data or cleanup
167  * handler. */
168 struct UnboundFunc {
169   CleanupFunc *GetCleanup() { return nullptr; }
170   void *GetData() { return nullptr; }
171 };
172 
173 template <class R, class P1, R F(P1), class I>
174 struct Func1 : public UnboundFunc {
175   typedef R Return;
176   typedef I FuncInfo;
177   static R Call(P1 p1) { return F(p1); }
178 };
179 
180 template <class R, class P1, class P2, R F(P1, P2), class I>
181 struct Func2 : public UnboundFunc {
182   typedef R Return;
183   typedef I FuncInfo;
184   static R Call(P1 p1, P2 p2) { return F(p1, p2); }
185 };
186 
187 template <class R, class P1, class P2, class P3, R F(P1, P2, P3), class I>
188 struct Func3 : public UnboundFunc {
189   typedef R Return;
190   typedef I FuncInfo;
191   static R Call(P1 p1, P2 p2, P3 p3) { return F(p1, p2, p3); }
192 };
193 
194 template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4),
195           class I>
196 struct Func4 : public UnboundFunc {
197   typedef R Return;
198   typedef I FuncInfo;
199   static R Call(P1 p1, P2 p2, P3 p3, P4 p4) { return F(p1, p2, p3, p4); }
200 };
201 
202 template <class R, class P1, class P2, class P3, class P4, class P5,
203           R F(P1, P2, P3, P4, P5), class I>
204 struct Func5 : public UnboundFunc {
205   typedef R Return;
206   typedef I FuncInfo;
207   static R Call(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
208     return F(p1, p2, p3, p4, p5);
209   }
210 };
211 
212 /* BoundFunc ******************************************************************/
213 
214 /* BoundFunc2, BoundFunc3: Like Func2/Func3 except also contains a value that
215  * shall be bound to the function's second parameter.
216  *
217  * Note that the second parameter is a const pointer, but our stored bound value
218  * is non-const so we can free it when the handlers are destroyed. */
219 template <class T>
220 struct BoundFunc {
221   typedef typename remove_constptr<T>::type MutableP2;
222   explicit BoundFunc(MutableP2 data_) : data(data_) {}
223   CleanupFunc *GetCleanup() { return &DeletePointer<MutableP2>; }
224   MutableP2 GetData() { return data; }
225   MutableP2 data;
226 };
227 
228 template <class R, class P1, class P2, R F(P1, P2), class I>
229 struct BoundFunc2 : public BoundFunc<P2> {
230   typedef BoundFunc<P2> Base;
231   typedef I FuncInfo;
232   explicit BoundFunc2(typename Base::MutableP2 arg) : Base(arg) {}
233 };
234 
235 template <class R, class P1, class P2, class P3, R F(P1, P2, P3), class I>
236 struct BoundFunc3 : public BoundFunc<P2> {
237   typedef BoundFunc<P2> Base;
238   typedef I FuncInfo;
239   explicit BoundFunc3(typename Base::MutableP2 arg) : Base(arg) {}
240 };
241 
242 template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4),
243           class I>
244 struct BoundFunc4 : public BoundFunc<P2> {
245   typedef BoundFunc<P2> Base;
246   typedef I FuncInfo;
247   explicit BoundFunc4(typename Base::MutableP2 arg) : Base(arg) {}
248 };
249 
250 template <class R, class P1, class P2, class P3, class P4, class P5,
251           R F(P1, P2, P3, P4, P5), class I>
252 struct BoundFunc5 : public BoundFunc<P2> {
253   typedef BoundFunc<P2> Base;
254   typedef I FuncInfo;
255   explicit BoundFunc5(typename Base::MutableP2 arg) : Base(arg) {}
256 };
257 
258 /* FuncSig ********************************************************************/
259 
260 /* FuncSig1, FuncSig2, FuncSig3: template classes reflecting a function
261  * *signature*, but without a specific function attached.
262  *
263  * These classes contain member functions that can be invoked with a
264  * specific function to return a Func/BoundFunc class. */
265 template <class R, class P1>
266 struct FuncSig1 {
267   template <R F(P1)>
268   Func1<R, P1, F, FuncInfo<P1, R> > GetFunc() {
269     return Func1<R, P1, F, FuncInfo<P1, R> >();
270   }
271 };
272 
273 template <class R, class P1, class P2>
274 struct FuncSig2 {
275   template <R F(P1, P2)>
276   Func2<R, P1, P2, F, FuncInfo<P1, R> > GetFunc() {
277     return Func2<R, P1, P2, F, FuncInfo<P1, R> >();
278   }
279 
280   template <R F(P1, P2)>
281   BoundFunc2<R, P1, P2, F, FuncInfo<P1, R> > GetFunc(
282       typename remove_constptr<P2>::type param2) {
283     return BoundFunc2<R, P1, P2, F, FuncInfo<P1, R> >(param2);
284   }
285 };
286 
287 template <class R, class P1, class P2, class P3>
288 struct FuncSig3 {
289   template <R F(P1, P2, P3)>
290   Func3<R, P1, P2, P3, F, FuncInfo<P1, R> > GetFunc() {
291     return Func3<R, P1, P2, P3, F, FuncInfo<P1, R> >();
292   }
293 
294   template <R F(P1, P2, P3)>
295   BoundFunc3<R, P1, P2, P3, F, FuncInfo<P1, R> > GetFunc(
296       typename remove_constptr<P2>::type param2) {
297     return BoundFunc3<R, P1, P2, P3, F, FuncInfo<P1, R> >(param2);
298   }
299 };
300 
301 template <class R, class P1, class P2, class P3, class P4>
302 struct FuncSig4 {
303   template <R F(P1, P2, P3, P4)>
304   Func4<R, P1, P2, P3, P4, F, FuncInfo<P1, R> > GetFunc() {
305     return Func4<R, P1, P2, P3, P4, F, FuncInfo<P1, R> >();
306   }
307 
308   template <R F(P1, P2, P3, P4)>
309   BoundFunc4<R, P1, P2, P3, P4, F, FuncInfo<P1, R> > GetFunc(
310       typename remove_constptr<P2>::type param2) {
311     return BoundFunc4<R, P1, P2, P3, P4, F, FuncInfo<P1, R> >(param2);
312   }
313 };
314 
315 template <class R, class P1, class P2, class P3, class P4, class P5>
316 struct FuncSig5 {
317   template <R F(P1, P2, P3, P4, P5)>
318   Func5<R, P1, P2, P3, P4, P5, F, FuncInfo<P1, R> > GetFunc() {
319     return Func5<R, P1, P2, P3, P4, P5, F, FuncInfo<P1, R> >();
320   }
321 
322   template <R F(P1, P2, P3, P4, P5)>
323   BoundFunc5<R, P1, P2, P3, P4, P5, F, FuncInfo<P1, R> > GetFunc(
324       typename remove_constptr<P2>::type param2) {
325     return BoundFunc5<R, P1, P2, P3, P4, P5, F, FuncInfo<P1, R> >(param2);
326   }
327 };
328 
329 /* Overloaded template function that can construct the appropriate FuncSig*
330  * class given a function pointer by deducing the template parameters. */
331 template <class R, class P1>
332 inline FuncSig1<R, P1> MatchFunc(R (*f)(P1)) {
333   UPB_UNUSED(f);  /* Only used for template parameter deduction. */
334   return FuncSig1<R, P1>();
335 }
336 
337 template <class R, class P1, class P2>
338 inline FuncSig2<R, P1, P2> MatchFunc(R (*f)(P1, P2)) {
339   UPB_UNUSED(f);  /* Only used for template parameter deduction. */
340   return FuncSig2<R, P1, P2>();
341 }
342 
343 template <class R, class P1, class P2, class P3>
344 inline FuncSig3<R, P1, P2, P3> MatchFunc(R (*f)(P1, P2, P3)) {
345   UPB_UNUSED(f);  /* Only used for template parameter deduction. */
346   return FuncSig3<R, P1, P2, P3>();
347 }
348 
349 template <class R, class P1, class P2, class P3, class P4>
350 inline FuncSig4<R, P1, P2, P3, P4> MatchFunc(R (*f)(P1, P2, P3, P4)) {
351   UPB_UNUSED(f);  /* Only used for template parameter deduction. */
352   return FuncSig4<R, P1, P2, P3, P4>();
353 }
354 
355 template <class R, class P1, class P2, class P3, class P4, class P5>
356 inline FuncSig5<R, P1, P2, P3, P4, P5> MatchFunc(R (*f)(P1, P2, P3, P4, P5)) {
357   UPB_UNUSED(f);  /* Only used for template parameter deduction. */
358   return FuncSig5<R, P1, P2, P3, P4, P5>();
359 }
360 
361 /* MethodSig ******************************************************************/
362 
363 /* CallMethod*: a function template that calls a given method. */
364 template <class R, class C, R (C::*F)()>
365 R CallMethod0(C *obj) {
366   return ((*obj).*F)();
367 }
368 
369 template <class R, class C, class P1, R (C::*F)(P1)>
370 R CallMethod1(C *obj, P1 arg1) {
371   return ((*obj).*F)(arg1);
372 }
373 
374 template <class R, class C, class P1, class P2, R (C::*F)(P1, P2)>
375 R CallMethod2(C *obj, P1 arg1, P2 arg2) {
376   return ((*obj).*F)(arg1, arg2);
377 }
378 
379 template <class R, class C, class P1, class P2, class P3, R (C::*F)(P1, P2, P3)>
380 R CallMethod3(C *obj, P1 arg1, P2 arg2, P3 arg3) {
381   return ((*obj).*F)(arg1, arg2, arg3);
382 }
383 
384 template <class R, class C, class P1, class P2, class P3, class P4,
385           R (C::*F)(P1, P2, P3, P4)>
386 R CallMethod4(C *obj, P1 arg1, P2 arg2, P3 arg3, P4 arg4) {
387   return ((*obj).*F)(arg1, arg2, arg3, arg4);
388 }
389 
390 /* MethodSig: like FuncSig, but for member functions.
391  *
392  * GetFunc() returns a normal FuncN object, so after calling GetFunc() no
393  * more logic is required to special-case methods. */
394 template <class R, class C>
395 struct MethodSig0 {
396   template <R (C::*F)()>
397   Func1<R, C *, CallMethod0<R, C, F>, FuncInfo<C *, R> > GetFunc() {
398     return Func1<R, C *, CallMethod0<R, C, F>, FuncInfo<C *, R> >();
399   }
400 };
401 
402 template <class R, class C, class P1>
403 struct MethodSig1 {
404   template <R (C::*F)(P1)>
405   Func2<R, C *, P1, CallMethod1<R, C, P1, F>, FuncInfo<C *, R> > GetFunc() {
406     return Func2<R, C *, P1, CallMethod1<R, C, P1, F>, FuncInfo<C *, R> >();
407   }
408 
409   template <R (C::*F)(P1)>
410   BoundFunc2<R, C *, P1, CallMethod1<R, C, P1, F>, FuncInfo<C *, R> > GetFunc(
411       typename remove_constptr<P1>::type param1) {
412     return BoundFunc2<R, C *, P1, CallMethod1<R, C, P1, F>, FuncInfo<C *, R> >(
413         param1);
414   }
415 };
416 
417 template <class R, class C, class P1, class P2>
418 struct MethodSig2 {
419   template <R (C::*F)(P1, P2)>
420   Func3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F>, FuncInfo<C *, R> >
421   GetFunc() {
422     return Func3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F>,
423                  FuncInfo<C *, R> >();
424   }
425 
426   template <R (C::*F)(P1, P2)>
427   BoundFunc3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F>, FuncInfo<C *, R> >
428   GetFunc(typename remove_constptr<P1>::type param1) {
429     return BoundFunc3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F>,
430                       FuncInfo<C *, R> >(param1);
431   }
432 };
433 
434 template <class R, class C, class P1, class P2, class P3>
435 struct MethodSig3 {
436   template <R (C::*F)(P1, P2, P3)>
437   Func4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F>, FuncInfo<C *, R> >
438   GetFunc() {
439     return Func4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F>,
440                  FuncInfo<C *, R> >();
441   }
442 
443   template <R (C::*F)(P1, P2, P3)>
444   BoundFunc4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F>,
445              FuncInfo<C *, R> >
446   GetFunc(typename remove_constptr<P1>::type param1) {
447     return BoundFunc4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F>,
448                       FuncInfo<C *, R> >(param1);
449   }
450 };
451 
452 template <class R, class C, class P1, class P2, class P3, class P4>
453 struct MethodSig4 {
454   template <R (C::*F)(P1, P2, P3, P4)>
455   Func5<R, C *, P1, P2, P3, P4, CallMethod4<R, C, P1, P2, P3, P4, F>,
456         FuncInfo<C *, R> >
457   GetFunc() {
458     return Func5<R, C *, P1, P2, P3, P4, CallMethod4<R, C, P1, P2, P3, P4, F>,
459                  FuncInfo<C *, R> >();
460   }
461 
462   template <R (C::*F)(P1, P2, P3, P4)>
463   BoundFunc5<R, C *, P1, P2, P3, P4, CallMethod4<R, C, P1, P2, P3, P4, F>,
464              FuncInfo<C *, R> >
465   GetFunc(typename remove_constptr<P1>::type param1) {
466     return BoundFunc5<R, C *, P1, P2, P3, P4,
467                       CallMethod4<R, C, P1, P2, P3, P4, F>, FuncInfo<C *, R> >(
468         param1);
469   }
470 };
471 
472 template <class R, class C>
473 inline MethodSig0<R, C> MatchFunc(R (C::*f)()) {
474   UPB_UNUSED(f);  /* Only used for template parameter deduction. */
475   return MethodSig0<R, C>();
476 }
477 
478 template <class R, class C, class P1>
479 inline MethodSig1<R, C, P1> MatchFunc(R (C::*f)(P1)) {
480   UPB_UNUSED(f);  /* Only used for template parameter deduction. */
481   return MethodSig1<R, C, P1>();
482 }
483 
484 template <class R, class C, class P1, class P2>
485 inline MethodSig2<R, C, P1, P2> MatchFunc(R (C::*f)(P1, P2)) {
486   UPB_UNUSED(f);  /* Only used for template parameter deduction. */
487   return MethodSig2<R, C, P1, P2>();
488 }
489 
490 template <class R, class C, class P1, class P2, class P3>
491 inline MethodSig3<R, C, P1, P2, P3> MatchFunc(R (C::*f)(P1, P2, P3)) {
492   UPB_UNUSED(f);  /* Only used for template parameter deduction. */
493   return MethodSig3<R, C, P1, P2, P3>();
494 }
495 
496 template <class R, class C, class P1, class P2, class P3, class P4>
497 inline MethodSig4<R, C, P1, P2, P3, P4> MatchFunc(R (C::*f)(P1, P2, P3, P4)) {
498   UPB_UNUSED(f);  /* Only used for template parameter deduction. */
499   return MethodSig4<R, C, P1, P2, P3, P4>();
500 }
501 
502 /* MaybeWrapReturn ************************************************************/
503 
504 /* Template class that attempts to wrap the return value of the function so it
505  * matches the expected type.  There are two main adjustments it may make:
506  *
507  *   1. If the function returns void, make it return the expected type and with
508  *      a value that always indicates success.
509  *   2. If the function returns bool, make it return the expected type with a
510  *      value that indicates success or failure.
511  *
512  * The "expected type" for return is:
513  *   1. void* for start handlers.  If the closure parameter has a different type
514  *      we will cast it to void* for the return in the success case.
515  *   2. size_t for string buffer handlers.
516  *   3. bool for everything else. */
517 
518 /* Template parameters are FuncN type and desired return type. */
519 template <class F, class R, class Enable = void>
520 struct MaybeWrapReturn;
521 
522 /* If the return type matches, return the given function unwrapped. */
523 template <class F>
524 struct MaybeWrapReturn<F, typename F::Return> {
525   typedef F Func;
526 };
527 
528 /* Function wrapper that munges the return value from void to (bool)true. */
529 template <class P1, class P2, void F(P1, P2)>
530 bool ReturnTrue2(P1 p1, P2 p2) {
531   F(p1, p2);
532   return true;
533 }
534 
535 template <class P1, class P2, class P3, void F(P1, P2, P3)>
536 bool ReturnTrue3(P1 p1, P2 p2, P3 p3) {
537   F(p1, p2, p3);
538   return true;
539 }
540 
541 /* Function wrapper that munges the return value from void to (void*)arg1  */
542 template <class P1, class P2, void F(P1, P2)>
543 void *ReturnClosure2(P1 p1, P2 p2) {
544   F(p1, p2);
545   return p1;
546 }
547 
548 template <class P1, class P2, class P3, void F(P1, P2, P3)>
549 void *ReturnClosure3(P1 p1, P2 p2, P3 p3) {
550   F(p1, p2, p3);
551   return p1;
552 }
553 
554 /* Function wrapper that munges the return value from R to void*. */
555 template <class R, class P1, class P2, R F(P1, P2)>
556 void *CastReturnToVoidPtr2(P1 p1, P2 p2) {
557   return F(p1, p2);
558 }
559 
560 template <class R, class P1, class P2, class P3, R F(P1, P2, P3)>
561 void *CastReturnToVoidPtr3(P1 p1, P2 p2, P3 p3) {
562   return F(p1, p2, p3);
563 }
564 
565 /* Function wrapper that munges the return value from bool to void*. */
566 template <class P1, class P2, bool F(P1, P2)>
567 void *ReturnClosureOrBreak2(P1 p1, P2 p2) {
568   return F(p1, p2) ? p1 : UPB_BREAK;
569 }
570 
571 template <class P1, class P2, class P3, bool F(P1, P2, P3)>
572 void *ReturnClosureOrBreak3(P1 p1, P2 p2, P3 p3) {
573   return F(p1, p2, p3) ? p1 : UPB_BREAK;
574 }
575 
576 /* For the string callback, which takes five params, returns the size param. */
577 template <class P1, class P2,
578           void F(P1, P2, const char *, size_t, const upb_bufhandle *)>
579 size_t ReturnStringLen(P1 p1, P2 p2, const char *p3, size_t p4,
580                        const upb_bufhandle *p5) {
581   F(p1, p2, p3, p4, p5);
582   return p4;
583 }
584 
585 /* For the string callback, which takes five params, returns the size param or
586  * zero. */
587 template <class P1, class P2,
588           bool F(P1, P2, const char *, size_t, const upb_bufhandle *)>
589 size_t ReturnNOr0(P1 p1, P2 p2, const char *p3, size_t p4,
590                   const upb_bufhandle *p5) {
591   return F(p1, p2, p3, p4, p5) ? p4 : 0;
592 }
593 
594 /* If we have a function returning void but want a function returning bool, wrap
595  * it in a function that returns true. */
596 template <class P1, class P2, void F(P1, P2), class I>
597 struct MaybeWrapReturn<Func2<void, P1, P2, F, I>, bool> {
598   typedef Func2<bool, P1, P2, ReturnTrue2<P1, P2, F>, I> Func;
599 };
600 
601 template <class P1, class P2, class P3, void F(P1, P2, P3), class I>
602 struct MaybeWrapReturn<Func3<void, P1, P2, P3, F, I>, bool> {
603   typedef Func3<bool, P1, P2, P3, ReturnTrue3<P1, P2, P3, F>, I> Func;
604 };
605 
606 /* If our function returns void but we want one returning void*, wrap it in a
607  * function that returns the first argument. */
608 template <class P1, class P2, void F(P1, P2), class I>
609 struct MaybeWrapReturn<Func2<void, P1, P2, F, I>, void *> {
610   typedef Func2<void *, P1, P2, ReturnClosure2<P1, P2, F>, I> Func;
611 };
612 
613 template <class P1, class P2, class P3, void F(P1, P2, P3), class I>
614 struct MaybeWrapReturn<Func3<void, P1, P2, P3, F, I>, void *> {
615   typedef Func3<void *, P1, P2, P3, ReturnClosure3<P1, P2, P3, F>, I> Func;
616 };
617 
618 /* If our function returns R* but we want one returning void*, wrap it in a
619  * function that casts to void*. */
620 template <class R, class P1, class P2, R *F(P1, P2), class I>
621 struct MaybeWrapReturn<Func2<R *, P1, P2, F, I>, void *,
622                        typename disable_if_same<R *, void *>::Type> {
623   typedef Func2<void *, P1, P2, CastReturnToVoidPtr2<R *, P1, P2, F>, I> Func;
624 };
625 
626 template <class R, class P1, class P2, class P3, R *F(P1, P2, P3), class I>
627 struct MaybeWrapReturn<Func3<R *, P1, P2, P3, F, I>, void *,
628                        typename disable_if_same<R *, void *>::Type> {
629   typedef Func3<void *, P1, P2, P3, CastReturnToVoidPtr3<R *, P1, P2, P3, F>, I>
630       Func;
631 };
632 
633 /* If our function returns bool but we want one returning void*, wrap it in a
634  * function that returns either the first param or UPB_BREAK. */
635 template <class P1, class P2, bool F(P1, P2), class I>
636 struct MaybeWrapReturn<Func2<bool, P1, P2, F, I>, void *> {
637   typedef Func2<void *, P1, P2, ReturnClosureOrBreak2<P1, P2, F>, I> Func;
638 };
639 
640 template <class P1, class P2, class P3, bool F(P1, P2, P3), class I>
641 struct MaybeWrapReturn<Func3<bool, P1, P2, P3, F, I>, void *> {
642   typedef Func3<void *, P1, P2, P3, ReturnClosureOrBreak3<P1, P2, P3, F>, I>
643       Func;
644 };
645 
646 /* If our function returns void but we want one returning size_t, wrap it in a
647  * function that returns the size argument. */
648 template <class P1, class P2,
649           void F(P1, P2, const char *, size_t, const upb_bufhandle *), class I>
650 struct MaybeWrapReturn<
651     Func5<void, P1, P2, const char *, size_t, const upb_bufhandle *, F, I>,
652           size_t> {
653   typedef Func5<size_t, P1, P2, const char *, size_t, const upb_bufhandle *,
654                 ReturnStringLen<P1, P2, F>, I> Func;
655 };
656 
657 /* If our function returns bool but we want one returning size_t, wrap it in a
658  * function that returns either 0 or the buf size. */
659 template <class P1, class P2,
660           bool F(P1, P2, const char *, size_t, const upb_bufhandle *), class I>
661 struct MaybeWrapReturn<
662     Func5<bool, P1, P2, const char *, size_t, const upb_bufhandle *, F, I>,
663     size_t> {
664   typedef Func5<size_t, P1, P2, const char *, size_t, const upb_bufhandle *,
665                 ReturnNOr0<P1, P2, F>, I> Func;
666 };
667 
668 /* ConvertParams **************************************************************/
669 
670 /* Template class that converts the function parameters if necessary, and
671  * ignores the HandlerData parameter if appropriate.
672  *
673  * Template parameter is the are FuncN function type. */
674 template <class F, class T>
675 struct ConvertParams;
676 
677 /* Function that discards the handler data parameter. */
678 template <class R, class P1, R F(P1)>
679 R IgnoreHandlerData2(void *p1, const void *hd) {
680   UPB_UNUSED(hd);
681   return F(static_cast<P1>(p1));
682 }
683 
684 template <class R, class P1, class P2Wrapper, class P2Wrapped,
685           R F(P1, P2Wrapped)>
686 R IgnoreHandlerData3(void *p1, const void *hd, P2Wrapper p2) {
687   UPB_UNUSED(hd);
688   return F(static_cast<P1>(p1), p2);
689 }
690 
691 template <class R, class P1, class P2, class P3, R F(P1, P2, P3)>
692 R IgnoreHandlerData4(void *p1, const void *hd, P2 p2, P3 p3) {
693   UPB_UNUSED(hd);
694   return F(static_cast<P1>(p1), p2, p3);
695 }
696 
697 template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4)>
698 R IgnoreHandlerData5(void *p1, const void *hd, P2 p2, P3 p3, P4 p4) {
699   UPB_UNUSED(hd);
700   return F(static_cast<P1>(p1), p2, p3, p4);
701 }
702 
703 template <class R, class P1, R F(P1, const char*, size_t)>
704 R IgnoreHandlerDataIgnoreHandle(void *p1, const void *hd, const char *p2,
705                                 size_t p3, const upb_bufhandle *handle) {
706   UPB_UNUSED(hd);
707   UPB_UNUSED(handle);
708   return F(static_cast<P1>(p1), p2, p3);
709 }
710 
711 /* Function that casts the handler data parameter. */
712 template <class R, class P1, class P2, R F(P1, P2)>
713 R CastHandlerData2(void *c, const void *hd) {
714   return F(static_cast<P1>(c), static_cast<P2>(hd));
715 }
716 
717 template <class R, class P1, class P2, class P3Wrapper, class P3Wrapped,
718           R F(P1, P2, P3Wrapped)>
719 R CastHandlerData3(void *c, const void *hd, P3Wrapper p3) {
720   return F(static_cast<P1>(c), static_cast<P2>(hd), p3);
721 }
722 
723 template <class R, class P1, class P2, class P3, class P4, class P5,
724           R F(P1, P2, P3, P4, P5)>
725 R CastHandlerData5(void *c, const void *hd, P3 p3, P4 p4, P5 p5) {
726   return F(static_cast<P1>(c), static_cast<P2>(hd), p3, p4, p5);
727 }
728 
729 template <class R, class P1, class P2, R F(P1, P2, const char *, size_t)>
730 R CastHandlerDataIgnoreHandle(void *c, const void *hd, const char *p3,
731                               size_t p4, const upb_bufhandle *handle) {
732   UPB_UNUSED(handle);
733   return F(static_cast<P1>(c), static_cast<P2>(hd), p3, p4);
734 }
735 
736 /* For unbound functions, ignore the handler data. */
737 template <class R, class P1, R F(P1), class I, class T>
738 struct ConvertParams<Func1<R, P1, F, I>, T> {
739   typedef Func2<R, void *, const void *, IgnoreHandlerData2<R, P1, F>, I> Func;
740 };
741 
742 template <class R, class P1, class P2, R F(P1, P2), class I,
743           class R2, class P1_2, class P2_2, class P3_2>
744 struct ConvertParams<Func2<R, P1, P2, F, I>,
745                      R2 (*)(P1_2, P2_2, P3_2)> {
746   typedef Func3<R, void *, const void *, P3_2,
747                 IgnoreHandlerData3<R, P1, P3_2, P2, F>, I> Func;
748 };
749 
750 /* For StringBuffer only; this ignores both the handler data and the
751  * upb_bufhandle. */
752 template <class R, class P1, R F(P1, const char *, size_t), class I, class T>
753 struct ConvertParams<Func3<R, P1, const char *, size_t, F, I>, T> {
754   typedef Func5<R, void *, const void *, const char *, size_t,
755                 const upb_bufhandle *, IgnoreHandlerDataIgnoreHandle<R, P1, F>,
756                 I> Func;
757 };
758 
759 template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4),
760           class I, class T>
761 struct ConvertParams<Func4<R, P1, P2, P3, P4, F, I>, T> {
762   typedef Func5<R, void *, const void *, P2, P3, P4,
763                 IgnoreHandlerData5<R, P1, P2, P3, P4, F>, I> Func;
764 };
765 
766 /* For bound functions, cast the handler data. */
767 template <class R, class P1, class P2, R F(P1, P2), class I, class T>
768 struct ConvertParams<BoundFunc2<R, P1, P2, F, I>, T> {
769   typedef Func2<R, void *, const void *, CastHandlerData2<R, P1, P2, F>, I>
770       Func;
771 };
772 
773 template <class R, class P1, class P2, class P3, R F(P1, P2, P3), class I,
774           class R2, class P1_2, class P2_2, class P3_2>
775 struct ConvertParams<BoundFunc3<R, P1, P2, P3, F, I>,
776                      R2 (*)(P1_2, P2_2, P3_2)> {
777   typedef Func3<R, void *, const void *, P3_2,
778                 CastHandlerData3<R, P1, P2, P3_2, P3, F>, I> Func;
779 };
780 
781 /* For StringBuffer only; this ignores the upb_bufhandle. */
782 template <class R, class P1, class P2, R F(P1, P2, const char *, size_t),
783           class I, class T>
784 struct ConvertParams<BoundFunc4<R, P1, P2, const char *, size_t, F, I>, T> {
785   typedef Func5<R, void *, const void *, const char *, size_t,
786                 const upb_bufhandle *,
787                 CastHandlerDataIgnoreHandle<R, P1, P2, F>, I>
788       Func;
789 };
790 
791 template <class R, class P1, class P2, class P3, class P4, class P5,
792           R F(P1, P2, P3, P4, P5), class I, class T>
793 struct ConvertParams<BoundFunc5<R, P1, P2, P3, P4, P5, F, I>, T> {
794   typedef Func5<R, void *, const void *, P3, P4, P5,
795                 CastHandlerData5<R, P1, P2, P3, P4, P5, F>, I> Func;
796 };
797 
798 /* utype/ltype are upper/lower-case, ctype is canonical C type, vtype is
799  * variant C type. */
800 #define TYPE_METHODS(utype, ltype, ctype, vtype)                      \
801   template <>                                                         \
802   struct CanonicalType<vtype> {                                       \
803     typedef ctype Type;                                               \
804   };                                                                  \
805   template <>                                                         \
806   inline bool HandlersPtr::SetValueHandler<vtype>(                    \
807       FieldDefPtr f, const HandlersPtr::utype##Handler &handler) {    \
808     handler.AddCleanup(ptr());                                        \
809     return upb_handlers_set##ltype(ptr(), f.ptr(), handler.handler(), \
810                                    &handler.attr());                  \
811   }
812 
813 TYPE_METHODS(Double, double, double,   double)
814 TYPE_METHODS(Float,  float,  float,    float)
815 TYPE_METHODS(UInt64, uint64, uint64_t, UPB_UINT64_T)
816 TYPE_METHODS(UInt32, uint32, uint32_t, UPB_UINT32_T)
817 TYPE_METHODS(Int64,  int64,  int64_t,  UPB_INT64_T)
818 TYPE_METHODS(Int32,  int32,  int32_t,  UPB_INT32_T)
819 TYPE_METHODS(Bool,   bool,   bool,     bool)
820 
821 #ifdef UPB_TWO_32BIT_TYPES
822 TYPE_METHODS(Int32,  int32,  int32_t,  UPB_INT32ALT_T)
823 TYPE_METHODS(UInt32, uint32, uint32_t, UPB_UINT32ALT_T)
824 #endif
825 
826 #ifdef UPB_TWO_64BIT_TYPES
827 TYPE_METHODS(Int64,  int64,  int64_t,  UPB_INT64ALT_T)
828 TYPE_METHODS(UInt64, uint64, uint64_t, UPB_UINT64ALT_T)
829 #endif
830 #undef TYPE_METHODS
831 
832 template <> struct CanonicalType<Status*> {
833   typedef Status* Type;
834 };
835 
836 template <class F> struct ReturnOf;
837 
838 template <class R, class P1, class P2>
839 struct ReturnOf<R (*)(P1, P2)> {
840   typedef R Return;
841 };
842 
843 template <class R, class P1, class P2, class P3>
844 struct ReturnOf<R (*)(P1, P2, P3)> {
845   typedef R Return;
846 };
847 
848 template <class R, class P1, class P2, class P3, class P4>
849 struct ReturnOf<R (*)(P1, P2, P3, P4)> {
850   typedef R Return;
851 };
852 
853 template <class R, class P1, class P2, class P3, class P4, class P5>
854 struct ReturnOf<R (*)(P1, P2, P3, P4, P5)> {
855   typedef R Return;
856 };
857 
858 
859 template <class T>
860 template <class F>
861 inline Handler<T>::Handler(F func)
862     : registered_(false),
863       cleanup_data_(func.GetData()),
864       cleanup_func_(func.GetCleanup()) {
865   attr_.handler_data = func.GetData();
866   typedef typename ReturnOf<T>::Return Return;
867   typedef typename ConvertParams<F, T>::Func ConvertedParamsFunc;
868   typedef typename MaybeWrapReturn<ConvertedParamsFunc, Return>::Func
869       ReturnWrappedFunc;
870   handler_ = ReturnWrappedFunc().Call;
871 
872   /* Set attributes based on what templates can statically tell us about the
873    * user's function. */
874 
875   /* If the original function returns void, then we know that we wrapped it to
876    * always return ok. */
877   bool always_ok = is_same<typename F::FuncInfo::Return, void>::value;
878   attr_.alwaysok = always_ok;
879 
880   /* Closure parameter and return type. */
881   attr_.closure_type = UniquePtrForType<typename F::FuncInfo::Closure>();
882 
883   /* We use the closure type (from the first parameter) if the return type is
884    * void or bool, since these are the two cases we wrap to return the closure's
885    * type anyway.
886    *
887    * This is all nonsense for non START* handlers, but it doesn't matter because
888    * in that case the value will be ignored. */
889   typedef typename FirstUnlessVoidOrBool<typename F::FuncInfo::Return,
890                                          typename F::FuncInfo::Closure>::value
891       EffectiveReturn;
892   attr_.return_closure_type = UniquePtrForType<EffectiveReturn>();
893 }
894 
895 template <class T>
896 inline void Handler<T>::AddCleanup(upb_handlers* h) const {
897   UPB_ASSERT(!registered_);
898   registered_ = true;
899   if (cleanup_func_) {
900     bool ok = upb_handlers_addcleanup(h, cleanup_data_, cleanup_func_);
901     UPB_ASSERT(ok);
902   }
903 }
904 
905 }  /* namespace upb */
906 
907 #endif  /* __cplusplus */
908 
909 
910 #undef UPB_TWO_32BIT_TYPES
911 #undef UPB_TWO_64BIT_TYPES
912 #undef UPB_INT32_T
913 #undef UPB_UINT32_T
914 #undef UPB_INT32ALT_T
915 #undef UPB_UINT32ALT_T
916 #undef UPB_INT64_T
917 #undef UPB_UINT64_T
918 #undef UPB_INT64ALT_T
919 #undef UPB_UINT64ALT_T
920 
921 #include "upb/port_undef.inc"
922 
923 #endif  /* UPB_HANDLERS_INL_H_ */
924