1 // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*- 2 // 3 // dispatch.h: Rcpp R/C++ interface class library -- macros for dispatch 4 // 5 // Copyright (C) 2012 - 2016 Dirk Eddelbuettel and Romain Francois 6 // Copyright (C) 2016 Dirk Eddelbuettel, Romain Francois, Artem Klevtsov and Nathan Russell 7 // 8 // This file is part of Rcpp. 9 // 10 // Rcpp is free software: you can redistribute it and/or modify it 11 // under the terms of the GNU General Public License as published by 12 // the Free Software Foundation, either version 2 of the License, or 13 // (at your option) any later version. 14 // 15 // Rcpp is distributed in the hope that it will be useful, but 16 // WITHOUT ANY WARRANTY; without even the implied warranty of 17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 // GNU General Public License for more details. 19 // 20 // You should have received a copy of the GNU General Public License 21 // along with Rcpp. If not, see <http://www.gnu.org/licenses/>. 22 23 #ifndef Rcpp__macros__dispatch_h 24 #define Rcpp__macros__dispatch_h 25 26 // The variadic macros below incorporate techniques presented by 27 // Stack Overflow user Richard Hansen in this answer 28 // 29 // http://stackoverflow.com/a/11172679/1869097 30 // 31 // and are necessary to avoid the use of GNU compiler extensions. 32 33 #ifdef RCPP_USING_CXX11 34 35 #define ___RCPP_HANDLE_CASE___(___RTYPE___, ___FUN___, ___RCPPTYPE___, ...) \ 36 case ___RTYPE___: \ 37 return ___FUN___(::Rcpp::___RCPPTYPE___<___RTYPE___>(RCPP_MACRO_FIRST(__VA_ARGS__)) \ 38 RCPP_MACRO_REST(__VA_ARGS__)); 39 40 41 #define ___RCPP_RETURN___(__FUN__, __RCPPTYPE__, ...) \ 42 SEXP __TMP__ = RCPP_MACRO_FIRST(__VA_ARGS__); \ 43 switch (TYPEOF(__TMP__)) { \ 44 ___RCPP_HANDLE_CASE___(INTSXP, __FUN__, __RCPPTYPE__, __VA_ARGS__) \ 45 ___RCPP_HANDLE_CASE___(REALSXP, __FUN__, __RCPPTYPE__, __VA_ARGS__) \ 46 ___RCPP_HANDLE_CASE___(RAWSXP, __FUN__, __RCPPTYPE__, __VA_ARGS__) \ 47 ___RCPP_HANDLE_CASE___(LGLSXP, __FUN__, __RCPPTYPE__, __VA_ARGS__) \ 48 ___RCPP_HANDLE_CASE___(CPLXSXP, __FUN__, __RCPPTYPE__, __VA_ARGS__) \ 49 ___RCPP_HANDLE_CASE___(STRSXP, __FUN__, __RCPPTYPE__, __VA_ARGS__) \ 50 ___RCPP_HANDLE_CASE___(VECSXP, __FUN__, __RCPPTYPE__, __VA_ARGS__) \ 51 ___RCPP_HANDLE_CASE___(EXPRSXP, __FUN__, __RCPPTYPE__, __VA_ARGS__) \ 52 default: \ 53 throw std::range_error("Not a vector"); \ 54 } 55 56 57 #define RCPP_RETURN_VECTOR(_FUN_, ...) \ 58 ___RCPP_RETURN___(_FUN_, Vector, __VA_ARGS__) 59 #define RCPP_RETURN_MATRIX(_FUN_, ...) \ 60 ___RCPP_RETURN___(_FUN_, Matrix, __VA_ARGS__) 61 62 63 #define RCPP_MACRO_FIRST(...) RCPP_MACRO_FIRST_HELPER(__VA_ARGS__, throwaway) 64 #define RCPP_MACRO_FIRST_HELPER(first, ...) first 65 66 #define RCPP_MACRO_REST(...) RCPP_MACRO_REST_HELPER(RCPP_MACRO_NUM(__VA_ARGS__), __VA_ARGS__) 67 #define RCPP_MACRO_REST_HELPER(qty, ...) RCPP_MACRO_REST_HELPER2(qty, __VA_ARGS__) 68 #define RCPP_MACRO_REST_HELPER2(qty, ...) RCPP_MACRO_REST_HELPER_##qty(__VA_ARGS__) 69 #define RCPP_MACRO_REST_HELPER_ONE(first) 70 #define RCPP_MACRO_REST_HELPER_TWOORMORE(first, ...) , __VA_ARGS__ 71 #define RCPP_MACRO_NUM(...) \ 72 RCPP_MACRO_SELECT_25TH(__VA_ARGS__, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, \ 73 TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, \ 74 TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, \ 75 TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, \ 76 TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway) 77 #define RCPP_MACRO_SELECT_25TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, \ 78 a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, ...) a25 79 80 #else 81 82 #define ___RCPP_HANDLE_CASE___(___RTYPE___, ___FUN___, ___OBJECT___, \ 83 ___RCPPTYPE___) \ 84 case ___RTYPE___: \ 85 return ___FUN___(::Rcpp::___RCPPTYPE___<___RTYPE___>(___OBJECT___)); 86 87 #define ___RCPP_RETURN___(__FUN__, __SEXP__, __RCPPTYPE__) \ 88 SEXP __TMP__ = __SEXP__; \ 89 switch (TYPEOF(__TMP__)) { \ 90 ___RCPP_HANDLE_CASE___(INTSXP, __FUN__, __TMP__, __RCPPTYPE__) \ 91 ___RCPP_HANDLE_CASE___(REALSXP, __FUN__, __TMP__, __RCPPTYPE__) \ 92 ___RCPP_HANDLE_CASE___(RAWSXP, __FUN__, __TMP__, __RCPPTYPE__) \ 93 ___RCPP_HANDLE_CASE___(LGLSXP, __FUN__, __TMP__, __RCPPTYPE__) \ 94 ___RCPP_HANDLE_CASE___(CPLXSXP, __FUN__, __TMP__, __RCPPTYPE__) \ 95 ___RCPP_HANDLE_CASE___(STRSXP, __FUN__, __TMP__, __RCPPTYPE__) \ 96 ___RCPP_HANDLE_CASE___(VECSXP, __FUN__, __TMP__, __RCPPTYPE__) \ 97 ___RCPP_HANDLE_CASE___(EXPRSXP, __FUN__, __TMP__, __RCPPTYPE__) \ 98 default: \ 99 throw std::range_error("Not a vector"); \ 100 } 101 102 #define RCPP_RETURN_VECTOR(_FUN_, _SEXP_) \ 103 ___RCPP_RETURN___(_FUN_, _SEXP_, Vector) 104 #define RCPP_RETURN_MATRIX(_FUN_, _SEXP_) \ 105 ___RCPP_RETURN___(_FUN_, _SEXP_, Matrix) 106 #endif 107 108 #endif 109