Skip to content

Commit

Permalink
Use a universal reserve() method (#373)
Browse files Browse the repository at this point in the history
  • Loading branch information
DavisVaughan authored Aug 8, 2024
1 parent 758683c commit 457c441
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 80 deletions.
17 changes: 5 additions & 12 deletions inst/include/cpp11/doubles.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ typedef r_vector<double> doubles;

namespace writable {

template <>
inline SEXPTYPE r_vector<double>::get_sexptype() {
return REALSXP;
}

template <>
inline typename r_vector<double>::proxy& r_vector<double>::proxy::operator=(
const double& rhs) {
Expand Down Expand Up @@ -104,18 +109,6 @@ inline r_vector<double>::r_vector(std::initializer_list<named_arg> il)
}
}

template <>
inline void r_vector<double>::reserve(R_xlen_t new_capacity) {
data_ = data_ == R_NilValue ? safe[Rf_allocVector](REALSXP, new_capacity)
: safe[Rf_xlengthgets](data_, new_capacity);
SEXP old_protect = protect_;
protect_ = detail::store::insert(data_);
detail::store::release(old_protect);

data_p_ = REAL(data_);
capacity_ = new_capacity;
}

template <>
inline void r_vector<double>::push_back(double value) {
while (length_ >= capacity_) {
Expand Down
21 changes: 5 additions & 16 deletions inst/include/cpp11/integers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ typedef r_vector<int> integers;

namespace writable {

template <>
inline SEXPTYPE r_vector<int>::get_sexptype() {
return INTSXP;
}

template <>
inline typename r_vector<int>::proxy& r_vector<int>::proxy::operator=(const int& rhs) {
if (is_altrep_) {
Expand All @@ -80,22 +85,6 @@ template <>
inline r_vector<int>::r_vector(std::initializer_list<int> il)
: cpp11::r_vector<int>(as_sexp(il)), capacity_(il.size()) {}

template <>
inline void r_vector<int>::reserve(R_xlen_t new_capacity) {
data_ = data_ == R_NilValue ? safe[Rf_allocVector](INTSXP, new_capacity)
: safe[Rf_xlengthgets](data_, new_capacity);
SEXP old_protect = protect_;

// Protect the new data
protect_ = detail::store::insert(data_);

// Release the old protection;
detail::store::release(old_protect);

data_p_ = INTEGER(data_);
capacity_ = new_capacity;
}

template <>
inline r_vector<int>::r_vector(std::initializer_list<named_arg> il)
: cpp11::r_vector<int>(safe[Rf_allocVector](INTSXP, il.size())),
Expand Down
17 changes: 5 additions & 12 deletions inst/include/cpp11/list.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ typedef r_vector<SEXP> list;

namespace writable {

template <>
inline SEXPTYPE r_vector<SEXP>::get_sexptype() {
return VECSXP;
}

template <>
inline typename r_vector<SEXP>::proxy& r_vector<SEXP>::proxy::operator=(const SEXP& rhs) {
SET_VECTOR_ELT(data_, index_, rhs);
Expand Down Expand Up @@ -108,18 +113,6 @@ inline r_vector<SEXP>::r_vector(std::initializer_list<named_arg> il)
}
}

template <>
inline void r_vector<SEXP>::reserve(R_xlen_t new_capacity) {
data_ = data_ == R_NilValue ? safe[Rf_allocVector](VECSXP, new_capacity)
: safe[Rf_xlengthgets](data_, new_capacity);

SEXP old_protect = protect_;
protect_ = detail::store::insert(data_);
detail::store::release(old_protect);

capacity_ = new_capacity;
}

template <>
inline void r_vector<SEXP>::push_back(SEXP value) {
while (length_ >= capacity_) {
Expand Down
18 changes: 5 additions & 13 deletions inst/include/cpp11/logicals.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ typedef r_vector<r_bool> logicals;

namespace writable {

template <>
inline SEXPTYPE r_vector<r_bool>::get_sexptype() {
return LGLSXP;
}

template <>
inline typename r_vector<r_bool>::proxy& r_vector<r_bool>::proxy::operator=(
const r_bool& rhs) {
Expand Down Expand Up @@ -110,19 +115,6 @@ inline r_vector<r_bool>::r_vector(std::initializer_list<named_arg> il)
}
}

template <>
inline void r_vector<r_bool>::reserve(R_xlen_t new_capacity) {
data_ = data_ == R_NilValue ? safe[Rf_allocVector](LGLSXP, new_capacity)
: safe[Rf_xlengthgets](data_, new_capacity);
SEXP old_protect = protect_;
protect_ = detail::store::insert(data_);

detail::store::release(old_protect);

data_p_ = LOGICAL(data_);
capacity_ = new_capacity;
}

template <>
inline void r_vector<r_bool>::push_back(r_bool value) {
while (length_ >= capacity_) {
Expand Down
25 changes: 23 additions & 2 deletions inst/include/cpp11/r_vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,6 @@ class r_vector : public cpp11::r_vector<T> {
void pop_back();

void resize(R_xlen_t count);

/// Implemented in specialization
void reserve(R_xlen_t new_capacity);

iterator insert(R_xlen_t pos, T value);
Expand Down Expand Up @@ -308,6 +306,9 @@ class r_vector : public cpp11::r_vector<T> {
};

private:
/// Implemented in specialization
static SEXPTYPE get_sexptype();

using cpp11::r_vector<T>::get_p;
};
} // namespace writable
Expand Down Expand Up @@ -886,6 +887,26 @@ inline void r_vector<T>::resize(R_xlen_t count) {
length_ = count;
}

/// Reserve a new capacity and copy all elements over
///
/// SAFETY: The new capacity is allowed to be smaller than the current capacity, which
/// is used in the `SEXP` conversion operator during truncation, but if that occurs then
/// we also need to update the `length_`, so if you need to truncate then you should call
/// `resize()` instead.
template <typename T>
inline void r_vector<T>::reserve(R_xlen_t new_capacity) {
SEXP old_protect = protect_;

data_ = (data_ == R_NilValue) ? safe[Rf_allocVector](get_sexptype(), new_capacity)
: safe[Rf_xlengthgets](data_, new_capacity);
protect_ = detail::store::insert(data_);
is_altrep_ = ALTREP(data_);
data_p_ = get_p(is_altrep_, data_);
capacity_ = new_capacity;

detail::store::release(old_protect);
}

template <typename T>
inline typename r_vector<T>::iterator r_vector<T>::insert(R_xlen_t pos, T value) {
push_back(value);
Expand Down
18 changes: 5 additions & 13 deletions inst/include/cpp11/raws.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ typedef r_vector<uint8_t> raws;

namespace writable {

template <>
inline SEXPTYPE r_vector<uint8_t>::get_sexptype() {
return RAWSXP;
}

template <>
inline typename r_vector<uint8_t>::proxy& r_vector<uint8_t>::proxy::operator=(
const uint8_t& rhs) {
Expand Down Expand Up @@ -119,19 +124,6 @@ inline r_vector<uint8_t>::r_vector(std::initializer_list<named_arg> il)
}
}

template <>
inline void r_vector<uint8_t>::reserve(R_xlen_t new_capacity) {
data_ = data_ == R_NilValue ? safe[Rf_allocVector](RAWSXP, new_capacity)
: safe[Rf_xlengthgets](data_, new_capacity);

SEXP old_protect = protect_;
protect_ = detail::store::insert(data_);
detail::store::release(old_protect);

data_p_ = RAW(data_);
capacity_ = new_capacity;
}

template <>
inline void r_vector<uint8_t>::push_back(uint8_t value) {
while (length_ >= capacity_) {
Expand Down
17 changes: 5 additions & 12 deletions inst/include/cpp11/strings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ typedef r_vector<r_string> strings;

namespace writable {

template <>
inline SEXPTYPE r_vector<r_string>::get_sexptype() {
return STRSXP;
}

template <>
inline typename r_vector<r_string>::proxy& r_vector<r_string>::proxy::operator=(
const r_string& rhs) {
Expand Down Expand Up @@ -136,18 +141,6 @@ inline r_vector<r_string>::r_vector(std::initializer_list<named_arg> il)
}
}

template <>
inline void r_vector<r_string>::reserve(R_xlen_t new_capacity) {
data_ = data_ == R_NilValue ? safe[Rf_allocVector](STRSXP, new_capacity)
: safe[Rf_xlengthgets](data_, new_capacity);

SEXP old_protect = protect_;
protect_ = detail::store::insert(data_);
detail::store::release(old_protect);

capacity_ = new_capacity;
}

template <>
inline void r_vector<r_string>::push_back(r_string value) {
while (length_ >= capacity_) {
Expand Down

0 comments on commit 457c441

Please sign in to comment.