]> git.proxmox.com Git - ceph.git/blob - ceph/src/arrow/r/inst/include/cpp11/r_vector.hpp
import quincy 17.2.0
[ceph.git] / ceph / src / arrow / r / inst / include / cpp11 / r_vector.hpp
1 // cpp11 version: 0.3.1.1
2 // vendored on: 2021-08-11
3 #pragma once
4
5 #include <stddef.h> // for ptrdiff_t, size_t
6
7 #include <algorithm> // for max
8 #include <array> // for array
9 #include <cstdio> // for snprintf
10 #include <exception> // for exception
11 #include <initializer_list> // for initializer_list
12 #include <iterator> // for forward_iterator_tag, random_ac...
13 #include <stdexcept> // for out_of_range
14 #include <string> // for string, basic_string
15 #include <type_traits> // for decay, is_same, enable_if, is_c...
16 #include <utility> // for declval
17
18 #include "cpp11/R.hpp" // for R_xlen_t, SEXP, SEXPREC, Rf_xle...
19 #include "cpp11/attribute_proxy.hpp" // for attribute_proxy
20 #include "cpp11/protect.hpp" // for preserved
21 #include "cpp11/r_string.hpp" // for r_string
22 #include "cpp11/sexp.hpp" // for sexp
23
24 namespace cpp11 {
25
26 using namespace cpp11::literals;
27
28 class type_error : public std::exception {
29 public:
30 type_error(int expected, int actual) : expected_(expected), actual_(actual) {}
31 virtual const char* what() const noexcept {
32 snprintf(str_, 64, "Invalid input type, expected '%s' actual '%s'",
33 Rf_type2char(expected_), Rf_type2char(actual_));
34 return str_;
35 }
36
37 private:
38 int expected_;
39 int actual_;
40 mutable char str_[64];
41 };
42
43 // Forward Declarations
44 class named_arg;
45
46 namespace writable {
47 template <typename T>
48 class r_vector;
49 } // namespace writable
50
51 // Declarations
52 template <typename T>
53 class r_vector {
54 public:
55 typedef ptrdiff_t difference_type;
56 typedef size_t size_type;
57 typedef T value_type;
58 typedef T* pointer;
59 typedef T& reference;
60
61 r_vector() = default;
62
63 r_vector(SEXP data);
64
65 r_vector(SEXP data, bool is_altrep);
66
67 #ifdef LONG_VECTOR_SUPPORT
68 T operator[](const int pos) const;
69 T at(const int pos) const;
70 #endif
71 T operator[](const R_xlen_t pos) const;
72 T operator[](const size_type pos) const;
73 T operator[](const r_string& name) const;
74
75 T at(const R_xlen_t pos) const;
76 T at(const size_type pos) const;
77 T at(const r_string& name) const;
78
79 bool contains(const r_string& name) const;
80
81 r_vector& operator=(const r_vector& rhs) {
82 SEXP old_protect = protect_;
83
84 data_ = rhs.data_;
85 protect_ = preserved.insert(data_);
86 is_altrep_ = rhs.is_altrep_;
87 data_p_ = rhs.data_p_;
88 length_ = rhs.length_;
89
90 preserved.release(old_protect);
91
92 return *this;
93 };
94
95 r_vector(const r_vector& rhs) {
96 SEXP old_protect = protect_;
97
98 data_ = rhs.data_;
99 protect_ = preserved.insert(data_);
100 is_altrep_ = rhs.is_altrep_;
101 data_p_ = rhs.data_p_;
102 length_ = rhs.length_;
103
104 preserved.release(old_protect);
105 };
106
107 r_vector(const writable::r_vector<T>& rhs) : r_vector(static_cast<SEXP>(rhs)) {}
108
109 bool is_altrep() const;
110
111 bool named() const;
112
113 R_xlen_t size() const;
114
115 operator SEXP() const;
116
117 operator sexp() const;
118
119 bool empty() const;
120
121 /// Provide access to the underlying data, mainly for interface
122 /// compatibility with std::vector
123 SEXP data() const;
124
125 sexp attr(const char* name) const {
126 return SEXP(attribute_proxy<r_vector<T>>(*this, name));
127 }
128
129 sexp attr(const std::string& name) const {
130 return SEXP(attribute_proxy<r_vector<T>>(*this, name.c_str()));
131 }
132
133 sexp attr(SEXP name) const { return SEXP(attribute_proxy<r_vector<T>>(*this, name)); }
134
135 r_vector<r_string> names() const {
136 SEXP nms = SEXP(attribute_proxy<r_vector<T>>(*this, R_NamesSymbol));
137 if (nms == R_NilValue) {
138 return r_vector<r_string>();
139 }
140
141 return nms;
142 }
143
144 class const_iterator {
145 public:
146 using difference_type = ptrdiff_t;
147 using value_type = T;
148 using pointer = T*;
149 using reference = T&;
150 using iterator_category = std::random_access_iterator_tag;
151
152 const_iterator(const r_vector* data, R_xlen_t pos);
153
154 inline const_iterator& operator+(R_xlen_t pos);
155 inline ptrdiff_t operator-(const const_iterator& other) const;
156
157 inline const_iterator& operator++();
158 inline const_iterator& operator--();
159
160 inline const_iterator& operator+=(R_xlen_t pos);
161 inline const_iterator& operator-=(R_xlen_t pos);
162
163 inline bool operator!=(const const_iterator& other) const;
164 inline bool operator==(const const_iterator& other) const;
165
166 inline T operator*() const;
167
168 friend class writable::r_vector<T>::iterator;
169
170 private:
171 const r_vector* data_;
172 void fill_buf(R_xlen_t pos);
173
174 R_xlen_t pos_;
175 std::array<T, 64 * 64> buf_;
176 R_xlen_t block_start_ = 0;
177 R_xlen_t length_ = 0;
178 };
179
180 public:
181 const_iterator begin() const;
182 const_iterator end() const;
183
184 const_iterator cbegin() const;
185 const_iterator cend() const;
186
187 const_iterator find(const r_string& name) const;
188
189 ~r_vector() { preserved.release(protect_); }
190
191 private:
192 SEXP data_ = R_NilValue;
193 SEXP protect_ = R_NilValue;
194 bool is_altrep_ = false;
195 T* data_p_ = nullptr;
196 R_xlen_t length_ = 0;
197
198 static T* get_p(bool is_altrep, SEXP data);
199
200 static SEXP valid_type(SEXP data);
201
202 friend class writable::r_vector<T>;
203 };
204
205 namespace writable {
206
207 template <typename T>
208 using has_begin_fun = std::decay<decltype(*begin(std::declval<T>()))>;
209
210 /// Read/write access to new or copied r_vectors
211 template <typename T>
212 class r_vector : public cpp11::r_vector<T> {
213 private:
214 SEXP protect_ = R_NilValue;
215
216 // These are necessary because type names are not directly accessible in
217 // template inheritance
218 using cpp11::r_vector<T>::data_;
219 using cpp11::r_vector<T>::data_p_;
220 using cpp11::r_vector<T>::is_altrep_;
221 using cpp11::r_vector<T>::length_;
222
223 R_xlen_t capacity_ = 0;
224
225 public:
226 class proxy {
227 private:
228 const SEXP data_;
229 const R_xlen_t index_;
230 T* const p_;
231 bool is_altrep_;
232
233 public:
234 proxy(SEXP data, const R_xlen_t index, T* const p, bool is_altrep);
235
236 proxy& operator=(const T& rhs);
237 proxy& operator+=(const T& rhs);
238 proxy& operator-=(const T& rhs);
239 proxy& operator*=(const T& rhs);
240 proxy& operator/=(const T& rhs);
241 proxy& operator++(int);
242 proxy& operator--(int);
243
244 void operator++();
245 void operator--();
246
247 operator T() const;
248 };
249
250 typedef ptrdiff_t difference_type;
251 typedef size_t size_type;
252 typedef proxy value_type;
253 typedef proxy* pointer;
254 typedef proxy& reference;
255
256 class iterator : public cpp11::r_vector<T>::const_iterator {
257 private:
258 const r_vector& data_;
259 using cpp11::r_vector<T>::const_iterator::block_start_;
260 using cpp11::r_vector<T>::const_iterator::pos_;
261 using cpp11::r_vector<T>::const_iterator::buf_;
262 using cpp11::r_vector<T>::const_iterator::length_;
263 using cpp11::r_vector<T>::const_iterator::fill_buf;
264
265 public:
266 using difference_type = ptrdiff_t;
267 using value_type = proxy;
268 using pointer = proxy*;
269 using reference = proxy&;
270 using iterator_category = std::forward_iterator_tag;
271
272 iterator(const r_vector& data, R_xlen_t pos);
273
274 inline iterator& operator++();
275
276 inline proxy operator*() const;
277
278 using cpp11::r_vector<T>::const_iterator::operator!=;
279
280 inline iterator& operator+(R_xlen_t rhs);
281 };
282
283 r_vector() = default;
284 r_vector(const SEXP& data);
285 r_vector(SEXP&& data);
286 r_vector(const SEXP& data, bool is_altrep);
287 r_vector(SEXP&& data, bool is_altrep);
288 r_vector(std::initializer_list<T> il);
289 r_vector(std::initializer_list<named_arg> il);
290 r_vector(std::initializer_list<const char*> il);
291 r_vector(std::initializer_list<std::string> il);
292
293 template <typename Iter>
294 r_vector(Iter first, Iter last);
295
296 template <typename V, typename W = has_begin_fun<V>>
297 r_vector(const V& obj);
298
299 r_vector(const R_xlen_t size);
300
301 ~r_vector();
302
303 r_vector(const r_vector& rhs);
304 r_vector(r_vector&& rhs);
305
306 r_vector(const cpp11::r_vector<T>& rhs);
307
308 r_vector& operator=(const r_vector& rhs);
309 r_vector& operator=(r_vector&& rhs);
310
311 #ifdef LONG_VECTOR_SUPPORT
312 proxy operator[](const int pos) const;
313 proxy at(const int pos) const;
314 #endif
315 proxy operator[](const R_xlen_t pos) const;
316 proxy operator[](const size_type pos) const;
317 proxy operator[](const r_string& name) const;
318
319 proxy at(const R_xlen_t pos) const;
320 proxy at(const size_type pos) const;
321 proxy at(const r_string& name) const;
322
323 void push_back(T value);
324 void push_back(const named_arg& value);
325 void pop_back();
326
327 void resize(R_xlen_t count);
328
329 void reserve(R_xlen_t new_capacity);
330
331 iterator insert(R_xlen_t pos, T value);
332 iterator erase(R_xlen_t pos);
333
334 void clear();
335
336 iterator begin() const;
337 iterator end() const;
338
339 using cpp11::r_vector<T>::cbegin;
340 using cpp11::r_vector<T>::cend;
341 using cpp11::r_vector<T>::size;
342
343 iterator find(const r_string& name) const;
344
345 attribute_proxy<r_vector<T>> attr(const char* name) const {
346 return attribute_proxy<r_vector<T>>(*this, name);
347 }
348
349 attribute_proxy<r_vector<T>> attr(const std::string& name) const {
350 return attribute_proxy<r_vector<T>>(*this, name.c_str());
351 }
352
353 attribute_proxy<r_vector<T>> attr(SEXP name) const {
354 return attribute_proxy<r_vector<T>>(*this, name);
355 }
356
357 attribute_proxy<r_vector<T>> names() const {
358 return attribute_proxy<r_vector<T>>(*this, R_NamesSymbol);
359 }
360
361 operator SEXP() const;
362 };
363 } // namespace writable
364
365 // Implementations below
366
367 template <typename T>
368 inline r_vector<T>::r_vector(const SEXP data)
369 : data_(valid_type(data)),
370 protect_(preserved.insert(data)),
371 is_altrep_(ALTREP(data)),
372 data_p_(get_p(ALTREP(data), data)),
373 length_(Rf_xlength(data)) {}
374
375 template <typename T>
376 inline r_vector<T>::r_vector(const SEXP data, bool is_altrep)
377 : data_(valid_type(data)),
378 protect_(preserved.insert(data)),
379 is_altrep_(is_altrep),
380 data_p_(get_p(is_altrep, data)),
381 length_(Rf_xlength(data)) {}
382
383 template <typename T>
384 inline bool r_vector<T>::is_altrep() const {
385 return is_altrep_;
386 }
387
388 template <typename T>
389 inline bool r_vector<T>::named() const {
390 return ((this->names()) != R_NilValue);
391 }
392
393 template <typename T>
394 inline R_xlen_t r_vector<T>::size() const {
395 return length_;
396 }
397
398 template <typename T>
399 inline r_vector<T>::operator SEXP() const {
400 return data_;
401 }
402
403 template <typename T>
404 inline bool r_vector<T>::empty() const {
405 return (!(this->size() > 0));
406 }
407
408 template <typename T>
409 inline r_vector<T>::operator sexp() const {
410 return data_;
411 }
412
413 /// Provide access to the underlying data, mainly for interface
414 /// compatibility with std::vector
415 template <typename T>
416 inline SEXP r_vector<T>::data() const {
417 return data_;
418 }
419
420 template <typename T>
421 inline typename r_vector<T>::const_iterator r_vector<T>::begin() const {
422 return const_iterator(this, 0);
423 }
424
425 template <typename T>
426 inline typename r_vector<T>::const_iterator r_vector<T>::end() const {
427 return const_iterator(this, length_);
428 }
429
430 template <typename T>
431 inline typename r_vector<T>::const_iterator r_vector<T>::cbegin() const {
432 return const_iterator(this, 0);
433 }
434
435 template <typename T>
436 inline typename r_vector<T>::const_iterator r_vector<T>::cend() const {
437 return const_iterator(this, length_);
438 }
439
440 template <typename T>
441 r_vector<T>::const_iterator::const_iterator(const r_vector* data, R_xlen_t pos)
442 : data_(data), pos_(pos), buf_() {
443 if (data_->is_altrep()) {
444 fill_buf(pos);
445 }
446 }
447
448 template <typename T>
449 inline typename r_vector<T>::const_iterator& r_vector<T>::const_iterator::operator++() {
450 ++pos_;
451 if (data_->is_altrep() && pos_ >= block_start_ + length_) {
452 fill_buf(pos_);
453 }
454 return *this;
455 }
456
457 template <typename T>
458 inline typename r_vector<T>::const_iterator& r_vector<T>::const_iterator::operator--() {
459 --pos_;
460 if (data_->is_altrep() && pos_ > 0 && pos_ < block_start_) {
461 fill_buf(std::max(0_xl, pos_ - 64));
462 }
463 return *this;
464 }
465
466 template <typename T>
467 inline typename r_vector<T>::const_iterator& r_vector<T>::const_iterator::operator+=(
468 R_xlen_t i) {
469 pos_ += i;
470 if (data_->is_altrep() && pos_ >= block_start_ + length_) {
471 fill_buf(pos_);
472 }
473 return *this;
474 }
475
476 template <typename T>
477 inline typename r_vector<T>::const_iterator& r_vector<T>::const_iterator::operator-=(
478 R_xlen_t i) {
479 pos_ -= i;
480 if (data_->is_altrep() && pos_ >= block_start_ + length_) {
481 fill_buf(std::max(0_xl, pos_ - 64));
482 }
483 return *this;
484 }
485
486 template <typename T>
487 inline bool r_vector<T>::const_iterator::operator!=(
488 const r_vector<T>::const_iterator& other) const {
489 return pos_ != other.pos_;
490 }
491
492 template <typename T>
493 inline bool r_vector<T>::const_iterator::operator==(
494 const r_vector<T>::const_iterator& other) const {
495 return pos_ == other.pos_;
496 }
497
498 template <typename T>
499 inline ptrdiff_t r_vector<T>::const_iterator::operator-(
500 const r_vector<T>::const_iterator& other) const {
501 return pos_ - other.pos_;
502 }
503
504 template <typename T>
505 inline typename r_vector<T>::const_iterator& r_vector<T>::const_iterator::operator+(
506 R_xlen_t rhs) {
507 pos_ += rhs;
508 if (data_->is_altrep() && pos_ >= block_start_ + length_) {
509 fill_buf(pos_);
510 }
511 return *this;
512 }
513
514 template <typename T>
515 inline T cpp11::r_vector<T>::at(R_xlen_t pos) const {
516 if (pos < 0 || pos >= length_) {
517 throw std::out_of_range("r_vector");
518 }
519
520 return operator[](pos);
521 }
522
523 template <typename T>
524 inline T cpp11::r_vector<T>::at(size_type pos) const {
525 return at(static_cast<R_xlen_t>(pos));
526 }
527
528 template <typename T>
529 inline T cpp11::r_vector<T>::operator[](const r_string& name) const {
530 SEXP names = this->names();
531 R_xlen_t size = Rf_xlength(names);
532
533 for (R_xlen_t pos = 0; pos < size; ++pos) {
534 auto cur = Rf_translateCharUTF8(STRING_ELT(names, pos));
535 if (name == cur) {
536 return operator[](pos);
537 }
538 }
539
540 throw std::out_of_range("r_vector");
541 }
542
543 template <typename T>
544 inline bool cpp11::r_vector<T>::contains(const r_string& name) const {
545 SEXP names = this->names();
546 R_xlen_t size = Rf_xlength(names);
547
548 for (R_xlen_t pos = 0; pos < size; ++pos) {
549 auto cur = Rf_translateCharUTF8(STRING_ELT(names, pos));
550 if (name == cur) {
551 return true;
552 }
553 }
554
555 return false;
556 }
557
558 template <typename T>
559 inline typename cpp11::r_vector<T>::const_iterator cpp11::r_vector<T>::find(
560 const r_string& name) const {
561 SEXP names = this->names();
562 R_xlen_t size = Rf_xlength(names);
563
564 for (R_xlen_t pos = 0; pos < size; ++pos) {
565 auto cur = Rf_translateCharUTF8(STRING_ELT(names, pos));
566 if (name == cur) {
567 return begin() + pos;
568 }
569 }
570
571 return end();
572 }
573
574 template <typename T>
575 inline T r_vector<T>::const_iterator::operator*() const {
576 if (data_->is_altrep()) {
577 return buf_[pos_ - block_start_];
578 } else {
579 return data_->data_p_[pos_];
580 }
581 }
582
583 #ifdef LONG_VECTOR_SUPPORT
584 template <typename T>
585 inline T r_vector<T>::operator[](const int pos) const {
586 return operator[](static_cast<R_xlen_t>(pos));
587 }
588
589 template <typename T>
590 inline T r_vector<T>::at(const int pos) const {
591 return at(static_cast<R_xlen_t>(pos));
592 }
593 #endif
594
595 template <typename T>
596 inline T r_vector<T>::operator[](size_type pos) const {
597 return operator[](static_cast<R_xlen_t>(pos));
598 }
599
600 namespace writable {
601
602 template <typename T>
603 r_vector<T>::proxy::proxy(SEXP data, const R_xlen_t index, T* const p, bool is_altrep)
604 : data_(data), index_(index), p_(p), is_altrep_(is_altrep) {}
605
606 template <typename T>
607 inline typename r_vector<T>::proxy r_vector<T>::iterator::operator*() const {
608 if (data_.is_altrep()) {
609 return proxy(data_.data(), pos_, const_cast<T*>(&buf_[pos_ - block_start_]), true);
610 } else {
611 return proxy(data_.data(), pos_,
612 data_.data_p_ != nullptr ? &data_.data_p_[pos_] : nullptr, false);
613 }
614 }
615
616 template <typename T>
617 r_vector<T>::iterator::iterator(const r_vector& data, R_xlen_t pos)
618 : r_vector<T>::const_iterator(&data, pos), data_(data) {}
619
620 template <typename T>
621 inline typename r_vector<T>::iterator& r_vector<T>::iterator::operator++() {
622 ++pos_;
623 if (data_.is_altrep() && pos_ >= block_start_ + length_) {
624 fill_buf(pos_);
625 }
626 return *this;
627 }
628
629 template <typename T>
630 inline typename r_vector<T>::iterator& r_vector<T>::iterator::operator+(R_xlen_t rhs) {
631 pos_ += rhs;
632 if (data_.is_altrep() && pos_ >= block_start_ + length_) {
633 fill_buf(pos_);
634 }
635 return *this;
636 }
637
638 template <typename T>
639 inline typename r_vector<T>::iterator r_vector<T>::begin() const {
640 return iterator(*this, 0);
641 }
642
643 template <typename T>
644 inline typename r_vector<T>::iterator r_vector<T>::end() const {
645 return iterator(*this, length_);
646 }
647
648 template <typename T>
649 inline r_vector<T>::r_vector(const SEXP& data)
650 : cpp11::r_vector<T>(safe[Rf_shallow_duplicate](data)),
651 protect_(preserved.insert(data_)),
652 capacity_(length_) {}
653
654 template <typename T>
655 inline r_vector<T>::r_vector(const SEXP& data, bool is_altrep)
656 : cpp11::r_vector<T>(safe[Rf_shallow_duplicate](data), is_altrep),
657 protect_(preserved.insert(data_)),
658 capacity_(length_) {}
659
660 template <typename T>
661 inline r_vector<T>::r_vector(SEXP&& data)
662 : cpp11::r_vector<T>(data), protect_(preserved.insert(data_)), capacity_(length_) {}
663
664 template <typename T>
665 inline r_vector<T>::r_vector(SEXP&& data, bool is_altrep)
666 : cpp11::r_vector<T>(data, is_altrep),
667 protect_(preserved.insert(data_)),
668 capacity_(length_) {}
669
670 template <typename T>
671 template <typename Iter>
672 inline r_vector<T>::r_vector(Iter first, Iter last) : r_vector() {
673 reserve(last - first);
674 while (first != last) {
675 push_back(*first);
676 ++first;
677 }
678 }
679
680 template <typename T>
681 template <typename V, typename W>
682 inline r_vector<T>::r_vector(const V& obj) : r_vector() {
683 auto first = obj.begin();
684 auto last = obj.end();
685 reserve(last - first);
686 while (first != last) {
687 push_back(*first);
688 ++first;
689 }
690 }
691
692 template <typename T>
693 inline r_vector<T>::r_vector(R_xlen_t size) : r_vector() {
694 resize(size);
695 }
696
697 template <typename T>
698 inline r_vector<T>::~r_vector() {
699 preserved.release(protect_);
700 }
701
702 #ifdef LONG_VECTOR_SUPPORT
703 template <typename T>
704 inline typename r_vector<T>::proxy r_vector<T>::operator[](const int pos) const {
705 return operator[](static_cast<R_xlen_t>(pos));
706 }
707
708 template <typename T>
709 inline typename r_vector<T>::proxy r_vector<T>::at(const int pos) const {
710 return at(static_cast<R_xlen_t>(pos));
711 }
712 #endif
713
714 template <typename T>
715 inline typename r_vector<T>::proxy r_vector<T>::operator[](const R_xlen_t pos) const {
716 if (is_altrep_) {
717 return {data_, pos, nullptr, true};
718 }
719 return {data_, pos, data_p_ != nullptr ? &data_p_[pos] : nullptr, false};
720 }
721
722 template <typename T>
723 inline typename r_vector<T>::proxy r_vector<T>::operator[](size_type pos) const {
724 return operator[](static_cast<R_xlen_t>(pos));
725 }
726
727 template <typename T>
728 inline typename r_vector<T>::proxy r_vector<T>::at(const R_xlen_t pos) const {
729 if (pos < 0 || pos >= length_) {
730 throw std::out_of_range("r_vector");
731 }
732 return operator[](static_cast<R_xlen_t>(pos));
733 }
734
735 template <typename T>
736 inline typename r_vector<T>::proxy r_vector<T>::at(size_type pos) const {
737 return at(static_cast<R_xlen_t>(pos));
738 }
739
740 template <typename T>
741 inline typename r_vector<T>::proxy r_vector<T>::operator[](const r_string& name) const {
742 SEXP names = PROTECT(this->names());
743 R_xlen_t size = Rf_xlength(names);
744
745 for (R_xlen_t pos = 0; pos < size; ++pos) {
746 auto cur = Rf_translateCharUTF8(STRING_ELT(names, pos));
747 if (name == cur) {
748 UNPROTECT(1);
749 return operator[](pos);
750 }
751 }
752
753 UNPROTECT(1);
754 throw std::out_of_range("r_vector");
755 }
756
757 template <typename T>
758 inline typename r_vector<T>::proxy r_vector<T>::at(const r_string& name) const {
759 return operator[](name);
760 }
761
762 template <typename T>
763 inline typename r_vector<T>::iterator r_vector<T>::find(const r_string& name) const {
764 SEXP names = PROTECT(this->names());
765 R_xlen_t size = Rf_xlength(names);
766
767 for (R_xlen_t pos = 0; pos < size; ++pos) {
768 auto cur = Rf_translateCharUTF8(STRING_ELT(names, pos));
769 if (name == cur) {
770 UNPROTECT(1);
771 return begin() + pos;
772 }
773 }
774
775 UNPROTECT(1);
776 return end();
777 }
778
779 template <typename T>
780 inline r_vector<T>::r_vector(const r_vector<T>& rhs)
781 : cpp11::r_vector<T>(safe[Rf_shallow_duplicate](rhs)),
782 protect_(preserved.insert(data_)),
783 capacity_(rhs.capacity_) {}
784
785 template <typename T>
786 inline r_vector<T>::r_vector(r_vector<T>&& rhs)
787 : cpp11::r_vector<T>(rhs), protect_(rhs.protect_), capacity_(rhs.capacity_) {
788 rhs.data_ = R_NilValue;
789 rhs.protect_ = R_NilValue;
790 }
791
792 template <typename T>
793 inline r_vector<T>::r_vector(const cpp11::r_vector<T>& rhs)
794 : cpp11::r_vector<T>(safe[Rf_shallow_duplicate](rhs)),
795 protect_(preserved.insert(data_)),
796 capacity_(rhs.length_) {}
797
798 // We don't release the old object until the end in case we throw an exception
799 // during the duplicate.
800 template <typename T>
801 inline r_vector<T>& r_vector<T>::operator=(const r_vector<T>& rhs) {
802 if (data_ == rhs.data_) {
803 return *this;
804 }
805
806 cpp11::r_vector<T>::operator=(rhs);
807
808 auto old_protect = protect_;
809
810 data_ = safe[Rf_shallow_duplicate](rhs.data_);
811 protect_ = preserved.insert(data_);
812
813 preserved.release(old_protect);
814
815 capacity_ = rhs.capacity_;
816
817 return *this;
818 }
819
820 template <typename T>
821 inline r_vector<T>& r_vector<T>::operator=(r_vector<T>&& rhs) {
822 if (data_ == rhs.data_) {
823 return *this;
824 }
825
826 cpp11::r_vector<T>::operator=(rhs);
827
828 SEXP old_protect = protect_;
829
830 data_ = rhs.data_;
831 protect_ = preserved.insert(data_);
832
833 preserved.release(old_protect);
834
835 capacity_ = rhs.capacity_;
836
837 rhs.data_ = R_NilValue;
838 rhs.protect_ = R_NilValue;
839
840 return *this;
841 }
842
843 template <typename T>
844 inline void r_vector<T>::pop_back() {
845 --length_;
846 }
847
848 template <typename T>
849 inline void r_vector<T>::resize(R_xlen_t count) {
850 reserve(count);
851 length_ = count;
852 }
853
854 template <typename T>
855 inline typename r_vector<T>::iterator r_vector<T>::insert(R_xlen_t pos, T value) {
856 push_back(value);
857
858 R_xlen_t i = length_ - 1;
859 while (i > pos) {
860 operator[](i) = (T) operator[](i - 1);
861 --i;
862 };
863 operator[](pos) = value;
864
865 return begin() + pos;
866 }
867
868 template <typename T>
869 inline typename r_vector<T>::iterator r_vector<T>::erase(R_xlen_t pos) {
870 R_xlen_t i = pos;
871 while (i < length_ - 1) {
872 operator[](i) = (T) operator[](i + 1);
873 ++i;
874 }
875 pop_back();
876
877 return begin() + pos;
878 }
879
880 template <typename T>
881 inline void r_vector<T>::clear() {
882 length_ = 0;
883 }
884
885 template <typename T>
886 inline r_vector<T>::operator SEXP() const {
887 if (length_ < capacity_) {
888 #if R_VERSION >= R_Version(3, 4, 0)
889 SETLENGTH(data_, length_);
890 SET_TRUELENGTH(data_, capacity_);
891 SET_GROWABLE_BIT(data_);
892 #else
893 auto* p = const_cast<r_vector<T>*>(this);
894 p->data_ = safe[Rf_lengthgets](data_, length_);
895 #endif
896 }
897 return data_;
898 }
899
900 template <typename T>
901 inline typename r_vector<T>::proxy& r_vector<T>::proxy::operator+=(const T& rhs) {
902 operator=(static_cast<T>(*this) + rhs);
903 return *this;
904 }
905
906 template <typename T>
907 inline typename r_vector<T>::proxy& r_vector<T>::proxy::operator-=(const T& rhs) {
908 operator=(static_cast<T>(*this) - rhs);
909 return *this;
910 }
911
912 template <typename T>
913 inline typename r_vector<T>::proxy& r_vector<T>::proxy::operator*=(const T& rhs) {
914 operator=(static_cast<T>(*this) * rhs);
915 return *this;
916 }
917
918 template <typename T>
919 inline typename r_vector<T>::proxy& r_vector<T>::proxy::operator/=(const T& rhs) {
920 operator=(static_cast<T>(*this) / rhs);
921 return *this;
922 }
923
924 template <typename T>
925 inline typename r_vector<T>::proxy& r_vector<T>::proxy::operator++(int) {
926 operator=(static_cast<T>(*this) + 1);
927 return *this;
928 }
929
930 template <typename T>
931 inline typename r_vector<T>::proxy& r_vector<T>::proxy::operator--(int) {
932 operator=(static_cast<T>(*this) - 1);
933 return *this;
934 }
935
936 template <typename T>
937 inline void r_vector<T>::proxy::operator--() {
938 operator=(static_cast<T>(*this) - 1);
939 }
940
941 template <typename T>
942 inline void r_vector<T>::proxy::operator++() {
943 operator=(static_cast<T>(*this) + 1);
944 }
945
946 } // namespace writable
947
948 // TODO: is there a better condition we could use, e.g. assert something true
949 // rather than three things false?
950 template <typename C, typename T>
951 using is_container_but_not_sexp_or_string = typename std::enable_if<
952 !std::is_constructible<C, SEXP>::value &&
953 !std::is_same<typename std::decay<C>::type, std::string>::value &&
954 !std::is_same<typename std::decay<T>::type, std::string>::value,
955 typename std::decay<C>::type>::type;
956
957 template <typename C, typename T = typename std::decay<C>::type::value_type>
958 // typename T = typename C::value_type>
959 is_container_but_not_sexp_or_string<C, T> as_cpp(SEXP from) {
960 auto obj = cpp11::r_vector<T>(from);
961 return {obj.begin(), obj.end()};
962 }
963
964 // TODO: could we make this generalize outside of std::string?
965 template <typename C, typename T = C>
966 using is_vector_of_strings = typename std::enable_if<
967 std::is_same<typename std::decay<T>::type, std::string>::value,
968 typename std::decay<C>::type>::type;
969
970 template <typename C, typename T = typename std::decay<C>::type::value_type>
971 // typename T = typename C::value_type>
972 is_vector_of_strings<C, T> as_cpp(SEXP from) {
973 auto obj = cpp11::r_vector<cpp11::r_string>(from);
974 typename std::decay<C>::type res;
975 auto it = obj.begin();
976 while (it != obj.end()) {
977 r_string s = *it;
978 res.emplace_back(static_cast<std::string>(s));
979 ++it;
980 }
981 return res;
982 }
983
984 template <typename T>
985 bool operator==(const r_vector<T>& lhs, const r_vector<T>& rhs) {
986 if (lhs.size() != rhs.size()) {
987 return false;
988 }
989
990 auto lhs_it = lhs.begin();
991 auto rhs_it = rhs.begin();
992
993 auto end = lhs.end();
994 while (lhs_it != end) {
995 if (!(*lhs_it == *rhs_it)) {
996 return false;
997 }
998 ++lhs_it;
999 ++rhs_it;
1000 }
1001 return true;
1002 }
1003
1004 template <typename T>
1005 bool operator!=(const r_vector<T>& lhs, const r_vector<T>& rhs) {
1006 return !(lhs == rhs);
1007 }
1008
1009 } // namespace cpp11