NumPy-源码解析-七十六-

52 阅读1小时+

NumPy 源码解析(七十六)

.\numpy\numpy\_core\src\umath\reduction.h

#ifndef _NPY_PRIVATE__REDUCTION_H_
#define _NPY_PRIVATE__REDUCTION_H_

/************************************************************
 * Typedefs used by PyArray_ReduceWrapper, new in 1.7.
 ************************************************************/

/*
 * This typedef defines a function pointer type for assigning a reduction identity
 * to the result array before performing the reduction computation. The `data`
 * parameter is passed through from PyArray_ReduceWrapper.
 *
 * This function should return -1 on failure or 0 on success.
 */
typedef int (PyArray_AssignReduceIdentityFunc)(PyArrayObject *result,
                                               void *data);

/*
 * This typedef defines a function pointer type for the inner definition of the reduce loop.
 * It was intended for customization of the reduce loop at a lower level per ufunc.
 * This aspect of the API might be deprecated or restructured in future versions.
 */
typedef int (PyArray_ReduceLoopFunc)(PyArrayMethod_Context *context,
                                     PyArrayMethod_StridedLoop *strided_loop,
                                     NpyAuxData *auxdata,
                                     NpyIter *iter,
                                     char **dataptrs,
                                     npy_intp const *strides,
                                     npy_intp const *countptr,
                                     NpyIter_IterNextFunc *iternext,
                                     int needs_api,
                                     npy_intp skip_first_count);

#endif  // _NPY_PRIVATE__REDUCTION_H_
/*
 * This function executes all the standard NumPy reduction function
 * boilerplate code, just calling the appropriate inner loop function where
 * necessary.
 *
 * operand     : The array to be reduced.
 * out         : NULL, or the array into which to place the result.
 * wheremask   : NOT YET SUPPORTED, but this parameter is placed here
 *               so that support can be added in the future without breaking
 *               API compatibility. Pass in NULL.
 * operand_dtype : The dtype the inner loop expects for the operand.
 * result_dtype : The dtype the inner loop expects for the result.
 * casting     : The casting rule to apply to the operands.
 * axis_flags  : Flags indicating the reduction axes of 'operand'.
 * reorderable : If True, the reduction being done is reorderable, which
 *               means specifying multiple axes of reduction at once is ok,
 *               and the reduction code may calculate the reduction in an
 *               arbitrary order. The calculation may be reordered because
 *               of cache behavior or multithreading requirements.
 * keepdims    : If true, leaves the reduction dimensions in the result
 *               with size one.
 * identity    : If Py_None, PyArray_CopyInitialReduceValues is used, otherwise
 *               this value is used to initialize the result to
 *               the reduction's unit.
 * loop        : The loop which does the reduction.
 * data        : Data which is passed to the inner loop.
 * buffersize  : Buffer size for the iterator. For the default, pass in 0.
 * funcname    : The name of the reduction function, for error messages.
 * errormask   : forwarded from _get_bufsize_errmask
 */
NPY_NO_EXPORT PyArrayObject *
PyUFunc_ReduceWrapper(PyArrayMethod_Context *context,
        PyArrayObject *operand, PyArrayObject *out, PyArrayObject *wheremask,
        npy_bool *axis_flags, int keepdims,
        PyObject *initial, PyArray_ReduceLoopFunc *loop,
        npy_intp buffersize, const char *funcname, int errormask)
{
    // 实现所有标准 NumPy 函数的归约逻辑,根据需要调用适当的内部循环函数

    // 返回归约结果的数组对象
    NPY_NO_EXPORT PyArrayObject * 
    // 执行归约操作的上下文
    context,

    // 要归约的数组
    * operand, 
    
    // 存放结果的数组,如果为 NULL 则在函数内部创建
    * out, 
    
    // 状态掩码,目前不支持,为了未来兼容性保留
    * wheremask, 
    
    // 操作数的数据类型,内部循环期望的类型
    * operand_dtype, 
    
    // 结果的数据类型,内部循环期望的类型
    * result_dtype, 
    
    // 应用于操作数的类型转换规则
    * casting, 
    
    // 标志指示 'operand' 的归约轴
    * axis_flags, 
    
    // 如果为 True,保留结果中尺寸为一的归约维度
    keepdims, 
    
    // 如果为 Py_None,使用 PyArray_CopyInitialReduceValues 初始化结果
    * identity, 
    
    // 执行归约的循环
    * loop, 
    
    // 传递给内部循环的数据
    * data, 
    
    // 迭代器的缓冲区大小,默认为 0
    buffersize, 
    
    // 归约函数的名称,用于错误消息
    * funcname, 
    
    // 从 _get_bufsize_errmask 转发的错误掩码
    * errormask);
}

.\numpy\numpy\_core\src\umath\special_integer_comparisons.cpp

/*
 * 包含 Python.h 头文件,提供 Python C API 功能支持。
 */
#include <Python.h>

/*
 * 避免使用过时的 NumPy API,并设置使用的 NumPy API 版本。
 */
#define NPY_NO_DEPRECATED_API NPY_API_VERSION
#define _MULTIARRAYMODULE
#define _UMATHMODULE

/*
 * 包含 NumPy 的相关头文件,定义了 ndarray 类型、数学运算、通用函数等。
 */
#include "numpy/ndarraytypes.h"
#include "numpy/npy_math.h"
#include "numpy/ufuncobject.h"

/*
 * 包含抽象数据类型、分派功能、数据类型元信息、数据类型转换等相关头文件。
 */
#include "abstractdtypes.h"
#include "dispatching.h"
#include "dtypemeta.h"
#include "convert_datatype.h"

/*
 * 包含 legacy_array_method.h 头文件,用于获取 legacy ufunc 循环的包装函数。
 */
#include "legacy_array_method.h"

/*
 * 包含 special_integer_comparisons.h 头文件,用于特殊整数比较的函数。
 */
#include "special_integer_comparisons.h"


/*
 * 用于模板中的辅助函数,避免未覆盖的 switch 分支导致的警告。
 */
enum class COMP {
    EQ, NE, LT, LE, GT, GE,
};

/*
 * 根据 COMP 枚举值返回对应的比较名称字符串。
 */
static char const *
comp_name(COMP comp) {
    switch(comp) {
        case COMP::EQ: return "equal";
        case COMP::NE: return "not_equal";
        case COMP::LT: return "less";
        case COMP::LE: return "less_equal";
        case COMP::GT: return "greater";
        case COMP::GE: return "greater_equal";
        default:
            assert(0);  // 如果出现未知的 COMP 值,触发断言错误。
            return nullptr;
    }
}

/*
 * 模板函数,根据 result 参数设置输出数组的布尔值结果。
 * 返回值为 0 表示成功执行。
 */
template <bool result>
static int
fixed_result_loop(PyArrayMethod_Context *NPY_UNUSED(context),
        char *const data[], npy_intp const dimensions[],
        npy_intp const strides[], NpyAuxData *NPY_UNUSED(auxdata))
{
    npy_intp N = dimensions[0];  // 获取数组的第一个维度大小
    char *out = data[2];  // 获取输出数组的起始地址
    npy_intp stride = strides[2];  // 获取输出数组的步幅

    while (N--) {
        *reinterpret_cast<npy_bool *>(out) = result;  // 将 result 赋值给输出数组的当前元素
        out += stride;  // 移动到下一个输出数组元素
    }
    return 0;  // 返回表示成功执行
}

/*
 * 内联函数,根据数据类型 typenum 获取其最小值和最大值。
 */
static inline void
get_min_max(int typenum, long long *min, unsigned long long *max)
{
    *min = 0;  // 默认最小值为 0

    switch (typenum) {
        case NPY_BYTE:
            *min = NPY_MIN_BYTE;  // 设置为 NPY_BYTE 类型的最小值
            *max = NPY_MAX_BYTE;  // 设置为 NPY_BYTE 类型的最大值
            break;
        case NPY_UBYTE:
            *max = NPY_MAX_UBYTE;  // 设置为 NPY_UBYTE 类型的最大值
            break;
        case NPY_SHORT:
            *min = NPY_MIN_SHORT;  // 设置为 NPY_SHORT 类型的最小值
            *max = NPY_MAX_SHORT;  // 设置为 NPY_SHORT 类型的最大值
            break;
        case NPY_USHORT:
            *max = NPY_MAX_USHORT;  // 设置为 NPY_USHORT 类型的最大值
            break;
        case NPY_INT:
            *min = NPY_MIN_INT;  // 设置为 NPY_INT 类型的最小值
            *max = NPY_MAX_INT;  // 设置为 NPY_INT 类型的最大值
            break;
        case NPY_UINT:
            *max = NPY_MAX_UINT;  // 设置为 NPY_UINT 类型的最大值
            break;
        case NPY_LONG:
            *min = NPY_MIN_LONG;  // 设置为 NPY_LONG 类型的最小值
            *max = NPY_MAX_LONG;  // 设置为 NPY_LONG 类型的最大值
            break;
        case NPY_ULONG:
            *max = NPY_MAX_ULONG;  // 设置为 NPY_ULONG 类型的最大值
            break;
        case NPY_LONGLONG:
            *min = NPY_MIN_LONGLONG;  // 设置为 NPY_LONGLONG 类型的最小值
            *max = NPY_MAX_LONGLONG;  // 设置为 NPY_LONGLONG 类型的最大值
            break;
        case NPY_ULONGLONG:
            *max = NPY_MAX_ULONGLONG;  // 设置为 NPY_ULONGLONG 类型的最大值
            break;
        default:
            *max = 0;  // 默认最大值为 0
            assert(0);  // 如果出现未知的 typenum 值,触发断言错误
    }
}

/*
 * 内联函数,检查 Python 的长整型对象是否在给定类型的范围内。
 * 返回 -1 表示出错。
 */
static inline int
get_value_range(PyObject *value, int type_num, int *range)
{
    long long min;
    unsigned long long max;
    get_min_max(type_num, &min, &max);  // 获取指定类型的最小值和最大值

    int overflow;
    long long val = PyLong_AsLongLongAndOverflow(value, &overflow);  // 将 Python 长整型转换为 long long
    if (val == -1 && overflow == 0 && PyErr_Occurred()) {
        return -1;  // 如果转换出错,返回 -1
    }
    // 如果转换成功,检查值是否在指定类型的范围内

    return 0;  // 返回表示成功执行
}
    // 如果溢出标志为0
    if (overflow == 0) {
        // 如果值小于最小值,设置范围为-1
        if (val < min) {
            *range = -1;
        }
        // 如果值大于0且大于最大值,设置范围为1
        else if (val > 0 && (unsigned long long)val > max) {
            *range = 1;
        }
        // 否则,设置范围为0
        else {
            *range = 0;
        }
    }
    // 如果溢出标志为负数,设置范围为-1
    else if (overflow < 0) {
        *range = -1;
    }
    // 如果最大值小于等于最大长长整数值
    else if (max <= NPY_MAX_LONGLONG) {
        // 设置范围为1
        *range = 1;
    }
    // 否则,处理大于长长整数的情况
    else {
        /*
        * 如果我们正在检查无符号长长整数,则值可能大于长长整数,
        * 但在无符号长长整数的范围内。通过正常的Python整数比较来检查这一点。
        */
        // 创建一个无符号长长整数的Python对象
        PyObject *obj = PyLong_FromUnsignedLongLong(max);
        // 如果对象创建失败,返回-1
        if (obj == NULL) {
            return -1;
        }
        // 进行Python对象的大于比较
        int cmp = PyObject_RichCompareBool(value, obj, Py_GT);
        Py_DECREF(obj);
        // 如果比较出错,返回-1
        if (cmp < 0) {
            return -1;
        }
        // 根据比较结果设置范围:1表示大于,0表示否
        if (cmp) {
            *range = 1;
        }
        else {
            *range = 0;
        }
    }
    // 返回处理结果,成功返回0
    return 0;
/*
 * Find the type resolution for any numpy_int with pyint comparison.  This
 * function supports *both* directions for all types.
 */
static NPY_CASTING
resolve_descriptors_with_scalars(
    PyArrayMethodObject *self, PyArray_DTypeMeta **dtypes,
    PyArray_Descr **given_descrs, PyObject *const *input_scalars,
    PyArray_Descr **loop_descrs, npy_intp *view_offset)
{
    // 初始化变量 value_range 为 0
    int value_range = 0;

    // 检查第一个 dtypes 是否为 PyArray_PyLongDType 类型
    npy_bool first_is_pyint = dtypes[0] == &PyArray_PyLongDType;
    // 根据 first_is_pyint 的值选择数组和标量的索引
    int arr_idx = first_is_pyint ? 1 : 0;
    int scalar_idx = first_is_pyint ? 0 : 1;
    // 获取输入的标量
    PyObject *scalar = input_scalars[scalar_idx];
    // 断言数组的类型是整数类型
    assert(PyTypeNum_ISINTEGER(dtypes[arr_idx]->type_num));
    // 获取数组的数据类型元数据
    PyArray_DTypeMeta *arr_dtype = dtypes[arr_idx];

    /*
     * Three way decision (with hack) on value range:
     *  0: The value fits within the range of the dtype.
     *  1: The value came second and is larger or came first and is smaller.
     * -1: The value came second and is smaller or came first and is larger
     */
    // 如果标量不为空且是精确的长整型
    if (scalar != NULL && PyLong_CheckExact(scalar)) {
        // 获取标量值的范围,并根据结果调整 value_range
        if (get_value_range(scalar, arr_dtype->type_num, &value_range) < 0) {
            return _NPY_ERROR_OCCURRED_IN_CAST;
        }
        // 如果 first_is_pyint 为真,则将 value_range 取反
        if (first_is_pyint == 1) {
            value_range *= -1;
        }
    }

    /*
     * Very small/large values always need to be encoded as `object` dtype
     * in order to never fail casting (NumPy will store the Python integer
     * in a 0-D object array this way -- even if we never inspect it).
     *
     * TRICK: We encode the value range by whether or not we use the object
     *        singleton!  This information is then available in `get_loop()`
     *        to pick a loop that returns always True or False.
     */
    // 根据 value_range 的值选择相应的描述符类型
    if (value_range == 0) {
        // 对于范围为 0 的情况,使用数组数据类型的 singleton
        Py_INCREF(arr_dtype->singleton);
        loop_descrs[scalar_idx] = arr_dtype->singleton;
    }
    else if (value_range < 0) {
        // 对于范围小于 0 的情况,使用 NPY_OBJECT 类型的描述符
        loop_descrs[scalar_idx] = PyArray_DescrFromType(NPY_OBJECT);
    }
    else {
        // 对于范围大于 0 的情况,创建一个新的 NPY_OBJECT 类型的描述符
        loop_descrs[scalar_idx] = PyArray_DescrNewFromType(NPY_OBJECT);
        if (loop_descrs[scalar_idx] == NULL) {
            return _NPY_ERROR_OCCURRED_IN_CAST;
        }
    }
    // 增加数组数据类型的 singleton 的引用计数
    Py_INCREF(arr_dtype->singleton);
    // 将数组数据类型的 singleton 设置为数组的描述符
    loop_descrs[arr_idx] = arr_dtype->singleton;
    // 将 NP_BOOL 类型的描述符设置为第三个描述符
    loop_descrs[2] = PyArray_DescrFromType(NPY_BOOL);

    // 返回无需转换的状态
    return NPY_NO_CASTING;
}

/*
 * Template function to retrieve a loop based on the comparison type.
 */
template<COMP comp>
static int
get_loop(PyArrayMethod_Context *context,
        int aligned, int move_references, const npy_intp *strides,
        PyArrayMethod_StridedLoop **out_loop, NpyAuxData **out_transferdata,
        NPY_ARRAYMETHOD_FLAGS *flags)
{
    // 如果第一个描述符的类型与第二个相同,则回退到旧的循环实现
    if (context->descriptors[1]->type_num == context->descriptors[0]->type_num) {
        /*
         * Fall back to the current implementation, which wraps legacy loops.
         */
        return get_wrapped_legacy_ufunc_loop(
                context, aligned, move_references, strides,
                out_loop, out_transferdata, flags);
    }
}
    // 否则情况的处理分支,开始
    else {
        // 定义指向另一个描述符的指针
        PyArray_Descr *other_descr;
        // 如果第二个描述符的类型是 NPY_OBJECT,则将其赋给 other_descr
        if (context->descriptors[1]->type_num == NPY_OBJECT) {
            other_descr = context->descriptors[1];
        }
        // 否则,假设第一个描述符的类型是 NPY_OBJECT
        else {
            assert(context->descriptors[0]->type_num == NPY_OBJECT);
            other_descr = context->descriptors[0];
        }
        // HACK: 如果描述符是单例,则结果较小
        // 创建一个指向 NPY_OBJECT 类型的单例描述符对象
        PyArray_Descr *obj_singleton = PyArray_DescrFromType(NPY_OBJECT);
        // 如果 other_descr 和 obj_singleton 相等
        if (other_descr == obj_singleton) {
            // 根据比较操作类型设置输出循环的指针
            switch (comp) {
                case COMP::EQ:
                case COMP::LT:
                case COMP::LE:
                    *out_loop = &fixed_result_loop<false>;
                    break;
                case COMP::NE:
                case COMP::GT:
                case COMP::GE:
                    *out_loop = &fixed_result_loop<true>;
                    break;
            }
        }
        // 否则,other_descr 和 obj_singleton 不相等
        else {
            // 根据比较操作类型设置输出循环的指针
            switch (comp) {
                case COMP::EQ:
                case COMP::GT:
                case COMP::GE:
                    *out_loop = &fixed_result_loop<false>;
                    break;
                case COMP::NE:
                case COMP::LT:
                case COMP::LE:
                    *out_loop = &fixed_result_loop<true>;
                    break;
            }
        }
        // 释放单例描述符对象的引用
        Py_DECREF(obj_singleton);
    }
    // 设置标志位,指示无浮点错误
    *flags = NPY_METH_NO_FLOATINGPOINT_ERRORS;
    // 返回 0 表示成功
    return 0;
/*
 * 结束函数,返回成功状态码
 */
}


/*
 * 用于将 Python 整数添加到 NumPy 整数比较中的机制,
 * 以及用于特殊情况下的 Python 整数与 Python 整数比较的特殊推广。
 */

/*
 * 简单的推广器,确保在输入仅为 Python 整数时使用对象循环。
 * 注意,如果用户显式传递 Python `int` 抽象的 DType,则承诺实际传递的是 Python 整数,
 * 我们接受这一点,并不做检查。
 */
static int
pyint_comparison_promoter(PyUFuncObject *NPY_UNUSED(ufunc),
        PyArray_DTypeMeta *op_dtypes[], PyArray_DTypeMeta *signature[],
        PyArray_DTypeMeta *new_op_dtypes[])
{
    new_op_dtypes[0] = NPY_DT_NewRef(&PyArray_ObjectDType);  // 第一个操作数类型设为对象类型
    new_op_dtypes[1] = NPY_DT_NewRef(&PyArray_ObjectDType);  // 第二个操作数类型设为对象类型
    new_op_dtypes[2] = NPY_DT_NewRef(&PyArray_BoolDType);    // 结果类型设为布尔类型
    return 0;  // 返回成功状态码
}


/*
 * 此函数使用传入的循环替换步进循环,并将其注册到给定的 ufunc 中。
 * 它还为 (pyint, pyint, bool) 添加推广器,以使用 (object, object, bool) 实现。
 */
template<COMP comp>
static int
add_dtype_loops(PyObject *umath, PyArrayMethod_Spec *spec, PyObject *info)
{
    PyArray_DTypeMeta *PyInt = &PyArray_PyLongDType;  // Python 整数类型

    PyObject *name = PyUnicode_FromString(comp_name(comp));
    if (name == nullptr) {  // 如果创建名称对象失败
        return -1;  // 返回错误状态码
    }
    PyUFuncObject *ufunc = (PyUFuncObject *)PyObject_GetItem(umath, name);  // 获取 ufunc 对象
    Py_DECREF(name);  // 释放名称对象的引用计数
    if (ufunc == nullptr) {  // 如果获取 ufunc 对象失败
        return -1;  // 返回错误状态码
    }
    if (Py_TYPE(ufunc) != &PyUFunc_Type) {  // 如果 ufunc 对象类型不是 PyUFunc_Type
        PyErr_SetString(PyExc_RuntimeError,
                "internal NumPy error: comparison not a ufunc");  // 设置错误信息
        goto fail;  // 跳转到失败处理代码块
    }

    /* 
     * 注意:迭代所有类型号码,希望减少此次迭代。
     *       (如果我们总体上统一 int DTypes 将更容易。)
     */
    for (int typenum = NPY_BYTE; typenum <= NPY_ULONGLONG; typenum++) {
        spec->slots[0].pfunc = (void *)get_loop<comp>;  // 设置特定比较操作的循环函数

        PyArray_DTypeMeta *Int = PyArray_DTypeFromTypeNum(typenum);  // 根据类型号码获取类型对象

        /* 注册正向和反向方向的 spec/loop */
        spec->dtypes[0] = Int;     // 第一个操作数类型设为当前类型对象
        spec->dtypes[1] = PyInt;   // 第二个操作数类型设为 Python 整数类型
        int res = PyUFunc_AddLoopFromSpec_int((PyObject *)ufunc, spec, 1);  // 添加 spec/loop 到 ufunc
        if (res < 0) {
            Py_DECREF(Int);  // 减少类型对象的引用计数
            goto fail;  // 跳转到失败处理代码块
        }
        spec->dtypes[0] = PyInt;   // 第一个操作数类型设为 Python 整数类型
        spec->dtypes[1] = Int;     // 第二个操作数类型设为当前类型对象
        res = PyUFunc_AddLoopFromSpec_int((PyObject *)ufunc, spec, 1);  // 添加 spec/loop 到 ufunc
        Py_DECREF(Int);  // 减少类型对象的引用计数
        if (res < 0) {
            goto fail;  // 跳转到失败处理代码块
        }
    }

    /*
     * 安装推广信息以允许两个 Python 整数进行比较。
     */
    return PyUFunc_AddLoop((PyUFuncObject *)ufunc, info, 0);  // 添加循环到 ufunc 并返回成功状态码

    Py_DECREF(ufunc);  // 减少 ufunc 对象的引用计数
    return 0;  // 返回成功状态码

  fail:
    Py_DECREF(ufunc);  // 减少 ufunc 对象的引用计数
    return -1;  // 返回错误状态码
}


template<COMP...>
struct add_loops;

template<>
struct add_loops<> {
    int operator()(PyObject*, PyArrayMethod_Spec*, PyObject *) {
        return 0;  // 返回成功状态码
    }
};
/*
 * 定义模板结构体 `add_loops`,接受多个比较器作为模板参数,并重载函数调用操作符
 */
struct add_loops<comp, comps...> {
    /*
     * 重载函数调用操作符,接受三个指针参数,并返回整数结果
     */
    int operator()(PyObject* umath, PyArrayMethod_Spec* spec, PyObject *info) {
        // 如果调用 `add_dtype_loops` 失败,返回 -1
        if (add_dtype_loops<comp>(umath, spec, info) < 0) {
            return -1;
        }
        else {
            // 递归调用 `add_loops` 结构体的实例
            return add_loops<comps...>()(umath, spec, info);
        }
    }
};

/*
 * 初始化特殊整数比较操作
 */
NPY_NO_EXPORT int
init_special_int_comparisons(PyObject *umath)
{
    int res = -1;
    PyObject *info = NULL, *promoter = NULL;
    PyArray_DTypeMeta *Bool = &PyArray_BoolDType;

    /* 所有循环具有布尔输出 DType(其它类型稍后填充) */
    PyArray_DTypeMeta *dtypes[] = {NULL, NULL, Bool};
    /*
     * 目前我们只有一个循环,即步进循环。默认类型解析器确保原生字节顺序/规范表示。
     */
    PyType_Slot slots[] = {
        {NPY_METH_get_loop, nullptr},
        {_NPY_METH_resolve_descriptors_with_scalars,
             (void *)&resolve_descriptors_with_scalars},
        {0, NULL},
    };

    PyArrayMethod_Spec spec = {};
    spec.name = "templated_pyint_to_integers_comparisons";
    spec.nin = 2;
    spec.nout = 1;
    spec.dtypes = dtypes;
    spec.slots = slots;
    spec.flags = NPY_METH_NO_FLOATINGPOINT_ERRORS;

    /*
     * 以下设置正确的促进器,以使类似 `np.equal(2, 4)`(使用两个 Python 整数)的比较使用对象循环。
     */
    PyObject *dtype_tuple = PyTuple_Pack(3,
            &PyArray_PyLongDType, &PyArray_PyLongDType, Bool);
    if (dtype_tuple == NULL) {
        goto finish;
    }
    promoter = PyCapsule_New(
            (void *)&pyint_comparison_promoter, "numpy._ufunc_promoter", NULL);
    if (promoter == NULL) {
        Py_DECREF(dtype_tuple);
        goto finish;
    }
    info = PyTuple_Pack(2, dtype_tuple, promoter);
    Py_DECREF(dtype_tuple);
    Py_DECREF(promoter);
    if (info == NULL) {
        goto finish;
    }

    /* 添加所有 PyInt 和 NumPy 整数比较的组合 */
    using comp_looper = add_loops<COMP::EQ, COMP::NE, COMP::LT, COMP::LE, COMP::GT, COMP::GE>;
    if (comp_looper()(umath, &spec, info) < 0) {
        goto finish;
    }

    res = 0;
  finish:

    Py_XDECREF(info);
    return res;
}

.\numpy\numpy\_core\src\umath\special_integer_comparisons.h

#ifndef _NPY_CORE_SRC_UMATH_SPECIAL_COMPARISONS_H_
// 如果 _NPY_CORE_SRC_UMATH_SPECIAL_COMPARISONS_H_ 宏未定义,则执行以下内容
#define _NPY_CORE_SRC_UMATH_SPECIAL_COMPARISONS_H_
// 定义 _NPY_CORE_SRC_UMATH_SPECIAL_COMPARISONS_H_ 宏,避免重复包含

#ifdef __cplusplus
// 如果编译器为 C++,则进行 C++ 的链接处理
extern "C" {
#endif
// 开始 extern "C" 块,确保链接符合 C++ 格式的要求

NPY_NO_EXPORT int
// 声明一个不导出的 int 类型函数,NPY_NO_EXPORT 是一个宏,用于指示不导出函数
init_special_int_comparisons(PyObject *umath);
// 函数原型声明,初始化特殊整数比较函数,接受一个 PyObject 类型指针作为参数

#ifdef __cplusplus
// 如果编译器为 C++,结束 C++ 的链接处理
}
#endif
// 结束 extern "C"#endif  /* _NPY_CORE_SRC_UMATH_SPECIAL_COMPARISONS_H_ */
// 结束宏定义,确保头文件内容完整,并使用宏定义的名称作为结束注释

.\numpy\numpy\_core\src\umath\stringdtype_ufuncs.cpp

/* Ufunc implementations for the StringDType class */

