|
Rcpp Version 0.9.10
|
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