Skip to content

Commit 6739ade

Browse files
authored
Merge pull request #36 from pachadotdev/named_arg_utf8-clean
named_arg check with minimal changes
2 parents 05c888b + 6d8426c commit 6739ade

File tree

1 file changed

+50
-10
lines changed

1 file changed

+50
-10
lines changed

inst/include/cpp11/r_vector.hpp

Lines changed: 50 additions & 10 deletions
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

@@ -256,6 +258,15 @@ class r_vector : public cpp11::r_vector<T> {
256258

257259
iterator find(const r_string& name) const;
258260

261+
/// Get the value at position without returning a proxy
262+
/// This is useful when you need the actual value (e.g., for C-style printf functions)
263+
/// that don't trigger implicit conversions from proxy types
264+
#ifdef LONG_VECTOR_SUPPORT
265+
T value(const int pos) const;
266+
#endif
267+
T value(const R_xlen_t pos) const;
268+
T value(const size_type pos) const;
269+
259270
attribute_proxy<r_vector<T>> attr(const char* name) const;
260271
attribute_proxy<r_vector<T>> attr(const std::string& name) const;
261272
attribute_proxy<r_vector<T>> attr(SEXP name) const;
@@ -865,7 +876,8 @@ inline r_vector<T>::r_vector(std::initializer_list<named_arg> il)
865876
}
866877

867878
unwind_protect([&] {
868-
SEXP names = Rf_allocVector(STRSXP, capacity_);
879+
SEXP names;
880+
PROTECT(names = Rf_allocVector(STRSXP, capacity_));
869881
Rf_setAttrib(data_, R_NamesSymbol, names);
870882

871883
auto it = il.begin();
@@ -876,20 +888,30 @@ inline r_vector<T>::r_vector(std::initializer_list<named_arg> il)
876888
// SAFETY: We've validated type and length ahead of this.
877889
const underlying_type elt = get_elt(value, 0);
878890

879-
// TODO: The equivalent ctor from `initializer_list<r_string>` has a specialization
880-
// for `<r_string>` to translate `elt` to UTF-8 before assigning. Should we have
881-
// that here too? `named_arg` doesn't do any checking here.
882-
if (data_p_ != nullptr) {
883-
data_p_[i] = elt;
891+
if constexpr (std::is_same<T, cpp11::r_string>::value) {
892+
// Translate to UTF-8 before assigning for string types
893+
SEXP translated_elt = Rf_mkCharCE(Rf_translateCharUTF8(elt), CE_UTF8);
894+
895+
if (data_p_ != nullptr) {
896+
data_p_[i] = translated_elt;
897+
} else {
898+
// Handles STRSXP case. VECSXP case has its own specialization.
899+
// We don't expect any ALTREP cases since we just freshly allocated `data_`.
900+
set_elt(data_, i, translated_elt);
901+
}
884902
} else {
885-
// Handles STRSXP case. VECSXP case has its own specialization.
886-
// We don't expect any ALTREP cases since we just freshly allocated `data_`.
887-
set_elt(data_, i, elt);
903+
if (data_p_ != nullptr) {
904+
data_p_[i] = elt;
905+
} else {
906+
set_elt(data_, i, elt);
907+
}
888908
}
889909

890910
SEXP name = Rf_mkCharCE(it->name(), CE_UTF8);
891911
SET_STRING_ELT(names, i, name);
892912
}
913+
914+
UNPROTECT(1);
893915
});
894916
}
895917

@@ -1156,6 +1178,24 @@ inline typename r_vector<T>::iterator r_vector<T>::find(const r_string& name) co
11561178
return end();
11571179
}
11581180

1181+
#ifdef LONG_VECTOR_SUPPORT
1182+
template <typename T>
1183+
inline T r_vector<T>::value(const int pos) const {
1184+
return value(static_cast<R_xlen_t>(pos));
1185+
}
1186+
#endif
1187+
1188+
template <typename T>
1189+
inline T r_vector<T>::value(const R_xlen_t pos) const {
1190+
// Use the parent read-only class's operator[] which returns T directly
1191+
return cpp11::r_vector<T>::operator[](pos);
1192+
}
1193+
1194+
template <typename T>
1195+
inline T r_vector<T>::value(const size_type pos) const {
1196+
return value(static_cast<R_xlen_t>(pos));
1197+
}
1198+
11591199
template <typename T>
11601200
inline attribute_proxy<r_vector<T>> r_vector<T>::attr(const char* name) const {
11611201
return attribute_proxy<r_vector<T>>(*this, name);

0 commit comments

Comments
 (0)