#define PY_SSIZE_T_CLEAN
#include <Python.h>

#define NPY_NO_DEPRECATED_API NPY_API_VERSION
#define _MULTIARRAYMODULE
#define _UMATHMODULE

#include "numpy/arrayobject.h"
#include "numpy/ndarraytypes.h"
#include "numpy/npy_math.h"
#include "numpy/ufuncobject.h"

#include "numpyos.h"
#include "gil_utils.h"
#include "dtypemeta.h"
#include "abstractdtypes.h"
#include "dispatching.h"
#include "string_ufuncs.h"
#include "stringdtype_ufuncs.h"
#include "string_buffer.h"
#include "string_fastsearch.h"
#include "templ_common.h" /* for npy_mul_size_with_overflow_size_t */

#include "stringdtype/static_string.h"
#include "stringdtype/dtype.h"
#include "stringdtype/utf8_utils.h"

/* Define macro LOAD_TWO_INPUT_STRINGS(CONTEXT) for loading and checking two input strings */
#define LOAD_TWO_INPUT_STRINGS(CONTEXT)                                            \
        const npy_packed_static_string *ps1 = (npy_packed_static_string *)in1;     \
        npy_static_string s1 = {0, NULL};                                          \
        int s1_isnull = NpyString_load(s1allocator, ps1, &s1);                     \
        const npy_packed_static_string *ps2 = (npy_packed_static_string *)in2;     \
        npy_static_string s2 = {0, NULL};                                          \
        int s2_isnull = NpyString_load(s2allocator, ps2, &s2);                     \
        if (s1_isnull == -1 || s2_isnull == -1) {                                  \
            npy_gil_error(PyExc_MemoryError, "Failed to load string in %s",        \
                          CONTEXT);                                                \
            goto fail;                                                             \
        }                                                                          \

/* Implementation of a function to resolve descriptors for multiplication */
static NPY_CASTING
multiply_resolve_descriptors(
        struct PyArrayMethodObject_tag *NPY_UNUSED(method),
        PyArray_DTypeMeta *const dtypes[], PyArray_Descr *const given_descrs[],
        PyArray_Descr *loop_descrs[], npy_intp *NPY_UNUSED(view_offset))
{
    PyArray_Descr *ldescr = given_descrs[0];  // Left input descriptor
    PyArray_Descr *rdescr = given_descrs[1];  // Right input descriptor
    PyArray_StringDTypeObject *odescr = NULL; // Output string dtype descriptor
    PyArray_Descr *out_descr = NULL;          // Output descriptor

    // Determine which dtype (left or right) corresponds to PyArray_StringDType
    if (dtypes[0] == &PyArray_StringDType) {
        odescr = (PyArray_StringDTypeObject *)ldescr;
    }
    else {
        odescr = (PyArray_StringDTypeObject *)rdescr;
    }

    // If the third descriptor is not provided, create a new instance of string dtype
    if (given_descrs[2] == NULL) {
        out_descr = (PyArray_Descr *)new_stringdtype_instance(
                odescr->na_object, odescr->coerce);
        if (out_descr == NULL) {
            return (NPY_CASTING)-1;  // Return error if creation fails
        }
    }
    else {
        Py_INCREF(given_descrs[2]);
        out_descr = given_descrs[2];
    }

    // Increment references to input descriptors and assign to loop descriptors
    Py_INCREF(ldescr);
    loop_descrs[0] = ldescr;
    Py_INCREF(rdescr);
    loop_descrs[1] = rdescr;
    loop_descrs[2] = out_descr;  // Assign output descriptor to loop descriptors array

    return NPY_NO_CASTING;  // Return no-casting flag
}
# 定义一个静态函数,用于在循环中执行字符串数组的乘法操作
static int multiply_loop_core(
        npy_intp N, char *sin, char *iin, char *out,
        npy_intp s_stride, npy_intp i_stride, npy_intp o_stride,
        PyArray_StringDTypeObject *idescr, PyArray_StringDTypeObject *odescr)
{
    # 创建一个描述符数组,包含输入和输出的字符串数据类型描述符
    PyArray_Descr *descrs[2] =
            {(PyArray_Descr *)idescr, (PyArray_Descr *)odescr};
    # 申请字符串分配器的内存,获取用于字符串操作的分配器
    npy_string_allocator *allocators[2] = {};
    NpyString_acquire_allocators(2, descrs, allocators);
    # 分别获取输入和输出字符串的分配器
    npy_string_allocator *iallocator = allocators[0];
    npy_string_allocator *oallocator = allocators[1];
    # 检查输入描述符是否有空对象
    int has_null = idescr->na_object != NULL;
    # 检查输入描述符是否具有 NaN 或 NA 值
    int has_nan_na = idescr->has_nan_na;
    # 检查输入描述符是否具有字符串类型的 NA 值
    int has_string_na = idescr->has_string_na;
    # 获取默认字符串指针
    const npy_static_string *default_string = &idescr->default_string;
    // 循环 N 次,处理输入和输出的字符串数据
    while (N--) {
        // 从输入源读取一个静态压缩字符串结构到 ips
        const npy_packed_static_string *ips =
                (npy_packed_static_string *)sin;
        // 初始化输出的静态字符串结构 is
        npy_static_string is = {0, NULL};
        // 从输出源读取一个静态压缩字符串结构到 ops
        npy_packed_static_string *ops = (npy_packed_static_string *)out;
        // 载入 ips 所指向的数据到 is,如果失败返回 is_isnull
        int is_isnull = NpyString_load(iallocator, ips, &is);
        // 如果载入过程中出现内存错误,报错并跳转到 fail 标签
        if (is_isnull == -1) {
            npy_gil_error(PyExc_MemoryError,
                          "Failed to load string in multiply");
            goto fail;
        }
        // 如果载入结果为空值
        else if (is_isnull) {
            // 如果允许 NaN 或 NA 值存在
            if (has_nan_na) {
                // 将空值打包到 ops 中,如果失败则报错并跳转到 fail 标签
                if (NpyString_pack_null(oallocator, ops) < 0) {
                    npy_gil_error(PyExc_MemoryError,
                                  "Failed to deallocate string in multiply");
                    goto fail;
                }
                // 调整输入和输出指针以及步长,并继续下一次循环
                sin += s_stride;
                iin += i_stride;
                out += o_stride;
                continue;
            }
            // 如果存在字符串的 NA 值或者不允许空值存在
            else if (has_string_na || !has_null) {
                // 使用默认字符串作为 is 的值
                is = *(npy_static_string *)default_string;
            }
            // 否则报类型错误并跳转到 fail 标签
            else {
                npy_gil_error(PyExc_TypeError,
                              "Cannot multiply null that is not a nan-like "
                              "value");
                goto fail;
            }
        }
        // 从输入中读取因子值到 factor
        T factor = *(T *)iin;
        // 计算新的字符串大小,检查是否溢出
        size_t cursize = is.size;
        size_t newsize;
        int overflowed = npy_mul_with_overflow_size_t(
                &newsize, cursize, factor);
        // 如果溢出,报内存错误并跳转到 fail 标签
        if (overflowed) {
            npy_gil_error(PyExc_MemoryError,
                          "Failed to allocate string in string multiply");
            goto fail;
        }

        char *buf = NULL;
        npy_static_string os = {0, NULL};
        // 如果描述符相同,执行原地操作
        if (descrs[0] == descrs[1]) {
            // 分配新的缓冲区以存储扩展后的字符串
            buf = (char *)PyMem_RawMalloc(newsize);
            // 如果分配失败,报内存错误并跳转到 fail 标签
            if (buf == NULL) {
                npy_gil_error(PyExc_MemoryError,
                              "Failed to allocate string in multiply");
                goto fail;
            }
        }
        // 如果描述符不同,加载新的字符串到 os 中
        else {
            // 加载新字符串到 ops 中,如果失败则跳转到 fail 标签
            if (load_new_string(
                        ops, &os, newsize,
                        oallocator, "multiply") == -1) {
                goto fail;
            }
            // 将新缓冲区初始化为 os.buf
            /* explicitly discard const; initializing new buffer */
            buf = (char *)os.buf;
        }

        // 将 is.buf 的内容复制 factor 次到 buf 中
        for (size_t i = 0; i < (size_t)factor; i++) {
            /* multiply can't overflow because cursize * factor */
            /* has already been checked and doesn't overflow */
            memcpy((char *)buf + i * cursize, is.buf, cursize);
        }

        // 如果描述符相同,进行原地打包操作
        if (descrs[0] == descrs[1]) {
            // 将 buf 中的数据打包到 ops 中,如果失败则报内存错误并跳转到 fail 标签
            if (NpyString_pack(oallocator, ops, buf, newsize) < 0) {
                npy_gil_error(PyExc_MemoryError,
                              "Failed to pack string in multiply");
                goto fail;
            }
            // 释放临时缓冲区 buf
            PyMem_RawFree(buf);
        }

        // 调整输入和输出指针以及步长,准备下一轮循环
        sin += s_stride;
        iin += i_stride;
        out += o_stride;
    }
    // 调用 NpyString_release_allocators 函数,释放内存分配器资源,参数为 2 和 allocators 数组
    NpyString_release_allocators(2, allocators);
    // 返回整数值 0,表示函数执行成功
    return 0;
fail:
    # 释放两个分配器,这里使用了 NpyString_release_allocators 函数
    NpyString_release_allocators(2, allocators);
    # 返回 -1,表示函数执行失败
    return -1;
}

template <typename T>
static int multiply_right_strided_loop(
        PyArrayMethod_Context *context, char *const data[],
        npy_intp const dimensions[], npy_intp const strides[],
        NpyAuxData *NPY_UNUSED(auxdata))
{
    // 获取输入和输出的数据类型描述符
    PyArray_StringDTypeObject *idescr =
            (PyArray_StringDTypeObject *)context->descriptors[0];
    PyArray_StringDTypeObject *odescr =
            (PyArray_StringDTypeObject *)context->descriptors[2];
    // 获取数组的长度
    npy_intp N = dimensions[0];
    // 获取输入数组的指针
    char *sin = data[0];
    char *iin = data[1];
    char *out = data[2];
    // 获取输入数组的步长
    npy_intp in1_stride = strides[0];
    npy_intp in2_stride = strides[1];
    npy_intp out_stride = strides[2];

    // 调用模板函数 multiply_loop_core 进行核心的乘法运算
    return multiply_loop_core<T>(
            N, sin, iin, out, in1_stride, in2_stride, out_stride,
            idescr, odescr);
}

template <typename T>
static int multiply_left_strided_loop(
        PyArrayMethod_Context *context, char *const data[],
        npy_intp const dimensions[], npy_intp const strides[],
        NpyAuxData *NPY_UNUSED(auxdata))
{
    // 获取输入和输出的数据类型描述符
    PyArray_StringDTypeObject *idescr =
            (PyArray_StringDTypeObject *)context->descriptors[1];
    PyArray_StringDTypeObject *odescr =
            (PyArray_StringDTypeObject *)context->descriptors[2];
    // 获取数组的长度
    npy_intp N = dimensions[0];
    // 获取输入数组的指针
    char *iin = data[0];
    char *sin = data[1];
    char *out = data[2];
    // 获取输入数组的步长
    npy_intp in1_stride = strides[0];
    npy_intp in2_stride = strides[1];
    npy_intp out_stride = strides[2];

    // 调用模板函数 multiply_loop_core 进行核心的乘法运算
    return multiply_loop_core<T>(
            N, sin, iin, out, in2_stride, in1_stride, out_stride,
            idescr, odescr);
}

static NPY_CASTING
binary_resolve_descriptors(struct PyArrayMethodObject_tag *NPY_UNUSED(method),
                           PyArray_DTypeMeta *const NPY_UNUSED(dtypes[]),
                           PyArray_Descr *const given_descrs[],
                           PyArray_Descr *loop_descrs[],
                           npy_intp *NPY_UNUSED(view_offset))
{
    // 获取给定的输入数据类型描述符
    PyArray_StringDTypeObject *descr1 = (PyArray_StringDTypeObject *)given_descrs[0];
    PyArray_StringDTypeObject *descr2 = (PyArray_StringDTypeObject *)given_descrs[1];
    // 判断是否需要强制转换输出
    int out_coerce = descr1->coerce && descr1->coerce;
    PyObject *out_na_object = NULL;

    // 检查字符串类型描述符的兼容性,如果不兼容则返回 -1
    if (stringdtype_compatible_na(
                descr1->na_object, descr2->na_object, &out_na_object) == -1) {
        return (NPY_CASTING)-1;
    }

    // 增加输入描述符的引用计数,并设置循环描述符的值
    Py_INCREF(given_descrs[0]);
    loop_descrs[0] = given_descrs[0];
    // 增加输入描述符的引用计数,并设置循环描述符的值
    Py_INCREF(given_descrs[1]);
    loop_descrs[1] = given_descrs[1];

    PyArray_Descr *out_descr = NULL;

    // 如果没有给定输出描述符,则创建一个新的字符串类型实例
    if (given_descrs[2] == NULL) {
        out_descr = (PyArray_Descr *)new_stringdtype_instance(
                out_na_object, out_coerce);

        // 如果创建失败,则返回 -1
        if (out_descr == NULL) {
            return (NPY_CASTING)-1;
        }
    }
    else {
        // 增加给定输出描述符的引用计数,并设置循环描述符的值
        Py_INCREF(given_descrs[2]);
        loop_descrs[2] = given_descrs[2];
    }

    // 设置输出描述符的值
    loop_descrs[2] = out_descr;

    // 返回不需要任何强制转换
    return NPY_NO_CASTING;
}
# 定义名为 add_strided_loop 的静态函数,接受 PyArrayMethod_Context 结构体指针和多个数组参数
static int
add_strided_loop(PyArrayMethod_Context *context, char *const data[],
                 npy_intp const dimensions[], npy_intp const strides[],
                 NpyAuxData *NPY_UNUSED(auxdata))
{
    # 获取第一个输入数组的字符串数据类型描述符
    PyArray_StringDTypeObject *s1descr = (PyArray_StringDTypeObject *)context->descriptors[0];
    # 获取第二个输入数组的字符串数据类型描述符
    PyArray_StringDTypeObject *s2descr = (PyArray_StringDTypeObject *)context->descriptors[1];
    # 获取输出数组的字符串数据类型描述符
    PyArray_StringDTypeObject *odescr = (PyArray_StringDTypeObject *)context->descriptors[2];
    # 检查 s1descr 中是否包含空值对象
    int has_null = s1descr->na_object != NULL;
    # 检查 s1descr 是否具有 NaN 和 NA 值
    int has_nan_na = s1descr->has_nan_na;
    # 检查 s1descr 是否包含字符串 NA 值
    int has_string_na = s1descr->has_string_na;
    # 获取 s1descr 的默认字符串
    const npy_static_string *default_string = &s1descr->default_string;
    # 获取输入数组的第一维度大小
    npy_intp N = dimensions[0];
    # 获取第一个输入数组的起始地址
    char *in1 = data[0];
    # 获取第二个输入数组的起始地址
    char *in2 = data[1];
    # 获取输出数组的起始地址
    char *out = data[2];
    # 获取第一个输入数组的步长
    npy_intp in1_stride = strides[0];
    # 获取第二个输入数组的步长
    npy_intp in2_stride = strides[1];
    # 获取输出数组的步长
    npy_intp out_stride = strides[2];

    # 创建一个长度为 3 的指针数组 allocators,用于存储字符串分配器
    npy_string_allocator *allocators[3] = {};
    # 调用 NpyString_acquire_allocators 函数获取字符串分配器
    NpyString_acquire_allocators(3, context->descriptors, allocators);
    # 分别获取第一个、第二个输入数组以及输出数组的字符串分配器
    npy_string_allocator *s1allocator = allocators[0];
    npy_string_allocator *s2allocator = allocators[1];
    npy_string_allocator *oallocator = allocators[2];
    // 循环执行 N 次,每次执行一组操作
    while (N--) {
        // 宏定义:加载两个输入字符串,操作为"add"
        LOAD_TWO_INPUT_STRINGS("add")
        
        // 初始化变量
        char *buf = NULL;
        npy_static_string os = {0, NULL};
        size_t newsize = 0;
        npy_packed_static_string *ops = (npy_packed_static_string *)out;
        
        // 检查是否存在空值
        if (NPY_UNLIKELY(s1_isnull || s2_isnull)) {
            // 如果存在 NaN 或 NA,将空字符串打包到输出
            if (has_nan_na) {
                if (NpyString_pack_null(oallocator, ops) < 0) {
                    // 内存错误处理:打包字符串失败
                    npy_gil_error(PyExc_MemoryError,
                                  "Failed to deallocate string in add");
                    goto fail;
                }
                // 跳转到下一步骤
                goto next_step;
            }
            // 如果存在字符串 NA 或没有空值
            else if (has_string_na || !has_null) {
                // 如果 s1 为空,则使用默认字符串
                if (s1_isnull) {
                    s1 = *default_string;
                }
                // 如果 s2 为空,则使用默认字符串
                if (s2_isnull) {
                    s2 = *default_string;
                }
            }
            // 否则,出现不支持的空值情况,抛出值错误
            else {
                npy_gil_error(PyExc_ValueError,
                              "Cannot add null that is not a nan-like value");
                goto fail;
            }
        }

        // 检查是否会溢出
        newsize = s1.size + s2.size;
        if (newsize < s1.size) {
            // 内存错误处理:分配字符串失败
            npy_gil_error(PyExc_MemoryError, "Failed to allocate string in add");
            goto fail;
        }

        // 如果是原地操作
        if (s1descr == odescr || s2descr == odescr) {
            // 分配内存
            buf = (char *)PyMem_RawMalloc(newsize);

            if (buf == NULL) {
                // 内存错误处理:分配字符串失败
                npy_gil_error(PyExc_MemoryError,
                          "Failed to allocate string in add");
                goto fail;
            }
        }
        // 否则,加载新字符串并初始化新缓冲区
        else {
            if (load_new_string(ops, &os, newsize, oallocator, "add") == -1) {
                goto fail;
            }
            // 显式丢弃 const;初始化新缓冲区
            buf = (char *)os.buf;
        }

        // 复制 s1 和 s2 的内容到 buf
        memcpy(buf, s1.buf, s1.size);
        memcpy(buf + s1.size, s2.buf, s2.size);

        // 清理临时的原地缓冲区
        if (s1descr == odescr || s2descr == odescr) {
            // 将 buf 打包到输出字符串
            if (NpyString_pack(oallocator, ops, buf, newsize) < 0) {
                // 内存错误处理:打包输出字符串失败
                npy_gil_error(PyExc_MemoryError,
                          "Failed to pack output string in add");
                goto fail;
            }

            // 释放内存
            PyMem_RawFree(buf);
        }

    next_step:
        // 更新输入和输出指针位置
        in1 += in1_stride;
        in2 += in2_stride;
        out += out_stride;
    }
    // 释放所有分配器
    NpyString_release_allocators(3, allocators);
    // 返回成功状态
    return 0;
// 根据输入的上下文和数据执行字符串比较操作的循环
static int
string_comparison_strided_loop(PyArrayMethod_Context *context, char *const data[],
                            npy_intp const dimensions[],
                            npy_intp const strides[],
                            NpyAuxData *NPY_UNUSED(auxdata))
{
    // 获取调用该函数的通用函数对象的名称
    const char *ufunc_name = ((PyUFuncObject *)context->caller)->name;
    // 从静态数据中提取等于操作的结果标志
    npy_bool res_for_eq = ((npy_bool *)context->method->static_data)[0];
    // 从静态数据中提取小于操作的结果标志
    npy_bool res_for_lt = ((npy_bool *)context->method->static_data)[1];

    // 获取第一个输入参数的字符串数据类型描述符
    PyArray_StringDTypeObject *in1_descr =
            ((PyArray_StringDTypeObject *)context->descriptors[0]);
    // 获取第二个输入参数的字符串数据类型描述符
    PyArray_StringDTypeObject *in2_descr =
            ((PyArray_StringDTypeObject *)context->descriptors[1]);

    // 获取当前处理的维度大小
    npy_intp N = dimensions[0];
    // 获取第一个输入参数的起始地址
    char *in1 = data[0];
    // 获取第二个输入参数的起始地址
    char *in2 = data[1];
    // 获取输出参数的起始地址
    char *out = data[2];
    // 获取第一个输入参数的步长
    npy_intp in1_stride = strides[0];
    // 获取第二个输入参数的步长
    npy_intp in2_stride = strides[1];
    // 获取输出参数的步长
    npy_intp out_stride = strides[2];

    // 创建用于存储字符串分配器的数组
    npy_string_allocator *allocators[3] = {};
    // 获取字符串分配器,用于输入和输出参数的内存分配
    NpyString_acquire_allocators(3, context->descriptors, allocators);
    // 获取第一个输入参数的字符串分配器
    npy_string_allocator *in1_allocator = allocators[0];
    // 获取第二个输入参数的字符串分配器
    npy_string_allocator *in2_allocator = allocators[1];
    // 获取输出参数的字符串分配器
    npy_string_allocator *out_allocator = allocators[2];

    // 循环处理每个元素
    while (N--) {
        // 将第一个输入参数转换为静态字符串
        const npy_packed_static_string *sin1 = (npy_packed_static_string *)in1;
        // 将第二个输入参数转换为静态字符串
        const npy_packed_static_string *sin2 = (npy_packed_static_string *)in2;
        // 将输出参数转换为静态字符串
        npy_packed_static_string *sout = (npy_packed_static_string *)out;
        
        // 执行字符串的比较操作
        int cmp = _compare(in1, in2, in1_descr, in2_descr);
        
        // 如果字符串相等且输出等于输入之一,则跳到下一步
        if (cmp == 0 && (in1 == out || in2 == out)) {
            goto next_step;
        }
        
        // 根据比较结果和操作标志执行复制操作或避免释放后使用
        if ((cmp < 0) ^ res_for_lt) {
            // 如果输入1不等于输出,则执行复制操作
            if (in1 != out) {
                if (free_and_copy(in1_allocator, out_allocator, sin1, sout,
                                  ufunc_name) == -1) {
                    goto fail;
                }
            }
        }
        else {
            // 如果输入2不等于输出,则执行复制操作
            if (in2 != out) {
                if (free_and_copy(in2_allocator, out_allocator, sin2, sout,
                                  ufunc_name) == -1) {
                    goto fail;
                }
            }
        }

      next_step:
        // 更新输入和输出的指针位置
        in1 += in1_stride;
        in2 += in2_stride;
        out += out_stride;
    }

    // 释放字符串分配器
    NpyString_release_allocators(3, allocators);
    // 返回成功完成操作的标志
    return 0;

fail:
    // 在操作失败时释放字符串分配器
    NpyString_release_allocators(3, allocators);
    // 返回操作失败的标志
    return -1;
}
    // 从上下文中获取第三个静态数据的布尔值作为大于结果的标志
    npy_bool res_for_gt = ((npy_bool *)context->method->static_data)[2];
    // 计算不等于结果的布尔值
    npy_bool res_for_ne = !res_for_eq;
    // 检查是否等于或不等于的结果是相同的
    npy_bool eq_or_ne = res_for_lt == res_for_gt;
    // 从上下文中获取第一个描述符并转换为字符串数据类型对象
    PyArray_StringDTypeObject *descr1 = (PyArray_StringDTypeObject *)context->descriptors[0];
    // 检查描述符中是否有 NULL 值
    int has_null = descr1->na_object != NULL;
    // 检查描述符中是否有 NaN 或 NA 值
    int has_nan_na = descr1->has_nan_na;
    // 检查描述符中是否有字符串 NA 值
    int has_string_na = descr1->has_string_na;
    // 获取默认字符串并指向描述符的默认字符串
    const npy_static_string *default_string = &descr1->default_string;
    // 获取第一个维度的大小
    npy_intp N = dimensions[0];
    // 获取输入数据数组的第一个指针
    char *in1 = data[0];
    // 获取输入数据数组的第二个指针
    char *in2 = data[1];
    // 获取输出数据数组的指针,并转换为布尔类型指针
    npy_bool *out = (npy_bool *)data[2];
    // 获取输入数据数组的第一个步长
    npy_intp in1_stride = strides[0];
    // 获取输入数据数组的第二个步长
    npy_intp in2_stride = strides[1];
    // 获取输出数据数组的步长
    npy_intp out_stride = strides[2];

    // 分配两个字符串分配器的数组并初始化为 NULL
    npy_string_allocator *allocators[2] = {};
    // 调用函数以获取字符串分配器
    NpyString_acquire_allocators(2, context->descriptors, allocators);
    // 获取第一个字符串分配器
    npy_string_allocator *s1allocator = allocators[0];
    // 获取第二个字符串分配器
    npy_string_allocator *s2allocator = allocators[1];

    // 循环处理每个元素
    while (N--) {
        int cmp;
        // 载入两个输入字符串,宏定义的函数
        LOAD_TWO_INPUT_STRINGS(ufunc_name);
        // 检查是否有 NULL 或 NaN NA 值
        if (NPY_UNLIKELY(s1_isnull || s2_isnull)) {
            // 如果有 NaN NA 值
            if (has_nan_na) {
                // s1 或 s2 是 NA
                *out = NPY_FALSE;
                // 跳转到下一步骤
                goto next_step;
            }
            // 如果有 NULL 值但没有字符串 NA 值
            else if (has_null && !has_string_na) {
                // 如果是等于或不等于操作
                if (eq_or_ne) {
                    // 如果两个都是 NULL
                    if (s1_isnull && s2_isnull) {
                        *out = res_for_eq;
                    }
                    else {
                        *out = res_for_ne;
                    }
                }
                else {
                    // 抛出异常,不支持在非 NaN 类型或字符串中的空值
                    npy_gil_error(PyExc_ValueError,
                                  "'%s' not supported for null values that are not "
                                  "nan-like or strings.", ufunc_name);
                    // 跳转到失败处理
                    goto fail;
                }
            }
            // 否则,处理默认字符串
            else {
                if (s1_isnull) {
                    s1 = *default_string;
                }
                if (s2_isnull) {
                    s2 = *default_string;
                }
            }
        }
        // 比较两个字符串
        cmp = NpyString_cmp(&s1, &s2);
        // 根据比较结果设置输出值
        if (cmp == 0) {
            *out = res_for_eq;
        }
        else if (cmp < 0) {
            *out = res_for_lt;
        }
        else {
            *out = res_for_gt;
        }

    next_step:
        // 更新输入和输出指针
        in1 += in1_stride;
        in2 += in2_stride;
        out += out_stride;
    }

    // 释放字符串分配器
    NpyString_release_allocators(2, allocators);

    // 返回成功状态
    return 0;
fail:
    # 释放两个分配器的资源
    NpyString_release_allocators(2, allocators);

    # 返回错误状态码
    return -1;
}

