1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
|
#pragma once
#include <limits> // for numeric_limits
#include <ostream>
#include <type_traits> // for is_convertible, enable_if
#include "R_ext/Boolean.h" // for Rboolean
#include "cpp11/R.hpp" // for SEXP, SEXPREC, ...
#include "cpp11/as.hpp" // for as_sexp
#include "cpp11/protect.hpp" // for unwind_protect
#include "cpp11/r_vector.hpp"
#include "cpp11/sexp.hpp" // for sexp
namespace cpp11 {
class r_bool {
public:
r_bool() = default;
r_bool(SEXP data) {
if (Rf_isLogical(data)) {
if (Rf_xlength(data) == 1) {
value_ = static_cast<Rboolean>(LOGICAL_ELT(data, 0));
}
}
throw std::invalid_argument("Invalid r_bool value");
}
r_bool(bool value) : value_(value ? TRUE : FALSE) {}
r_bool(Rboolean value) : value_(value) {}
r_bool(int value) : value_(from_int(value)) {}
operator bool() const { return value_ == TRUE; }
operator int() const { return value_; }
operator Rboolean() const { return value_ ? TRUE : FALSE; }
bool operator==(r_bool rhs) const { return value_ == rhs.value_; }
bool operator==(bool rhs) const { return operator==(r_bool(rhs)); }
bool operator==(Rboolean rhs) const { return operator==(r_bool(rhs)); }
bool operator==(int rhs) const { return operator==(r_bool(rhs)); }
private:
static constexpr int na = std::numeric_limits<int>::min();
static int from_int(int value) {
if (value == static_cast<int>(FALSE)) return FALSE;
if (value == static_cast<int>(na)) return na;
return TRUE;
}
int value_ = na;
};
inline std::ostream& operator<<(std::ostream& os, r_bool const& value) {
os << ((value == TRUE) ? "TRUE" : "FALSE");
return os;
}
template <typename T, typename R = void>
using enable_if_r_bool = enable_if_t<std::is_same<T, r_bool>::value, R>;
template <typename T>
enable_if_r_bool<T, SEXP> as_sexp(T from) {
sexp res = Rf_allocVector(LGLSXP, 1);
unwind_protect([&] { SET_LOGICAL_ELT(res.data(), 0, from); });
return res;
}
template <>
inline r_bool na() {
return NA_LOGICAL;
}
namespace traits {
template <>
struct get_underlying_type<r_bool> {
using type = int;
};
} // namespace traits
} // namespace cpp11
|