Skip to content

Commit 25b7b88

Browse files
committed
sketch "other" support
1 parent a5a9b6f commit 25b7b88

File tree

1 file changed

+82
-1
lines changed

1 file changed

+82
-1
lines changed

r/src/vctr_builder_other.h

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,90 @@
2424

2525
#include "vctr_builder_base.h"
2626

27+
// If we've ended up here, we need to call in to R to convert this stream
28+
// of arrays into an R vector. Currently, the S3 generic that implements
29+
// this is convert_array(), so we have to do this one array at a time.
30+
// The current conversions that are implemented this way internally are
31+
// factor(), decimal, and + extension types/dictionary.
32+
//
33+
// An early version of this reimplemented a good chunk of vctrs-like internals
34+
// to allow a generic preallocate where each chunk would be copied in to the
35+
// preallocated vector. This version just converts each chunk as it comes
36+
// and calls c(); however, eventually the generic should be
37+
// convert_array_stream() to give implementations in other packages the ability
38+
// to handle converting more than one array at a time.
2739
class OtherBuilder : public VctrBuilder {
2840
public:
29-
explicit OtherBuilder(SEXP ptype_sexp) : VctrBuilder(VECTOR_TYPE_OTHER, ptype_sexp) {}
41+
explicit OtherBuilder(SEXP ptype_sexp)
42+
: VctrBuilder(VECTOR_TYPE_OTHER, ptype_sexp),
43+
chunks_sexp_(R_NilValue),
44+
chunks_tail_(R_NilValue) {}
45+
46+
~OtherBuilder() { nanoarrow_release_sexp(chunks_sexp_); }
47+
48+
ArrowErrorCode Reserve(R_xlen_t n, ArrowError* error) override { return NANOARROW_OK; }
49+
50+
ArrowErrorCode PushNext(const ArrowArray* array, ArrowError* error) override {
51+
// Fill this in
52+
return NANOARROW_OK;
53+
}
54+
55+
ArrowErrorCode Finish(ArrowError* error) override {
56+
if (chunks_tail_ == chunks_sexp_) {
57+
Rprintf("zero chunks\n");
58+
// Zero chunks (return the ptype)
59+
// Probably need to ensure the ptype has zero elements
60+
SetValue(GetPtype());
61+
62+
} else if (chunks_tail_ == CDR(chunks_sexp_)) {
63+
Rprintf("one chunk\n");
64+
// One chunk (return the chunk)
65+
SetValue(CAR(chunks_tail_));
66+
67+
} else {
68+
Rprintf("many chunks\n");
69+
// Many chunks (concatenate or rbind)
70+
SEXP fun;
71+
if (Rf_inherits(ptype_sexp_, "data.frame")) {
72+
fun = PROTECT(Rf_install("rbind"));
73+
} else {
74+
fun = PROTECT(Rf_install("c"));
75+
}
76+
77+
SETCAR(chunks_sexp_, fun);
78+
UNPROTECT(1);
79+
80+
SEXP result = PROTECT(Rf_eval(chunks_sexp_, R_BaseEnv));
81+
SetValue(result);
82+
UNPROTECT(1);
83+
}
84+
85+
nanoarrow_release_sexp(chunks_sexp_);
86+
chunks_sexp_ = R_NilValue;
87+
chunks_tail_ = R_NilValue;
88+
return NANOARROW_OK;
89+
}
90+
91+
private:
92+
SEXP chunks_sexp_;
93+
SEXP chunks_tail_;
94+
95+
void Append(SEXP chunk_sexp) {
96+
if (chunks_sexp_ == R_NilValue) {
97+
// Not sure if we will need no function, c, or rbind when we
98+
// create this, so leave it as R_NilValue for now.
99+
SEXP chunks_init = PROTECT(Rf_lang1(R_NilValue));
100+
chunks_sexp_ = chunks_init;
101+
nanoarrow_preserve_sexp(chunks_sexp_);
102+
chunks_tail_ = chunks_sexp_;
103+
UNPROTECT(1);
104+
}
105+
106+
SEXP next_sexp = PROTECT(Rf_lcons(chunk_sexp, R_NilValue));
107+
SETCDR(chunks_tail_, next_sexp);
108+
UNPROTECT(1);
109+
chunks_tail_ = next_sexp;
110+
}
30111
};
31112

32113
#endif

0 commit comments

Comments
 (0)