static NPY_CASTING
string_comparison_resolve_descriptors(
        struct PyArrayMethodObject_tag *NPY_UNUSED(method),
        PyArray_DTypeMeta *const NPY_UNUSED(dtypes[]),
        PyArray_Descr *const given_descrs[],
        PyArray_Descr *loop_descrs[], npy_intp *NPY_UNUSED(view_offset))
{
    # 将给定的描述符转换为字符串数据类型对象
    PyArray_StringDTypeObject *descr1 = (PyArray_StringDTypeObject *)given_descrs[0];
    PyArray_StringDTypeObject *descr2 = (PyArray_StringDTypeObject *)given_descrs[1];

    # 检查是否两个字符串数据类型对象的特性兼容,如果不兼容则返回错误状态
    if (stringdtype_compatible_na(descr1->na_object, descr2->na_object, NULL) == -1) {
        return (NPY_CASTING)-1;
    }

    # 增加给定描述符的引用计数,并将其赋值给循环描述符数组
    Py_INCREF(given_descrs[0]);
    loop_descrs[0] = given_descrs[0];
    Py_INCREF(given_descrs[1]);
    loop_descrs[1] = given_descrs[1];
    # 将循环描述符数组的第三个位置设置为布尔类型的描述符,操作不可能失败
    loop_descrs[2] = PyArray_DescrFromType(NPY_BOOL);

    # 返回无需转换的状态
    return NPY_NO_CASTING;
}

static int
string_isnan_strided_loop(PyArrayMethod_Context *context, char *const data[],
                          npy_intp const dimensions[],
                          npy_intp const strides[],
                          NpyAuxData *NPY_UNUSED(auxdata))
{
    # 获取字符串数据类型对象的描述符并检查是否包含 NaN 或 NA
    PyArray_StringDTypeObject *descr = (PyArray_StringDTypeObject *)context->descriptors[0];
    int has_nan_na = descr->has_nan_na;

    # 获取第一维度的大小
    npy_intp N = dimensions[0];
    # 输入数据的起始地址
    char *in = data[0];
    # 输出数据的起始地址
    npy_bool *out = (npy_bool *)data[1];
    # 输入数据和输出数据的步幅
    npy_intp in_stride = strides[0];
    npy_intp out_stride = strides[1];

    # 遍历每个元素并检查是否为 NaN 或 NA
    while (N--) {
        const npy_packed_static_string *s = (npy_packed_static_string *)in;
        if (has_nan_na && NpyString_isnull(s)) {
            *out = NPY_TRUE;
        }
        else {
            *out = NPY_FALSE;
        }

        in += in_stride;
        out += out_stride;
    }

    # 返回成功状态
    return 0;
}

static NPY_CASTING
string_bool_output_resolve_descriptors(
        struct PyArrayMethodObject_tag *NPY_UNUSED(method),
        PyArray_DTypeMeta *const NPY_UNUSED(dtypes[]),
        PyArray_Descr *const given_descrs[],
        PyArray_Descr *loop_descrs[], npy_intp *NPY_UNUSED(view_offset))
{
    # 增加给定描述符的引用计数,并将其赋值给循环描述符数组
    Py_INCREF(given_descrs[0]);
    loop_descrs[0] = given_descrs[0];
    # 将循环描述符数组的第二个位置设置为布尔类型的描述符,操作不可能失败
    loop_descrs[1] = PyArray_DescrFromType(NPY_BOOL);

    # 返回无需转换的状态
    return NPY_NO_CASTING;
}

static NPY_CASTING
string_intp_output_resolve_descriptors(
        struct PyArrayMethodObject_tag *NPY_UNUSED(method),
        PyArray_DTypeMeta *const NPY_UNUSED(dtypes[]),
        PyArray_Descr *const given_descrs[],
        PyArray_Descr *loop_descrs[], npy_intp *NPY_UNUSED(view_offset))
{
    # 增加给定描述符的引用计数,并将其赋值给循环描述符数组
    Py_INCREF(given_descrs[0]);
    loop_descrs[0] = given_descrs[0];
    # 将循环描述符数组的第二个位置设置为整数类型的描述符,操作不可能失败
    loop_descrs[1] = PyArray_DescrFromType(NPY_INTP);

    # 返回无需转换的状态
    return NPY_NO_CASTING;
}

using utf8_buffer_method = bool (Buffer<ENCODING::UTF8>::*)();

static int
// 获取调用者的 ufunc 名称
const char *ufunc_name = ((PyUFuncObject *)context->caller)->name;
// 获取 static_data 中的 utf8_buffer_method 结构体
utf8_buffer_method is_it = *(utf8_buffer_method *)(context->method->static_data);
// 获取第一个描述符的字符串数据类型对象
PyArray_StringDTypeObject *descr = (PyArray_StringDTypeObject *)context->descriptors[0];
// 获取字符串分配器
npy_string_allocator *allocator = NpyString_acquire_allocator(descr);
// 检查描述符是否包含字符串 NA
int has_string_na = descr->has_string_na;
// 检查描述符是否包含 NaN NA
int has_nan_na = descr->has_nan_na;
// 获取默认字符串
const npy_static_string *default_string = &descr->default_string;
// 获取第一个维度的大小
npy_intp N = dimensions[0];
// 获取输入数据指针
char *in = data[0];
// 获取输出数据指针
char *out = data[1];
// 获取输入步长
npy_intp in_stride = strides[0];
// 获取输出步长
npy_intp out_stride = strides[1];

// 循环处理每个元素
while (N--) {
    // 将输入数据解析为 npy_packed_static_string 结构体
    const npy_packed_static_string *ps = (npy_packed_static_string *)in;

    // 初始化一个空的静态字符串 s
    npy_static_string s = {0, NULL};
    // 初始化 buffer 和 size 为 NULL
    const char *buffer = NULL;
    size_t size = 0;
    // 初始化一个 Buffer<ENCODING::UTF8> 对象 buf
    Buffer<ENCODING::UTF8> buf;

    // 载入字符串到 s 中,返回是否为 null
    int is_null = NpyString_load(allocator, ps, &s);

    // 如果载入失败,抛出内存错误并跳转到 fail 标签处
    if (is_null == -1) {
        npy_gil_error(PyExc_MemoryError, "Failed to load string in %s", ufunc_name);
        goto fail;
    }

    // 如果字符串为 null
    if (is_null) {
        // 如果描述符允许 NaN NA,则将输出设为 NPY_FALSE 并跳转到 next_step
        if (has_nan_na) {
            *out = NPY_FALSE;
            goto next_step;
        }
        // 如果不允许字符串 NA,则抛出值错误并跳转到 fail 标签处
        else if (!has_string_na) {
            npy_gil_error(PyExc_ValueError,
                          "Cannot use the %s function with a null that is "
                          "not a nan-like value", ufunc_name);
            goto fail;
        }
        // 否则使用默认字符串的数据
        buffer = default_string->buf;
        size = default_string->size;
    }
    else {
        // 否则使用载入的字符串数据
        buffer = s.buf;
        size = s.size;
    }

    // 初始化 buf 为包含 buffer 和 size 的 UTF8 编码的 Buffer 对象
    buf = Buffer<ENCODING::UTF8>((char *)buffer, size);
    // 将输出数据转换为 npy_bool 并存储 buf 执行 is_it 操作的结果
    *(npy_bool *)out = (buf.*is_it)();

next_step:
    // 更新输入和输出指针
    in += in_stride;
    out += out_stride;
}

// 释放字符串分配器
NpyString_release_allocator(allocator);

return 0;

fail:
// 失败时释放字符串分配器并返回 -1
NpyString_release_allocator(allocator);
return -1;
}



// 使用字符串长度函数的循环处理函数
static int
string_strlen_strided_loop(PyArrayMethod_Context *context, char *const data[],
                           npy_intp const dimensions[],
                           npy_intp const strides[],
                           NpyAuxData *auxdata)
{
    // 获取第一个描述符的字符串数据类型对象
    PyArray_StringDTypeObject *descr = (PyArray_StringDTypeObject *)context->descriptors[0];
    // 获取字符串分配器
    npy_string_allocator *allocator = NpyString_acquire_allocator(descr);
    // 检查描述符是否包含字符串 NA
    int has_string_na = descr->has_string_na;
    // 获取默认字符串
    const npy_static_string *default_string = &descr->default_string;

    // 获取第一个维度的大小
    npy_intp N = dimensions[0];
    // 获取输入数据指针
    char *in = data[0];
    // 获取输出数据指针
    char *out = data[1];
    // 获取输入步长
    npy_intp in_stride = strides[0];
    // 获取输出步长
    npy_intp out_stride = strides[1];
    // 循环,执行N次
    while (N--) {
        // 将输入的指针解释为np_packed_static_string类型,并赋给ps
        const npy_packed_static_string *ps = (npy_packed_static_string *)in;

        // 定义并初始化npy_static_string结构体变量s
        npy_static_string s = {0, NULL};
        
        // 初始化buffer为空指针,size为0
        const char *buffer = NULL;
        size_t size = 0;
        
        // 创建一个Buffer对象,模板参数为ENCODING::UTF8
        Buffer<ENCODING::UTF8> buf;
        
        // 调用NpyString_load函数加载字符串数据,返回值表示字符串是否为空
        int is_null = NpyString_load(allocator, ps, &s);

        // 如果加载失败,抛出内存错误,并跳转到fail标签处
        if (is_null == -1) {
            npy_gil_error(PyExc_MemoryError, "Failed to load string in str_len");
            goto fail;
        }

        // 如果字符串为空
        if (is_null) {
            // 如果未设置has_string_na标志,抛出数值错误并跳转到next_step标签处
            if (!has_string_na) {
                npy_gil_error(PyExc_ValueError,
                              "The length of a null string is undefined");
                goto next_step;
            }
            // 否则使用默认字符串的缓冲区和大小
            buffer = default_string->buf;
            size = default_string->size;
        }
        else {
            // 否则使用加载的字符串的缓冲区和大小
            buffer = s.buf;
            size = s.size;
        }
        
        // 将buffer和size传递给Buffer对象buf进行初始化
        buf = Buffer<ENCODING::UTF8>((char *)buffer, size);
        
        // 将buf的字符数赋给输出指针指向的npy_intp类型变量(假设out是npy_intp*类型)
        *(npy_intp *)out = buf.num_codepoints();

      next_step:
        // 更新输入指针,移动到下一个字符串位置
        in += in_stride;
        // 更新输出指针,移动到下一个输出位置
        out += out_stride;
    }

    // 释放分配器allocator所分配的内存资源
    NpyString_release_allocator(allocator);

    // 返回0表示成功执行
    return 0;
fail:
    # 调用 NpyString_release_allocator 函数释放分配器
    NpyString_release_allocator(allocator);
    # 返回 -1 表示失败
    return -1;
}

static int
string_findlike_promoter(PyObject *NPY_UNUSED(ufunc),
        PyArray_DTypeMeta *const op_dtypes[],
        PyArray_DTypeMeta *const signature[],
        PyArray_DTypeMeta *new_op_dtypes[])
{
    # 设置新操作的数据类型为字符串类型
    new_op_dtypes[0] = NPY_DT_NewRef(&PyArray_StringDType);
    new_op_dtypes[1] = NPY_DT_NewRef(&PyArray_StringDType);
    # 设置新操作的数据类型为 int64 类型
    new_op_dtypes[2] = NPY_DT_NewRef(&PyArray_Int64DType);
    new_op_dtypes[3] = NPY_DT_NewRef(&PyArray_Int64DType);
    # 设置新操作的数据类型为默认整数类型
    new_op_dtypes[4] = PyArray_DTypeFromTypeNum(NPY_DEFAULT_INT);
    # 返回 0 表示成功
    return 0;
}

static NPY_CASTING
string_findlike_resolve_descriptors(
        struct PyArrayMethodObject_tag *NPY_UNUSED(method),
        PyArray_DTypeMeta *const NPY_UNUSED(dtypes[]),
        PyArray_Descr *const given_descrs[],
        PyArray_Descr *loop_descrs[],
        npy_intp *NPY_UNUSED(view_offset))
{
    # 强制转换给定描述符为字符串类型对象
    PyArray_StringDTypeObject *descr1 = (PyArray_StringDTypeObject *)given_descrs[0];
    PyArray_StringDTypeObject *descr2 = (PyArray_StringDTypeObject *)given_descrs[1];

    # 检查给定的字符串类型是否兼容
    if (stringdtype_compatible_na(descr1->na_object, descr2->na_object, NULL) == -1) {
        return (NPY_CASTING)-1;
    }

    # 增加对给定描述符的引用计数,并将其赋给循环描述符
    Py_INCREF(given_descrs[0]);
    loop_descrs[0] = given_descrs[0];
    Py_INCREF(given_descrs[1]);
    loop_descrs[1] = given_descrs[1];
    Py_INCREF(given_descrs[2]);
    loop_descrs[2] = given_descrs[2];
    Py_INCREF(given_descrs[3]);
    loop_descrs[3] = given_descrs[3];
    # 如果第四个描述符为空,则使用默认整数类型
    if (given_descrs[4] == NULL) {
        loop_descrs[4] = PyArray_DescrFromType(NPY_DEFAULT_INT);
    }
    else {
        Py_INCREF(given_descrs[4]);
        loop_descrs[4] = given_descrs[4];
    }

    # 返回不需要类型转换的值
    return NPY_NO_CASTING;
}

static int
string_startswith_endswith_promoter(
        PyObject *NPY_UNUSED(ufunc),
        PyArray_DTypeMeta *const op_dtypes[],
        PyArray_DTypeMeta *const signature[],
        PyArray_DTypeMeta *new_op_dtypes[])
{
    # 设置新操作的数据类型为字符串类型
    new_op_dtypes[0] = NPY_DT_NewRef(&PyArray_StringDType);
    new_op_dtypes[1] = NPY_DT_NewRef(&PyArray_StringDType);
    # 设置新操作的数据类型为 int64 类型
    new_op_dtypes[2] = NPY_DT_NewRef(&PyArray_Int64DType);
    new_op_dtypes[3] = NPY_DT_NewRef(&PyArray_Int64DType);
    # 设置新操作的数据类型为布尔类型
    new_op_dtypes[4] = PyArray_DTypeFromTypeNum(NPY_BOOL);
    # 返回 0 表示成功
    return 0;
}

static NPY_CASTING
string_startswith_endswith_resolve_descriptors(
        struct PyArrayMethodObject_tag *NPY_UNUSED(method),
        PyArray_DTypeMeta *const NPY_UNUSED(dtypes[]),
        PyArray_Descr *const given_descrs[],
        PyArray_Descr *loop_descrs[],
        npy_intp *NPY_UNUSED(view_offset))
{
    # 强制转换给定描述符为字符串类型对象
    PyArray_StringDTypeObject *descr1 = (PyArray_StringDTypeObject *)given_descrs[0];
    PyArray_StringDTypeObject *descr2 = (PyArray_StringDTypeObject *)given_descrs[1];

    # 检查给定的字符串类型是否兼容
    if (stringdtype_compatible_na(descr1->na_object, descr2->na_object, NULL) == -1) {
        return (NPY_CASTING)-1;
    }

    # 增加对给定描述符的引用计数,并将其赋给循环描述符
    Py_INCREF(given_descrs[0]);
    loop_descrs[0] = given_descrs[0];
    Py_INCREF(given_descrs[1]);
    loop_descrs[1] = given_descrs[1];
    # 使用默认整数类型描述符
    # 增加给定描述符数组索引为 2 的引用计数
    Py_INCREF(given_descrs[2]);
    # 将给定描述符数组索引为 2 的元素赋值给循环描述符数组的索引为 2 的位置
    loop_descrs[2] = given_descrs[2];
    # 增加给定描述符数组索引为 3 的引用计数
    Py_INCREF(given_descrs[3]);
    # 将给定描述符数组索引为 3 的元素赋值给循环描述符数组的索引为 3 的位置
    loop_descrs[3] = given_descrs[3];
    # 如果给定描述符数组索引为 4 的元素为空指针
    if (given_descrs[4] == NULL) {
        # 将循环描述符数组的索引为 4 的位置设置为布尔类型的数组描述符
        loop_descrs[4] = PyArray_DescrFromType(NPY_BOOL);
    }
    else {
        # 增加给定描述符数组索引为 4 的引用计数
        Py_INCREF(given_descrs[4]);
        # 将给定描述符数组索引为 4 的元素赋值给循环描述符数组的索引为 4 的位置
        loop_descrs[4] = given_descrs[4];
    }
    
    # 返回值 NPY_NO_CASTING,表示不进行任何类型转换
    return NPY_NO_CASTING;
static int
string_findlike_strided_loop(PyArrayMethod_Context *context,
                         char *const data[],
                         npy_intp const dimensions[],
                         npy_intp const strides[],
                         NpyAuxData *auxdata)
{
    // 获取调用该函数的 ufunc 的名字
    const char *ufunc_name = ((PyUFuncObject *)context->caller)->name;
    
    // 从静态数据中获取 find_like_function 函数指针
    find_like_function *function = *(find_like_function *)(context->method->static_data);
    
    // 获取第一个输入的字符串描述符
    PyArray_StringDTypeObject *descr1 = (PyArray_StringDTypeObject *)context->descriptors[0];

    // 检查第一个输入是否包含空值
    int has_null = descr1->na_object != NULL;
    // 检查第一个输入是否包含字符串 NA
    int has_string_na = descr1->has_string_na;
    // 获取默认字符串
    const npy_static_string *default_string = &descr1->default_string;

    // 分配字符串的内存分配器
    npy_string_allocator *allocators[2] = {};
    NpyString_acquire_allocators(2, context->descriptors, allocators);
    // 获取第一个和第二个输入的字符串内存分配器
    npy_string_allocator *s1allocator = allocators[0];
    npy_string_allocator *s2allocator = allocators[1];

    // 获取输入数据的指针
    char *in1 = data[0];  // 输入字符串 1 的指针
    char *in2 = data[1];  // 输入字符串 2 的指针
    char *in3 = data[2];  // 输入起始位置的指针
    char *in4 = data[3];  // 输入结束位置的指针
    char *out = data[4];  // 输出结果的指针

    // 获取数据维度的大小
    npy_intp N = dimensions[0];

    // 迭代处理每一个数据点
    while (N--) {
        // 加载两个输入字符串
        LOAD_TWO_INPUT_STRINGS(ufunc_name);
        
        // 如果输入字符串中有空值
        if (NPY_UNLIKELY(s1_isnull || s2_isnull)) {
            // 如果支持空值且不支持字符串 NA
            if (has_null && !has_string_na) {
                // 报告错误并跳转到失败标签
                npy_gil_error(PyExc_ValueError,
                              "'%s' not supported for null values that are not "
                              "strings.", ufunc_name);
                goto fail;
            }
            else {
                // 如果输入字符串 1 是空值,使用默认字符串
                if (s1_isnull) {
                    s1 = *default_string;
                }
                // 如果输入字符串 2 是空值,使用默认字符串
                if (s2_isnull) {
                    s2 = *default_string;
                }
            }
        }

        // 获取起始和结束位置
        npy_int64 start = *(npy_int64 *)in3;
        npy_int64 end = *(npy_int64 *)in4;

        // 将输入字符串转换为 Buffer 对象
        Buffer<ENCODING::UTF8> buf1((char *)s1.buf, s1.size);
        Buffer<ENCODING::UTF8> buf2((char *)s2.buf, s2.size);

        // 调用 find_like_function 函数计算结果
        npy_intp pos = function(buf1, buf2, start, end);
        // 如果返回特定错误标志,跳转到失败标签
        if (pos == -2) {
            goto fail;
        }
        
        // 将结果写入输出数组
        *(npy_intp *)out = pos;

        // 更新输入和输出指针位置
        in1 += strides[0];
        in2 += strides[1];
        in3 += strides[2];
        in4 += strides[3];
        out += strides[4];
    }

    // 释放字符串的内存分配器
    NpyString_release_allocators(2, allocators);

    // 返回成功
    return 0;

fail:
    // 在失败时释放字符串的内存分配器并返回失败
    NpyString_release_allocators(2, allocators);
    return -1;
}
    // 获取第一个描述符,并将其转换为字符串数据类型对象
    PyArray_StringDTypeObject *descr1 = (PyArray_StringDTypeObject *)context->descriptors[0];

    // 检查是否存在空值
    int has_null = descr1->na_object != NULL;
    // 检查是否存在字符串类型的空值
    int has_string_na = descr1->has_string_na;
    // 检查是否存在NaN类型的空值
    int has_nan_na = descr1->has_nan_na;
    // 获取默认字符串指针
    const npy_static_string *default_string = &descr1->default_string;

    // 分配两个字符串分配器的空间,并获取描述符中的字符串分配器
    npy_string_allocator *allocators[2] = {};
    NpyString_acquire_allocators(2, context->descriptors, allocators);
    // 分配器1用于第一个描述符
    npy_string_allocator *s1allocator = allocators[0];
    // 分配器2用于第二个描述符
    npy_string_allocator *s2allocator = allocators[1];

    // 获取输入数据指针
    char *in1 = data[0];
    char *in2 = data[1];
    char *in3 = data[2];
    char *in4 = data[3];
    // 获取输出数据指针
    char *out = data[4];

    // 获取第一维度的大小
    npy_intp N = dimensions[0];

    // 进入主循环,逐行处理数据
    while (N--) {
        // 加载两个输入字符串
        LOAD_TWO_INPUT_STRINGS(ufunc_name);
        
        // 如果其中一个字符串为null
        if (NPY_UNLIKELY(s1_isnull || s2_isnull)) {
            // 如果支持null,并且不支持字符串类型的空值
            if (has_null && !has_string_na) {
                // 如果支持NaN类型的空值
                if (has_nan_na) {
                    // 对于此操作,null始终为假
                    *(npy_bool *)out = 0;
                    // 跳转到下一步骤
                    goto next_step;
                }
                // 否则,抛出值错误异常
                else {
                    npy_gil_error(PyExc_ValueError,
                                  "'%s' not supported for null values that "
                                  "are not nan-like or strings.", ufunc_name);
                    // 跳转到失败处理
                    goto fail;
                }
            }
            // 否则,如果第一个字符串为null,使用默认字符串
            else {
                if (s1_isnull) {
                    s1 = *default_string;
                }
                // 如果第二个字符串为null,使用默认字符串
                if (s2_isnull) {
                    s2 = *default_string;
                }
            }
        }
        {
            // 从输入数据中获取起始和结束位置
            npy_int64 start = *(npy_int64 *)in3;
            npy_int64 end = *(npy_int64 *)in4;

            // 使用UTF8编码创建缓冲区1和缓冲区2
            Buffer<ENCODING::UTF8> buf1((char *)s1.buf, s1.size);
            Buffer<ENCODING::UTF8> buf2((char *)s2.buf, s2.size);

            // 执行UTF8编码的尾部匹配操作
            npy_bool match = tailmatch<ENCODING::UTF8>(buf1, buf2, start, end,
                                                       startposition);
            // 将匹配结果存储到输出数据中
            *(npy_bool *)out = match;
        }

      next_step:

        // 更新输入和输出数据指针
        in1 += strides[0];
        in2 += strides[1];
        in3 += strides[2];
        in4 += strides[3];
        out += strides[4];
    }

    // 释放两个字符串分配器
    NpyString_release_allocators(2, allocators);

    // 返回0表示成功
    return 0;
    // 释放之前获取的字符串分配器的资源
    NpyString_release_allocators(2, allocators);

    // 返回错误码 -1
    return -1;
}

static int
all_strings_promoter(PyObject *NPY_UNUSED(ufunc),
                     PyArray_DTypeMeta *const op_dtypes[],
                     PyArray_DTypeMeta *const signature[],
                     PyArray_DTypeMeta *new_op_dtypes[])
{
    // 将所有新操作数据类型设置为对字符串数据类型的新引用
    new_op_dtypes[0] = NPY_DT_NewRef(&PyArray_StringDType);
    new_op_dtypes[1] = NPY_DT_NewRef(&PyArray_StringDType);
    new_op_dtypes[2] = NPY_DT_NewRef(&PyArray_StringDType);
    // 返回成功码 0
    return 0;
}

NPY_NO_EXPORT int
string_lrstrip_chars_strided_loop(
        PyArrayMethod_Context *context, char *const data[],
        npy_intp const dimensions[],
        npy_intp const strides[],
        NpyAuxData *auxdata)
{
    // 获取调用者的名称作为字符串类型
    const char *ufunc_name = ((PyUFuncObject *)context->caller)->name;
    // 获取方法静态数据中的剥离类型
    STRIPTYPE striptype = *(STRIPTYPE *)context->method->static_data;
    // 获取第一个描述符作为字符串数据类型对象
    PyArray_StringDTypeObject *s1descr = (PyArray_StringDTypeObject *)context->descriptors[0];
    // 检查第一个描述符是否有 NULL 对象
    int has_null = s1descr->na_object != NULL;
    // 检查第一个描述符是否包含字符串 NA 值
    int has_string_na = s1descr->has_string_na;
    // 检查第一个描述符是否包含 NaN NA 值
    int has_nan_na = s1descr->has_nan_na;

    // 获取默认字符串的静态指针
    const npy_static_string *default_string = &s1descr->default_string;
    // 获取数据的第一维度大小
    npy_intp N = dimensions[0];
    // 获取输入数据数组的指针
    char *in1 = data[0];
    char *in2 = data[1];
    char *out = data[2];

    // 定义字符串分配器数组,并获取三个描述符的字符串分配器
    npy_string_allocator *allocators[3] = {};
    NpyString_acquire_allocators(3, context->descriptors, allocators);
    npy_string_allocator *s1allocator = allocators[0];
    npy_string_allocator *s2allocator = allocators[1];
    npy_string_allocator *oallocator = allocators[2];
    while (N--) {
        LOAD_TWO_INPUT_STRINGS(ufunc_name);
        // 从输入数组中加载两个字符串
        npy_packed_static_string *ops = (npy_packed_static_string *)out;
        // 将输出指针类型转换为静态字符串结构体指针

        if (NPY_UNLIKELY(s1_isnull || s2_isnull)) {
            // 如果 s1 或 s2 是空值
            if (has_string_na || !has_null) {
                // 如果存在字符串类型的空值或者没有空值
                if (s1_isnull) {
                    s1 = *default_string;
                    // 如果 s1 是空值,则使用默认字符串
                }
                if (s2_isnull) {
                    s2 = *default_string;
                    // 如果 s2 是空值,则使用默认字符串
                }
            }
            else if (has_nan_na) {
                // 如果存在 NaN 类型的空值
                if (s2_isnull) {
                    npy_gil_error(PyExc_ValueError,
                                  "Cannot use a null string that is not a "
                                  "string as the %s delimiter", ufunc_name);
                    // 报错,不能使用非字符串类型的空字符串作为分隔符
                }
                if (s1_isnull) {
                    if (NpyString_pack_null(oallocator, ops) < 0) {
                        npy_gil_error(PyExc_MemoryError,
                                      "Failed to deallocate string in %s",
                                      ufunc_name);
                        // 打印内存错误信息
                        goto fail;
                    }
                    goto next_step;
                    // 跳转到下一步
                }
            }
            else {
                npy_gil_error(PyExc_ValueError,
                              "Can only strip null values that are strings "
                              "or NaN-like values");
                // 报错,只能去除字符串类型或类似 NaN 的空值
                goto fail;
                // 跳转到错误处理
            }
        }
        {
            char *new_buf = (char *)PyMem_RawCalloc(s1.size, 1);
            // 分配新的内存缓冲区
            Buffer<ENCODING::UTF8> buf1((char *)s1.buf, s1.size);
            Buffer<ENCODING::UTF8> buf2((char *)s2.buf, s2.size);
            Buffer<ENCODING::UTF8> outbuf(new_buf, s1.size);
            // 创建 UTF-8 编码的缓冲区对象

            size_t new_buf_size = string_lrstrip_chars
                    (buf1, buf2, outbuf, striptype);
            // 调用字符串去除函数,计算新缓冲区的大小

            if (NpyString_pack(oallocator, ops, new_buf, new_buf_size) < 0) {
                npy_gil_error(PyExc_MemoryError, "Failed to pack string in %s",
                              ufunc_name);
                // 打印内存错误信息
                PyMem_RawFree(new_buf);
                // 释放内存
                goto fail;
                // 跳转到错误处理
            }

            PyMem_RawFree(new_buf);
            // 释放内存
        }
      next_step:
        // 下一步标签

        in1 += strides[0];
        in2 += strides[1];
        out += strides[2];
        // 更新输入输出指针的位置
    }

    NpyString_release_allocators(3, allocators);
    // 释放分配器
    return 0;
fail:
    // 调用NpyString_release_allocators函数释放分配的字符串分配器
    NpyString_release_allocators(3, allocators);
    // 返回-1,表示函数执行失败
    return -1;
}



