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