LCOV - code coverage report
Current view: top level - Objects/stringlib - find.h (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 41 57 71.9 %
Date: 2017-04-19 Functions: 6 7 85.7 %

          Line data    Source code
       1             : /* stringlib: find/index implementation */
       2             : 
       3             : #ifndef STRINGLIB_FIND_H
       4             : #define STRINGLIB_FIND_H
       5             : 
       6             : #ifndef STRINGLIB_FASTSEARCH_H
       7             : #error must include "stringlib/fastsearch.h" before including this module
       8             : #endif
       9             : 
      10             : Py_LOCAL_INLINE(Py_ssize_t)
      11        8085 : stringlib_find(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
      12             :                const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
      13             :                Py_ssize_t offset)
      14             : {
      15             :     Py_ssize_t pos;
      16             : 
      17        8085 :     if (str_len < 0)
      18           0 :         return -1;
      19        8085 :     if (sub_len == 0)
      20           0 :         return offset;
      21             : 
      22        8085 :     pos = fastsearch(str, str_len, sub, sub_len, -1, FAST_SEARCH);
      23             : 
      24        8085 :     if (pos >= 0)
      25        5187 :         pos += offset;
      26             : 
      27        8085 :     return pos;
      28             : }
      29             : 
      30             : Py_LOCAL_INLINE(Py_ssize_t)
      31          18 : stringlib_rfind(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
      32             :                 const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
      33             :                 Py_ssize_t offset)
      34             : {
      35             :     Py_ssize_t pos;
      36             : 
      37          18 :     if (str_len < 0)
      38           0 :         return -1;
      39          18 :     if (sub_len == 0)
      40           0 :         return str_len + offset;
      41             : 
      42          18 :     pos = fastsearch(str, str_len, sub, sub_len, -1, FAST_RSEARCH);
      43             : 
      44          18 :     if (pos >= 0)
      45          15 :         pos += offset;
      46             : 
      47          18 :     return pos;
      48             : }
      49             : 
      50             : /* helper macro to fixup start/end slice values */
      51             : #define ADJUST_INDICES(start, end, len)         \
      52             :     if (end > len)                              \
      53             :         end = len;                              \
      54             :     else if (end < 0) {                         \
      55             :         end += len;                             \
      56             :         if (end < 0)                            \
      57             :             end = 0;                            \
      58             :     }                                           \
      59             :     if (start < 0) {                            \
      60             :         start += len;                           \
      61             :         if (start < 0)                          \
      62             :             start = 0;                          \
      63             :     }
      64             : 
      65             : Py_LOCAL_INLINE(Py_ssize_t)
      66        2550 : stringlib_find_slice(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
      67             :                      const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
      68             :                      Py_ssize_t start, Py_ssize_t end)
      69             : {
      70        2550 :     ADJUST_INDICES(start, end, str_len);
      71        2550 :     return stringlib_find(str + start, end - start, sub, sub_len, start);
      72             : }
      73             : 
      74             : Py_LOCAL_INLINE(Py_ssize_t)
      75          18 : stringlib_rfind_slice(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
      76             :                       const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
      77             :                       Py_ssize_t start, Py_ssize_t end)
      78             : {
      79          18 :     ADJUST_INDICES(start, end, str_len);
      80          18 :     return stringlib_rfind(str + start, end - start, sub, sub_len, start);
      81             : }
      82             : 
      83             : #ifdef STRINGLIB_WANT_CONTAINS_OBJ
      84             : 
      85             : Py_LOCAL_INLINE(int)
      86        5535 : stringlib_contains_obj(PyObject* str, PyObject* sub)
      87             : {
      88       22140 :     return stringlib_find(
      89        5535 :         STRINGLIB_STR(str), STRINGLIB_LEN(str),
      90        5535 :         STRINGLIB_STR(sub), STRINGLIB_LEN(sub), 0
      91        5535 :         ) != -1;
      92             : }
      93             : 
      94             : #endif /* STRINGLIB_WANT_CONTAINS_OBJ */
      95             : 
      96             : /*
      97             : This function is a helper for the "find" family (find, rfind, index,
      98             : rindex) and for count, startswith and endswith, because they all have
      99             : the same behaviour for the arguments.
     100             : 
     101             : It does not touch the variables received until it knows everything 
     102             : is ok.
     103             : */
     104             : 
     105             : #define FORMAT_BUFFER_SIZE 50
     106             : 
     107             : Py_LOCAL_INLINE(int)
     108        3372 : stringlib_parse_args_finds(const char * function_name, PyObject *args,
     109             :                            PyObject **subobj,
     110             :                            Py_ssize_t *start, Py_ssize_t *end)
     111             : {
     112             :     PyObject *tmp_subobj;
     113        3372 :     Py_ssize_t tmp_start = 0;
     114        3372 :     Py_ssize_t tmp_end = PY_SSIZE_T_MAX;
     115        3372 :     PyObject *obj_start=Py_None, *obj_end=Py_None;
     116        3372 :     char format[FORMAT_BUFFER_SIZE] = "O|OO:";
     117        3372 :     size_t len = strlen(format);
     118             : 
     119        3372 :     strncpy(format + len, function_name, FORMAT_BUFFER_SIZE - len - 1);
     120        3372 :     format[FORMAT_BUFFER_SIZE - 1] = '\0';
     121             : 
     122        3372 :     if (!PyArg_ParseTuple(args, format, &tmp_subobj, &obj_start, &obj_end))
     123           0 :         return 0;
     124             : 
     125             :     /* To support None in "start" and "end" arguments, meaning
     126             :        the same as if they were not passed.
     127             :     */
     128        3372 :     if (obj_start != Py_None)
     129        2442 :         if (!_PyEval_SliceIndex(obj_start, &tmp_start))
     130           0 :             return 0;
     131        3372 :     if (obj_end != Py_None)
     132           0 :         if (!_PyEval_SliceIndex(obj_end, &tmp_end))
     133           0 :             return 0;
     134             : 
     135        3372 :     *start = tmp_start;
     136        3372 :     *end = tmp_end;
     137        3372 :     *subobj = tmp_subobj;
     138        3372 :     return 1;
     139             : }
     140             : 
     141             : #undef FORMAT_BUFFER_SIZE
     142             : 
     143             : #if STRINGLIB_IS_UNICODE
     144             : 
     145             : /*
     146             : Wraps stringlib_parse_args_finds() and additionally ensures that the
     147             : first argument is a unicode object.
     148             : 
     149             : Note that we receive a pointer to the pointer of the substring object,
     150             : so when we create that object in this function we don't DECREF it,
     151             : because it continues living in the caller functions (those functions, 
     152             : after finishing using the substring, must DECREF it).
     153             : */
     154             : 
     155             : Py_LOCAL_INLINE(int)
     156           0 : stringlib_parse_args_finds_unicode(const char * function_name, PyObject *args,
     157             :                                    PyUnicodeObject **substring,
     158             :                                    Py_ssize_t *start, Py_ssize_t *end)
     159             : {
     160             :     PyObject *tmp_substring;
     161             : 
     162           0 :     if(stringlib_parse_args_finds(function_name, args, &tmp_substring,
     163             :                                   start, end)) {
     164           0 :         tmp_substring = PyUnicode_FromObject(tmp_substring);
     165           0 :         if (!tmp_substring)
     166           0 :             return 0;
     167           0 :         *substring = (PyUnicodeObject *)tmp_substring;
     168           0 :         return 1;
     169             :     }
     170           0 :     return 0;
     171             : }
     172             : 
     173             : #endif /* STRINGLIB_IS_UNICODE */
     174             : 
     175             : #endif /* STRINGLIB_FIND_H */

Generated by: LCOV version 1.10