static NPY_CASTING
strip_whitespace_resolve_descriptors(
        struct PyArrayMethodObject_tag *NPY_UNUSED(method),
        PyArray_DTypeMeta *const NPY_UNUSED(dtypes[]),
        PyArray_Descr *const given_descrs[],
        PyArray_Descr *loop_descrs[],
        npy_intp *NPY_UNUSED(view_offset))
{
    // 增加给定描述符的引用计数
    Py_INCREF(given_descrs[0]);
    // 将给定的描述符赋值给循环描述符数组的第一个元素
    loop_descrs[0] = given_descrs[0];

    // 初始化输出描述符指针为NULL
    PyArray_Descr *out_descr = NULL;

    // 如果第二个给定描述符为NULL
    if (given_descrs[1] == NULL) {
        // 创建一个新的字符串类型实例作为输出描述符
        out_descr = (PyArray_Descr *)new_stringdtype_instance(
                ((PyArray_StringDTypeObject *)given_descrs[0])->na_object,
                ((PyArray_StringDTypeObject *)given_descrs[0])->coerce);

        // 如果无法创建输出描述符实例,返回-1表示失败
        if (out_descr == NULL) {
            return (NPY_CASTING)-1;
        }
    }
    else {
        // 增加第二个给定描述符的引用计数
        Py_INCREF(given_descrs[1]);
        // 将第二个给定描述符赋值给输出描述符
        out_descr = given_descrs[1];
    }

    // 将输出描述符赋值给循环描述符数组的第二个元素
    loop_descrs[1] = out_descr;

    // 返回NPY_NO_CASTING,表示无需类型转换
    return NPY_NO_CASTING;
}



static int
string_lrstrip_whitespace_strided_loop(
        PyArrayMethod_Context *context,
        char *const data[], npy_intp const dimensions[],
        npy_intp const strides[], NpyAuxData *NPY_UNUSED(auxdata))
{
    // 获取调用者的ufunc名称
    const char *ufunc_name = ((PyUFuncObject *)context->caller)->name;
    // 获取strip类型,这是一个枚举值
    STRIPTYPE striptype = *(STRIPTYPE *)context->method->static_data;
    // 获取第一个描述符作为字符串类型对象
    PyArray_StringDTypeObject *descr = (PyArray_StringDTypeObject *)context->descriptors[0];
    // 检查是否存在na_object
    int has_null = descr->na_object != NULL;
    // 检查是否具有string_na标志
    int has_string_na = descr->has_string_na;
    // 检查是否具有nan_na标志
    int has_nan_na = descr->has_nan_na;
    // 获取默认字符串的指针
    const npy_static_string *default_string = &descr->default_string;

    // 分配两个字符串分配器的数组
    npy_string_allocator *allocators[2] = {};
    // 获取两个描述符的字符串分配器
    NpyString_acquire_allocators(2, context->descriptors, allocators);
    // 第一个分配器用于输入数据,第二个分配器用于输出数据
    npy_string_allocator *allocator = allocators[0];
    npy_string_allocator *oallocator = allocators[1];

    // 输入数据的指针
    char *in = data[0];
    // 输出数据的指针
    char *out = data[1];

    // 数据的维度大小
    npy_intp N = dimensions[0];

    // 这里是函数的主要逻辑,后续的代码应该继续注释,但超出了最大字符数限制,因此结束。
    // 循环,N 逐步减少直到为 0
    while (N--) {
        // 将输入的指针视为 npy_packed_static_string 类型的静态字符串指针
        const npy_packed_static_string *ps = (npy_packed_static_string *)in;
        // 定义并初始化一个静态字符串 s
        npy_static_string s = {0, NULL};
        // 调用 NpyString_load 函数加载字符串 s,并检查是否为空
        int s_isnull = NpyString_load(allocator, ps, &s);

        // 如果加载过程中出现错误,抛出内存错误并跳转到失败处理标签
        if (s_isnull == -1) {
            npy_gil_error(PyExc_MemoryError, "Failed to load string in %s", ufunc_name);
            goto fail;
        }

        // 将输出指针视为 npy_packed_static_string 类型的静态字符串指针
        npy_packed_static_string *ops = (npy_packed_static_string *)out;

        // 如果 s 为空
        if (NPY_UNLIKELY(s_isnull)) {
            // 如果允许字符串为空或者不存在空值,使用默认字符串替换 s
            if (has_string_na || !has_null) {
                s = *default_string;
            }
            // 如果存在 NaN 类型的空值
            else if (has_nan_na) {
                // 使用空值填充 ops,并检查是否出错
                if (NpyString_pack_null(oallocator, ops) < 0) {
                    npy_gil_error(PyExc_MemoryError, "Failed to deallocate string in %s", ufunc_name);
                    goto fail;
                }
                // 跳转到下一步处理标签
                goto next_step;
            }
            // 其他情况,抛出数值错误,说明只能去除字符串类型的空值或 NaN 类型的空值
            else {
                npy_gil_error(PyExc_ValueError, "Can only strip null values that are strings or NaN-like values");
                goto fail;
            }
        }

        {
            // 分配新的缓冲区,用于处理字符串操作
            char *new_buf = (char *)PyMem_RawCalloc(s.size, 1);
            // 创建输入和输出的 UTF-8 编码缓冲区
            Buffer<ENCODING::UTF8> buf((char *)s.buf, s.size);
            Buffer<ENCODING::UTF8> outbuf(new_buf, s.size);
            // 对字符串进行去除空白字符处理,得到新的缓冲区大小
            size_t new_buf_size = string_lrstrip_whitespace(buf, outbuf, striptype);

            // 将处理后的字符串打包到 ops,检查是否出错
            if (NpyString_pack(oallocator, ops, new_buf, new_buf_size) < 0) {
                npy_gil_error(PyExc_MemoryError, "Failed to pack string in %s", ufunc_name);
                goto fail;
            }

            // 释放新分配的缓冲区
            PyMem_RawFree(new_buf);
        }

      next_step:
        // 更新输入和输出指针的位置
        in += strides[0];
        out += strides[1];
    }

    // 释放所有的分配器资源
    NpyString_release_allocators(2, allocators);

    // 返回成功状态码
    return 0;

  fail:
    // 释放所有的分配器资源
    NpyString_release_allocators(2, allocators);

    // 返回失败状态码
    return -1;
static int
string_replace_promoter(PyObject *NPY_UNUSED(ufunc),
                        PyArray_DTypeMeta *const op_dtypes[],
                        PyArray_DTypeMeta *const signature[],
                        PyArray_DTypeMeta *new_op_dtypes[])
{
    // 设置新的操作数据类型为字符串类型的引用
    new_op_dtypes[0] = NPY_DT_NewRef(&PyArray_StringDType);
    new_op_dtypes[1] = NPY_DT_NewRef(&PyArray_StringDType);
    new_op_dtypes[2] = NPY_DT_NewRef(&PyArray_StringDType);
    new_op_dtypes[3] = NPY_DT_NewRef(&PyArray_Int64DType);
    new_op_dtypes[4] = NPY_DT_NewRef(&PyArray_StringDType);
    // 返回操作成功
    return 0;
}

static NPY_CASTING
replace_resolve_descriptors(struct PyArrayMethodObject_tag *NPY_UNUSED(method),
                            PyArray_DTypeMeta *const NPY_UNUSED(dtypes[]),
                            PyArray_Descr *const given_descrs[],
                            PyArray_Descr *loop_descrs[],
                            npy_intp *NPY_UNUSED(view_offset))
{
    // 获取给定描述符的字符串类型对象
    PyArray_StringDTypeObject *descr1 = (PyArray_StringDTypeObject *)given_descrs[0];
    PyArray_StringDTypeObject *descr2 = (PyArray_StringDTypeObject *)given_descrs[1];
    PyArray_StringDTypeObject *descr3 = (PyArray_StringDTypeObject *)given_descrs[2];
    // 判断是否需要强制转换
    int out_coerce = descr1->coerce && descr2->coerce && descr3->coerce;
    PyObject *out_na_object = NULL;

    // 检查字符串类型的可兼容性
    if (stringdtype_compatible_na(
                descr1->na_object, descr2->na_object, &out_na_object) == -1) {
        return (NPY_CASTING)-1;
    }

    // 继续检查另一组字符串类型的兼容性
    if (stringdtype_compatible_na(
                out_na_object, descr3->na_object, &out_na_object) == -1) {
        return (NPY_CASTING)-1;
    }

    // 增加给定描述符的引用计数,并将其复制到循环描述符中
    Py_INCREF(given_descrs[0]);
    loop_descrs[0] = given_descrs[0];
    Py_INCREF(given_descrs[1]);
    loop_descrs[1] = given_descrs[1];
    Py_INCREF(given_descrs[2]);
    loop_descrs[2] = given_descrs[2];
    Py_INCREF(given_descrs[3]);
    loop_descrs[3] = given_descrs[3];

    PyArray_Descr *out_descr = NULL;

    // 如果第四个描述符为空,则创建新的字符串类型实例
    if (given_descrs[4] == NULL) {
        out_descr = (PyArray_Descr *)new_stringdtype_instance(
                out_na_object, out_coerce);

        // 如果创建失败,则返回错误状态
        if (out_descr == NULL) {
            return (NPY_CASTING)-1;
        }
    }
    else {
        // 否则增加给定描述符的引用计数,并直接使用
        Py_INCREF(given_descrs[4]);
        out_descr = given_descrs[4];
    }

    // 将输出描述符放入循环描述符中
    loop_descrs[4] = out_descr;

    // 返回不需要强制转换的状态
    return NPY_NO_CASTING;
}


static int
string_replace_strided_loop(
        PyArrayMethod_Context *context,
        char *const data[], npy_intp const dimensions[],
        npy_intp const strides[], NpyAuxData *NPY_UNUSED(auxdata))
{
    // 获取输入和输出数据的指针
    char *in1 = data[0];
    char *in2 = data[1];
    char *in3 = data[2];
    char *in4 = data[3];
    char *out = data[4];

    // 获取数据的维度大小
    npy_intp N = dimensions[0];

    // 获取描述符对象并检查其属性
    PyArray_StringDTypeObject *descr0 =
            (PyArray_StringDTypeObject *)context->descriptors[0];
    int has_null = descr0->na_object != NULL;
    int has_string_na = descr0->has_string_na;
    int has_nan_na = descr0->has_nan_na;
    const npy_static_string *default_string = &descr0->default_string;


这些注释详细说明了每行代码的功能和作用,遵循了提供的示例和要求。
    # 创建一个包含5个元素的指针数组,初始都为空指针
    npy_string_allocator *allocators[5] = {};

    # 调用函数,获取字符串分配器的数组,存储在allocators数组中
    NpyString_acquire_allocators(5, context->descriptors, allocators);

    # 获取特定位置的字符串分配器
    npy_string_allocator *i1allocator = allocators[0];
    npy_string_allocator *i2allocator = allocators[1];
    npy_string_allocator *i3allocator = allocators[2];

    # allocators[3] 是空指针
    npy_string_allocator *oallocator = allocators[4];

    # 释放字符串分配器的数组
    NpyString_release_allocators(5, allocators);

    # 返回成功状态
    return 0;

  fail:
    # 如果出现错误,释放字符串分配器的数组
    NpyString_release_allocators(5, allocators);

    # 返回错误状态
    return -1;
}


static NPY_CASTING expandtabs_resolve_descriptors(
        struct PyArrayMethodObject_tag *NPY_UNUSED(method),
        PyArray_DTypeMeta *const NPY_UNUSED(dtypes[]),
        PyArray_Descr *const given_descrs[],
        PyArray_Descr *loop_descrs[],
        npy_intp *NPY_UNUSED(view_offset))
{
    // 增加给定描述符的引用计数,并将其赋给循环描述符数组中的第一个位置
    Py_INCREF(given_descrs[0]);
    loop_descrs[0] = given_descrs[0];
    // 增加给定描述符的引用计数,并将其赋给循环描述符数组中的第二个位置
    Py_INCREF(given_descrs[1]);
    loop_descrs[1] = given_descrs[1];
    // 初始化输出描述符为 NULL
    PyArray_Descr *out_descr = NULL;
    // 将给定描述符数组中的第一个描述符转换为字符串类型描述符对象
    PyArray_StringDTypeObject *idescr =
            (PyArray_StringDTypeObject *)given_descrs[0];

    // 如果第三个给定描述符为空
    if (given_descrs[2] == NULL) {
        // 创建新的字符串类型实例作为输出描述符
        out_descr = (PyArray_Descr *)new_stringdtype_instance(
                idescr->na_object, idescr->coerce);
        // 如果创建失败,则返回错误标志
        if (out_descr == NULL) {
            return (NPY_CASTING)-1;
        }
    }
    else {
        // 如果第三个给定描述符不为空,则增加其引用计数并直接赋给输出描述符
        Py_INCREF(given_descrs[2]);
        out_descr = given_descrs[2];
    }
    // 将输出描述符赋给循环描述符数组中的第三个位置
    loop_descrs[2] = out_descr;
    // 返回无需转换的标志
    return NPY_NO_CASTING;
}


static int
string_expandtabs_strided_loop(PyArrayMethod_Context *context,
                               char *const data[],
                               npy_intp const dimensions[],
                               npy_intp const strides[],
                               NpyAuxData *NPY_UNUSED(auxdata))
{
    // 获取输入字符串数组的指针
    char *in1 = data[0];
    char *in2 = data[1];
    // 获取输出字符串数组的指针
    char *out = data[2];

    // 获取数组的长度
    npy_intp N = dimensions[0];

    // 将描述符数组中的第一个描述符转换为字符串类型描述符对象
    PyArray_StringDTypeObject *descr0 =
            (PyArray_StringDTypeObject *)context->descriptors[0];
    // 检查第一个描述符对象是否包含字符串 NA
    int has_string_na = descr0->has_string_na;
    // 获取默认字符串
    const npy_static_string *default_string = &descr0->default_string;


    // 分配字符串操作所需的分配器数组
    npy_string_allocator *allocators[3] = {};
    NpyString_acquire_allocators(3, context->descriptors, allocators);
    npy_string_allocator *iallocator = allocators[0];
    // allocators[1] 是 NULL,因为这里没有第二个输入
    npy_string_allocator *oallocator = allocators[2];
    // 使用 while 循环,循环执行 N 次,每次处理一个字符串
    while (N--) {
        // 将输入指针强制转换为 npy_packed_static_string 类型,赋给 ips
        const npy_packed_static_string *ips = (npy_packed_static_string *)in1;
        // 将输出指针强制转换为 npy_packed_static_string 类型,赋给 ops
        npy_packed_static_string *ops = (npy_packed_static_string *)out;
        // 创建并初始化 npy_static_string 结构体 is
        npy_static_string is = {0, NULL};
        // 从输入中读取 tabsize,赋给 tabsize
        npy_int64 tabsize = *(npy_int64 *)in2;

        // 调用 NpyString_load 函数加载字符串 is
        int isnull = NpyString_load(iallocator, ips, &is);

        // 如果加载失败,抛出内存错误异常,并跳转到 fail 标签处
        if (isnull == -1) {
            npy_gil_error(
                    PyExc_MemoryError, "Failed to load string in expandtabs");
            goto fail;
        }
        // 如果加载的字符串为空
        else if (isnull) {
            // 如果不支持字符串 NA(缺失值),抛出值错误异常,并跳转到 fail 标签处
            if (!has_string_na) {
                npy_gil_error(PyExc_ValueError,
                              "Null values are not supported arguments for "
                              "expandtabs");
                goto fail;
            }
            // 否则,使用默认字符串替代 is
            else {
                is = *default_string;
            }
        }

        // 使用 Buffer 类型的 buf 封装 is 的数据和大小
        Buffer<ENCODING::UTF8> buf((char *)is.buf, is.size);
        // 计算扩展制表符后的新字符串大小
        npy_intp new_buf_size = string_expandtabs_length(buf, tabsize);

        // 如果新字符串大小小于 0,跳转到 fail 标签处
        if (new_buf_size < 0) {
            goto fail;
        }

        // 分配 new_buf_size 大小的内存,并初始化为 0,赋给 new_buf
        char *new_buf = (char *)PyMem_RawCalloc(new_buf_size, 1);
        // 使用 Buffer 类型的 outbuf 封装 new_buf 和 new_buf_size
        Buffer<ENCODING::UTF8> outbuf(new_buf, new_buf_size);

        // 执行字符串扩展制表符处理
        string_expandtabs(buf, tabsize, outbuf);

        // 将处理后的字符串打包到 ops 中,如果失败,抛出内存错误异常,并跳转到 fail 标签处
        if (NpyString_pack(oallocator, ops, new_buf, new_buf_size) < 0) {
            npy_gil_error(
                    PyExc_MemoryError, "Failed to pack string in expandtabs");
            goto fail;
        }

        // 释放 new_buf 的内存
        PyMem_RawFree(new_buf);

        // 更新输入和输出指针位置
        in1 += strides[0];
        in2 += strides[1];
        out += strides[2];
    }

    // 释放所有分配器
    NpyString_release_allocators(3, allocators);
    // 成功执行,返回 0
    return 0;

  fail:
    // 发生失败,释放所有分配器,并返回 -1
    NpyString_release_allocators(3, allocators);
    return -1;
}

static NPY_CASTING
center_ljust_rjust_resolve_descriptors(
        struct PyArrayMethodObject_tag *NPY_UNUSED(method),
        PyArray_DTypeMeta *const dtypes[], PyArray_Descr *const given_descrs[],
        PyArray_Descr *loop_descrs[], npy_intp *NPY_UNUSED(view_offset))
{
    PyArray_StringDTypeObject *input_descr = (PyArray_StringDTypeObject *)given_descrs[0];
    // 获取输入字符串类型描述符
    PyArray_StringDTypeObject *fill_descr = (PyArray_StringDTypeObject *)given_descrs[2];
    // 获取填充字符串类型描述符
    int out_coerce = input_descr->coerce && fill_descr->coerce;
    // 检查是否需要强制转换输出
    PyObject *out_na_object = NULL;

    if (stringdtype_compatible_na(
                input_descr->na_object, fill_descr->na_object, &out_na_object) == -1) {
        // 检查输入和填充描述符的兼容性,设置输出 NA 对象
        return (NPY_CASTING)-1;
        // 若兼容性检查失败则返回错误码
    }

    Py_INCREF(given_descrs[0]);
    // 增加输入描述符的引用计数
    loop_descrs[0] = given_descrs[0];
    // 设置循环描述符数组的第一个元素为输入描述符
    Py_INCREF(given_descrs[1]);
    // 增加输入描述符的引用计数
    loop_descrs[1] = given_descrs[1];
    // 设置循环描述符数组的第二个元素为输入描述符
    Py_INCREF(given_descrs[2]);
    // 增加输入描述符的引用计数
    loop_descrs[2] = given_descrs[2];
    // 设置循环描述符数组的第三个元素为输入描述符

    PyArray_Descr *out_descr = NULL;

    if (given_descrs[3] == NULL) {
        // 若输出描述符为空
        out_descr = (PyArray_Descr *)new_stringdtype_instance(
                out_na_object, out_coerce);
        // 根据输出 NA 对象和是否需要强制转换创建新的字符串类型实例

        if (out_descr == NULL) {
            // 若创建实例失败
            return (NPY_CASTING)-1;
            // 返回错误码
        }
    }
    else {
        // 若输出描述符不为空
        Py_INCREF(given_descrs[3]);
        // 增加输出描述符的引用计数
        out_descr = given_descrs[3];
        // 设置输出描述符为给定的输出描述符
    }

    loop_descrs[3] = out_descr;
    // 设置循环描述符数组的第四个元素为输出描述符

    return NPY_NO_CASTING;
    // 返回无需转换的标志
}


static int
center_ljust_rjust_strided_loop(PyArrayMethod_Context *context,
                                char *const data[],
                                npy_intp const dimensions[],
                                npy_intp const strides[],
                                NpyAuxData *NPY_UNUSED(auxdata))
{
    PyArray_StringDTypeObject *s1descr = (PyArray_StringDTypeObject *)context->descriptors[0];
    // 获取第一个字符串描述符
    int has_null = s1descr->na_object != NULL;
    // 检查第一个描述符是否有 NA 对象
    int has_nan_na = s1descr->has_nan_na;
    // 检查第一个描述符是否有 NaN 或 NA
    int has_string_na = s1descr->has_string_na;
    // 检查第一个描述符是否有字符串 NA
    const npy_static_string *default_string = &s1descr->default_string;
    // 获取第一个描述符的默认字符串
    npy_intp N = dimensions[0];
    // 获取维度的大小
    char *in1 = data[0];
    // 获取输入数据数组的第一个元素
    char *in2 = data[1];
    // 获取输入数据数组的第二个元素
    char *in3 = data[2];
    // 获取输入数据数组的第三个元素
    char *out = data[3];
    // 获取输出数据数组的第四个元素
    npy_intp in1_stride = strides[0];
    // 获取输入数据数组的第一个元素的步长
    npy_intp in2_stride = strides[1];
    // 获取输入数据数组的第二个元素的步长
    npy_intp in3_stride = strides[2];
    // 获取输入数据数组的第三个元素的步长
    npy_intp out_stride = strides[3];
    // 获取输出数据数组的第四个元素的步长

    npy_string_allocator *allocators[4] = {};
    // 创建字符串分配器数组
    NpyString_acquire_allocators(4, context->descriptors, allocators);
    // 获取字符串分配器

    npy_string_allocator *s1allocator = allocators[0];
    // 获取第一个字符串分配器
    // allocators[1] is NULL
    npy_string_allocator *s2allocator = allocators[2];
    // 获取第三个字符串分配器
    npy_string_allocator *oallocator = allocators[3];
    // 获取第四个字符串分配器

    JUSTPOSITION pos = *(JUSTPOSITION *)(context->method->static_data);
    // 获取 JUSTPOSITION 结构体
    const char* ufunc_name = ((PyUFuncObject *)context->caller)->name;
    // 获取 UFunc 的名称

    }

    NpyString_release_allocators(4, allocators);
    // 释放字符串分配器
    return 0;

 fail:
    NpyString_release_allocators(4, allocators);
    // 释放字符串分配器
    return -1;
}

static int
# 定义字符串分割循环函数,接受一些输入参数和执行环境
zfill_strided_loop(PyArrayMethod_Context *context,
                   char *const data[], npy_intp const dimensions[],
                   npy_intp const strides[], NpyAuxData *NPY_UNUSED(auxdata))
{
    # 获取描述符数组中的字符串类型描述符
    PyArray_StringDTypeObject *idescr =
            (PyArray_StringDTypeObject *)context->descriptors[0];
    # 获取第一个维度的大小
    npy_intp N = dimensions[0];
    # 输入数组的第一个,第二个和输出数组的指针
    char *in1 = data[0];
    char *in2 = data[1];
    char *out = data[2];
    # 输入数组的步幅
    npy_intp in1_stride = strides[0];
    npy_intp in2_stride = strides[1];
    npy_intp out_stride = strides[2];

    # 字符串分配器数组,用于存储字符串分配器的指针
    npy_string_allocator *allocators[3] = {};
    # 获取字符串分配器
    NpyString_acquire_allocators(3, context->descriptors, allocators);
    npy_string_allocator *iallocator = allocators[0];
    # allocators[1] 是 NULL
    npy_string_allocator *oallocator = allocators[2];
    # 是否具有空值标志
    int has_null = idescr->na_object != NULL;
    # 是否具有NaN或NA标志
    int has_nan_na = idescr->has_nan_na;
    # 是否具有字符串NA标志
    int has_string_na = idescr->has_string_na;
    # 默认字符串
    const npy_static_string *default_string = &idescr->default_string;

    # 释放字符串分配器资源
    }

    # 在失败时释放字符串分配器资源,并返回失败状态
    NpyString_release_allocators(3, allocators);
    return 0;

fail:
    NpyString_release_allocators(3, allocators);
    return -1;
}


# 解析字符串分割函数描述符,用于字符串数据类型对象的处理
static NPY_CASTING
string_partition_resolve_descriptors(
        PyArrayMethodObject *self,
        PyArray_DTypeMeta *const NPY_UNUSED(dtypes[3]),
        PyArray_Descr *const given_descrs[3],
        PyArray_Descr *loop_descrs[3],
        npy_intp *NPY_UNUSED(view_offset))
{
    # 如果给定的描述符中包含不支持的 'out' 关键字,则引发类型错误异常
    if (given_descrs[2] || given_descrs[3] || given_descrs[4]) {
        PyErr_Format(PyExc_TypeError, "The StringDType '%s' ufunc does not "
                     "currently support the 'out' keyword", self->name);
        return (NPY_CASTING)-1;
    }

    # 获取给定的字符串类型描述符
    PyArray_StringDTypeObject *descr1 = (PyArray_StringDTypeObject *)given_descrs[0];
    PyArray_StringDTypeObject *descr2 = (PyArray_StringDTypeObject *)given_descrs[1];
    # 确定是否需要强制类型转换
    int out_coerce = descr1->coerce && descr2->coerce;
    PyObject *out_na_object = NULL;

    # 检查是否兼容NA对象
    if (stringdtype_compatible_na(
                descr1->na_object, descr2->na_object, &out_na_object) == -1) {
        return (NPY_CASTING)-1;
    }

    # 增加引用计数并复制描述符
    Py_INCREF(given_descrs[0]);
    loop_descrs[0] = given_descrs[0];
    Py_INCREF(given_descrs[1]);
    loop_descrs[1] = given_descrs[1];

    # 对于索引从2到4的循环描述符
    for (int i=2; i<5; i++) {
        # 创建新的字符串数据类型实例
        loop_descrs[i] = (PyArray_Descr *)new_stringdtype_instance(
                out_na_object, out_coerce);
        # 如果创建失败,则返回错误状态
        if (loop_descrs[i] == NULL) {
            return (NPY_CASTING)-1;
        }
    }

    # 返回无需类型转换的标志
    return NPY_NO_CASTING;
}

