SEXP dybuf_collect(SEXP s) { dybuf_info_t *d = (dybuf_info_t*) RAW(VECTOR_ELT(s, 1)); unsigned long total = 0; char *dst; SEXP head = VECTOR_ELT(s, 0), res; if (d->con) { long wr; /* FIXME: should we try partial sends as well ? */ if ((wr = R_WriteConnection(d->con, d->data, d->pos)) != d->pos) Rf_error("write failed, expected %lu, got %ld", d->pos, wr); d->pos = 0; return R_NilValue; } while (d->tail != head) { total += LENGTH(CAR(head)); head = CDR(head); } total += d->pos; dst = (char*) RAW(res = PROTECT(allocVector(RAWSXP, total))); head = VECTOR_ELT(s, 0); while (d->tail != head) { int l = LENGTH(CAR(head)); memcpy(dst, RAW(CAR(head)), l); dst += l; head = CDR(head); } if (d->pos) memcpy(dst, RAW(CAR(head)), d->pos); UNPROTECT(1); return res; }
std::streamsize connection_sink::write(const char* s, std::streamsize n) { size_t write_size; if ((write_size = R_WriteConnection(con_, (void*)s, n)) != static_cast<size_t>(n)) { Rcpp::stop("write failed, expected %l, got %l", n, write_size); } return write_size; }
void dybuf_add(SEXP s, const char *data, unsigned long len) { dybuf_info_t *d = (dybuf_info_t*) RAW(VECTOR_ELT(s, 1)); unsigned long n = (d->pos + len > d->size) ? (d->size - d->pos) : len; if (!len) return; /* printf("[%lu/%lu] %lu\n", d->pos, d->size, len); */ if (n) { memcpy(d->data + d->pos, data, n); d->pos += n; if (len == n) return; data += n; len -= n; } /* printf("[%lu/%lu] filled, need %lu more", d->pos, d->size, len); */ /* if the output is connection-based, flush */ if (d->con) { long wr; /* FIXME: should we try partial sends as well ? */ if ((wr = R_WriteConnection(d->con, d->data, d->pos)) != d->pos) Rf_error("write failed, expected %lu, got %ld", d->pos, wr); d->pos = 0; /* if the extra content is substantially big, don't even bother storing it and send right away */ if (len > (d->size / 2)) { /* FIXME: (actually FIX R): WriteConnection should be using const void* */ if ((wr = R_WriteConnection(d->con, (void*) data, len)) != len) Rf_error("write failed, expected %lu, got %ld", len, wr); } else { /* otherwise copy into the buffer */ memcpy(d->data, data, len); d->pos = len; } } else { /* need more buffers */ SEXP nb; while (len > d->size) d->size *= 2; /* printf(", creating %lu more\n", d->size); */ d->tail = SETCDR(d->tail, list1(nb = allocVector(RAWSXP, d->size))); memcpy(d->data = (char*) RAW(nb), data, len); d->pos = len; } }