Skip to content

Commit

Permalink
Merge pull request #387 from duckdb/f-382-cpp11
Browse files Browse the repository at this point in the history
feat: Bump vendored cpp11 to v0.5.0
  • Loading branch information
krlmlr authored Sep 24, 2024
2 parents 6670f8b + f05d56c commit dea42c8
Show file tree
Hide file tree
Showing 24 changed files with 1,349 additions and 1,161 deletions.
4 changes: 2 additions & 2 deletions inst/include/cpp11.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// cpp11 version: 0.4.7
// vendored on: 2024-06-26
// cpp11 version: 0.5.0
// vendored on: 2024-09-24
#pragma once

#include "cpp11/R.hpp"
Expand Down
73 changes: 71 additions & 2 deletions inst/include/cpp11/R.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// cpp11 version: 0.4.7
// vendored on: 2024-06-26
// cpp11 version: 0.5.0
// vendored on: 2024-09-24
#pragma once

#ifdef R_INTERNALS_H_
Expand All @@ -12,7 +12,9 @@

#define R_NO_REMAP
#define STRICT_R_HEADERS
#include "R_ext/Boolean.h"
#include "Rinternals.h"
#include "Rversion.h"

// clang-format off
#ifdef __clang__
Expand All @@ -29,6 +31,18 @@
#include <type_traits>
#include "cpp11/altrep.hpp"

#if defined(R_VERSION) && R_VERSION >= R_Version(4, 4, 0)
// Use R's new macro
#define CPP11_PRIdXLEN_T R_PRIdXLEN_T
#else
// Recreate what new R does
#ifdef LONG_VECTOR_SUPPORT
#define CPP11_PRIdXLEN_T "td"
#else
#define CPP11_PRIdXLEN_T "d"
#endif
#endif

