[Rcpp-commits] r655 - in pkg: inst inst/unitTests src/Rcpp

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Wed Feb 10 11:36:53 CET 2010


Author: romain
Date: 2010-02-10 11:36:52 +0100 (Wed, 10 Feb 2010)
New Revision: 655

Modified:
   pkg/inst/ChangeLog
   pkg/inst/unitTests/runit.GenericVector.R
   pkg/src/Rcpp/SEXP_Vector.h
Log:
+ SEXP_Vector.push_{back,front}

Modified: pkg/inst/ChangeLog
===================================================================
--- pkg/inst/ChangeLog	2010-02-10 09:03:46 UTC (rev 654)
+++ pkg/inst/ChangeLog	2010-02-10 10:36:52 UTC (rev 655)
@@ -1,5 +1,12 @@
 2010-02-10  Romain Francois <romain at r-enthusiasts.com>
 
+	* src/Rcpp/SEXP_Vector.h: SEXP_Vector (and therefore 
+	ExpressionVector and GenericVector, a.k.a List) gain 
+	methods push_front and push_back that are templated and 
+	use the implicit wrap idiom to add an element to the front
+	or to the back of the list, pushing other elements. Internally
+	the SEXP is actually copied.
+
 	* src/Rcpp/VectorBase.h: VectorBase gains a version of 
 	offset to support retrieving the offset of a given name of a
 	vector: offset( const std::string& name)

Modified: pkg/inst/unitTests/runit.GenericVector.R
===================================================================
--- pkg/inst/unitTests/runit.GenericVector.R	2010-02-10 09:03:46 UTC (rev 654)
+++ pkg/inst/unitTests/runit.GenericVector.R	2010-02-10 10:36:52 UTC (rev 655)
@@ -153,3 +153,36 @@
 	checkEquals( funx( d ), sum(1:10), msg = "List names based indexing" )
 }
 
+test.List.push.back <- function(){
+	
+	funx <- cfunction( signature(x = "list"), 
+	'
+	List list(x) ;
+	list.push_back( 10 ) ;
+	list.push_back( Named( "foo", "bar" ) ) ;
+	return list ;
+	', Rcpp = TRUE, includes = "using namespace Rcpp;" )
+	d <- list( x = 1:10, y = letters[1:10] )
+	res <- funx( d )
+	checkEquals( res,
+		list( x = 1:10, y = letters[1:10], 10L, foo = "bar" ), 
+		msg = "List.push_back" )
+}
+
+test.List.push.front <- function(){
+	
+	funx <- cfunction( signature(x = "list"), 
+	'
+	List list(x) ;
+	list.push_front( 10 ) ;
+	list.push_front( Named( "foo", "bar" ) ) ;
+	return list ;
+	', Rcpp = TRUE, includes = "using namespace Rcpp;" )
+	d <- list( x = 1:10, y = letters[1:10] )
+	res <- funx( d )
+	checkEquals( res,
+		list( foo = "bar", 10L, x = 1:10, y = letters[1:10] ), 
+		msg = "List.push_front" )
+}
+
+

Modified: pkg/src/Rcpp/SEXP_Vector.h
===================================================================
--- pkg/src/Rcpp/SEXP_Vector.h	2010-02-10 09:03:46 UTC (rev 654)
+++ pkg/src/Rcpp/SEXP_Vector.h	2010-02-10 10:36:52 UTC (rev 655)
@@ -168,8 +168,92 @@
 	void assign( InputIterator first, InputIterator last){
 		setSEXP( r_cast<RTYPE>( wrap( first, last) ) ) ;
 	}
+	
+	template <typename WRAPPABLE>
+	void push_back( const WRAPPABLE& t){
+		push_back_sexp( wrap(t), "" ) ;
+	}
+	void push_back( const Named& t){
+		push_back_sexp( t.getSEXP() , t.getTag() ) ;
+	}
 
+	template <typename WRAPPABLE>
+	void push_front( const WRAPPABLE& t){
+		push_front_sexp( wrap(t), false, "" ) ;
+	}
+	void push_front( const Named& t){
+		push_front_sexp( t.getSEXP() , true, t.getTag() ) ;
+	}
+
+private:
 	
+	void push_back_sexp( SEXP t, bool named, const std::string& name ){
+		if( isNULL() ){ 
+			set_single( t, named, name );
+		} else {
+			/* not sure we can avoid the copy. R does the same
+			   with lengthgets at builtin.c */
+			R_len_t n = size() ;
+			SEXP x = PROTECT( Rf_allocVector( RTYPE, n+1 ) ) ;
+			R_len_t i=0 ;
+			for( ; i<n; i++){
+				SET_VECTOR_ELT( x, i, VECTOR_ELT(m_sexp, i ) ) ;
+			}
+			SET_VECTOR_ELT( x, i, t ) ;
+			SEXP names = RCPP_GET_NAMES( m_sexp ) ;
+			if( names != R_NilValue ){
+				SEXP x_names = PROTECT( Rf_allocVector( STRSXP, n+1) );
+				for( i=0; i<n; i++){
+					SET_STRING_ELT( x_names, i, STRING_ELT(names, i ) ) ;
+				}
+				SET_STRING_ELT(x_names, i, Rf_mkChar(name.c_str()) ) ;
+				Rf_setAttrib( x, Rf_install("names"), x_names );
+				UNPROTECT(1) ; /* x_names */
+			}
+			setSEXP( x ); 
+			UNPROTECT(1) ; /* x */
+		}
+	}
+	
+	void push_front_sexp( SEXP t, bool named, const std::string& name ){
+		if( isNULL() ){ 
+			set_single( t, named, name );
+		} else {
+			/* not sure we can avoid the copy. R does the same
+			   with lengthgets at builtin.c */
+			R_len_t n = size() ;
+			SEXP x = PROTECT( Rf_allocVector( RTYPE, n+1 ) ) ;
+			R_len_t i=0 ;
+			SET_VECTOR_ELT( x, 0, t ) ;
+			for(i=0 ; i<n; i++){
+				SET_VECTOR_ELT( x, i+1, VECTOR_ELT(m_sexp, i ) ) ;
+			}
+			SEXP names = RCPP_GET_NAMES( m_sexp ) ;
+			if( names != R_NilValue ){
+				SEXP x_names = PROTECT( Rf_allocVector( STRSXP, n+1) );
+				for( i=0; i<n; i++){
+					SET_STRING_ELT( x_names, i+1, STRING_ELT(names, i ) ) ;
+				}
+				SET_STRING_ELT(x_names, 0, Rf_mkChar(name.c_str()) ) ;
+				Rf_setAttrib( x, Rf_install("names"), x_names );
+				UNPROTECT(1) ; /* x_names */
+			}
+			setSEXP( x ); 
+			UNPROTECT(1) ; /* x */
+		}
+	}
+
+	void set_single( SEXP t, bool named, const std::string& name ){
+		SEXP x = PROTECT( Rf_allocVector( RTYPE, 1) );
+		SET_VECTOR_ELT( x, 0, t ) ;
+		if( named ){
+			SEXP names = PROTECT( Rf_mkString( name.c_str() ) ) ;
+			Rf_setAttrib( x, Rf_install("names"), names) ;
+			UNPROTECT(1) ; /* names */
+		}
+		setSEXP( x ) ;
+		UNPROTECT(1) ;
+	}
 }   ;
 
 typedef SEXP_Vector<VECSXP> GenericVector ;



More information about the Rcpp-commits mailing list