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