summaryrefslogtreecommitdiffstats
path: root/src/arrow/r/inst/include/cpp11/data_frame.hpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/arrow/r/inst/include/cpp11/data_frame.hpp102
1 files changed, 102 insertions, 0 deletions
diff --git a/src/arrow/r/inst/include/cpp11/data_frame.hpp b/src/arrow/r/inst/include/cpp11/data_frame.hpp
new file mode 100644
index 000000000..9abbc0f33
--- /dev/null
+++ b/src/arrow/r/inst/include/cpp11/data_frame.hpp
@@ -0,0 +1,102 @@
+// cpp11 version: 0.3.1.1
+// vendored on: 2021-08-11
+#pragma once
+
+#include <cstdlib> // for abs
+#include <cstdlib>
+#include <initializer_list> // for initializer_list
+#include <string> // for string, basic_string
+#include <utility> // for move
+
+#include "R_ext/Arith.h" // for NA_INTEGER
+#include "cpp11/R.hpp" // for Rf_xlength, SEXP, SEXPREC, INTEGER
+#include "cpp11/attribute_proxy.hpp" // for attribute_proxy
+#include "cpp11/list.hpp" // for list, r_vector<>::r_vector, r_v...
+#include "cpp11/r_vector.hpp" // for r_vector
+
+namespace cpp11 {
+
+class named_arg;
+namespace writable {
+class data_frame;
+} // namespace writable
+
+class data_frame : public list {
+ using list::list;
+
+ friend class writable::data_frame;
+
+ /* we cannot use Rf_getAttrib because it has a special case for c(NA, -n) and creates
+ * the full vector */
+ static SEXP get_attrib0(SEXP x, SEXP sym) {
+ for (SEXP attr = ATTRIB(x); attr != R_NilValue; attr = CDR(attr)) {
+ if (TAG(attr) == sym) {
+ return CAR(attr);
+ }
+ }
+
+ return R_NilValue;
+ }
+
+ static int calc_nrow(SEXP x) {
+ auto nms = get_attrib0(x, R_RowNamesSymbol);
+ bool has_short_rownames =
+ (Rf_isInteger(nms) && Rf_xlength(nms) == 2 && INTEGER(nms)[0] == NA_INTEGER);
+ if (has_short_rownames) {
+ return abs(INTEGER(nms)[1]);
+ }
+
+ if (!Rf_isNull(nms)) {
+ return Rf_xlength(nms);
+ }
+
+ if (Rf_xlength(x) == 0) {
+ return 0;
+ }
+
+ return Rf_xlength(VECTOR_ELT(x, 0));
+ }
+
+ public:
+ /* Adapted from
+ * https://github.com/wch/r-source/blob/f2a0dfab3e26fb42b8b296fcba40cbdbdbec767d/src/main/attrib.c#L198-L207
+ */
+ R_xlen_t nrow() const { return calc_nrow(*this); }
+ R_xlen_t ncol() const { return size(); }
+};
+
+namespace writable {
+class data_frame : public cpp11::data_frame {
+ private:
+ writable::list set_data_frame_attributes(writable::list&& x) {
+ x.attr(R_RowNamesSymbol) = {NA_INTEGER, -static_cast<int>(calc_nrow(x))};
+ x.attr(R_ClassSymbol) = "data.frame";
+ return std::move(x);
+ }
+
+ public:
+ data_frame(const SEXP data) : cpp11::data_frame(set_data_frame_attributes(data)) {}
+ data_frame(const SEXP data, bool is_altrep)
+ : cpp11::data_frame(set_data_frame_attributes(data), is_altrep) {}
+ data_frame(std::initializer_list<list> il)
+ : cpp11::data_frame(set_data_frame_attributes(writable::list(il))) {}
+ data_frame(std::initializer_list<named_arg> il)
+ : cpp11::data_frame(set_data_frame_attributes(writable::list(il))) {}
+
+ using cpp11::data_frame::ncol;
+ using cpp11::data_frame::nrow;
+
+ attribute_proxy<data_frame> attr(const char* name) const { return {*this, name}; }
+
+ attribute_proxy<data_frame> attr(const std::string& name) const {
+ return {*this, name.c_str()};
+ }
+
+ attribute_proxy<data_frame> attr(SEXP name) const { return {*this, name}; }
+
+ attribute_proxy<data_frame> names() const { return {*this, R_NamesSymbol}; }
+};
+
+} // namespace writable
+
+} // namespace cpp11