17db96d56Sopenharmony_ci/* stringlib: split implementation */
27db96d56Sopenharmony_ci
37db96d56Sopenharmony_ci#ifndef STRINGLIB_FASTSEARCH_H
47db96d56Sopenharmony_ci#error must include "stringlib/fastsearch.h" before including this module
57db96d56Sopenharmony_ci#endif
67db96d56Sopenharmony_ci
77db96d56Sopenharmony_ci/* Overallocate the initial list to reduce the number of reallocs for small
87db96d56Sopenharmony_ci   split sizes.  Eg, "A A A A A A A A A A".split() (10 elements) has three
97db96d56Sopenharmony_ci   resizes, to sizes 4, 8, then 16.  Most observed string splits are for human
107db96d56Sopenharmony_ci   text (roughly 11 words per line) and field delimited data (usually 1-10
117db96d56Sopenharmony_ci   fields).  For large strings the split algorithms are bandwidth limited
127db96d56Sopenharmony_ci   so increasing the preallocation likely will not improve things.*/
137db96d56Sopenharmony_ci
147db96d56Sopenharmony_ci#define MAX_PREALLOC 12
157db96d56Sopenharmony_ci
167db96d56Sopenharmony_ci/* 5 splits gives 6 elements */
177db96d56Sopenharmony_ci#define PREALLOC_SIZE(maxsplit) \
187db96d56Sopenharmony_ci    (maxsplit >= MAX_PREALLOC ? MAX_PREALLOC : maxsplit+1)
197db96d56Sopenharmony_ci
207db96d56Sopenharmony_ci#define SPLIT_APPEND(data, left, right)         \
217db96d56Sopenharmony_ci    sub = STRINGLIB_NEW((data) + (left),        \
227db96d56Sopenharmony_ci                        (right) - (left));      \
237db96d56Sopenharmony_ci    if (sub == NULL)                            \
247db96d56Sopenharmony_ci        goto onError;                           \
257db96d56Sopenharmony_ci    if (PyList_Append(list, sub)) {             \
267db96d56Sopenharmony_ci        Py_DECREF(sub);                         \
277db96d56Sopenharmony_ci        goto onError;                           \
287db96d56Sopenharmony_ci    }                                           \
297db96d56Sopenharmony_ci    else                                        \
307db96d56Sopenharmony_ci        Py_DECREF(sub);
317db96d56Sopenharmony_ci
327db96d56Sopenharmony_ci#define SPLIT_ADD(data, left, right) {          \
337db96d56Sopenharmony_ci    sub = STRINGLIB_NEW((data) + (left),        \
347db96d56Sopenharmony_ci                        (right) - (left));      \
357db96d56Sopenharmony_ci    if (sub == NULL)                            \
367db96d56Sopenharmony_ci        goto onError;                           \
377db96d56Sopenharmony_ci    if (count < MAX_PREALLOC) {                 \
387db96d56Sopenharmony_ci        PyList_SET_ITEM(list, count, sub);      \
397db96d56Sopenharmony_ci    } else {                                    \
407db96d56Sopenharmony_ci        if (PyList_Append(list, sub)) {         \
417db96d56Sopenharmony_ci            Py_DECREF(sub);                     \
427db96d56Sopenharmony_ci            goto onError;                       \
437db96d56Sopenharmony_ci        }                                       \
447db96d56Sopenharmony_ci        else                                    \
457db96d56Sopenharmony_ci            Py_DECREF(sub);                     \
467db96d56Sopenharmony_ci    }                                           \
477db96d56Sopenharmony_ci    count++; }
487db96d56Sopenharmony_ci
497db96d56Sopenharmony_ci
507db96d56Sopenharmony_ci/* Always force the list to the expected size. */
517db96d56Sopenharmony_ci#define FIX_PREALLOC_SIZE(list) Py_SET_SIZE(list, count)
527db96d56Sopenharmony_ci
537db96d56Sopenharmony_ciPy_LOCAL_INLINE(PyObject *)
547db96d56Sopenharmony_ciSTRINGLIB(split_whitespace)(PyObject* str_obj,
557db96d56Sopenharmony_ci                           const STRINGLIB_CHAR* str, Py_ssize_t str_len,
567db96d56Sopenharmony_ci                           Py_ssize_t maxcount)
577db96d56Sopenharmony_ci{
587db96d56Sopenharmony_ci    Py_ssize_t i, j, count=0;
597db96d56Sopenharmony_ci    PyObject *list = PyList_New(PREALLOC_SIZE(maxcount));
607db96d56Sopenharmony_ci    PyObject *sub;
617db96d56Sopenharmony_ci
627db96d56Sopenharmony_ci    if (list == NULL)
637db96d56Sopenharmony_ci        return NULL;
647db96d56Sopenharmony_ci
657db96d56Sopenharmony_ci    i = j = 0;
667db96d56Sopenharmony_ci    while (maxcount-- > 0) {
677db96d56Sopenharmony_ci        while (i < str_len && STRINGLIB_ISSPACE(str[i]))
687db96d56Sopenharmony_ci            i++;
697db96d56Sopenharmony_ci        if (i == str_len) break;
707db96d56Sopenharmony_ci        j = i; i++;
717db96d56Sopenharmony_ci        while (i < str_len && !STRINGLIB_ISSPACE(str[i]))
727db96d56Sopenharmony_ci            i++;
737db96d56Sopenharmony_ci#if !STRINGLIB_MUTABLE
747db96d56Sopenharmony_ci        if (j == 0 && i == str_len && STRINGLIB_CHECK_EXACT(str_obj)) {
757db96d56Sopenharmony_ci            /* No whitespace in str_obj, so just use it as list[0] */
767db96d56Sopenharmony_ci            Py_INCREF(str_obj);
777db96d56Sopenharmony_ci            PyList_SET_ITEM(list, 0, (PyObject *)str_obj);
787db96d56Sopenharmony_ci            count++;
797db96d56Sopenharmony_ci            break;
807db96d56Sopenharmony_ci        }
817db96d56Sopenharmony_ci#endif
827db96d56Sopenharmony_ci        SPLIT_ADD(str, j, i);
837db96d56Sopenharmony_ci    }
847db96d56Sopenharmony_ci
857db96d56Sopenharmony_ci    if (i < str_len) {
867db96d56Sopenharmony_ci        /* Only occurs when maxcount was reached */
877db96d56Sopenharmony_ci        /* Skip any remaining whitespace and copy to end of string */
887db96d56Sopenharmony_ci        while (i < str_len && STRINGLIB_ISSPACE(str[i]))
897db96d56Sopenharmony_ci            i++;
907db96d56Sopenharmony_ci        if (i != str_len)
917db96d56Sopenharmony_ci            SPLIT_ADD(str, i, str_len);
927db96d56Sopenharmony_ci    }
937db96d56Sopenharmony_ci    FIX_PREALLOC_SIZE(list);
947db96d56Sopenharmony_ci    return list;
957db96d56Sopenharmony_ci
967db96d56Sopenharmony_ci  onError:
977db96d56Sopenharmony_ci    Py_DECREF(list);
987db96d56Sopenharmony_ci    return NULL;
997db96d56Sopenharmony_ci}
1007db96d56Sopenharmony_ci
1017db96d56Sopenharmony_ciPy_LOCAL_INLINE(PyObject *)
1027db96d56Sopenharmony_ciSTRINGLIB(split_char)(PyObject* str_obj,
1037db96d56Sopenharmony_ci                     const STRINGLIB_CHAR* str, Py_ssize_t str_len,
1047db96d56Sopenharmony_ci                     const STRINGLIB_CHAR ch,
1057db96d56Sopenharmony_ci                     Py_ssize_t maxcount)
1067db96d56Sopenharmony_ci{
1077db96d56Sopenharmony_ci    Py_ssize_t i, j, count=0;
1087db96d56Sopenharmony_ci    PyObject *list = PyList_New(PREALLOC_SIZE(maxcount));
1097db96d56Sopenharmony_ci    PyObject *sub;
1107db96d56Sopenharmony_ci
1117db96d56Sopenharmony_ci    if (list == NULL)
1127db96d56Sopenharmony_ci        return NULL;
1137db96d56Sopenharmony_ci
1147db96d56Sopenharmony_ci    i = j = 0;
1157db96d56Sopenharmony_ci    while ((j < str_len) && (maxcount-- > 0)) {
1167db96d56Sopenharmony_ci        for(; j < str_len; j++) {
1177db96d56Sopenharmony_ci            /* I found that using memchr makes no difference */
1187db96d56Sopenharmony_ci            if (str[j] == ch) {
1197db96d56Sopenharmony_ci                SPLIT_ADD(str, i, j);
1207db96d56Sopenharmony_ci                i = j = j + 1;
1217db96d56Sopenharmony_ci                break;
1227db96d56Sopenharmony_ci            }
1237db96d56Sopenharmony_ci        }
1247db96d56Sopenharmony_ci    }
1257db96d56Sopenharmony_ci#if !STRINGLIB_MUTABLE
1267db96d56Sopenharmony_ci    if (count == 0 && STRINGLIB_CHECK_EXACT(str_obj)) {
1277db96d56Sopenharmony_ci        /* ch not in str_obj, so just use str_obj as list[0] */
1287db96d56Sopenharmony_ci        Py_INCREF(str_obj);
1297db96d56Sopenharmony_ci        PyList_SET_ITEM(list, 0, (PyObject *)str_obj);
1307db96d56Sopenharmony_ci        count++;
1317db96d56Sopenharmony_ci    } else
1327db96d56Sopenharmony_ci#endif
1337db96d56Sopenharmony_ci    if (i <= str_len) {
1347db96d56Sopenharmony_ci        SPLIT_ADD(str, i, str_len);
1357db96d56Sopenharmony_ci    }
1367db96d56Sopenharmony_ci    FIX_PREALLOC_SIZE(list);
1377db96d56Sopenharmony_ci    return list;
1387db96d56Sopenharmony_ci
1397db96d56Sopenharmony_ci  onError:
1407db96d56Sopenharmony_ci    Py_DECREF(list);
1417db96d56Sopenharmony_ci    return NULL;
1427db96d56Sopenharmony_ci}
1437db96d56Sopenharmony_ci
1447db96d56Sopenharmony_ciPy_LOCAL_INLINE(PyObject *)
1457db96d56Sopenharmony_ciSTRINGLIB(split)(PyObject* str_obj,
1467db96d56Sopenharmony_ci                const STRINGLIB_CHAR* str, Py_ssize_t str_len,
1477db96d56Sopenharmony_ci                const STRINGLIB_CHAR* sep, Py_ssize_t sep_len,
1487db96d56Sopenharmony_ci                Py_ssize_t maxcount)
1497db96d56Sopenharmony_ci{
1507db96d56Sopenharmony_ci    Py_ssize_t i, j, pos, count=0;
1517db96d56Sopenharmony_ci    PyObject *list, *sub;
1527db96d56Sopenharmony_ci
1537db96d56Sopenharmony_ci    if (sep_len == 0) {
1547db96d56Sopenharmony_ci        PyErr_SetString(PyExc_ValueError, "empty separator");
1557db96d56Sopenharmony_ci        return NULL;
1567db96d56Sopenharmony_ci    }
1577db96d56Sopenharmony_ci    else if (sep_len == 1)
1587db96d56Sopenharmony_ci        return STRINGLIB(split_char)(str_obj, str, str_len, sep[0], maxcount);
1597db96d56Sopenharmony_ci
1607db96d56Sopenharmony_ci    list = PyList_New(PREALLOC_SIZE(maxcount));
1617db96d56Sopenharmony_ci    if (list == NULL)
1627db96d56Sopenharmony_ci        return NULL;
1637db96d56Sopenharmony_ci
1647db96d56Sopenharmony_ci    i = j = 0;
1657db96d56Sopenharmony_ci    while (maxcount-- > 0) {
1667db96d56Sopenharmony_ci        pos = FASTSEARCH(str+i, str_len-i, sep, sep_len, -1, FAST_SEARCH);
1677db96d56Sopenharmony_ci        if (pos < 0)
1687db96d56Sopenharmony_ci            break;
1697db96d56Sopenharmony_ci        j = i + pos;
1707db96d56Sopenharmony_ci        SPLIT_ADD(str, i, j);
1717db96d56Sopenharmony_ci        i = j + sep_len;
1727db96d56Sopenharmony_ci    }
1737db96d56Sopenharmony_ci#if !STRINGLIB_MUTABLE
1747db96d56Sopenharmony_ci    if (count == 0 && STRINGLIB_CHECK_EXACT(str_obj)) {
1757db96d56Sopenharmony_ci        /* No match in str_obj, so just use it as list[0] */
1767db96d56Sopenharmony_ci        Py_INCREF(str_obj);
1777db96d56Sopenharmony_ci        PyList_SET_ITEM(list, 0, (PyObject *)str_obj);
1787db96d56Sopenharmony_ci        count++;
1797db96d56Sopenharmony_ci    } else
1807db96d56Sopenharmony_ci#endif
1817db96d56Sopenharmony_ci    {
1827db96d56Sopenharmony_ci        SPLIT_ADD(str, i, str_len);
1837db96d56Sopenharmony_ci    }
1847db96d56Sopenharmony_ci    FIX_PREALLOC_SIZE(list);
1857db96d56Sopenharmony_ci    return list;
1867db96d56Sopenharmony_ci
1877db96d56Sopenharmony_ci  onError:
1887db96d56Sopenharmony_ci    Py_DECREF(list);
1897db96d56Sopenharmony_ci    return NULL;
1907db96d56Sopenharmony_ci}
1917db96d56Sopenharmony_ci
1927db96d56Sopenharmony_ciPy_LOCAL_INLINE(PyObject *)
1937db96d56Sopenharmony_ciSTRINGLIB(rsplit_whitespace)(PyObject* str_obj,
1947db96d56Sopenharmony_ci                            const STRINGLIB_CHAR* str, Py_ssize_t str_len,
1957db96d56Sopenharmony_ci                            Py_ssize_t maxcount)
1967db96d56Sopenharmony_ci{
1977db96d56Sopenharmony_ci    Py_ssize_t i, j, count=0;
1987db96d56Sopenharmony_ci    PyObject *list = PyList_New(PREALLOC_SIZE(maxcount));
1997db96d56Sopenharmony_ci    PyObject *sub;
2007db96d56Sopenharmony_ci
2017db96d56Sopenharmony_ci    if (list == NULL)
2027db96d56Sopenharmony_ci        return NULL;
2037db96d56Sopenharmony_ci
2047db96d56Sopenharmony_ci    i = j = str_len - 1;
2057db96d56Sopenharmony_ci    while (maxcount-- > 0) {
2067db96d56Sopenharmony_ci        while (i >= 0 && STRINGLIB_ISSPACE(str[i]))
2077db96d56Sopenharmony_ci            i--;
2087db96d56Sopenharmony_ci        if (i < 0) break;
2097db96d56Sopenharmony_ci        j = i; i--;
2107db96d56Sopenharmony_ci        while (i >= 0 && !STRINGLIB_ISSPACE(str[i]))
2117db96d56Sopenharmony_ci            i--;
2127db96d56Sopenharmony_ci#if !STRINGLIB_MUTABLE
2137db96d56Sopenharmony_ci        if (j == str_len - 1 && i < 0 && STRINGLIB_CHECK_EXACT(str_obj)) {
2147db96d56Sopenharmony_ci            /* No whitespace in str_obj, so just use it as list[0] */
2157db96d56Sopenharmony_ci            Py_INCREF(str_obj);
2167db96d56Sopenharmony_ci            PyList_SET_ITEM(list, 0, (PyObject *)str_obj);
2177db96d56Sopenharmony_ci            count++;
2187db96d56Sopenharmony_ci            break;
2197db96d56Sopenharmony_ci        }
2207db96d56Sopenharmony_ci#endif
2217db96d56Sopenharmony_ci        SPLIT_ADD(str, i + 1, j + 1);
2227db96d56Sopenharmony_ci    }
2237db96d56Sopenharmony_ci
2247db96d56Sopenharmony_ci    if (i >= 0) {
2257db96d56Sopenharmony_ci        /* Only occurs when maxcount was reached */
2267db96d56Sopenharmony_ci        /* Skip any remaining whitespace and copy to beginning of string */
2277db96d56Sopenharmony_ci        while (i >= 0 && STRINGLIB_ISSPACE(str[i]))
2287db96d56Sopenharmony_ci            i--;
2297db96d56Sopenharmony_ci        if (i >= 0)
2307db96d56Sopenharmony_ci            SPLIT_ADD(str, 0, i + 1);
2317db96d56Sopenharmony_ci    }
2327db96d56Sopenharmony_ci    FIX_PREALLOC_SIZE(list);
2337db96d56Sopenharmony_ci    if (PyList_Reverse(list) < 0)
2347db96d56Sopenharmony_ci        goto onError;
2357db96d56Sopenharmony_ci    return list;
2367db96d56Sopenharmony_ci
2377db96d56Sopenharmony_ci  onError:
2387db96d56Sopenharmony_ci    Py_DECREF(list);
2397db96d56Sopenharmony_ci    return NULL;
2407db96d56Sopenharmony_ci}
2417db96d56Sopenharmony_ci
2427db96d56Sopenharmony_ciPy_LOCAL_INLINE(PyObject *)
2437db96d56Sopenharmony_ciSTRINGLIB(rsplit_char)(PyObject* str_obj,
2447db96d56Sopenharmony_ci                      const STRINGLIB_CHAR* str, Py_ssize_t str_len,
2457db96d56Sopenharmony_ci                      const STRINGLIB_CHAR ch,
2467db96d56Sopenharmony_ci                      Py_ssize_t maxcount)
2477db96d56Sopenharmony_ci{
2487db96d56Sopenharmony_ci    Py_ssize_t i, j, count=0;
2497db96d56Sopenharmony_ci    PyObject *list = PyList_New(PREALLOC_SIZE(maxcount));
2507db96d56Sopenharmony_ci    PyObject *sub;
2517db96d56Sopenharmony_ci
2527db96d56Sopenharmony_ci    if (list == NULL)
2537db96d56Sopenharmony_ci        return NULL;
2547db96d56Sopenharmony_ci
2557db96d56Sopenharmony_ci    i = j = str_len - 1;
2567db96d56Sopenharmony_ci    while ((i >= 0) && (maxcount-- > 0)) {
2577db96d56Sopenharmony_ci        for(; i >= 0; i--) {
2587db96d56Sopenharmony_ci            if (str[i] == ch) {
2597db96d56Sopenharmony_ci                SPLIT_ADD(str, i + 1, j + 1);
2607db96d56Sopenharmony_ci                j = i = i - 1;
2617db96d56Sopenharmony_ci                break;
2627db96d56Sopenharmony_ci            }
2637db96d56Sopenharmony_ci        }
2647db96d56Sopenharmony_ci    }
2657db96d56Sopenharmony_ci#if !STRINGLIB_MUTABLE
2667db96d56Sopenharmony_ci    if (count == 0 && STRINGLIB_CHECK_EXACT(str_obj)) {
2677db96d56Sopenharmony_ci        /* ch not in str_obj, so just use str_obj as list[0] */
2687db96d56Sopenharmony_ci        Py_INCREF(str_obj);
2697db96d56Sopenharmony_ci        PyList_SET_ITEM(list, 0, (PyObject *)str_obj);
2707db96d56Sopenharmony_ci        count++;
2717db96d56Sopenharmony_ci    } else
2727db96d56Sopenharmony_ci#endif
2737db96d56Sopenharmony_ci    if (j >= -1) {
2747db96d56Sopenharmony_ci        SPLIT_ADD(str, 0, j + 1);
2757db96d56Sopenharmony_ci    }
2767db96d56Sopenharmony_ci    FIX_PREALLOC_SIZE(list);
2777db96d56Sopenharmony_ci    if (PyList_Reverse(list) < 0)
2787db96d56Sopenharmony_ci        goto onError;
2797db96d56Sopenharmony_ci    return list;
2807db96d56Sopenharmony_ci
2817db96d56Sopenharmony_ci  onError:
2827db96d56Sopenharmony_ci    Py_DECREF(list);
2837db96d56Sopenharmony_ci    return NULL;
2847db96d56Sopenharmony_ci}
2857db96d56Sopenharmony_ci
2867db96d56Sopenharmony_ciPy_LOCAL_INLINE(PyObject *)
2877db96d56Sopenharmony_ciSTRINGLIB(rsplit)(PyObject* str_obj,
2887db96d56Sopenharmony_ci                 const STRINGLIB_CHAR* str, Py_ssize_t str_len,
2897db96d56Sopenharmony_ci                 const STRINGLIB_CHAR* sep, Py_ssize_t sep_len,
2907db96d56Sopenharmony_ci                 Py_ssize_t maxcount)
2917db96d56Sopenharmony_ci{
2927db96d56Sopenharmony_ci    Py_ssize_t j, pos, count=0;
2937db96d56Sopenharmony_ci    PyObject *list, *sub;
2947db96d56Sopenharmony_ci
2957db96d56Sopenharmony_ci    if (sep_len == 0) {
2967db96d56Sopenharmony_ci        PyErr_SetString(PyExc_ValueError, "empty separator");
2977db96d56Sopenharmony_ci        return NULL;
2987db96d56Sopenharmony_ci    }
2997db96d56Sopenharmony_ci    else if (sep_len == 1)
3007db96d56Sopenharmony_ci        return STRINGLIB(rsplit_char)(str_obj, str, str_len, sep[0], maxcount);
3017db96d56Sopenharmony_ci
3027db96d56Sopenharmony_ci    list = PyList_New(PREALLOC_SIZE(maxcount));
3037db96d56Sopenharmony_ci    if (list == NULL)
3047db96d56Sopenharmony_ci        return NULL;
3057db96d56Sopenharmony_ci
3067db96d56Sopenharmony_ci    j = str_len;
3077db96d56Sopenharmony_ci    while (maxcount-- > 0) {
3087db96d56Sopenharmony_ci        pos = FASTSEARCH(str, j, sep, sep_len, -1, FAST_RSEARCH);
3097db96d56Sopenharmony_ci        if (pos < 0)
3107db96d56Sopenharmony_ci            break;
3117db96d56Sopenharmony_ci        SPLIT_ADD(str, pos + sep_len, j);
3127db96d56Sopenharmony_ci        j = pos;
3137db96d56Sopenharmony_ci    }
3147db96d56Sopenharmony_ci#if !STRINGLIB_MUTABLE
3157db96d56Sopenharmony_ci    if (count == 0 && STRINGLIB_CHECK_EXACT(str_obj)) {
3167db96d56Sopenharmony_ci        /* No match in str_obj, so just use it as list[0] */
3177db96d56Sopenharmony_ci        Py_INCREF(str_obj);
3187db96d56Sopenharmony_ci        PyList_SET_ITEM(list, 0, (PyObject *)str_obj);
3197db96d56Sopenharmony_ci        count++;
3207db96d56Sopenharmony_ci    } else
3217db96d56Sopenharmony_ci#endif
3227db96d56Sopenharmony_ci    {
3237db96d56Sopenharmony_ci        SPLIT_ADD(str, 0, j);
3247db96d56Sopenharmony_ci    }
3257db96d56Sopenharmony_ci    FIX_PREALLOC_SIZE(list);
3267db96d56Sopenharmony_ci    if (PyList_Reverse(list) < 0)
3277db96d56Sopenharmony_ci        goto onError;
3287db96d56Sopenharmony_ci    return list;
3297db96d56Sopenharmony_ci
3307db96d56Sopenharmony_ci  onError:
3317db96d56Sopenharmony_ci    Py_DECREF(list);
3327db96d56Sopenharmony_ci    return NULL;
3337db96d56Sopenharmony_ci}
3347db96d56Sopenharmony_ci
3357db96d56Sopenharmony_ciPy_LOCAL_INLINE(PyObject *)
3367db96d56Sopenharmony_ciSTRINGLIB(splitlines)(PyObject* str_obj,
3377db96d56Sopenharmony_ci                     const STRINGLIB_CHAR* str, Py_ssize_t str_len,
3387db96d56Sopenharmony_ci                     int keepends)
3397db96d56Sopenharmony_ci{
3407db96d56Sopenharmony_ci    /* This does not use the preallocated list because splitlines is
3417db96d56Sopenharmony_ci       usually run with hundreds of newlines.  The overhead of
3427db96d56Sopenharmony_ci       switching between PyList_SET_ITEM and append causes about a
3437db96d56Sopenharmony_ci       2-3% slowdown for that common case.  A smarter implementation
3447db96d56Sopenharmony_ci       could move the if check out, so the SET_ITEMs are done first
3457db96d56Sopenharmony_ci       and the appends only done when the prealloc buffer is full.
3467db96d56Sopenharmony_ci       That's too much work for little gain.*/
3477db96d56Sopenharmony_ci
3487db96d56Sopenharmony_ci    Py_ssize_t i;
3497db96d56Sopenharmony_ci    Py_ssize_t j;
3507db96d56Sopenharmony_ci    PyObject *list = PyList_New(0);
3517db96d56Sopenharmony_ci    PyObject *sub;
3527db96d56Sopenharmony_ci
3537db96d56Sopenharmony_ci    if (list == NULL)
3547db96d56Sopenharmony_ci        return NULL;
3557db96d56Sopenharmony_ci
3567db96d56Sopenharmony_ci    for (i = j = 0; i < str_len; ) {
3577db96d56Sopenharmony_ci        Py_ssize_t eol;
3587db96d56Sopenharmony_ci
3597db96d56Sopenharmony_ci        /* Find a line and append it */
3607db96d56Sopenharmony_ci        while (i < str_len && !STRINGLIB_ISLINEBREAK(str[i]))
3617db96d56Sopenharmony_ci            i++;
3627db96d56Sopenharmony_ci
3637db96d56Sopenharmony_ci        /* Skip the line break reading CRLF as one line break */
3647db96d56Sopenharmony_ci        eol = i;
3657db96d56Sopenharmony_ci        if (i < str_len) {
3667db96d56Sopenharmony_ci            if (str[i] == '\r' && i + 1 < str_len && str[i+1] == '\n')
3677db96d56Sopenharmony_ci                i += 2;
3687db96d56Sopenharmony_ci            else
3697db96d56Sopenharmony_ci                i++;
3707db96d56Sopenharmony_ci            if (keepends)
3717db96d56Sopenharmony_ci                eol = i;
3727db96d56Sopenharmony_ci        }
3737db96d56Sopenharmony_ci#if !STRINGLIB_MUTABLE
3747db96d56Sopenharmony_ci        if (j == 0 && eol == str_len && STRINGLIB_CHECK_EXACT(str_obj)) {
3757db96d56Sopenharmony_ci            /* No linebreak in str_obj, so just use it as list[0] */
3767db96d56Sopenharmony_ci            if (PyList_Append(list, str_obj))
3777db96d56Sopenharmony_ci                goto onError;
3787db96d56Sopenharmony_ci            break;
3797db96d56Sopenharmony_ci        }
3807db96d56Sopenharmony_ci#endif
3817db96d56Sopenharmony_ci        SPLIT_APPEND(str, j, eol);
3827db96d56Sopenharmony_ci        j = i;
3837db96d56Sopenharmony_ci    }
3847db96d56Sopenharmony_ci    return list;
3857db96d56Sopenharmony_ci
3867db96d56Sopenharmony_ci  onError:
3877db96d56Sopenharmony_ci    Py_DECREF(list);
3887db96d56Sopenharmony_ci    return NULL;
3897db96d56Sopenharmony_ci}
3907db96d56Sopenharmony_ci
391