in src/nanoarrow/array_inline.h [201:320]
static inline ArrowErrorCode _ArrowArrayAppendEmptyInternal(struct ArrowArray* array,
int64_t n, uint8_t is_valid) {
struct ArrowArrayPrivateData* private_data =
(struct ArrowArrayPrivateData*)array->private_data;
if (n == 0) {
return NANOARROW_OK;
}
// Some type-specific handling
switch (private_data->storage_type) {
case NANOARROW_TYPE_NA:
// (An empty value for a null array *is* a null)
array->null_count += n;
array->length += n;
return NANOARROW_OK;
case NANOARROW_TYPE_DENSE_UNION: {
// Add one null to the first child and append n references to that child
int8_t type_id = _ArrowArrayUnionTypeId(array, 0);
NANOARROW_RETURN_NOT_OK(
_ArrowArrayAppendEmptyInternal(array->children[0], 1, is_valid));
NANOARROW_RETURN_NOT_OK(
ArrowBufferAppendFill(ArrowArrayBuffer(array, 0), type_id, n));
for (int64_t i = 0; i < n; i++) {
NANOARROW_RETURN_NOT_OK(ArrowBufferAppendInt32(
ArrowArrayBuffer(array, 1), (int32_t)array->children[0]->length - 1));
}
// For the purposes of array->null_count, union elements are never considered "null"
// even if some children contain nulls.
array->length += n;
return NANOARROW_OK;
}
case NANOARROW_TYPE_SPARSE_UNION: {
// Add n nulls to the first child and append n references to that child
int8_t type_id = _ArrowArrayUnionTypeId(array, 0);
NANOARROW_RETURN_NOT_OK(
_ArrowArrayAppendEmptyInternal(array->children[0], n, is_valid));
for (int64_t i = 1; i < array->n_children; i++) {
NANOARROW_RETURN_NOT_OK(ArrowArrayAppendEmpty(array->children[i], n));
}
NANOARROW_RETURN_NOT_OK(
ArrowBufferAppendFill(ArrowArrayBuffer(array, 0), type_id, n));
// For the purposes of array->null_count, union elements are never considered "null"
// even if some children contain nulls.
array->length += n;
return NANOARROW_OK;
}
case NANOARROW_TYPE_FIXED_SIZE_LIST:
NANOARROW_RETURN_NOT_OK(ArrowArrayAppendEmpty(
array->children[0], n * private_data->layout.child_size_elements));
break;
case NANOARROW_TYPE_STRUCT:
for (int64_t i = 0; i < array->n_children; i++) {
NANOARROW_RETURN_NOT_OK(ArrowArrayAppendEmpty(array->children[i], n));
}
break;
default:
break;
}
// Append n is_valid bits to the validity bitmap. If we haven't allocated a bitmap yet
// and we need to append nulls, do it now.
if (!is_valid && private_data->bitmap.buffer.data == NULL) {
NANOARROW_RETURN_NOT_OK(ArrowBitmapReserve(&private_data->bitmap, array->length + n));
ArrowBitmapAppendUnsafe(&private_data->bitmap, 1, array->length);
ArrowBitmapAppendUnsafe(&private_data->bitmap, is_valid, n);
} else if (private_data->bitmap.buffer.data != NULL) {
NANOARROW_RETURN_NOT_OK(ArrowBitmapReserve(&private_data->bitmap, n));
ArrowBitmapAppendUnsafe(&private_data->bitmap, is_valid, n);
}
// Add appropriate buffer fill
struct ArrowBuffer* buffer;
int64_t size_bytes;
for (int i = 0; i < 3; i++) {
buffer = ArrowArrayBuffer(array, i);
size_bytes = private_data->layout.element_size_bits[i] / 8;
switch (private_data->layout.buffer_type[i]) {
case NANOARROW_BUFFER_TYPE_NONE:
case NANOARROW_BUFFER_TYPE_VALIDITY:
continue;
case NANOARROW_BUFFER_TYPE_DATA_OFFSET:
// Append the current value at the end of the offset buffer for each element
NANOARROW_RETURN_NOT_OK(ArrowBufferReserve(buffer, size_bytes * n));
for (int64_t j = 0; j < n; j++) {
ArrowBufferAppendUnsafe(buffer, buffer->data + size_bytes * (array->length + j),
size_bytes);
}
// Skip the data buffer
i++;
continue;
case NANOARROW_BUFFER_TYPE_DATA:
// Zero out the next bit of memory
if (private_data->layout.element_size_bits[i] % 8 == 0) {
NANOARROW_RETURN_NOT_OK(ArrowBufferAppendFill(buffer, 0, size_bytes * n));
} else {
NANOARROW_RETURN_NOT_OK(_ArrowArrayAppendBits(array, i, 0, n));
}
continue;
case NANOARROW_BUFFER_TYPE_TYPE_ID:
case NANOARROW_BUFFER_TYPE_UNION_OFFSET:
// These cases return above
return EINVAL;
}
}
array->length += n;
array->null_count += n * !is_valid;
return NANOARROW_OK;
}