Skip to content

Commit df9f81e

Browse files
handling const string proxy. closes #32
1 parent 66a7413 commit df9f81e

File tree

7 files changed

+180
-5
lines changed

7 files changed

+180
-5
lines changed

inst/include/Rcpp/Vector.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ template <int RTYPE> class SubMatrix ;
6161

6262
#include <Rcpp/vector/instantiation.h>
6363
#include <Rcpp/vector/string_proxy.h>
64+
#include <Rcpp/vector/const_string_proxy.h>
6465
}
6566

6667
#include <Rcpp/String.h>

inst/include/Rcpp/vector/00_forward_proxy.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
namespace internal{
2626
template <int RTYPE> class string_proxy ;
27+
template <int RTYPE> class const_string_proxy ;
2728
template <int RTYPE> class generic_proxy ;
2829
template <int RTYPE> class simple_name_proxy ;
2930
template <int RTYPE> class string_name_proxy ;
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*-
2+
//
3+
// const_string_proxy.h: Rcpp R/C++ interface class library --
4+
//
5+
// Copyright (C) 2013 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__const_string_proxy_h
23+
#define Rcpp__vector__const_string_proxy_h
24+
25+
namespace internal{
26+
27+
template<int RTYPE> class const_string_proxy {
28+
public:
29+
30+
typedef typename ::Rcpp::Vector<RTYPE> VECTOR ;
31+
typedef const char* iterator ;
32+
typedef const char& reference ;
33+
34+
const_string_proxy() : parent(0), index(-1){};
35+
36+
/**
37+
* Creates a proxy
38+
*
39+
* @param v reference to the associated character vector
40+
* @param index index
41+
*/
42+
const_string_proxy( VECTOR& v, int index_ ) : parent(&v), index(index_){}
43+
44+
const_string_proxy( const const_string_proxy& other ) :
45+
parent(other.parent), index(other.index){} ;
46+
47+
void import( const const_string_proxy& other){
48+
parent = other.parent ;
49+
index = other.index ;
50+
}
51+
52+
/**
53+
* rhs use. Retrieves the current value of the
54+
* element this proxy refers to.
55+
*/
56+
operator SEXP() const {
57+
return get() ;
58+
}
59+
60+
/**
61+
* rhs use. Retrieves the current value of the
62+
* element this proxy refers to and convert it to a
63+
* C string
64+
*/
65+
operator /* const */ char*() const {
66+
return const_cast<char*>( CHAR(get()) );
67+
}
68+
69+
/**
70+
* Prints the element this proxy refers to to an
71+
* output stream
72+
*/
73+
template <int RT>
74+
friend std::ostream& operator<<(std::ostream& os, const const_string_proxy<RT>& proxy);
75+
76+
template <int RT>
77+
friend std::string operator+( const std::string& x, const const_string_proxy<RT>& proxy);
78+
79+
const VECTOR* parent;
80+
int index ;
81+
inline void move( int n ){ index += n ;}
82+
83+
inline SEXP get() const {
84+
return STRING_ELT( *parent, index ) ;
85+
}
86+
87+
inline iterator begin() const { return CHAR( STRING_ELT( *parent, index ) ) ; }
88+
inline iterator end() const { return begin() + size() ; }
89+
inline int size() const { return strlen( begin() ) ; }
90+
inline reference operator[]( int n ){ return *( begin() + n ) ; }
91+
92+
bool operator==( const char* other){
93+
return strcmp( begin(), other ) == 0 ;
94+
}
95+
bool operator!=( const char* other){
96+
return strcmp( begin(), other ) != 0 ;
97+
}
98+
99+
bool operator==( const const_string_proxy& other){
100+
return strcmp( begin(), other.begin() ) == 0 ;
101+
}
102+
bool operator!=( const const_string_proxy& other){
103+
return strcmp( begin(), other.begin() ) != 0 ;
104+
}
105+
106+
107+
private:
108+
static std::string buffer ;
109+
110+
} ;
111+
112+
template <int RT>
113+
bool operator<( const const_string_proxy<RT>& lhs, const const_string_proxy<RT>& rhs) {
114+
return strcmp(
115+
const_cast<char *>(lhs.begin() ),
116+
const_cast<char *>(rhs.begin())
117+
) < 0 ;
118+
}
119+
120+
template <int RT>
121+
bool operator>( const const_string_proxy<RT>& lhs, const const_string_proxy<RT>& rhs) {
122+
return strcmp(
123+
const_cast<char *>(lhs.begin() ),
124+
const_cast<char *>(rhs.begin())
125+
) > 0 ;
126+
}
127+
128+
template <int RT>
129+
bool operator>=( const const_string_proxy<RT>& lhs, const const_string_proxy<RT>& rhs) {
130+
return strcmp(
131+
const_cast<char *>(lhs.begin() ),
132+
const_cast<char *>(rhs.begin())
133+
) >= 0 ;
134+
}
135+
136+
template <int RT>
137+
bool operator<=( const const_string_proxy<RT>& lhs, const const_string_proxy<RT>& rhs) {
138+
return strcmp(
139+
const_cast<char *>(lhs.begin() ),
140+
const_cast<char *>(rhs.begin())
141+
) <= 0 ;
142+
}
143+
144+
template<int RTYPE> std::string const_string_proxy<RTYPE>::buffer ;
145+
146+
inline std::ostream& operator<<(std::ostream& os, const const_string_proxy<STRSXP>& proxy) {
147+
os << static_cast<const char*>(proxy) ;
148+
return os;
149+
}
150+
151+
inline std::string operator+( const std::string& x, const const_string_proxy<STRSXP>& y ){
152+
return x + static_cast<const char*>(y) ;
153+
}
154+
155+
156+
}
157+
158+
#endif

inst/include/Rcpp/vector/proxy.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,10 @@ namespace traits {
227227
struct r_vector_const_proxy{
228228
typedef const typename storage_type<RTYPE>::type& type ;
229229
} ;
230-
230+
template<> struct r_vector_const_proxy<STRSXP> {
231+
typedef ::Rcpp::internal::const_string_proxy<STRSXP> type ;
232+
} ;
233+
231234
template <int RTYPE>
232235
struct r_vector_iterator {
233236
typedef typename storage_type<RTYPE>::type* type ;

inst/include/Rcpp/vector/traits.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,8 @@ namespace traits{
7070
inline proxy ref() { return proxy(*p,0) ; }
7171
inline proxy ref(int i) { return proxy(*p,i);}
7272

73-
// inline const_proxy ref() const { return const_proxy(*p,0) ; }
74-
// inline const_proxy ref(int i) const { return const_proxy(*p,i);}
75-
inline const_proxy ref() const { return *get_vector_ptr(*p) ; }
76-
inline const_proxy ref(int i) const { return get_vector_ptr(*p)[i] ;}
73+
inline const_proxy ref() const { return const_proxy(*p,0) ; }
74+
inline const_proxy ref(int i) const { return const_proxy(*p,i);}
7775

7876
private:
7977
VECTOR* p ;

inst/unitTests/cpp/Vector.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,3 +720,12 @@ int stdVectorIntRef(std::vector<int> & x) {
720720
int stdVectorIntConstRef(const std::vector<int> & x) {
721721
return x.size();
722722
}
723+
724+
// [[Rcpp::export]]
725+
std::string character_vector_const_proxy(const CharacterVector& str){
726+
char* cstr = (char*) str[0] ;
727+
std::string res ;
728+
res += cstr ;
729+
return cstr ;
730+
}
731+

inst/unitTests/runit.Vector.R

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,5 +649,10 @@ if (.runThisTest) {
649649
checkEquals(fun(x), 5, msg = "automatic conversion of stdVectorIntConstRef")
650650
}
651651

652+
test.character.vector.const.proxy <- function(){
653+
res <- character_vector_const_proxy( "fooo" )
654+
checkEquals( res, "fooo", msg = "CharacterVector const proxy. #32" )
655+
}
656+
652657
}
653658

0 commit comments

Comments
 (0)