Rcpp Version 0.9.10
string_proxy.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Defines