# 字符串分割的分段循环函数
NPY_NO_EXPORT int
string_partition_strided_loop(
        PyArrayMethod_Context *context,
        char *const data[],
        npy_intp const dimensions[],
        npy_intp const strides[],
        NpyAuxData *NPY_UNUSED(auxdata))
{
    # 获取字符串分割方法的起始位置
    STARTPOSITION startposition = *(STARTPOSITION *)(context->method->static_data);
    # 确定快速搜索方向
    int fastsearch_direction =
            startposition == STARTPOSITION::FRONT ? FAST_SEARCH : FAST_RSEARCH;

    # 获取第一个维度的大小
    npy_intp N = dimensions[0];

    # 输入数组的指针
    char *in1 = data[0];
    char *in2 = data[1];
    # 获取输入和输出数据指针,从传入的数据数组中取出特定索引处的指针
    char *out1 = data[2];
    char *out2 = data[3];
    char *out3 = data[4];

    # 获取输入和输出数据的步长(strides)
    npy_intp in1_stride = strides[0];
    npy_intp in2_stride = strides[1];
    npy_intp out1_stride = strides[2];
    npy_intp out2_stride = strides[3];
    npy_intp out3_stride = strides[4];

    # 分配字符串处理所需的内存分配器
    npy_string_allocator *allocators[5] = {};
    NpyString_acquire_allocators(5, context->descriptors, allocators);
    npy_string_allocator *in1allocator = allocators[0];
    npy_string_allocator *in2allocator = allocators[1];
    npy_string_allocator *out1allocator = allocators[2];
    npy_string_allocator *out2allocator = allocators[3];
    npy_string_allocator *out3allocator = allocators[4];

    # 获取字符串类型描述符对象,并从中获取特定信息
    PyArray_StringDTypeObject *idescr =
            (PyArray_StringDTypeObject *)context->descriptors[0];
    int has_string_na = idescr->has_string_na;
    const npy_static_string *default_string = &idescr->default_string;

    # 释放分配的内存分配器资源
    NpyString_release_allocators(5, allocators);
    # 返回成功标志
    return 0;

  fail:

    # 在失败时释放已分配的内存分配器资源
    NpyString_release_allocators(5, allocators);
    # 返回失败标志
    return -1;
}

NPY_NO_EXPORT int
string_inputs_promoter(
        PyObject *ufunc_obj, PyArray_DTypeMeta *const op_dtypes[],
        PyArray_DTypeMeta *const signature[],
        PyArray_DTypeMeta *new_op_dtypes[],
        PyArray_DTypeMeta *final_dtype,
        PyArray_DTypeMeta *result_dtype)
{
    PyUFuncObject *ufunc = (PyUFuncObject *)ufunc_obj;
    /* set all input operands to final_dtype */
    for (int i = 0; i < ufunc->nin; i++) {
        PyArray_DTypeMeta *tmp = final_dtype;
        if (signature[i]) {
            tmp = signature[i]; /* never replace a fixed one. */
        }
        Py_INCREF(tmp);
        new_op_dtypes[i] = tmp;
    }
    /* don't touch output dtypes if they are set */
    for (int i = ufunc->nin; i < ufunc->nargs; i++) {
        if (op_dtypes[i] != NULL) {
            Py_INCREF(op_dtypes[i]);
            new_op_dtypes[i] = op_dtypes[i];
        }
        else {
            Py_INCREF(result_dtype);
            new_op_dtypes[i] = result_dtype;
        }
    }

    return 0;
}

static int
string_object_bool_output_promoter(
        PyObject *ufunc, PyArray_DTypeMeta *const op_dtypes[],
        PyArray_DTypeMeta *const signature[],
        PyArray_DTypeMeta *new_op_dtypes[])
{
    return string_inputs_promoter(
            ufunc, op_dtypes, signature,
            new_op_dtypes, &PyArray_ObjectDType, &PyArray_BoolDType);
}

static int
string_unicode_bool_output_promoter(
        PyObject *ufunc, PyArray_DTypeMeta *const op_dtypes[],
        PyArray_DTypeMeta *const signature[],
        PyArray_DTypeMeta *new_op_dtypes[])
{
    return string_inputs_promoter(
            ufunc, op_dtypes, signature,
            new_op_dtypes, &PyArray_StringDType, &PyArray_BoolDType);
}

static int
is_integer_dtype(PyArray_DTypeMeta *DType)
{
    if (DType == &PyArray_PyLongDType) {
        return 1;
    }
    else if (DType == &PyArray_Int8DType) {
        return 1;
    }
    else if (DType == &PyArray_Int16DType) {
        return 1;
    }
    else if (DType == &PyArray_Int32DType) {
        return 1;
    }
    // int64 already has a loop registered for it,
    // so don't need to consider it
#if NPY_SIZEOF_BYTE == NPY_SIZEOF_SHORT
    else if (DType == &PyArray_ByteDType) {
        return 1;
    }
#endif
#if NPY_SIZEOF_SHORT == NPY_SIZEOF_INT
    else if (DType == &PyArray_ShortDType) {
        return 1;
    }
#endif
#if NPY_SIZEOF_INT == NPY_SIZEOF_LONG
    else if (DType == &PyArray_IntDType) {
        return 1;
    }
#endif
#if NPY_SIZEOF_LONGLONG == NPY_SIZEOF_LONG
    else if (DType == &PyArray_LongLongDType) {
        return 1;
    }
#endif
    else if (DType == &PyArray_UInt8DType) {
        return 1;
    }
    else if (DType == &PyArray_UInt16DType) {
        return 1;
    }
    else if (DType == &PyArray_UInt32DType) {
        return 1;
    }
    // uint64 already has a loop registered for it,
    // so don't need to consider it
#if NPY_SIZEOF_BYTE == NPY_SIZEOF_SHORT
    else if (DType == &PyArray_UByteDType) {
        return 1;
    }
#endif

    // No match found, not an integer dtype
    return 0;
}
#ifdef
#if NPY_SIZEOF_SHORT == NPY_SIZEOF_INT
    // 如果短整型和整型的字节大小相同,返回1
    else if (DType == &PyArray_UShortDType) {
        return 1;
    }
#endif
#if NPY_SIZEOF_INT == NPY_SIZEOF_LONG
    // 如果整型和长整型的字节大小相同,返回1
    else if (DType == &PyArray_UIntDType) {
        return 1;
    }
#endif
#if NPY_SIZEOF_LONGLONG == NPY_SIZEOF_LONG
    // 如果长长整型和长整型的字节大小相同,返回1
    else if (DType == &PyArray_ULongLongDType) {
        return 1;
    }
#endif
    // 默认情况下返回0
    return 0;
}


static int
string_multiply_promoter(PyObject *ufunc_obj,
                         PyArray_DTypeMeta *const op_dtypes[],
                         PyArray_DTypeMeta *const signature[],
                         PyArray_DTypeMeta *new_op_dtypes[])
{
    PyUFuncObject *ufunc = (PyUFuncObject *)ufunc_obj;
    // 遍历输入参数
    for (int i = 0; i < ufunc->nin; i++) {
        PyArray_DTypeMeta *tmp = NULL;
        // 如果有签名类型,则使用签名类型
        if (signature[i]) {
            tmp = signature[i];
        }
        // 如果是整数类型,则使用64位整型
        else if (is_integer_dtype(op_dtypes[i])) {
            tmp = &PyArray_Int64DType;
        }
        // 如果存在操作类型,则使用该类型
        else if (op_dtypes[i]) {
            tmp = op_dtypes[i];
        }
        // 默认使用字符串类型
        else {
            tmp = &PyArray_StringDType;
        }
        // 增加临时类型的引用计数
        Py_INCREF(tmp);
        new_op_dtypes[i] = tmp;
    }
    /* don't touch output dtypes if they are set */
    // 如果输出类型已经设置,则不修改输出类型
    for (int i = ufunc->nin; i < ufunc->nargs; i++) {
        if (op_dtypes[i]) {
            // 增加输出类型的引用计数
            Py_INCREF(op_dtypes[i]);
            new_op_dtypes[i] = op_dtypes[i];
        }
        else {
            // 默认使用字符串类型
            Py_INCREF(&PyArray_StringDType);
            new_op_dtypes[i] = &PyArray_StringDType;
        }
    }
    return 0;
}

// Register a ufunc.
//
// Pass NULL for resolve_func to use the default_resolve_descriptors.
int
init_ufunc(PyObject *umath, const char *ufunc_name, PyArray_DTypeMeta **dtypes,
           PyArrayMethod_ResolveDescriptors *resolve_func,
           PyArrayMethod_StridedLoop *loop_func, int nin, int nout,
           NPY_CASTING casting, NPY_ARRAYMETHOD_FLAGS flags,
           void *static_data)
{
    PyObject *ufunc = PyObject_GetAttrString(umath, ufunc_name);
    if (ufunc == NULL) {
        return -1;
    }
    char loop_name[256] = {0};

    // 根据ufunc_name创建循环名称
    snprintf(loop_name, sizeof(loop_name), "string_%s", ufunc_name);

    // 定义PyArrayMethod_Spec结构体
    PyArrayMethod_Spec spec;
    spec.name = loop_name;
    spec.nin = nin;
    spec.nout = nout;
    spec.casting = casting;
    spec.flags = flags;
    spec.dtypes = dtypes;
    spec.slots = NULL;

    // 设置PyType_Slot resolve_slots数组
    PyType_Slot resolve_slots[] = {
            {NPY_METH_resolve_descriptors, (void *)resolve_func},
            {NPY_METH_strided_loop, (void *)loop_func},
            {_NPY_METH_static_data, static_data},
            {0, NULL}};

    // 将resolve_slots数组赋值给spec.slots
    spec.slots = resolve_slots;

    // 将循环规范添加到ufunc中
    if (PyUFunc_AddLoopFromSpec_int(ufunc, &spec, 1) < 0) {
        Py_DECREF(ufunc);
        return -1;
    }

    // 减少ufunc的引用计数
    Py_DECREF(ufunc);
    return 0;
}

int
add_promoter(PyObject *numpy, const char *ufunc_name,
             PyArray_DTypeMeta *dtypes[], size_t n_dtypes,
             PyArrayMethod_PromoterFunction *promoter_impl)
{
    // 从numpy对象中获取ufunc对象
    PyObject *ufunc = PyObject_GetAttrString((PyObject *)numpy, ufunc_name);
    if (ufunc == NULL) {
        return -1;
    }
    // 剩余代码未提供,不进行注释
    # 如果传入的 ufunc 指针为空,则直接返回错误码 -1
    if (ufunc == NULL) {
        return -1;
    }

    # 创建一个包含 n_dtypes 个元素的 Python 元组对象 DType_tuple
    PyObject *DType_tuple = PyTuple_New(n_dtypes);

    # 如果创建元组失败,则释放之前分配的 ufunc 对象,并返回错误码 -1
    if (DType_tuple == NULL) {
        Py_DECREF(ufunc);
        return -1;
    }

    # 遍历 dtypes 数组,对每个 PyObject 指针增加引用计数并添加到 DType_tuple 中
    for (size_t i=0; i<n_dtypes; i++) {
        Py_INCREF((PyObject *)dtypes[i]);
        PyTuple_SET_ITEM(DType_tuple, i, (PyObject *)dtypes[i]);
    }

    # 创建一个 PyCapsule 对象 promoter_capsule,用于包装 promoter_impl 函数指针
    PyObject *promoter_capsule = PyCapsule_New((void *)promoter_impl,
                                               "numpy._ufunc_promoter", NULL);

    # 如果创建 PyCapsule 失败,则释放之前分配的对象,并返回错误码 -1
    if (promoter_capsule == NULL) {
        Py_DECREF(ufunc);
        Py_DECREF(DType_tuple);
        return -1;
    }

    # 将 DType_tuple 和 promoter_capsule 传递给 PyUFunc_AddPromoter 函数,将数据类型和
    # 优化器函数注册到 ufunc 中。如果添加失败,则释放相关对象并返回错误码 -1
    if (PyUFunc_AddPromoter(ufunc, DType_tuple, promoter_capsule) < 0) {
        Py_DECREF(promoter_capsule);
        Py_DECREF(DType_tuple);
        Py_DECREF(ufunc);
        return -1;
    }

    # 成功添加优化器后,释放 promoter_capsule、DType_tuple 和 ufunc 对象的引用计数
    Py_DECREF(promoter_capsule);
    Py_DECREF(DType_tuple);
    Py_DECREF(ufunc);

    # 返回成功标志码 0
    return 0;
#define INIT_MULTIPLY(typename, shortname)                                 \
    // 创建一个用于右操作数为指定类型的乘法通用函数类型数组
    PyArray_DTypeMeta *multiply_right_##shortname##_types[] = {            \
        &PyArray_StringDType, &PyArray_##typename##DType,                  \
        &PyArray_StringDType};                                             \
                                                                           \
    // 初始化右操作数为指定类型的乘法通用函数
    if (init_ufunc(umath, "multiply", multiply_right_##shortname##_types,  \
                   &multiply_resolve_descriptors,                          \
                   &multiply_right_strided_loop<npy_##shortname>, 2, 1,    \
                   NPY_NO_CASTING, (NPY_ARRAYMETHOD_FLAGS) 0, NULL) < 0) { \
        return -1;                                                         \
    }                                                                      \
                                                                           \
    // 创建一个用于左操作数为指定类型的乘法通用函数类型数组
    PyArray_DTypeMeta *multiply_left_##shortname##_types[] = {             \
            &PyArray_##typename##DType, &PyArray_StringDType,              \
            &PyArray_StringDType};                                         \
                                                                           \
    // 初始化左操作数为指定类型的乘法通用函数
    if (init_ufunc(umath, "multiply", multiply_left_##shortname##_types,   \
                   &multiply_resolve_descriptors,                          \
                   &multiply_left_strided_loop<npy_##shortname>, 2, 1,     \
                   NPY_NO_CASTING, (NPY_ARRAYMETHOD_FLAGS) 0, NULL) < 0) { \
        return -1;                                                         \
    }
    // 定义一个静态常量字符指针数组,包含6个字符串,表示比较操作的函数名
    static const char *comparison_ufunc_names[6] = {
            "equal", "not_equal",
            "less", "less_equal", "greater_equal", "greater",
    };

    // 定义一个 PyArray_DTypeMeta 指针数组,包含3个数据类型元信息对象,用于比较操作
    PyArray_DTypeMeta *comparison_dtypes[] = {
            &PyArray_StringDType,
            &PyArray_StringDType, &PyArray_BoolDType};

    // 定义一个静态布尔数组,表示在 string_cmp_strided_loop 函数中,eq 和 ne 的比较结果
    static npy_bool comparison_ufunc_eq_lt_gt_results[6*3] = {
        NPY_TRUE, NPY_FALSE, NPY_FALSE, // eq: results for eq, lt, gt
        NPY_FALSE, NPY_TRUE, NPY_TRUE,  // ne
        NPY_FALSE, NPY_TRUE, NPY_FALSE, // lt
        NPY_TRUE, NPY_TRUE, NPY_FALSE,  // le
        NPY_TRUE, NPY_FALSE, NPY_TRUE,  // gt
        NPY_FALSE, NPY_FALSE, NPY_TRUE, // ge
    };

    // 循环初始化比较操作的通用函数
    for (int i = 0; i < 6; i++) {
        // 初始化通用函数 umath 中的比较函数,如果失败则返回 -1
        if (init_ufunc(umath, comparison_ufunc_names[i], comparison_dtypes,
                       &string_comparison_resolve_descriptors,
                       &string_comparison_strided_loop, 2, 1, NPY_NO_CASTING,
                       (NPY_ARRAYMETHOD_FLAGS) 0,
                       &comparison_ufunc_eq_lt_gt_results[i*3]) < 0) {
            return -1;
        }

        // 将对象和 Unicode 提升器添加到 umath 中的比较函数中,如果失败则返回 -1
        if (add_object_and_unicode_promoters(
                    umath, comparison_ufunc_names[i],
                    &string_unicode_bool_output_promoter,
                    &string_object_bool_output_promoter) < 0) {
            return -1;
        }
    }

    // 定义一个布尔输出数据类型的 PyArray_DTypeMeta 指针数组
    PyArray_DTypeMeta *bool_output_dtypes[] = {
        &PyArray_StringDType,
        &PyArray_BoolDType
    };

    // 初始化 umath 中的 "isnan" 函数,如果失败则返回 -1
    if (init_ufunc(umath, "isnan", bool_output_dtypes,
                   &string_bool_output_resolve_descriptors,
                   &string_isnan_strided_loop, 1, 1, NPY_NO_CASTING,
                   (NPY_ARRAYMETHOD_FLAGS) 0, NULL) < 0) {
        return -1;
    }

    // 定义一个一元操作的函数名字符串数组
    const char *unary_loop_names[] = {
        "isalpha", "isdecimal", "isdigit", "isnumeric", "isspace",
        "isalnum", "istitle", "isupper", "islower",
    };

    // 定义一组 utf8_buffer_method 指针数组,指向一元操作函数成员方法
    static utf8_buffer_method unary_loop_buffer_methods[] = {
        &Buffer<ENCODING::UTF8>::isalpha,
        &Buffer<ENCODING::UTF8>::isdecimal,
        &Buffer<ENCODING::UTF8>::isdigit,
        &Buffer<ENCODING::UTF8>::isnumeric,
        &Buffer<ENCODING::UTF8>::isspace,
        &Buffer<ENCODING::UTF8>::isalnum,
        &Buffer<ENCODING::UTF8>::istitle,
        &Buffer<ENCODING::UTF8>::isupper,
        &Buffer<ENCODING::UTF8>::islower,
    };

    // 循环初始化一元操作的通用函数
    for (int i=0; i<9; i++) {
        // 初始化通用函数 umath 中的一元操作函数,如果失败则返回 -1
        if (init_ufunc(umath, unary_loop_names[i], bool_output_dtypes,
                       &string_bool_output_resolve_descriptors,
                       &string_bool_output_unary_strided_loop, 1, 1, NPY_NO_CASTING,
                       (NPY_ARRAYMETHOD_FLAGS) 0,
                       &unary_loop_buffer_methods[i]) < 0) {
            return -1;
        }
    }
    // 定义一个包含两种数据类型元信息的数组,分别为字符串和整数指针
    PyArray_DTypeMeta *intp_output_dtypes[] = {
        &PyArray_StringDType,
        &PyArray_IntpDType
    };

    // 初始化一个ufunc函数,用于计算字符串长度,设置输出数据类型,解析描述符,并设置循环函数
    if (init_ufunc(umath, "str_len", intp_output_dtypes,
                   &string_intp_output_resolve_descriptors,
                   &string_strlen_strided_loop, 1, 1, NPY_NO_CASTING,
                   (NPY_ARRAYMETHOD_FLAGS) 0, NULL) < 0) {
        return -1;
    }

    // 定义一个包含三种字符串数据类型元信息的数组
    PyArray_DTypeMeta *binary_dtypes[] = {
            &PyArray_StringDType,
            &PyArray_StringDType,
            &PyArray_StringDType,
    };

    // 定义包含字符串数组的名称
    const char* minimum_maximum_names[] = {"minimum", "maximum"};

    // 定义静态布尔数组,用于指示最小和最大的反转状态
    static npy_bool minimum_maximum_invert[2] = {NPY_FALSE, NPY_TRUE};

    // 循环处理最小和最大名称,为每个名称初始化一个ufunc函数
    for (int i = 0; i < 2; i++) {
        if (init_ufunc(umath, minimum_maximum_names[i],
                       binary_dtypes, binary_resolve_descriptors,
                       &minimum_maximum_strided_loop, 2, 1, NPY_NO_CASTING,
                       (NPY_ARRAYMETHOD_FLAGS) 0,
                       &minimum_maximum_invert[i]) < 0) {
            return -1;
        }
    }

    // 初始化一个ufunc函数,用于执行加法操作,设置输入输出数据类型和相关处理函数
    if (init_ufunc(umath, "add", binary_dtypes, binary_resolve_descriptors,
                   &add_strided_loop, 2, 1, NPY_NO_CASTING,
                   (NPY_ARRAYMETHOD_FLAGS) 0, NULL) < 0) {
        return -1;
    }

    // 定义包含三种数据类型元信息的数组,用于所有字符串推广操作
    PyArray_DTypeMeta *rall_strings_promoter_dtypes[] = {
        &PyArray_StringDType,
        &PyArray_UnicodeDType,
        &PyArray_StringDType,
    };

    // 添加所有字符串推广操作的ufunc函数,并指定数据类型和推广函数
    if (add_promoter(umath, "add", rall_strings_promoter_dtypes, 3,
                     all_strings_promoter) < 0) {
        return -1;
    }

    // 定义包含三种数据类型元信息的数组,用于左侧所有字符串推广操作
    PyArray_DTypeMeta *lall_strings_promoter_dtypes[] = {
        &PyArray_UnicodeDType,
        &PyArray_StringDType,
        &PyArray_StringDType,
    };

    // 添加左侧所有字符串推广操作的ufunc函数,并指定数据类型和推广函数
    if (add_promoter(umath, "add", lall_strings_promoter_dtypes, 3,
                     all_strings_promoter) < 0) {
        return -1;
    }

    // 初始化 Int64 和 UInt64 的乘法操作的宏定义
    INIT_MULTIPLY(Int64, int64);
    INIT_MULTIPLY(UInt64, uint64);

    // 定义包含三种数据类型元信息的数组,用于字符串乘法操作
    PyArray_DTypeMeta *rdtypes[] = {
        &PyArray_StringDType,
        &PyArray_IntAbstractDType,
        &PyArray_StringDType};

    // 添加字符串乘法操作的ufunc函数,并指定数据类型和推广函数
    if (add_promoter(umath, "multiply", rdtypes, 3, string_multiply_promoter) < 0) {
        return -1;
    }

    // 定义包含三种数据类型元信息的数组,用于左侧字符串乘法操作
    PyArray_DTypeMeta *ldtypes[] = {
        &PyArray_IntAbstractDType,
        &PyArray_StringDType,
        &PyArray_StringDType};

    // 添加左侧字符串乘法操作的ufunc函数,并指定数据类型和推广函数
    if (add_promoter(umath, "multiply", ldtypes, 3, string_multiply_promoter) < 0) {
        return -1;
    }

    // 定义包含五种数据类型元信息的数组,用于 find-like 操作
    PyArray_DTypeMeta *findlike_dtypes[] = {
        &PyArray_StringDType, &PyArray_StringDType,
        &PyArray_Int64DType, &PyArray_Int64DType,
        &PyArray_DefaultIntDType,
    };

    // 定义包含五种字符串操作名称的数组
    const char* findlike_names[] = {
        "find", "rfind", "index", "rindex", "count",
    };

    // 定义包含五种数据类型元信息的数组,用于所有字符串推广操作
    PyArray_DTypeMeta *findlike_promoter_dtypes[] = {
        &PyArray_StringDType, &PyArray_UnicodeDType,
        &PyArray_IntAbstractDType, &PyArray_IntAbstractDType,
        &PyArray_DefaultIntDType,
    };
    // 定义一个函数指针数组,包含查找类函数的指针
    find_like_function *findlike_functions[] = {
        // 使用UTF-8编码的字符串查找函数
        string_find<ENCODING::UTF8>,
        // 使用UTF-8编码的字符串反向查找函数
        string_rfind<ENCODING::UTF8>,
        // 使用UTF-8编码的字符串索引函数
        string_index<ENCODING::UTF8>,
        // 使用UTF-8编码的字符串反向索引函数
        string_rindex<ENCODING::UTF8>,
        // 使用UTF-8编码的字符串计数函数
        string_count<ENCODING::UTF8>,
    };

    // 遍历函数指针数组
    for (int i=0; i<5; i++) {
        // 初始化通用函数,设置查找函数的解析描述符和循环处理函数
        if (init_ufunc(umath, findlike_names[i], findlike_dtypes,
                       &string_findlike_resolve_descriptors,
                       &string_findlike_strided_loop, 4, 1, NPY_NO_CASTING,
                       (NPY_ARRAYMETHOD_FLAGS) 0,
                       (void *)findlike_functions[i]) < 0) {
            return -1;
        }

        // 添加字符串查找类函数的类型提升器
        if (add_promoter(umath, findlike_names[i],
                         findlike_promoter_dtypes,
                         5, string_findlike_promoter) < 0) {
            return -1;
        }
    }

    // 定义开始和结束字符串操作的数据类型数组
    PyArray_DTypeMeta *startswith_endswith_dtypes[] = {
        &PyArray_StringDType, &PyArray_StringDType,
        &PyArray_Int64DType, &PyArray_Int64DType,
        &PyArray_BoolDType,
    };

    // 开始和结束字符串操作的函数名数组
    const char* startswith_endswith_names[] = {
        "startswith", "endswith",
    };

    // 开始和结束字符串操作的类型提升器数据类型数组
    PyArray_DTypeMeta *startswith_endswith_promoter_dtypes[] = {
        &PyArray_StringDType, &PyArray_UnicodeDType,
        &PyArray_IntAbstractDType, &PyArray_IntAbstractDType,
        &PyArray_BoolDType,
    };

    // 开始和结束字符串操作的起始位置数组
    static STARTPOSITION startswith_endswith_startposition[] = {
        STARTPOSITION::FRONT,
        STARTPOSITION::BACK,
    };

    // 遍历开始和结束字符串操作的名称数组
    for (int i=0; i<2; i++) {
        // 初始化通用函数,设置开始和结束字符串操作的解析描述符和循环处理函数
        if (init_ufunc(umath, startswith_endswith_names[i], startswith_endswith_dtypes,
                       &string_startswith_endswith_resolve_descriptors,
                       &string_startswith_endswith_strided_loop,
                       4, 1, NPY_NO_CASTING, (NPY_ARRAYMETHOD_FLAGS) 0,
                       &startswith_endswith_startposition[i]) < 0) {
            return -1;
        }

        // 添加开始和结束字符串操作的类型提升器
        if (add_promoter(umath, startswith_endswith_names[i],
                         startswith_endswith_promoter_dtypes,
                         5, string_startswith_endswith_promoter) < 0) {
            return -1;
        }
    }

    // 定义去除字符串两端空白字符操作的数据类型数组
    PyArray_DTypeMeta *strip_whitespace_dtypes[] = {
        &PyArray_StringDType, &PyArray_StringDType
    };

    // 去除字符串两端空白字符操作的函数名数组
    const char *strip_whitespace_names[] = {
        "_lstrip_whitespace", "_rstrip_whitespace", "_strip_whitespace",
    };

    // 去除字符串两端空白字符操作的类型数组
    static STRIPTYPE strip_types[] = {
        STRIPTYPE::LEFTSTRIP,
        STRIPTYPE::RIGHTSTRIP,
        STRIPTYPE::BOTHSTRIP,
    };

    // 遍历去除字符串两端空白字符操作的名称数组
    for (int i=0; i<3; i++) {
        // 初始化通用函数,设置去除字符串两端空白字符的解析描述符和循环处理函数
        if (init_ufunc(umath, strip_whitespace_names[i], strip_whitespace_dtypes,
                       &strip_whitespace_resolve_descriptors,
                       &string_lrstrip_whitespace_strided_loop,
                       1, 1, NPY_NO_CASTING, (NPY_ARRAYMETHOD_FLAGS) 0,
                       &strip_types[i]) < 0) {
            return -1;
        }
    }
    # 定义包含三个字符类型的数组,用于字符串操作
    PyArray_DTypeMeta *strip_chars_dtypes[] = {
        &PyArray_StringDType, &PyArray_StringDType, &PyArray_StringDType
    };

    # 定义包含三个字符类型名称的数组
    const char *strip_chars_names[] = {
        "_lstrip_chars", "_rstrip_chars", "_strip_chars",
    };

    # 循环处理三个字符操作
    for (int i=0; i<3; i++) {
        # 初始化通用函数,处理去除字符操作
        if (init_ufunc(umath, strip_chars_names[i], strip_chars_dtypes,
                       &binary_resolve_descriptors,
                       &string_lrstrip_chars_strided_loop,
                       2, 1, NPY_NO_CASTING, (NPY_ARRAYMETHOD_FLAGS) 0,
                       &strip_types[i]) < 0) {
            return -1;
        }

        # 添加字符串推广器,处理右侧去除字符操作
        if (add_promoter(umath, strip_chars_names[i],
                         rall_strings_promoter_dtypes, 3,
                         all_strings_promoter) < 0) {
            return -1;
        }

        # 添加字符串推广器,处理左侧去除字符操作
        if (add_promoter(umath, strip_chars_names[i],
                         lall_strings_promoter_dtypes, 3,
                         all_strings_promoter) < 0) {
            return -1;
        }
    }

    # 定义包含五个替换操作类型的数组
    PyArray_DTypeMeta *replace_dtypes[] = {
        &PyArray_StringDType, &PyArray_StringDType, &PyArray_StringDType,
        &PyArray_Int64DType, &PyArray_StringDType,
    };

    # 初始化通用函数,处理字符串替换操作
    if (init_ufunc(umath, "_replace", replace_dtypes,
                   &replace_resolve_descriptors,
                   &string_replace_strided_loop, 4, 1,
                   NPY_NO_CASTING,
                   (NPY_ARRAYMETHOD_FLAGS) 0, NULL) < 0) {
        return -1;
    }

    # 定义包含五个替换操作推广器类型的数组(Python整数类型)
    PyArray_DTypeMeta *replace_promoter_pyint_dtypes[] = {
        &PyArray_StringDType, &PyArray_UnicodeDType, &PyArray_UnicodeDType,
        &PyArray_IntAbstractDType, &PyArray_StringDType,
    };

    # 添加字符串推广器,处理Python整数类型的替换操作
    if (add_promoter(umath, "_replace", replace_promoter_pyint_dtypes, 5,
                     string_replace_promoter) < 0) {
        return -1;
    }

    # 定义包含五个替换操作推广器类型的数组(Int64类型)
    PyArray_DTypeMeta *replace_promoter_int64_dtypes[] = {
        &PyArray_StringDType, &PyArray_UnicodeDType, &PyArray_UnicodeDType,
        &PyArray_Int64DType, &PyArray_StringDType,
    };

    # 添加字符串推广器,处理Int64类型的替换操作
    if (add_promoter(umath, "_replace", replace_promoter_int64_dtypes, 5,
                     string_replace_promoter) < 0) {
        return -1;
    }

    # 定义包含三个扩展制表符操作类型的数组
    PyArray_DTypeMeta *expandtabs_dtypes[] = {
        &PyArray_StringDType,
        &PyArray_Int64DType,
        &PyArray_StringDType,
    };

    # 初始化通用函数,处理扩展制表符操作
    if (init_ufunc(umath, "_expandtabs", expandtabs_dtypes,
                   &expandtabs_resolve_descriptors,
                   &string_expandtabs_strided_loop, 2, 1,
                   NPY_NO_CASTING,
                   (NPY_ARRAYMETHOD_FLAGS) 0, NULL) < 0) {
        return -1;
    }

    # 定义包含三个扩展制表符操作推广器类型的数组
    PyArray_DTypeMeta *expandtabs_promoter_dtypes[] = {
        &PyArray_StringDType,
        (PyArray_DTypeMeta *)Py_None,
        &PyArray_StringDType
    };

    # 添加字符串推广器,处理扩展制表符操作
    if (add_promoter(umath, "_expandtabs", expandtabs_promoter_dtypes,
                     3, string_multiply_promoter) < 0) {
        return -1;
    }
    # 定义一个数组,包含三种不同的 PyArray_DTypeMeta 类型的指针,用于处理 center、ljust、rjust 操作
    PyArray_DTypeMeta *center_ljust_rjust_dtypes[] = {
        &PyArray_StringDType,
        &PyArray_Int64DType,
        &PyArray_StringDType,
        &PyArray_StringDType,
    };
    
    # 定义一个静态数组,包含三个字符串常量,分别表示 center、ljust、rjust 操作的名称
    static const char* center_ljust_rjust_names[3] = {
        "_center", "_ljust", "_rjust"
    };
    
    # 定义一个静态数组,包含三个 JUSTPOSITION 枚举类型的元素,表示 center、ljust、rjust 操作的对齐位置
    static JUSTPOSITION positions[3] = {
        JUSTPOSITION::CENTER, JUSTPOSITION::LEFT, JUSTPOSITION::RIGHT
    };
    
    # 循环遍历三个操作名称
    for (int i=0; i<3; i++) {
        # 初始化通用函数对象(ufunc),注册 center、ljust、rjust 操作
        if (init_ufunc(umath, center_ljust_rjust_names[i],
                       center_ljust_rjust_dtypes,
                       &center_ljust_rjust_resolve_descriptors,
                       &center_ljust_rjust_strided_loop, 3, 1, NPY_NO_CASTING,
                       (NPY_ARRAYMETHOD_FLAGS) 0, &positions[i]) < 0) {
            return -1;
        }
    
        # 定义一个数组,包含四种不同的 PyArray_DTypeMeta 类型的指针,用于处理整数推广操作
        PyArray_DTypeMeta *int_promoter_dtypes[] = {
            &PyArray_StringDType,
            (PyArray_DTypeMeta *)Py_None,
            &PyArray_StringDType,
            &PyArray_StringDType,
        };
    
        # 将整数推广操作添加到通用函数对象(ufunc)中
        if (add_promoter(umath, center_ljust_rjust_names[i],
                         int_promoter_dtypes, 4,
                         string_multiply_promoter) < 0) {
            return -1;
        }
    
        # 定义一个数组,包含四种不同的 PyArray_DTypeMeta 类型的指针,用于处理Unicode字符串推广操作
        PyArray_DTypeMeta *unicode_promoter_dtypes[] = {
            &PyArray_StringDType,
            (PyArray_DTypeMeta *)Py_None,
            &PyArray_UnicodeDType,
            &PyArray_StringDType,
        };
    
        # 将Unicode字符串推广操作添加到通用函数对象(ufunc)中
        if (add_promoter(umath, center_ljust_rjust_names[i],
                         unicode_promoter_dtypes, 4,
                         string_multiply_promoter) < 0) {
            return -1;
        }
    }
    
    # 定义一个数组,包含三种不同的 PyArray_DTypeMeta 类型的指针,用于处理 zfill 操作
    PyArray_DTypeMeta *zfill_dtypes[] = {
        &PyArray_StringDType,
        &PyArray_Int64DType,
        &PyArray_StringDType,
    };
    
    # 初始化通用函数对象(ufunc),注册 zfill 操作
    if (init_ufunc(umath, "_zfill", zfill_dtypes, multiply_resolve_descriptors,
                   zfill_strided_loop, 2, 1, NPY_NO_CASTING,
                   (NPY_ARRAYMETHOD_FLAGS) 0, NULL) < 0) {
        return -1;
    }
    
    # 定义一个数组,包含三种不同的 PyArray_DTypeMeta 类型的指针,用于处理整数推广操作
    PyArray_DTypeMeta *int_promoter_dtypes[] = {
            &PyArray_StringDType,
            (PyArray_DTypeMeta *)Py_None,
            &PyArray_StringDType,
    };
    
    # 将整数推广操作添加到通用函数对象(ufunc)中
    if (add_promoter(umath, "_zfill", int_promoter_dtypes, 3,
                     string_multiply_promoter) < 0) {
        return -1;
    }
    
    # 定义一个数组,包含五种不同的 PyArray_DTypeMeta 类型的指针,用于处理 partition 操作
    PyArray_DTypeMeta *partition_dtypes[] = {
        &PyArray_StringDType,
        &PyArray_StringDType,
        &PyArray_StringDType,
        &PyArray_StringDType,
        &PyArray_StringDType
    };
    
    # 定义一个静态数组,包含两个字符串常量,表示 partition 和 rpartition 操作的名称
    const char *partition_names[] = {"_partition", "_rpartition"};
    
    # 定义一个静态数组,包含两个 STARTPOSITION 枚举类型的元素,表示 partition 和 rpartition 操作的起始位置
    static STARTPOSITION partition_startpositions[] = {
        STARTPOSITION::FRONT, STARTPOSITION::BACK
    };
    # 循环两次,初始化分区函数
    for (int i=0; i<2; i++) {
        # 调用初始化通用函数 init_ufunc,初始化第 i 个分区
        if (init_ufunc(umath, partition_names[i], partition_dtypes,
                       string_partition_resolve_descriptors,
                       string_partition_strided_loop, 2, 3, NPY_NO_CASTING,
                       (NPY_ARRAYMETHOD_FLAGS) 0, &partition_startpositions[i]) < 0) {
            # 如果初始化失败,返回 -1
            return -1;
        }
    }

    # 初始化完成,返回 0 表示成功
    return 0;
}


