Repository: numpy/numpy
File: numpy/_core/src/multiarray/stringdtype/dtype.c (C)

Code before:
    return ret;
}

/*
 * This is currently required even though the default implementation would work,
 * because the output, though enforced to be equal to the input, is parametric.
 */
static NPY_CASTING
stringdtype_sort_resolve_descriptors(
        PyArrayMethodObject *method,
        PyArray_DTypeMeta *const *dtypes,
        PyArray_Descr *const *input_descrs,
        PyArray_Descr **output_descrs,
        npy_intp *view_offset)
{
    output_descrs[0] = NPY_DT_CALL_ensure_canonical(input_descrs[0]);
    if (NPY_UNLIKELY(output_descrs[0] == NULL)) {
        return -1;
    }
    output_descrs[1] = NPY_DT_CALL_ensure_canonical(input_descrs[1]);
    if (NPY_UNLIKELY(output_descrs[1] == NULL)) {
        Py_XDECREF(output_descrs[0]);
        return -1;
    }

    // sorting cannot be a view
    *view_offset = 0;

    return method->casting;
}

int
stringdtype_wrap_argsort_loop(
        PyArrayMethod_Context *context,
        char *const *data, const npy_intp *dimensions, const npy_intp *strides,
        NpyAuxData *transferdata)
{
    PyArray_StringDTypeObject *sdescr =
            (PyArray_StringDTypeObject *)context->descriptors[0];
    PyArray_ArgSortImpl *argsort_loop =
        ((PyArrayMethod_SortParameters *)context->parameters)
        ->flags == NPY_SORT_STABLE ? &npy_amergesort_impl : &npy_aquicksort_impl;

    npy_string_allocator *allocator = NpyString_acquire_allocator(sdescr);
    int ret = argsort_loop(
            data[0], (npy_intp *)data[1], dimensions[0], context,
            context->descriptors[0]->elsize, &_sort_compare);
    NpyString_release_allocator(allocator);
    return ret;
}


Review comment (suggestion):
Small one, but I think by setting `*view_offset = 0` you actually indicate it *can* be a view (no view is `NPY_MIN_INTP`. I think it is fine not to touch `view_offset` at all, but maybe best to ask @seberg.

Code after:
    return ret;
}

/*
 * This is currently required even though the default implementation would work,
 * because the output, though enforced to be equal to the input, is parametric.
 */
static NPY_CASTING
stringdtype_sort_resolve_descriptors(
        PyArrayMethodObject *method,
        PyArray_DTypeMeta *const *dtypes,
        PyArray_Descr *const *input_descrs,
        PyArray_Descr **output_descrs,
        npy_intp *view_offset)
{
    output_descrs[0] = NPY_DT_CALL_ensure_canonical(input_descrs[0]);
    if (NPY_UNLIKELY(output_descrs[0] == NULL)) {
        return -1;
    }
    output_descrs[1] = NPY_DT_CALL_ensure_canonical(input_descrs[1]);
    if (NPY_UNLIKELY(output_descrs[1] == NULL)) {
        Py_XDECREF(output_descrs[0]);
        return -1;
    }

    return method->casting;
}

static int
stringdtype_wrap_argsort_loop(
        PyArrayMethod_Context *context,
        char *const *data, const npy_intp *dimensions, const npy_intp *strides,
        NpyAuxData *transferdata)
{
    PyArray_StringDTypeObject *sdescr =
            (PyArray_StringDTypeObject *)context->descriptors[0];
    PyArray_ArgSortImpl *argsort_loop =
        ((PyArrayMethod_SortParameters *)context->parameters)
        ->flags == NPY_SORT_STABLE ? &npy_amergesort_impl : &npy_aquicksort_impl;

    npy_string_allocator *allocator = NpyString_acquire_allocator(sdescr);
    int ret = argsort_loop(
            data[0], (npy_intp *)data[1], dimensions[0], context,
            context->descriptors[0]->elsize, &_sort_compare);
    NpyString_release_allocator(allocator);
    return ret;
}

static int
stringdtype_get_sort_loop(
        PyArrayMethod_Context *context,