Skip to content

Commit bbee709

Browse files
committed
fix #406
1 parent aeb1895 commit bbee709

File tree

3 files changed

+40
-17
lines changed

3 files changed

+40
-17
lines changed

cpp11test/DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@ Suggests:
2020
xml2
2121
LazyData: true
2222
Roxygen: list(markdown = TRUE)
23-
RoxygenNote: 7.1.1
23+
RoxygenNote: 7.3.2

inst/include/cpp11/r_vector.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,9 @@ class r_vector : public cpp11::r_vector<T> {
235235
proxy at(const r_string& name) const;
236236

237237
void push_back(T value);
238-
/// Implemented in `strings.hpp`
238+
template <typename U = T,
239+
typename std::enable_if<std::is_same<U, r_string>::value>::type* = nullptr>
240+
void push_back(const std::string& value); // Pacha: r_string only (#406)
239241
void push_back(const named_arg& value);
240242
void pop_back();
241243

inst/include/cpp11/strings.hpp

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,32 @@ typedef r_vector<r_string> strings;
6161
namespace writable {
6262

6363
template <>
64-
inline void r_vector<r_string>::set_elt(SEXP x, R_xlen_t i,
65-
typename r_vector::underlying_type value) {
64+
inline void r_vector<r_string>::set_elt(
65+
SEXP x, R_xlen_t i, typename r_vector<r_string>::underlying_type value) {
6666
// NOPROTECT: Likely too costly to unwind protect every set elt
6767
SET_STRING_ELT(x, i, value);
6868
}
6969

70+
// Pacha: Optimized subscript assignment for std::string
71+
template <>
72+
inline typename r_vector<r_string>::proxy r_vector<r_string>::operator[](
73+
R_xlen_t i) const {
74+
return typename r_vector<r_string>::proxy(data_, i, nullptr, false);
75+
}
76+
77+
// Pacha: Optimized push_back for std::string
78+
template <>
79+
template <typename U, typename std::enable_if<std::is_same<U, r_string>::value>::type*>
80+
inline void r_vector<r_string>::push_back(const std::string& value) {
81+
while (this->length_ >= this->capacity_) {
82+
this->reserve(this->capacity_ == 0 ? 1 : this->capacity_ * 2);
83+
}
84+
85+
SEXP char_sexp = Rf_mkCharLenCE(value.c_str(), value.size(), CE_UTF8);
86+
SET_STRING_ELT(this->data_, this->length_, char_sexp);
87+
++this->length_;
88+
}
89+
7090
inline bool operator==(const r_vector<r_string>::proxy& lhs, r_string rhs) {
7191
return static_cast<r_string>(lhs).operator==(static_cast<std::string>(rhs).c_str());
7292
}
@@ -95,17 +115,17 @@ inline SEXP alloc_if_charsxp(const SEXP data) {
95115

96116
template <>
97117
inline r_vector<r_string>::r_vector(const SEXP& data)
98-
: cpp11::r_vector<r_string>(alloc_or_copy(data)), capacity_(length_) {
118+
: cpp11::r_vector<r_string>(alloc_or_copy(data)), capacity_(this->length_) {
99119
if (detail::r_typeof(data) == CHARSXP) {
100-
SET_STRING_ELT(data_, 0, data);
120+
SET_STRING_ELT(this->data_, 0, data);
101121
}
102122
}
103123

104124
template <>
105125
inline r_vector<r_string>::r_vector(SEXP&& data)
106-
: cpp11::r_vector<r_string>(alloc_if_charsxp(data)), capacity_(length_) {
126+
: cpp11::r_vector<r_string>(alloc_if_charsxp(data)), capacity_(this->length_) {
107127
if (detail::r_typeof(data) == CHARSXP) {
108-
SET_STRING_ELT(data_, 0, data);
128+
SET_STRING_ELT(this->data_, 0, data);
109129
}
110130
}
111131

@@ -117,14 +137,15 @@ inline r_vector<r_string>::r_vector(std::initializer_list<r_string> il)
117137
unwind_protect([&] {
118138
auto it = il.begin();
119139

120-
for (R_xlen_t i = 0; i < capacity_; ++i, ++it) {
140+
for (R_xlen_t i = 0; i < this->capacity_; ++i, ++it) {
121141
// i.e. to `SEXP`
122-
underlying_type elt = static_cast<underlying_type>(*it);
142+
typename r_vector<r_string>::underlying_type elt =
143+
static_cast<typename r_vector<r_string>::underlying_type>(*it);
123144

124145
if (elt == NA_STRING) {
125-
set_elt(data_, i, elt);
146+
set_elt(this->data_, i, elt);
126147
} else {
127-
set_elt(data_, i, Rf_mkCharCE(Rf_translateCharUTF8(elt), CE_UTF8));
148+
set_elt(this->data_, i, Rf_mkCharCE(Rf_translateCharUTF8(elt), CE_UTF8));
128149
}
129150
}
130151
});
@@ -135,12 +156,12 @@ typedef r_vector<r_string> strings;
135156
template <typename T>
136157
inline void r_vector<T>::push_back(const named_arg& value) {
137158
push_back(value.value());
138-
if (Rf_xlength(names()) == 0) {
139-
cpp11::writable::strings new_nms(size());
140-
names() = new_nms;
159+
if (Rf_xlength(this->names()) == 0) {
160+
cpp11::writable::strings new_nms(this->size());
161+
this->names() = new_nms;
141162
}
142-
cpp11::writable::strings nms(names());
143-
nms[size() - 1] = value.name();
163+
cpp11::writable::strings nms(this->names());
164+
nms[this->size() - 1] = value.name();
144165
}
145166

146167
} // namespace writable

0 commit comments

Comments
 (0)