Rcpp Version 0.9.10
RObject.cpp
Go to the documentation of this file.
00001 // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*-
00002 //
00003 // RObject.cpp: Rcpp R/C++ interface class library -- R Object support
00004 //
00005 // Copyright (C) 2009 - 2011 Dirk Eddelbuettel and Romain Francois
00006 //
00007 // This file is part of Rcpp.
00008 //
00009 // Rcpp is free software: you can redistribute it and/or modify it
00010 // under the terms of the GNU General Public License as published by
00011 // the Free Software Foundation, either version 2 of the License, or
00012 // (at your option) any later version.
00013 //
00014 // Rcpp is distributed in the hope that it will be useful, but
00015 // WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 // GNU General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU General Public License
00020 // along with Rcpp.  If not, see <http://www.gnu.org/licenses/>.
00021 
00022 #include <RcppCommon.h>
00023 #include <Rcpp/RObject.h>
00024 
00025 namespace Rcpp {
00026     namespace internal{
00027 
00028         SEXPstack::SEXPstack() : 
00029             stack( Rf_allocVector(VECSXP,1000) ), 
00030             data( get_vector_ptr(stack) ), 
00031             len( 1000 ), 
00032             top( 0 )
00033         {
00034             R_PreserveObject( stack ) ;  
00035         }
00036     
00037         void SEXPstack::preserve( SEXP object){
00038             if( top == len-1) grow() ;
00039             SET_VECTOR_ELT( stack, top++, object ) ;
00040         }
00041     
00042         void SEXPstack::release( SEXP object ){
00043             int n = top - 1 ;
00044             while( n > -1 && data[n] != object ) n-- ;
00045             while( n < top - 1 ){ 
00046                 data[n] = data[n+1] ; 
00047                 n++ ;
00048             }
00049             data[--top] = R_NilValue ;
00050         }
00051     
00052         void SEXPstack::grow( ){
00053             int newsize = len * 2 ;
00054             SEXP x = PROTECT( Rf_allocVector( VECSXP, newsize ) ) ;
00055             SEXP* x_data = get_vector_ptr( x) ;
00056             std::copy( data, data + len, x_data ) ;
00057             stack = x ;
00058             UNPROTECT(1);
00059             data = x_data ;
00060         }
00061     }
00062 
00063     // internal::SEXPstack RObject::PPstack ;    
00064     
00065     void RObject::setSEXP(SEXP x){
00066         RCPP_DEBUG_1( "RObject::setSEXP(SEXP = <%p> )", x ) ; 
00067     
00068         /* if we are setting to the same SEXP as we already have, do nothing */
00069         if( x != m_sexp ){
00070                 
00071             /* the previous SEXP was not NULL, so release it */
00072             release() ;
00073                 
00074             /* set the SEXP */
00075             m_sexp = x ;
00076                 
00077             /* the new SEXP is not NULL, so preserve it */
00078             preserve() ;
00079                         
00080             update() ;
00081         }
00082     }
00083 
00084     /* copy constructor */
00085     RObject::RObject( const RObject& other ){
00086         SEXP x = other.asSexp() ;       
00087         setSEXP( x ) ; 
00088     }
00089 
00090     RObject& RObject::operator=( const RObject& other){
00091         SEXP x = other.asSexp() ;       
00092         setSEXP( x ) ; 
00093         return *this ;
00094     }
00095 
00096     RObject& RObject::operator=( SEXP other ){
00097         setSEXP( other ) ; 
00098         return *this ;
00099     }
00100 
00101     RObject::~RObject() {
00102         release() ;
00103         logTxt("~RObject");
00104     }
00105 
00106     std::vector<std::string> RObject::attributeNames() const {
00107         /* inspired from do_attributes@attrib.c */
00108         
00109         std::vector<std::string> v ;
00110         SEXP attrs = ATTRIB(m_sexp);
00111         while( attrs != R_NilValue ){
00112             v.push_back( std::string(CHAR(PRINTNAME(TAG(attrs)))) ) ;
00113             attrs = CDR( attrs ) ;
00114         }
00115         return v ;
00116     }
00117 
00118     bool RObject::hasAttribute( const std::string& attr) const {
00119         SEXP attrs = ATTRIB(m_sexp);
00120         while( attrs != R_NilValue ){
00121             if( attr == CHAR(PRINTNAME(TAG(attrs))) ){
00122                 return true ;
00123             }
00124             attrs = CDR( attrs ) ;
00125         }
00126         return false; /* give up */
00127     }
00128 
00129     RObject::SlotProxy::SlotProxy( const RObject& v, const std::string& name) : 
00130         parent(v), slot_name(name)
00131     {
00132         SEXP nameSym = Rf_install(name.c_str());            // cannot be gc()'ed  once in symbol table
00133         if( !R_has_slot( v, nameSym) ){
00134             throw no_such_slot() ; 
00135         }
00136     }
00137 
00138     RObject::SlotProxy& RObject::SlotProxy::operator=(const SlotProxy& rhs){
00139         set( rhs.get() ) ;
00140         return *this ;
00141     }
00142 
00143 
00144     SEXP RObject::SlotProxy::get() const {
00145         SEXP slotSym = Rf_install( slot_name.c_str() );     // cannot be gc()'ed  once in symbol table
00146         return R_do_slot( parent, slotSym ) ;       
00147     }
00148 
00149     void RObject::SlotProxy::set( SEXP x) const {
00150         SEXP slotnameSym = Rf_install( slot_name.c_str() ); // cannot be gc()'ed  once in symbol table
00151         // the SEXP might change (.Data)
00152         SEXP new_obj = PROTECT( R_do_slot_assign(parent, slotnameSym, x) ) ;
00153         const_cast<RObject&>(parent).setSEXP( new_obj ) ;
00154         UNPROTECT(1) ;
00155     }
00156 
00157     SEXP RObject::AttributeProxy::get() const {
00158         SEXP attrnameSym = Rf_install( attr_name.c_str() ); // cannot be gc()'ed  once in symbol table
00159         return Rf_getAttrib( parent, attrnameSym ) ;
00160     }
00161 
00162     void RObject::AttributeProxy::set(SEXP x) const{
00163         SEXP attrnameSym = Rf_install( attr_name.c_str() ); // cannot be gc()'ed  once in symbol table
00164 #if RCPP_DEBUG_LEVEL > 0
00165         RCPP_DEBUG_1( "RObject::AttributeProxy::set() before = <%p>", parent.asSexp() ) ;
00166         SEXP res = Rf_setAttrib( parent, attrnameSym, x ) ;
00167         RCPP_DEBUG_1( "RObject::AttributeProxy::set() after  = <%p>", res ) ;
00168 #else
00169         Rf_setAttrib( parent, attrnameSym, x ) ;
00170 #endif
00171     }
00172 
00173     RObject::AttributeProxy::AttributeProxy( const RObject& v, const std::string& name) :
00174         parent(v), attr_name(name) {}
00175 
00176     RObject::AttributeProxy& RObject::AttributeProxy::operator=(const AttributeProxy& rhs){
00177         set( rhs.get() ) ;
00178         return *this ;
00179     }
00180 
00181     RObject::AttributeProxy RObject::attr( const std::string& name) const{
00182         return AttributeProxy( *this, name)  ;
00183     }
00184 
00185     /* S4 */
00186 
00187     bool RObject::hasSlot(const std::string& name) const {
00188         if( !Rf_isS4(m_sexp) ) throw not_s4() ;
00189         return R_has_slot( m_sexp, Rf_mkString(name.c_str()) ) ;
00190     }
00191 
00192     RObject::SlotProxy RObject::slot(const std::string& name) const {
00193         if( !Rf_isS4(m_sexp) ) throw not_s4() ;
00194         return SlotProxy( *this, name ) ;
00195     }
00196 
00197 } // namespace Rcpp
00198 
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Defines