Skip to content

Commit a9b743f

Browse files
author
qkou
committed
Rcpp_PreserveObject/Rcpp_ReplaceObject to protect underlying SEXP
1 parent a2fc8a3 commit a9b743f

File tree

1 file changed

+42
-22
lines changed

1 file changed

+42
-22
lines changed

inst/include/Rcpp/String.h

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -54,45 +54,54 @@ namespace Rcpp {
5454

5555
/** default constructor */
5656
String( ): data( Rf_mkChar("") ), buffer(), valid(true), buffer_ready(true), enc(CE_NATIVE) {
57+
Rcpp_PreserveObject( data );
5758
RCPP_STRING_DEBUG( "String()" ) ;
5859
}
5960

6061
/** copy constructor */
6162
String( const String& other) : data( other.get_sexp()), valid(true), buffer_ready(false), enc(Rf_getCharCE(other.get_sexp())) {
63+
Rcpp_PreserveObject( data );
6264
RCPP_STRING_DEBUG( "String(const String&)" ) ;
6365
}
6466

6567
String( const String& other, const std::string& enc) : data( other.get_sexp()), valid(true), buffer_ready(false) {
68+
Rcpp_PreserveObject( data );
6669
set_encoding(enc);
6770
RCPP_STRING_DEBUG( "String(const String&)" ) ;
6871
}
6972

7073
/** construct a string from a single CHARSXP SEXP */
7174
String(SEXP charsxp) : data(charsxp), valid(true), buffer_ready(false), enc(Rf_getCharCE(charsxp)) {
75+
Rcpp_PreserveObject( data );
7276
RCPP_STRING_DEBUG( "String(SEXP)" ) ;
7377
}
7478

7579
String(SEXP charsxp, const std::string& enc) : data(charsxp), valid(true), buffer_ready(false) {
80+
Rcpp_PreserveObject( data );
7681
set_encoding(enc);
7782
RCPP_STRING_DEBUG( "String(SEXP)" ) ;
7883
}
7984

8085
/** from string proxy */
8186
String( const StringProxy& proxy ): data( proxy.get() ), valid(true), buffer_ready(false), enc(Rf_getCharCE(proxy.get())){
87+
Rcpp_PreserveObject( data );
8288
RCPP_STRING_DEBUG( "String( const StringProxy&)" ) ;
8389
}
8490

8591
String( const StringProxy& proxy, const std::string& enc ): data( proxy.get() ), valid(true), buffer_ready(false) {
92+
Rcpp_PreserveObject( data );
8693
set_encoding(enc);
8794
RCPP_STRING_DEBUG( "String( const StringProxy&)" ) ;
8895
}
8996

9097
/** from string proxy */
9198
String( const const_StringProxy& proxy ): data( proxy.get() ), valid(true), buffer_ready(false), enc(Rf_getCharCE(proxy.get())){
99+
Rcpp_PreserveObject( data );
92100
RCPP_STRING_DEBUG( "String( const const_StringProxy&)" ) ;
93101
}
94102

95103
String( const const_StringProxy& proxy, const std::string& enc ): data( proxy.get() ), valid(true), buffer_ready(false) {
104+
Rcpp_PreserveObject( data );
96105
set_encoding(enc);
97106
RCPP_STRING_DEBUG( "String( const const_StringProxy&)" ) ;
98107
}
@@ -103,6 +112,7 @@ namespace Rcpp {
103112
}
104113

105114
String( const std::wstring& s) : data(internal::make_charsexp(s)), valid(true), buffer_ready(false), enc(CE_NATIVE) {
115+
Rcpp_PreserveObject( data );
106116
RCPP_STRING_DEBUG( "String(const std::wstring& )" ) ;
107117
}
108118

@@ -112,32 +122,38 @@ namespace Rcpp {
112122
}
113123

114124
String( const wchar_t* s) : data(internal::make_charsexp(s)), valid(true), buffer_ready(false), enc(CE_NATIVE) {
125+
Rcpp_PreserveObject( data );
115126
RCPP_STRING_DEBUG( "String(const wchar_t* s)" ) ;
116127
}
117128

118129
/** constructors from R primitives */
119-
String( int x ) : data( internal::r_coerce<INTSXP,STRSXP>(x) ), valid(true), buffer_ready(false), enc(CE_NATIVE){}
120-
String( double x ) : data( internal::r_coerce<REALSXP,STRSXP>(x) ), valid(true), buffer_ready(false), enc(CE_NATIVE){}
121-
String( bool x ) : data( internal::r_coerce<LGLSXP,STRSXP>(x) ), valid( true ) , buffer_ready(false), enc(CE_NATIVE){}
122-
String( Rcomplex x ) : data( internal::r_coerce<CPLXSXP,STRSXP>(x) ), valid( true ), buffer_ready(false), enc(CE_NATIVE){}
123-
String( Rbyte x ) : data( internal::r_coerce<RAWSXP,STRSXP>(x) ), valid(true), buffer_ready(false), enc(CE_NATIVE){}
124-
125-
126-
inline String& operator=( int x ){ data = internal::r_coerce<INTSXP ,STRSXP>( x ) ; valid = true ; buffer_ready = false ; return *this ; }
127-
inline String& operator=( double x ){ data = internal::r_coerce<REALSXP,STRSXP>( x ) ; valid = true ; buffer_ready = false ; return *this ; }
128-
inline String& operator=( Rbyte x ){ data = internal::r_coerce<RAWSXP ,STRSXP>( x ) ; valid = true ; buffer_ready = false ; return *this ; }
129-
inline String& operator=( bool x ){ data = internal::r_coerce<LGLSXP ,STRSXP>( x ) ; valid = true ; buffer_ready = false ; return *this ; }
130-
inline String& operator=( Rcomplex x){ data = internal::r_coerce<CPLXSXP,STRSXP>( x ) ; valid = true ; buffer_ready = false ; return *this ; }
131-
inline String& operator=( SEXP x){ data = x ; valid = true ; buffer_ready = false ; return *this ; }
132-
inline String& operator=( const StringProxy& proxy){ data = proxy.get() ; valid = true ; buffer_ready=false ; return *this ; }
133-
inline String& operator=( const String& other ){ data = other.get_sexp() ; valid = true ; buffer_ready = false ; return *this ; }
130+
String( int x ) : data( internal::r_coerce<INTSXP,STRSXP>(x) ), valid(true), buffer_ready(false), enc(CE_NATIVE){Rcpp_PreserveObject( data );}
131+
String( double x ) : data( internal::r_coerce<REALSXP,STRSXP>(x) ), valid(true), buffer_ready(false), enc(CE_NATIVE){Rcpp_PreserveObject( data );}
132+
String( bool x ) : data( internal::r_coerce<LGLSXP,STRSXP>(x) ), valid( true ) , buffer_ready(false), enc(CE_NATIVE){Rcpp_PreserveObject( data );}
133+
String( Rcomplex x ) : data( internal::r_coerce<CPLXSXP,STRSXP>(x) ), valid( true ), buffer_ready(false), enc(CE_NATIVE){Rcpp_PreserveObject( data );}
134+
String( Rbyte x ) : data( internal::r_coerce<RAWSXP,STRSXP>(x) ), valid(true), buffer_ready(false), enc(CE_NATIVE){Rcpp_PreserveObject( data );}
135+
136+
~String() {
137+
Rcpp_ReleaseObject( data );
138+
data = R_NilValue ;
139+
}
140+
141+
142+
inline String& operator=( int x ){ data = Rcpp_ReplaceObject( data, internal::r_coerce<INTSXP ,STRSXP>( x )) ; valid = true ; buffer_ready = false ; return *this ; }
143+
inline String& operator=( double x ){ data = Rcpp_ReplaceObject( data, internal::r_coerce<REALSXP,STRSXP>( x )) ; valid = true ; buffer_ready = false ; return *this ; }
144+
inline String& operator=( Rbyte x ){ data = Rcpp_ReplaceObject( data, internal::r_coerce<RAWSXP ,STRSXP>( x )) ; valid = true ; buffer_ready = false ; return *this ; }
145+
inline String& operator=( bool x ){ data = Rcpp_ReplaceObject( data, internal::r_coerce<LGLSXP ,STRSXP>( x )) ; valid = true ; buffer_ready = false ; return *this ; }
146+
inline String& operator=( Rcomplex x){ data = Rcpp_ReplaceObject( data, internal::r_coerce<CPLXSXP,STRSXP>( x )) ; valid = true ; buffer_ready = false ; return *this ; }
147+
inline String& operator=( SEXP x){ data = Rcpp_ReplaceObject( data, x ) ; valid = true ; buffer_ready = false ; return *this ; }
148+
inline String& operator=( const StringProxy& proxy){ data = Rcpp_ReplaceObject( data, proxy.get() ) ; valid = true ; buffer_ready=false ; return *this ; }
149+
inline String& operator=( const String& other ){ data = Rcpp_ReplaceObject( data, other.get_sexp() ) ; valid = true ; buffer_ready = false ; return *this ; }
134150
inline String& operator=( const std::string& s){ buffer = s ; valid = false ; buffer_ready = true ; return *this ; }
135151
inline String& operator=( const char* s){ buffer = s ; valid = false ; buffer_ready = true ; return *this ; }
136152

137153
private:
138154
template <typename T>
139155
inline String& assign_wide_string( const T& s){
140-
data = internal::make_charsexp( s ) ;
156+
data = Rcpp_ReplaceObject( data, internal::make_charsexp( s )) ;
141157
valid = true ;
142158
buffer_ready = false ;
143159
return *this ;
@@ -169,7 +185,7 @@ namespace Rcpp {
169185
const char* buf = CHAR( data );
170186
std::wstring tmp( buf, buf + strlen(buf ) ) ;
171187
tmp += s ;
172-
data = internal::make_charsexp( tmp ) ;
188+
data = Rcpp_ReplaceObject( data, internal::make_charsexp( tmp ) ) ;
173189
valid = true ;
174190
buffer_ready = false ;
175191
return *this ;
@@ -183,22 +199,22 @@ namespace Rcpp {
183199
inline String& operator+=( const String& other ){
184200
RCPP_STRING_DEBUG( "String::operator+=( const char*)" ) ;
185201
if( is_na() ) return *this ;
186-
if( other.is_na() ){ data = NA_STRING ; valid = true ; buffer_ready = false ; return *this ; }
202+
if( other.is_na() ){ data = Rcpp_ReplaceObject( data, NA_STRING) ; valid = true ; buffer_ready = false ; return *this ; }
187203
setBuffer() ; buffer += other ; valid = false ;
188204
return *this ;
189205
}
190206
inline String& operator+=( const StringProxy& proxy){
191207
RCPP_STRING_DEBUG( "String::operator+=( const StringProxy& )" ) ;
192208
if( is_na() ) return *this ;
193209
SEXP proxy_sexp = proxy ;
194-
if( proxy_sexp == NA_STRING ) { data = NA_STRING ; valid = true; buffer_ready = false ; return *this ;}
210+
if( proxy_sexp == NA_STRING ) { data = Rcpp_ReplaceObject( data, NA_STRING) ; valid = true; buffer_ready = false ; return *this ;}
195211
setBuffer() ; buffer += CHAR(proxy_sexp) ; valid = false ;
196212
return *this ;
197213
}
198214
inline String& operator+=( SEXP x){
199215
RCPP_STRING_DEBUG( "String::operator+=( SEXP )" ) ;
200216
if( is_na() ) return *this ;
201-
if( x == NA_STRING ) { data = NA_STRING ; valid = true; buffer_ready = false ; return *this ;}
217+
if( x == NA_STRING ) { data = Rcpp_ReplaceObject( data, NA_STRING ) ; valid = true; buffer_ready = false ; return *this ;}
202218
setBuffer() ; buffer += CHAR(x) ; valid = false ;
203219
return *this ;
204220
}
@@ -324,7 +340,8 @@ namespace Rcpp {
324340

325341

326342
inline void set_na(){
327-
data = NA_STRING ; valid = true; buffer_ready = false ;
343+
data = Rcpp_ReplaceObject(data, NA_STRING) ;
344+
valid = true; buffer_ready = false ;
328345
}
329346

330347

@@ -368,9 +385,10 @@ namespace Rcpp {
368385
enc = encoding;
369386

370387
if (valid) {
371-
data = Rf_mkCharCE(Rf_translateCharUTF8(data), encoding);
388+
data = Rcpp_ReplaceObject(data, Rf_mkCharCE(Rf_translateCharUTF8(data), encoding) );
372389
} else {
373390
data = Rf_mkCharCE(buffer.c_str(), encoding) ;
391+
Rcpp_PreserveObject( data );
374392
valid = true ;
375393
}
376394
}
@@ -430,6 +448,7 @@ namespace Rcpp {
430448
RCPP_STRING_DEBUG( "setData" ) ;
431449
if(!valid) {
432450
data = Rf_mkCharCE(buffer.c_str(), enc) ;
451+
Rcpp_PreserveObject( data );
433452
valid = true ;
434453
}
435454
}
@@ -476,6 +495,7 @@ namespace Rcpp {
476495
RCPP_STRING_DEBUG( "wrap<String>()" ) ;
477496
Shield<SEXP> res( Rf_allocVector( STRSXP, 1 ) ) ;
478497
SEXP data = object.get_sexp();
498+
Rcpp_PreserveObject( data );
479499
SET_STRING_ELT( res, 0, data ) ;
480500
return res ;
481501
}

0 commit comments

Comments
 (0)