1 // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*- 2 // 3 // proxy.h: Rcpp R/C++ interface class library -- proxies 4 // 5 // Copyright (C) 2010 - 2018 Dirk Eddelbuettel and Romain Francois 6 // 7 // This file is part of Rcpp. 8 // 9 // Rcpp is free software: you can redistribute it and/or modify it 10 // under the terms of the GNU General Public License as published by 11 // the Free Software Foundation, either version 2 of the License, or 12 // (at your option) any later version. 13 // 14 // Rcpp is distributed in the hope that it will be useful, but 15 // WITHOUT ANY WARRANTY; without even the implied warranty of 16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 // GNU General Public License for more details. 18 // 19 // You should have received a copy of the GNU General Public License 20 // along with Rcpp. If not, see <http://www.gnu.org/licenses/>. 21 22 #ifndef Rcpp__vector__proxy_h 23 #define Rcpp__vector__proxy_h 24 25 namespace Rcpp{ 26 namespace internal{ 27 28 template <int RTYPE, template <class> class StoragePolicy> 29 class simple_name_proxy { 30 public: 31 typedef ::Rcpp::Vector<RTYPE, StoragePolicy> VECTOR ; 32 typedef typename ::Rcpp::traits::storage_type<RTYPE>::type CTYPE ; 33 simple_name_proxy(VECTOR & v,const std::string & name_)34 simple_name_proxy( VECTOR& v, const std::string& name_) : 35 parent(v), name(name_){} ; simple_name_proxy(const simple_name_proxy & other)36 simple_name_proxy( const simple_name_proxy& other ) : 37 parent(other.parent), name(other.name){} ; ~simple_name_proxy()38 ~simple_name_proxy() {} ; 39 40 simple_name_proxy& operator=( CTYPE rhs ){ 41 set( rhs ) ; 42 return *this ; 43 } 44 simple_name_proxy& operator=( const simple_name_proxy& other){ 45 set( other.get() ) ; 46 return *this ; 47 } 48 49 template <typename T> 50 simple_name_proxy& operator=( const T& rhs ){ 51 set( caster<T,CTYPE>(rhs) ) ; 52 return *this ; 53 } 54 55 // TODO: other operators +=, -=, ... 56 CTYPE()57 operator CTYPE() const { 58 return get() ; 59 } 60 61 // this helps wrap, for example : wrap( x["foo"] ) SEXP()62 operator SEXP() const { 63 return ::Rcpp::wrap(get()) ; 64 } 65 66 private: 67 VECTOR& parent ; 68 std::string name; set(CTYPE rhs)69 void set( CTYPE rhs ){ 70 R_xlen_t index = 0 ; 71 try{ 72 index = parent.offset(name) ; 73 parent[ index ] = rhs ; 74 } catch( const index_out_of_bounds& ex ){ 75 parent.push_back( rhs, name ); 76 } 77 } get()78 CTYPE get() const { 79 return parent[ parent.offset(name) ]; 80 } 81 } ; 82 83 template <int RTYPE, template <class> class StoragePolicy> 84 class string_name_proxy{ 85 public: 86 typedef typename ::Rcpp::Vector<RTYPE, StoragePolicy> VECTOR ; 87 typedef const char* iterator ; 88 typedef const char& reference ; 89 string_name_proxy(VECTOR & v,const std::string & name_)90 string_name_proxy( VECTOR& v, const std::string& name_) : 91 parent(v), name(name_){} ; string_name_proxy(const string_name_proxy & other)92 string_name_proxy( const string_name_proxy& other ) : 93 parent(other.parent), name(other.name){} ; ~string_name_proxy()94 ~string_name_proxy(){} ; 95 96 string_name_proxy& operator=( const std::string& rhs ){ 97 set( rhs ) ; 98 return *this ; 99 } 100 string_name_proxy& operator=( const string_name_proxy& other){ 101 set( other.get() ) ; 102 return *this ; 103 } 104 105 operator char* () const { 106 return get() ; 107 } 108 SEXP()109 operator SEXP() const { 110 return ::Rf_mkString(get()) ; 111 } 112 begin()113 inline iterator begin() { return get() ; } end()114 inline iterator end(){ return begin() + size() ; } 115 inline reference operator[]( R_xlen_t i ){ return *( get() + i ) ; } size()116 inline R_xlen_t size(){ return strlen( get() ) ; } 117 118 private: 119 VECTOR& parent ; 120 std::string name; set(const std::string & rhs)121 void set( const std::string& rhs ){ 122 R_xlen_t index = 0 ; 123 try{ 124 index = parent.offset(name) ; 125 parent[ index ] = rhs ; 126 } catch( const index_out_of_bounds& ex ){ 127 parent.push_back( rhs, name ); 128 } 129 } get()130 char* get() const { 131 return parent[ parent.offset(name) ]; 132 } 133 134 } ; 135 136 template <int RTYPE, template <class> class StoragePolicy> 137 class generic_name_proxy { 138 public: 139 typedef ::Rcpp::Vector<RTYPE, StoragePolicy> VECTOR ; generic_name_proxy(VECTOR & v,const std::string & name_)140 generic_name_proxy( VECTOR& v, const std::string& name_) : 141 parent(v), name(name_){} generic_name_proxy(const generic_name_proxy & other)142 generic_name_proxy( const generic_name_proxy& other ) : 143 parent(other.parent), name(other.name){} ~generic_name_proxy()144 ~generic_name_proxy(){} ; 145 146 generic_name_proxy& operator=( SEXP rhs ){ 147 set( rhs ) ; 148 return *this ; 149 } 150 generic_name_proxy& operator=( const generic_name_proxy& other){ 151 set( other.get() ) ; 152 return *this ; 153 } 154 155 template <typename T> 156 generic_name_proxy& operator=( const T& rhs ){ 157 set(Shield<SEXP>(wrap(rhs))); 158 return *this ; 159 } 160 161 // TODO: other operators +=, -=, ... 162 SEXP()163 operator SEXP() const { 164 return get() ; 165 } 166 167 template <typename T> T()168 operator T() const { 169 #if RCPP_DEBUG_LEVEL > 0 170 SEXP res = get() ; 171 RCPP_DEBUG_1( "generic_name_proxy::get() = <%p> ", res ) ; 172 return ::Rcpp::as<T>( res ) ; 173 #else 174 return ::Rcpp::as<T>( get() ) ; 175 #endif 176 } 177 178 private: 179 VECTOR& parent ; 180 std::string name; set(SEXP rhs)181 void set( SEXP rhs ){ 182 R_xlen_t index = 0 ; 183 try{ 184 index = parent.offset(name) ; 185 parent[ index ] = rhs ; 186 } catch( const index_out_of_bounds& ex ){ 187 parent.push_back( rhs, name ); 188 } 189 } get()190 SEXP get() const { 191 return parent[ parent.offset(name) ]; 192 } 193 } ; 194 } 195 196 namespace traits { 197 198 template <int RTYPE, template <class> class StoragePolicy> 199 struct r_vector_name_proxy{ 200 typedef typename ::Rcpp::internal::simple_name_proxy<RTYPE, StoragePolicy> type ; 201 } ; 202 template<template <class> class StoragePolicy> 203 struct r_vector_name_proxy<STRSXP, StoragePolicy>{ 204 typedef ::Rcpp::internal::string_name_proxy<STRSXP, StoragePolicy> type ; 205 } ; 206 template<template <class> class StoragePolicy> 207 struct r_vector_name_proxy<VECSXP, StoragePolicy>{ 208 typedef ::Rcpp::internal::generic_name_proxy<VECSXP, StoragePolicy> type ; 209 } ; 210 template<template <class> class StoragePolicy> 211 struct r_vector_name_proxy<EXPRSXP, StoragePolicy>{ 212 typedef ::Rcpp::internal::generic_name_proxy<EXPRSXP, StoragePolicy> type ; 213 } ; 214 215 template <int RTYPE, template <class> class StoragePolicy> 216 struct r_vector_proxy{ 217 typedef typename storage_type<RTYPE>::type& type ; 218 } ; 219 template<template <class> class StoragePolicy> 220 struct r_vector_proxy<STRSXP, StoragePolicy> { 221 typedef ::Rcpp::internal::string_proxy<STRSXP, StoragePolicy> type ; 222 } ; 223 template<template <class> class StoragePolicy> 224 struct r_vector_proxy<EXPRSXP, StoragePolicy> { 225 typedef ::Rcpp::internal::generic_proxy<EXPRSXP, StoragePolicy> type ; 226 } ; 227 template<template <class> class StoragePolicy> 228 struct r_vector_proxy<VECSXP, StoragePolicy> { 229 typedef ::Rcpp::internal::generic_proxy<VECSXP, StoragePolicy> type ; 230 } ; 231 232 template <int RTYPE, template <class> class StoragePolicy> 233 struct r_vector_const_proxy{ 234 typedef const typename storage_type<RTYPE>::type& type ; 235 } ; 236 template<template <class> class StoragePolicy> 237 struct r_vector_const_proxy<STRSXP, StoragePolicy> { 238 typedef ::Rcpp::internal::const_string_proxy<STRSXP, StoragePolicy> type ; 239 } ; 240 template<template <class> class StoragePolicy> 241 struct r_vector_const_proxy<VECSXP, StoragePolicy> { 242 typedef ::Rcpp::internal::const_generic_proxy<VECSXP, StoragePolicy> type ; 243 } ; 244 template<template <class> class StoragePolicy> 245 struct r_vector_const_proxy<EXPRSXP, StoragePolicy> { 246 typedef ::Rcpp::internal::const_generic_proxy<EXPRSXP, StoragePolicy> type ; 247 } ; 248 249 template <int RTYPE, template <class> class StoragePolicy> 250 struct r_vector_iterator { 251 typedef typename storage_type<RTYPE>::type* type ; 252 }; 253 template <int RTYPE, template <class> class StoragePolicy> 254 struct r_vector_const_iterator { 255 typedef const typename storage_type<RTYPE>::type* type ; 256 }; 257 258 template <int RTYPE, template <class> class StoragePolicy> 259 struct proxy_based_iterator{ 260 typedef ::Rcpp::internal::Proxy_Iterator< typename r_vector_proxy<RTYPE, StoragePolicy>::type > type ; 261 } ; 262 template<template <class> class StoragePolicy> struct r_vector_iterator<VECSXP, StoragePolicy> : proxy_based_iterator<VECSXP, StoragePolicy>{} ; 263 template<template <class> class StoragePolicy> struct r_vector_iterator<EXPRSXP, StoragePolicy> : proxy_based_iterator<EXPRSXP, StoragePolicy>{} ; 264 template<template <class> class StoragePolicy> struct r_vector_iterator<STRSXP, StoragePolicy> : proxy_based_iterator<STRSXP, StoragePolicy>{} ; 265 266 template <int RTYPE, template <class> class StoragePolicy> 267 struct proxy_based_const_iterator{ 268 typedef ::Rcpp::internal::Proxy_Iterator< typename r_vector_const_proxy<RTYPE, StoragePolicy>::type > type ; 269 } ; 270 template<template <class> class StoragePolicy> struct r_vector_const_iterator<VECSXP, StoragePolicy> : proxy_based_const_iterator<VECSXP, StoragePolicy>{} ; 271 template<template <class> class StoragePolicy> struct r_vector_const_iterator<EXPRSXP, StoragePolicy> : proxy_based_const_iterator<EXPRSXP, StoragePolicy>{} ; 272 template<template <class> class StoragePolicy> struct r_vector_const_iterator<STRSXP, StoragePolicy> : proxy_based_const_iterator<STRSXP, StoragePolicy>{} ; 273 274 } // traits 275 } 276 277 #endif 278