注释:


# 这是一个单独的右大括号 '}',用于闭合之前的代码块或函数定义。
# 在这里没有上下文,无法具体说明其用途,需要结合前面的代码来理解。

.\numpy\numpy\_core\src\umath\stringdtype_ufuncs.h

#ifndef _NPY_CORE_SRC_UMATH_STRINGDTYPE_UFUNCS_H_
#define _NPY_CORE_SRC_UMATH_STRINGDTYPE_UFUNCS_H_

#ifdef __cplusplus
extern "C" {
#endif

// 声明一个不导出的函数,用于初始化字符串数据类型的通用函数
NPY_NO_EXPORT int
init_stringdtype_ufuncs(PyObject* umath);

#ifdef __cplusplus
}
#endif

#endif /* _NPY_CORE_SRC_UMATH_STRINGDTYPE_UFUNCS_H_ */

.\numpy\numpy\_core\src\umath\string_buffer.h

#ifndef _NPY_CORE_SRC_UMATH_STRING_BUFFER_H_
#define _NPY_CORE_SRC_UMATH_STRING_BUFFER_H_

#include <Python.h>
#include <cstddef>
#include <wchar.h>

// 定义不使用过时 API 的标志
#define NPY_NO_DEPRECATED_API NPY_API_VERSION
// 定义多维数组模块
#define _MULTIARRAYMODULE
// 定义数学模块
#define _UMATHMODULE

#include "numpy/ndarraytypes.h"
#include "stringdtype/utf8_utils.h"
#include "string_fastsearch.h"
#include "gil_utils.h"

// 定义宏,检查索引是否溢出
#define CHECK_OVERFLOW(index) if (buf + (index) >= after) return 0
// 定义宏,提取一个整数的最高有效位
#define MSB(val) ((val) >> 7 & 1)

// 枚举类型,表示字符编码方式
enum class ENCODING {
    ASCII, UTF32, UTF8
};

// 枚举类型,表示实现的一元函数
enum class IMPLEMENTED_UNARY_FUNCTIONS {
    ISALPHA,
    ISDECIMAL,
    ISDIGIT,
    ISSPACE,
    ISALNUM,
    ISLOWER,
    ISUPPER,
    ISTITLE,
    ISNUMERIC,
    STR_LEN,
};

// 模板函数,根据编码类型返回字符
template <ENCODING enc>
inline npy_ucs4
getchar(const unsigned char *buf, int *bytes);

// 特化模板函数,处理 ASCII 编码类型的字符
template <>
inline npy_ucs4
getchar<ENCODING::ASCII>(const unsigned char *buf, int *bytes)
{
    *bytes = 1;  // ASCII 字符占用一个字节
    return (npy_ucs4) *buf;  // 返回字符的 Unicode 码点
}

// 特化模板函数,处理 UTF32 编码类型的字符
template <>
inline npy_ucs4
getchar<ENCODING::UTF32>(const unsigned char *buf, int *bytes)
{
    *bytes = 4;  // UTF32 字符占用四个字节
    return *(npy_ucs4 *)buf;  // 返回 UTF32 编码字符的 Unicode 码点
}

// 特化模板函数,处理 UTF8 编码类型的字符
template <>
inline npy_ucs4
getchar<ENCODING::UTF8>(const unsigned char *buf, int *bytes)
{
    Py_UCS4 codepoint;
    *bytes = utf8_char_to_ucs4_code(buf, &codepoint);  // 将 UTF8 字符转换为 Unicode 码点
    return (npy_ucs4)codepoint;  // 返回 Unicode 码点
}

// 模板函数,根据编码类型判断字符是否为字母
template<ENCODING enc>
inline bool
codepoint_isalpha(npy_ucs4 code);

// 特化模板函数,处理 ASCII 编码类型的字母判断
template<>
inline bool
codepoint_isalpha<ENCODING::ASCII>(npy_ucs4 code)
{
    return NumPyOS_ascii_isalpha(code);  // 使用 NumPy 的 ASCII 字母判断函数
}

// 特化模板函数,处理 UTF32 编码类型的字母判断
template<>
inline bool
codepoint_isalpha<ENCODING::UTF32>(npy_ucs4 code)
{
    return Py_UNICODE_ISALPHA(code);  // 使用 Python 内部的 UTF32 字母判断函数
}

// 特化模板函数,处理 UTF8 编码类型的字母判断
template<>
inline bool
codepoint_isalpha<ENCODING::UTF8>(npy_ucs4 code)
{
    return Py_UNICODE_ISALPHA(code);  // 使用 Python 内部的 UTF8 字母判断函数
}

// 模板函数,根据编码类型判断字符是否为数字
template<ENCODING enc>
inline bool
codepoint_isdigit(npy_ucs4 code);

// 特化模板函数,处理 ASCII 编码类型的数字判断
template<>
inline bool
codepoint_isdigit<ENCODING::ASCII>(npy_ucs4 code)
{
    return NumPyOS_ascii_isdigit(code);  // 使用 NumPy 的 ASCII 数字判断函数
}

// 特化模板函数,处理 UTF32 编码类型的数字判断
template<>
inline bool
codepoint_isdigit<ENCODING::UTF32>(npy_ucs4 code)
{
    return Py_UNICODE_ISDIGIT(code);  // 使用 Python 内部的 UTF32 数字判断函数
}

// 特化模板函数,处理 UTF8 编码类型的数字判断
template<>
inline bool
codepoint_isdigit<ENCODING::UTF8>(npy_ucs4 code)
{
    return Py_UNICODE_ISDIGIT(code);  // 使用 Python 内部的 UTF8 数字判断函数
}

// 模板函数,根据编码类型判断字符是否为空白字符
template<ENCODING enc>
inline bool
codepoint_isspace(npy_ucs4 code);

// 特化模板函数,处理 ASCII 编码类型的空白字符判断
template<>
inline bool
codepoint_isspace<ENCODING::ASCII>(npy_ucs4 code)
{
    return NumPyOS_ascii_isspace(code);  // 使用 NumPy 的 ASCII 空白字符判断函数
}

// 特化模板函数,处理 UTF32 编码类型的空白字符判断
template<>
inline bool
codepoint_isspace<ENCODING::UTF32>(npy_ucs4 code)
{
    return Py_UNICODE_ISSPACE(code);  // 使用 Python 内部的 UTF32 空白字符判断函数
}

// 特化模板函数,处理 UTF8 编码类型的空白字符判断
template<>
inline bool
codepoint_isspace<ENCODING::UTF8>(npy_ucs4 code)
{
    return Py_UNICODE_ISSPACE(code);  // 使用 Python 内部的 UTF8 空白字符判断函数
}

// 模板函数,根据编码类型判断字符是否为字母或数字
template<ENCODING enc>
inline bool
codepoint_isalnum(npy_ucs4 code);

// 特化模板函数,处理 ASCII 编码类型的字母或数字判断
template<>
inline bool
codepoint_isalnum<ENCODING::ASCII>(npy_ucs4 code)
{
    return NumPyOS_ascii_isalnum(code);  // 使用 NumPy 的 ASCII 字母或数字判断函数
}

// 特化模板函数,处理 UTF32 编码类型的字母或数字判断
template<>
inline bool
codepoint_isalnum<ENCODING::UTF32>(npy_ucs4 code)
{
    return Py_UNICODE_ISALNUM(code);  // 使用 Python 内部的 UTF32 字母或数字判断函数
}

// 特化模板函数,处理 UTF8 编码类型的字母或数字判断
template<>
inline bool
codepoint_isalnum<ENCODING::UTF8>(npy_ucs4 code)
{
    return Py_UNICODE_ISALNUM(code);  // 使用 Python 内部的 UTF8 字母或数字判断函数
}

// 继续添加更多的模板函数实现...
// 声明模板特化,用于判断给定编码下的 Unicode 代码点是否为小写字母
template<>
inline bool
codepoint_islower<ENCODING::ASCII>(npy_ucs4 code)
{
    return NumPyOS_ascii_islower(code);
}

// 声明模板特化,用于判断给定编码下的 Unicode 代码点是否为小写字母
template<>
inline bool
codepoint_islower<ENCODING::UTF32>(npy_ucs4 code)
{
    return Py_UNICODE_ISLOWER(code);
}

// 声明模板特化,用于判断给定编码下的 Unicode 代码点是否为小写字母
template<>
inline bool
codepoint_islower<ENCODING::UTF8>(npy_ucs4 code)
{
    return Py_UNICODE_ISLOWER(code);
}

// 声明模板特化,用于判断给定编码下的 Unicode 代码点是否为大写字母
template<ENCODING enc>
inline bool
codepoint_isupper(npy_ucs4 code);

// 模板特化实现,用于判断 ASCII 编码下的 Unicode 代码点是否为大写字母
template<>
inline bool
codepoint_isupper<ENCODING::ASCII>(npy_ucs4 code)
{
    return NumPyOS_ascii_isupper(code);
}

// 模板特化实现,用于判断 UTF32 编码下的 Unicode 代码点是否为大写字母
template<>
inline bool
codepoint_isupper<ENCODING::UTF32>(npy_ucs4 code)
{
    return Py_UNICODE_ISUPPER(code);
}

// 模板特化实现,用于判断 UTF8 编码下的 Unicode 代码点是否为大写字母
template<>
inline bool
codepoint_isupper<ENCODING::UTF8>(npy_ucs4 code)
{
    return Py_UNICODE_ISUPPER(code);
}

// 声明模板特化,用于判断给定编码下的 Unicode 代码点是否为标题字母
template<ENCODING enc>
inline bool
codepoint_istitle(npy_ucs4);

// 模板特化实现,ASCII 编码下的 Unicode 代码点不支持标题字母的定义,始终返回 false
template<>
inline bool
codepoint_istitle<ENCODING::ASCII>(npy_ucs4 code)
{
    return false;
}

// 模板特化实现,UTF32 编码下的 Unicode 代码点是否为标题字母
template<>
inline bool
codepoint_istitle<ENCODING::UTF32>(npy_ucs4 code)
{
    return Py_UNICODE_ISTITLE(code);
}

// 模板特化实现,UTF8 编码下的 Unicode 代码点是否为标题字母
template<>
inline bool
codepoint_istitle<ENCODING::UTF8>(npy_ucs4 code)
{
    return Py_UNICODE_ISTITLE(code);
}

// 判断给定的 Unicode 代码点是否为数字
inline bool
codepoint_isnumeric(npy_ucs4 code)
{
    return Py_UNICODE_ISNUMERIC(code);
}

