26
26
/* The C API of R is awfully ugly and unpractical (and poorly
27
27
documented). These wrappers make it a little more bearable. */
28
28
29
+ #define PROTECT_PLUS (WHAT ) PROTECT(WHAT); nprotected++
30
+
29
31
#define Rexp (VAR ) Rexp_##VAR
30
32
31
- #define new_real_matrix (VAR , DIM1 , DIM2 ) \
32
- SEXP Rexp_##VAR; double *VAR; \
33
- PROTECT (Rexp_##VAR = Rf_allocMatrix(REALSXP, (DIM1), (DIM2))); \
34
- nprotected++; VAR = REAL(Rexp_##VAR)
33
+ #define new_real_matrix (VAR , DIM1 , DIM2 ) \
34
+ SEXP Rexp_##VAR; \
35
+ PROTECT_PLUS (Rexp_##VAR = Rf_allocMatrix(REALSXP, (DIM1), (DIM2))); \
36
+ double * VAR = REAL(Rexp_##VAR)
35
37
36
- #define new_real_vector (VAR , DIM ) \
37
- SEXP Rexp_##VAR; double *VAR; \
38
- PROTECT (Rexp_##VAR = Rf_allocVector(REALSXP, (DIM))); \
39
- nprotected++; VAR = REAL(Rexp_##VAR)
38
+ #define new_real_vector (VAR , DIM ) \
39
+ SEXP Rexp_##VAR; \
40
+ PROTECT_PLUS (Rexp_##VAR = Rf_allocVector(REALSXP, (DIM))); \
41
+ double * VAR = REAL(Rexp_##VAR)
40
42
41
- #define new_int_vector (VAR , DIM ) \
42
- SEXP Rexp_##VAR; int *VAR; \
43
- PROTECT (Rexp_##VAR = Rf_allocVector(INTSXP, (DIM))); \
44
- nprotected++; VAR = INTEGER(Rexp_##VAR)
43
+ #define new_int_vector (VAR , DIM ) \
44
+ SEXP Rexp_##VAR; \
45
+ PROTECT_PLUS (Rexp_##VAR = Rf_allocVector(INTSXP, (DIM))); \
46
+ int * VAR = INTEGER(Rexp_##VAR)
45
47
46
48
#define new_string_vector (VAR , DIM ) \
47
49
SEXP Rexp_##VAR; int Rexp_##VAR##_len = 0; \
48
- PROTECT(Rexp_##VAR = Rf_allocVector(STRSXP, (DIM))); \
49
- nprotected++
50
+ PROTECT_PLUS(Rexp_##VAR = Rf_allocVector(STRSXP, (DIM)))
50
51
51
52
#define string_vector_push_back (VAR , ELEMENT ) \
52
53
SET_STRING_ELT(Rexp_##VAR, Rexp_##VAR##_len, Rf_mkChar(ELEMENT)); \
53
54
Rexp_##VAR##_len++
54
55
55
56
#define new_list (LISTVAR , LENGTH ) \
56
57
SEXP Rexp_##LISTVAR; int Rexp_##LISTVAR##_len = 0; \
57
- PROTECT(Rexp_##LISTVAR = Rf_allocVector(VECSXP, (LENGTH))); \
58
- ++nprotected
58
+ PROTECT_PLUS(Rexp_##LISTVAR = Rf_allocVector(VECSXP, (LENGTH)))
59
59
60
60
#define new_logical_vector (VAR , DIM ) \
61
- SEXP Rexp_##VAR; int *VAR; \
62
- PROTECT (Rexp_##VAR = Rf_allocVector(LGLSXP, (DIM))); \
63
- nprotected++; VAR = LOGICAL(Rexp_##VAR)
61
+ SEXP Rexp_##VAR; \
62
+ PROTECT_PLUS (Rexp_##VAR = Rf_allocVector(LGLSXP, (DIM))); \
63
+ int * VAR = LOGICAL(Rexp_##VAR)
64
64
65
65
#define list_len (VAR ) Rexp_##VAR##_len
66
66
74
74
#define set_attribute (VAR , ATTRIBUTE , VALUE ) \
75
75
Rf_setAttrib(Rexp_##VAR, Rf_install(ATTRIBUTE), Rexp_##VALUE)
76
76
77
+
77
78
/*
78
79
* Unpack an integer vector stored in SEXP S.
79
80
*/
@@ -139,17 +140,16 @@ bool_2_logical_vector(int *dst, const bool *src, size_t n)
139
140
static inline SEXP
140
141
set_colnames (SEXP matrix , const char * const * names , size_t names_len )
141
142
{
142
- int nprotected = 0 ;
143
- SEXP dimnames = Rf_getAttrib (matrix , R_DimNamesSymbol );
144
- if (dimnames == R_NilValue ) {
145
- PROTECT (dimnames = Rf_allocVector (VECSXP , 2 ));
146
- nprotected ++ ;
147
- }
148
-
143
+ int nprotected = 0 ;
149
144
new_string_vector (colnames , names_len );
150
145
for (size_t k = 0 ; k < names_len ; k ++ ) {
151
146
string_vector_push_back (colnames , names [k ]);
152
147
}
148
+
149
+ SEXP dimnames = PROTECT_PLUS (Rf_getAttrib (matrix , R_DimNamesSymbol ));
150
+ if (dimnames == R_NilValue ) {
151
+ PROTECT_PLUS (dimnames = Rf_allocVector (VECSXP , 2 ));
152
+ }
153
153
SET_VECTOR_ELT (dimnames , 1 , Rexp (colnames ));
154
154
Rf_setAttrib (matrix , R_DimNamesSymbol , dimnames );
155
155
@@ -161,6 +161,7 @@ set_colnames(SEXP matrix, const char *const * names, size_t names_len)
161
161
static inline void
162
162
matrix_copy_dimnames (SEXP dest , const SEXP src )
163
163
{
164
+ int nprotected = 0 ;
164
165
// Ensure both source and target are matrices
165
166
if (!Rf_isMatrix (src ))
166
167
Rf_error ("src must be a matrix." );
@@ -169,8 +170,9 @@ matrix_copy_dimnames(SEXP dest, const SEXP src)
169
170
Rf_error ("dest must be a matrix." );
170
171
171
172
// Get the dimnames from the source matrix
172
- SEXP dimnames = Rf_getAttrib (src , R_DimNamesSymbol );
173
+ SEXP dimnames = PROTECT_PLUS ( Rf_getAttrib (src , R_DimNamesSymbol ) );
173
174
174
175
// Set the dimnames to the target matrix
175
176
Rf_setAttrib (dest , R_DimNamesSymbol , dimnames );
177
+ UNPROTECT (nprotected );
176
178
}
0 commit comments