17db96d56Sopenharmony_ci/* stringlib: find/index 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_ciPy_LOCAL_INLINE(Py_ssize_t)
87db96d56Sopenharmony_ciSTRINGLIB(find)(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
97db96d56Sopenharmony_ci               const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
107db96d56Sopenharmony_ci               Py_ssize_t offset)
117db96d56Sopenharmony_ci{
127db96d56Sopenharmony_ci    Py_ssize_t pos;
137db96d56Sopenharmony_ci
147db96d56Sopenharmony_ci    assert(str_len >= 0);
157db96d56Sopenharmony_ci    if (sub_len == 0)
167db96d56Sopenharmony_ci        return offset;
177db96d56Sopenharmony_ci
187db96d56Sopenharmony_ci    pos = FASTSEARCH(str, str_len, sub, sub_len, -1, FAST_SEARCH);
197db96d56Sopenharmony_ci
207db96d56Sopenharmony_ci    if (pos >= 0)
217db96d56Sopenharmony_ci        pos += offset;
227db96d56Sopenharmony_ci
237db96d56Sopenharmony_ci    return pos;
247db96d56Sopenharmony_ci}
257db96d56Sopenharmony_ci
267db96d56Sopenharmony_ciPy_LOCAL_INLINE(Py_ssize_t)
277db96d56Sopenharmony_ciSTRINGLIB(rfind)(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
287db96d56Sopenharmony_ci                const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
297db96d56Sopenharmony_ci                Py_ssize_t offset)
307db96d56Sopenharmony_ci{
317db96d56Sopenharmony_ci    Py_ssize_t pos;
327db96d56Sopenharmony_ci
337db96d56Sopenharmony_ci    assert(str_len >= 0);
347db96d56Sopenharmony_ci    if (sub_len == 0)
357db96d56Sopenharmony_ci        return str_len + offset;
367db96d56Sopenharmony_ci
377db96d56Sopenharmony_ci    pos = FASTSEARCH(str, str_len, sub, sub_len, -1, FAST_RSEARCH);
387db96d56Sopenharmony_ci
397db96d56Sopenharmony_ci    if (pos >= 0)
407db96d56Sopenharmony_ci        pos += offset;
417db96d56Sopenharmony_ci
427db96d56Sopenharmony_ci    return pos;
437db96d56Sopenharmony_ci}
447db96d56Sopenharmony_ci
457db96d56Sopenharmony_ciPy_LOCAL_INLINE(Py_ssize_t)
467db96d56Sopenharmony_ciSTRINGLIB(find_slice)(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
477db96d56Sopenharmony_ci                     const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
487db96d56Sopenharmony_ci                     Py_ssize_t start, Py_ssize_t end)
497db96d56Sopenharmony_ci{
507db96d56Sopenharmony_ci    return STRINGLIB(find)(str + start, end - start, sub, sub_len, start);
517db96d56Sopenharmony_ci}
527db96d56Sopenharmony_ci
537db96d56Sopenharmony_ciPy_LOCAL_INLINE(Py_ssize_t)
547db96d56Sopenharmony_ciSTRINGLIB(rfind_slice)(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
557db96d56Sopenharmony_ci                      const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
567db96d56Sopenharmony_ci                      Py_ssize_t start, Py_ssize_t end)
577db96d56Sopenharmony_ci{
587db96d56Sopenharmony_ci    return STRINGLIB(rfind)(str + start, end - start, sub, sub_len, start);
597db96d56Sopenharmony_ci}
607db96d56Sopenharmony_ci
617db96d56Sopenharmony_ci#ifdef STRINGLIB_WANT_CONTAINS_OBJ
627db96d56Sopenharmony_ci
637db96d56Sopenharmony_ciPy_LOCAL_INLINE(int)
647db96d56Sopenharmony_ciSTRINGLIB(contains_obj)(PyObject* str, PyObject* sub)
657db96d56Sopenharmony_ci{
667db96d56Sopenharmony_ci    return STRINGLIB(find)(
677db96d56Sopenharmony_ci        STRINGLIB_STR(str), STRINGLIB_LEN(str),
687db96d56Sopenharmony_ci        STRINGLIB_STR(sub), STRINGLIB_LEN(sub), 0
697db96d56Sopenharmony_ci        ) != -1;
707db96d56Sopenharmony_ci}
717db96d56Sopenharmony_ci
727db96d56Sopenharmony_ci#endif /* STRINGLIB_WANT_CONTAINS_OBJ */
737db96d56Sopenharmony_ci
747db96d56Sopenharmony_ci/*
757db96d56Sopenharmony_ciThis function is a helper for the "find" family (find, rfind, index,
767db96d56Sopenharmony_cirindex) and for count, startswith and endswith, because they all have
777db96d56Sopenharmony_cithe same behaviour for the arguments.
787db96d56Sopenharmony_ci
797db96d56Sopenharmony_ciIt does not touch the variables received until it knows everything
807db96d56Sopenharmony_ciis ok.
817db96d56Sopenharmony_ci*/
827db96d56Sopenharmony_ci
837db96d56Sopenharmony_ci#define FORMAT_BUFFER_SIZE 50
847db96d56Sopenharmony_ci
857db96d56Sopenharmony_ciPy_LOCAL_INLINE(int)
867db96d56Sopenharmony_ciSTRINGLIB(parse_args_finds)(const char * function_name, PyObject *args,
877db96d56Sopenharmony_ci                           PyObject **subobj,
887db96d56Sopenharmony_ci                           Py_ssize_t *start, Py_ssize_t *end)
897db96d56Sopenharmony_ci{
907db96d56Sopenharmony_ci    PyObject *tmp_subobj;
917db96d56Sopenharmony_ci    Py_ssize_t tmp_start = 0;
927db96d56Sopenharmony_ci    Py_ssize_t tmp_end = PY_SSIZE_T_MAX;
937db96d56Sopenharmony_ci    PyObject *obj_start=Py_None, *obj_end=Py_None;
947db96d56Sopenharmony_ci    char format[FORMAT_BUFFER_SIZE] = "O|OO:";
957db96d56Sopenharmony_ci    size_t len = strlen(format);
967db96d56Sopenharmony_ci
977db96d56Sopenharmony_ci    strncpy(format + len, function_name, FORMAT_BUFFER_SIZE - len - 1);
987db96d56Sopenharmony_ci    format[FORMAT_BUFFER_SIZE - 1] = '\0';
997db96d56Sopenharmony_ci
1007db96d56Sopenharmony_ci    if (!PyArg_ParseTuple(args, format, &tmp_subobj, &obj_start, &obj_end))
1017db96d56Sopenharmony_ci        return 0;
1027db96d56Sopenharmony_ci
1037db96d56Sopenharmony_ci    /* To support None in "start" and "end" arguments, meaning
1047db96d56Sopenharmony_ci       the same as if they were not passed.
1057db96d56Sopenharmony_ci    */
1067db96d56Sopenharmony_ci    if (obj_start != Py_None)
1077db96d56Sopenharmony_ci        if (!_PyEval_SliceIndex(obj_start, &tmp_start))
1087db96d56Sopenharmony_ci            return 0;
1097db96d56Sopenharmony_ci    if (obj_end != Py_None)
1107db96d56Sopenharmony_ci        if (!_PyEval_SliceIndex(obj_end, &tmp_end))
1117db96d56Sopenharmony_ci            return 0;
1127db96d56Sopenharmony_ci
1137db96d56Sopenharmony_ci    *start = tmp_start;
1147db96d56Sopenharmony_ci    *end = tmp_end;
1157db96d56Sopenharmony_ci    *subobj = tmp_subobj;
1167db96d56Sopenharmony_ci    return 1;
1177db96d56Sopenharmony_ci}
1187db96d56Sopenharmony_ci
1197db96d56Sopenharmony_ci#undef FORMAT_BUFFER_SIZE
120