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