in r/src/as_array.c [321:404]
static void as_array_chr(SEXP x_sexp, struct ArrowArray* array, SEXP schema_xptr,
struct ArrowError* error) {
struct ArrowSchema* schema = schema_from_xptr(schema_xptr);
struct ArrowSchemaView schema_view;
int result = ArrowSchemaViewInit(&schema_view, schema, error);
if (result != NANOARROW_OK) {
Rf_error("ArrowSchemaViewInit(): %s", error->message);
}
// Only consider the default create for now
if (schema_view.type != NANOARROW_TYPE_STRING) {
call_as_nanoarrow_array(x_sexp, array, schema_xptr, "as_nanoarrow_array_from_c");
return;
}
int64_t len = Rf_xlength(x_sexp);
result = ArrowArrayInitFromType(array, NANOARROW_TYPE_STRING);
if (result != NANOARROW_OK) {
Rf_error("ArrowArrayInitFromType() failed");
}
// Keep these buffers under the umbrella of the array so that we don't have
// to worry about cleaning them up if STRING_ELT jumps
struct ArrowBuffer* offset_buffer = ArrowArrayBuffer(array, 1);
struct ArrowBuffer* data_buffer = ArrowArrayBuffer(array, 2);
ArrowBufferReserve(offset_buffer, (len + 1) * sizeof(int32_t));
int64_t null_count = 0;
int32_t cumulative_len = 0;
ArrowBufferAppendUnsafe(offset_buffer, &cumulative_len, sizeof(int32_t));
for (int64_t i = 0; i < len; i++) {
SEXP item = STRING_ELT(x_sexp, i);
if (item == NA_STRING) {
null_count++;
} else {
const void* vmax = vmaxget();
const char* item_utf8 = Rf_translateCharUTF8(item);
int64_t item_size = strlen(item_utf8);
if ((item_size + cumulative_len) > INT_MAX) {
Rf_error("Use na_large_string() to convert character() with total size > 2GB");
}
int result = ArrowBufferAppend(data_buffer, item_utf8, item_size);
if (result != NANOARROW_OK) {
Rf_error("ArrowBufferAppend() failed");
}
cumulative_len += item_size;
vmaxset(vmax);
}
ArrowBufferAppendUnsafe(offset_buffer, &cumulative_len, sizeof(int32_t));
}
// Set the array fields
array->length = len;
array->offset = 0;
// If there are nulls, pack the validity buffer
if (null_count > 0) {
struct ArrowBitmap bitmap;
ArrowBitmapInit(&bitmap);
result = ArrowBitmapReserve(&bitmap, len);
if (result != NANOARROW_OK) {
Rf_error("ArrowBitmapReserve() failed");
}
for (int64_t i = 0; i < len; i++) {
uint8_t is_valid = STRING_ELT(x_sexp, i) != NA_STRING;
ArrowBitmapAppend(&bitmap, is_valid, 1);
}
ArrowArraySetValidityBitmap(array, &bitmap);
}
array->null_count = null_count;
result = ArrowArrayFinishBuildingDefault(array, error);
if (result != NANOARROW_OK) {
Rf_error("ArrowArrayFinishBuildingDefault(): %s", error->message);
}
}