|
Rcpp Version 0.9.10
|
00001 // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*- 00002 // 00003 // S4.cpp: Rcpp R/C++ interface class library -- S4 objects 00004 // 00005 // Copyright (C) 2010 - 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 <Rcpp/Reference.h> 00023 #include <Rcpp/exceptions.h> 00024 #include <Rcpp/Vector.h> 00025 00026 namespace Rcpp { 00027 00028 Reference::Reference() : S4(){} 00029 00030 Reference::Reference(SEXP x) : S4(){ 00031 set( x) ; 00032 } 00033 00034 Reference::Reference( const Reference& other) : S4(){ 00035 setSEXP( other.asSexp() ) ; 00036 } 00037 00038 Reference::Reference( const RObject::SlotProxy& proxy ) : S4() { 00039 set( proxy ) ; 00040 } 00041 Reference::Reference( const RObject::AttributeProxy& proxy ) : S4() { 00042 set( proxy ) ; 00043 } 00044 00045 Reference& Reference::operator=( const Reference& other){ 00046 setSEXP( other.asSexp() ) ; 00047 return *this ; 00048 } 00049 00050 Reference& Reference::operator=( SEXP other ) { 00051 set( other ) ; 00052 return *this ; 00053 } 00054 00055 Reference::Reference( const std::string& klass ) : S4(){ 00056 // using callback to R as apparently R_do_new_object always makes the same environment 00057 SEXP newSym = Rf_install("new"); 00058 SEXP call = PROTECT( Rf_lang2( newSym, Rf_mkString( klass.c_str() ) ) ) ; 00059 setSEXP( Rcpp::internal::try_catch( call ) ) ; 00060 UNPROTECT(1) ; // call 00061 } 00062 00063 void Reference::set( SEXP x) { 00064 // TODO: check that x is of a reference class 00065 if( ! ::Rf_isS4(x) ){ 00066 throw not_reference() ; 00067 } else{ 00068 setSEXP( x) ; 00069 } 00070 } 00071 00072 Reference::FieldProxy::FieldProxy( const Reference& v, const std::string& name) : 00073 parent(v), field_name(name) {} 00074 00075 Reference::FieldProxy& Reference::FieldProxy::operator=(const FieldProxy& rhs){ 00076 set( rhs.get() ) ; 00077 return *this ; 00078 } 00079 00080 00081 SEXP Reference::FieldProxy::get() const { 00082 // TODO: get the field 00083 00084 SEXP call = PROTECT( Rf_lang3( 00085 R_DollarSymbol, 00086 const_cast<Reference&>(parent).asSexp(), 00087 Rf_mkString( field_name.c_str() ) 00088 ) ) ; 00089 return Rcpp::internal::try_catch( call ) ; 00090 UNPROTECT(1) ; 00091 } 00092 00093 void Reference::FieldProxy::set( SEXP x) const { 00094 PROTECT(x); 00095 SEXP dollarGetsSym = Rf_install( "$<-"); 00096 SEXP call = PROTECT( Rf_lang4( 00097 dollarGetsSym, 00098 const_cast<Reference&>(parent).asSexp(), 00099 Rf_mkString( field_name.c_str() ), 00100 x 00101 ) ) ; 00102 const_cast<Reference&>(parent).setSEXP( Rf_eval( call, R_GlobalEnv ) ); 00103 UNPROTECT(2) ; 00104 } 00105 00106 Reference::FieldProxy Reference::field( const std::string& name) const { 00107 return FieldProxy( *this, name ); 00108 } 00109 00110 } // namespace Rcpp