|
Rcpp Version 0.9.10
|
00001 // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*- 00002 // 00003 // string_proxy.h: Rcpp R/C++ interface class library -- 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 #ifndef Rcpp__vector__string_proxy_h 00023 #define Rcpp__vector__string_proxy_h 00024 00025 namespace internal{ 00026 00027 template<int RTYPE> class string_proxy { 00028 public: 00029 00030 typedef typename ::Rcpp::Vector<RTYPE> VECTOR ; 00031 typedef const char* iterator ; 00032 typedef const char& reference ; 00033 00034 string_proxy() : parent(0), index(-1){}; 00035 00042 string_proxy( VECTOR& v, int index_ ) : 00043 parent(&v), index(index_){ 00044 RCPP_DEBUG_2( "string_proxy( VECTOR& = <%p>, index_ = %d) ", v.asSexp(), index_ ) ; 00045 } 00046 00047 string_proxy( const string_proxy& other ) : 00048 parent(other.parent), index(other.index){} ; 00049 00057 string_proxy& operator=(const string_proxy& other){ 00058 set( other.get() ) ; 00059 return *this ; 00060 } 00061 00068 string_proxy& operator=(const std::string& rhs){ 00069 set( Rf_mkChar( rhs.c_str() ) ) ; 00070 return *this ; 00071 } 00072 00073 string_proxy& operator=(const char& rhs){ 00074 set( Rf_mkChar( &rhs ) ) ; 00075 return *this ; 00076 } 00077 00078 string_proxy& operator=(SEXP rhs){ 00079 // TODO: check this is a CHARSXP 00080 set( rhs ) ; 00081 return *this ; 00082 } 00083 00084 void import( const string_proxy& other){ 00085 parent = other.parent ; 00086 index = other.index ; 00087 } 00088 00093 string_proxy& operator+=(const string_proxy& rhs){ 00094 buffer = CHAR(STRING_ELT(*parent,index)) ; 00095 buffer += CHAR(STRING_ELT( *(rhs.parent), rhs.index)) ; 00096 SET_STRING_ELT( *parent, index, Rf_mkChar(buffer.c_str()) ) ; 00097 return *this ; 00098 } 00099 00103 string_proxy& operator+=(const std::string& rhs){ 00104 buffer = CHAR(STRING_ELT(*parent,index)) ; 00105 buffer += rhs ; 00106 SET_STRING_ELT( *parent, index, Rf_mkChar(buffer.c_str()) ) ; 00107 return *this ; 00108 } 00109 00114 operator SEXP() const { 00115 return get() ; 00116 } 00117 00123 operator /*const */ char*() const { 00124 return const_cast<char*>( CHAR(get()) ); 00125 } 00126 00131 template <int RT> 00132 friend std::ostream& operator<<(std::ostream& os, const string_proxy<RT>& proxy); 00133 00134 template <int RT> 00135 friend std::string operator+( const std::string& x, const string_proxy<RT>& proxy); 00136 00137 void swap( string_proxy& other ){ 00138 SEXP tmp = PROTECT( STRING_ELT(*parent, index)) ; 00139 SET_STRING_ELT( *parent, index, STRING_ELT( *(other.parent), other.index) ) ; 00140 SET_STRING_ELT( *(other.parent), other.index, tmp ) ; 00141 UNPROTECT(1) ; /* tmp */ 00142 } 00143 00144 VECTOR* parent; 00145 int index ; 00146 inline void move( int n ){ index += n ;} 00147 00148 inline SEXP get() const { 00149 return STRING_ELT( *parent, index ) ; 00150 } 00151 inline void set(SEXP x){ 00152 SET_STRING_ELT( *parent, index, x ) ; 00153 } 00154 inline void set( const std::string& x ){ 00155 set( ::Rf_mkChar(x.c_str()) ) ; 00156 } 00157 00158 inline iterator begin() const { return CHAR( STRING_ELT( *parent, index ) ) ; } 00159 inline iterator end() const { return begin() + size() ; } 00160 inline int size() const { return strlen( begin() ) ; } 00161 inline reference operator[]( int n ){ return *( begin() + n ) ; } 00162 00163 template <typename UnaryOperator> 00164 void transform( UnaryOperator op ){ 00165 buffer = begin() ; 00166 std::transform( buffer.begin(), buffer.end(), buffer.begin(), op ) ; 00167 set( buffer ) ; 00168 } 00169 00170 template <typename OutputIterator, typename UnaryOperator> 00171 void apply( OutputIterator target, UnaryOperator op){ 00172 std::transform( begin(), end(), target, op ) ; 00173 } 00174 00175 template <typename UnaryOperator> 00176 void apply( UnaryOperator op){ 00177 std::for_each( begin(), end(), op ); 00178 } 00179 00180 bool operator==( const char* other){ 00181 return strcmp( begin(), other ) == 0 ; 00182 } 00183 00184 private: 00185 static std::string buffer ; 00186 00187 } ; 00188 00189 template <int RT> 00190 bool operator<( const string_proxy<RT>& lhs, const string_proxy<RT>& rhs) { 00191 return strcmp( 00192 const_cast<char *>(lhs.begin() ), 00193 const_cast<char *>(rhs.begin()) 00194 ) < 0 ; 00195 } 00196 00197 template <int RT> 00198 bool operator>( const string_proxy<RT>& lhs, const string_proxy<RT>& rhs) { 00199 return strcmp( 00200 const_cast<char *>(lhs.begin() ), 00201 const_cast<char *>(rhs.begin()) 00202 ) > 0 ; 00203 } 00204 00205 template <int RT> 00206 bool operator>=( const string_proxy<RT>& lhs, const string_proxy<RT>& rhs) { 00207 return strcmp( 00208 const_cast<char *>(lhs.begin() ), 00209 const_cast<char *>(rhs.begin()) 00210 ) >= 0 ; 00211 } 00212 00213 template <int RT> 00214 bool operator<=( const string_proxy<RT>& lhs, const string_proxy<RT>& rhs) { 00215 return strcmp( 00216 const_cast<char *>(lhs.begin() ), 00217 const_cast<char *>(rhs.begin()) 00218 ) <= 0 ; 00219 } 00220 00221 template<int RTYPE> std::string string_proxy<RTYPE>::buffer ; 00222 00223 inline std::ostream& operator<<(std::ostream& os, const string_proxy<STRSXP>& proxy) { 00224 os << static_cast<const char*>(proxy) ; 00225 return os; 00226 } 00227 00228 inline std::string operator+( const std::string& x, const string_proxy<STRSXP>& y ){ 00229 return x + static_cast<const char*>(y) ; 00230 } 00231 00232 template <int RTYPE> 00233 class generic_proxy{ 00234 public: 00235 typedef typename ::Rcpp::Vector<RTYPE> VECTOR ; 00236 00237 generic_proxy(): parent(0), index(-1){} 00238 00239 generic_proxy( const generic_proxy& other ) : 00240 parent(other.parent), index(other.index){} ; 00241 00242 generic_proxy( VECTOR& v, int i ) : parent(&v), index(i){} ; 00243 00244 generic_proxy& operator=(SEXP rhs) { 00245 set(rhs) ; 00246 return *this ; 00247 } 00248 00249 generic_proxy& operator=(const generic_proxy& rhs) { 00250 set(rhs.get()); 00251 return *this ; 00252 } 00253 00254 template <typename T> 00255 generic_proxy& operator=( const T& rhs){ 00256 set(wrap(rhs)) ; 00257 return *this; 00258 } 00259 00260 operator SEXP() const { 00261 return get() ; 00262 } 00263 00264 template <typename U> operator U() const { 00265 return ::Rcpp::as<U>(get()) ; 00266 } 00267 00268 // helping the compiler (not sure why it can't help itself) 00269 operator bool() const { return ::Rcpp::as<bool>(get()) ; } 00270 operator int() const { return ::Rcpp::as<int>(get()) ; } 00271 00272 void swap(generic_proxy& other){ 00273 SEXP tmp = PROTECT(get()) ; 00274 set( other.get() ) ; 00275 other.set(tmp) ; 00276 UNPROTECT(1) ; 00277 } 00278 00279 VECTOR* parent; 00280 int index ; 00281 inline void move(int n) { index += n ; } 00282 00283 void import( const generic_proxy& other){ 00284 parent = other.parent ; 00285 index = other.index ; 00286 } 00287 00288 private: 00289 inline void set(SEXP x) { SET_VECTOR_ELT( *parent, index, x ) ;} 00290 inline SEXP get() const { return VECTOR_ELT(*parent, index ); } 00291 00292 } ; 00293 00294 } 00295 00296 #endif