Skip to content

Names of named args in list are now resized along with list elements #212

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Jul 23, 2021
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* Error messages now output original file name rather than the temporary file name (@sbearrows, #194)
* Fixed bug when running `cpp_source()` on the same file more than once (@sbearrows, #202)
* Removed internal instances of `cpp11::stop()` and replaced with C++ exceptions (@sbearrows, #203)
* Names of named lists are now resized along with the list elements (@sbearrows, #206)
* Added optionally formatting to `stop()` and `warning()` using {fmt} library (@sbearrows, #169)

# cpp11 0.3.1
Expand Down
13 changes: 13 additions & 0 deletions cpp11test/src/test-list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,4 +141,17 @@ context("list-C++") {

expect_false(y.empty());
}

test_that("names of named lists are also resized") {
cpp11::writable::list x;
x.push_back({"n1"_nm = 1});
x.push_back({"n2"_nm = 2});
x.push_back({"n3"_nm = 3});
x.push_back({"n4"_nm = 4});
x.push_back({"n5"_nm = 5});
x = SEXP(x);

cpp11::strings nms(x.names());
expect_true(x.size() == nms.size());
}
}
25 changes: 18 additions & 7 deletions inst/include/cpp11/r_vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -878,17 +878,28 @@ inline void r_vector<T>::clear() {
length_ = 0;
}

inline SEXP truncate(SEXP x, R_xlen_t length, R_xlen_t capacity) {
#if R_VERSION >= R_Version(3, 4, 0)
SETLENGTH(x, length);
SET_TRUELENGTH(x, capacity);
SET_GROWABLE_BIT(x);
#else
x = safe[Rf_lengthgets](x, length_);
#endif
return x;
}

template <typename T>
inline r_vector<T>::operator SEXP() const {
if (length_ < capacity_) {
#if R_VERSION >= R_Version(3, 4, 0)
SETLENGTH(data_, length_);
SET_TRUELENGTH(data_, capacity_);
SET_GROWABLE_BIT(data_);
#else
auto* p = const_cast<r_vector<T>*>(this);
p->data_ = safe[Rf_lengthgets](data_, length_);
#endif
p->data_ = truncate(p->data_, length_, capacity_);
SEXP nms = names();
auto nms_size = Rf_xlength(nms);
if ((nms_size > 0) && (length_ < nms_size)) {
nms = truncate(nms, length_, capacity_);
names() = nms;
}
}
return data_;
}
Expand Down