1 // Copyright (C) 2013 Romain Francois
2 //
3 // This file is part of Rcpp.
4 //
5 // Rcpp is free software: you can redistribute it and/or modify it
6 // under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // Rcpp is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Rcpp.  If not, see <http://www.gnu.org/licenses/>.
17 
18 #ifndef Rcpp_proxy_AttributeProxy_h
19 #define Rcpp_proxy_AttributeProxy_h
20 
21 namespace Rcpp{
22 
23 template <typename CLASS>
24 class AttributeProxyPolicy {
25 public:
26 
27     class AttributeProxy : public GenericProxy<AttributeProxy> {
28     public:
AttributeProxy(CLASS & v,const std::string & name)29         AttributeProxy( CLASS& v, const std::string& name)
30             : parent(v), attr_name(Rf_install(name.c_str()))
31         {}
32 
33         AttributeProxy& operator=(const AttributeProxy& rhs){
34             if( this != &rhs ) set( rhs.get() ) ;
35             return *this ;
36         }
37 
38         template <typename T> AttributeProxy& operator=(const T& rhs);
39 
40         template <typename T> operator T() const;
41 
42         inline operator SEXP() const;
43 
44     private:
45         CLASS& parent;
46         SEXP attr_name ;
47 
get()48         SEXP get() const {
49             return Rf_getAttrib( parent, attr_name ) ;
50         }
set(SEXP x)51         void set(SEXP x ){
52             Rf_setAttrib( parent, attr_name, Shield<SEXP>(x) ) ;
53         }
54     } ;
55 
56     class const_AttributeProxy : public GenericProxy<const_AttributeProxy> {
57     public:
const_AttributeProxy(const CLASS & v,const std::string & name)58         const_AttributeProxy( const CLASS& v, const std::string& name)
59             : parent(v), attr_name(Rf_install(name.c_str())){}
60 
61         template <typename T> operator T() const;
62         inline operator SEXP() const;
63 
64     private:
65         const CLASS& parent;
66         SEXP attr_name ;
67 
get()68         SEXP get() const {
69             return Rf_getAttrib( parent, attr_name ) ;
70         }
71     } ;
72 
attr(const std::string & name)73     AttributeProxy attr( const std::string& name){
74         return AttributeProxy( static_cast<CLASS&>( *this ), name ) ;
75     }
attr(const std::string & name)76     const_AttributeProxy attr( const std::string& name) const {
77         return const_AttributeProxy( static_cast<const CLASS&>( *this ), name ) ;
78     }
79 
attributeNames()80     std::vector<std::string> attributeNames() const {
81         std::vector<std::string> v ;
82         SEXP attrs = ATTRIB( static_cast<const CLASS&>(*this).get__());
83         while( attrs != R_NilValue ){
84             v.push_back( std::string(CHAR(PRINTNAME(TAG(attrs)))) ) ;
85             attrs = CDR( attrs ) ;
86         }
87         return v ;
88     }
89 
hasAttribute(const std::string & attr)90     bool hasAttribute( const std::string& attr) const {
91         SEXP attrs = ATTRIB(static_cast<const CLASS&>(*this).get__());
92         while( attrs != R_NilValue ){
93             if( attr == CHAR(PRINTNAME(TAG(attrs))) ){
94                 return true ;
95             }
96             attrs = CDR( attrs ) ;
97         }
98         return false; /* give up */
99     }
100 
101 
102 } ;
103 
104 }
105 #endif
106