]>
Commit | Line | Data |
---|---|---|
1d09f67e TL |
1 | // cpp11 version: 0.3.1.1 |
2 | // vendored on: 2021-08-11 | |
3 | #pragma once | |
4 | ||
5 | #include <initializer_list> // for initializer_list | |
6 | ||
7 | #include "cpp11/R.hpp" // for SEXP, SEXPREC, SET_VECTOR_ELT | |
8 | #include "cpp11/attribute_proxy.hpp" // for attribute_proxy | |
9 | #include "cpp11/named_arg.hpp" // for named_arg | |
10 | #include "cpp11/protect.hpp" // for preserved | |
11 | #include "cpp11/r_string.hpp" // for r_string | |
12 | #include "cpp11/r_vector.hpp" // for r_vector, r_vector<>::proxy | |
13 | #include "cpp11/sexp.hpp" // for sexp | |
14 | ||
15 | // Specializations for list | |
16 | ||
17 | namespace cpp11 { | |
18 | ||
19 | template <> | |
20 | inline SEXP r_vector<SEXP>::valid_type(SEXP data) { | |
21 | if (TYPEOF(data) != VECSXP) { | |
22 | throw type_error(VECSXP, TYPEOF(data)); | |
23 | } | |
24 | return data; | |
25 | } | |
26 | ||
27 | template <> | |
28 | inline SEXP r_vector<SEXP>::operator[](const R_xlen_t pos) const { | |
29 | return VECTOR_ELT(data_, pos); | |
30 | } | |
31 | ||
32 | template <> | |
33 | inline SEXP r_vector<SEXP>::operator[](const r_string& name) const { | |
34 | SEXP names = this->names(); | |
35 | R_xlen_t size = Rf_xlength(names); | |
36 | ||
37 | for (R_xlen_t pos = 0; pos < size; ++pos) { | |
38 | auto cur = Rf_translateCharUTF8(STRING_ELT(names, pos)); | |
39 | if (name == cur) { | |
40 | return operator[](pos); | |
41 | } | |
42 | } | |
43 | return R_NilValue; | |
44 | } | |
45 | ||
46 | template <> | |
47 | inline SEXP* r_vector<SEXP>::get_p(bool, SEXP) { | |
48 | return nullptr; | |
49 | } | |
50 | ||
51 | template <> | |
52 | inline void r_vector<SEXP>::const_iterator::fill_buf(R_xlen_t) { | |
53 | return; | |
54 | } | |
55 | ||
56 | template <> | |
57 | inline SEXP r_vector<SEXP>::const_iterator::operator*() const { | |
58 | return VECTOR_ELT(data_->data(), pos_); | |
59 | } | |
60 | ||
61 | typedef r_vector<SEXP> list; | |
62 | ||
63 | namespace writable { | |
64 | ||
65 | template <> | |
66 | inline typename r_vector<SEXP>::proxy& r_vector<SEXP>::proxy::operator=(const SEXP& rhs) { | |
67 | SET_VECTOR_ELT(data_, index_, rhs); | |
68 | return *this; | |
69 | } | |
70 | ||
71 | template <> | |
72 | inline r_vector<SEXP>::proxy::operator SEXP() const { | |
73 | return VECTOR_ELT(data_, index_); | |
74 | } | |
75 | ||
76 | template <> | |
77 | inline r_vector<SEXP>::r_vector(std::initializer_list<SEXP> il) | |
78 | : cpp11::r_vector<SEXP>(safe[Rf_allocVector](VECSXP, il.size())), | |
79 | capacity_(il.size()) { | |
80 | protect_ = preserved.insert(data_); | |
81 | auto it = il.begin(); | |
82 | for (R_xlen_t i = 0; i < capacity_; ++i, ++it) { | |
83 | SET_VECTOR_ELT(data_, i, *it); | |
84 | } | |
85 | } | |
86 | ||
87 | template <> | |
88 | inline r_vector<SEXP>::r_vector(std::initializer_list<named_arg> il) | |
89 | : cpp11::r_vector<SEXP>(safe[Rf_allocVector](VECSXP, il.size())), | |
90 | capacity_(il.size()) { | |
91 | protect_ = preserved.insert(data_); | |
92 | int n_protected = 0; | |
93 | ||
94 | try { | |
95 | unwind_protect([&] { | |
96 | Rf_setAttrib(data_, R_NamesSymbol, Rf_allocVector(STRSXP, capacity_)); | |
97 | SEXP names = PROTECT(Rf_getAttrib(data_, R_NamesSymbol)); | |
98 | ++n_protected; | |
99 | auto it = il.begin(); | |
100 | for (R_xlen_t i = 0; i < capacity_; ++i, ++it) { | |
101 | SET_VECTOR_ELT(data_, i, it->value()); | |
102 | SET_STRING_ELT(names, i, Rf_mkCharCE(it->name(), CE_UTF8)); | |
103 | } | |
104 | UNPROTECT(n_protected); | |
105 | }); | |
106 | } catch (const unwind_exception& e) { | |
107 | preserved.release(protect_); | |
108 | UNPROTECT(n_protected); | |
109 | throw e; | |
110 | } | |
111 | } | |
112 | ||
113 | template <> | |
114 | inline void r_vector<SEXP>::reserve(R_xlen_t new_capacity) { | |
115 | data_ = data_ == R_NilValue ? safe[Rf_allocVector](VECSXP, new_capacity) | |
116 | : safe[Rf_xlengthgets](data_, new_capacity); | |
117 | ||
118 | SEXP old_protect = protect_; | |
119 | protect_ = preserved.insert(data_); | |
120 | preserved.release(old_protect); | |
121 | ||
122 | capacity_ = new_capacity; | |
123 | } | |
124 | ||
125 | template <> | |
126 | inline void r_vector<SEXP>::push_back(SEXP value) { | |
127 | while (length_ >= capacity_) { | |
128 | reserve(capacity_ == 0 ? 1 : capacity_ *= 2); | |
129 | } | |
130 | SET_VECTOR_ELT(data_, length_, value); | |
131 | ++length_; | |
132 | } | |
133 | ||
134 | typedef r_vector<SEXP> list; | |
135 | ||
136 | } // namespace writable | |
137 | ||
138 | } // namespace cpp11 |