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

Code before:
    }
    if (count < 0) {
        elcount = PyObject_LengthHint(obj, 0);
        if (elcount < 0) {
            goto done;
        }
    }
    else {
        elcount = count;
    }

    elsize = dtype->elsize;

    /*
     * Note that PyArray_DESCR(ret) may not match dtype.  There are exactly
     * two cases where this can happen: empty strings/bytes/void (rejected
     * above) and subarray dtypes (supported by sticking with `dtype`).
     */
    Py_INCREF(dtype);
    ret = (PyArrayObject *)PyArray_NewFromDescr(&PyArray_Type, dtype, 1,
                                                &elcount, NULL,NULL, 0, NULL);
    if (ret == NULL) {
        goto done;
    }
    /* set up for resizing */
    dims = npy_alloc_cache_dim(PyArray_NDIM(ret));
    memcpy(dims, PyArray_DIMS(ret), PyArray_NDIM(ret)*sizeof(npy_intp));
    PyArray_Dims new_dims = {dims, PyArray_NDIM(ret)};

    char *item = PyArray_BYTES(ret);
    for (i = 0; i < count || count == -1; i++, item += elsize) {
        PyObject *value = PyIter_Next(iter);
        if (value == NULL) {
            if (PyErr_Occurred()) {
                /* Fetching next item failed perhaps due to exhausting iterator */
                goto done;
            }
            break;
        }

        if (NPY_UNLIKELY(i >= elcount) && elsize != 0) {
            npy_intp nbytes = 0;
            PyObject *res = NULL;
            /*
              Grow PyArray_DATA(ret):
              this is similar for the strategy for PyListObject, but we use
              50% overallocation => 0, 4, 8, 14, 23, 36, 56, 86 ...
              TODO: The loadtxt code now uses a `growth` helper that would
                    be suitable to reuse here.
            */
            elcount = (i >> 1) + (i < 4 ? 4 : 2) + i;

Review comment (suggestion):
This is missing an OOM check, but really just use `npy_intp dims[NPY_MAXDIMS]` and stop worrying about cleanup.

Code after:
    if (count < 0) {
        elcount = PyObject_LengthHint(obj, 0);
        if (elcount < 0) {
            goto done;
        }
    }
    else {
        elcount = count;
    }

    elsize = dtype->elsize;

    /*
     * Note that PyArray_DESCR(ret) may not match dtype.  There are exactly
     * two cases where this can happen: empty strings/bytes/void (rejected
     * above) and subarray dtypes (supported by sticking with `dtype`).
     */
    Py_INCREF(dtype);
    ret = (PyArrayObject *)PyArray_NewFromDescr(&PyArray_Type, dtype, 1,
                                                &elcount, NULL,NULL, 0, NULL);
    if (ret == NULL) {
        goto done;
    }
    /* set up for possible resizing */
    memcpy(dims, PyArray_DIMS(ret), PyArray_NDIM(ret)*sizeof(npy_intp));
    PyArray_Dims new_dims = {dims, PyArray_NDIM(ret)};

    char *item = PyArray_BYTES(ret);
    for (i = 0; i < count || count == -1; i++, item += elsize) {
        PyObject *value = PyIter_Next(iter);
        if (value == NULL) {
            if (PyErr_Occurred()) {
                /* Fetching next item failed perhaps due to exhausting iterator */
                goto fail;
            }
            break;
        }

        if (NPY_UNLIKELY(i >= elcount) && elsize != 0) {
            /*
              Grow PyArray_DATA(ret):
              this is similar for the strategy for PyListObject, but we use
              50% overallocation => 0, 4, 8, 14, 23, 36, 56, 86 ...
              TODO: The loadtxt code now uses a `growth` helper that would
                    be suitable to reuse here.
            */
            elcount = (i >> 1) + (i < 4 ? 4 : 2) + i;
            dims[0] = elcount;
            if (PyArray_Resize_int(ret, &new_dims, 0) < 0) {
                Py_DECREF(value);
                goto fail;