Rcpp Version 0.9.10
S4.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 // 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/S4.h>
00023 #include <Rcpp/exceptions.h>
00024 #include <Rcpp/Vector.h>
00025 
00026 namespace Rcpp {
00027 
00028     S4::S4() : RObject(){}
00029         
00030     S4::S4(SEXP x) : RObject(){
00031         set( x) ;
00032     }
00033         
00034     S4::S4( const S4& other) : RObject(){
00035         setSEXP( other.asSexp() ) ;     
00036     }
00037         
00038     S4::S4( const RObject::SlotProxy& proxy ) : RObject() {
00039         set( proxy ) ;
00040     }
00041     S4::S4( const RObject::AttributeProxy& proxy ) : RObject() {
00042         set( proxy ) ;
00043     }
00044         
00045     S4& S4::operator=( const S4& other){
00046         setSEXP( other.asSexp() ) ;
00047         return *this ;
00048     }
00049         
00050     S4& S4::operator=( SEXP other ) {
00051         set( other ) ;
00052         return *this ;
00053     }
00054         
00055     S4::S4( const std::string& klass ) {
00056         SEXP oo = PROTECT( R_do_new_object(R_do_MAKE_CLASS(klass.c_str())) ) ;
00057         if (!Rf_inherits(oo, klass.c_str())) {
00058             UNPROTECT( 1) ;
00059             throw S4_creation_error( klass ) ;
00060         }
00061         setSEXP( oo ) ;
00062         UNPROTECT( 1) ; /* oo */
00063     }
00064         
00065     bool S4::is( const std::string& clazz ) {
00066         CharacterVector cl = attr("class");
00067                 
00068         // simple test for exact match
00069         if( ! clazz.compare( cl[0] ) ) return true ;
00070                 
00071         try{
00072             SEXP containsSym = ::Rf_install("contains");
00073             CharacterVector res(::Rf_getAttrib(
00074                                     ::R_do_slot(::R_getClassDef(CHAR(::Rf_asChar(as<SEXP>(cl)))),
00075                                                 containsSym),
00076                                     R_NamesSymbol));
00077 
00078             // 
00079             // mimic the R call: 
00080             // names( slot( getClassDef( cl ), "contains" ) )
00081             // 
00082             // SEXP slotSym = Rf_install( "slot" ), // cannot cause gc() once in symbol table
00083             //     getClassDefSym = Rf_install( "getClassDef" );
00084             // CharacterVector res = internal::try_catch(Rf_lang2(R_NamesSymbol,
00085             //                                                    Rf_lang3(slotSym,
00086             //                                                             Rf_lang2( getClassDefSym, cl ), 
00087             //                                                             Rf_mkString( "contains" )))) ;
00088             return any( res.begin(), res.end(), clazz.c_str() ) ;
00089         } catch( ... ){
00090             // we catch eval_error and also not_compatible when 
00091             // contains is NULL
00092         }
00093         return false ;
00094                 
00095     }
00096         
00097     void S4::set( SEXP x) {
00098         if( ! ::Rf_isS4(x) ){
00099             throw not_s4() ;
00100         } else{
00101             setSEXP( x) ;
00102         }
00103     }
00104         
00105 } // namespace Rcpp
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Defines