summaryrefslogtreecommitdiffstats
path: root/src/arrow/r/inst/include/cpp11/logicals.hpp
blob: 5f96b3eab4030c1baf223758c162b576c0c56f07 (plain)
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// cpp11 version: 0.3.1.1
// vendored on: 2021-08-11
#pragma once

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

#include "cpp11/R.hpp"                // for SEXP, SEXPREC, Rf_all...
#include "cpp11/attribute_proxy.hpp"  // for attribute_proxy
#include "cpp11/named_arg.hpp"        // for named_arg
#include "cpp11/protect.hpp"          // for preserved
#include "cpp11/r_bool.hpp"           // for r_bool
#include "cpp11/r_vector.hpp"         // for r_vector, r_vector<>::proxy
#include "cpp11/sexp.hpp"             // for sexp

// Specializations for logicals

namespace cpp11 {

template <>
inline SEXP r_vector<r_bool>::valid_type(SEXP data) {
  if (TYPEOF(data) != LGLSXP) {
    throw type_error(LGLSXP, TYPEOF(data));
  }
  return data;
}

template <>
inline r_bool r_vector<r_bool>::operator[](const R_xlen_t pos) const {
  return is_altrep_ ? static_cast<r_bool>(LOGICAL_ELT(data_, pos)) : data_p_[pos];
}

template <>
inline r_bool* r_vector<r_bool>::get_p(bool is_altrep, SEXP data) {
  if (is_altrep) {
    return nullptr;
  } else {
    return reinterpret_cast<r_bool*>(LOGICAL(data));
  }
}

template <>
inline void r_vector<r_bool>::const_iterator::fill_buf(R_xlen_t pos) {
  length_ = std::min(64_xl, data_->size() - pos);
  LOGICAL_GET_REGION(data_->data_, pos, length_, reinterpret_cast<int*>(buf_.data()));
  block_start_ = pos;
}

typedef r_vector<r_bool> logicals;

namespace writable {

template <>
inline typename r_vector<r_bool>::proxy& r_vector<r_bool>::proxy::operator=(
    const r_bool& rhs) {
  if (is_altrep_) {
    SET_LOGICAL_ELT(data_, index_, rhs);
  } else {
    *p_ = rhs;
  }
  return *this;
}

template <>
inline r_vector<r_bool>::proxy::operator r_bool() const {
  if (p_ == nullptr) {
    return static_cast<r_bool>(LOGICAL_ELT(data_, index_));
  } else {
    return *p_;
  }
}

inline bool operator==(const r_vector<r_bool>::proxy& lhs, r_bool rhs) {
  return static_cast<r_bool>(lhs).operator==(rhs);
}

template <>
inline r_vector<r_bool>::r_vector(std::initializer_list<r_bool> il)
    : cpp11::r_vector<r_bool>(Rf_allocVector(LGLSXP, il.size())), capacity_(il.size()) {
  protect_ = preserved.insert(data_);
  auto it = il.begin();
  for (R_xlen_t i = 0; i < capacity_; ++i, ++it) {
    SET_LOGICAL_ELT(data_, i, *it);
  }
}

template <>
inline r_vector<r_bool>::r_vector(std::initializer_list<named_arg> il)
    : cpp11::r_vector<r_bool>(safe[Rf_allocVector](LGLSXP, 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] = static_cast<r_bool>(LOGICAL_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;
  }
}

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

  preserved.release(old_protect);

  data_p_ = reinterpret_cast<r_bool*>(LOGICAL(data_));
  capacity_ = new_capacity;
}

template <>
inline void r_vector<r_bool>::push_back(r_bool value) {
  while (length_ >= capacity_) {
    reserve(capacity_ == 0 ? 1 : capacity_ *= 2);
  }
  if (is_altrep_) {
    SET_LOGICAL_ELT(data_, length_, value);
  } else {
    data_p_[length_] = value;
  }
  ++length_;
}

typedef r_vector<r_bool> logicals;

}  // namespace writable
}  // namespace cpp11