namespace cpp11 {
namespace literals {

Expand All @@ -43,6 +57,61 @@ struct get_underlying_type {
};
} // namespace traits

namespace detail {

// Annoyingly, `TYPEOF()` returns an `int` rather than a `SEXPTYPE`,
// which can throw warnings with `-Wsign-compare` on Windows.
inline SEXPTYPE r_typeof(SEXP x) { return static_cast<SEXPTYPE>(TYPEOF(x)); }

/// Get an object from an environment
///
/// SAFETY: Keep as a pure C function. Call like an R API function, i.e. wrap in `safe[]`
/// as required.
inline SEXP r_env_get(SEXP env, SEXP sym) {
#if defined(R_VERSION) && R_VERSION >= R_Version(4, 5, 0)
const Rboolean inherits = FALSE;
return R_getVar(sym, env, inherits);
#else
SEXP out = Rf_findVarInFrame3(env, sym, TRUE);

// Replicate the 3 checks from `R_getVar()` (along with exact error message):
// - Object must be found in the `env`
// - `R_MissingArg` can't leak from an `env` anymore
// - Promises can't leak from an `env` anymore

if (out == R_MissingArg) {
Rf_errorcall(R_NilValue, "argument \"%s\" is missing, with no default",
CHAR(PRINTNAME(sym)));
}

if (out == R_UnboundValue) {
Rf_errorcall(R_NilValue, "object '%s' not found", CHAR(PRINTNAME(sym)));
}

if (r_typeof(out) == PROMSXP) {
PROTECT(out);
out = Rf_eval(out, env);
UNPROTECT(1);
}

return out;
#endif
}

/// Check if an object exists in an environment
///
/// SAFETY: Keep as a pure C function. Call like an R API function, i.e. wrap in `safe[]`
/// as required.
inline bool r_env_has(SEXP env, SEXP sym) {
#if R_VERSION >= R_Version(4, 2, 0)
return R_existsVarInFrame(env, sym);
#else
return Rf_findVarInFrame3(env, sym, FALSE) != R_UnboundValue;
#endif
}

} // namespace detail

template <typename T>
inline T na();

Expand Down
4 changes: 2 additions & 2 deletions inst/include/cpp11/altrep.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// cpp11 version: 0.4.7
// vendored on: 2024-06-26
// cpp11 version: 0.5.0
// vendored on: 2024-09-24
#pragma once

#include "Rversion.h"
Expand Down
4 changes: 2 additions & 2 deletions inst/include/cpp11/as.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// cpp11 version: 0.4.7
// vendored on: 2024-06-26
// cpp11 version: 0.5.0
// vendored on: 2024-09-24
#pragma once

#include <cmath> // for modf
Expand Down
4 changes: 2 additions & 2 deletions inst/include/cpp11/attribute_proxy.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// cpp11 version: 0.4.7
// vendored on: 2024-06-26
// cpp11 version: 0.5.0
// vendored on: 2024-09-24
#pragma once

#include <initializer_list> // for initializer_list
Expand Down
16 changes: 11 additions & 5 deletions inst/include/cpp11/data_frame.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// cpp11 version: 0.4.7
// vendored on: 2024-06-26
// cpp11 version: 0.5.0
// vendored on: 2024-09-24
#pragma once

#include <cstdlib> // for abs
Expand Down Expand Up @@ -38,12 +38,12 @@ class data_frame : public list {
return R_NilValue;
}

static int calc_nrow(SEXP x) {
static R_xlen_t calc_nrow(SEXP x) {
auto nms = get_attrib0(x, R_RowNamesSymbol);
bool has_short_rownames =
(Rf_isInteger(nms) && Rf_xlength(nms) == 2 && INTEGER(nms)[0] == NA_INTEGER);
if (has_short_rownames) {
return abs(INTEGER(nms)[1]);
return static_cast<R_xlen_t>(abs(INTEGER(nms)[1]));
}

if (!Rf_isNull(nms)) {
Expand All @@ -69,7 +69,11 @@ namespace writable {
class data_frame : public cpp11::data_frame {
private:
writable::list set_data_frame_attributes(writable::list&& x) {
x.attr(R_RowNamesSymbol) = {NA_INTEGER, -static_cast<int>(calc_nrow(x))};
return set_data_frame_attributes(std::move(x), calc_nrow(x));
}

writable::list set_data_frame_attributes(writable::list&& x, R_xlen_t nrow) {
x.attr(R_RowNamesSymbol) = {NA_INTEGER, -static_cast<int>(nrow)};
x.attr(R_ClassSymbol) = "data.frame";
return std::move(x);
}
Expand All @@ -78,6 +82,8 @@ class data_frame : public cpp11::data_frame {
data_frame(const SEXP data) : cpp11::data_frame(set_data_frame_attributes(data)) {}
data_frame(const SEXP data, bool is_altrep)
: cpp11::data_frame(set_data_frame_attributes(data), is_altrep) {}
data_frame(const SEXP data, bool is_altrep, R_xlen_t nrow)
: cpp11::data_frame(set_data_frame_attributes(data, nrow), is_altrep) {}
data_frame(std::initializer_list<list> il)
: cpp11::data_frame(set_data_frame_attributes(writable::list(il))) {}
data_frame(std::initializer_list<named_arg> il)
Expand Down
4 changes: 2 additions & 2 deletions inst/include/cpp11/declarations.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// cpp11 version: 0.4.7
// vendored on: 2024-06-26
// cpp11 version: 0.5.0
// vendored on: 2024-09-24
#pragma once

#include <cstring>
Expand Down
129 changes: 32 additions & 97 deletions inst/include/cpp11/doubles.hpp
Original file line number Diff line number Diff line change
@@ -1,38 +1,32 @@
// cpp11 version: 0.4.7
// vendored on: 2024-06-26
// cpp11 version: 0.5.0
// vendored on: 2024-09-24
#pragma once

#include <algorithm> // for min, tranform
#include <array> // for array
#include <initializer_list> // for initializer_list

#include "R_ext/Arith.h" // for ISNA
#include "cpp11/R.hpp" // for SEXP, SEXPREC, Rf_allocVector, REAL
#include "cpp11/as.hpp" // for as_sexp
#include "cpp11/named_arg.hpp" // for named_arg
#include "cpp11/protect.hpp" // for SEXP, SEXPREC, REAL_ELT, R_Preserve...
#include "cpp11/r_vector.hpp" // for vector, vector<>::proxy, vector<>::...
#include "cpp11/sexp.hpp" // for sexp
#include "R_ext/Arith.h" // for ISNA
#include "cpp11/R.hpp" // for SEXP, SEXPREC, Rf_allocVector, REAL
#include "cpp11/as.hpp" // for as_sexp
#include "cpp11/protect.hpp" // for safe
#include "cpp11/r_vector.hpp" // for vector, vector<>::proxy, vector<>::...
#include "cpp11/sexp.hpp" // for sexp

// Specializations for doubles

namespace cpp11 {

template <>
inline SEXP r_vector<double>::valid_type(SEXP data) {
if (data == nullptr) {
throw type_error(REALSXP, NILSXP);
}
if (TYPEOF(data) != REALSXP) {
throw type_error(REALSXP, TYPEOF(data));
}
return data;
inline SEXPTYPE r_vector<double>::get_sexptype() {
return REALSXP;
}

template <>
inline double r_vector<double>::operator[](const R_xlen_t pos) const {
inline typename r_vector<double>::underlying_type r_vector<double>::get_elt(SEXP x,
R_xlen_t i) {
// NOPROTECT: likely too costly to unwind protect every elt
return is_altrep_ ? REAL_ELT(data_, pos) : data_p_[pos];
return REAL_ELT(x, i);
}

template <>
Expand All @@ -46,91 +40,32 @@ inline typename r_vector<double>::underlying_type* r_vector<double>::get_p(bool
}

template <>
inline void r_vector<double>::const_iterator::fill_buf(R_xlen_t pos) {
length_ = std::min(64_xl, data_->size() - pos);
REAL_GET_REGION(data_->data_, pos, length_, buf_.data());
block_start_ = pos;
inline typename r_vector<double>::underlying_type const* r_vector<double>::get_const_p(
bool is_altrep, SEXP data) {
return REAL_OR_NULL(data);
}

typedef r_vector<double> doubles;

namespace writable {

template <>
inline typename r_vector<double>::proxy& r_vector<double>::proxy::operator=(
const double& rhs) {
if (is_altrep_) {
// NOPROTECT: likely too costly to unwind protect every set elt
SET_REAL_ELT(data_, index_, rhs);
} else {
*p_ = rhs;
}
return *this;
}
inline void r_vector<double>::get_region(SEXP x, R_xlen_t i, R_xlen_t n,
typename r_vector::underlying_type* buf) {
// NOPROTECT: likely too costly to unwind protect here
REAL_GET_REGION(x, i, n, buf);
};

template <>
inline r_vector<double>::proxy::operator double() const {
if (p_ == nullptr) {
// NOPROTECT: likely too costly to unwind protect every elt
return REAL_ELT(data_, index_);
} else {
return *p_;
}
inline bool r_vector<double>::const_iterator::use_buf(bool is_altrep) {
return is_altrep;
}

template <>
inline r_vector<double>::r_vector(std::initializer_list<double> il)
: cpp11::r_vector<double>(as_sexp(il)), capacity_(il.size()) {}

template <>
inline r_vector<double>::r_vector(std::initializer_list<named_arg> il)
: cpp11::r_vector<double>(safe[Rf_allocVector](REALSXP, il.size())),
capacity_(il.size()) {
protect_ = preserved.insert(data_);
int n_protected = 0;

try {
unwind_protect([&] {
Rf_setAttrib(data_, R_NamesSymbol, Rf_allocVector(STRSXP, capacity_));
SEXP names = PROTECT(Rf_getAttrib(data_, R_NamesSymbol));
++n_protected;
auto it = il.begin();
for (R_xlen_t i = 0; i < capacity_; ++i, ++it) {
data_p_[i] = REAL_ELT(it->value(), 0);
SET_STRING_ELT(names, i, Rf_mkCharCE(it->name(), CE_UTF8));
}
UNPROTECT(n_protected);
});
} catch (const unwind_exception& e) {
preserved.release(protect_);
UNPROTECT(n_protected);
throw e;
}
}
typedef r_vector<double> doubles;

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_ = preserved.insert(data_);
preserved.release(old_protect);

data_p_ = REAL(data_);
capacity_ = new_capacity;
}
namespace writable {

template <>
inline void r_vector<double>::push_back(double value) {
while (length_ >= capacity_) {
reserve(capacity_ == 0 ? 1 : capacity_ *= 2);
}
if (is_altrep_) {
SET_REAL_ELT(data_, length_, value);
} else {
data_p_[length_] = value;
}
++length_;
inline void r_vector<double>::set_elt(SEXP x, R_xlen_t i,
typename r_vector::underlying_type value) {
// NOPROTECT: Likely too costly to unwind protect every set elt
SET_REAL_ELT(x, i, value);
}

typedef r_vector<double> doubles;
Expand All @@ -140,11 +75,11 @@ typedef r_vector<double> doubles;
typedef r_vector<int> integers;

inline doubles as_doubles(SEXP x) {
if (TYPEOF(x) == REALSXP) {
if (detail::r_typeof(x) == REALSXP) {
return doubles(x);
}

else if (TYPEOF(x) == INTSXP) {
else if (detail::r_typeof(x) == INTSXP) {
integers xn(x);
size_t len = xn.size();
writable::doubles ret(len);
Expand All @@ -154,7 +89,7 @@ inline doubles as_doubles(SEXP x) {
return ret;
}

throw type_error(REALSXP, TYPEOF(x));
throw type_error(REALSXP, detail::r_typeof(x));
}

template <>
Expand Down
Loading

0 comments on commit dea42c8

Please sign in to comment.