// 判断给定的 Unicode 代码点是否为十进制数字
inline bool
codepoint_isdecimal(npy_ucs4 code)
{
    return Py_UNICODE_ISDECIMAL(code);
}
    {
        // 开始一个 switch 结构,根据 enc 的值进行不同的操作
        switch (enc) {
        case ENCODING::ASCII:
            // 如果编码是 ASCII,将 buf 减去 rhs
            buf -= rhs;
            break;
        case ENCODING::UTF32:
            // 如果编码是 UTF32,将 buf 减去 rhs 乘以每个字符的字节数(sizeof(npy_ucs4))
            buf -= rhs * sizeof(npy_ucs4);
            break;
        case ENCODING::UTF8:
            // 如果编码是 UTF8,查找 buf 中前一个 UTF8 字符的位置,并将 buf 设置为该位置
            buf = (char *) find_previous_utf8_character((unsigned char *)buf, (size_t) rhs);
        }
        // 返回当前对象的引用
        return *this;
    }

    inline Buffer<enc>&
    operator++()
    {
        // 前缀递增运算符重载,调用后缀递增运算符重载,然后返回当前对象的引用
        *this += 1;
        return *this;
    }

    inline Buffer<enc>
    operator++(int)
    {
        // 后缀递增运算符重载,保存当前对象的副本,调用前缀递增运算符重载,然后返回保存的副本
        Buffer<enc> old = *this;
        operator++();
        return old;
    }

    inline Buffer<enc>&
    operator--()
    {
        // 前缀递减运算符重载,调用后缀递减运算符重载,然后返回当前对象的引用
        *this -= 1;
        return *this;
    }

    inline Buffer<enc>
    operator--(int)
    {
        // 后缀递减运算符重载,保存当前对象的副本,调用前缀递减运算符重载,然后返回保存的副本
        Buffer<enc> old = *this;
        operator--();
        return old;
    }

    inline npy_ucs4
    operator*()
    {
        // 解引用运算符重载,获取当前位置 buf 的字符并返回
        int bytes;
        return getchar<enc>((unsigned char *) buf, &bytes);
    }

    inline int
    buffer_memcmp(Buffer<enc> other, size_t len)
    {
        // 比较当前对象 buf 和另一个对象 other 的前 len 字节或字符
        if (len == 0) {
            return 0;
        }
        switch (enc) {
            case ENCODING::ASCII:
            case ENCODING::UTF8:
                // 对于 ASCII 和 UTF8,按字节比较 len 长度
                return memcmp(buf, other.buf, len);
            case ENCODING::UTF32:
                // 对于 UTF32,按每个字符占用的字节数进行比较
                return memcmp(buf, other.buf, len * sizeof(npy_ucs4));
        }
    }

    inline void
    buffer_memcpy(Buffer<enc> out, size_t n_chars)
    {
        // 将当前对象 buf 的前 n_chars 个字节或字符复制到目标对象 out 的 buf 中
        if (n_chars == 0) {
            return;
        }
        switch (enc) {
            case ENCODING::ASCII:
            case ENCODING::UTF8:
                // 对于 ASCII 和 UTF8,按字节复制 n_chars 长度
                memcpy(out.buf, buf, n_chars);
                break;
            case ENCODING::UTF32:
                // 对于 UTF32,按每个字符占用的字节数进行复制
                memcpy(out.buf, buf, n_chars * sizeof(npy_ucs4));
                break;
        }
    }

    inline npy_intp
    buffer_memset(npy_ucs4 fill_char, size_t n_chars)
    {
        // 将当前对象 buf 的前 n_chars 个字节或字符设置为 fill_char 所代表的值
        if (n_chars == 0) {
            return 0;
        }
        switch (enc) {
            case ENCODING::ASCII:
                // 对于 ASCII,使用 memset 将 buf 的每个字节设置为 fill_char
                memset(this->buf, fill_char, n_chars);
                return n_chars;
            case ENCODING::UTF32:
            {
                // 对于 UTF32,将 buf 的每个字符设置为 fill_char,每个字符占用 sizeof(npy_ucs4) 字节
                char *tmp = this->buf;
                for (size_t i = 0; i < n_chars; i++) {
                    *(npy_ucs4 *)tmp = fill_char;
                    tmp += sizeof(npy_ucs4);
                }
                return n_chars;
            }
            case ENCODING::UTF8:
            {
                // 对于 UTF8,将 fill_char 转换为 UTF8 编码后,复制 n_chars 个字符到 buf 中
                char utf8_c[4] = {0};
                char *tmp = this->buf;
                size_t num_bytes = ucs4_code_to_utf8_char(fill_char, utf8_c);
                for (size_t i = 0; i < n_chars; i++) {
                    memcpy(tmp, utf8_c, num_bytes);
                    tmp += num_bytes;
                }
                return num_bytes * n_chars;
            }
        }
    }

    inline void
    buffer_fill_with_zeros_after_index(size_t start_index)
    {
        // 将从 start_index 开始之后的缓冲区填充为零
        Buffer<enc> offset = *this + start_index;
        for (char *tmp = offset.buf; tmp < after; tmp++) {
            *tmp = 0;
        }
    }

    inline void
    advance_chars_or_bytes(size_t n) {
        // 根据编码类型前进 n 个字符或字节
        switch (enc) {
            case ENCODING::ASCII:
            case ENCODING::UTF32:
                *this += n;
                break;
            case ENCODING::UTF8:
                this->buf += n;
                break;
        }
    }

    inline size_t
    num_bytes_next_character(void) {
        // 返回下一个字符所占的字节数
        switch (enc) {
            case ENCODING::ASCII:
                return 1;
            case ENCODING::UTF32:
                return 4;
            case ENCODING::UTF8:
                return num_bytes_for_utf8_character((unsigned char *)(*this).buf);
        }
    }

    template<IMPLEMENTED_UNARY_FUNCTIONS f>
    inline bool
    unary_loop()
    {
        // 对每个代码点执行特定的一元操作,直到结束或出现失败
        size_t len = num_codepoints();
        if (len == 0) {
            return false;
        }

        Buffer<enc> tmp = *this;

        for (size_t i=0; i<len; i++) {
            bool result;

            call_buffer_member_function<f, enc, bool> cbmf;

            // 调用特定的一元操作函数
            result = cbmf(tmp);

            if (!result) {
                return false;
            }
            tmp++;
        }
        return true;
    }

    inline bool
    isalpha()
    {
        // 检查是否所有字符都是字母
        return unary_loop<IMPLEMENTED_UNARY_FUNCTIONS::ISALPHA>();
    }

    inline bool
    first_character_isspace()
    {
        // 检查首字符是否为空白字符
        switch (enc) {
            case ENCODING::ASCII:
                return NumPyOS_ascii_isspace(**this);
            case ENCODING::UTF32:
            case ENCODING::UTF8:
                return Py_UNICODE_ISSPACE(**this);
        }
    }

    inline bool
    isspace()
    {
        // 检查是否所有字符都是空白字符
        return unary_loop<IMPLEMENTED_UNARY_FUNCTIONS::ISSPACE>();
    }

    inline bool
    isdigit()
    {
        // 检查是否所有字符都是数字
        return unary_loop<IMPLEMENTED_UNARY_FUNCTIONS::ISDIGIT>();
    }

    inline bool
    isalnum()
    {
        // 检查是否所有字符都是字母或数字
        return unary_loop<IMPLEMENTED_UNARY_FUNCTIONS::ISALNUM>();
    }

    inline bool
    islower()
    {
        // 检查是否所有字符都是小写字母
        size_t len = num_codepoints();
        if (len == 0) {
            return false;
        }

        Buffer<enc> tmp = *this;
        bool cased = 0;
        for (size_t i = 0; i < len; i++) {
            if (codepoint_isupper<enc>(*tmp) || codepoint_istitle<enc>(*tmp)) {
                return false;
            }
            else if (!cased && codepoint_islower<enc>(*tmp)) {
                cased = true;
            }
            tmp++;
        }
        return cased;
    }

    inline bool
    isupper()
    {
        // 获取此缓冲区中的字符数
        size_t len = num_codepoints();
        // 如果字符数为零,返回 false
        if (len == 0) {
            return false;
        }
    
        // 创建缓冲区的临时副本
        Buffer<enc> tmp = *this;
        // 指示是否至少有一个字符为大写
        bool cased = 0;
        // 遍历缓冲区中的每个字符
        for (size_t i = 0; i < len; i++) {
            // 如果字符是小写或标题格式,则返回 false
            if (codepoint_islower<enc>(*tmp) || codepoint_istitle<enc>(*tmp)) {
                return false;
            }
            // 如果之前未遇到大写字符且当前字符是大写,则设置 cased 为 true
            else if (!cased && codepoint_isupper<enc>(*tmp)) {
                cased = true;
            }
            // 移动临时副本到下一个字符位置
            tmp++;
        }
        // 返回是否存在大写字符的标志
        return cased;
    }
    
    inline bool
    istitle()
    {
        // 获取此缓冲区中的字符数
        size_t len = num_codepoints();
        // 如果字符数为零,返回 false
        if (len == 0) {
            return false;
        }
    
        // 创建缓冲区的临时副本
        Buffer<enc> tmp = *this;
        // 指示是否存在标题格式的字符
        bool cased = false;
        // 指示前一个字符是否为标题格式或大写
        bool previous_is_cased = false;
        // 遍历缓冲区中的每个字符
        for (size_t i = 0; i < len; i++) {
            // 如果字符是大写或标题格式
            if (codepoint_isupper<enc>(*tmp) || codepoint_istitle<enc>(*tmp)) {
                // 如果之前已经有字符是标题格式或大写,则返回 false
                if (previous_is_cased) {
                    return false;
                }
                // 设置前一个字符为标题格式或大写
                previous_is_cased = true;
                // 设置 cased 为 true
                cased = true;
            }
            // 如果字符是小写
            else if (codepoint_islower<enc>(*tmp)) {
                // 如果之前没有遇到标题格式或大写字符,则返回 false
                if (!previous_is_cased) {
                    return false;
                }
                // 设置 cased 为 true
                cased = true;
            }
            // 如果字符既不是大写也不是小写
            else {
                // 设置前一个字符不是标题格式或大写
                previous_is_cased = false;
            }
            // 移动临时副本到下一个字符位置
            tmp++;
        }
        // 返回是否存在标题格式的字符的标志
        return cased;
    }
    
    inline bool
    isnumeric()
    {
        // 调用 unary_loop 函数检查是否存在数值字符
        return unary_loop<IMPLEMENTED_UNARY_FUNCTIONS::ISNUMERIC>();
    }
    
    inline bool
    isdecimal()
    {
        // 调用 unary_loop 函数检查是否存在十进制字符
        return unary_loop<IMPLEMENTED_UNARY_FUNCTIONS::ISDECIMAL>();
    }
    
    inline Buffer<enc>
    rstrip()
    {
        // 创建缓冲区的临时副本
        Buffer<enc> tmp(after, 0);
        // 将 tmp 移动到末尾字符的前一个位置
        tmp--;
        // 移除尾部的空白字符或者 '\0'
        while (tmp >= *this && (*tmp == '\0' || NumPyOS_ascii_isspace(*tmp))) {
            tmp--;
        }
        // 将 after 指向 tmp 的缓冲区
        after = tmp.buf;
        // 返回原始缓冲区
        return *this;
    }
    
    inline int
    strcmp(Buffer<enc> other, bool rstrip)
    {
        // 如果 rstrip 为 true,则对当前对象和 other 对象执行 rstrip 操作
        Buffer tmp1 = rstrip ? this->rstrip() : *this;
        Buffer tmp2 = rstrip ? other.rstrip() : other;
    
        // 比较两个缓冲区中的字符内容
        while (tmp1.buf < tmp1.after && tmp2.buf < tmp2.after) {
            // 如果 tmp1 中的字符小于 tmp2 中的字符,返回 -1
            if (*tmp1 < *tmp2) {
                return -1;
            }
            // 如果 tmp1 中的字符大于 tmp2 中的字符,返回 1
            if (*tmp1 > *tmp2) {
                return 1;
            }
            // 移动 tmp1 和 tmp2 到下一个字符位置
            tmp1++;
            tmp2++;
        }
        // 如果 tmp1 还有剩余字符且不为 '\0',返回 1
        while (tmp1.buf < tmp1.after) {
            if (*tmp1) {
                return 1;
            }
            tmp1++;
        }
        // 如果 tmp2 还有剩余字符且不为 '\0',返回 -1
        while (tmp2.buf < tmp2.after) {
            if (*tmp2) {
                return -1;
            }
            tmp2++;
        }
        // 如果两个缓冲区内容相同,返回 0
        return 0;
    }
    
    inline int
    strcmp(Buffer<enc> other)
    {
        // 调用带 rstrip 参数为 false 的 strcmp 函数
        return strcmp(other, false);
    }
// 结构模板,用于调用缓冲区成员函数的特定操作
template <IMPLEMENTED_UNARY_FUNCTIONS f, ENCODING enc, typename T>
struct call_buffer_member_function {
    // 重载函数调用操作符,根据给定的操作选择并调用对应的代码点检查函数
    T operator()(Buffer<enc> buf) {
        switch (f) {
            case IMPLEMENTED_UNARY_FUNCTIONS::ISALPHA:
                return codepoint_isalpha<enc>(*buf);
            case IMPLEMENTED_UNARY_FUNCTIONS::ISDIGIT:
                return codepoint_isdigit<enc>(*buf);
            case IMPLEMENTED_UNARY_FUNCTIONS::ISSPACE:
                return codepoint_isspace<enc>(*buf);
            case IMPLEMENTED_UNARY_FUNCTIONS::ISALNUM:
                return codepoint_isalnum<enc>(*buf);
            case IMPLEMENTED_UNARY_FUNCTIONS::ISNUMERIC:
                return codepoint_isnumeric(*buf);
            case IMPLEMENTED_UNARY_FUNCTIONS::ISDECIMAL:
                return codepoint_isdecimal(*buf);
        }
    }
};

// 重载加法操作符,用于将缓冲区和一个整数相加
template <ENCODING enc>
inline Buffer<enc>
operator+(Buffer<enc> lhs, npy_int64 rhs)
{
    switch (enc) {
        case ENCODING::ASCII:
            // 返回一个新的缓冲区,偏移 rhs 个字节后
            return Buffer<enc>(lhs.buf + rhs, lhs.after - lhs.buf - rhs);
        case ENCODING::UTF32:
            // 返回一个新的 UTF32 编码的缓冲区,偏移 rhs 个字符后
            return Buffer<enc>(lhs.buf + rhs * sizeof(npy_ucs4),
                          lhs.after - lhs.buf - rhs * sizeof(npy_ucs4));
        case ENCODING::UTF8:
            char* buf = lhs.buf;
            // 迭代偏移 rhs 次,找到新位置的 UTF8 字符的起始位置
            for (int i=0; i<rhs; i++) {
                buf += num_bytes_for_utf8_character((unsigned char *)buf);
            }
            // 返回一个新的 UTF8 编码的缓冲区,偏移后的长度
            return Buffer<enc>(buf, (npy_int64)(lhs.after - buf));
    }
}

// 重载减法操作符,用于将缓冲区和一个整数相减
template <ENCODING enc>
inline std::ptrdiff_t
operator-(Buffer<enc> lhs, Buffer<enc> rhs)
{
    switch (enc) {
    case ENCODING::ASCII:
    case ENCODING::UTF8:
        // 返回两个缓冲区指针之间的偏移量
        // 对于 UTF8 字符串,除非比较的是同一字符串中的两个位置,否则结果可能无意义
        return lhs.buf - rhs.buf;
    case ENCODING::UTF32:
        // 返回两个 UTF32 编码的缓冲区指针之间的偏移量,以字符数表示
        return (lhs.buf - rhs.buf) / (std::ptrdiff_t) sizeof(npy_ucs4);
    }
}

// 重载减法操作符,用于将缓冲区和一个整数相减
template <ENCODING enc>
inline Buffer<enc>
operator-(Buffer<enc> lhs, npy_int64 rhs)
{
    switch (enc) {
        case ENCODING::ASCII:
            // 返回一个新的缓冲区,偏移 rhs 个字节前
            return Buffer<enc>(lhs.buf - rhs, lhs.after - lhs.buf + rhs);
        case ENCODING::UTF32:
            // 返回一个新的 UTF32 编码的缓冲区,偏移 rhs 个字符前
            return Buffer<enc>(lhs.buf - rhs * sizeof(npy_ucs4),
                          lhs.after - lhs.buf + rhs * sizeof(npy_ucs4));
        case ENCODING::UTF8:
            char* buf = lhs.buf;
            // 找到从当前位置往前偏移 rhs 个字符后的 UTF8 字符的起始位置
            buf = (char *)find_previous_utf8_character((unsigned char *)buf, rhs);
            // 返回一个新的 UTF8 编码的缓冲区,偏移后的长度
            return Buffer<enc>(buf, (npy_int64)(lhs.after - buf));
    }
}

// 重载相等比较操作符,用于比较两个缓冲区是否相等
template <ENCODING enc>
inline bool
operator==(Buffer<enc> lhs, Buffer<enc> rhs)
{
    return lhs.buf == rhs.buf;
}

// 重载不等比较操作符,用于比较两个缓冲区是否不相等
template <ENCODING enc>
inline bool
operator!=(Buffer<enc> lhs, Buffer<enc> rhs)
{
    return !(rhs == lhs);
}

// 重载小于比较操作符,用于比较两个缓冲区的大小关系
template <ENCODING enc>
inline bool
operator<(Buffer<enc> lhs, Buffer<enc> rhs)
{
    return lhs.buf < rhs.buf;
}

// 重载大于比较操作符,用于比较两个缓冲区的大小关系
template <ENCODING enc>
inline bool
operator>(Buffer<enc> lhs, Buffer<enc> rhs)
{
    return rhs < lhs;
}

// 未完成的模板函数声明
template <ENCODING enc>
inline bool
/*
 * Operator <= for Buffer objects.
 *
 * This function provides the less than or equal to comparison
 * for Buffer objects. It delegates to the negation of the
 * greater than operator for the implementation.
 */
operator<=(Buffer<enc> lhs, Buffer<enc> rhs)
{
    return !(lhs > rhs);
}

/*
 * Operator >= for Buffer objects.
 *
 * This function provides the greater than or equal to comparison
 * for Buffer objects. It delegates to the negation of the
 * less than operator for the implementation.
 */
template <ENCODING enc>
inline bool
operator>=(Buffer<enc> lhs, Buffer<enc> rhs)
{
    return !(lhs < rhs);
}

/*
 * Helper function to adjust start/end slice values.
 *
 * This function adjusts start and end slice indices to ensure
 * they are within valid bounds for a given length. It modifies
 * the start and end values accordingly based on Python's slicing
 * rules to handle negative indices and bounds exceeding length.
 */
static inline void
adjust_offsets(npy_int64 *start, npy_int64 *end, size_t len)
{
    if (*end > static_cast<npy_int64>(len)) {
        *end = len;
    }
    else if (*end < 0) {
        *end += len;
        if (*end < 0) {
            *end = 0;
        }
    }

    if (*start < 0) {
        *start += len;
        if (*start < 0) {
            *start = 0;
        }
    }
}

/*
 * Find function for strings in a given encoding.
 *
 * This function searches for buf2 within buf1 using start and end
 * indices. It handles different encodings (UTF8, ASCII, UTF32) and
 * adjusts the search indices using adjust_offsets() for compatibility
 * with Python's str functions. It returns the index of the first occurrence
 * of buf2 in buf1[start:end], or -1 if not found.
 */
