Skip to content

Commit 888afdb

Browse files
committed
Unify valid_type() implementations
1 parent 364e713 commit 888afdb

File tree

7 files changed

+62
-115
lines changed

7 files changed

+62
-115
lines changed

inst/include/cpp11/doubles.hpp

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,18 @@
1616

1717
namespace cpp11 {
1818

19+
template <>
20+
inline SEXPTYPE r_vector<double>::get_sexptype() {
21+
return REALSXP;
22+
}
23+
1924
template <>
2025
inline typename r_vector<double>::underlying_type r_vector<double>::get_elt(SEXP x,
2126
R_xlen_t i) {
2227
// NOPROTECT: likely too costly to unwind protect every elt
2328
return REAL_ELT(x, i);
2429
}
2530

26-
template <>
27-
inline SEXP r_vector<double>::valid_type(SEXP data) {
28-
if (data == nullptr) {
29-
throw type_error(REALSXP, NILSXP);
30-
}
31-
if (TYPEOF(data) != REALSXP) {
32-
throw type_error(REALSXP, TYPEOF(data));
33-
}
34-
return data;
35-
}
36-
3731
template <>
3832
inline typename r_vector<double>::underlying_type* r_vector<double>::get_p(bool is_altrep,
3933
SEXP data) {
@@ -60,11 +54,6 @@ typedef r_vector<double> doubles;
6054

6155
namespace writable {
6256

63-
template <>
64-
inline SEXPTYPE r_vector<double>::get_sexptype() {
65-
return REALSXP;
66-
}
67-
6857
template <>
6958
inline void r_vector<double>::set_elt(SEXP x, R_xlen_t i,
7059
typename r_vector::underlying_type value) {

inst/include/cpp11/integers.hpp

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,18 @@
1717

1818
namespace cpp11 {
1919

20+
template <>
21+
inline SEXPTYPE r_vector<int>::get_sexptype() {
22+
return INTSXP;
23+
}
24+
2025
template <>
2126
inline typename r_vector<int>::underlying_type r_vector<int>::get_elt(SEXP x,
2227
R_xlen_t i) {
2328
// NOPROTECT: likely too costly to unwind protect every elt
2429
return INTEGER_ELT(x, i);
2530
}
2631

27-
template <>
28-
inline SEXP r_vector<int>::valid_type(SEXP data) {
29-
if (data == nullptr) {
30-
throw type_error(INTSXP, NILSXP);
31-
}
32-
if (TYPEOF(data) != INTSXP) {
33-
throw type_error(INTSXP, TYPEOF(data));
34-
}
35-
return data;
36-
}
37-
3832
template <>
3933
inline typename r_vector<int>::underlying_type* r_vector<int>::get_p(bool is_altrep,
4034
SEXP data) {
@@ -61,11 +55,6 @@ typedef r_vector<int> integers;
6155

6256
namespace writable {
6357

64-
template <>
65-
inline SEXPTYPE r_vector<int>::get_sexptype() {
66-
return INTSXP;
67-
}
68-
6958
template <>
7059
inline void r_vector<int>::set_elt(SEXP x, R_xlen_t i,
7160
typename r_vector::underlying_type value) {

inst/include/cpp11/list.hpp

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,18 @@
1414

1515
namespace cpp11 {
1616

17+
template <>
18+
inline SEXPTYPE r_vector<SEXP>::get_sexptype() {
19+
return VECSXP;
20+
}
21+
1722
template <>
1823
inline typename r_vector<SEXP>::underlying_type r_vector<SEXP>::get_elt(SEXP x,
1924
R_xlen_t i) {
2025
// NOPROTECT: likely too costly to unwind protect every elt
2126
return VECTOR_ELT(x, i);
2227
}
2328

24-
template <>
25-
inline SEXP r_vector<SEXP>::valid_type(SEXP data) {
26-
if (data == nullptr) {
27-
throw type_error(VECSXP, NILSXP);
28-
}
29-
if (TYPEOF(data) != VECSXP) {
30-
throw type_error(VECSXP, TYPEOF(data));
31-
}
32-
return data;
33-
}
34-
3529
template <>
3630
inline SEXP r_vector<SEXP>::operator[](const r_string& name) const {
3731
SEXP names = this->names();
@@ -71,11 +65,6 @@ typedef r_vector<SEXP> list;
7165

7266
namespace writable {
7367

74-
template <>
75-
inline SEXPTYPE r_vector<SEXP>::get_sexptype() {
76-
return VECSXP;
77-
}
78-
7968
template <>
8069
inline void r_vector<SEXP>::set_elt(SEXP x, R_xlen_t i,
8170
typename r_vector::underlying_type value) {

inst/include/cpp11/logicals.hpp

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,18 @@
1616

1717
namespace cpp11 {
1818

19+
template <>
20+
inline SEXPTYPE r_vector<r_bool>::get_sexptype() {
21+
return LGLSXP;
22+
}
23+
1924
template <>
2025
inline typename r_vector<r_bool>::underlying_type r_vector<r_bool>::get_elt(SEXP x,
2126
R_xlen_t i) {
2227
// NOPROTECT: likely too costly to unwind protect every elt
2328
return LOGICAL_ELT(x, i);
2429
}
2530

26-
template <>
27-
inline SEXP r_vector<r_bool>::valid_type(SEXP data) {
28-
if (data == nullptr) {
29-
throw type_error(LGLSXP, NILSXP);
30-
}
31-
if (TYPEOF(data) != LGLSXP) {
32-
throw type_error(LGLSXP, TYPEOF(data));
33-
}
34-
return data;
35-
}
36-
3731
template <>
3832
inline typename r_vector<r_bool>::underlying_type* r_vector<r_bool>::get_p(bool is_altrep,
3933
SEXP data) {
@@ -60,11 +54,6 @@ typedef r_vector<r_bool> logicals;
6054

6155
namespace writable {
6256

63-
template <>
64-
inline SEXPTYPE r_vector<r_bool>::get_sexptype() {
65-
return LGLSXP;
66-
}
67-
6857
template <>
6958
inline void r_vector<r_bool>::set_elt(SEXP x, R_xlen_t i,
7059
typename r_vector::underlying_type value) {

inst/include/cpp11/r_vector.hpp

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,8 @@ class r_vector {
149149
/// Implemented in specialization
150150
static void get_region(SEXP x, R_xlen_t i, R_xlen_t n, underlying_type* buf);
151151
/// Implemented in specialization
152-
static SEXP valid_type(SEXP data);
152+
static SEXPTYPE get_sexptype();
153+
static SEXP valid_type(SEXP x);
153154

154155
friend class writable::r_vector<T>;
155156
};
@@ -308,12 +309,11 @@ class r_vector : public cpp11::r_vector<T> {
308309
};
309310

310311
private:
311-
/// Implemented in specialization
312-
static SEXPTYPE get_sexptype();
313312
/// Implemented in specialization
314313
static void set_elt(SEXP x, R_xlen_t i, underlying_type value);
315314

316315
using cpp11::r_vector<T>::get_p;
316+
using cpp11::r_vector<T>::get_sexptype;
317317
};
318318
} // namespace writable
319319

@@ -559,6 +559,35 @@ inline r_vector<r_string> r_vector<T>::names() const {
559559
}
560560
}
561561

562+
class type_error : public std::exception {
563+
public:
564+
type_error(int expected, int actual) : expected_(expected), actual_(actual) {}
565+
virtual const char* what() const noexcept override {
566+
snprintf(str_, 64, "Invalid input type, expected '%s' actual '%s'",
567+
Rf_type2char(expected_), Rf_type2char(actual_));
568+
return str_;
569+
}
570+
571+
private:
572+
int expected_;
573+
int actual_;
574+
mutable char str_[64];
575+
};
576+
577+
template <typename T>
578+
inline SEXP r_vector<T>::valid_type(SEXP x) {
579+
const SEXPTYPE type = get_sexptype();
580+
581+
if (x == nullptr) {
582+
throw type_error(type, NILSXP);
583+
}
584+
if (TYPEOF(x) != type) {
585+
throw type_error(type, TYPEOF(x));
586+
}
587+
588+
return x;
589+
}
590+
562591
template <typename T>
563592
inline typename r_vector<T>::const_iterator r_vector<T>::begin() const {
564593
return const_iterator(this, 0);
@@ -1200,20 +1229,4 @@ bool operator!=(const r_vector<T>& lhs, const r_vector<T>& rhs) {
12001229
return !(lhs == rhs);
12011230
}
12021231

1203-
// Special helper class used by specializations to throw consistent exceptions
1204-
class type_error : public std::exception {
1205-
public:
1206-
type_error(int expected, int actual) : expected_(expected), actual_(actual) {}
1207-
virtual const char* what() const noexcept override {
1208-
snprintf(str_, 64, "Invalid input type, expected '%s' actual '%s'",
1209-
Rf_type2char(expected_), Rf_type2char(actual_));
1210-
return str_;
1211-
}
1212-
1213-
private:
1214-
int expected_;
1215-
int actual_;
1216-
mutable char str_[64];
1217-
};
1218-
12191232
} // namespace cpp11

inst/include/cpp11/raws.hpp

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,24 +24,18 @@ struct get_underlying_type<uint8_t> {
2424
};
2525
} // namespace traits
2626

27+
template <>
28+
inline SEXPTYPE r_vector<uint8_t>::get_sexptype() {
29+
return RAWSXP;
30+
}
31+
2732
template <>
2833
inline typename r_vector<uint8_t>::underlying_type r_vector<uint8_t>::get_elt(
2934
SEXP x, R_xlen_t i) {
3035
// NOPROTECT: likely too costly to unwind protect every elt
3136
return RAW_ELT(x, i);
3237
}
3338

34-
template <>
35-
inline SEXP r_vector<uint8_t>::valid_type(SEXP data) {
36-
if (data == nullptr) {
37-
throw type_error(RAWSXP, NILSXP);
38-
}
39-
if (TYPEOF(data) != RAWSXP) {
40-
throw type_error(RAWSXP, TYPEOF(data));
41-
}
42-
return data;
43-
}
44-
4539
template <>
4640
inline typename r_vector<uint8_t>::underlying_type* r_vector<uint8_t>::get_p(
4741
bool is_altrep, SEXP data) {
@@ -68,11 +62,6 @@ typedef r_vector<uint8_t> raws;
6862

6963
namespace writable {
7064

71-
template <>
72-
inline SEXPTYPE r_vector<uint8_t>::get_sexptype() {
73-
return RAWSXP;
74-
}
75-
7665
template <>
7766
inline void r_vector<uint8_t>::set_elt(SEXP x, R_xlen_t i,
7867
typename r_vector::underlying_type value) {

inst/include/cpp11/strings.hpp

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,18 @@
1616

1717
namespace cpp11 {
1818

19+
template <>
20+
inline SEXPTYPE r_vector<r_string>::get_sexptype() {
21+
return STRSXP;
22+
}
23+
1924
template <>
2025
inline typename r_vector<r_string>::underlying_type r_vector<r_string>::get_elt(
2126
SEXP x, R_xlen_t i) {
2227
// NOPROTECT: likely too costly to unwind protect every elt
2328
return STRING_ELT(x, i);
2429
}
2530

26-
template <>
27-
inline SEXP r_vector<r_string>::valid_type(SEXP data) {
28-
if (data == nullptr) {
29-
throw type_error(STRSXP, NILSXP);
30-
}
31-
if (TYPEOF(data) != STRSXP) {
32-
throw type_error(STRSXP, TYPEOF(data));
33-
}
34-
return data;
35-
}
36-
3731
template <>
3832
inline typename r_vector<r_string>::underlying_type* r_vector<r_string>::get_p(bool,
3933
SEXP) {
@@ -60,11 +54,6 @@ typedef r_vector<r_string> strings;
6054

6155
namespace writable {
6256

63-
template <>
64-
inline SEXPTYPE r_vector<r_string>::get_sexptype() {
65-
return STRSXP;
66-
}
67-
6857
template <>
6958
inline void r_vector<r_string>::set_elt(SEXP x, R_xlen_t i,
7059
typename r_vector::underlying_type value) {

0 commit comments

Comments
 (0)