Skip to content

Commit 0b27a52

Browse files
committed
Vendor cpp11 0.5.0
1 parent e25be7a commit 0b27a52

24 files changed

+1349
-1160
lines changed

inst/include/cpp11.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// cpp11 version: 0.4.7
2-
// vendored on: 2024-06-26
1+
// cpp11 version: 0.5.0
2+
// vendored on: 2024-09-24
33
#pragma once
44

55
#include "cpp11/R.hpp"

inst/include/cpp11/R.hpp

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// cpp11 version: 0.4.7
2-
// vendored on: 2024-06-26
1+
// cpp11 version: 0.5.0
2+
// vendored on: 2024-09-24
33
#pragma once
44

55
#ifdef R_INTERNALS_H_
@@ -12,7 +12,9 @@
1212

1313
#define R_NO_REMAP
1414
#define STRICT_R_HEADERS
15+
#include "R_ext/Boolean.h"
1516
#include "Rinternals.h"
17+
#include "Rversion.h"
1618

1719
// clang-format off
1820
#ifdef __clang__
@@ -29,6 +31,18 @@
2931
#include <type_traits>
3032
#include "cpp11/altrep.hpp"
3133

34+
#if defined(R_VERSION) && R_VERSION >= R_Version(4, 4, 0)
35+
// Use R's new macro
36+
#define CPP11_PRIdXLEN_T R_PRIdXLEN_T
37+
#else
38+
// Recreate what new R does
39+
#ifdef LONG_VECTOR_SUPPORT
40+
#define CPP11_PRIdXLEN_T "td"
41+
#else
42+
#define CPP11_PRIdXLEN_T "d"
43+
#endif
44+
#endif
45+
3246
namespace cpp11 {
3347
namespace literals {
3448

@@ -43,6 +57,61 @@ struct get_underlying_type {
4357
};
4458
} // namespace traits
4559

60+
namespace detail {
61+
62+
// Annoyingly, `TYPEOF()` returns an `int` rather than a `SEXPTYPE`,
63+
// which can throw warnings with `-Wsign-compare` on Windows.
64+
inline SEXPTYPE r_typeof(SEXP x) { return static_cast<SEXPTYPE>(TYPEOF(x)); }
65+
66+
/// Get an object from an environment
67+
///
68+
/// SAFETY: Keep as a pure C function. Call like an R API function, i.e. wrap in `safe[]`
69+
/// as required.
70+
inline SEXP r_env_get(SEXP env, SEXP sym) {
71+
#if defined(R_VERSION) && R_VERSION >= R_Version(4, 5, 0)
72+
const Rboolean inherits = FALSE;
73+
return R_getVar(sym, env, inherits);
74+
#else
75+
SEXP out = Rf_findVarInFrame3(env, sym, TRUE);
76+
77+
// Replicate the 3 checks from `R_getVar()` (along with exact error message):
78+
// - Object must be found in the `env`
79+
// - `R_MissingArg` can't leak from an `env` anymore
80+
// - Promises can't leak from an `env` anymore
81+
82+
if (out == R_MissingArg) {
83+
Rf_errorcall(R_NilValue, "argument \"%s\" is missing, with no default",
84+
CHAR(PRINTNAME(sym)));
85+
}
86+
87+
if (out == R_UnboundValue) {
88+
Rf_errorcall(R_NilValue, "object '%s' not found", CHAR(PRINTNAME(sym)));
89+
}
90+
91+
if (r_typeof(out) == PROMSXP) {
92+
PROTECT(out);
93+
out = Rf_eval(out, env);
94+
UNPROTECT(1);
95+
}
96+
97+
return out;
98+
#endif
99+
}
100+
101+
/// Check if an object exists in an environment
102+
///
103+
/// SAFETY: Keep as a pure C function. Call like an R API function, i.e. wrap in `safe[]`
104+
/// as required.
105+
inline bool r_env_has(SEXP env, SEXP sym) {
106+
#if R_VERSION >= R_Version(4, 2, 0)
107+
return R_existsVarInFrame(env, sym);
108+
#else
109+
return Rf_findVarInFrame3(env, sym, FALSE) != R_UnboundValue;
110+
#endif
111+
}
112+
113+
} // namespace detail
114+
46115
template <typename T>
47116
inline T na();
48117

inst/include/cpp11/altrep.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// cpp11 version: 0.4.7
2-
// vendored on: 2024-06-26
1+
// cpp11 version: 0.5.0
2+
// vendored on: 2024-09-24
33
#pragma once
44

55
#include "Rversion.h"

inst/include/cpp11/as.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// cpp11 version: 0.4.7
2-
// vendored on: 2024-06-26
1+
// cpp11 version: 0.5.0
2+
// vendored on: 2024-09-24
33
#pragma once
44

55
#include <cmath> // for modf

inst/include/cpp11/attribute_proxy.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// cpp11 version: 0.4.7
2-
// vendored on: 2024-06-26
1+
// cpp11 version: 0.5.0
2+
// vendored on: 2024-09-24
33
#pragma once
44

55
#include <initializer_list> // for initializer_list

inst/include/cpp11/data_frame.hpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// cpp11 version: 0.4.7
2-
// vendored on: 2024-06-26
1+
// cpp11 version: 0.5.0
2+
// vendored on: 2024-09-24
33
#pragma once
44

55
#include <cstdlib> // for abs
@@ -38,12 +38,12 @@ class data_frame : public list {
3838
return R_NilValue;
3939
}
4040

41-
static int calc_nrow(SEXP x) {
41+
static R_xlen_t calc_nrow(SEXP x) {
4242
auto nms = get_attrib0(x, R_RowNamesSymbol);
4343
bool has_short_rownames =
4444
(Rf_isInteger(nms) && Rf_xlength(nms) == 2 && INTEGER(nms)[0] == NA_INTEGER);
4545
if (has_short_rownames) {
46-
return abs(INTEGER(nms)[1]);
46+
return static_cast<R_xlen_t>(abs(INTEGER(nms)[1]));
4747
}
4848

4949
if (!Rf_isNull(nms)) {
@@ -69,7 +69,11 @@ namespace writable {
6969
class data_frame : public cpp11::data_frame {
7070
private:
7171
writable::list set_data_frame_attributes(writable::list&& x) {
72-
x.attr(R_RowNamesSymbol) = {NA_INTEGER, -static_cast<int>(calc_nrow(x))};
72+
return set_data_frame_attributes(std::move(x), calc_nrow(x));
73+
}
74+
75+
writable::list set_data_frame_attributes(writable::list&& x, R_xlen_t nrow) {
76+
x.attr(R_RowNamesSymbol) = {NA_INTEGER, -static_cast<int>(nrow)};
7377
x.attr(R_ClassSymbol) = "data.frame";
7478
return std::move(x);
7579
}
@@ -78,6 +82,8 @@ class data_frame : public cpp11::data_frame {
7882
data_frame(const SEXP data) : cpp11::data_frame(set_data_frame_attributes(data)) {}
7983
data_frame(const SEXP data, bool is_altrep)
8084
: cpp11::data_frame(set_data_frame_attributes(data), is_altrep) {}
85+
data_frame(const SEXP data, bool is_altrep, R_xlen_t nrow)
86+
: cpp11::data_frame(set_data_frame_attributes(data, nrow), is_altrep) {}
8187
data_frame(std::initializer_list<list> il)
8288
: cpp11::data_frame(set_data_frame_attributes(writable::list(il))) {}
8389
data_frame(std::initializer_list<named_arg> il)

inst/include/cpp11/declarations.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// cpp11 version: 0.4.7
2-
// vendored on: 2024-06-26
1+
// cpp11 version: 0.5.0
2+
// vendored on: 2024-09-24
33
#pragma once
44

55
#include <cstring>

inst/include/cpp11/doubles.hpp

Lines changed: 32 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,32 @@
1-
// cpp11 version: 0.4.7
2-
// vendored on: 2024-06-26
1+
// cpp11 version: 0.5.0
2+
// vendored on: 2024-09-24
33
#pragma once
44

55
#include <algorithm> // for min, tranform
66
#include <array> // for array
77
#include <initializer_list> // for initializer_list
88

9-
#include "R_ext/Arith.h" // for ISNA
10-
#include "cpp11/R.hpp" // for SEXP, SEXPREC, Rf_allocVector, REAL
11-
#include "cpp11/as.hpp" // for as_sexp
12-
#include "cpp11/named_arg.hpp" // for named_arg
13-
#include "cpp11/protect.hpp" // for SEXP, SEXPREC, REAL_ELT, R_Preserve...
14-
#include "cpp11/r_vector.hpp" // for vector, vector<>::proxy, vector<>::...
15-
#include "cpp11/sexp.hpp" // for sexp
9+
#include "R_ext/Arith.h" // for ISNA
10+
#include "cpp11/R.hpp" // for SEXP, SEXPREC, Rf_allocVector, REAL
11+
#include "cpp11/as.hpp" // for as_sexp
12+
#include "cpp11/protect.hpp" // for safe
13+
#include "cpp11/r_vector.hpp" // for vector, vector<>::proxy, vector<>::...
14+
#include "cpp11/sexp.hpp" // for sexp
1615

1716
// Specializations for doubles
1817

1918
namespace cpp11 {
2019

2120
template <>
22-
inline SEXP r_vector<double>::valid_type(SEXP data) {
23-
if (data == nullptr) {
24-
throw type_error(REALSXP, NILSXP);
25-
}
26-
if (TYPEOF(data) != REALSXP) {
27-
throw type_error(REALSXP, TYPEOF(data));
28-
}
29-
return data;
21+
inline SEXPTYPE r_vector<double>::get_sexptype() {
22+
return REALSXP;
3023
}
3124

3225
template <>
33-
inline double r_vector<double>::operator[](const R_xlen_t pos) const {
26+
inline typename r_vector<double>::underlying_type r_vector<double>::get_elt(SEXP x,
27+
R_xlen_t i) {
3428
// NOPROTECT: likely too costly to unwind protect every elt
35-
return is_altrep_ ? REAL_ELT(data_, pos) : data_p_[pos];
29+
return REAL_ELT(x, i);
3630
}
3731

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

4842
template <>
49-
inline void r_vector<double>::const_iterator::fill_buf(R_xlen_t pos) {
50-
length_ = std::min(64_xl, data_->size() - pos);
51-
REAL_GET_REGION(data_->data_, pos, length_, buf_.data());
52-
block_start_ = pos;
43+
inline typename r_vector<double>::underlying_type const* r_vector<double>::get_const_p(
44+
bool is_altrep, SEXP data) {
45+
return REAL_OR_NULL(data);
5346
}
5447

55-
typedef r_vector<double> doubles;
56-
57-
namespace writable {
58-
5948
template <>
60-
inline typename r_vector<double>::proxy& r_vector<double>::proxy::operator=(
61-
const double& rhs) {
62-
if (is_altrep_) {
63-
// NOPROTECT: likely too costly to unwind protect every set elt
64-
SET_REAL_ELT(data_, index_, rhs);
65-
} else {
66-
*p_ = rhs;
67-
}
68-
return *this;
69-
}
49+
inline void r_vector<double>::get_region(SEXP x, R_xlen_t i, R_xlen_t n,
50+
typename r_vector::underlying_type* buf) {
51+
// NOPROTECT: likely too costly to unwind protect here
52+
REAL_GET_REGION(x, i, n, buf);
53+
};
7054

7155
template <>
72-
inline r_vector<double>::proxy::operator double() const {
73-
if (p_ == nullptr) {
74-
// NOPROTECT: likely too costly to unwind protect every elt
75-
return REAL_ELT(data_, index_);
76-
} else {
77-
return *p_;
78-
}
56+
inline bool r_vector<double>::const_iterator::use_buf(bool is_altrep) {
57+
return is_altrep;
7958
}
8059

81-
template <>
82-
inline r_vector<double>::r_vector(std::initializer_list<double> il)
83-
: cpp11::r_vector<double>(as_sexp(il)), capacity_(il.size()) {}
84-
85-
template <>
86-
inline r_vector<double>::r_vector(std::initializer_list<named_arg> il)
87-
: cpp11::r_vector<double>(safe[Rf_allocVector](REALSXP, il.size())),
88-
capacity_(il.size()) {
89-
protect_ = preserved.insert(data_);
90-
int n_protected = 0;
91-
92-
try {
93-
unwind_protect([&] {
94-
Rf_setAttrib(data_, R_NamesSymbol, Rf_allocVector(STRSXP, capacity_));
95-
SEXP names = PROTECT(Rf_getAttrib(data_, R_NamesSymbol));
96-
++n_protected;
97-
auto it = il.begin();
98-
for (R_xlen_t i = 0; i < capacity_; ++i, ++it) {
99-
data_p_[i] = REAL_ELT(it->value(), 0);
100-
SET_STRING_ELT(names, i, Rf_mkCharCE(it->name(), CE_UTF8));
101-
}
102-
UNPROTECT(n_protected);
103-
});
104-
} catch (const unwind_exception& e) {
105-
preserved.release(protect_);
106-
UNPROTECT(n_protected);
107-
throw e;
108-
}
109-
}
60+
typedef r_vector<double> doubles;
11061

111-
template <>
112-
inline void r_vector<double>::reserve(R_xlen_t new_capacity) {
113-
data_ = data_ == R_NilValue ? safe[Rf_allocVector](REALSXP, new_capacity)
114-
: safe[Rf_xlengthgets](data_, new_capacity);
115-
SEXP old_protect = protect_;
116-
protect_ = preserved.insert(data_);
117-
preserved.release(old_protect);
118-
119-
data_p_ = REAL(data_);
120-
capacity_ = new_capacity;
121-
}
62+
namespace writable {
12263

12364
template <>
124-
inline void r_vector<double>::push_back(double value) {
125-
while (length_ >= capacity_) {
126-
reserve(capacity_ == 0 ? 1 : capacity_ *= 2);
127-
}
128-
if (is_altrep_) {
129-
SET_REAL_ELT(data_, length_, value);
130-
} else {
131-
data_p_[length_] = value;
132-
}
133-
++length_;
65+
inline void r_vector<double>::set_elt(SEXP x, R_xlen_t i,
66+
typename r_vector::underlying_type value) {
67+
// NOPROTECT: Likely too costly to unwind protect every set elt
68+
SET_REAL_ELT(x, i, value);
13469
}
13570

13671
typedef r_vector<double> doubles;
@@ -140,11 +75,11 @@ typedef r_vector<double> doubles;
14075
typedef r_vector<int> integers;
14176

14277
inline doubles as_doubles(SEXP x) {
143-
if (TYPEOF(x) == REALSXP) {
78+
if (detail::r_typeof(x) == REALSXP) {
14479
return doubles(x);
14580
}
14681

147-
else if (TYPEOF(x) == INTSXP) {
82+
else if (detail::r_typeof(x) == INTSXP) {
14883
integers xn(x);
14984
size_t len = xn.size();
15085
writable::doubles ret(len);
@@ -154,7 +89,7 @@ inline doubles as_doubles(SEXP x) {
15489
return ret;
15590
}
15691

157-
throw type_error(REALSXP, TYPEOF(x));
92+
throw type_error(REALSXP, detail::r_typeof(x));
15893
}
15994

16095
template <>

0 commit comments

Comments
 (0)