template <ENCODING enc>
static inline npy_intp
string_find(Buffer<enc> buf1, Buffer<enc> buf2, npy_int64 start, npy_int64 end)
{
    size_t len1 = buf1.num_codepoints();
    size_t len2 = buf2.num_codepoints();

    // Adjust start and end indices to fit within the length of buf1
    adjust_offsets(&start, &end, len1);

    // If buf2 is longer than the slice [start:end], return -1
    if (end - start < static_cast<npy_int64>(len2)) {
        return (npy_intp) -1;
    }

    // If buf2 is empty, return the start index
    if (len2 == 0) {
        return (npy_intp) start;
    }

    char *start_loc = NULL;
    char *end_loc = NULL;

    // Depending on encoding, set start_loc and end_loc appropriately
    if (enc == ENCODING::UTF8) {
        find_start_end_locs(buf1.buf, (buf1.after - buf1.buf), start, end,
                            &start_loc, &end_loc);
    }
    else {
        start_loc = (buf1 + start).buf;
        end_loc = (buf1 + end).buf;
    }

    // Handle the case of searching for a single character
    if (len2 == 1) {
        npy_intp result;
        switch (enc) {
            case ENCODING::UTF8:
            {
                // Handle UTF8 characters that span multiple bytes
                if (num_bytes_for_utf8_character((const unsigned char *)buf2.buf) > 1) {
                    goto multibyte_search;
                }
                // fall through to the ASCII case because this is a one-byte character
            }
            case ENCODING::ASCII:
            {
                char ch = *buf2;
                CheckedIndexer<char> ind(start_loc, end_loc - start_loc);
                result = (npy_intp) findchar(ind, end_loc - start_loc, ch);
                // Adjust result index for UTF8 encoding if necessary
                if (enc == ENCODING::UTF8 && result > 0) {
                    result = utf8_character_index(
                            start_loc, start_loc - buf1.buf, start, result,
                            buf1.after - start_loc);
                }
                break;
            }
            case ENCODING::UTF32:
            {
                npy_ucs4 ch = *buf2;
                CheckedIndexer<npy_ucs4> ind((npy_ucs4 *)(buf1 + start).buf, end-start);
                result = (npy_intp) findchar(ind, end - start, ch);
                break;
            }
        }
        // Return -1 if character not found, otherwise return adjusted index
        if (result == -1) {
            return (npy_intp) -1;
        }
        else {
            return result + (npy_intp) start;
        }
    }

  multibyte_search:

    npy_intp pos;
    // 根据不同的编码格式进行搜索
    switch(enc) {
        case ENCODING::UTF8:
            // 如果是UTF-8编码,使用快速搜索算法在buf2中查找子串位置
            pos = fastsearch(start_loc, end_loc - start_loc, buf2.buf, buf2.after - buf2.buf, -1, FAST_SEARCH);
            // pos 是字节索引,需要转换为字符索引
            if (pos > 0) {
                pos = utf8_character_index(start_loc, start_loc - buf1.buf, start, pos, buf1.after - start_loc);
            }
            break;
        case ENCODING::ASCII:
            // 如果是ASCII编码,使用快速搜索算法在buf2中查找子串位置
            pos = fastsearch(start_loc, end - start, buf2.buf, len2, -1, FAST_SEARCH);
            break;
        case ENCODING::UTF32:
            // 如果是UTF-32编码,使用快速搜索算法在buf2中查找子串位置(类型转换为npy_ucs4*)
            pos = fastsearch((npy_ucs4 *)start_loc, end - start,
                             (npy_ucs4 *)buf2.buf, len2, -1, FAST_SEARCH);
            break;
    }

    // 如果找到了匹配的位置,转换为全局索引
    if (pos >= 0) {
        pos += start;
    }
    // 返回搜索到的位置
    return pos;
/* 
   定义了一个模板函数 string_index,用于在 buf1 中查找 buf2 的子串,
   并返回其在 buf1 中的索引位置。如果未找到子串,则抛出异常并返回 -2。
*/
template <ENCODING enc>
static inline npy_intp
string_index(Buffer<enc> buf1, Buffer<enc> buf2, npy_int64 start, npy_int64 end)
{
    // 调用 string_find 函数在 buf1 中查找 buf2 的位置
    npy_intp pos = string_find(buf1, buf2, start, end);
    // 如果找不到子串,则抛出 ValueError 异常并返回 -2
    if (pos == -1) {
        npy_gil_error(PyExc_ValueError, "substring not found");
        return -2;
    }
    // 返回找到的子串在 buf1 中的索引位置
    return pos;
}

/* 
   定义了一个模板函数 string_rfind,用于在 buf1 中逆向查找 buf2 的子串,
   并返回其在 buf1 中的索引位置。如果未找到子串或条件不符合,则返回 -1。
*/
template <ENCODING enc>
static inline npy_intp
string_rfind(Buffer<enc> buf1, Buffer<enc> buf2, npy_int64 start, npy_int64 end)
{
    // 获取 buf1 和 buf2 的字符数
    size_t len1 = buf1.num_codepoints();
    size_t len2 = buf2.num_codepoints();

    // 调整查找范围的起始和结束位置,确保不超出 buf1 的长度范围
    adjust_offsets(&start, &end, len1);
    
    // 如果查找范围内的长度小于 buf2 的长度,则直接返回 -1
    if (end - start < static_cast<npy_int64>(len2)) {
        return (npy_intp) -1;
    }

    // 如果 buf2 的长度为 0,则返回查找的结束位置 end
    if (len2 == 0) {
        return (npy_intp) end;
    }

    // 初始化起始和结束位置的指针
    char *start_loc = NULL;
    char *end_loc = NULL;
    
    // 根据编码类型选择不同的查找函数和位置计算方式
    if (enc == ENCODING::UTF8) {
        // 如果是 UTF-8 编码,则调用 find_start_end_locs 函数获取起始和结束位置的指针
        find_start_end_locs(buf1.buf, (buf1.after - buf1.buf), start, end,
                            &start_loc, &end_loc);
    }
    else {
        // 其他编码方式则直接计算起始和结束位置的指针
        start_loc = (buf1 + start).buf;
        end_loc = (buf1 + end).buf;
    }

    // 如果 buf2 的长度为 1,则根据不同的编码类型选择不同的查找方式
    if (len2 == 1) {
        npy_intp result;
        switch (enc) {
            case ENCODING::UTF8:
            {
                // 如果是 UTF-8 编码并且 buf2 是多字节字符,则跳转到 multibyte_search 分支
                if (num_bytes_for_utf8_character((const unsigned char *)buf2.buf) > 1) {
                    goto multibyte_search;
                }
                // 单字节字符则继续 ASCII 查找
            }
            // ASCII 编码的情况
            case ENCODING::ASCII:
            {
                // 获取 buf2 的第一个字符
                char ch = *buf2;
                // 初始化 CheckedIndexer 对象,用于安全地访问字符数组
                CheckedIndexer<char> ind(start_loc, end_loc - start_loc);
                // 在 [start_loc, end_loc) 范围内逆向查找字符 ch,并返回索引位置
                result = (npy_intp) rfindchar(ind, end_loc - start_loc, ch);
                // 如果是 UTF-8 编码并且找到了字符,则调整结果索引为字符的实际位置
                if (enc == ENCODING::UTF8 && result > 0) {
                    result = utf8_character_index(
                            start_loc, start_loc - buf1.buf, start, result,
                            buf1.after - start_loc);
                }
                break;
            }
            // UTF-32 编码的情况
            case ENCODING::UTF32:
            {
                // 获取 buf2 的第一个字符
                npy_ucs4 ch = *buf2;
                // 初始化 CheckedIndexer 对象,用于安全地访问 UCS-4 编码字符数组
                CheckedIndexer<npy_ucs4> ind((npy_ucs4 *)(buf1 + start).buf, end - start);
                // 在 [start, end) 范围内逆向查找字符 ch,并返回索引位置
                result = (npy_intp) rfindchar(ind, end - start, ch);
                break;
            }
        }
        // 如果未找到字符,则返回 -1;否则返回字符的实际位置加上起始位置 start
        if (result == -1) {
            return (npy_intp) -1;
        }
        else {
            return result + (npy_intp) start;
        }
    }

  multibyte_search:

    npy_intp pos;
    switch (enc) {
        case ENCODING::UTF8:
            // 在 buf2 中快速搜索 start_loc 到 end_loc 之间的内容
            pos = fastsearch(start_loc, end_loc - start_loc, buf2.buf, buf2.after - buf2.buf, -1, FAST_RSEARCH);
            // pos 是字节索引,需要转换为字符索引
            if (pos > 0) {
                // 根据 UTF-8 编码,计算字符索引
                pos = utf8_character_index(start_loc, start_loc - buf1.buf, start, pos, buf1.after - start_loc);
            }
            break;
        case ENCODING::ASCII:
            // 在 buf2 中快速搜索 start 到 end 之间的内容
            pos = (npy_intp) fastsearch(start_loc, end - start, buf2.buf, len2, -1, FAST_RSEARCH);
            break;
        case ENCODING::UTF32:
            // 在 buf2 中快速搜索 start 到 end 之间的 UTF-32 编码内容
            pos = (npy_intp) fastsearch((npy_ucs4 *)start_loc, end - start,
                                        (npy_ucs4 *)buf2.buf, len2, -1, FAST_RSEARCH);
            break;
    }
    // 如果找到位置 pos,则将其转换为全局字符索引
    if (pos >= 0) {
        pos += start;
    }
    // 返回最终的位置索引
    return pos;
/*
 * string_rindex: Searches for the last occurrence of buf2 in buf1 within the range [start, end).
 * Returns the index of the occurrence or -2 if not found (with an exception raised).
 */
template <ENCODING enc>
static inline npy_intp
string_rindex(Buffer<enc> buf1, Buffer<enc> buf2, npy_int64 start, npy_int64 end)
{
    // Find the last occurrence of buf2 in buf1
    npy_intp pos = string_rfind(buf1, buf2, start, end);
    // Handle case where substring is not found
    if (pos == -1) {
        npy_gil_error(PyExc_ValueError, "substring not found");
        return -2;
    }
    // Return the index of the last occurrence
    return pos;
}

/*
 * string_count: Counts occurrences of buf2 in buf1 within the range [start, end).
 * Returns the count of occurrences.
 */
template <ENCODING enc>
static inline npy_intp
string_count(Buffer<enc> buf1, Buffer<enc> buf2, npy_int64 start, npy_int64 end)
{
    size_t len1 = buf1.num_codepoints();
    size_t len2 = buf2.num_codepoints();

    // Adjust start and end positions based on buffer lengths
    adjust_offsets(&start, &end, len1);
    
    // If the search range is invalid or empty, return 0 occurrences
    if (end < start || end - start < static_cast<npy_int64>(len2)) {
        return (npy_intp) 0;
    }

    // Handle case where buf2 is empty
    if (len2 == 0) {
        return (end - start) < PY_SSIZE_T_MAX ? end - start + 1 : PY_SSIZE_T_MAX;
    }

    char *start_loc = NULL;
    char *end_loc = NULL;

    // Determine start and end positions based on encoding type
    if (enc == ENCODING::UTF8) {
        find_start_end_locs(buf1.buf, (buf1.after - buf1.buf), start, end,
                            &start_loc, &end_loc);
    }
    else {
        start_loc = (buf1 + start).buf;
        end_loc = (buf1 + end).buf;
    }

    npy_intp count;
    // Perform fast search based on encoding type
    switch (enc) {
        case ENCODING::UTF8:
            count = fastsearch(start_loc, end_loc - start_loc, buf2.buf,
                               buf2.after - buf2.buf, PY_SSIZE_T_MAX,
                               FAST_COUNT);
            break;
        case ENCODING::ASCII:
            count = (npy_intp) fastsearch(start_loc, end - start, buf2.buf, len2,
                                          PY_SSIZE_T_MAX, FAST_COUNT);
            break;
        case ENCODING::UTF32:
            count = (npy_intp) fastsearch((npy_ucs4 *)start_loc, end - start,
                                          (npy_ucs4 *)buf2.buf, len2,
                                          PY_SSIZE_T_MAX, FAST_COUNT);
            break;
    }

    // Return 0 if an error occurred during search
    if (count < 0) {
        return 0;
    }
    // Return the count of occurrences found
    return count;
}

/*
 * tailmatch: Checks if buf2 matches the end of buf1 within the specified range [start, end).
 * Returns true (1) if there's a match, otherwise false (0).
 */
template <ENCODING enc>
inline npy_bool
tailmatch(Buffer<enc> buf1, Buffer<enc> buf2, npy_int64 start, npy_int64 end,
          STARTPOSITION direction)
{
    size_t len1 = buf1.num_codepoints();
    size_t len2 = buf2.num_codepoints();

    // Adjust start and end positions based on buffer lengths
    adjust_offsets(&start, &end, len1);
    
    // Calculate the position to start checking for tail match
    end -= len2;
    if (end < start) {
        return 0;
    }

    // Handle case where buf2 is empty, always return true
    if (len2 == 0) {
        return 1;
    }

    size_t offset;
    size_t end_sub = len2 - 1;

    // Determine offset based on direction of search (front or back)
    if (direction == STARTPOSITION::BACK) {
        offset = end;
    }
    else {
        offset = start;
    }

    size_t size2 = len2;

    // Adjust size2 for UTF8 encoding
    if (enc == ENCODING::UTF8) {
        size2 = (buf2.after - buf2.buf);
    }

    // Create buffer slices for comparison
    Buffer start_buf = (buf1 + offset);
    Buffer end_buf = start_buf + end_sub;

    // Check if the buffers match at the start and end positions
    if (*start_buf == *buf2 && *end_buf == *(buf2 + end_sub)) {
        return !start_buf.buffer_memcmp(buf2, size2);
    }

    // Default return indicating no match

    // Return false indicating no match
    return 0;
}
    return 0;
}

// 枚举类型,表示字符串修剪的类型,可以是左修剪、右修剪或者两者结合
enum class STRIPTYPE {
    LEFTSTRIP, RIGHTSTRIP, BOTHSTRIP
};

// 模板函数,用于去除字符串两端的空白字符
template <ENCODING enc>
static inline size_t
string_lrstrip_whitespace(Buffer<enc> buf, Buffer<enc> out, STRIPTYPE striptype)
{
    // 获取字符串的字符数
    size_t len = buf.num_codepoints();
    
    // 如果字符串长度为0
    if (len == 0) {
        // 如果编码不是UTF-8,则将输出缓冲区填充为零
        if (enc != ENCODING::UTF8) {
            out.buffer_fill_with_zeros_after_index(0);
        }
        return 0;  // 返回修剪后的长度
    }

    size_t i = 0;

    // 计算输入缓冲区的字节数
    size_t num_bytes = (buf.after - buf.buf);
    Buffer traverse_buf = Buffer<enc>(buf.buf, num_bytes);

    // 如果不是右修剪类型,则从左端开始移除空白字符
    if (striptype != STRIPTYPE::RIGHTSTRIP) {
        while (i < len) {
            if (!traverse_buf.first_character_isspace()) {
                break;
            }
            num_bytes -= traverse_buf.num_bytes_next_character();
            traverse_buf++;
            i++;
        }
    }

    npy_intp j = len - 1;  // j表示从右端开始的索引,如果整个字符串都被修剪,则可能变成负数
    if (enc == ENCODING::UTF8) {
        traverse_buf = Buffer<enc>(buf.after, 0) - 1;  // UTF-8编码时,从尾部开始处理
    }
    else {
        traverse_buf = buf + j;  // 其他编码,从末尾字符开始处理
    }

    // 如果不是左修剪类型,则从右端开始移除空白字符
    if (striptype != STRIPTYPE::LEFTSTRIP) {
        while (j >= static_cast<npy_intp>(i)) {
            if (*traverse_buf != 0 && !traverse_buf.first_character_isspace()) {
                break;
            }
            num_bytes -= traverse_buf.num_bytes_next_character();
            traverse_buf--;
            j--;
        }
    }

    Buffer offset_buf = buf + i;  // 根据i偏移得到修剪后的起始位置
    if (enc == ENCODING::UTF8) {
        offset_buf.buffer_memcpy(out, num_bytes);  // 将修剪后的字符串复制到输出缓冲区
        return num_bytes;  // 返回修剪后的长度
    }
    offset_buf.buffer_memcpy(out, j - i + 1);  // 将修剪后的字符串复制到输出缓冲区
    out.buffer_fill_with_zeros_after_index(j - i + 1);  // 将剩余部分填充为零
    return j - i + 1;  // 返回修剪后的长度
}

// 模板函数,用于根据指定的字符集合修剪字符串的两端字符
template <ENCODING enc>
static inline size_t
string_lrstrip_chars(Buffer<enc> buf1, Buffer<enc> buf2, Buffer<enc> out, STRIPTYPE striptype)
{
    // 获取第一个缓冲区的字符数
    size_t len1 = buf1.num_codepoints();
    // 如果第一个缓冲区长度为0
    if (len1 == 0) {
        // 如果编码是UTF-8,则将整个第一个缓冲区复制到输出缓冲区
        if (enc == ENCODING::UTF8) {
            buf1.buffer_memcpy(out, (buf1.after - buf1.buf));
            return buf1.after - buf1.buf;
        }
        // 否则,将第一个缓冲区的长度复制到输出缓冲区,并填充剩余部分为零
        buf1.buffer_memcpy(out, len1);
        out.buffer_fill_with_zeros_after_index(len1);
        return len1;
    }

    size_t i = 0;

    // 获取第一个缓冲区的字节数
    size_t num_bytes = (buf1.after - buf1.buf);
    Buffer traverse_buf = Buffer<enc>(buf1.buf, num_bytes);

    // 确定字符串开始修剪的位置
    if (striptype != STRIPTYPE::RIGHTSTRIP) {
        while (i < len1) {
            // 如果第一个缓冲区的第一个字符不是指定的字符集合中的空白字符,则停止修剪
            if (!traverse_buf.first_character_isspace()) {
                break;
            }
            num_bytes -= traverse_buf.num_bytes_next_character();
            traverse_buf++;
            i++;
        }
    }

    // 获取第二个缓冲区的字符数
    size_t len2 = buf2.num_codepoints();
    // 如果第二个缓冲区长度为0
    if (len2 == 0) {
        // 如果编码是UTF-8,则将整个第一个缓冲区复制到输出缓冲区
        if (enc == ENCODING::UTF8) {
            buf1.buffer_memcpy(out, (buf1.after - buf1.buf));
            return buf1.after - buf1.buf;
        }
        // 否则,将第一个缓冲区的长度复制到输出缓冲区,并填充剩余部分为零
        buf1.buffer_memcpy(out, len1);
        out.buffer_fill_with_zeros_after_index(len1);
        return len1;
    }

    Buffer offset_buf = buf1 + i;  // 根据i偏移得到修剪后的起始位置
    if (enc == ENCODING::UTF8) {
        offset_buf.buffer_memcpy(out, num_bytes);  // 将修剪后的字符串复制到输出缓冲区
        return num_bytes;  // 返回修剪后的长度
    }
    offset_buf.buffer_memcpy(out, len1);  // 将修剪后的字符串复制到输出缓冲区
    out.buffer_fill_with_zeros_after_index(len1);  // 将剩余部分填充为零
    return len1;  // 返回修剪后的长度
}
    # 如果不是右侧去除空格类型,则执行以下代码块
    if (striptype != STRIPTYPE::RIGHTSTRIP) {
        # 循环直到 i 小于 len1
        while (i < len1) {
            # 声明一个 Py_ssize_t 类型的变量 res
            Py_ssize_t res;
            # 根据编码类型进行不同处理
            switch (enc) {
                # 对于 ASCII 和 UTF8 编码
                case ENCODING::ASCII:
                case ENCODING::UTF8:
                {
                    # 使用 CheckedIndexer<char> 对象 ind,索引 buf2.buf 的前 len2 个元素
                    CheckedIndexer<char> ind(buf2.buf, len2);
                    # 调用 findchar<char> 函数,在 ind 中查找 traverse_buf 指向的字符
                    res = findchar<char>(ind, len2, *traverse_buf);
                    break;
                }
                # 对于 UTF32 编码
                case ENCODING::UTF32:
                {
                    # 使用 CheckedIndexer<npy_ucs4> 对象 ind,索引 buf2.buf 的前 len2 个元素
                    CheckedIndexer<npy_ucs4> ind((npy_ucs4 *)buf2.buf, len2);
                    # 调用 findchar<npy_ucs4> 函数,在 ind 中查找 traverse_buf 指向的字符
                    res = findchar<npy_ucs4>(ind, len2, *traverse_buf);
                    break;
                }
            }
            # 如果未找到目标字符,则跳出循环
            if (res < 0) {
                break;
            }
            # 更新 num_bytes,减去 traverse_buf 下一个字符的字节数
            num_bytes -= traverse_buf.num_bytes_next_character();
            # traverse_buf 向后移动一个位置
            traverse_buf++;
            # i 自增
            i++;
        }
    }

    # 初始化 j 为 len1 减 1
    npy_intp j = len1 - 1;
    # 如果编码类型是 UTF8
    if (enc == ENCODING::UTF8) {
        # 将 traverse_buf 指向 Buffer<enc>(buf1.after, 0) 的前一个位置
        traverse_buf = Buffer<enc>(buf1.after, 0) - 1;
    }
    # 否则
    else {
        # 将 traverse_buf 指向 buf1 的末尾
        traverse_buf = buf1 + j;
    }

    # 如果不是左侧去除空格类型,则执行以下代码块
    if (striptype != STRIPTYPE::LEFTSTRIP) {
        # 循环直到 j 大于等于 i
        while (j >= static_cast<npy_intp>(i)) {
            # 声明一个 Py_ssize_t 类型的变量 res
            Py_ssize_t res;
            # 根据编码类型进行不同处理
            switch (enc) {
                # 对于 ASCII 和 UTF8 编码
                case ENCODING::ASCII:
                case ENCODING::UTF8:
                {
                    # 使用 CheckedIndexer<char> 对象 ind,索引 buf2.buf 的前 len2 个元素
                    CheckedIndexer<char> ind(buf2.buf, len2);
                    # 调用 findchar<char> 函数,在 ind 中查找 traverse_buf 指向的字符
                    res = findchar<char>(ind, len2, *traverse_buf);
                    break;
                }
                # 对于 UTF32 编码
                case ENCODING::UTF32:
                {
                    # 使用 CheckedIndexer<npy_ucs4> 对象 ind,索引 buf2.buf 的前 len2 个元素
                    CheckedIndexer<npy_ucs4> ind((npy_ucs4 *)buf2.buf, len2);
                    # 调用 findchar<npy_ucs4> 函数,在 ind 中查找 traverse_buf 指向的字符
                    res = findchar<npy_ucs4>(ind, len2, *traverse_buf);
                    break;
                }
            }
            # 如果未找到目标字符,则跳出循环
            if (res < 0) {
                break;
            }
            # 更新 num_bytes,减去 traverse_buf 下一个字符的字节数
            num_bytes -= traverse_buf.num_bytes_next_character();
            # j 自减
            j--;
            # 如果 j 大于 0,则 traverse_buf 向前移动一个位置
            if (j > 0) {
                traverse_buf--;
            }
        }
    }

    # 将 offset_buf 初始化为 buf1 + i
    Buffer offset_buf = buf1 + i;
    # 如果编码类型是 UTF8
    if (enc == ENCODING::UTF8) {
        # 将 offset_buf 的数据拷贝到 out 中,并返回 num_bytes
        offset_buf.buffer_memcpy(out, num_bytes);
        return num_bytes;
    }
    # 否则
    offset_buf.buffer_memcpy(out, j - i + 1);
    # 将 out 中索引为 j - i + 1 之后的位置填充为零
    out.buffer_fill_with_zeros_after_index(j - i + 1);
    # 返回 j - i + 1
    return j - i + 1;
// 如果要替换的字符串为空,则直接返回索引 0
template <typename char_type>
static inline npy_intp
findslice_for_replace(CheckedIndexer<char_type> buf1, npy_intp len1,
                      CheckedIndexer<char_type> buf2, npy_intp len2)
{
    if (len2 == 0) {
        return 0;
    }
    // 如果要替换的字符串长度为 1,则在 buf1 中查找该字符的位置并返回索引
    if (len2 == 1) {
        return (npy_intp) findchar(buf1, len1, *buf2);
    }
    // 使用快速搜索算法在 buf1 中查找 buf2,并返回第一个匹配的位置索引
    return (npy_intp) fastsearch(buf1.buffer, len1, buf2.buffer, len2, -1, FAST_SEARCH);
}

// 根据不同的编码方式进行字符串替换操作
template <ENCODING enc>
static inline size_t
string_replace(Buffer<enc> buf1, Buffer<enc> buf2, Buffer<enc> buf3, npy_int64 count,
               Buffer<enc> out)
{
    size_t len1 = buf1.num_codepoints();  // 获取 buf1 的字符数
    size_t len2 = buf2.num_codepoints();  // 获取 buf2 的字符数
    size_t len3 = buf3.num_codepoints();  // 获取 buf3 的字符数
    char *start;
    size_t length = len1;
    // 根据编码类型确定起始位置 start
    if (enc == ENCODING::UTF8) {
        start = buf1.after;  // UTF8 编码的起始位置为 buf1 的末尾后面
        length = 0;  // 针对 UTF8 编码,长度设为 0
    }
    else if (enc == ENCODING::UTF32) {
        start = buf1.buf + sizeof(npy_ucs4) * len1;  // UTF32 编码的起始位置为 buf1 末尾加上 len1 个 UCS4 字节长度
    }
    else {
        start = buf1.buf + len1;  // 其他编码的起始位置为 buf1 末尾
    }

    Buffer<enc> end1(start, length);  // 根据起始位置和长度创建 Buffer 对象 end1
    size_t span2, span3;

    switch(enc) {
        case ENCODING::ASCII:
        case ENCODING::UTF32:
        {
            span2 = len2;  // 对于 ASCII 和 UTF32 编码,span2 设为 len2
            span3 = len3;  // 对于 ASCII 和 UTF32 编码,span3 设为 len3
            break;
        }
        case ENCODING::UTF8:
        {
            span2 = buf2.after - buf2.buf;  // 对于 UTF8 编码,span2 是 buf2 的长度
            span3 = buf3.after - buf3.buf;  // 对于 UTF8 编码,span3 是 buf3 的长度
            break;
        }
    }

    size_t ret = 0;

    // 只有在替换次数 count 大于 0 且满足一些条件时才尝试进行替换操作
    if (count <= 0                      // 没有需要替换的内容
        || len1 < len2                  // 输入太小无法匹配
        || (len2 <= 0 && len3 <= 0)     // 匹配和替换字符串均为空
        || (len2 == len3 && buf2.strcmp(buf3) == 0)) {  // 匹配和替换字符串相同
        goto copy_rest;  // 跳转到 copy_rest 标签处,执行剩余复制操作
    }
    // 如果需要替换的字符串长度大于 0,则执行以下逻辑
    if (len2 > 0) {
        // 循环处理每个时间戳
        for (npy_int64 time = 0; time < count; time++) {
            npy_intp pos;  // 定义位置变量

            // 根据编码类型选择合适的索引器
            switch (enc) {
                case ENCODING::ASCII:
                case ENCODING::UTF8:
                {
                    // 使用 CheckedIndexer 处理 buf1 和 buf2,获取替换位置
                    CheckedIndexer<char> ind1(buf1.buf, end1 - buf1);
                    CheckedIndexer<char> ind2(buf2.buf, span2);
                    pos = findslice_for_replace(ind1, end1 - buf1, ind2, span2);
                    break;
                }
                case ENCODING::UTF32:
                {
                    // 使用 CheckedIndexer 处理 buf1 和 buf2,获取替换位置
                    CheckedIndexer<npy_ucs4> ind1((npy_ucs4 *)buf1.buf, end1 - buf1);
                    CheckedIndexer<npy_ucs4> ind2((npy_ucs4 *)buf2.buf, span2);
                    pos = findslice_for_replace(ind1, end1 - buf1, ind2, span2);
                    break;
                }
            }

            // 如果未找到替换位置,跳出循环
            if (pos < 0) {
                break;
            }

            // 将 buf1 的数据拷贝到 out,更新相关变量
            buf1.buffer_memcpy(out, pos);
            ret += pos;
            out.advance_chars_or_bytes(pos);
            buf1.advance_chars_or_bytes(pos);

            // 将 buf3 的数据拷贝到 out,更新相关变量
            buf3.buffer_memcpy(out, span3);
            ret += span3;
            out.advance_chars_or_bytes(span3);
            buf1.advance_chars_or_bytes(span2);
        }
    }
    else {  // 如果匹配字符串为空,则执行交替处理
        // 循环处理每个时间戳
        while (count > 0) {
            // 将 buf3 的数据拷贝到 out,更新相关变量
            buf3.buffer_memcpy(out, span3);
            ret += span3;
            out.advance_chars_or_bytes(span3);

            // 减少计数,如果小于等于 0,则跳出循环
            if (--count <= 0) {
                break;
            }

            // 根据编码类型选择处理方式
            switch (enc) {
                case ENCODING::ASCII:
                case ENCODING::UTF32:
                    // 将 buf1 的数据拷贝到 out,更新相关变量
                    buf1.buffer_memcpy(out, 1);
                    ret += 1;
                    break;
                case ENCODING::UTF8:
                    // 获取 UTF-8 字符的字节数量,并将 buf1 的数据拷贝到 out,更新相关变量
                    size_t n_bytes = buf1.num_bytes_next_character();
                    buf1.buffer_memcpy(out, n_bytes);
                    ret += n_bytes;
                    break;
            }

            // 更新 buf1 和 out 的位置
            buf1 += 1;
            out += 1;
        }
    }
copy_rest:
    // 使用 buf1 的 buffer_memcpy 方法将 buf1 的内容复制到 out 中,复制长度为 end1 - buf1
    buf1.buffer_memcpy(out, end1 - buf1);
    // 将复制的字节数累加到 ret 中
    ret += end1 - buf1;
    // 如果编码为 UTF8,则直接返回当前 ret 的值
    if (enc == ENCODING::UTF8) {
        return ret;
    }
    // 否则,在复制结束后,使用 out 的 buffer_fill_with_zeros_after_index 方法将 end1 - buf1 之后的字节填充为零
    out.buffer_fill_with_zeros_after_index(end1 - buf1);
    // 返回 ret 的值作为函数结果
    return ret;
}



template <ENCODING enc>
static inline npy_intp
string_expandtabs_length(Buffer<enc> buf, npy_int64 tabsize)
{
    // 计算 buf 中的代码点数目
    size_t len = buf.num_codepoints();

    npy_intp new_len = 0, line_pos = 0;

    // 复制一份 buf 到 tmp 中
    Buffer<enc> tmp = buf;
    // 遍历 buf 中的每个代码点
    for (size_t i = 0; i < len; i++) {
        // 获取当前代码点的值
        npy_ucs4 ch = *tmp;
        // 如果当前代码点是制表符 '\t'
        if (ch == '\t') {
            // 如果制表符大小 tabsize 大于 0
            if (tabsize > 0) {
                // 计算需要增加的长度,使得 line_pos 对齐到 tabsize 的倍数
                npy_intp incr = tabsize - (line_pos % tabsize);
                line_pos += incr;
                new_len += incr;
            }
        }
        else {
            // 如果当前代码点不是制表符
            line_pos += 1;
            // 获取当前代码点在缓冲区中所占的字节数
            size_t n_bytes = tmp.num_bytes_next_character();
            new_len += n_bytes;
            // 如果当前代码点是换行符 '\n' 或回车符 '\r',将行位置重置为 0
            if (ch == '\n' || ch == '\r') {
                line_pos = 0;
            }
        }
        // 检查 new_len 是否超过 INT_MAX 或为负数,如果是则抛出溢出错误并返回 -1
        if (new_len > INT_MAX  || new_len < 0) {
            npy_gil_error(PyExc_OverflowError, "new string is too long");
            return -1;
        }
        // 指向下一个代码点
        tmp++;
    }
    // 返回计算得到的 new_len 作为函数结果
    return new_len;
}



template <ENCODING enc>
static inline npy_intp
string_expandtabs(Buffer<enc> buf, npy_int64 tabsize, Buffer<enc> out)
{
    // 计算 buf 中的代码点数目
    size_t len = buf.num_codepoints();

    npy_intp new_len = 0, line_pos = 0;

    // 复制一份 buf 到 tmp 中
    Buffer<enc> tmp = buf;
    // 遍历 buf 中的每个代码点
    for (size_t i = 0; i < len; i++) {
        // 获取当前代码点的值
        npy_ucs4 ch = *tmp;
        // 如果当前代码点是制表符 '\t'
        if (ch == '\t') {
            // 如果制表符大小 tabsize 大于 0
            if (tabsize > 0) {
                // 计算需要增加的长度,使得 line_pos 对齐到 tabsize 的倍数
                npy_intp incr = tabsize - (line_pos % tabsize);
                line_pos += incr;
                // 使用 out 的 buffer_memset 方法将 incr 个空格填充到输出缓冲区中
                new_len += out.buffer_memset((npy_ucs4) ' ', incr);
                // 移动 out 指针,向后移动 incr 个位置
                out += incr;
            }
        }
        else {
            // 如果当前代码点不是制表符
            line_pos++;
            // 使用 out 的 buffer_memset 方法将当前代码点 ch 写入输出缓冲区
            new_len += out.buffer_memset(ch, 1);
            // 移动 out 指针,向后移动一个位置
            out++;
            // 如果当前代码点是换行符 '\n' 或回车符 '\r',将行位置重置为 0
            if (ch == '\n' || ch == '\r') {
                line_pos = 0;
            }
        }
        // 指向下一个代码点
        tmp++;
    }
    // 返回计算得到的 new_len 作为函数结果
    return new_len;
}



enum class JUSTPOSITION {
    CENTER, LEFT, RIGHT
};

template <ENCODING enc>
static inline npy_intp
string_pad(Buffer<enc> buf, npy_int64 width, npy_ucs4 fill, JUSTPOSITION pos, Buffer<enc> out)
{
    // 计算最终的字符串宽度,如果 width 小于等于 0,则设为 0
    size_t finalwidth = width > 0 ? width : 0;
    // 如果 finalwidth 超过了 PY_SSIZE_T_MAX,抛出溢出错误并返回 -1
    if (finalwidth > PY_SSIZE_T_MAX) {
        npy_gil_error(PyExc_OverflowError, "padded string is too long");
        return -1;
    }

    // 计算 buf 中的代码点数目和字节长度
    size_t len_codepoints = buf.num_codepoints();
    size_t len_bytes = buf.after - buf.buf;

    size_t len;
    // 根据编码类型确定长度的计算方式
    if (enc == ENCODING::UTF8) {
        len = len_bytes;
    }
    else {
        len = len_codepoints;
    }

    // 如果 buf 的代码点数目大于等于最终宽度,直接将 buf 复制到 out 中并返回长度
    if (len_codepoints >= finalwidth) {
        buf.buffer_memcpy(out, len);
        return (npy_intp) len;
    }

    size_t left, right;
    // 根据对齐方式 pos 计算左右填充量
    if (pos == JUSTPOSITION::CENTER) {
        size_t pad = finalwidth - len_codepoints;
        left = pad / 2 + (pad & finalwidth & 1);
        right = pad - left;
    }
    else if (pos == JUSTPOSITION::LEFT) {
        left = 0;
        right = finalwidth - len_codepoints;
    }



    // 在此处继续填写剩余的代码...
}
    # 否则分支:计算左侧填充空间和右侧填充空间
    else:
        left = finalwidth - len_codepoints;  # 计算左侧填充空间
        right = 0;  # 右侧填充空间设为0

    # 断言:确保左侧填充空间和右侧填充空间非负
    assert(left >= 0 or right >= 0);
    # 断言:确保左侧填充后的长度和右侧填充后的长度不会超出最大允许长度
    assert(left <= PY_SSIZE_T_MAX - len and right <= PY_SSIZE_T_MAX - (left + len));

    # 如果存在左侧填充空间大于0
    if (left > 0):
        # 将填充字符(fill)写入左侧填充空间,然后向前移动输出位置(out)
        out.advance_chars_or_bytes(out.buffer_memset(fill, left));

    # 将数据拷贝到输出缓冲区
    buf.buffer_memcpy(out, len);
    # 更新输出位置,增加已处理的代码点数
    out += len_codepoints;

    # 如果存在右侧填充空间大于0
    if (right > 0):
        # 将填充字符(fill)写入右侧填充空间,然后向前移动输出位置(out)
        out.advance_chars_or_bytes(out.buffer_memset(fill, right));

    # 返回最终输出的宽度
    return finalwidth;
// 结束当前的 C++ 函数定义,适用于模板函数和静态内联函数
}

// 定义一个静态内联函数 string_zfill,模板参数为编码类型 enc
template <ENCODING enc>
static inline npy_intp
string_zfill(Buffer<enc> buf, npy_int64 width, Buffer<enc> out)
{
    // 计算最终的宽度,如果指定宽度大于0,则使用指定宽度,否则为0
    size_t finalwidth = width > 0 ? width : 0;

    // 填充字符设为 '0'
    npy_ucs4 fill = '0';
    // 调用 string_pad 函数对 buf 进行填充,返回填充后的长度
    npy_intp new_len = string_pad(buf, width, fill, JUSTPOSITION::RIGHT, out);
    // 如果填充失败,返回 -1
    if (new_len == -1) {
        return -1;
    }

    // 计算偏移量,将 out 指针偏移 finalwidth - buf.num_codepoints() 个位置
    size_t offset = finalwidth - buf.num_codepoints();
    Buffer<enc> tmp = out + offset;

    // 取出 tmp 指针所指位置的字符
    npy_ucs4 c = *tmp;
    // 如果字符为 '+' 或 '-',则将 tmp 指针位置的字符改为 fill
    if (c == '+' || c == '-') {
        tmp.buffer_memset(fill, 1);  // 将 tmp 指针位置的字符改为 fill
        out.buffer_memset(c, 1);     // 将 out 指针位置的字符改为 c
    }

    // 返回新长度 new_len
    return new_len;
}

// 定义一个静态内联函数 string_partition,模板参数为编码类型 enc
template <ENCODING enc>
static inline void
string_partition(Buffer<enc> buf1, Buffer<enc> buf2, npy_int64 idx,
                 Buffer<enc> out1, Buffer<enc> out2, Buffer<enc> out3,
                 npy_intp *final_len1, npy_intp *final_len2, npy_intp *final_len3,
                 STARTPOSITION pos)
{
    // 断言编码类型不为 UTF8,如果为 UTF8,则触发错误
    assert(enc != ENCODING::UTF8);

    // 计算 buf1 和 buf2 的字符数
    size_t len1 = buf1.num_codepoints();
    size_t len2 = buf2.num_codepoints();

    // 如果 buf2 长度为 0,则抛出异常并设置长度返回值为 -1
    if (len2 == 0) {
        npy_gil_error(PyExc_ValueError, "empty separator");
        *final_len1 = *final_len2 = *final_len3 = -1;
        return;
    }

    // 如果 idx 小于 0
    if (idx < 0) {
        // 根据 pos 的值进行处理
        if (pos == STARTPOSITION::FRONT) {
            buf1.buffer_memcpy(out1, len1);  // 将 buf1 复制到 out1
            *final_len1 = len1;  // 设置 out1 的最终长度
            *final_len2 = *final_len3 = 0;  // 设置 out2 和 out3 的最终长度为 0
        }
        else {
            buf1.buffer_memcpy(out3, len1);  // 将 buf1 复制到 out3
            *final_len1 = *final_len2 = 0;  // 设置 out1 和 out2 的最终长度为 0
            *final_len3 = len1;  // 设置 out3 的最终长度
        }
        return;
    }

    // 将 buf1 的前 idx 个字符复制到 out1
    buf1.buffer_memcpy(out1, idx);
    *final_len1 = idx;  // 设置 out1 的最终长度为 idx
    // 将 buf2 复制到 out2
    buf2.buffer_memcpy(out2, len2);
    *final_len2 = len2;  // 设置 out2 的最终长度为 len2
    // 将 buf1 的 idx+len2 到末尾的字符复制到 out3
    (buf1 + idx + len2).buffer_memcpy(out3, len1 - idx - len2);
    *final_len3 = len1 - idx - len2;  // 设置 out3 的最终长度
}