1/* stringlib: partition implementation */
2
3#ifndef STRINGLIB_FASTSEARCH_H
4#  error must include "stringlib/fastsearch.h" before including this module
5#endif
6
7#if !STRINGLIB_MUTABLE && !defined(STRINGLIB_GET_EMPTY)
8#  error "STRINGLIB_GET_EMPTY must be defined if STRINGLIB_MUTABLE is zero"
9#endif
10
11
12Py_LOCAL_INLINE(PyObject*)
13STRINGLIB(partition)(PyObject* str_obj,
14                    const STRINGLIB_CHAR* str, Py_ssize_t str_len,
15                    PyObject* sep_obj,
16                    const STRINGLIB_CHAR* sep, Py_ssize_t sep_len)
17{
18    PyObject* out;
19    Py_ssize_t pos;
20
21    if (sep_len == 0) {
22        PyErr_SetString(PyExc_ValueError, "empty separator");
23        return NULL;
24    }
25
26    out = PyTuple_New(3);
27    if (!out)
28        return NULL;
29
30    pos = FASTSEARCH(str, str_len, sep, sep_len, -1, FAST_SEARCH);
31
32    if (pos < 0) {
33#if STRINGLIB_MUTABLE
34        PyTuple_SET_ITEM(out, 0, STRINGLIB_NEW(str, str_len));
35        PyTuple_SET_ITEM(out, 1, STRINGLIB_NEW(NULL, 0));
36        PyTuple_SET_ITEM(out, 2, STRINGLIB_NEW(NULL, 0));
37
38        if (PyErr_Occurred()) {
39            Py_DECREF(out);
40            return NULL;
41        }
42#else
43        Py_INCREF(str_obj);
44        PyTuple_SET_ITEM(out, 0, (PyObject*) str_obj);
45        PyObject *empty = (PyObject*)STRINGLIB_GET_EMPTY();
46        assert(empty != NULL);
47        Py_INCREF(empty);
48        PyTuple_SET_ITEM(out, 1, empty);
49        Py_INCREF(empty);
50        PyTuple_SET_ITEM(out, 2, empty);
51#endif
52        return out;
53    }
54
55    PyTuple_SET_ITEM(out, 0, STRINGLIB_NEW(str, pos));
56    Py_INCREF(sep_obj);
57    PyTuple_SET_ITEM(out, 1, sep_obj);
58    pos += sep_len;
59    PyTuple_SET_ITEM(out, 2, STRINGLIB_NEW(str + pos, str_len - pos));
60
61    if (PyErr_Occurred()) {
62        Py_DECREF(out);
63        return NULL;
64    }
65
66    return out;
67}
68
69Py_LOCAL_INLINE(PyObject*)
70STRINGLIB(rpartition)(PyObject* str_obj,
71                     const STRINGLIB_CHAR* str, Py_ssize_t str_len,
72                     PyObject* sep_obj,
73                     const STRINGLIB_CHAR* sep, Py_ssize_t sep_len)
74{
75    PyObject* out;
76    Py_ssize_t pos;
77
78    if (sep_len == 0) {
79        PyErr_SetString(PyExc_ValueError, "empty separator");
80        return NULL;
81    }
82
83    out = PyTuple_New(3);
84    if (!out)
85        return NULL;
86
87    pos = FASTSEARCH(str, str_len, sep, sep_len, -1, FAST_RSEARCH);
88
89    if (pos < 0) {
90#if STRINGLIB_MUTABLE
91        PyTuple_SET_ITEM(out, 0, STRINGLIB_NEW(NULL, 0));
92        PyTuple_SET_ITEM(out, 1, STRINGLIB_NEW(NULL, 0));
93        PyTuple_SET_ITEM(out, 2, STRINGLIB_NEW(str, str_len));
94
95        if (PyErr_Occurred()) {
96            Py_DECREF(out);
97            return NULL;
98        }
99#else
100        PyObject *empty = (PyObject*)STRINGLIB_GET_EMPTY();
101        assert(empty != NULL);
102        Py_INCREF(empty);
103        PyTuple_SET_ITEM(out, 0, empty);
104        Py_INCREF(empty);
105        PyTuple_SET_ITEM(out, 1, empty);
106        Py_INCREF(str_obj);
107        PyTuple_SET_ITEM(out, 2, (PyObject*) str_obj);
108#endif
109        return out;
110    }
111
112    PyTuple_SET_ITEM(out, 0, STRINGLIB_NEW(str, pos));
113    Py_INCREF(sep_obj);
114    PyTuple_SET_ITEM(out, 1, sep_obj);
115    pos += sep_len;
116    PyTuple_SET_ITEM(out, 2, STRINGLIB_NEW(str + pos, str_len - pos));
117
118    if (PyErr_Occurred()) {
119        Py_DECREF(out);
120        return NULL;
121    }
122
123    return out;
124}
125
126